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"
72 static Eet_Version _version = { VMAJ, VMIN, VMIC, VREV };
73 EAPI Eet_Version *eet_version = &_version;;
79 #define EET_MAGIC_FILE 0x1ee7ff00
80 #define EET_MAGIC_FILE_HEADER 0x1ee7ff01
82 #define EET_MAGIC_FILE2 0x1ee70f42
84 typedef struct _Eet_File_Header Eet_File_Header;
85 typedef struct _Eet_File_Node Eet_File_Node;
86 typedef struct _Eet_File_Directory Eet_File_Directory;
92 Eet_File_Header *header;
95 const unsigned char *data;
97 const void *signature;
107 unsigned int signature_length;
112 #ifdef EFL_HAVE_PTHREAD
113 pthread_mutex_t file_lock;
116 unsigned char writes_pending : 1;
117 unsigned char delete_me_now : 1;
120 struct _Eet_File_Header
123 Eet_File_Directory *directory;
126 struct _Eet_File_Directory
129 Eet_File_Node **nodes;
132 struct _Eet_File_Node
136 Eet_File_Node *next; /* FIXME: make buckets linked lists */
139 int dictionary_offset;
146 unsigned char free_name : 1;
147 unsigned char compression : 1;
148 unsigned char ciphered : 1;
153 /* NB: all int's are stored in network byte order on disk */
155 int magic; /* magic number ie 0x1ee7ff00 */
156 int num_directory_entries; /* number of directory entries to follow */
157 int bytes_directory_entries; /* bytes of directory entries to follow */
160 int offset; /* bytes offset into file for data chunk */
161 int flags; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */
162 int size; /* size of the data chunk */
163 int data_size; /* size of the (uncompressed) data chunk */
164 int name_size; /* length in bytes of the name field */
165 char name[name_size]; /* name string (variable length) and \0 terminated */
166 } directory[num_directory_entries];
167 /* and now startes the data stream... */
172 /* NB: all int's are stored in network byte order on disk */
174 int magic; /* magic number ie 0x1ee70f42 */
175 int num_directory_entries; /* number of directory entries to follow */
176 int num_dictionary_entries; /* number of dictionary entries to follow */
179 int data_offset; /* bytes offset into file for data chunk */
180 int size; /* size of the data chunk */
181 int data_size; /* size of the (uncompressed) data chunk */
182 int name_offset; /* bytes offset into file for name string */
183 int name_size; /* length in bytes of the name field */
184 int flags; /* flags - for now 0 = uncompressed, 1 = compressed */
185 } directory[num_directory_entries];
193 } dictionary[num_dictionary_entries];
194 /* now start the string stream. */
195 /* and right after them the data stream. */
196 int magic_sign; /* Optional, only if the eet file is signed. */
197 int signature_length; /* Signature length. */
198 int x509_length; /* Public certificate that signed the file. */
199 char signature[signature_length]; /* The signature. */
200 char x509[x509_length]; /* The public certificate. */
203 #define EET_FILE2_HEADER_COUNT 3
204 #define EET_FILE2_DIRECTORY_ENTRY_COUNT 6
205 #define EET_FILE2_DICTIONARY_ENTRY_COUNT 5
207 #define EET_FILE2_HEADER_SIZE (sizeof(int) * EET_FILE2_HEADER_COUNT)
208 #define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DIRECTORY_ENTRY_COUNT)
209 #define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DICTIONARY_ENTRY_COUNT)
211 /* prototypes of internal calls */
212 static Eet_File *eet_cache_find(const char *path, Eet_File **cache, int cache_num);
213 static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
214 static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
215 static int eet_string_match(const char *s1, const char *s2);
217 static Eet_Error eet_flush(Eet_File *ef);
219 static Eet_Error eet_flush2(Eet_File *ef);
220 static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name);
221 static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
223 static Eet_Error eet_internal_close(Eet_File *ef, Eina_Bool locked);
225 #ifdef EFL_HAVE_PTHREAD
226 static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER;
228 #define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock);
229 #define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock);
231 #define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL);
232 #define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock);
233 #define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock);
234 #define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock);
239 #define UNLOCK_CACHE ;
241 #define INIT_FILE(File) ;
242 #define LOCK_FILE(File) ;
243 #define UNLOCK_FILE(File) ;
244 #define DESTROY_FILE(File) ;
248 /* cache. i don't expect this to ever be large, so arrays will do */
249 static int eet_writers_num = 0;
250 static int eet_writers_alloc = 0;
251 static Eet_File **eet_writers = NULL;
252 static int eet_readers_num = 0;
253 static int eet_readers_alloc = 0;
254 static Eet_File **eet_readers = NULL;
255 static int eet_init_count = 0;
257 /* log domain variable */
258 int _eet_log_dom_global = -1;
260 /* Check to see its' an eet file pointer */
262 eet_check_pointer(const Eet_File *ef)
264 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
270 eet_check_header(const Eet_File *ef)
274 if (!ef->header->directory)
280 eet_test_close(int test, Eet_File *ef)
284 ef->delete_me_now = 1;
285 eet_internal_close(ef, EINA_TRUE);
290 /* find an eet file in the currently in use cache */
292 eet_cache_find(const char *path, Eet_File **cache, int cache_num)
297 for (i = 0; i < cache_num; i++)
299 /* if matches real path - return it */
300 if (eet_string_match(cache[i]->path, path))
302 if (!cache[i]->delete_me_now)
311 /* add to end of cache */
312 /* this should only be called when the cache lock is already held */
314 eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
316 Eet_File **new_cache;
320 new_cache_num = *cache_num;
321 if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */
323 Eet_File *del_ef = NULL;
327 for (i = 0; i < new_cache_num; i++)
329 if (new_cache[i]->references == 0)
331 del_ef = new_cache[i];
338 del_ef->delete_me_now = 1;
339 eet_internal_close(del_ef, EINA_TRUE);
344 new_cache_num = *cache_num;
345 new_cache_alloc = *cache_alloc;
347 if (new_cache_num > new_cache_alloc)
349 new_cache_alloc += 16;
350 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
353 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
357 new_cache[new_cache_num - 1] = ef;
359 *cache_num = new_cache_num;
360 *cache_alloc = new_cache_alloc;
363 /* delete from cache */
364 /* this should only be called when the cache lock is already held */
366 eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
368 Eet_File **new_cache;
369 int new_cache_num, new_cache_alloc;
373 new_cache_num = *cache_num;
374 new_cache_alloc = *cache_alloc;
375 if (new_cache_num <= 0)
378 for (i = 0; i < new_cache_num; i++)
380 if (new_cache[i] == ef)
384 if (i >= new_cache_num)
388 for (j = i; j < new_cache_num; j++)
389 new_cache[j] = new_cache[j + 1];
391 if (new_cache_num <= (new_cache_alloc - 16))
393 new_cache_alloc -= 16;
394 if (new_cache_num > 0)
396 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
399 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
410 *cache_num = new_cache_num;
411 *cache_alloc = new_cache_alloc;
414 /* internal string match. null friendly, catches same ptr */
416 eet_string_match(const char *s1, const char *s2)
418 /* both null- no match */
419 if ((!s1) || (!s2)) return 0;
420 if (s1 == s2) return 1;
421 return (!strcmp(s1, s2));
424 /* flush out writes to a v2 eet file */
426 eet_flush2(Eet_File *ef)
430 Eet_Error error = EET_ERROR_NONE;
431 int head[EET_FILE2_HEADER_COUNT];
432 int num_directory_entries = 0;
433 int num_dictionary_entries = 0;
434 int bytes_directory_entries = 0;
435 int bytes_dictionary_entries = 0;
436 int bytes_strings = 0;
438 int strings_offset = 0;
443 if (eet_check_pointer(ef))
444 return EET_ERROR_BAD_OBJECT;
445 if (eet_check_header(ef))
446 return EET_ERROR_EMPTY;
447 if (!ef->writes_pending)
448 return EET_ERROR_NONE;
450 if ((ef->mode == EET_FILE_MODE_READ_WRITE)
451 || (ef->mode == EET_FILE_MODE_WRITE))
455 /* opening for write - delete old copy of file right away */
457 fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
458 fp = fdopen(fd, "wb");
459 if (!fp) return EET_ERROR_NOT_WRITABLE;
460 fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
463 return EET_ERROR_NOT_WRITABLE;
465 /* calculate string base offset and data base offset */
466 num = (1 << ef->header->directory->size);
467 for (i = 0; i < num; ++i)
469 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
471 num_directory_entries++;
472 bytes_strings += strlen(efn->name) + 1;
477 num_dictionary_entries = ef->ed->count;
479 for (i = 0; i < num_dictionary_entries; ++i)
480 bytes_strings += ef->ed->all[i].len;
483 /* calculate section bytes size */
484 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
485 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
487 /* calculate per entry offset */
488 strings_offset = bytes_directory_entries + bytes_dictionary_entries;
489 data_offset = bytes_directory_entries + bytes_dictionary_entries + bytes_strings;
491 for (i = 0; i < num; ++i)
493 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
495 efn->offset = data_offset;
496 data_offset += efn->size;
498 efn->name_offset = strings_offset;
499 strings_offset += efn->name_size;
503 /* calculate dictionary strings offset */
505 ef->ed->offset = strings_offset;
507 /* go thru and write the header */
508 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE2);
509 head[1] = (int) htonl ((unsigned int) num_directory_entries);
510 head[2] = (int) htonl ((unsigned int) num_dictionary_entries);
512 fseek(fp, 0, SEEK_SET);
513 if (fwrite(head, sizeof (head), 1, fp) != 1)
516 /* write directories entry */
517 for (i = 0; i < num; i++)
519 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
522 int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
524 flag = (efn->ciphered << 1) | efn->compression;
526 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
527 ibuf[1] = (int) htonl ((unsigned int) efn->size);
528 ibuf[2] = (int) htonl ((unsigned int) efn->data_size);
529 ibuf[3] = (int) htonl ((unsigned int) efn->name_offset);
530 ibuf[4] = (int) htonl ((unsigned int) efn->name_size);
531 ibuf[5] = (int) htonl ((unsigned int) flag);
533 if (fwrite(ibuf, sizeof(ibuf), 1, fp) != 1)
538 /* write dictionnary */
541 int offset = strings_offset;
543 for (j = 0; j < ef->ed->count; ++j)
545 int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
547 sbuf[0] = (int) htonl ((unsigned int) ef->ed->all[j].hash);
548 sbuf[1] = (int) htonl ((unsigned int) offset);
549 sbuf[2] = (int) htonl ((unsigned int) ef->ed->all[j].len);
550 sbuf[3] = (int) htonl ((unsigned int) ef->ed->all[j].prev);
551 sbuf[4] = (int) htonl ((unsigned int) ef->ed->all[j].next);
553 offset += ef->ed->all[j].len;
555 if (fwrite(sbuf, sizeof (sbuf), 1, fp) != 1)
560 /* write directories name */
561 for (i = 0; i < num; i++)
563 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
565 if (fwrite(efn->name, efn->name_size, 1, fp) != 1)
573 for (j = 0; j < ef->ed->count; ++j)
575 if (ef->ed->all[j].str)
577 if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, fp) != 1)
582 if (fwrite(ef->ed->all[j].mmap, ef->ed->all[j].len, 1, fp) != 1)
589 for (i = 0; i < num; i++)
591 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
593 if (fwrite(efn->data, efn->size, 1, fp) != 1)
598 /* flush all write to the file. */
600 // this is going to really cause trouble. if ANYTHING this needs to go into a
601 // thread spawned off - but even then...
602 // in this case... ext4 is "wrong". (yes we can jump up and down and point posix
603 // manual pages at eachother, but ext4 broke behavior that has been in place
604 // for decades and that 1000's of apps rely on daily - that is that one operation
605 // to disk is committed to disk BEFORE following operations, so the fs retains
606 // a consistent state
607 // fsync(fileno(fp));
609 /* append signature if required */
612 error = eet_identity_sign(fp, ef->key);
613 if (error != EET_ERROR_NONE)
617 /* no more writes pending */
618 ef->writes_pending = 0;
622 return EET_ERROR_NONE;
629 case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
630 case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
631 case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
632 case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
633 default: error = EET_ERROR_WRITE_ERROR; break;
644 if (++eet_init_count != 1)
645 return eet_init_count;
649 fprintf(stderr, "Eet: Eina init failed");
650 return --eet_init_count;
652 _eet_log_dom_global = eina_log_domain_register("Eet", EET_DEFAULT_LOG_COLOR);
653 if (_eet_log_dom_global < 0)
655 EINA_LOG_ERR("Eet Can not create a general log domain.");
659 if (!eet_node_init())
661 EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
662 goto unregister_log_domain;
666 /* Before the library can be used, it must initialize itself if needed. */
667 if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0)
669 gcry_check_version(NULL);
670 /* Disable warning messages about problems with the secure memory subsystem.
671 This command should be run right after gcry_check_version. */
672 if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN))
674 /* This command is used to allocate a pool of secure memory and thus
675 enabling the use of secure memory. It also drops all extra privileges the
676 process has (i.e. if it is run as setuid (root)). If the argument nbytes
677 is 0, secure memory will be disabled. The minimum amount of secure memory
678 allocated is currently 16384 bytes; you may thus use a value of 1 to
679 request that default size. */
680 if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
681 WRN("BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
683 if (gnutls_global_init())
687 ERR_load_crypto_strings();
688 OpenSSL_add_all_algorithms();
691 return eet_init_count;
695 unregister_log_domain:
696 eina_log_domain_unregister(_eet_log_dom_global);
697 _eet_log_dom_global = -1;
700 return --eet_init_count;
706 if (--eet_init_count != 0)
707 return eet_init_count;
712 gnutls_global_deinit();
718 eina_log_domain_unregister(_eet_log_dom_global);
719 _eet_log_dom_global = -1;
722 return eet_init_count;
726 eet_sync(Eet_File *ef)
730 if (eet_check_pointer(ef))
731 return EET_ERROR_BAD_OBJECT;
733 if ((ef->mode != EET_FILE_MODE_WRITE) &&
734 (ef->mode != EET_FILE_MODE_READ_WRITE))
735 return EET_ERROR_NOT_WRITABLE;
737 if (!ef->writes_pending)
738 return EET_ERROR_NONE;
742 ret = eet_flush2(ef);
755 * We need to compute the list of eet file to close separately from the cache,
756 * due to eet_close removing them from the cache after each call.
759 for (i = 0; i < eet_writers_num; i++)
761 if (eet_writers[i]->references <= 0) num++;
764 for (i = 0; i < eet_readers_num; i++)
766 if (eet_readers[i]->references <= 0) num++;
771 Eet_File **closelist = NULL;
773 closelist = alloca(num * sizeof(Eet_File *));
775 for (i = 0; i < eet_writers_num; i++)
777 if (eet_writers[i]->references <= 0)
779 closelist[num] = eet_writers[i];
780 eet_writers[i]->delete_me_now = 1;
785 for (i = 0; i < eet_readers_num; i++)
787 if (eet_readers[i]->references <= 0)
789 closelist[num] = eet_readers[i];
790 eet_readers[i]->delete_me_now = 1;
795 for (i = 0; i < num; i++)
797 eet_internal_close(closelist[i], EINA_TRUE);
803 /* FIXME: MMAP race condition in READ_WRITE_MODE */
805 eet_internal_read2(Eet_File *ef)
807 const int *data = (const int*) ef->data;
808 const char *start = (const char*) ef->data;
810 int num_directory_entries;
811 int bytes_directory_entries;
812 int num_dictionary_entries;
813 int bytes_dictionary_entries;
814 int signature_base_offset;
818 if (eet_test_close((int) ntohl(*data) != EET_MAGIC_FILE2, ef))
822 #define GET_INT(Value, Pointer, Index) \
824 Value = ntohl(*Pointer); \
826 Index += sizeof(int); \
829 /* get entries count and byte count */
830 GET_INT(num_directory_entries, data, idx);
831 /* get dictionary count and byte count */
832 GET_INT(num_dictionary_entries, data, idx);
834 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
835 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
837 /* we cant have <= 0 values here - invalid */
838 if (eet_test_close((num_directory_entries <= 0), ef))
841 /* we cant have more bytes directory and bytes in dictionaries than the size of the file */
842 if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > ef->data_size, ef))
845 /* allocate header */
846 ef->header = calloc(1, sizeof(Eet_File_Header));
847 if (eet_test_close(!ef->header, ef))
850 ef->header->magic = EET_MAGIC_FILE_HEADER;
852 /* allocate directory block in ram */
853 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
854 if (eet_test_close(!ef->header->directory, ef))
857 /* 8 bit hash table (256 buckets) */
858 ef->header->directory->size = 8;
859 /* allocate base hash table */
860 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
861 if (eet_test_close(!ef->header->directory->nodes, ef))
864 signature_base_offset = 0;
866 /* actually read the directory block - all of it, into ram */
867 for (i = 0; i < num_directory_entries; ++i)
876 /* out directory block is inconsistent - we have oveerun our */
877 /* dynamic block buffer before we finished scanning dir entries */
878 efn = malloc (sizeof(Eet_File_Node));
879 if (eet_test_close(!efn, ef))
882 /* get entrie header */
883 GET_INT(efn->offset, data, idx);
884 GET_INT(efn->size, data, idx);
885 GET_INT(efn->data_size, data, idx);
886 GET_INT(name_offset, data, idx);
887 GET_INT(name_size, data, idx);
888 GET_INT(flag, data, idx);
890 efn->compression = flag & 0x1 ? 1 : 0;
891 efn->ciphered = flag & 0x2 ? 1 : 0;
893 #define EFN_TEST(Test, Ef, Efn) \
894 if (eet_test_close(Test, Ef)) \
900 /* check data pointer position */
901 EFN_TEST(!((efn->size > 0)
902 && (efn->offset + efn->size <= ef->data_size)
903 && (efn->offset > bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
905 /* check name position */
906 EFN_TEST(!((name_size > 0)
907 && (name_offset + name_size < ef->data_size)
908 && (name_offset >= bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
910 name = start + name_offset;
912 /* check '\0' at the end of name string */
913 EFN_TEST(name[name_size - 1] != '\0', ef, efn);
916 efn->name = (char*) name;
917 efn->name_size = name_size;
919 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
920 efn->next = ef->header->directory->nodes[hash];
921 ef->header->directory->nodes[hash] = efn;
923 /* read-only mode, so currently we have no data loaded */
924 if (ef->mode == EET_FILE_MODE_READ)
926 /* read-write mode - read everything into ram */
929 efn->data = malloc(efn->size);
931 memcpy(efn->data, ef->data + efn->offset, efn->size);
934 /* compute the possible position of a signature */
935 if (signature_base_offset < efn->offset + efn->size)
936 signature_base_offset = efn->offset + efn->size;
941 if (num_dictionary_entries)
943 const int *dico = (const int*) ef->data + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + EET_FILE2_HEADER_COUNT;
946 if (eet_test_close((num_dictionary_entries * (int) EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) > (bytes_dictionary_entries + bytes_directory_entries), ef))
949 ef->ed = calloc(1, sizeof (Eet_Dictionary));
950 if (eet_test_close(!ef->ed, ef)) return NULL;
952 ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String));
953 if (eet_test_close(!ef->ed->all, ef)) return NULL;
955 ef->ed->count = num_dictionary_entries;
956 ef->ed->total = num_dictionary_entries;
957 ef->ed->start = start + bytes_dictionary_entries + bytes_directory_entries;
958 ef->ed->end = ef->ed->start;
960 for (j = 0; j < ef->ed->count; ++j)
965 GET_INT(hash, dico, idx);
966 GET_INT(offset, dico, idx);
967 GET_INT(ef->ed->all[j].len, dico, idx);
968 GET_INT(ef->ed->all[j].prev, dico, idx);
969 GET_INT(ef->ed->all[j].next, dico, idx);
971 /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
972 So stick to int and check the value. */
973 if (eet_test_close(hash & 0xFFFFFF00, ef)) return NULL;
975 /* Check string position */
976 if (eet_test_close(!((ef->ed->all[j].len > 0)
977 && (offset > (bytes_dictionary_entries + bytes_directory_entries))
978 && (offset + ef->ed->all[j].len < ef->data_size)), ef))
981 ef->ed->all[j].mmap = start + offset;
982 ef->ed->all[j].str = NULL;
984 if (ef->ed->all[j].mmap + ef->ed->all[j].len > ef->ed->end)
985 ef->ed->end = ef->ed->all[j].mmap + ef->ed->all[j].len;
987 /* Check '\0' at the end of the string */
988 if (eet_test_close(ef->ed->all[j].mmap[ef->ed->all[j].len - 1] != '\0', ef)) return NULL;
990 ef->ed->all[j].hash = hash;
991 if (ef->ed->all[j].prev == -1)
992 ef->ed->hash[hash] = j;
994 /* compute the possible position of a signature */
995 if (signature_base_offset < offset + ef->ed->all[j].len)
996 signature_base_offset = offset + ef->ed->all[j].len;
1000 /* Check if the file is signed */
1001 ef->x509_der = NULL;
1002 ef->x509_length = 0;
1003 ef->signature = NULL;
1004 ef->signature_length = 0;
1006 if (signature_base_offset < ef->data_size)
1008 #ifdef HAVE_SIGNATURE
1009 const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset;
1010 ef->x509_der = eet_identity_check(ef->data, signature_base_offset,
1011 &ef->sha1, &ef->sha1_length,
1012 buffer, ef->data_size - signature_base_offset,
1013 &ef->signature, &ef->signature_length,
1016 if (eet_test_close(ef->x509_der == NULL, ef)) return NULL;
1018 ERR("This file could be signed but you didn't compile the necessary code to check the signature.");
1025 #if EET_OLD_EET_FILE_FORMAT
1027 eet_internal_read1(Eet_File *ef)
1029 const unsigned char *dyn_buf = NULL;
1030 const unsigned char *p = NULL;
1036 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);
1038 /* build header table if read mode */
1041 if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
1044 #define EXTRACT_INT(Value, Pointer, Index) \
1047 memcpy(&tmp, Pointer + Index, sizeof(int)); \
1048 Value = ntohl(tmp); \
1049 Index += sizeof(int); \
1052 /* get entries count and byte count */
1053 EXTRACT_INT(num_entries, ef->data, idx);
1054 EXTRACT_INT(byte_entries, ef->data, idx);
1056 /* we cant have <= 0 values here - invalid */
1057 if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef))
1060 /* we can't have more entires than minimum bytes for those! invalid! */
1061 if (eet_test_close((num_entries * 20) > byte_entries, ef))
1064 /* check we will not outrun the file limit */
1065 if (eet_test_close(((byte_entries + (int) sizeof(int) * 3) > ef->data_size), ef))
1068 /* allocate header */
1069 ef->header = calloc(1, sizeof(Eet_File_Header));
1070 if (eet_test_close(!ef->header, ef))
1073 ef->header->magic = EET_MAGIC_FILE_HEADER;
1075 /* allocate directory block in ram */
1076 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1077 if (eet_test_close(!ef->header->directory, ef))
1080 /* 8 bit hash table (256 buckets) */
1081 ef->header->directory->size = 8;
1082 /* allocate base hash table */
1083 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1084 if (eet_test_close(!ef->header->directory->nodes, ef))
1087 /* actually read the directory block - all of it, into ram */
1088 dyn_buf = ef->data + idx;
1090 /* parse directory block */
1093 for (i = 0; i < num_entries; i++)
1102 #define HEADER_SIZE (sizeof(int) * 5)
1104 /* out directory block is inconsistent - we have oveerun our */
1105 /* dynamic block buffer before we finished scanning dir entries */
1106 if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
1109 /* allocate all the ram needed for this stored node accounting */
1110 efn = malloc (sizeof(Eet_File_Node));
1111 if (eet_test_close(!efn, ef))
1114 /* get entrie header */
1115 EXTRACT_INT(efn->offset, p, indexn);
1116 EXTRACT_INT(efn->compression, p, indexn);
1117 EXTRACT_INT(efn->size, p, indexn);
1118 EXTRACT_INT(efn->data_size, p, indexn);
1119 EXTRACT_INT(name_size, p, indexn);
1121 efn->name_size = name_size;
1125 if (eet_test_close(efn->size <= 0, ef))
1131 /* invalid name_size */
1132 if (eet_test_close(name_size <= 0, ef))
1138 /* reading name would mean falling off end of dyn_buf - invalid */
1139 if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
1145 /* This code is useless if we dont want backward compatibility */
1146 for (k = name_size; k > 0 && ((unsigned char) * (p + HEADER_SIZE + k)) != 0; --k)
1149 efn->free_name = ((unsigned char) * (p + HEADER_SIZE + k)) != 0;
1153 efn->name = malloc(sizeof(char) * name_size + 1);
1154 if (eet_test_close(efn->name == NULL, ef))
1160 strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
1161 efn->name[name_size] = 0;
1163 WRN("File: %s is not up to date for key \"%s\" - needs rebuilding sometime", ef->path, efn->name);
1166 /* The only really usefull peace of code for efn->name (no backward compatibility) */
1167 efn->name = (char*)((unsigned char*)(p + HEADER_SIZE));
1169 /* get hash bucket it should go in */
1170 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1171 efn->next = ef->header->directory->nodes[hash];
1172 ef->header->directory->nodes[hash] = efn;
1174 /* read-only mode, so currently we have no data loaded */
1175 if (ef->mode == EET_FILE_MODE_READ)
1177 /* read-write mode - read everything into ram */
1180 data = malloc(efn->size);
1182 memcpy(data, ef->data + efn->offset, efn->size);
1186 p += HEADER_SIZE + name_size;
1193 * this should only be called when the cache lock is already held
1194 * (We could drop this restriction if we add a parameter to eet_test_close
1195 * that indicates if the lock is held or not. For now it is easiest
1196 * to just require that it is always held.)
1199 eet_internal_read(Eet_File *ef)
1201 const int *data = (const int*) ef->data;
1203 if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef))
1206 if (eet_test_close(ef->data_size < (int) sizeof(int) * 3, ef))
1209 switch (ntohl(*data))
1211 #if EET_OLD_EET_FILE_FORMAT
1212 case EET_MAGIC_FILE:
1213 return eet_internal_read1(ef);
1215 case EET_MAGIC_FILE2:
1216 return eet_internal_read2(ef);
1218 ef->delete_me_now = 1;
1219 eet_internal_close(ef, EINA_TRUE);
1227 eet_internal_close(Eet_File *ef, Eina_Bool locked)
1231 /* check to see its' an eet file pointer */
1232 if (eet_check_pointer(ef))
1233 return EET_ERROR_BAD_OBJECT;
1235 if (!locked) LOCK_CACHE;
1239 /* if its still referenced - dont go any further */
1240 if (ef->references > 0) goto on_error;
1241 /* flush any writes */
1242 err = eet_flush2(ef);
1244 eet_identity_unref(ef->key);
1247 /* if not urgent to delete it - dont free it - leave it in cache */
1248 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
1251 /* remove from cache */
1252 if (ef->mode == EET_FILE_MODE_READ)
1253 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1254 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1255 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1257 /* we can unlock the cache now */
1258 if (!locked) UNLOCK_CACHE;
1265 if (ef->header->directory)
1267 if (ef->header->directory->nodes)
1271 num = (1 << ef->header->directory->size);
1272 for (i = 0; i < num; i++)
1276 while ((efn = ef->header->directory->nodes[i]))
1281 ef->header->directory->nodes[i] = efn->next;
1289 free(ef->header->directory->nodes);
1291 free(ef->header->directory);
1296 eet_dictionary_free(ef->ed);
1298 if (ef->sha1) free(ef->sha1);
1299 if (ef->data) munmap((void*)ef->data, ef->data_size);
1300 if (ef->readfp) fclose(ef->readfp);
1302 /* zero out ram for struct - caution tactic against stale memory use */
1303 memset(ef, 0, sizeof(Eet_File));
1310 if (!locked) UNLOCK_CACHE;
1311 return EET_ERROR_NONE;
1315 eet_memopen_read(const void *data, size_t size)
1319 if (data == NULL || size == 0)
1322 ef = malloc (sizeof (Eet_File));
1330 ef->magic = EET_MAGIC_FILE;
1332 ef->mode = EET_FILE_MODE_READ;
1335 ef->delete_me_now = 1;
1338 ef->data_size = size;
1340 ef->sha1_length = 0;
1342 /* eet_internal_read expects the cache lock to be held when it is called */
1344 ef = eet_internal_read(ef);
1350 eet_open(const char *file, Eet_File_Mode mode)
1355 struct stat file_stat;
1360 /* find the current file handle in cache*/
1363 if (mode == EET_FILE_MODE_READ)
1365 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1370 ef->delete_me_now = 1;
1371 eet_internal_close(ef, EINA_TRUE);
1373 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1375 else if ((mode == EET_FILE_MODE_WRITE) ||
1376 (mode == EET_FILE_MODE_READ_WRITE))
1378 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1381 ef->delete_me_now = 1;
1383 eet_internal_close(ef, EINA_TRUE);
1385 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1388 /* try open the file based on mode */
1389 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1391 /* Prevent garbage in futur comparison. */
1392 file_stat.st_mtime = 0;
1394 fp = fopen(file, "rb");
1395 if (!fp) goto open_error;
1396 if (fstat(fileno(fp), &file_stat))
1402 if ((mode == EET_FILE_MODE_READ) &&
1403 (file_stat.st_size < ((int) sizeof(int) * 3)))
1411 if (fp == NULL && mode == EET_FILE_MODE_READ) goto on_error;
1415 if (mode != EET_FILE_MODE_WRITE) return NULL;
1416 memset(&file_stat, 0, sizeof(file_stat));
1422 if (ef && (file_stat.st_mtime != ef->mtime))
1424 ef->delete_me_now = 1;
1426 eet_internal_close(ef, EINA_TRUE);
1432 /* reference it up and return it */
1433 if (fp != NULL) fclose(fp);
1439 file_len = strlen(file) + 1;
1441 /* Allocate struct for eet file and have it zero'd out */
1442 ef = malloc(sizeof(Eet_File) + file_len);
1446 /* fill some of the members */
1450 ef->path = ((char *)ef) + sizeof(Eet_File);
1451 memcpy(ef->path, file, file_len);
1452 ef->magic = EET_MAGIC_FILE;
1456 ef->mtime = file_stat.st_mtime;
1457 ef->writes_pending = 0;
1458 ef->delete_me_now = 0;
1462 ef->sha1_length = 0;
1464 ef->ed = (mode == EET_FILE_MODE_WRITE)
1465 || (ef->readfp == NULL && mode == EET_FILE_MODE_READ_WRITE) ?
1466 eet_dictionary_add() : NULL;
1468 if (ef->readfp == NULL &&
1469 (mode == EET_FILE_MODE_READ_WRITE || mode == EET_FILE_MODE_WRITE))
1472 /* if we can't open - bail out */
1473 if (eet_test_close(!ef->readfp, ef))
1476 fcntl(fileno(ef->readfp), F_SETFD, FD_CLOEXEC);
1477 /* if we opened for read or read-write */
1478 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1480 ef->data_size = file_stat.st_size;
1481 ef->data = mmap(NULL, ef->data_size, PROT_READ,
1482 MAP_SHARED, fileno(ef->readfp), 0);
1483 if (eet_test_close((ef->data == MAP_FAILED), ef))
1485 ef = eet_internal_read(ef);
1492 if (ef->references == 1)
1494 if (ef->mode == EET_FILE_MODE_READ)
1495 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1497 if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1498 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1510 eet_mode_get(Eet_File *ef)
1512 /* check to see its' an eet file pointer */
1513 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
1514 return EET_FILE_MODE_INVALID;
1520 eet_identity_x509(Eet_File *ef, int *der_length)
1522 if (!ef->x509_der) return NULL;
1524 if (der_length) *der_length = ef->x509_length;
1525 return ef->x509_der;
1529 eet_identity_signature(Eet_File *ef, int *signature_length)
1531 if (!ef->signature) return NULL;
1533 if (signature_length) *signature_length = ef->signature_length;
1534 return ef->signature;
1538 eet_identity_sha1(Eet_File *ef, int *sha1_length)
1541 ef->sha1 = eet_identity_compute_sha1(ef->data, ef->data_size, &ef->sha1_length);
1543 if (sha1_length) *sha1_length = ef->sha1_length;
1548 eet_identity_set(Eet_File *ef, Eet_Key *key)
1550 Eet_Key *tmp = ef->key;
1552 if (!ef) return EET_ERROR_BAD_OBJECT;
1555 eet_identity_ref(ef->key);
1556 eet_identity_unref(tmp);
1558 /* flags that writes are pending */
1559 ef->writes_pending = 1;
1561 return EET_ERROR_NONE;
1565 eet_close(Eet_File *ef)
1567 return eet_internal_close(ef, EINA_FALSE);
1571 eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *cipher_key)
1580 /* check to see its' an eet file pointer */
1581 if (eet_check_pointer(ef))
1585 if ((ef->mode != EET_FILE_MODE_READ) &&
1586 (ef->mode != EET_FILE_MODE_READ_WRITE))
1589 /* no header, return NULL */
1590 if (eet_check_header(ef))
1595 /* hunt hash bucket */
1596 efn = find_node_by_name(ef, name);
1597 if (!efn) goto on_error;
1599 /* get size (uncompressed, if compressed at all) */
1600 size = efn->data_size;
1603 data = malloc(size);
1604 if (!data) goto on_error;
1606 /* uncompressed data */
1607 if (efn->compression == 0)
1609 void *data_deciphered = NULL;
1610 unsigned int data_deciphered_sz = 0;
1611 /* if we alreayd have the data in ram... copy that */
1613 memcpy(data, efn->data, efn->size);
1615 if (!read_data_from_disk(ef, efn, data, size))
1617 if (efn->ciphered && cipher_key)
1619 if (eet_decipher(data, size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1621 if (data_deciphered) free(data_deciphered);
1625 data = data_deciphered;
1626 size = data_deciphered_sz;
1629 /* compressed data */
1633 void *data_deciphered = NULL;
1634 unsigned int data_deciphered_sz = 0;
1636 int compr_size = efn->size;
1639 /* if we already have the data in ram... copy that */
1641 tmp_data = efn->data;
1644 tmp_data = malloc(compr_size);
1650 if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
1657 if (efn->ciphered && cipher_key)
1659 if (eet_decipher(tmp_data, compr_size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1661 if (free_tmp) free(tmp_data);
1662 if (data_deciphered) free(data_deciphered);
1666 tmp_data = data_deciphered;
1667 compr_size = data_deciphered_sz;
1672 if (uncompress((Bytef *)data, &dlen,
1673 tmp_data, (uLongf)compr_size))
1680 /* fill in return values */
1695 eet_read(Eet_File *ef, const char *name, int *size_ret)
1697 return eet_read_cipher(ef, name, size_ret, NULL);
1701 eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
1703 const void *data = NULL;
1710 /* check to see its' an eet file pointer */
1711 if (eet_check_pointer(ef))
1715 if ((ef->mode != EET_FILE_MODE_READ) &&
1716 (ef->mode != EET_FILE_MODE_READ_WRITE))
1719 /* no header, return NULL */
1720 if (eet_check_header(ef))
1725 /* hunt hash bucket */
1726 efn = find_node_by_name(ef, name);
1727 if (!efn) goto on_error;
1729 if (efn->offset < 0 && efn->data == NULL)
1732 /* get size (uncompressed, if compressed at all) */
1733 size = efn->data_size;
1735 /* uncompressed data */
1736 if (efn->compression == 0
1737 && efn->ciphered == 0)
1738 data = efn->data ? efn->data : ef->data + efn->offset;
1739 /* compressed data */
1743 /* fill in return values */
1757 eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int comp, const char *cipher_key)
1761 int exists_already = 0;
1765 /* check to see its' an eet file pointer */
1766 if (eet_check_pointer(ef))
1768 if ((!name) || (!data) || (size <= 0))
1770 if ((ef->mode != EET_FILE_MODE_WRITE) &&
1771 (ef->mode != EET_FILE_MODE_READ_WRITE))
1778 /* allocate header */
1779 ef->header = calloc(1, sizeof(Eet_File_Header));
1783 ef->header->magic = EET_MAGIC_FILE_HEADER;
1784 /* allocate directory block in ram */
1785 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1786 if (!ef->header->directory)
1793 /* 8 bit hash table (256 buckets) */
1794 ef->header->directory->size = 8;
1795 /* allocate base hash table */
1796 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1797 if (!ef->header->directory->nodes)
1799 free(ef->header->directory);
1805 /* figure hash bucket */
1806 hash = _eet_hash_gen(name, ef->header->directory->size);
1808 data_size = comp ? 12 + ((size * 101) / 100) : size;
1810 if (comp || !cipher_key)
1812 data2 = malloc(data_size);
1813 if (!data2) goto on_error;
1816 /* if we want to compress */
1821 /* compress the data with max compression */
1822 buflen = (uLongf)data_size;
1823 if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
1824 (uLong)size, Z_BEST_COMPRESSION) != Z_OK)
1829 /* record compressed chunk size */
1830 data_size = (int)buflen;
1831 if (data_size < 0 || data_size >= size)
1840 data3 = realloc(data2, data_size);
1848 void *data_ciphered = NULL;
1849 unsigned int data_ciphered_sz = 0;
1852 tmp = data2 ? data2 : data;
1853 if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), &data_ciphered, &data_ciphered_sz))
1855 if (data2) free(data2);
1856 data2 = data_ciphered;
1857 data_size = data_ciphered_sz;
1858 size = (data_size > size) ? data_size : size;
1862 if (data_ciphered) free(data_ciphered);
1868 memcpy(data2, data, size);
1870 /* Does this node already exist? */
1871 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
1874 if ((efn->name) && (eet_string_match(efn->name, name)))
1877 efn->ciphered = cipher_key ? 1 : 0;
1878 efn->compression = !!comp;
1879 efn->size = data_size;
1880 efn->data_size = size;
1887 if (!exists_already)
1889 efn = malloc(sizeof(Eet_File_Node));
1895 efn->name = strdup(name);
1896 efn->name_size = strlen(efn->name) + 1;
1899 efn->next = ef->header->directory->nodes[hash];
1900 ef->header->directory->nodes[hash] = efn;
1902 efn->ciphered = cipher_key ? 1 : 0;
1903 efn->compression = !!comp;
1904 efn->size = data_size;
1905 efn->data_size = size;
1909 /* flags that writes are pending */
1910 ef->writes_pending = 1;
1920 eet_write(Eet_File *ef, const char *name, const void *data, int size, int comp)
1922 return eet_write_cipher(ef, name, data, size, comp, NULL);
1926 eet_delete(Eet_File *ef, const char *name)
1929 Eet_File_Node *pefn;
1931 int exists_already = 0;
1933 /* check to see its' an eet file pointer */
1934 if (eet_check_pointer(ef))
1939 /* deleting keys is only possible in RW or WRITE mode */
1940 if (ef->mode == EET_FILE_MODE_READ)
1943 if (eet_check_header(ef))
1948 /* figure hash bucket */
1949 hash = _eet_hash_gen(name, ef->header->directory->size);
1951 /* Does this node already exist? */
1952 for (pefn = NULL, efn = ef->header->directory->nodes[hash];
1954 pefn = efn, efn = efn->next)
1957 if (eet_string_match(efn->name, name))
1963 ef->header->directory->nodes[hash] = efn->next;
1965 pefn->next = efn->next;
1967 if (efn->free_name) free(efn->name);
1973 /* flags that writes are pending */
1975 ef->writes_pending = 1;
1979 /* update access time */
1980 return exists_already;
1983 EAPI Eet_Dictionary *
1984 eet_dictionary_get(Eet_File *ef)
1986 if (eet_check_pointer(ef)) return NULL;
1993 eet_list(Eet_File *ef, const char *glob, int *count_ret)
1996 char **list_ret = NULL;
1998 int list_count_alloc = 0;
2001 /* check to see its' an eet file pointer */
2002 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2004 ((ef->mode != EET_FILE_MODE_READ) &&
2005 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2013 if (!strcmp(glob, "*")) glob = NULL;
2017 /* loop through all entries */
2018 num = (1 << ef->header->directory->size);
2019 for (i = 0; i < num; i++)
2021 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2023 /* if the entry matches the input glob
2024 * check for * explicitly, because on some systems, * isn't well
2027 if ((!glob) || !fnmatch(glob, efn->name, 0))
2029 /* add it to our list */
2032 /* only realloc in 32 entry chunks */
2033 if (list_count > list_count_alloc)
2035 char **new_list = NULL;
2037 list_count_alloc += 64;
2038 new_list = realloc(list_ret, list_count_alloc * (sizeof(char *)));
2045 list_ret = new_list;
2048 /* put pointer of name string in */
2049 list_ret[list_count - 1] = efn->name;
2056 /* return count and list */
2058 *count_ret = list_count;
2072 eet_num_entries(Eet_File *ef)
2074 int i, num, ret = 0;
2077 /* check to see its' an eet file pointer */
2078 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2079 ((ef->mode != EET_FILE_MODE_READ) &&
2080 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2085 /* loop through all entries */
2086 num = (1 << ef->header->directory->size);
2087 for (i = 0; i < num; i++)
2089 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2098 static Eet_File_Node *
2099 find_node_by_name(Eet_File *ef, const char *name)
2104 /* get hash bucket this should be in */
2105 hash = _eet_hash_gen(name, ef->header->directory->size);
2107 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2109 if (eet_string_match(efn->name, name))
2117 read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len)
2119 if (efn->offset < 0) return 0;
2123 if ((efn->offset + len) > ef->data_size) return 0;
2124 memcpy(buf, ef->data + efn->offset, len);
2131 /* seek to data location */
2132 if (fseek(ef->readfp, efn->offset, SEEK_SET) < 0)
2136 len = fread(buf, len, 1, ef->readfp);