2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
9 #if defined(_WIN32) && ! defined(__CEGCC__)
10 # include <winsock2.h>
15 #elif defined __GNUC__
16 # define alloca __builtin_alloca
18 # define alloca __alloca
19 #elif defined _MSC_VER
21 # define alloca _alloca
27 void *alloca (size_t);
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;
90 Eet_File_Header *header;
93 const unsigned char *data;
95 const void *signature;
105 unsigned int signature_length;
110 #ifdef EFL_HAVE_PTHREAD
111 pthread_mutex_t file_lock;
114 unsigned char writes_pending : 1;
115 unsigned char delete_me_now : 1;
118 struct _Eet_File_Header
121 Eet_File_Directory *directory;
124 struct _Eet_File_Directory
127 Eet_File_Node **nodes;
130 struct _Eet_File_Node
134 Eet_File_Node *next; /* FIXME: make buckets linked lists */
137 int dictionary_offset;
144 unsigned char free_name : 1;
145 unsigned char compression : 1;
146 unsigned char ciphered : 1;
151 /* NB: all int's are stored in network byte order on disk */
153 int magic; /* magic number ie 0x1ee7ff00 */
154 int num_directory_entries; /* number of directory entries to follow */
155 int bytes_directory_entries; /* bytes of directory entries to follow */
158 int offset; /* bytes offset into file for data chunk */
159 int flags; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */
160 int size; /* size of the data chunk */
161 int data_size; /* size of the (uncompressed) data chunk */
162 int name_size; /* length in bytes of the name field */
163 char name[name_size]; /* name string (variable length) and \0 terminated */
164 } directory[num_directory_entries];
165 /* and now startes the data stream... */
170 /* NB: all int's are stored in network byte order on disk */
172 int magic; /* magic number ie 0x1ee70f42 */
173 int num_directory_entries; /* number of directory entries to follow */
174 int num_dictionary_entries; /* number of dictionary entries to follow */
177 int data_offset; /* bytes offset into file for data chunk */
178 int size; /* size of the data chunk */
179 int data_size; /* size of the (uncompressed) data chunk */
180 int name_offset; /* bytes offset into file for name string */
181 int name_size; /* length in bytes of the name field */
182 int flags; /* flags - for now 0 = uncompressed, 1 = compressed */
183 } directory[num_directory_entries];
191 } dictionary[num_dictionary_entries];
192 /* now start the string stream. */
193 /* and right after them the data stream. */
194 int magic_sign; /* Optional, only if the eet file is signed. */
195 int signature_length; /* Signature length. */
196 int x509_length; /* Public certificate that signed the file. */
197 char signature[signature_length]; /* The signature. */
198 char x509[x509_length]; /* The public certificate. */
201 #define EET_FILE2_HEADER_COUNT 3
202 #define EET_FILE2_DIRECTORY_ENTRY_COUNT 6
203 #define EET_FILE2_DICTIONARY_ENTRY_COUNT 5
205 #define EET_FILE2_HEADER_SIZE (sizeof(int) * EET_FILE2_HEADER_COUNT)
206 #define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DIRECTORY_ENTRY_COUNT)
207 #define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DICTIONARY_ENTRY_COUNT)
209 /* prototypes of internal calls */
210 static Eet_File *eet_cache_find(const char *path, Eet_File **cache, int cache_num);
211 static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
212 static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
213 static int eet_string_match(const char *s1, const char *s2);
215 static Eet_Error eet_flush(Eet_File *ef);
217 static Eet_Error eet_flush2(Eet_File *ef);
218 static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name);
219 static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
221 static Eet_Error eet_internal_close(Eet_File *ef, Eina_Bool locked);
223 #ifdef EFL_HAVE_PTHREAD
224 static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER;
226 #define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock);
227 #define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock);
229 #define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL);
230 #define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock);
231 #define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock);
232 #define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock);
237 #define UNLOCK_CACHE ;
239 #define INIT_FILE(File) ;
240 #define LOCK_FILE(File) ;
241 #define UNLOCK_FILE(File) ;
242 #define DESTROY_FILE(File) ;
246 /* cache. i don't expect this to ever be large, so arrays will do */
247 static int eet_writers_num = 0;
248 static int eet_writers_alloc = 0;
249 static Eet_File **eet_writers = NULL;
250 static int eet_readers_num = 0;
251 static int eet_readers_alloc = 0;
252 static Eet_File **eet_readers = NULL;
253 static int eet_init_count = 0;
255 /* log domain variable */
256 int _eet_log_dom_global = -1;
258 /* Check to see its' an eet file pointer */
260 eet_check_pointer(const Eet_File *ef)
262 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
268 eet_check_header(const Eet_File *ef)
272 if (!ef->header->directory)
278 eet_test_close(int test, Eet_File *ef)
282 ef->delete_me_now = 1;
283 eet_internal_close(ef, 0);
288 /* find an eet file in the currently in use cache */
290 eet_cache_find(const char *path, Eet_File **cache, int cache_num)
295 for (i = 0; i < cache_num; i++)
297 /* if matches real path - return it */
298 if (eet_string_match(cache[i]->path, path))
300 if (!cache[i]->delete_me_now)
309 /* add to end of cache */
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(ef, 1);
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 */
362 eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
364 Eet_File **new_cache;
365 int new_cache_num, new_cache_alloc;
369 new_cache_num = *cache_num;
370 new_cache_alloc = *cache_alloc;
371 if (new_cache_num <= 0)
374 for (i = 0; i < new_cache_num; i++)
376 if (new_cache[i] == ef)
380 if (i >= new_cache_num)
384 for (j = i; j < new_cache_num; j++)
385 new_cache[j] = new_cache[j + 1];
387 if (new_cache_num <= (new_cache_alloc - 16))
389 new_cache_alloc -= 16;
390 if (new_cache_num > 0)
392 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
395 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
406 *cache_num = new_cache_num;
407 *cache_alloc = new_cache_alloc;
410 /* internal string match. null friendly, catches same ptr */
412 eet_string_match(const char *s1, const char *s2)
414 /* both null- no match */
415 if ((!s1) || (!s2)) return 0;
416 if (s1 == s2) return 1;
417 return (!strcmp(s1, s2));
420 /* flush out writes to a v2 eet file */
422 eet_flush2(Eet_File *ef)
425 Eet_Error error = EET_ERROR_NONE;
426 int head[EET_FILE2_HEADER_COUNT];
427 int num_directory_entries = 0;
428 int num_dictionary_entries = 0;
429 int bytes_directory_entries = 0;
430 int bytes_dictionary_entries = 0;
431 int bytes_strings = 0;
433 int strings_offset = 0;
438 if (eet_check_pointer(ef))
439 return EET_ERROR_BAD_OBJECT;
440 if (eet_check_header(ef))
441 return EET_ERROR_EMPTY;
442 if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
443 return EET_ERROR_NOT_WRITABLE;
444 if (!ef->writes_pending)
445 return EET_ERROR_NONE;
446 if (ef->mode == EET_FILE_MODE_READ_WRITE && ef->fp == NULL)
451 fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
452 ef->fp = fdopen(fd, "wb");
453 if (!ef->fp) return EET_ERROR_NOT_WRITABLE;
454 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
457 /* calculate string base offset and data base offset */
458 num = (1 << ef->header->directory->size);
459 for (i = 0; i < num; ++i)
461 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
463 num_directory_entries++;
464 bytes_strings += strlen(efn->name) + 1;
469 num_dictionary_entries = ef->ed->count;
471 for (i = 0; i < num_dictionary_entries; ++i)
472 bytes_strings += ef->ed->all[i].len;
475 /* calculate section bytes size */
476 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
477 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
479 /* calculate per entry offset */
480 strings_offset = bytes_directory_entries + bytes_dictionary_entries;
481 data_offset = bytes_directory_entries + bytes_dictionary_entries + bytes_strings;
483 for (i = 0; i < num; ++i)
485 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
487 efn->offset = data_offset;
488 data_offset += efn->size;
490 efn->name_offset = strings_offset;
491 strings_offset += efn->name_size;
495 /* calculate dictionary strings offset */
497 ef->ed->offset = strings_offset;
499 /* go thru and write the header */
500 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE2);
501 head[1] = (int) htonl ((unsigned int) num_directory_entries);
502 head[2] = (int) htonl ((unsigned int) num_dictionary_entries);
504 fseek(ef->fp, 0, SEEK_SET);
505 if (fwrite(head, sizeof (head), 1, ef->fp) != 1)
508 /* write directories entry */
509 for (i = 0; i < num; i++)
511 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
514 int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
516 flag = (efn->ciphered << 1) | efn->compression;
518 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
519 ibuf[1] = (int) htonl ((unsigned int) efn->size);
520 ibuf[2] = (int) htonl ((unsigned int) efn->data_size);
521 ibuf[3] = (int) htonl ((unsigned int) efn->name_offset);
522 ibuf[4] = (int) htonl ((unsigned int) efn->name_size);
523 ibuf[5] = (int) htonl ((unsigned int) flag);
525 if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
530 /* write dictionnary */
533 int offset = strings_offset;
535 for (j = 0; j < ef->ed->count; ++j)
537 int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
539 sbuf[0] = (int) htonl ((unsigned int) ef->ed->all[j].hash);
540 sbuf[1] = (int) htonl ((unsigned int) offset);
541 sbuf[2] = (int) htonl ((unsigned int) ef->ed->all[j].len);
542 sbuf[3] = (int) htonl ((unsigned int) ef->ed->all[j].prev);
543 sbuf[4] = (int) htonl ((unsigned int) ef->ed->all[j].next);
545 offset += ef->ed->all[j].len;
547 if (fwrite(sbuf, sizeof (sbuf), 1, ef->fp) != 1)
552 /* write directories name */
553 for (i = 0; i < num; i++)
555 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
557 if (fwrite(efn->name, efn->name_size, 1, ef->fp) != 1)
565 for (j = 0; j < ef->ed->count; ++j)
567 if (ef->ed->all[j].str)
569 if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, ef->fp) != 1)
574 if (fwrite(ef->ed->all[j].mmap, ef->ed->all[j].len, 1, ef->fp) != 1)
581 for (i = 0; i < num; i++)
583 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
585 if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
590 /* flush all write to the file. */
592 // this is going to really cause trouble. if ANYTHING this needs to go into a
593 // thread spawned off - but even then...
594 // in this case... ext4 is "wrong". (yes we can jump up and down and point posix
595 // manual pages at eachother, but ext4 broke behavior that has been in place
596 // for decades and that 1000's of apps rely on daily - that is that one operation
597 // to disk is committed to disk BEFORE following operations, so the fs retains
598 // a consistent state
599 // fsync(fileno(ef->fp));
601 /* append signature if required */
604 error = eet_identity_sign(ef->fp, ef->key);
605 if (error != EET_ERROR_NONE)
609 /* no more writes pending */
610 ef->writes_pending = 0;
612 return EET_ERROR_NONE;
619 case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
620 case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
621 case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
622 case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
623 default: error = EET_ERROR_WRITE_ERROR; break;
627 if (ef->fp) fclose(ef->fp);
633 /* flush out writes to an eet file */
635 eet_flush(Eet_File *ef)
645 /* check to see its' an eet file pointer */
646 if (eet_check_pointer(ef))
647 return EET_ERROR_BAD_OBJECT;
648 if (eet_check_header(ef))
649 return EET_ERROR_EMPTY;
650 if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
651 return EET_ERROR_NOT_WRITABLE;
652 if (!ef->writes_pending)
653 return EET_ERROR_NONE;
655 /* calculate total size in bytes of directory block */
656 num = (1 << ef->header->directory->size);
657 for (i = 0; i < num; i++)
659 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
661 size += 20 + strlen(efn->name) + 1;
666 /* calculate offsets per entry */
668 for (i = 0; i < num; i++)
670 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
672 efn->offset = 12 + size + offset;
677 /* go thru and write the header */
678 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE);
679 head[1] = (int) htonl ((unsigned int) count);
680 head[2] = (int) htonl ((unsigned int) size);
682 fseek(ef->fp, 0, SEEK_SET);
683 if (fwrite(head, 12, 1, ef->fp) != 1)
686 for (i = 0; i < num; i++)
688 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
690 unsigned int ibuf[5];
693 name_size = strlen(efn->name) + 1;
695 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
696 ibuf[1] = (int) htonl ((unsigned int) efn->compression);
697 ibuf[2] = (int) htonl ((unsigned int) efn->size);
698 ibuf[3] = (int) htonl ((unsigned int) efn->data_size);
699 ibuf[4] = (int) htonl ((unsigned int) name_size);
702 if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
704 if (fwrite(efn->name, name_size, 1, ef->fp) != 1)
710 for (i = 0; i < num; i++)
712 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
714 if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
719 /* no more writes pending */
720 ef->writes_pending = 0;
722 return EET_ERROR_NONE;
732 return EET_ERROR_WRITE_ERROR_FILE_TOO_BIG;
736 return EET_ERROR_WRITE_ERROR_IO_ERROR;
740 return EET_ERROR_WRITE_ERROR_OUT_OF_SPACE;
744 return EET_ERROR_WRITE_ERROR_FILE_CLOSED;
748 return EET_ERROR_WRITE_ERROR;
752 if (ef->fp) fclose(ef->fp);
754 return EET_ERROR_WRITE_ERROR;
761 if (++eet_init_count != 1)
762 return eet_init_count;
766 fprintf(stderr, "Eet: Eina init failed");
767 return --eet_init_count;
769 _eet_log_dom_global = eina_log_domain_register("Eet", EET_DEFAULT_LOG_COLOR);
770 if (_eet_log_dom_global < 0)
772 EINA_LOG_ERR("Eet Can not create a general log domain.");
776 if (!eet_node_init())
778 EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
779 goto unregister_log_domain;
783 /* Before the library can be used, it must initialize itself if needed. */
784 if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0)
786 gcry_check_version(NULL);
787 /* Disable warning messages about problems with the secure memory subsystem.
788 This command should be run right after gcry_check_version. */
789 if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN))
791 /* This command is used to allocate a pool of secure memory and thus
792 enabling the use of secure memory. It also drops all extra privileges the
793 process has (i.e. if it is run as setuid (root)). If the argument nbytes
794 is 0, secure memory will be disabled. The minimum amount of secure memory
795 allocated is currently 16384 bytes; you may thus use a value of 1 to
796 request that default size. */
797 if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
798 WRN("BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
800 if (gnutls_global_init())
804 ERR_load_crypto_strings();
805 OpenSSL_add_all_algorithms();
808 return eet_init_count;
812 unregister_log_domain:
813 eina_log_domain_unregister(_eet_log_dom_global);
814 _eet_log_dom_global = -1;
817 return --eet_init_count;
823 if (--eet_init_count != 0)
824 return eet_init_count;
829 gnutls_global_deinit();
835 eina_log_domain_unregister(_eet_log_dom_global);
836 _eet_log_dom_global = -1;
839 return eet_init_count;
849 * We need to compute the list of eet file to close separately from the cache,
850 * due to eet_close removing them from the cache after each call.
852 for (i = 0; i < eet_writers_num; i++)
854 if (eet_writers[i]->references <= 0) num++;
857 for (i = 0; i < eet_readers_num; i++)
859 if (eet_readers[i]->references <= 0) num++;
864 Eet_File **closelist = NULL;
866 closelist = alloca(num * sizeof(Eet_File *));
868 for (i = 0; i < eet_writers_num; i++)
870 if (eet_writers[i]->references <= 0)
872 closelist[num] = eet_writers[i];
873 eet_writers[i]->delete_me_now = 1;
878 for (i = 0; i < eet_readers_num; i++)
880 if (eet_readers[i]->references <= 0)
882 closelist[num] = eet_readers[i];
883 eet_readers[i]->delete_me_now = 1;
888 for (i = 0; i < num; i++)
890 eet_close(closelist[i]);
895 /* FIXME: MMAP race condition in READ_WRITE_MODE */
897 eet_internal_read2(Eet_File *ef)
899 const int *data = (const int*) ef->data;
900 const char *start = (const char*) ef->data;
902 int num_directory_entries;
903 int bytes_directory_entries;
904 int num_dictionary_entries;
905 int bytes_dictionary_entries;
906 int signature_base_offset;
909 index += sizeof(int);
910 if (eet_test_close((int) ntohl(*data) != EET_MAGIC_FILE2, ef))
914 #define GET_INT(Value, Pointer, Index) \
916 Value = ntohl(*Pointer); \
918 Index += sizeof(int); \
921 /* get entries count and byte count */
922 GET_INT(num_directory_entries, data, index);
923 /* get dictionary count and byte count */
924 GET_INT(num_dictionary_entries, data, index);
926 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
927 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
929 /* we cant have <= 0 values here - invalid */
930 if (eet_test_close((num_directory_entries <= 0), ef))
933 /* we cant have more bytes directory and bytes in dictionaries than the size of the file */
934 if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > ef->data_size, ef))
937 /* allocate header */
938 ef->header = calloc(1, sizeof(Eet_File_Header));
939 if (eet_test_close(!ef->header, ef))
942 ef->header->magic = EET_MAGIC_FILE_HEADER;
944 /* allocate directory block in ram */
945 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
946 if (eet_test_close(!ef->header->directory, ef))
949 /* 8 bit hash table (256 buckets) */
950 ef->header->directory->size = 8;
951 /* allocate base hash table */
952 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
953 if (eet_test_close(!ef->header->directory->nodes, ef))
956 signature_base_offset = 0;
958 /* actually read the directory block - all of it, into ram */
959 for (i = 0; i < num_directory_entries; ++i)
968 /* out directory block is inconsistent - we have oveerun our */
969 /* dynamic block buffer before we finished scanning dir entries */
970 efn = malloc (sizeof(Eet_File_Node));
971 if (eet_test_close(!efn, ef))
974 /* get entrie header */
975 GET_INT(efn->offset, data, index);
976 GET_INT(efn->size, data, index);
977 GET_INT(efn->data_size, data, index);
978 GET_INT(name_offset, data, index);
979 GET_INT(name_size, data, index);
980 GET_INT(flag, data, index);
982 efn->compression = flag & 0x1 ? 1 : 0;
983 efn->ciphered = flag & 0x2 ? 1 : 0;
985 #define EFN_TEST(Test, Ef, Efn) \
986 if (eet_test_close(Test, Ef)) \
992 /* check data pointer position */
993 EFN_TEST(!((efn->size > 0)
994 && (efn->offset + efn->size <= ef->data_size)
995 && (efn->offset > bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
997 /* check name position */
998 EFN_TEST(!((name_size > 0)
999 && (name_offset + name_size < ef->data_size)
1000 && (name_offset >= bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
1002 name = start + name_offset;
1004 /* check '\0' at the end of name string */
1005 EFN_TEST(name[name_size - 1] != '\0', ef, efn);
1008 efn->name = (char*) name;
1009 efn->name_size = name_size;
1011 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1012 efn->next = ef->header->directory->nodes[hash];
1013 ef->header->directory->nodes[hash] = efn;
1015 /* read-only mode, so currently we have no data loaded */
1016 if (ef->mode == EET_FILE_MODE_READ)
1018 /* read-write mode - read everything into ram */
1021 efn->data = malloc(efn->size);
1023 memcpy(efn->data, ef->data + efn->offset, efn->size);
1026 /* compute the possible position of a signature */
1027 if (signature_base_offset < efn->offset + efn->size)
1028 signature_base_offset = efn->offset + efn->size;
1033 if (num_dictionary_entries)
1035 const int *dico = (const int*) ef->data + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + EET_FILE2_HEADER_COUNT;
1038 if (eet_test_close((num_dictionary_entries * (int) EET_FILE2_DICTIONARY_ENTRY_SIZE + index) > (bytes_dictionary_entries + bytes_directory_entries), ef))
1041 ef->ed = calloc(1, sizeof (Eet_Dictionary));
1042 if (eet_test_close(!ef->ed, ef)) return NULL;
1044 ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String));
1045 if (eet_test_close(!ef->ed->all, ef)) return NULL;
1047 ef->ed->count = num_dictionary_entries;
1048 ef->ed->total = num_dictionary_entries;
1049 ef->ed->start = start + bytes_dictionary_entries + bytes_directory_entries;
1050 ef->ed->end = ef->ed->start;
1052 for (j = 0; j < ef->ed->count; ++j)
1057 GET_INT(hash, dico, index);
1058 GET_INT(offset, dico, index);
1059 GET_INT(ef->ed->all[j].len, dico, index);
1060 GET_INT(ef->ed->all[j].prev, dico, index);
1061 GET_INT(ef->ed->all[j].next, dico, index);
1063 /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
1064 So stick to int and check the value. */
1065 if (eet_test_close(hash & 0xFFFFFF00, ef)) return NULL;
1067 /* Check string position */
1068 if (eet_test_close(!((ef->ed->all[j].len > 0)
1069 && (offset > (bytes_dictionary_entries + bytes_directory_entries))
1070 && (offset + ef->ed->all[j].len < ef->data_size)), ef))
1073 ef->ed->all[j].mmap = start + offset;
1074 ef->ed->all[j].str = NULL;
1076 if (ef->ed->all[j].mmap + ef->ed->all[j].len > ef->ed->end)
1077 ef->ed->end = ef->ed->all[j].mmap + ef->ed->all[j].len;
1079 /* Check '\0' at the end of the string */
1080 if (eet_test_close(ef->ed->all[j].mmap[ef->ed->all[j].len - 1] != '\0', ef)) return NULL;
1082 ef->ed->all[j].hash = hash;
1083 if (ef->ed->all[j].prev == -1)
1084 ef->ed->hash[hash] = j;
1086 /* compute the possible position of a signature */
1087 if (signature_base_offset < offset + ef->ed->all[j].len)
1088 signature_base_offset = offset + ef->ed->all[j].len;
1092 /* Check if the file is signed */
1093 ef->x509_der = NULL;
1094 ef->x509_length = 0;
1095 ef->signature = NULL;
1096 ef->signature_length = 0;
1098 if (signature_base_offset < ef->data_size)
1100 #ifdef HAVE_SIGNATURE
1101 const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset;
1102 ef->x509_der = eet_identity_check(ef->data, signature_base_offset,
1103 &ef->sha1, &ef->sha1_length,
1104 buffer, ef->data_size - signature_base_offset,
1105 &ef->signature, &ef->signature_length,
1108 if (eet_test_close(ef->x509_der == NULL, ef)) return NULL;
1110 ERR("This file could be signed but you didn't compile the necessary code to check the signature.");
1117 #if EET_OLD_EET_FILE_FORMAT
1119 eet_internal_read1(Eet_File *ef)
1121 const unsigned char *dyn_buf = NULL;
1122 const unsigned char *p = NULL;
1128 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);
1130 /* build header table if read mode */
1132 index += sizeof(int);
1133 if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
1136 #define EXTRACT_INT(Value, Pointer, Index) \
1139 memcpy(&tmp, Pointer + Index, sizeof(int)); \
1140 Value = ntohl(tmp); \
1141 Index += sizeof(int); \
1144 /* get entries count and byte count */
1145 EXTRACT_INT(num_entries, ef->data, index);
1146 EXTRACT_INT(byte_entries, ef->data, index);
1148 /* we cant have <= 0 values here - invalid */
1149 if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef))
1152 /* we can't have more entires than minimum bytes for those! invalid! */
1153 if (eet_test_close((num_entries * 20) > byte_entries, ef))
1156 /* check we will not outrun the file limit */
1157 if (eet_test_close(((byte_entries + (int) sizeof(int) * 3) > ef->data_size), ef))
1160 /* allocate header */
1161 ef->header = calloc(1, sizeof(Eet_File_Header));
1162 if (eet_test_close(!ef->header, ef))
1165 ef->header->magic = EET_MAGIC_FILE_HEADER;
1167 /* allocate directory block in ram */
1168 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1169 if (eet_test_close(!ef->header->directory, ef))
1172 /* 8 bit hash table (256 buckets) */
1173 ef->header->directory->size = 8;
1174 /* allocate base hash table */
1175 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1176 if (eet_test_close(!ef->header->directory->nodes, ef))
1179 /* actually read the directory block - all of it, into ram */
1180 dyn_buf = ef->data + index;
1182 /* parse directory block */
1185 for (i = 0; i < num_entries; i++)
1194 #define HEADER_SIZE (sizeof(int) * 5)
1196 /* out directory block is inconsistent - we have oveerun our */
1197 /* dynamic block buffer before we finished scanning dir entries */
1198 if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
1201 /* allocate all the ram needed for this stored node accounting */
1202 efn = malloc (sizeof(Eet_File_Node));
1203 if (eet_test_close(!efn, ef))
1206 /* get entrie header */
1207 EXTRACT_INT(efn->offset, p, indexn);
1208 EXTRACT_INT(efn->compression, p, indexn);
1209 EXTRACT_INT(efn->size, p, indexn);
1210 EXTRACT_INT(efn->data_size, p, indexn);
1211 EXTRACT_INT(name_size, p, indexn);
1213 efn->name_size = name_size;
1217 if (eet_test_close(efn->size <= 0, ef))
1223 /* invalid name_size */
1224 if (eet_test_close(name_size <= 0, ef))
1230 /* reading name would mean falling off end of dyn_buf - invalid */
1231 if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
1237 /* This code is useless if we dont want backward compatibility */
1238 for (k = name_size; k > 0 && ((unsigned char) * (p + HEADER_SIZE + k)) != 0; --k)
1241 efn->free_name = ((unsigned char) * (p + HEADER_SIZE + k)) != 0;
1245 efn->name = malloc(sizeof(char) * name_size + 1);
1246 if (eet_test_close(efn->name == NULL, ef))
1252 strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
1253 efn->name[name_size] = 0;
1255 WRN("File: %s is not up to date for key \"%s\" - needs rebuilding sometime", ef->path, efn->name);
1258 /* The only really usefull peace of code for efn->name (no backward compatibility) */
1259 efn->name = (char*)((unsigned char*)(p + HEADER_SIZE));
1261 /* get hash bucket it should go in */
1262 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1263 efn->next = ef->header->directory->nodes[hash];
1264 ef->header->directory->nodes[hash] = efn;
1266 /* read-only mode, so currently we have no data loaded */
1267 if (ef->mode == EET_FILE_MODE_READ)
1269 /* read-write mode - read everything into ram */
1272 data = malloc(efn->size);
1274 memcpy(data, ef->data + efn->offset, efn->size);
1278 p += HEADER_SIZE + name_size;
1285 eet_internal_read(Eet_File *ef)
1287 const int *data = (const int*) ef->data;
1289 if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef))
1292 if (eet_test_close(ef->data_size < (int) sizeof(int) * 3, ef))
1295 switch (ntohl(*data))
1297 #if EET_OLD_EET_FILE_FORMAT
1298 case EET_MAGIC_FILE:
1299 return eet_internal_read1(ef);
1301 case EET_MAGIC_FILE2:
1302 return eet_internal_read2(ef);
1304 ef->delete_me_now = 1;
1313 eet_internal_close(Eet_File *ef, Eina_Bool locked)
1317 /* check to see its' an eet file pointer */
1318 if (eet_check_pointer(ef))
1319 return EET_ERROR_BAD_OBJECT;
1322 /* if its still referenced - dont go any further */
1323 if (ef->references > 0) return EET_ERROR_NONE;
1324 /* flush any writes */
1325 err = eet_flush2(ef);
1327 eet_identity_unref(ef->key);
1330 /* if not urgent to delete it - dont free it - leave it in cache */
1331 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
1332 return EET_ERROR_NONE;
1334 /* remove from cache */
1339 if (ef->mode == EET_FILE_MODE_READ)
1340 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1341 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1342 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1353 if (ef->header->directory)
1355 if (ef->header->directory->nodes)
1359 num = (1 << ef->header->directory->size);
1360 for (i = 0; i < num; i++)
1364 while ((efn = ef->header->directory->nodes[i]))
1369 ef->header->directory->nodes[i] = efn->next;
1377 free(ef->header->directory->nodes);
1379 free(ef->header->directory);
1384 eet_dictionary_free(ef->ed);
1386 if (ef->sha1) free(ef->sha1);
1387 if (ef->data) munmap((void*)ef->data, ef->data_size);
1388 if (ef->fp) fclose(ef->fp);
1389 if (ef->readfp) fclose(ef->readfp);
1391 /* zero out ram for struct - caution tactic against stale memory use */
1392 memset(ef, 0, sizeof(Eet_File));
1400 eet_memopen_read(const void *data, size_t size)
1404 if (data == NULL || size == 0)
1407 ef = malloc (sizeof (Eet_File));
1415 ef->magic = EET_MAGIC_FILE;
1417 ef->mode = EET_FILE_MODE_READ;
1420 ef->delete_me_now = 1;
1424 ef->data_size = size;
1426 ef->sha1_length = 0;
1428 return eet_internal_read(ef);
1432 eet_open(const char *file, Eet_File_Mode mode)
1437 struct stat file_stat;
1442 /* find the current file handle in cache*/
1445 if (mode == EET_FILE_MODE_READ)
1447 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1452 ef->delete_me_now = 1;
1453 eet_internal_close(ef, 1);
1455 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1457 else if ((mode == EET_FILE_MODE_WRITE) ||
1458 (mode == EET_FILE_MODE_READ_WRITE))
1460 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1463 ef->delete_me_now = 1;
1465 eet_internal_close(ef, 1);
1467 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1471 /* try open the file based on mode */
1472 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1474 /* Prevent garbage in futur comparison. */
1475 file_stat.st_mtime = 0;
1477 fp = fopen(file, "rb");
1478 if (!fp) goto on_error;
1479 if (fstat(fileno(fp), &file_stat))
1485 if ((mode == EET_FILE_MODE_READ) &&
1486 (file_stat.st_size < ((int) sizeof(int) * 3)))
1494 if (fp == NULL && mode == EET_FILE_MODE_READ) return NULL;
1500 if (mode != EET_FILE_MODE_WRITE) return NULL;
1501 memset(&file_stat, 0, sizeof(file_stat));
1502 /* opening for write - delete old copy of file right away */
1504 fd = open(file, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
1505 fp = fdopen(fd, "wb");
1506 if (!fp) return NULL;
1510 if (ef && (file_stat.st_mtime != ef->mtime))
1512 ef->delete_me_now = 1;
1514 eet_internal_close(ef, 0);
1520 /* reference it up and return it */
1521 if (fp != NULL) fclose(fp);
1526 file_len = strlen(file) + 1;
1528 /* Allocate struct for eet file and have it zero'd out */
1529 ef = malloc(sizeof(Eet_File) + file_len);
1533 /* fill some of the members */
1538 ef->path = ((char *)ef) + sizeof(Eet_File);
1539 memcpy(ef->path, file, file_len);
1540 ef->magic = EET_MAGIC_FILE;
1544 ef->mtime = file_stat.st_mtime;
1545 ef->writes_pending = 0;
1546 ef->delete_me_now = 0;
1550 ef->sha1_length = 0;
1552 ef->ed = (mode == EET_FILE_MODE_WRITE)
1553 || (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) ?
1554 eet_dictionary_add() : NULL;
1556 if (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) goto empty_file;
1558 /* if we can't open - bail out */
1559 if (eet_test_close(!ef->fp, ef))
1562 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
1563 /* if we opened for read or read-write */
1564 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1566 ef->data_size = file_stat.st_size;
1567 ef->data = mmap(NULL, ef->data_size, PROT_READ,
1568 MAP_SHARED, fileno(ef->fp), 0);
1569 if (eet_test_close((ef->data == MAP_FAILED), ef))
1571 ef = eet_internal_read(ef);
1577 /* we need to delete the original file in read-write mode and re-open for writing */
1578 if (ef->mode == EET_FILE_MODE_READ_WRITE)
1580 ef->readfp = ef->fp;
1585 if (ef->references == 1)
1588 if (ef->mode == EET_FILE_MODE_READ)
1589 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1591 if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1592 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1600 eet_mode_get(Eet_File *ef)
1602 /* check to see its' an eet file pointer */
1603 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
1604 return EET_FILE_MODE_INVALID;
1610 eet_identity_x509(Eet_File *ef, int *der_length)
1612 if (!ef->x509_der) return NULL;
1614 if (der_length) *der_length = ef->x509_length;
1615 return ef->x509_der;
1619 eet_identity_signature(Eet_File *ef, int *signature_length)
1621 if (!ef->signature) return NULL;
1623 if (signature_length) *signature_length = ef->signature_length;
1624 return ef->signature;
1628 eet_identity_sha1(Eet_File *ef, int *sha1_length)
1631 ef->sha1 = eet_identity_compute_sha1(ef->data, ef->data_size, &ef->sha1_length);
1633 if (sha1_length) *sha1_length = ef->sha1_length;
1638 eet_identity_set(Eet_File *ef, Eet_Key *key)
1640 Eet_Key *tmp = ef->key;
1642 if (!ef) return EET_ERROR_BAD_OBJECT;
1645 eet_identity_ref(ef->key);
1646 eet_identity_unref(tmp);
1648 /* flags that writes are pending */
1649 ef->writes_pending = 1;
1651 return EET_ERROR_NONE;
1655 eet_close(Eet_File *ef)
1657 return eet_internal_close(ef, 0);
1661 eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *cipher_key)
1670 /* check to see its' an eet file pointer */
1671 if (eet_check_pointer(ef))
1675 if ((ef->mode != EET_FILE_MODE_READ) &&
1676 (ef->mode != EET_FILE_MODE_READ_WRITE))
1679 /* no header, return NULL */
1680 if (eet_check_header(ef))
1685 /* hunt hash bucket */
1686 efn = find_node_by_name(ef, name);
1687 if (!efn) goto on_error;
1689 /* get size (uncompressed, if compressed at all) */
1690 size = efn->data_size;
1693 data = malloc(size);
1694 if (!data) goto on_error;
1696 /* uncompressed data */
1697 if (efn->compression == 0)
1699 void *data_deciphered = NULL;
1700 unsigned int data_deciphered_sz = 0;
1701 /* if we alreayd have the data in ram... copy that */
1703 memcpy(data, efn->data, efn->size);
1705 if (!read_data_from_disk(ef, efn, data, size))
1707 if (efn->ciphered && cipher_key)
1709 if (eet_decipher(data, size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1711 if (data_deciphered) free(data_deciphered);
1715 data = data_deciphered;
1716 size = data_deciphered_sz;
1719 /* compressed data */
1723 void *data_deciphered = NULL;
1724 unsigned int data_deciphered_sz = 0;
1726 int compr_size = efn->size;
1729 /* if we already have the data in ram... copy that */
1731 tmp_data = efn->data;
1734 tmp_data = malloc(compr_size);
1740 if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
1747 if (efn->ciphered && cipher_key)
1749 if (eet_decipher(tmp_data, compr_size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1751 if (free_tmp) free(tmp_data);
1752 if (data_deciphered) free(data_deciphered);
1756 tmp_data = data_deciphered;
1757 compr_size = data_deciphered_sz;
1762 if (uncompress((Bytef *)data, &dlen,
1763 tmp_data, (uLongf)compr_size))
1770 /* fill in return values */
1785 eet_read(Eet_File *ef, const char *name, int *size_ret)
1787 return eet_read_cipher(ef, name, size_ret, NULL);
1791 eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
1793 const void *data = NULL;
1800 /* check to see its' an eet file pointer */
1801 if (eet_check_pointer(ef))
1805 if ((ef->mode != EET_FILE_MODE_READ) &&
1806 (ef->mode != EET_FILE_MODE_READ_WRITE))
1809 /* no header, return NULL */
1810 if (eet_check_header(ef))
1815 /* hunt hash bucket */
1816 efn = find_node_by_name(ef, name);
1817 if (!efn) goto on_error;
1819 if (efn->offset < 0 && efn->data == NULL)
1822 /* get size (uncompressed, if compressed at all) */
1823 size = efn->data_size;
1825 /* uncompressed data */
1826 if (efn->compression == 0
1827 && efn->ciphered == 0)
1828 data = efn->data ? efn->data : ef->data + efn->offset;
1829 /* compressed data */
1833 /* fill in return values */
1847 eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int compress, const char *cipher_key)
1851 int exists_already = 0;
1855 /* check to see its' an eet file pointer */
1856 if (eet_check_pointer(ef))
1858 if ((!name) || (!data) || (size <= 0))
1860 if ((ef->mode != EET_FILE_MODE_WRITE) &&
1861 (ef->mode != EET_FILE_MODE_READ_WRITE))
1868 /* allocate header */
1869 ef->header = calloc(1, sizeof(Eet_File_Header));
1873 ef->header->magic = EET_MAGIC_FILE_HEADER;
1874 /* allocate directory block in ram */
1875 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1876 if (!ef->header->directory)
1883 /* 8 bit hash table (256 buckets) */
1884 ef->header->directory->size = 8;
1885 /* allocate base hash table */
1886 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1887 if (!ef->header->directory->nodes)
1889 free(ef->header->directory);
1895 /* figure hash bucket */
1896 hash = _eet_hash_gen(name, ef->header->directory->size);
1898 data_size = compress ? 12 + ((size * 101) / 100) : size;
1900 if (compress || !cipher_key)
1902 data2 = malloc(data_size);
1903 if (!data2) goto on_error;
1906 /* if we want to compress */
1911 /* compress the data with max compression */
1912 buflen = (uLongf)data_size;
1913 if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
1914 (uLong)size, Z_BEST_COMPRESSION) != Z_OK)
1919 /* record compressed chunk size */
1920 data_size = (int)buflen;
1921 if (data_size < 0 || data_size >= size)
1930 data3 = realloc(data2, data_size);
1938 void *data_ciphered = NULL;
1939 unsigned int data_ciphered_sz = 0;
1942 tmp = data2 ? data2 : data;
1943 if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), &data_ciphered, &data_ciphered_sz))
1945 if (data2) free(data2);
1946 data2 = data_ciphered;
1947 data_size = data_ciphered_sz;
1948 size = (data_size > size) ? data_size : size;
1952 if (data_ciphered) free(data_ciphered);
1958 memcpy(data2, data, size);
1960 /* Does this node already exist? */
1961 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
1964 if ((efn->name) && (eet_string_match(efn->name, name)))
1967 efn->ciphered = cipher_key ? 1 : 0;
1968 efn->compression = !!compress;
1969 efn->size = data_size;
1970 efn->data_size = size;
1977 if (!exists_already)
1979 efn = malloc(sizeof(Eet_File_Node));
1985 efn->name = strdup(name);
1986 efn->name_size = strlen(efn->name) + 1;
1989 efn->next = ef->header->directory->nodes[hash];
1990 ef->header->directory->nodes[hash] = efn;
1992 efn->ciphered = cipher_key ? 1 : 0;
1993 efn->compression = !!compress;
1994 efn->size = data_size;
1995 efn->data_size = size;
1999 /* flags that writes are pending */
2000 ef->writes_pending = 1;
2010 eet_write(Eet_File *ef, const char *name, const void *data, int size, int compress)
2012 return eet_write_cipher(ef, name, data, size, compress, NULL);
2016 eet_delete(Eet_File *ef, const char *name)
2019 Eet_File_Node *pefn;
2021 int exists_already = 0;
2023 /* check to see its' an eet file pointer */
2024 if (eet_check_pointer(ef))
2029 /* deleting keys is only possible in RW or WRITE mode */
2030 if (ef->mode == EET_FILE_MODE_READ)
2033 if (eet_check_header(ef))
2038 /* figure hash bucket */
2039 hash = _eet_hash_gen(name, ef->header->directory->size);
2041 /* Does this node already exist? */
2042 for (pefn = NULL, efn = ef->header->directory->nodes[hash];
2044 pefn = efn, efn = efn->next)
2047 if (eet_string_match(efn->name, name))
2053 ef->header->directory->nodes[hash] = efn->next;
2055 pefn->next = efn->next;
2057 if (efn->free_name) free(efn->name);
2063 /* flags that writes are pending */
2065 ef->writes_pending = 1;
2069 /* update access time */
2070 return exists_already;
2073 EAPI Eet_Dictionary *
2074 eet_dictionary_get(Eet_File *ef)
2076 if (eet_check_pointer(ef)) return NULL;
2083 eet_list(Eet_File *ef, const char *glob, int *count_ret)
2086 char **list_ret = NULL;
2088 int list_count_alloc = 0;
2091 /* check to see its' an eet file pointer */
2092 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2094 ((ef->mode != EET_FILE_MODE_READ) &&
2095 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2105 /* loop through all entries */
2106 num = (1 << ef->header->directory->size);
2107 for (i = 0; i < num; i++)
2109 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2111 /* if the entry matches the input glob
2112 * check for * explicitly, because on some systems, * isn't well
2115 if ((!strcmp (glob, "*")) || !fnmatch(glob, efn->name, 0))
2117 /* add it to our list */
2120 /* only realloc in 32 entry chunks */
2121 if (list_count > list_count_alloc)
2123 char **new_list = NULL;
2125 list_count_alloc += 64;
2126 new_list = realloc(list_ret, list_count_alloc * (sizeof(char *)));
2133 list_ret = new_list;
2136 /* put pointer of name string in */
2137 list_ret[list_count - 1] = efn->name;
2144 /* return count and list */
2146 *count_ret = list_count;
2160 eet_num_entries(Eet_File *ef)
2162 int i, num, ret = 0;
2165 /* check to see its' an eet file pointer */
2166 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2167 ((ef->mode != EET_FILE_MODE_READ) &&
2168 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2173 /* loop through all entries */
2174 num = (1 << ef->header->directory->size);
2175 for (i = 0; i < num; i++)
2177 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2186 static Eet_File_Node *
2187 find_node_by_name(Eet_File *ef, const char *name)
2192 /* get hash bucket this should be in */
2193 hash = _eet_hash_gen(name, ef->header->directory->size);
2195 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2197 if (eet_string_match(efn->name, name))
2205 read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len)
2207 if (efn->offset < 0) return 0;
2211 if ((efn->offset + len) > ef->data_size) return 0;
2212 memcpy(buf, ef->data + efn->offset, len);
2216 /* seek to data location */
2217 if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
2221 len = fread(buf, len, 1, ef->fp);