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);
28 #include <sys/types.h>
41 #ifdef HAVE_NETINET_IN_H
42 # include <netinet/in.h>
46 # include <winsock2.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, EINA_TRUE);
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 */
310 /* this should only be called when the cache lock is already held */
312 eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
314 Eet_File **new_cache;
318 new_cache_num = *cache_num;
319 if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */
321 Eet_File *del_ef = NULL;
325 for (i = 0; i < new_cache_num; i++)
327 if (new_cache[i]->references == 0)
329 del_ef = new_cache[i];
336 del_ef->delete_me_now = 1;
337 eet_internal_close(ef, EINA_TRUE);
342 new_cache_num = *cache_num;
343 new_cache_alloc = *cache_alloc;
345 if (new_cache_num > new_cache_alloc)
347 new_cache_alloc += 16;
348 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
351 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
355 new_cache[new_cache_num - 1] = ef;
357 *cache_num = new_cache_num;
358 *cache_alloc = new_cache_alloc;
361 /* delete from cache */
362 /* this should only be called when the cache lock is already held */
364 eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
366 Eet_File **new_cache;
367 int new_cache_num, new_cache_alloc;
371 new_cache_num = *cache_num;
372 new_cache_alloc = *cache_alloc;
373 if (new_cache_num <= 0)
376 for (i = 0; i < new_cache_num; i++)
378 if (new_cache[i] == ef)
382 if (i >= new_cache_num)
386 for (j = i; j < new_cache_num; j++)
387 new_cache[j] = new_cache[j + 1];
389 if (new_cache_num <= (new_cache_alloc - 16))
391 new_cache_alloc -= 16;
392 if (new_cache_num > 0)
394 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
397 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
408 *cache_num = new_cache_num;
409 *cache_alloc = new_cache_alloc;
412 /* internal string match. null friendly, catches same ptr */
414 eet_string_match(const char *s1, const char *s2)
416 /* both null- no match */
417 if ((!s1) || (!s2)) return 0;
418 if (s1 == s2) return 1;
419 return (!strcmp(s1, s2));
422 /* flush out writes to a v2 eet file */
424 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->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
445 return EET_ERROR_NOT_WRITABLE;
446 if (!ef->writes_pending)
447 return EET_ERROR_NONE;
448 if (ef->mode == EET_FILE_MODE_READ_WRITE && ef->fp == NULL)
453 fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
454 ef->fp = fdopen(fd, "wb");
455 if (!ef->fp) return EET_ERROR_NOT_WRITABLE;
456 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
459 /* calculate string base offset and data base offset */
460 num = (1 << ef->header->directory->size);
461 for (i = 0; i < num; ++i)
463 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
465 num_directory_entries++;
466 bytes_strings += strlen(efn->name) + 1;
471 num_dictionary_entries = ef->ed->count;
473 for (i = 0; i < num_dictionary_entries; ++i)
474 bytes_strings += ef->ed->all[i].len;
477 /* calculate section bytes size */
478 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
479 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
481 /* calculate per entry offset */
482 strings_offset = bytes_directory_entries + bytes_dictionary_entries;
483 data_offset = bytes_directory_entries + bytes_dictionary_entries + bytes_strings;
485 for (i = 0; i < num; ++i)
487 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
489 efn->offset = data_offset;
490 data_offset += efn->size;
492 efn->name_offset = strings_offset;
493 strings_offset += efn->name_size;
497 /* calculate dictionary strings offset */
499 ef->ed->offset = strings_offset;
501 /* go thru and write the header */
502 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE2);
503 head[1] = (int) htonl ((unsigned int) num_directory_entries);
504 head[2] = (int) htonl ((unsigned int) num_dictionary_entries);
506 fseek(ef->fp, 0, SEEK_SET);
507 if (fwrite(head, sizeof (head), 1, ef->fp) != 1)
510 /* write directories entry */
511 for (i = 0; i < num; i++)
513 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
516 int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
518 flag = (efn->ciphered << 1) | efn->compression;
520 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
521 ibuf[1] = (int) htonl ((unsigned int) efn->size);
522 ibuf[2] = (int) htonl ((unsigned int) efn->data_size);
523 ibuf[3] = (int) htonl ((unsigned int) efn->name_offset);
524 ibuf[4] = (int) htonl ((unsigned int) efn->name_size);
525 ibuf[5] = (int) htonl ((unsigned int) flag);
527 if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
532 /* write dictionnary */
535 int offset = strings_offset;
537 for (j = 0; j < ef->ed->count; ++j)
539 int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
541 sbuf[0] = (int) htonl ((unsigned int) ef->ed->all[j].hash);
542 sbuf[1] = (int) htonl ((unsigned int) offset);
543 sbuf[2] = (int) htonl ((unsigned int) ef->ed->all[j].len);
544 sbuf[3] = (int) htonl ((unsigned int) ef->ed->all[j].prev);
545 sbuf[4] = (int) htonl ((unsigned int) ef->ed->all[j].next);
547 offset += ef->ed->all[j].len;
549 if (fwrite(sbuf, sizeof (sbuf), 1, ef->fp) != 1)
554 /* write directories name */
555 for (i = 0; i < num; i++)
557 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
559 if (fwrite(efn->name, efn->name_size, 1, ef->fp) != 1)
567 for (j = 0; j < ef->ed->count; ++j)
569 if (ef->ed->all[j].str)
571 if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, ef->fp) != 1)
576 if (fwrite(ef->ed->all[j].mmap, ef->ed->all[j].len, 1, ef->fp) != 1)
583 for (i = 0; i < num; i++)
585 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
587 if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
592 /* flush all write to the file. */
594 // this is going to really cause trouble. if ANYTHING this needs to go into a
595 // thread spawned off - but even then...
596 // in this case... ext4 is "wrong". (yes we can jump up and down and point posix
597 // manual pages at eachother, but ext4 broke behavior that has been in place
598 // for decades and that 1000's of apps rely on daily - that is that one operation
599 // to disk is committed to disk BEFORE following operations, so the fs retains
600 // a consistent state
601 // fsync(fileno(ef->fp));
603 /* append signature if required */
606 error = eet_identity_sign(ef->fp, ef->key);
607 if (error != EET_ERROR_NONE)
611 /* no more writes pending */
612 ef->writes_pending = 0;
614 return EET_ERROR_NONE;
621 case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
622 case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
623 case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
624 case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
625 default: error = EET_ERROR_WRITE_ERROR; break;
629 if (ef->fp) fclose(ef->fp);
635 /* flush out writes to an eet file */
637 eet_flush(Eet_File *ef)
647 /* check to see its' an eet file pointer */
648 if (eet_check_pointer(ef))
649 return EET_ERROR_BAD_OBJECT;
650 if (eet_check_header(ef))
651 return EET_ERROR_EMPTY;
652 if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
653 return EET_ERROR_NOT_WRITABLE;
654 if (!ef->writes_pending)
655 return EET_ERROR_NONE;
657 /* calculate total size in bytes of directory block */
658 num = (1 << ef->header->directory->size);
659 for (i = 0; i < num; i++)
661 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
663 size += 20 + strlen(efn->name) + 1;
668 /* calculate offsets per entry */
670 for (i = 0; i < num; i++)
672 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
674 efn->offset = 12 + size + offset;
679 /* go thru and write the header */
680 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE);
681 head[1] = (int) htonl ((unsigned int) count);
682 head[2] = (int) htonl ((unsigned int) size);
684 fseek(ef->fp, 0, SEEK_SET);
685 if (fwrite(head, 12, 1, ef->fp) != 1)
688 for (i = 0; i < num; i++)
690 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
692 unsigned int ibuf[5];
695 name_size = strlen(efn->name) + 1;
697 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
698 ibuf[1] = (int) htonl ((unsigned int) efn->compression);
699 ibuf[2] = (int) htonl ((unsigned int) efn->size);
700 ibuf[3] = (int) htonl ((unsigned int) efn->data_size);
701 ibuf[4] = (int) htonl ((unsigned int) name_size);
704 if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
706 if (fwrite(efn->name, name_size, 1, ef->fp) != 1)
712 for (i = 0; i < num; i++)
714 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
716 if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
721 /* no more writes pending */
722 ef->writes_pending = 0;
724 return EET_ERROR_NONE;
734 return EET_ERROR_WRITE_ERROR_FILE_TOO_BIG;
738 return EET_ERROR_WRITE_ERROR_IO_ERROR;
742 return EET_ERROR_WRITE_ERROR_OUT_OF_SPACE;
746 return EET_ERROR_WRITE_ERROR_FILE_CLOSED;
750 return EET_ERROR_WRITE_ERROR;
754 if (ef->fp) fclose(ef->fp);
756 return EET_ERROR_WRITE_ERROR;
763 if (++eet_init_count != 1)
764 return eet_init_count;
768 fprintf(stderr, "Eet: Eina init failed");
769 return --eet_init_count;
771 _eet_log_dom_global = eina_log_domain_register("Eet", EET_DEFAULT_LOG_COLOR);
772 if (_eet_log_dom_global < 0)
774 EINA_LOG_ERR("Eet Can not create a general log domain.");
778 if (!eet_node_init())
780 EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
781 goto unregister_log_domain;
785 /* Before the library can be used, it must initialize itself if needed. */
786 if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0)
788 gcry_check_version(NULL);
789 /* Disable warning messages about problems with the secure memory subsystem.
790 This command should be run right after gcry_check_version. */
791 if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN))
793 /* This command is used to allocate a pool of secure memory and thus
794 enabling the use of secure memory. It also drops all extra privileges the
795 process has (i.e. if it is run as setuid (root)). If the argument nbytes
796 is 0, secure memory will be disabled. The minimum amount of secure memory
797 allocated is currently 16384 bytes; you may thus use a value of 1 to
798 request that default size. */
799 if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
800 WRN("BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
802 if (gnutls_global_init())
806 ERR_load_crypto_strings();
807 OpenSSL_add_all_algorithms();
810 return eet_init_count;
814 unregister_log_domain:
815 eina_log_domain_unregister(_eet_log_dom_global);
816 _eet_log_dom_global = -1;
819 return --eet_init_count;
825 if (--eet_init_count != 0)
826 return eet_init_count;
831 gnutls_global_deinit();
837 eina_log_domain_unregister(_eet_log_dom_global);
838 _eet_log_dom_global = -1;
841 return eet_init_count;
851 * We need to compute the list of eet file to close separately from the cache,
852 * due to eet_close removing them from the cache after each call.
855 for (i = 0; i < eet_writers_num; i++)
857 if (eet_writers[i]->references <= 0) num++;
860 for (i = 0; i < eet_readers_num; i++)
862 if (eet_readers[i]->references <= 0) num++;
867 Eet_File **closelist = NULL;
869 closelist = alloca(num * sizeof(Eet_File *));
871 for (i = 0; i < eet_writers_num; i++)
873 if (eet_writers[i]->references <= 0)
875 closelist[num] = eet_writers[i];
876 eet_writers[i]->delete_me_now = 1;
881 for (i = 0; i < eet_readers_num; i++)
883 if (eet_readers[i]->references <= 0)
885 closelist[num] = eet_readers[i];
886 eet_readers[i]->delete_me_now = 1;
891 for (i = 0; i < num; i++)
893 eet_internal_close(closelist[i], EINA_TRUE);
899 /* FIXME: MMAP race condition in READ_WRITE_MODE */
901 eet_internal_read2(Eet_File *ef)
903 const int *data = (const int*) ef->data;
904 const char *start = (const char*) ef->data;
906 int num_directory_entries;
907 int bytes_directory_entries;
908 int num_dictionary_entries;
909 int bytes_dictionary_entries;
910 int signature_base_offset;
914 if (eet_test_close((int) ntohl(*data) != EET_MAGIC_FILE2, ef))
918 #define GET_INT(Value, Pointer, Index) \
920 Value = ntohl(*Pointer); \
922 Index += sizeof(int); \
925 /* get entries count and byte count */
926 GET_INT(num_directory_entries, data, idx);
927 /* get dictionary count and byte count */
928 GET_INT(num_dictionary_entries, data, idx);
930 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
931 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
933 /* we cant have <= 0 values here - invalid */
934 if (eet_test_close((num_directory_entries <= 0), ef))
937 /* we cant have more bytes directory and bytes in dictionaries than the size of the file */
938 if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > ef->data_size, ef))
941 /* allocate header */
942 ef->header = calloc(1, sizeof(Eet_File_Header));
943 if (eet_test_close(!ef->header, ef))
946 ef->header->magic = EET_MAGIC_FILE_HEADER;
948 /* allocate directory block in ram */
949 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
950 if (eet_test_close(!ef->header->directory, ef))
953 /* 8 bit hash table (256 buckets) */
954 ef->header->directory->size = 8;
955 /* allocate base hash table */
956 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
957 if (eet_test_close(!ef->header->directory->nodes, ef))
960 signature_base_offset = 0;
962 /* actually read the directory block - all of it, into ram */
963 for (i = 0; i < num_directory_entries; ++i)
972 /* out directory block is inconsistent - we have oveerun our */
973 /* dynamic block buffer before we finished scanning dir entries */
974 efn = malloc (sizeof(Eet_File_Node));
975 if (eet_test_close(!efn, ef))
978 /* get entrie header */
979 GET_INT(efn->offset, data, idx);
980 GET_INT(efn->size, data, idx);
981 GET_INT(efn->data_size, data, idx);
982 GET_INT(name_offset, data, idx);
983 GET_INT(name_size, data, idx);
984 GET_INT(flag, data, idx);
986 efn->compression = flag & 0x1 ? 1 : 0;
987 efn->ciphered = flag & 0x2 ? 1 : 0;
989 #define EFN_TEST(Test, Ef, Efn) \
990 if (eet_test_close(Test, Ef)) \
996 /* check data pointer position */
997 EFN_TEST(!((efn->size > 0)
998 && (efn->offset + efn->size <= ef->data_size)
999 && (efn->offset > bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
1001 /* check name position */
1002 EFN_TEST(!((name_size > 0)
1003 && (name_offset + name_size < ef->data_size)
1004 && (name_offset >= bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
1006 name = start + name_offset;
1008 /* check '\0' at the end of name string */
1009 EFN_TEST(name[name_size - 1] != '\0', ef, efn);
1012 efn->name = (char*) name;
1013 efn->name_size = name_size;
1015 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1016 efn->next = ef->header->directory->nodes[hash];
1017 ef->header->directory->nodes[hash] = efn;
1019 /* read-only mode, so currently we have no data loaded */
1020 if (ef->mode == EET_FILE_MODE_READ)
1022 /* read-write mode - read everything into ram */
1025 efn->data = malloc(efn->size);
1027 memcpy(efn->data, ef->data + efn->offset, efn->size);
1030 /* compute the possible position of a signature */
1031 if (signature_base_offset < efn->offset + efn->size)
1032 signature_base_offset = efn->offset + efn->size;
1037 if (num_dictionary_entries)
1039 const int *dico = (const int*) ef->data + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + EET_FILE2_HEADER_COUNT;
1042 if (eet_test_close((num_dictionary_entries * (int) EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) > (bytes_dictionary_entries + bytes_directory_entries), ef))
1045 ef->ed = calloc(1, sizeof (Eet_Dictionary));
1046 if (eet_test_close(!ef->ed, ef)) return NULL;
1048 ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String));
1049 if (eet_test_close(!ef->ed->all, ef)) return NULL;
1051 ef->ed->count = num_dictionary_entries;
1052 ef->ed->total = num_dictionary_entries;
1053 ef->ed->start = start + bytes_dictionary_entries + bytes_directory_entries;
1054 ef->ed->end = ef->ed->start;
1056 for (j = 0; j < ef->ed->count; ++j)
1061 GET_INT(hash, dico, idx);
1062 GET_INT(offset, dico, idx);
1063 GET_INT(ef->ed->all[j].len, dico, idx);
1064 GET_INT(ef->ed->all[j].prev, dico, idx);
1065 GET_INT(ef->ed->all[j].next, dico, idx);
1067 /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
1068 So stick to int and check the value. */
1069 if (eet_test_close(hash & 0xFFFFFF00, ef)) return NULL;
1071 /* Check string position */
1072 if (eet_test_close(!((ef->ed->all[j].len > 0)
1073 && (offset > (bytes_dictionary_entries + bytes_directory_entries))
1074 && (offset + ef->ed->all[j].len < ef->data_size)), ef))
1077 ef->ed->all[j].mmap = start + offset;
1078 ef->ed->all[j].str = NULL;
1080 if (ef->ed->all[j].mmap + ef->ed->all[j].len > ef->ed->end)
1081 ef->ed->end = ef->ed->all[j].mmap + ef->ed->all[j].len;
1083 /* Check '\0' at the end of the string */
1084 if (eet_test_close(ef->ed->all[j].mmap[ef->ed->all[j].len - 1] != '\0', ef)) return NULL;
1086 ef->ed->all[j].hash = hash;
1087 if (ef->ed->all[j].prev == -1)
1088 ef->ed->hash[hash] = j;
1090 /* compute the possible position of a signature */
1091 if (signature_base_offset < offset + ef->ed->all[j].len)
1092 signature_base_offset = offset + ef->ed->all[j].len;
1096 /* Check if the file is signed */
1097 ef->x509_der = NULL;
1098 ef->x509_length = 0;
1099 ef->signature = NULL;
1100 ef->signature_length = 0;
1102 if (signature_base_offset < ef->data_size)
1104 #ifdef HAVE_SIGNATURE
1105 const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset;
1106 ef->x509_der = eet_identity_check(ef->data, signature_base_offset,
1107 &ef->sha1, &ef->sha1_length,
1108 buffer, ef->data_size - signature_base_offset,
1109 &ef->signature, &ef->signature_length,
1112 if (eet_test_close(ef->x509_der == NULL, ef)) return NULL;
1114 ERR("This file could be signed but you didn't compile the necessary code to check the signature.");
1121 #if EET_OLD_EET_FILE_FORMAT
1123 eet_internal_read1(Eet_File *ef)
1125 const unsigned char *dyn_buf = NULL;
1126 const unsigned char *p = NULL;
1132 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);
1134 /* build header table if read mode */
1137 if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
1140 #define EXTRACT_INT(Value, Pointer, Index) \
1143 memcpy(&tmp, Pointer + Index, sizeof(int)); \
1144 Value = ntohl(tmp); \
1145 Index += sizeof(int); \
1148 /* get entries count and byte count */
1149 EXTRACT_INT(num_entries, ef->data, idx);
1150 EXTRACT_INT(byte_entries, ef->data, idx);
1152 /* we cant have <= 0 values here - invalid */
1153 if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef))
1156 /* we can't have more entires than minimum bytes for those! invalid! */
1157 if (eet_test_close((num_entries * 20) > byte_entries, ef))
1160 /* check we will not outrun the file limit */
1161 if (eet_test_close(((byte_entries + (int) sizeof(int) * 3) > ef->data_size), ef))
1164 /* allocate header */
1165 ef->header = calloc(1, sizeof(Eet_File_Header));
1166 if (eet_test_close(!ef->header, ef))
1169 ef->header->magic = EET_MAGIC_FILE_HEADER;
1171 /* allocate directory block in ram */
1172 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1173 if (eet_test_close(!ef->header->directory, ef))
1176 /* 8 bit hash table (256 buckets) */
1177 ef->header->directory->size = 8;
1178 /* allocate base hash table */
1179 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1180 if (eet_test_close(!ef->header->directory->nodes, ef))
1183 /* actually read the directory block - all of it, into ram */
1184 dyn_buf = ef->data + idx;
1186 /* parse directory block */
1189 for (i = 0; i < num_entries; i++)
1198 #define HEADER_SIZE (sizeof(int) * 5)
1200 /* out directory block is inconsistent - we have oveerun our */
1201 /* dynamic block buffer before we finished scanning dir entries */
1202 if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
1205 /* allocate all the ram needed for this stored node accounting */
1206 efn = malloc (sizeof(Eet_File_Node));
1207 if (eet_test_close(!efn, ef))
1210 /* get entrie header */
1211 EXTRACT_INT(efn->offset, p, indexn);
1212 EXTRACT_INT(efn->compression, p, indexn);
1213 EXTRACT_INT(efn->size, p, indexn);
1214 EXTRACT_INT(efn->data_size, p, indexn);
1215 EXTRACT_INT(name_size, p, indexn);
1217 efn->name_size = name_size;
1221 if (eet_test_close(efn->size <= 0, ef))
1227 /* invalid name_size */
1228 if (eet_test_close(name_size <= 0, ef))
1234 /* reading name would mean falling off end of dyn_buf - invalid */
1235 if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
1241 /* This code is useless if we dont want backward compatibility */
1242 for (k = name_size; k > 0 && ((unsigned char) * (p + HEADER_SIZE + k)) != 0; --k)
1245 efn->free_name = ((unsigned char) * (p + HEADER_SIZE + k)) != 0;
1249 efn->name = malloc(sizeof(char) * name_size + 1);
1250 if (eet_test_close(efn->name == NULL, ef))
1256 strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
1257 efn->name[name_size] = 0;
1259 WRN("File: %s is not up to date for key \"%s\" - needs rebuilding sometime", ef->path, efn->name);
1262 /* The only really usefull peace of code for efn->name (no backward compatibility) */
1263 efn->name = (char*)((unsigned char*)(p + HEADER_SIZE));
1265 /* get hash bucket it should go in */
1266 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1267 efn->next = ef->header->directory->nodes[hash];
1268 ef->header->directory->nodes[hash] = efn;
1270 /* read-only mode, so currently we have no data loaded */
1271 if (ef->mode == EET_FILE_MODE_READ)
1273 /* read-write mode - read everything into ram */
1276 data = malloc(efn->size);
1278 memcpy(data, ef->data + efn->offset, efn->size);
1282 p += HEADER_SIZE + name_size;
1289 * this should only be called when the cache lock is already held
1290 * (We could drop this restriction if we add a parameter to eet_test_close
1291 * that indicates if the lock is held or not. For now it is easiest
1292 * to just require that it is always held.)
1295 eet_internal_read(Eet_File *ef)
1297 const int *data = (const int*) ef->data;
1299 if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef))
1302 if (eet_test_close(ef->data_size < (int) sizeof(int) * 3, ef))
1305 switch (ntohl(*data))
1307 #if EET_OLD_EET_FILE_FORMAT
1308 case EET_MAGIC_FILE:
1309 return eet_internal_read1(ef);
1311 case EET_MAGIC_FILE2:
1312 return eet_internal_read2(ef);
1314 ef->delete_me_now = 1;
1315 eet_internal_close(ef, EINA_TRUE);
1323 eet_internal_close(Eet_File *ef, Eina_Bool locked)
1327 /* check to see its' an eet file pointer */
1328 if (eet_check_pointer(ef))
1329 return EET_ERROR_BAD_OBJECT;
1331 if (!locked) LOCK_CACHE;
1335 /* if its still referenced - dont go any further */
1336 if (ef->references > 0) goto on_error;
1337 /* flush any writes */
1338 err = eet_flush2(ef);
1340 eet_identity_unref(ef->key);
1343 /* if not urgent to delete it - dont free it - leave it in cache */
1344 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
1347 /* remove from cache */
1348 if (ef->mode == EET_FILE_MODE_READ)
1349 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1350 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1351 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1353 /* we can unlock the cache now */
1354 if (!locked) UNLOCK_CACHE;
1361 if (ef->header->directory)
1363 if (ef->header->directory->nodes)
1367 num = (1 << ef->header->directory->size);
1368 for (i = 0; i < num; i++)
1372 while ((efn = ef->header->directory->nodes[i]))
1377 ef->header->directory->nodes[i] = efn->next;
1385 free(ef->header->directory->nodes);
1387 free(ef->header->directory);
1392 eet_dictionary_free(ef->ed);
1394 if (ef->sha1) free(ef->sha1);
1395 if (ef->data) munmap((void*)ef->data, ef->data_size);
1396 if (ef->fp) fclose(ef->fp);
1397 if (ef->readfp) fclose(ef->readfp);
1399 /* zero out ram for struct - caution tactic against stale memory use */
1400 memset(ef, 0, sizeof(Eet_File));
1407 if (!locked) UNLOCK_CACHE;
1408 return EET_ERROR_NONE;
1412 eet_memopen_read(const void *data, size_t size)
1416 if (data == NULL || size == 0)
1419 ef = malloc (sizeof (Eet_File));
1427 ef->magic = EET_MAGIC_FILE;
1429 ef->mode = EET_FILE_MODE_READ;
1432 ef->delete_me_now = 1;
1436 ef->data_size = size;
1438 ef->sha1_length = 0;
1440 /* eet_internal_read expects the cache lock to be held when it is called */
1442 ef = eet_internal_read(ef);
1448 eet_open(const char *file, Eet_File_Mode mode)
1453 struct stat file_stat;
1458 /* find the current file handle in cache*/
1461 if (mode == EET_FILE_MODE_READ)
1463 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1468 ef->delete_me_now = 1;
1469 eet_internal_close(ef, EINA_TRUE);
1471 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1473 else if ((mode == EET_FILE_MODE_WRITE) ||
1474 (mode == EET_FILE_MODE_READ_WRITE))
1476 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1479 ef->delete_me_now = 1;
1481 eet_internal_close(ef, EINA_TRUE);
1483 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1486 /* try open the file based on mode */
1487 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1489 /* Prevent garbage in futur comparison. */
1490 file_stat.st_mtime = 0;
1492 fp = fopen(file, "rb");
1493 if (!fp) goto open_error;
1494 if (fstat(fileno(fp), &file_stat))
1500 if ((mode == EET_FILE_MODE_READ) &&
1501 (file_stat.st_size < ((int) sizeof(int) * 3)))
1509 if (fp == NULL && mode == EET_FILE_MODE_READ) goto on_error;
1515 if (mode != EET_FILE_MODE_WRITE) return NULL;
1516 memset(&file_stat, 0, sizeof(file_stat));
1517 /* opening for write - delete old copy of file right away */
1519 fd = open(file, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
1520 fp = fdopen(fd, "wb");
1521 if (!fp) goto on_error;
1525 if (ef && (file_stat.st_mtime != ef->mtime))
1527 ef->delete_me_now = 1;
1529 eet_internal_close(ef, EINA_TRUE);
1535 /* reference it up and return it */
1536 if (fp != NULL) fclose(fp);
1542 file_len = strlen(file) + 1;
1544 /* Allocate struct for eet file and have it zero'd out */
1545 ef = malloc(sizeof(Eet_File) + file_len);
1549 /* fill some of the members */
1554 ef->path = ((char *)ef) + sizeof(Eet_File);
1555 memcpy(ef->path, file, file_len);
1556 ef->magic = EET_MAGIC_FILE;
1560 ef->mtime = file_stat.st_mtime;
1561 ef->writes_pending = 0;
1562 ef->delete_me_now = 0;
1566 ef->sha1_length = 0;
1568 ef->ed = (mode == EET_FILE_MODE_WRITE)
1569 || (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) ?
1570 eet_dictionary_add() : NULL;
1572 if (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) goto empty_file;
1574 /* if we can't open - bail out */
1575 if (eet_test_close(!ef->fp, ef))
1578 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
1579 /* if we opened for read or read-write */
1580 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1582 ef->data_size = file_stat.st_size;
1583 ef->data = mmap(NULL, ef->data_size, PROT_READ,
1584 MAP_SHARED, fileno(ef->fp), 0);
1585 if (eet_test_close((ef->data == MAP_FAILED), ef))
1587 ef = eet_internal_read(ef);
1593 /* we need to delete the original file in read-write mode and re-open for writing */
1594 if (ef->mode == EET_FILE_MODE_READ_WRITE)
1596 ef->readfp = ef->fp;
1601 if (ef->references == 1)
1603 if (ef->mode == EET_FILE_MODE_READ)
1604 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1606 if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1607 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1619 eet_mode_get(Eet_File *ef)
1621 /* check to see its' an eet file pointer */
1622 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
1623 return EET_FILE_MODE_INVALID;
1629 eet_identity_x509(Eet_File *ef, int *der_length)
1631 if (!ef->x509_der) return NULL;
1633 if (der_length) *der_length = ef->x509_length;
1634 return ef->x509_der;
1638 eet_identity_signature(Eet_File *ef, int *signature_length)
1640 if (!ef->signature) return NULL;
1642 if (signature_length) *signature_length = ef->signature_length;
1643 return ef->signature;
1647 eet_identity_sha1(Eet_File *ef, int *sha1_length)
1650 ef->sha1 = eet_identity_compute_sha1(ef->data, ef->data_size, &ef->sha1_length);
1652 if (sha1_length) *sha1_length = ef->sha1_length;
1657 eet_identity_set(Eet_File *ef, Eet_Key *key)
1659 Eet_Key *tmp = ef->key;
1661 if (!ef) return EET_ERROR_BAD_OBJECT;
1664 eet_identity_ref(ef->key);
1665 eet_identity_unref(tmp);
1667 /* flags that writes are pending */
1668 ef->writes_pending = 1;
1670 return EET_ERROR_NONE;
1674 eet_close(Eet_File *ef)
1676 return eet_internal_close(ef, EINA_FALSE);
1680 eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *cipher_key)
1689 /* check to see its' an eet file pointer */
1690 if (eet_check_pointer(ef))
1694 if ((ef->mode != EET_FILE_MODE_READ) &&
1695 (ef->mode != EET_FILE_MODE_READ_WRITE))
1698 /* no header, return NULL */
1699 if (eet_check_header(ef))
1704 /* hunt hash bucket */
1705 efn = find_node_by_name(ef, name);
1706 if (!efn) goto on_error;
1708 /* get size (uncompressed, if compressed at all) */
1709 size = efn->data_size;
1712 data = malloc(size);
1713 if (!data) goto on_error;
1715 /* uncompressed data */
1716 if (efn->compression == 0)
1718 void *data_deciphered = NULL;
1719 unsigned int data_deciphered_sz = 0;
1720 /* if we alreayd have the data in ram... copy that */
1722 memcpy(data, efn->data, efn->size);
1724 if (!read_data_from_disk(ef, efn, data, size))
1726 if (efn->ciphered && cipher_key)
1728 if (eet_decipher(data, size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1730 if (data_deciphered) free(data_deciphered);
1734 data = data_deciphered;
1735 size = data_deciphered_sz;
1738 /* compressed data */
1742 void *data_deciphered = NULL;
1743 unsigned int data_deciphered_sz = 0;
1745 int compr_size = efn->size;
1748 /* if we already have the data in ram... copy that */
1750 tmp_data = efn->data;
1753 tmp_data = malloc(compr_size);
1759 if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
1766 if (efn->ciphered && cipher_key)
1768 if (eet_decipher(tmp_data, compr_size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1770 if (free_tmp) free(tmp_data);
1771 if (data_deciphered) free(data_deciphered);
1775 tmp_data = data_deciphered;
1776 compr_size = data_deciphered_sz;
1781 if (uncompress((Bytef *)data, &dlen,
1782 tmp_data, (uLongf)compr_size))
1789 /* fill in return values */
1804 eet_read(Eet_File *ef, const char *name, int *size_ret)
1806 return eet_read_cipher(ef, name, size_ret, NULL);
1810 eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
1812 const void *data = NULL;
1819 /* check to see its' an eet file pointer */
1820 if (eet_check_pointer(ef))
1824 if ((ef->mode != EET_FILE_MODE_READ) &&
1825 (ef->mode != EET_FILE_MODE_READ_WRITE))
1828 /* no header, return NULL */
1829 if (eet_check_header(ef))
1834 /* hunt hash bucket */
1835 efn = find_node_by_name(ef, name);
1836 if (!efn) goto on_error;
1838 if (efn->offset < 0 && efn->data == NULL)
1841 /* get size (uncompressed, if compressed at all) */
1842 size = efn->data_size;
1844 /* uncompressed data */
1845 if (efn->compression == 0
1846 && efn->ciphered == 0)
1847 data = efn->data ? efn->data : ef->data + efn->offset;
1848 /* compressed data */
1852 /* fill in return values */
1866 eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int comp, const char *cipher_key)
1870 int exists_already = 0;
1874 /* check to see its' an eet file pointer */
1875 if (eet_check_pointer(ef))
1877 if ((!name) || (!data) || (size <= 0))
1879 if ((ef->mode != EET_FILE_MODE_WRITE) &&
1880 (ef->mode != EET_FILE_MODE_READ_WRITE))
1887 /* allocate header */
1888 ef->header = calloc(1, sizeof(Eet_File_Header));
1892 ef->header->magic = EET_MAGIC_FILE_HEADER;
1893 /* allocate directory block in ram */
1894 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1895 if (!ef->header->directory)
1902 /* 8 bit hash table (256 buckets) */
1903 ef->header->directory->size = 8;
1904 /* allocate base hash table */
1905 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1906 if (!ef->header->directory->nodes)
1908 free(ef->header->directory);
1914 /* figure hash bucket */
1915 hash = _eet_hash_gen(name, ef->header->directory->size);
1917 data_size = comp ? 12 + ((size * 101) / 100) : size;
1919 if (comp || !cipher_key)
1921 data2 = malloc(data_size);
1922 if (!data2) goto on_error;
1925 /* if we want to compress */
1930 /* compress the data with max compression */
1931 buflen = (uLongf)data_size;
1932 if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
1933 (uLong)size, Z_BEST_COMPRESSION) != Z_OK)
1938 /* record compressed chunk size */
1939 data_size = (int)buflen;
1940 if (data_size < 0 || data_size >= size)
1949 data3 = realloc(data2, data_size);
1957 void *data_ciphered = NULL;
1958 unsigned int data_ciphered_sz = 0;
1961 tmp = data2 ? data2 : data;
1962 if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), &data_ciphered, &data_ciphered_sz))
1964 if (data2) free(data2);
1965 data2 = data_ciphered;
1966 data_size = data_ciphered_sz;
1967 size = (data_size > size) ? data_size : size;
1971 if (data_ciphered) free(data_ciphered);
1977 memcpy(data2, data, size);
1979 /* Does this node already exist? */
1980 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
1983 if ((efn->name) && (eet_string_match(efn->name, name)))
1986 efn->ciphered = cipher_key ? 1 : 0;
1987 efn->compression = !!comp;
1988 efn->size = data_size;
1989 efn->data_size = size;
1996 if (!exists_already)
1998 efn = malloc(sizeof(Eet_File_Node));
2004 efn->name = strdup(name);
2005 efn->name_size = strlen(efn->name) + 1;
2008 efn->next = ef->header->directory->nodes[hash];
2009 ef->header->directory->nodes[hash] = efn;
2011 efn->ciphered = cipher_key ? 1 : 0;
2012 efn->compression = !!comp;
2013 efn->size = data_size;
2014 efn->data_size = size;
2018 /* flags that writes are pending */
2019 ef->writes_pending = 1;
2029 eet_write(Eet_File *ef, const char *name, const void *data, int size, int comp)
2031 return eet_write_cipher(ef, name, data, size, comp, NULL);
2035 eet_delete(Eet_File *ef, const char *name)
2038 Eet_File_Node *pefn;
2040 int exists_already = 0;
2042 /* check to see its' an eet file pointer */
2043 if (eet_check_pointer(ef))
2048 /* deleting keys is only possible in RW or WRITE mode */
2049 if (ef->mode == EET_FILE_MODE_READ)
2052 if (eet_check_header(ef))
2057 /* figure hash bucket */
2058 hash = _eet_hash_gen(name, ef->header->directory->size);
2060 /* Does this node already exist? */
2061 for (pefn = NULL, efn = ef->header->directory->nodes[hash];
2063 pefn = efn, efn = efn->next)
2066 if (eet_string_match(efn->name, name))
2072 ef->header->directory->nodes[hash] = efn->next;
2074 pefn->next = efn->next;
2076 if (efn->free_name) free(efn->name);
2082 /* flags that writes are pending */
2084 ef->writes_pending = 1;
2088 /* update access time */
2089 return exists_already;
2092 EAPI Eet_Dictionary *
2093 eet_dictionary_get(Eet_File *ef)
2095 if (eet_check_pointer(ef)) return NULL;
2102 eet_list(Eet_File *ef, const char *glob, int *count_ret)
2105 char **list_ret = NULL;
2107 int list_count_alloc = 0;
2110 /* check to see its' an eet file pointer */
2111 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2113 ((ef->mode != EET_FILE_MODE_READ) &&
2114 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2122 if (!strcmp(glob, "*")) glob = NULL;
2126 /* loop through all entries */
2127 num = (1 << ef->header->directory->size);
2128 for (i = 0; i < num; i++)
2130 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2132 /* if the entry matches the input glob
2133 * check for * explicitly, because on some systems, * isn't well
2136 if ((!glob) || !fnmatch(glob, efn->name, 0))
2138 /* add it to our list */
2141 /* only realloc in 32 entry chunks */
2142 if (list_count > list_count_alloc)
2144 char **new_list = NULL;
2146 list_count_alloc += 64;
2147 new_list = realloc(list_ret, list_count_alloc * (sizeof(char *)));
2154 list_ret = new_list;
2157 /* put pointer of name string in */
2158 list_ret[list_count - 1] = efn->name;
2165 /* return count and list */
2167 *count_ret = list_count;
2181 eet_num_entries(Eet_File *ef)
2183 int i, num, ret = 0;
2186 /* check to see its' an eet file pointer */
2187 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2188 ((ef->mode != EET_FILE_MODE_READ) &&
2189 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2194 /* loop through all entries */
2195 num = (1 << ef->header->directory->size);
2196 for (i = 0; i < num; i++)
2198 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2207 static Eet_File_Node *
2208 find_node_by_name(Eet_File *ef, const char *name)
2213 /* get hash bucket this should be in */
2214 hash = _eet_hash_gen(name, ef->header->directory->size);
2216 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2218 if (eet_string_match(efn->name, name))
2226 read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len)
2228 if (efn->offset < 0) return 0;
2232 if ((efn->offset + len) > ef->data_size) return 0;
2233 memcpy(buf, ef->data + efn->offset, len);
2237 /* seek to data location */
2238 if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
2242 len = fread(buf, len, 1, ef->fp);