2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
11 #elif defined __GNUC__
12 # define alloca __builtin_alloca
14 # define alloca __alloca
15 #elif defined _MSC_VER
17 # define alloca _alloca
23 void *alloca (size_t);
27 # include <winsock2.h>
32 #include <sys/types.h>
45 #ifdef HAVE_NETINET_IN_H
46 # include <netinet/in.h>
54 # include <gnutls/gnutls.h>
59 # include <openssl/err.h>
60 # include <openssl/evp.h>
63 #ifdef EFL_HAVE_PTHREAD
70 #include "Eet_private.h"
76 #define EET_MAGIC_FILE 0x1ee7ff00
77 #define EET_MAGIC_FILE_HEADER 0x1ee7ff01
79 #define EET_MAGIC_FILE2 0x1ee70f42
81 typedef struct _Eet_File_Header Eet_File_Header;
82 typedef struct _Eet_File_Node Eet_File_Node;
83 typedef struct _Eet_File_Directory Eet_File_Directory;
89 Eet_File_Header *header;
92 const unsigned char *data;
94 const void *signature;
104 unsigned int signature_length;
109 #ifdef EFL_HAVE_PTHREAD
110 pthread_mutex_t file_lock;
113 unsigned char writes_pending : 1;
114 unsigned char delete_me_now : 1;
117 struct _Eet_File_Header
120 Eet_File_Directory *directory;
123 struct _Eet_File_Directory
126 Eet_File_Node **nodes;
129 struct _Eet_File_Node
133 Eet_File_Node *next; /* FIXME: make buckets linked lists */
136 int dictionary_offset;
143 unsigned char free_name : 1;
144 unsigned char compression : 1;
145 unsigned char ciphered : 1;
150 /* NB: all int's are stored in network byte order on disk */
152 int magic; /* magic number ie 0x1ee7ff00 */
153 int num_directory_entries; /* number of directory entries to follow */
154 int bytes_directory_entries; /* bytes of directory entries to follow */
157 int offset; /* bytes offset into file for data chunk */
158 int flags; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */
159 int size; /* size of the data chunk */
160 int data_size; /* size of the (uncompressed) data chunk */
161 int name_size; /* length in bytes of the name field */
162 char name[name_size]; /* name string (variable length) and \0 terminated */
163 } directory[num_directory_entries];
164 /* and now startes the data stream... */
169 /* NB: all int's are stored in network byte order on disk */
171 int magic; /* magic number ie 0x1ee70f42 */
172 int num_directory_entries; /* number of directory entries to follow */
173 int num_dictionary_entries; /* number of dictionary entries to follow */
176 int data_offset; /* bytes offset into file for data chunk */
177 int size; /* size of the data chunk */
178 int data_size; /* size of the (uncompressed) data chunk */
179 int name_offset; /* bytes offset into file for name string */
180 int name_size; /* length in bytes of the name field */
181 int flags; /* flags - for now 0 = uncompressed, 1 = compressed */
182 } directory[num_directory_entries];
190 } dictionary[num_dictionary_entries];
191 /* now start the string stream. */
192 /* and right after them the data stream. */
193 int magic_sign; /* Optional, only if the eet file is signed. */
194 int signature_length; /* Signature length. */
195 int x509_length; /* Public certificate that signed the file. */
196 char signature[signature_length]; /* The signature. */
197 char x509[x509_length]; /* The public certificate. */
200 #define EET_FILE2_HEADER_COUNT 3
201 #define EET_FILE2_DIRECTORY_ENTRY_COUNT 6
202 #define EET_FILE2_DICTIONARY_ENTRY_COUNT 5
204 #define EET_FILE2_HEADER_SIZE (sizeof(int) * EET_FILE2_HEADER_COUNT)
205 #define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DIRECTORY_ENTRY_COUNT)
206 #define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DICTIONARY_ENTRY_COUNT)
208 /* prototypes of internal calls */
209 static Eet_File *eet_cache_find(const char *path, Eet_File **cache, int cache_num);
210 static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
211 static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
212 static int eet_string_match(const char *s1, const char *s2);
214 static Eet_Error eet_flush(Eet_File *ef);
216 static Eet_Error eet_flush2(Eet_File *ef);
217 static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name);
218 static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
220 static Eet_Error eet_internal_close(Eet_File *ef, Eina_Bool locked);
222 #ifdef EFL_HAVE_PTHREAD
223 static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER;
225 #define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock);
226 #define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock);
228 #define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL);
229 #define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock);
230 #define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock);
231 #define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock);
236 #define UNLOCK_CACHE ;
238 #define INIT_FILE(File) ;
239 #define LOCK_FILE(File) ;
240 #define UNLOCK_FILE(File) ;
241 #define DESTROY_FILE(File) ;
245 /* cache. i don't expect this to ever be large, so arrays will do */
246 static int eet_writers_num = 0;
247 static int eet_writers_alloc = 0;
248 static Eet_File **eet_writers = NULL;
249 static int eet_readers_num = 0;
250 static int eet_readers_alloc = 0;
251 static Eet_File **eet_readers = NULL;
252 static int eet_init_count = 0;
254 /* log domain variable */
255 int _eet_log_dom_global = -1;
257 /* Check to see its' an eet file pointer */
259 eet_check_pointer(const Eet_File *ef)
261 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
267 eet_check_header(const Eet_File *ef)
271 if (!ef->header->directory)
277 eet_test_close(int test, Eet_File *ef)
281 ef->delete_me_now = 1;
282 eet_internal_close(ef, EINA_TRUE);
287 /* find an eet file in the currently in use cache */
289 eet_cache_find(const char *path, Eet_File **cache, int cache_num)
294 for (i = 0; i < cache_num; i++)
296 /* if matches real path - return it */
297 if (eet_string_match(cache[i]->path, path))
299 if (!cache[i]->delete_me_now)
308 /* add to end of cache */
309 /* this should only be called when the cache lock is already held */
311 eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
313 Eet_File **new_cache;
317 new_cache_num = *cache_num;
318 if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */
320 Eet_File *del_ef = NULL;
324 for (i = 0; i < new_cache_num; i++)
326 if (new_cache[i]->references == 0)
328 del_ef = new_cache[i];
335 del_ef->delete_me_now = 1;
336 eet_internal_close(del_ef, EINA_TRUE);
341 new_cache_num = *cache_num;
342 new_cache_alloc = *cache_alloc;
344 if (new_cache_num > new_cache_alloc)
346 new_cache_alloc += 16;
347 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
350 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
354 new_cache[new_cache_num - 1] = ef;
356 *cache_num = new_cache_num;
357 *cache_alloc = new_cache_alloc;
360 /* delete from cache */
361 /* this should only be called when the cache lock is already held */
363 eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
365 Eet_File **new_cache;
366 int new_cache_num, new_cache_alloc;
370 new_cache_num = *cache_num;
371 new_cache_alloc = *cache_alloc;
372 if (new_cache_num <= 0)
375 for (i = 0; i < new_cache_num; i++)
377 if (new_cache[i] == ef)
381 if (i >= new_cache_num)
385 for (j = i; j < new_cache_num; j++)
386 new_cache[j] = new_cache[j + 1];
388 if (new_cache_num <= (new_cache_alloc - 16))
390 new_cache_alloc -= 16;
391 if (new_cache_num > 0)
393 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
396 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
407 *cache_num = new_cache_num;
408 *cache_alloc = new_cache_alloc;
411 /* internal string match. null friendly, catches same ptr */
413 eet_string_match(const char *s1, const char *s2)
415 /* both null- no match */
416 if ((!s1) || (!s2)) return 0;
417 if (s1 == s2) return 1;
418 return (!strcmp(s1, s2));
421 /* flush out writes to a v2 eet file */
423 eet_flush2(Eet_File *ef)
427 Eet_Error error = EET_ERROR_NONE;
428 int head[EET_FILE2_HEADER_COUNT];
429 int num_directory_entries = 0;
430 int num_dictionary_entries = 0;
431 int bytes_directory_entries = 0;
432 int bytes_dictionary_entries = 0;
433 int bytes_strings = 0;
435 int strings_offset = 0;
440 if (eet_check_pointer(ef))
441 return EET_ERROR_BAD_OBJECT;
442 if (eet_check_header(ef))
443 return EET_ERROR_EMPTY;
444 if (!ef->writes_pending)
445 return EET_ERROR_NONE;
447 if ((ef->mode == EET_FILE_MODE_READ_WRITE)
448 || (ef->mode == EET_FILE_MODE_WRITE))
452 /* opening for write - delete old copy of file right away */
454 fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
455 fp = fdopen(fd, "wb");
456 if (!fp) return EET_ERROR_NOT_WRITABLE;
457 fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
460 return EET_ERROR_NOT_WRITABLE;
462 /* calculate string base offset and data base offset */
463 num = (1 << ef->header->directory->size);
464 for (i = 0; i < num; ++i)
466 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
468 num_directory_entries++;
469 bytes_strings += strlen(efn->name) + 1;
474 num_dictionary_entries = ef->ed->count;
476 for (i = 0; i < num_dictionary_entries; ++i)
477 bytes_strings += ef->ed->all[i].len;
480 /* calculate section bytes size */
481 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
482 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
484 /* calculate per entry offset */
485 strings_offset = bytes_directory_entries + bytes_dictionary_entries;
486 data_offset = bytes_directory_entries + bytes_dictionary_entries + bytes_strings;
488 for (i = 0; i < num; ++i)
490 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
492 efn->offset = data_offset;
493 data_offset += efn->size;
495 efn->name_offset = strings_offset;
496 strings_offset += efn->name_size;
500 /* calculate dictionary strings offset */
502 ef->ed->offset = strings_offset;
504 /* go thru and write the header */
505 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE2);
506 head[1] = (int) htonl ((unsigned int) num_directory_entries);
507 head[2] = (int) htonl ((unsigned int) num_dictionary_entries);
509 fseek(fp, 0, SEEK_SET);
510 if (fwrite(head, sizeof (head), 1, fp) != 1)
513 /* write directories entry */
514 for (i = 0; i < num; i++)
516 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
519 int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
521 flag = (efn->ciphered << 1) | efn->compression;
523 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
524 ibuf[1] = (int) htonl ((unsigned int) efn->size);
525 ibuf[2] = (int) htonl ((unsigned int) efn->data_size);
526 ibuf[3] = (int) htonl ((unsigned int) efn->name_offset);
527 ibuf[4] = (int) htonl ((unsigned int) efn->name_size);
528 ibuf[5] = (int) htonl ((unsigned int) flag);
530 if (fwrite(ibuf, sizeof(ibuf), 1, fp) != 1)
535 /* write dictionnary */
538 int offset = strings_offset;
540 for (j = 0; j < ef->ed->count; ++j)
542 int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
544 sbuf[0] = (int) htonl ((unsigned int) ef->ed->all[j].hash);
545 sbuf[1] = (int) htonl ((unsigned int) offset);
546 sbuf[2] = (int) htonl ((unsigned int) ef->ed->all[j].len);
547 sbuf[3] = (int) htonl ((unsigned int) ef->ed->all[j].prev);
548 sbuf[4] = (int) htonl ((unsigned int) ef->ed->all[j].next);
550 offset += ef->ed->all[j].len;
552 if (fwrite(sbuf, sizeof (sbuf), 1, fp) != 1)
557 /* write directories name */
558 for (i = 0; i < num; i++)
560 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
562 if (fwrite(efn->name, efn->name_size, 1, fp) != 1)
570 for (j = 0; j < ef->ed->count; ++j)
572 if (ef->ed->all[j].str)
574 if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, fp) != 1)
579 if (fwrite(ef->ed->all[j].mmap, ef->ed->all[j].len, 1, fp) != 1)
586 for (i = 0; i < num; i++)
588 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
590 if (fwrite(efn->data, efn->size, 1, fp) != 1)
595 /* flush all write to the file. */
597 // this is going to really cause trouble. if ANYTHING this needs to go into a
598 // thread spawned off - but even then...
599 // in this case... ext4 is "wrong". (yes we can jump up and down and point posix
600 // manual pages at eachother, but ext4 broke behavior that has been in place
601 // for decades and that 1000's of apps rely on daily - that is that one operation
602 // to disk is committed to disk BEFORE following operations, so the fs retains
603 // a consistent state
604 // fsync(fileno(fp));
606 /* append signature if required */
609 error = eet_identity_sign(fp, ef->key);
610 if (error != EET_ERROR_NONE)
614 /* no more writes pending */
615 ef->writes_pending = 0;
619 return EET_ERROR_NONE;
626 case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
627 case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
628 case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
629 case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
630 default: error = EET_ERROR_WRITE_ERROR; break;
641 if (++eet_init_count != 1)
642 return eet_init_count;
646 fprintf(stderr, "Eet: Eina init failed");
647 return --eet_init_count;
649 _eet_log_dom_global = eina_log_domain_register("Eet", EET_DEFAULT_LOG_COLOR);
650 if (_eet_log_dom_global < 0)
652 EINA_LOG_ERR("Eet Can not create a general log domain.");
656 if (!eet_node_init())
658 EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
659 goto unregister_log_domain;
663 /* Before the library can be used, it must initialize itself if needed. */
664 if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0)
666 gcry_check_version(NULL);
667 /* Disable warning messages about problems with the secure memory subsystem.
668 This command should be run right after gcry_check_version. */
669 if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN))
671 /* This command is used to allocate a pool of secure memory and thus
672 enabling the use of secure memory. It also drops all extra privileges the
673 process has (i.e. if it is run as setuid (root)). If the argument nbytes
674 is 0, secure memory will be disabled. The minimum amount of secure memory
675 allocated is currently 16384 bytes; you may thus use a value of 1 to
676 request that default size. */
677 if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
678 WRN("BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
680 if (gnutls_global_init())
684 ERR_load_crypto_strings();
685 OpenSSL_add_all_algorithms();
688 return eet_init_count;
692 unregister_log_domain:
693 eina_log_domain_unregister(_eet_log_dom_global);
694 _eet_log_dom_global = -1;
697 return --eet_init_count;
703 if (--eet_init_count != 0)
704 return eet_init_count;
709 gnutls_global_deinit();
715 eina_log_domain_unregister(_eet_log_dom_global);
716 _eet_log_dom_global = -1;
719 return eet_init_count;
723 eet_sync(Eet_File *ef)
727 if (eet_check_pointer(ef))
728 return EET_ERROR_BAD_OBJECT;
730 if ((ef->mode != EET_FILE_MODE_WRITE) &&
731 (ef->mode != EET_FILE_MODE_READ_WRITE))
732 return EET_ERROR_NOT_WRITABLE;
734 if (!ef->writes_pending)
735 return EET_ERROR_NONE;
739 ret = eet_flush2(ef);
752 * We need to compute the list of eet file to close separately from the cache,
753 * due to eet_close removing them from the cache after each call.
756 for (i = 0; i < eet_writers_num; i++)
758 if (eet_writers[i]->references <= 0) num++;
761 for (i = 0; i < eet_readers_num; i++)
763 if (eet_readers[i]->references <= 0) num++;
768 Eet_File **closelist = NULL;
770 closelist = alloca(num * sizeof(Eet_File *));
772 for (i = 0; i < eet_writers_num; i++)
774 if (eet_writers[i]->references <= 0)
776 closelist[num] = eet_writers[i];
777 eet_writers[i]->delete_me_now = 1;
782 for (i = 0; i < eet_readers_num; i++)
784 if (eet_readers[i]->references <= 0)
786 closelist[num] = eet_readers[i];
787 eet_readers[i]->delete_me_now = 1;
792 for (i = 0; i < num; i++)
794 eet_internal_close(closelist[i], EINA_TRUE);
800 /* FIXME: MMAP race condition in READ_WRITE_MODE */
802 eet_internal_read2(Eet_File *ef)
804 const int *data = (const int*) ef->data;
805 const char *start = (const char*) ef->data;
807 int num_directory_entries;
808 int bytes_directory_entries;
809 int num_dictionary_entries;
810 int bytes_dictionary_entries;
811 int signature_base_offset;
815 if (eet_test_close((int) ntohl(*data) != EET_MAGIC_FILE2, ef))
819 #define GET_INT(Value, Pointer, Index) \
821 Value = ntohl(*Pointer); \
823 Index += sizeof(int); \
826 /* get entries count and byte count */
827 GET_INT(num_directory_entries, data, idx);
828 /* get dictionary count and byte count */
829 GET_INT(num_dictionary_entries, data, idx);
831 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
832 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
834 /* we cant have <= 0 values here - invalid */
835 if (eet_test_close((num_directory_entries <= 0), ef))
838 /* we cant have more bytes directory and bytes in dictionaries than the size of the file */
839 if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > ef->data_size, ef))
842 /* allocate header */
843 ef->header = calloc(1, sizeof(Eet_File_Header));
844 if (eet_test_close(!ef->header, ef))
847 ef->header->magic = EET_MAGIC_FILE_HEADER;
849 /* allocate directory block in ram */
850 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
851 if (eet_test_close(!ef->header->directory, ef))
854 /* 8 bit hash table (256 buckets) */
855 ef->header->directory->size = 8;
856 /* allocate base hash table */
857 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
858 if (eet_test_close(!ef->header->directory->nodes, ef))
861 signature_base_offset = 0;
863 /* actually read the directory block - all of it, into ram */
864 for (i = 0; i < num_directory_entries; ++i)
873 /* out directory block is inconsistent - we have oveerun our */
874 /* dynamic block buffer before we finished scanning dir entries */
875 efn = malloc (sizeof(Eet_File_Node));
876 if (eet_test_close(!efn, ef))
879 /* get entrie header */
880 GET_INT(efn->offset, data, idx);
881 GET_INT(efn->size, data, idx);
882 GET_INT(efn->data_size, data, idx);
883 GET_INT(name_offset, data, idx);
884 GET_INT(name_size, data, idx);
885 GET_INT(flag, data, idx);
887 efn->compression = flag & 0x1 ? 1 : 0;
888 efn->ciphered = flag & 0x2 ? 1 : 0;
890 #define EFN_TEST(Test, Ef, Efn) \
891 if (eet_test_close(Test, Ef)) \
897 /* check data pointer position */
898 EFN_TEST(!((efn->size > 0)
899 && (efn->offset + efn->size <= ef->data_size)
900 && (efn->offset > bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
902 /* check name position */
903 EFN_TEST(!((name_size > 0)
904 && (name_offset + name_size < ef->data_size)
905 && (name_offset >= bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
907 name = start + name_offset;
909 /* check '\0' at the end of name string */
910 EFN_TEST(name[name_size - 1] != '\0', ef, efn);
913 efn->name = (char*) name;
914 efn->name_size = name_size;
916 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
917 efn->next = ef->header->directory->nodes[hash];
918 ef->header->directory->nodes[hash] = efn;
920 /* read-only mode, so currently we have no data loaded */
921 if (ef->mode == EET_FILE_MODE_READ)
923 /* read-write mode - read everything into ram */
926 efn->data = malloc(efn->size);
928 memcpy(efn->data, ef->data + efn->offset, efn->size);
931 /* compute the possible position of a signature */
932 if (signature_base_offset < efn->offset + efn->size)
933 signature_base_offset = efn->offset + efn->size;
938 if (num_dictionary_entries)
940 const int *dico = (const int*) ef->data + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + EET_FILE2_HEADER_COUNT;
943 if (eet_test_close((num_dictionary_entries * (int) EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) > (bytes_dictionary_entries + bytes_directory_entries), ef))
946 ef->ed = calloc(1, sizeof (Eet_Dictionary));
947 if (eet_test_close(!ef->ed, ef)) return NULL;
949 ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String));
950 if (eet_test_close(!ef->ed->all, ef)) return NULL;
952 ef->ed->count = num_dictionary_entries;
953 ef->ed->total = num_dictionary_entries;
954 ef->ed->start = start + bytes_dictionary_entries + bytes_directory_entries;
955 ef->ed->end = ef->ed->start;
957 for (j = 0; j < ef->ed->count; ++j)
962 GET_INT(hash, dico, idx);
963 GET_INT(offset, dico, idx);
964 GET_INT(ef->ed->all[j].len, dico, idx);
965 GET_INT(ef->ed->all[j].prev, dico, idx);
966 GET_INT(ef->ed->all[j].next, dico, idx);
968 /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
969 So stick to int and check the value. */
970 if (eet_test_close(hash & 0xFFFFFF00, ef)) return NULL;
972 /* Check string position */
973 if (eet_test_close(!((ef->ed->all[j].len > 0)
974 && (offset > (bytes_dictionary_entries + bytes_directory_entries))
975 && (offset + ef->ed->all[j].len < ef->data_size)), ef))
978 ef->ed->all[j].mmap = start + offset;
979 ef->ed->all[j].str = NULL;
981 if (ef->ed->all[j].mmap + ef->ed->all[j].len > ef->ed->end)
982 ef->ed->end = ef->ed->all[j].mmap + ef->ed->all[j].len;
984 /* Check '\0' at the end of the string */
985 if (eet_test_close(ef->ed->all[j].mmap[ef->ed->all[j].len - 1] != '\0', ef)) return NULL;
987 ef->ed->all[j].hash = hash;
988 if (ef->ed->all[j].prev == -1)
989 ef->ed->hash[hash] = j;
991 /* compute the possible position of a signature */
992 if (signature_base_offset < offset + ef->ed->all[j].len)
993 signature_base_offset = offset + ef->ed->all[j].len;
997 /* Check if the file is signed */
1000 ef->signature = NULL;
1001 ef->signature_length = 0;
1003 if (signature_base_offset < ef->data_size)
1005 #ifdef HAVE_SIGNATURE
1006 const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset;
1007 ef->x509_der = eet_identity_check(ef->data, signature_base_offset,
1008 &ef->sha1, &ef->sha1_length,
1009 buffer, ef->data_size - signature_base_offset,
1010 &ef->signature, &ef->signature_length,
1013 if (eet_test_close(ef->x509_der == NULL, ef)) return NULL;
1015 ERR("This file could be signed but you didn't compile the necessary code to check the signature.");
1022 #if EET_OLD_EET_FILE_FORMAT
1024 eet_internal_read1(Eet_File *ef)
1026 const unsigned char *dyn_buf = NULL;
1027 const unsigned char *p = NULL;
1033 WRN("EET file format of '%s' is deprecated. You should just open it one time with mode == EET_FILE_MODE_READ_WRITE to solve this issue.", ef->path);
1035 /* build header table if read mode */
1038 if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
1041 #define EXTRACT_INT(Value, Pointer, Index) \
1044 memcpy(&tmp, Pointer + Index, sizeof(int)); \
1045 Value = ntohl(tmp); \
1046 Index += sizeof(int); \
1049 /* get entries count and byte count */
1050 EXTRACT_INT(num_entries, ef->data, idx);
1051 EXTRACT_INT(byte_entries, ef->data, idx);
1053 /* we cant have <= 0 values here - invalid */
1054 if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef))
1057 /* we can't have more entires than minimum bytes for those! invalid! */
1058 if (eet_test_close((num_entries * 20) > byte_entries, ef))
1061 /* check we will not outrun the file limit */
1062 if (eet_test_close(((byte_entries + (int) sizeof(int) * 3) > ef->data_size), ef))
1065 /* allocate header */
1066 ef->header = calloc(1, sizeof(Eet_File_Header));
1067 if (eet_test_close(!ef->header, ef))
1070 ef->header->magic = EET_MAGIC_FILE_HEADER;
1072 /* allocate directory block in ram */
1073 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1074 if (eet_test_close(!ef->header->directory, ef))
1077 /* 8 bit hash table (256 buckets) */
1078 ef->header->directory->size = 8;
1079 /* allocate base hash table */
1080 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1081 if (eet_test_close(!ef->header->directory->nodes, ef))
1084 /* actually read the directory block - all of it, into ram */
1085 dyn_buf = ef->data + idx;
1087 /* parse directory block */
1090 for (i = 0; i < num_entries; i++)
1099 #define HEADER_SIZE (sizeof(int) * 5)
1101 /* out directory block is inconsistent - we have oveerun our */
1102 /* dynamic block buffer before we finished scanning dir entries */
1103 if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
1106 /* allocate all the ram needed for this stored node accounting */
1107 efn = malloc (sizeof(Eet_File_Node));
1108 if (eet_test_close(!efn, ef))
1111 /* get entrie header */
1112 EXTRACT_INT(efn->offset, p, indexn);
1113 EXTRACT_INT(efn->compression, p, indexn);
1114 EXTRACT_INT(efn->size, p, indexn);
1115 EXTRACT_INT(efn->data_size, p, indexn);
1116 EXTRACT_INT(name_size, p, indexn);
1118 efn->name_size = name_size;
1122 if (eet_test_close(efn->size <= 0, ef))
1128 /* invalid name_size */
1129 if (eet_test_close(name_size <= 0, ef))
1135 /* reading name would mean falling off end of dyn_buf - invalid */
1136 if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
1142 /* This code is useless if we dont want backward compatibility */
1143 for (k = name_size; k > 0 && ((unsigned char) * (p + HEADER_SIZE + k)) != 0; --k)
1146 efn->free_name = ((unsigned char) * (p + HEADER_SIZE + k)) != 0;
1150 efn->name = malloc(sizeof(char) * name_size + 1);
1151 if (eet_test_close(efn->name == NULL, ef))
1157 strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
1158 efn->name[name_size] = 0;
1160 WRN("File: %s is not up to date for key \"%s\" - needs rebuilding sometime", ef->path, efn->name);
1163 /* The only really usefull peace of code for efn->name (no backward compatibility) */
1164 efn->name = (char*)((unsigned char*)(p + HEADER_SIZE));
1166 /* get hash bucket it should go in */
1167 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1168 efn->next = ef->header->directory->nodes[hash];
1169 ef->header->directory->nodes[hash] = efn;
1171 /* read-only mode, so currently we have no data loaded */
1172 if (ef->mode == EET_FILE_MODE_READ)
1174 /* read-write mode - read everything into ram */
1177 data = malloc(efn->size);
1179 memcpy(data, ef->data + efn->offset, efn->size);
1183 p += HEADER_SIZE + name_size;
1190 * this should only be called when the cache lock is already held
1191 * (We could drop this restriction if we add a parameter to eet_test_close
1192 * that indicates if the lock is held or not. For now it is easiest
1193 * to just require that it is always held.)
1196 eet_internal_read(Eet_File *ef)
1198 const int *data = (const int*) ef->data;
1200 if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef))
1203 if (eet_test_close(ef->data_size < (int) sizeof(int) * 3, ef))
1206 switch (ntohl(*data))
1208 #if EET_OLD_EET_FILE_FORMAT
1209 case EET_MAGIC_FILE:
1210 return eet_internal_read1(ef);
1212 case EET_MAGIC_FILE2:
1213 return eet_internal_read2(ef);
1215 ef->delete_me_now = 1;
1216 eet_internal_close(ef, EINA_TRUE);
1224 eet_internal_close(Eet_File *ef, Eina_Bool locked)
1228 /* check to see its' an eet file pointer */
1229 if (eet_check_pointer(ef))
1230 return EET_ERROR_BAD_OBJECT;
1232 if (!locked) LOCK_CACHE;
1236 /* if its still referenced - dont go any further */
1237 if (ef->references > 0) goto on_error;
1238 /* flush any writes */
1239 err = eet_flush2(ef);
1241 eet_identity_unref(ef->key);
1244 /* if not urgent to delete it - dont free it - leave it in cache */
1245 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
1248 /* remove from cache */
1249 if (ef->mode == EET_FILE_MODE_READ)
1250 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1251 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1252 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1254 /* we can unlock the cache now */
1255 if (!locked) UNLOCK_CACHE;
1262 if (ef->header->directory)
1264 if (ef->header->directory->nodes)
1268 num = (1 << ef->header->directory->size);
1269 for (i = 0; i < num; i++)
1273 while ((efn = ef->header->directory->nodes[i]))
1278 ef->header->directory->nodes[i] = efn->next;
1286 free(ef->header->directory->nodes);
1288 free(ef->header->directory);
1293 eet_dictionary_free(ef->ed);
1295 if (ef->sha1) free(ef->sha1);
1296 if (ef->data) munmap((void*)ef->data, ef->data_size);
1297 if (ef->readfp) fclose(ef->readfp);
1299 /* zero out ram for struct - caution tactic against stale memory use */
1300 memset(ef, 0, sizeof(Eet_File));
1307 if (!locked) UNLOCK_CACHE;
1308 return EET_ERROR_NONE;
1312 eet_memopen_read(const void *data, size_t size)
1316 if (data == NULL || size == 0)
1319 ef = malloc (sizeof (Eet_File));
1327 ef->magic = EET_MAGIC_FILE;
1329 ef->mode = EET_FILE_MODE_READ;
1332 ef->delete_me_now = 1;
1335 ef->data_size = size;
1337 ef->sha1_length = 0;
1339 /* eet_internal_read expects the cache lock to be held when it is called */
1341 ef = eet_internal_read(ef);
1347 eet_open(const char *file, Eet_File_Mode mode)
1352 struct stat file_stat;
1357 /* find the current file handle in cache*/
1360 if (mode == EET_FILE_MODE_READ)
1362 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1367 ef->delete_me_now = 1;
1368 eet_internal_close(ef, EINA_TRUE);
1370 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1372 else if ((mode == EET_FILE_MODE_WRITE) ||
1373 (mode == EET_FILE_MODE_READ_WRITE))
1375 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1378 ef->delete_me_now = 1;
1380 eet_internal_close(ef, EINA_TRUE);
1382 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1385 /* try open the file based on mode */
1386 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1388 /* Prevent garbage in futur comparison. */
1389 file_stat.st_mtime = 0;
1391 fp = fopen(file, "rb");
1392 if (!fp) goto open_error;
1393 if (fstat(fileno(fp), &file_stat))
1399 if ((mode == EET_FILE_MODE_READ) &&
1400 (file_stat.st_size < ((int) sizeof(int) * 3)))
1408 if (fp == NULL && mode == EET_FILE_MODE_READ) goto on_error;
1412 if (mode != EET_FILE_MODE_WRITE) return NULL;
1413 memset(&file_stat, 0, sizeof(file_stat));
1419 if (ef && (file_stat.st_mtime != ef->mtime))
1421 ef->delete_me_now = 1;
1423 eet_internal_close(ef, EINA_TRUE);
1429 /* reference it up and return it */
1430 if (fp != NULL) fclose(fp);
1436 file_len = strlen(file) + 1;
1438 /* Allocate struct for eet file and have it zero'd out */
1439 ef = malloc(sizeof(Eet_File) + file_len);
1443 /* fill some of the members */
1447 ef->path = ((char *)ef) + sizeof(Eet_File);
1448 memcpy(ef->path, file, file_len);
1449 ef->magic = EET_MAGIC_FILE;
1453 ef->mtime = file_stat.st_mtime;
1454 ef->writes_pending = 0;
1455 ef->delete_me_now = 0;
1459 ef->sha1_length = 0;
1461 ef->ed = (mode == EET_FILE_MODE_WRITE)
1462 || (ef->readfp == NULL && mode == EET_FILE_MODE_READ_WRITE) ?
1463 eet_dictionary_add() : NULL;
1465 if (ef->readfp == NULL &&
1466 (mode == EET_FILE_MODE_READ_WRITE || mode == EET_FILE_MODE_WRITE))
1469 /* if we can't open - bail out */
1470 if (eet_test_close(!ef->readfp, ef))
1473 fcntl(fileno(ef->readfp), F_SETFD, FD_CLOEXEC);
1474 /* if we opened for read or read-write */
1475 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1477 ef->data_size = file_stat.st_size;
1478 ef->data = mmap(NULL, ef->data_size, PROT_READ,
1479 MAP_SHARED, fileno(ef->readfp), 0);
1480 if (eet_test_close((ef->data == MAP_FAILED), ef))
1482 ef = eet_internal_read(ef);
1489 if (ef->references == 1)
1491 if (ef->mode == EET_FILE_MODE_READ)
1492 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1494 if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1495 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1507 eet_mode_get(Eet_File *ef)
1509 /* check to see its' an eet file pointer */
1510 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
1511 return EET_FILE_MODE_INVALID;
1517 eet_identity_x509(Eet_File *ef, int *der_length)
1519 if (!ef->x509_der) return NULL;
1521 if (der_length) *der_length = ef->x509_length;
1522 return ef->x509_der;
1526 eet_identity_signature(Eet_File *ef, int *signature_length)
1528 if (!ef->signature) return NULL;
1530 if (signature_length) *signature_length = ef->signature_length;
1531 return ef->signature;
1535 eet_identity_sha1(Eet_File *ef, int *sha1_length)
1538 ef->sha1 = eet_identity_compute_sha1(ef->data, ef->data_size, &ef->sha1_length);
1540 if (sha1_length) *sha1_length = ef->sha1_length;
1545 eet_identity_set(Eet_File *ef, Eet_Key *key)
1547 Eet_Key *tmp = ef->key;
1549 if (!ef) return EET_ERROR_BAD_OBJECT;
1552 eet_identity_ref(ef->key);
1553 eet_identity_unref(tmp);
1555 /* flags that writes are pending */
1556 ef->writes_pending = 1;
1558 return EET_ERROR_NONE;
1562 eet_close(Eet_File *ef)
1564 return eet_internal_close(ef, EINA_FALSE);
1568 eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *cipher_key)
1577 /* check to see its' an eet file pointer */
1578 if (eet_check_pointer(ef))
1582 if ((ef->mode != EET_FILE_MODE_READ) &&
1583 (ef->mode != EET_FILE_MODE_READ_WRITE))
1586 /* no header, return NULL */
1587 if (eet_check_header(ef))
1592 /* hunt hash bucket */
1593 efn = find_node_by_name(ef, name);
1594 if (!efn) goto on_error;
1596 /* get size (uncompressed, if compressed at all) */
1597 size = efn->data_size;
1600 data = malloc(size);
1601 if (!data) goto on_error;
1603 /* uncompressed data */
1604 if (efn->compression == 0)
1606 void *data_deciphered = NULL;
1607 unsigned int data_deciphered_sz = 0;
1608 /* if we alreayd have the data in ram... copy that */
1610 memcpy(data, efn->data, efn->size);
1612 if (!read_data_from_disk(ef, efn, data, size))
1614 if (efn->ciphered && cipher_key)
1616 if (eet_decipher(data, size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1618 if (data_deciphered) free(data_deciphered);
1622 data = data_deciphered;
1623 size = data_deciphered_sz;
1626 /* compressed data */
1630 void *data_deciphered = NULL;
1631 unsigned int data_deciphered_sz = 0;
1633 int compr_size = efn->size;
1636 /* if we already have the data in ram... copy that */
1638 tmp_data = efn->data;
1641 tmp_data = malloc(compr_size);
1647 if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
1654 if (efn->ciphered && cipher_key)
1656 if (eet_decipher(tmp_data, compr_size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1658 if (free_tmp) free(tmp_data);
1659 if (data_deciphered) free(data_deciphered);
1663 tmp_data = data_deciphered;
1664 compr_size = data_deciphered_sz;
1669 if (uncompress((Bytef *)data, &dlen,
1670 tmp_data, (uLongf)compr_size))
1677 /* fill in return values */
1692 eet_read(Eet_File *ef, const char *name, int *size_ret)
1694 return eet_read_cipher(ef, name, size_ret, NULL);
1698 eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
1700 const void *data = NULL;
1707 /* check to see its' an eet file pointer */
1708 if (eet_check_pointer(ef))
1712 if ((ef->mode != EET_FILE_MODE_READ) &&
1713 (ef->mode != EET_FILE_MODE_READ_WRITE))
1716 /* no header, return NULL */
1717 if (eet_check_header(ef))
1722 /* hunt hash bucket */
1723 efn = find_node_by_name(ef, name);
1724 if (!efn) goto on_error;
1726 if (efn->offset < 0 && efn->data == NULL)
1729 /* get size (uncompressed, if compressed at all) */
1730 size = efn->data_size;
1732 /* uncompressed data */
1733 if (efn->compression == 0
1734 && efn->ciphered == 0)
1735 data = efn->data ? efn->data : ef->data + efn->offset;
1736 /* compressed data */
1740 /* fill in return values */
1754 eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int comp, const char *cipher_key)
1758 int exists_already = 0;
1762 /* check to see its' an eet file pointer */
1763 if (eet_check_pointer(ef))
1765 if ((!name) || (!data) || (size <= 0))
1767 if ((ef->mode != EET_FILE_MODE_WRITE) &&
1768 (ef->mode != EET_FILE_MODE_READ_WRITE))
1775 /* allocate header */
1776 ef->header = calloc(1, sizeof(Eet_File_Header));
1780 ef->header->magic = EET_MAGIC_FILE_HEADER;
1781 /* allocate directory block in ram */
1782 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1783 if (!ef->header->directory)
1790 /* 8 bit hash table (256 buckets) */
1791 ef->header->directory->size = 8;
1792 /* allocate base hash table */
1793 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1794 if (!ef->header->directory->nodes)
1796 free(ef->header->directory);
1802 /* figure hash bucket */
1803 hash = _eet_hash_gen(name, ef->header->directory->size);
1805 data_size = comp ? 12 + ((size * 101) / 100) : size;
1807 if (comp || !cipher_key)
1809 data2 = malloc(data_size);
1810 if (!data2) goto on_error;
1813 /* if we want to compress */
1818 /* compress the data with max compression */
1819 buflen = (uLongf)data_size;
1820 if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
1821 (uLong)size, Z_BEST_COMPRESSION) != Z_OK)
1826 /* record compressed chunk size */
1827 data_size = (int)buflen;
1828 if (data_size < 0 || data_size >= size)
1837 data3 = realloc(data2, data_size);
1845 void *data_ciphered = NULL;
1846 unsigned int data_ciphered_sz = 0;
1849 tmp = data2 ? data2 : data;
1850 if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), &data_ciphered, &data_ciphered_sz))
1852 if (data2) free(data2);
1853 data2 = data_ciphered;
1854 data_size = data_ciphered_sz;
1855 size = (data_size > size) ? data_size : size;
1859 if (data_ciphered) free(data_ciphered);
1865 memcpy(data2, data, size);
1867 /* Does this node already exist? */
1868 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
1871 if ((efn->name) && (eet_string_match(efn->name, name)))
1874 efn->ciphered = cipher_key ? 1 : 0;
1875 efn->compression = !!comp;
1876 efn->size = data_size;
1877 efn->data_size = size;
1884 if (!exists_already)
1886 efn = malloc(sizeof(Eet_File_Node));
1892 efn->name = strdup(name);
1893 efn->name_size = strlen(efn->name) + 1;
1896 efn->next = ef->header->directory->nodes[hash];
1897 ef->header->directory->nodes[hash] = efn;
1899 efn->ciphered = cipher_key ? 1 : 0;
1900 efn->compression = !!comp;
1901 efn->size = data_size;
1902 efn->data_size = size;
1906 /* flags that writes are pending */
1907 ef->writes_pending = 1;
1917 eet_write(Eet_File *ef, const char *name, const void *data, int size, int comp)
1919 return eet_write_cipher(ef, name, data, size, comp, NULL);
1923 eet_delete(Eet_File *ef, const char *name)
1926 Eet_File_Node *pefn;
1928 int exists_already = 0;
1930 /* check to see its' an eet file pointer */
1931 if (eet_check_pointer(ef))
1936 /* deleting keys is only possible in RW or WRITE mode */
1937 if (ef->mode == EET_FILE_MODE_READ)
1940 if (eet_check_header(ef))
1945 /* figure hash bucket */
1946 hash = _eet_hash_gen(name, ef->header->directory->size);
1948 /* Does this node already exist? */
1949 for (pefn = NULL, efn = ef->header->directory->nodes[hash];
1951 pefn = efn, efn = efn->next)
1954 if (eet_string_match(efn->name, name))
1960 ef->header->directory->nodes[hash] = efn->next;
1962 pefn->next = efn->next;
1964 if (efn->free_name) free(efn->name);
1970 /* flags that writes are pending */
1972 ef->writes_pending = 1;
1976 /* update access time */
1977 return exists_already;
1980 EAPI Eet_Dictionary *
1981 eet_dictionary_get(Eet_File *ef)
1983 if (eet_check_pointer(ef)) return NULL;
1990 eet_list(Eet_File *ef, const char *glob, int *count_ret)
1993 char **list_ret = NULL;
1995 int list_count_alloc = 0;
1998 /* check to see its' an eet file pointer */
1999 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2001 ((ef->mode != EET_FILE_MODE_READ) &&
2002 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2010 if (!strcmp(glob, "*")) glob = NULL;
2014 /* loop through all entries */
2015 num = (1 << ef->header->directory->size);
2016 for (i = 0; i < num; i++)
2018 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2020 /* if the entry matches the input glob
2021 * check for * explicitly, because on some systems, * isn't well
2024 if ((!glob) || !fnmatch(glob, efn->name, 0))
2026 /* add it to our list */
2029 /* only realloc in 32 entry chunks */
2030 if (list_count > list_count_alloc)
2032 char **new_list = NULL;
2034 list_count_alloc += 64;
2035 new_list = realloc(list_ret, list_count_alloc * (sizeof(char *)));
2042 list_ret = new_list;
2045 /* put pointer of name string in */
2046 list_ret[list_count - 1] = efn->name;
2053 /* return count and list */
2055 *count_ret = list_count;
2069 eet_num_entries(Eet_File *ef)
2071 int i, num, ret = 0;
2074 /* check to see its' an eet file pointer */
2075 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2076 ((ef->mode != EET_FILE_MODE_READ) &&
2077 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2082 /* loop through all entries */
2083 num = (1 << ef->header->directory->size);
2084 for (i = 0; i < num; i++)
2086 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2095 static Eet_File_Node *
2096 find_node_by_name(Eet_File *ef, const char *name)
2101 /* get hash bucket this should be in */
2102 hash = _eet_hash_gen(name, ef->header->directory->size);
2104 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2106 if (eet_string_match(efn->name, name))
2114 read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len)
2116 if (efn->offset < 0) return 0;
2120 if ((efn->offset + len) > ef->data_size) return 0;
2121 memcpy(buf, ef->data + efn->offset, len);
2128 /* seek to data location */
2129 if (fseek(ef->readfp, efn->offset, SEEK_SET) < 0)
2133 len = fread(buf, len, 1, ef->readfp);