3 #endif /* ifdef HAVE_CONFIG_H */
8 # define alloca __builtin_alloca
10 # define alloca __alloca
11 #elif defined _MSC_VER
13 # define alloca _alloca
14 #else /* ifdef HAVE_ALLOCA_H */
18 # endif /* ifdef __cplusplus */
20 #endif /* ifdef HAVE_ALLOCA_H */
23 # include <winsock2.h>
24 #endif /* ifdef _WIN32 */
28 #include <sys/types.h>
38 #endif /* ifdef HAVE_UNISTD_H */
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
42 #endif /* ifdef HAVE_NETINET_IN_H */
46 #endif /* ifdef HAVE_EVIL */
51 # include <gnutls/gnutls.h>
53 #endif /* ifdef HAVE_GNUTLS */
56 # include <openssl/err.h>
57 # include <openssl/evp.h>
58 #endif /* ifdef HAVE_OPENSSL */
60 #ifdef EINA_HAVE_THREADS
62 GCRY_THREAD_OPTION_PTHREAD_IMPL;
63 # endif /* ifdef HAVE_GNUTLS */
64 #endif /* ifdef EINA_HAVE_THREADS */
67 #include "Eet_private.h"
73 static Eet_Version _version = { VMAJ, VMIN, VMIC, VREV };
74 EAPI Eet_Version *eet_version = &_version;
78 #endif /* ifdef HAVE_REALPATH */
80 #define EET_MAGIC_FILE 0x1ee7ff00
81 #define EET_MAGIC_FILE_HEADER 0x1ee7ff01
83 #define EET_MAGIC_FILE2 0x1ee70f42
85 #define EET_FILE2_HEADER_COUNT 3
86 #define EET_FILE2_DIRECTORY_ENTRY_COUNT 6
87 #define EET_FILE2_DICTIONARY_ENTRY_COUNT 5
89 #define EET_FILE2_HEADER_SIZE (sizeof(int) * \
90 EET_FILE2_HEADER_COUNT)
91 #define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * \
92 EET_FILE2_DIRECTORY_ENTRY_COUNT)
93 #define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * \
94 EET_FILE2_DICTIONARY_ENTRY_COUNT)
96 /* prototypes of internal calls */
98 eet_cache_find(const char *path,
102 eet_cache_add(Eet_File *ef,
107 eet_cache_del(Eet_File *ef,
112 eet_string_match(const char *s1,
116 eet_flush(Eet_File *ef);
119 eet_flush2(Eet_File *ef);
120 static Eet_File_Node *
121 find_node_by_name(Eet_File *ef,
124 read_data_from_disk(Eet_File *ef,
130 eet_internal_close(Eet_File *ef,
133 static Eina_Lock eet_cache_lock;
135 #define LOCK_CACHE eina_lock_take(&eet_cache_lock)
136 #define UNLOCK_CACHE eina_lock_release(&eet_cache_lock)
138 #define INIT_FILE(File) eina_lock_new(&File->file_lock)
139 #define LOCK_FILE(File) eina_lock_take(&File->file_lock)
140 #define UNLOCK_FILE(File) eina_lock_release(&File->file_lock)
141 #define DESTROY_FILE(File) eina_lock_free(&File->file_lock)
143 /* cache. i don't expect this to ever be large, so arrays will do */
144 static int eet_writers_num = 0;
145 static int eet_writers_alloc = 0;
146 static Eet_File **eet_writers = NULL;
147 static int eet_readers_num = 0;
148 static int eet_readers_alloc = 0;
149 static Eet_File **eet_readers = NULL;
150 static int eet_init_count = 0;
152 /* log domain variable */
153 int _eet_log_dom_global = -1;
155 /* Check to see its' an eet file pointer */
157 eet_check_pointer(const Eet_File *ef)
159 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
166 eet_check_header(const Eet_File *ef)
171 if (!ef->header->directory)
178 eet_test_close(int test,
183 ef->delete_me_now = 1;
184 eet_internal_close(ef, EINA_TRUE);
190 /* find an eet file in the currently in use cache */
192 eet_cache_find(const char *path,
199 for (i = 0; i < cache_num; i++)
201 /* if matches real path - return it */
202 if (eet_string_match(cache[i]->path, path))
203 if (!cache[i]->delete_me_now)
211 /* add to end of cache */
212 /* this should only be called when the cache lock is already held */
214 eet_cache_add(Eet_File *ef,
219 Eet_File **new_cache;
223 new_cache_num = *cache_num;
224 if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */
226 Eet_File *del_ef = NULL;
230 for (i = 0; i < new_cache_num; i++)
232 if (new_cache[i]->references == 0)
234 del_ef = new_cache[i];
241 del_ef->delete_me_now = 1;
242 eet_internal_close(del_ef, EINA_TRUE);
247 new_cache_num = *cache_num;
248 new_cache_alloc = *cache_alloc;
250 if (new_cache_num > new_cache_alloc)
252 new_cache_alloc += 16;
253 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
256 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
261 new_cache[new_cache_num - 1] = ef;
263 *cache_num = new_cache_num;
264 *cache_alloc = new_cache_alloc;
267 /* delete from cache */
268 /* this should only be called when the cache lock is already held */
270 eet_cache_del(Eet_File *ef,
275 Eet_File **new_cache;
276 int new_cache_num, new_cache_alloc;
280 new_cache_num = *cache_num;
281 new_cache_alloc = *cache_alloc;
282 if (new_cache_num <= 0)
285 for (i = 0; i < new_cache_num; i++)
287 if (new_cache[i] == ef)
291 if (i >= new_cache_num)
295 for (j = i; j < new_cache_num; j++)
296 new_cache[j] = new_cache[j + 1];
298 if (new_cache_num <= (new_cache_alloc - 16))
300 new_cache_alloc -= 16;
301 if (new_cache_num > 0)
303 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
306 CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
318 *cache_num = new_cache_num;
319 *cache_alloc = new_cache_alloc;
322 /* internal string match. null friendly, catches same ptr */
324 eet_string_match(const char *s1,
327 /* both null- no match */
334 return !strcmp(s1, s2);
337 /* flush out writes to a v2 eet file */
339 eet_flush2(Eet_File *ef)
343 Eet_Error error = EET_ERROR_NONE;
344 int head[EET_FILE2_HEADER_COUNT];
345 int num_directory_entries = 0;
346 int num_dictionary_entries = 0;
347 int bytes_directory_entries = 0;
348 int bytes_dictionary_entries = 0;
349 int bytes_strings = 0;
351 int strings_offset = 0;
356 if (eet_check_pointer(ef))
357 return EET_ERROR_BAD_OBJECT;
359 if (eet_check_header(ef))
360 return EET_ERROR_EMPTY;
362 if (!ef->writes_pending)
363 return EET_ERROR_NONE;
365 if ((ef->mode == EET_FILE_MODE_READ_WRITE)
366 || (ef->mode == EET_FILE_MODE_WRITE))
370 /* opening for write - delete old copy of file right away */
372 fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
373 fp = fdopen(fd, "wb");
375 return EET_ERROR_NOT_WRITABLE;
377 fcntl(fd, F_SETFD, FD_CLOEXEC);
380 return EET_ERROR_NOT_WRITABLE;
382 /* calculate string base offset and data base offset */
383 num = (1 << ef->header->directory->size);
384 for (i = 0; i < num; ++i)
386 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
388 num_directory_entries++;
389 bytes_strings += strlen(efn->name) + 1;
394 num_dictionary_entries = ef->ed->count;
396 for (i = 0; i < num_dictionary_entries; ++i)
397 bytes_strings += ef->ed->all[i].len;
400 /* calculate section bytes size */
401 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE *
402 num_directory_entries + EET_FILE2_HEADER_SIZE;
403 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE *
404 num_dictionary_entries;
406 /* calculate per entry offset */
407 strings_offset = bytes_directory_entries + bytes_dictionary_entries;
408 data_offset = bytes_directory_entries + bytes_dictionary_entries +
411 for (i = 0; i < num; ++i)
413 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
415 efn->offset = data_offset;
416 data_offset += efn->size;
418 efn->name_offset = strings_offset;
419 strings_offset += efn->name_size;
423 /* calculate dictionary strings offset */
425 ef->ed->offset = strings_offset;
427 /* go thru and write the header */
428 head[0] = (int)htonl((unsigned int)EET_MAGIC_FILE2);
429 head[1] = (int)htonl((unsigned int)num_directory_entries);
430 head[2] = (int)htonl((unsigned int)num_dictionary_entries);
432 fseek(fp, 0, SEEK_SET);
433 if (fwrite(head, sizeof (head), 1, fp) != 1)
436 /* write directories entry */
437 for (i = 0; i < num; i++)
439 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
442 int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
444 flag = (efn->alias << 2) | (efn->ciphered << 1) | efn->compression;
446 ibuf[0] = (int)htonl((unsigned int)efn->offset);
447 ibuf[1] = (int)htonl((unsigned int)efn->size);
448 ibuf[2] = (int)htonl((unsigned int)efn->data_size);
449 ibuf[3] = (int)htonl((unsigned int)efn->name_offset);
450 ibuf[4] = (int)htonl((unsigned int)efn->name_size);
451 ibuf[5] = (int)htonl((unsigned int)flag);
453 if (fwrite(ibuf, sizeof(ibuf), 1, fp) != 1)
458 /* write dictionary */
461 int offset = strings_offset;
463 for (j = 0; j < ef->ed->count; ++j)
465 int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
467 sbuf[0] = (int)htonl((unsigned int)ef->ed->all[j].hash);
468 sbuf[1] = (int)htonl((unsigned int)offset);
469 sbuf[2] = (int)htonl((unsigned int)ef->ed->all[j].len);
470 sbuf[3] = (int)htonl((unsigned int)ef->ed->all[j].prev);
471 sbuf[4] = (int)htonl((unsigned int)ef->ed->all[j].next);
473 offset += ef->ed->all[j].len;
475 if (fwrite(sbuf, sizeof (sbuf), 1, fp) != 1)
480 /* write directories name */
481 for (i = 0; i < num; i++)
483 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
485 if (fwrite(efn->name, efn->name_size, 1, fp) != 1)
492 for (j = 0; j < ef->ed->count; ++j)
494 if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, fp) != 1)
499 for (i = 0; i < num; i++)
501 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
503 if (fwrite(efn->data, efn->size, 1, fp) != 1)
508 /* flush all write to the file. */
511 /* append signature if required */
514 error = eet_identity_sign(fp, ef->key);
515 if (error != EET_ERROR_NONE)
519 /* no more writes pending */
520 ef->writes_pending = 0;
524 return EET_ERROR_NONE;
531 case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
533 case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
535 case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
537 case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
539 default: error = EET_ERROR_WRITE_ERROR; break;
551 if (++eet_init_count != 1)
552 return eet_init_count;
555 return --eet_init_count;
557 _eet_log_dom_global = eina_log_domain_register("eet", EET_DEFAULT_LOG_COLOR);
558 if (_eet_log_dom_global < 0)
560 EINA_LOG_ERR("Eet Can not create a general log domain.");
564 eina_lock_new(&eet_cache_lock);
566 if (!eet_mempool_init())
568 EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
569 goto unregister_log_domain;
572 if (!eet_node_init())
574 EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
575 goto shutdown_mempool;
579 /* Before the library can be used, it must initialize itself if needed. */
580 if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
582 gcry_check_version(NULL);
583 /* Disable warning messages about problems with the secure memory subsystem.
584 This command should be run right after gcry_check_version. */
585 if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN))
586 goto shutdown_eet; /* This command is used to allocate a pool of secure memory and thus
587 enabling the use of secure memory. It also drops all extra privileges the
588 process has (i.e. if it is run as setuid (root)). If the argument nbytes
589 is 0, secure memory will be disabled. The minimum amount of secure memory
590 allocated is currently 16384 bytes; you may thus use a value of 1 to
591 request that default size. */
593 if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
595 "BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
598 # ifdef EINA_HAVE_THREADS
599 if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread))
601 "YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!");
603 # endif /* ifdef EINA_HAVE_THREADS */
604 if (gnutls_global_init())
607 #endif /* ifdef HAVE_GNUTLS */
609 ERR_load_crypto_strings();
610 OpenSSL_add_all_algorithms();
611 #endif /* ifdef HAVE_OPENSSL */
613 return eet_init_count;
620 eet_mempool_shutdown();
621 unregister_log_domain:
622 eina_log_domain_unregister(_eet_log_dom_global);
623 _eet_log_dom_global = -1;
626 return --eet_init_count;
632 if (--eet_init_count != 0)
633 return eet_init_count;
637 if (eet_writers_num || eet_readers_num)
639 Eet_File **closelist = NULL;
643 closelist = alloca((eet_writers_num + eet_readers_num)
644 * sizeof(Eet_File *));
645 for (i = 0; i < eet_writers_num; i++)
647 closelist[num++] = eet_writers[i];
648 eet_writers[i]->delete_me_now = 1;
651 for (i = 0; i < eet_readers_num; i++)
653 closelist[num++] = eet_readers[i];
654 eet_readers[i]->delete_me_now = 1;
657 for (i = 0; i < num; i++)
659 ERR("File '%s' is still open !", closelist[i]->path);
660 eet_internal_close(closelist[i], EINA_TRUE);
664 eet_mempool_shutdown();
666 eina_lock_free(&eet_cache_lock);
669 gnutls_global_deinit();
670 #endif /* ifdef HAVE_GNUTLS */
674 #endif /* ifdef HAVE_OPENSSL */
675 eina_log_domain_unregister(_eet_log_dom_global);
676 _eet_log_dom_global = -1;
679 return eet_init_count;
683 eet_sync(Eet_File *ef)
687 if (eet_check_pointer(ef))
688 return EET_ERROR_BAD_OBJECT;
690 if ((ef->mode != EET_FILE_MODE_WRITE) &&
691 (ef->mode != EET_FILE_MODE_READ_WRITE))
692 return EET_ERROR_NOT_WRITABLE;
694 if (!ef->writes_pending)
695 return EET_ERROR_NONE;
699 ret = eet_flush2(ef);
712 * We need to compute the list of eet file to close separately from the cache,
713 * due to eet_close removing them from the cache after each call.
716 for (i = 0; i < eet_writers_num; i++)
718 if (eet_writers[i]->references <= 0)
722 for (i = 0; i < eet_readers_num; i++)
724 if (eet_readers[i]->references <= 0)
730 Eet_File **closelist = NULL;
732 closelist = alloca(num * sizeof(Eet_File *));
734 for (i = 0; i < eet_writers_num; i++)
736 if (eet_writers[i]->references <= 0)
738 closelist[num] = eet_writers[i];
739 eet_writers[i]->delete_me_now = 1;
744 for (i = 0; i < eet_readers_num; i++)
746 if (eet_readers[i]->references <= 0)
748 closelist[num] = eet_readers[i];
749 eet_readers[i]->delete_me_now = 1;
754 for (i = 0; i < num; i++)
756 eet_internal_close(closelist[i], EINA_TRUE);
763 /* FIXME: MMAP race condition in READ_WRITE_MODE */
765 eet_internal_read2(Eet_File *ef)
767 const int *data = (const int *)ef->data;
768 const char *start = (const char *)ef->data;
770 unsigned long int bytes_directory_entries;
771 unsigned long int bytes_dictionary_entries;
772 unsigned long int signature_base_offset;
773 unsigned long int num_directory_entries;
774 unsigned long int num_dictionary_entries;
778 if (eet_test_close((int)ntohl(*data) != EET_MAGIC_FILE2, ef))
783 #define GET_INT(Value, Pointer, Index) \
785 Value = ntohl(*Pointer); \
787 Index += sizeof(int); \
790 /* get entries count and byte count */
791 GET_INT(num_directory_entries, data, idx);
792 /* get dictionary count and byte count */
793 GET_INT(num_dictionary_entries, data, idx);
795 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE *
796 num_directory_entries + EET_FILE2_HEADER_SIZE;
797 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE *
798 num_dictionary_entries;
800 /* we can't have > 0x7fffffff values here - invalid */
801 if (eet_test_close((num_directory_entries > 0x7fffffff), ef))
804 /* we can't have more bytes directory and bytes in dictionaries than the size of the file */
805 if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) >
809 /* allocate header */
810 ef->header = eet_file_header_calloc(1);
811 if (eet_test_close(!ef->header, ef))
814 ef->header->magic = EET_MAGIC_FILE_HEADER;
816 /* allocate directory block in ram */
817 ef->header->directory = eet_file_directory_calloc(1);
818 if (eet_test_close(!ef->header->directory, ef))
821 /* 8 bit hash table (256 buckets) */
822 ef->header->directory->size = 8;
823 /* allocate base hash table */
824 ef->header->directory->nodes =
825 calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
826 if (eet_test_close(!ef->header->directory->nodes, ef))
829 signature_base_offset = 0;
830 if (num_directory_entries == 0)
832 signature_base_offset = ef->data_size;
835 /* actually read the directory block - all of it, into ram */
836 for (i = 0; i < num_directory_entries; ++i)
840 unsigned long int name_offset;
841 unsigned long int name_size;
845 /* out directory block is inconsistent - we have overrun our */
846 /* dynamic block buffer before we finished scanning dir entries */
847 efn = eet_file_node_malloc(1);
848 if (eet_test_close(!efn, ef))
850 if (efn) eet_file_node_mp_free(efn); /* yes i know - we only get here if
851 * efn is null/0 -> trying to shut up
852 * warning tools like cppcheck */
856 /* get entrie header */
857 GET_INT(efn->offset, data, idx);
858 GET_INT(efn->size, data, idx);
859 GET_INT(efn->data_size, data, idx);
860 GET_INT(name_offset, data, idx);
861 GET_INT(name_size, data, idx);
862 GET_INT(flag, data, idx);
864 efn->compression = flag & 0x1 ? 1 : 0;
865 efn->ciphered = flag & 0x2 ? 1 : 0;
866 efn->alias = flag & 0x4 ? 1 : 0;
868 #define EFN_TEST(Test, Ef, Efn) \
869 if (eet_test_close(Test, Ef)) \
871 eet_file_node_mp_free(Efn); \
875 /* check data pointer position */
876 EFN_TEST(!((efn->size > 0)
877 && (efn->offset + efn->size <= ef->data_size)
878 && (efn->offset > bytes_dictionary_entries +
879 bytes_directory_entries)), ef, efn);
881 /* check name position */
882 EFN_TEST(!((name_size > 0)
883 && (name_offset + name_size < ef->data_size)
884 && (name_offset >= bytes_dictionary_entries +
885 bytes_directory_entries)), ef, efn);
887 name = start + name_offset;
889 /* check '\0' at the end of name string */
890 EFN_TEST(name[name_size - 1] != '\0', ef, efn);
893 efn->name = (char *)name;
894 efn->name_size = name_size;
896 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
897 efn->next = ef->header->directory->nodes[hash];
898 ef->header->directory->nodes[hash] = efn;
900 /* read-only mode, so currently we have no data loaded */
901 if (ef->mode == EET_FILE_MODE_READ)
902 efn->data = NULL; /* read-write mode - read everything into ram */
905 efn->data = malloc(efn->size);
907 memcpy(efn->data, ef->data + efn->offset, efn->size);
910 /* compute the possible position of a signature */
911 if (signature_base_offset < efn->offset + efn->size)
912 signature_base_offset = efn->offset + efn->size;
917 if (num_dictionary_entries)
919 const int *dico = (const int *)ef->data +
920 EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries +
921 EET_FILE2_HEADER_COUNT;
924 if (eet_test_close((num_dictionary_entries *
925 (int)EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) >
926 (bytes_dictionary_entries + bytes_directory_entries),
930 ef->ed = eet_dictionary_calloc(1);
931 if (eet_test_close(!ef->ed, ef))
934 ef->ed->all = calloc(1, num_dictionary_entries * sizeof(Eet_String));
935 if (eet_test_close(!ef->ed->all, ef))
938 ef->ed->count = num_dictionary_entries;
939 ef->ed->total = num_dictionary_entries;
940 ef->ed->start = start + bytes_dictionary_entries +
941 bytes_directory_entries;
942 ef->ed->end = ef->ed->start;
944 for (j = 0; j < ef->ed->count; ++j)
949 GET_INT(hash, dico, idx);
950 GET_INT(offset, dico, idx);
951 GET_INT(ef->ed->all[j].len, dico, idx);
952 GET_INT(ef->ed->all[j].prev, dico, idx);
953 GET_INT(ef->ed->all[j].next, dico, idx);
955 /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
956 So stick to int and check the value. */
957 if (eet_test_close(hash & 0xFFFFFF00, ef))
960 /* Check string position */
961 if (eet_test_close(!((ef->ed->all[j].len > 0)
963 (bytes_dictionary_entries +
964 bytes_directory_entries))
965 && (offset + ef->ed->all[j].len <
966 ef->data_size)), ef))
969 ef->ed->all[j].str = start + offset;
971 if (ef->ed->all[j].str + ef->ed->all[j].len > ef->ed->end)
972 ef->ed->end = ef->ed->all[j].str + ef->ed->all[j].len;
974 /* Check '\0' at the end of the string */
975 if (eet_test_close(ef->ed->all[j].str[ef->ed->all[j].len - 1] !=
979 ef->ed->all[j].hash = hash;
980 if (ef->ed->all[j].prev == -1)
981 ef->ed->hash[hash] = j;
983 /* compute the possible position of a signature */
984 if (signature_base_offset < offset + ef->ed->all[j].len)
985 signature_base_offset = offset + ef->ed->all[j].len;
989 /* Check if the file is signed */
992 ef->signature = NULL;
993 ef->signature_length = 0;
995 if (signature_base_offset < ef->data_size)
997 #ifdef HAVE_SIGNATURE
998 const unsigned char *buffer = ((const unsigned char *)ef->data) +
999 signature_base_offset;
1000 ef->x509_der = eet_identity_check(ef->data,
1001 signature_base_offset,
1005 ef->data_size - signature_base_offset,
1007 &ef->signature_length,
1010 if (eet_test_close(!ef->x509_der, ef))
1013 #else /* ifdef HAVE_SIGNATURE */
1015 "This file could be signed but you didn't compile the necessary code to check the signature.");
1016 #endif /* ifdef HAVE_SIGNATURE */
1022 #if EET_OLD_EET_FILE_FORMAT
1024 eet_internal_read1(Eet_File *ef)
1026 const unsigned char *dyn_buf = NULL;
1027 const unsigned char *p = NULL;
1028 unsigned long int byte_entries;
1029 unsigned long int num_entries;
1034 "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.",
1037 /* build header table if read mode */
1040 if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
1043 #define EXTRACT_INT(Value, Pointer, Index) \
1046 memcpy(&tmp, Pointer + Index, sizeof(int)); \
1047 Value = ntohl(tmp); \
1048 Index += sizeof(int); \
1051 /* get entries count and byte count */
1052 EXTRACT_INT(num_entries, ef->data, idx);
1053 EXTRACT_INT(byte_entries, ef->data, idx);
1055 /* we can't have <= 0 values here - invalid */
1056 if (eet_test_close((num_entries > 0x7fffffff) ||
1057 (byte_entries > 0x7fffffff), 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)) >
1066 ef->data_size), ef))
1069 /* allocate header */
1070 ef->header = eet_file_header_calloc(1);
1071 if (eet_test_close(!ef->header, ef))
1074 ef->header->magic = EET_MAGIC_FILE_HEADER;
1076 /* allocate directory block in ram */
1077 ef->header->directory = eet_file_directory_calloc(1);
1078 if (eet_test_close(!ef->header->directory, ef))
1081 /* 8 bit hash table (256 buckets) */
1082 ef->header->directory->size = 8;
1083 /* allocate base hash table */
1084 ef->header->directory->nodes =
1085 calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1086 if (eet_test_close(!ef->header->directory->nodes, ef))
1089 /* actually read the directory block - all of it, into ram */
1090 dyn_buf = ef->data + idx;
1092 /* parse directory block */
1095 for (i = 0; i < num_entries; i++)
1104 #define HEADER_SIZE (sizeof(int) * 5)
1106 /* out directory block is inconsistent - we have overrun our */
1107 /* dynamic block buffer before we finished scanning dir entries */
1108 if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
1111 /* allocate all the ram needed for this stored node accounting */
1112 efn = eet_file_node_malloc(1);
1113 if (eet_test_close(!efn, ef))
1115 if (efn) eet_file_node_mp_free(efn); /* yes i know - we only get here if
1116 * efn is null/0 -> trying to shut up
1117 * warning tools like cppcheck */
1121 /* get entrie header */
1122 EXTRACT_INT(efn->offset, p, indexn);
1123 EXTRACT_INT(efn->compression, p, indexn);
1124 EXTRACT_INT(efn->size, p, indexn);
1125 EXTRACT_INT(efn->data_size, p, indexn);
1126 EXTRACT_INT(name_size, p, indexn);
1128 efn->name_size = name_size;
1133 if (eet_test_close(efn->size <= 0, ef))
1135 eet_file_node_mp_free(efn);
1139 /* invalid name_size */
1140 if (eet_test_close(name_size <= 0, ef))
1142 eet_file_node_mp_free(efn);
1146 /* reading name would mean falling off end of dyn_buf - invalid */
1147 if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
1149 eet_file_node_mp_free(efn);
1153 /* This code is useless if we dont want backward compatibility */
1155 k > 0 && ((unsigned char)*(p + HEADER_SIZE + k)) != 0; --k)
1158 efn->free_name = ((unsigned char)*(p + HEADER_SIZE + k)) != 0;
1162 efn->name = malloc(sizeof(char) * name_size + 1);
1163 if (eet_test_close(!efn->name, ef))
1165 eet_file_node_mp_free(efn);
1169 strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
1170 efn->name[name_size] = 0;
1173 "File: %s is not up to date for key \"%s\" - needs rebuilding sometime",
1178 /* The only really useful peace of code for efn->name (no backward compatibility) */
1179 efn->name = (char *)((unsigned char *)(p + HEADER_SIZE));
1181 /* get hash bucket it should go in */
1182 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1183 efn->next = ef->header->directory->nodes[hash];
1184 ef->header->directory->nodes[hash] = efn;
1186 /* read-only mode, so currently we have no data loaded */
1187 if (ef->mode == EET_FILE_MODE_READ)
1188 efn->data = NULL; /* read-write mode - read everything into ram */
1191 data = malloc(efn->size);
1193 memcpy(data, ef->data + efn->offset, efn->size);
1199 p += HEADER_SIZE + name_size;
1204 #endif /* if EET_OLD_EET_FILE_FORMAT */
1207 * this should only be called when the cache lock is already held
1208 * (We could drop this restriction if we add a parameter to eet_test_close
1209 * that indicates if the lock is held or not. For now it is easiest
1210 * to just require that it is always held.)
1213 eet_internal_read(Eet_File *ef)
1215 const int *data = (const int *)ef->data;
1217 if (eet_test_close((ef->data == (void *)-1) || (!ef->data), ef))
1220 if (eet_test_close(ef->data_size < (int)sizeof(int) * 3, ef))
1223 switch (ntohl(*data))
1225 #if EET_OLD_EET_FILE_FORMAT
1226 case EET_MAGIC_FILE:
1227 return eet_internal_read1(ef);
1229 #endif /* if EET_OLD_EET_FILE_FORMAT */
1230 case EET_MAGIC_FILE2:
1231 return eet_internal_read2(ef);
1234 ef->delete_me_now = 1;
1235 eet_internal_close(ef, EINA_TRUE);
1243 eet_internal_close(Eet_File *ef,
1248 /* check to see its' an eet file pointer */
1249 if (eet_check_pointer(ef))
1250 return EET_ERROR_BAD_OBJECT;
1257 /* if its still referenced - dont go any further */
1258 if (ef->references > 0)
1260 /* flush any writes */
1261 if ((ef->mode == EET_FILE_MODE_WRITE) ||
1262 (ef->mode == EET_FILE_MODE_READ_WRITE))
1267 err = eet_flush2(ef);
1269 eet_identity_unref(ef->key);
1272 /* if not urgent to delete it - dont free it - leave it in cache */
1273 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
1276 /* remove from cache */
1277 if (ef->mode == EET_FILE_MODE_READ)
1278 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1279 else if ((ef->mode == EET_FILE_MODE_WRITE) ||
1280 (ef->mode == EET_FILE_MODE_READ_WRITE))
1281 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1283 /* we can unlock the cache now */
1292 if (ef->header->directory)
1294 if (ef->header->directory->nodes)
1298 num = (1 << ef->header->directory->size);
1299 for (i = 0; i < num; i++)
1303 while ((efn = ef->header->directory->nodes[i]))
1308 ef->header->directory->nodes[i] = efn->next;
1313 eet_file_node_mp_free(efn);
1316 free(ef->header->directory->nodes);
1319 eet_file_directory_mp_free(ef->header->directory);
1322 eet_file_header_mp_free(ef->header);
1325 eet_dictionary_free(ef->ed);
1333 eina_file_map_free(ef->readfp, (void *)ef->data);
1335 eina_file_close(ef->readfp);
1338 /* zero out ram for struct - caution tactic against stale memory use */
1339 memset(ef, 0, sizeof(Eet_File));
1342 eina_stringshare_del(ef->path);
1343 eet_file_mp_free(ef);
1350 return EET_ERROR_NONE;
1354 eet_memopen_read(const void *data,
1359 if (!data || size == 0)
1362 ef = eet_file_malloc(1);
1370 ef->magic = EET_MAGIC_FILE;
1372 ef->mode = EET_FILE_MODE_READ;
1374 ef->delete_me_now = 1;
1377 ef->data_size = size;
1379 ef->sha1_length = 0;
1381 /* eet_internal_read expects the cache lock to be held when it is called */
1383 ef = eet_internal_read(ef);
1389 eet_file_get(Eet_File *ef)
1391 if (eet_check_pointer(ef)) return NULL;
1396 eet_open(const char *file,
1402 unsigned long int size;
1407 /* find the current file handle in cache*/
1410 if (mode == EET_FILE_MODE_READ)
1412 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1417 ef->delete_me_now = 1;
1418 eet_internal_close(ef, EINA_TRUE);
1421 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1423 else if ((mode == EET_FILE_MODE_WRITE) ||
1424 (mode == EET_FILE_MODE_READ_WRITE))
1426 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1429 ef->delete_me_now = 1;
1431 eet_internal_close(ef, EINA_TRUE);
1434 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1437 /* try open the file based on mode */
1438 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1440 /* Prevent garbage in futur comparison. */
1441 fp = eina_file_open(file, EINA_FALSE);
1448 size = eina_file_size_get(fp);
1450 if (size < ((int)sizeof(int) * 3))
1452 eina_file_close(fp);
1461 if (!fp && mode == EET_FILE_MODE_READ)
1466 if (mode != EET_FILE_MODE_WRITE)
1475 if (ef && ef->readfp != fp)
1477 ef->delete_me_now = 1;
1479 eet_internal_close(ef, EINA_TRUE);
1485 /* reference it up and return it */
1487 eina_file_close(fp);
1494 file_len = strlen(file) + 1;
1496 /* Allocate struct for eet file and have it zero'd out */
1497 ef = eet_file_malloc(1);
1501 /* fill some of the members */
1505 ef->path = eina_stringshare_add_length(file, file_len);
1506 ef->magic = EET_MAGIC_FILE;
1510 ef->writes_pending = 0;
1511 ef->delete_me_now = 0;
1515 ef->sha1_length = 0;
1517 ef->ed = (mode == EET_FILE_MODE_WRITE)
1518 || (!ef->readfp && mode == EET_FILE_MODE_READ_WRITE) ?
1519 eet_dictionary_add() : NULL;
1522 (mode == EET_FILE_MODE_READ_WRITE || mode == EET_FILE_MODE_WRITE))
1525 /* if we can't open - bail out */
1526 if (eet_test_close(!ef->readfp, ef))
1529 /* if we opened for read or read-write */
1530 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1532 ef->data_size = size;
1533 ef->data = eina_file_map_all(fp, EINA_FILE_SEQUENTIAL);
1534 if (eet_test_close((ef->data == NULL), ef))
1537 ef = eet_internal_read(ef);
1544 if (ef->references == 1)
1546 if (ef->mode == EET_FILE_MODE_READ)
1547 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1548 else if ((ef->mode == EET_FILE_MODE_WRITE) ||
1549 (ef->mode == EET_FILE_MODE_READ_WRITE))
1550 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1562 eet_mode_get(Eet_File *ef)
1564 /* check to see its' an eet file pointer */
1565 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
1566 return EET_FILE_MODE_INVALID;
1572 eet_identity_x509(Eet_File *ef,
1579 *der_length = ef->x509_length;
1581 return ef->x509_der;
1585 eet_identity_signature(Eet_File *ef,
1586 int *signature_length)
1591 if (signature_length)
1592 *signature_length = ef->signature_length;
1594 return ef->signature;
1598 eet_identity_sha1(Eet_File *ef,
1602 ef->sha1 = eet_identity_compute_sha1(ef->data,
1607 *sha1_length = ef->sha1_length;
1613 eet_identity_set(Eet_File *ef,
1619 return EET_ERROR_BAD_OBJECT;
1623 eet_identity_ref(ef->key);
1624 eet_identity_unref(tmp);
1626 /* flags that writes are pending */
1627 ef->writes_pending = 1;
1629 return EET_ERROR_NONE;
1633 eet_close(Eet_File *ef)
1635 return eet_internal_close(ef, EINA_FALSE);
1639 eet_read_cipher(Eet_File *ef,
1642 const char *cipher_key)
1646 unsigned long int size = 0;
1651 /* check to see its' an eet file pointer */
1652 if (eet_check_pointer(ef))
1658 if ((ef->mode != EET_FILE_MODE_READ) &&
1659 (ef->mode != EET_FILE_MODE_READ_WRITE))
1662 /* no header, return NULL */
1663 if (eet_check_header(ef))
1668 /* hunt hash bucket */
1669 efn = find_node_by_name(ef, name);
1673 /* get size (uncompressed, if compressed at all) */
1674 size = efn->data_size;
1677 data = malloc(size);
1681 /* uncompressed data */
1682 if (efn->compression == 0)
1684 void *data_deciphered = NULL;
1685 unsigned int data_deciphered_sz = 0;
1686 /* if we already have the data in ram... copy that */
1688 if (efn->ciphered && efn->size > size)
1691 data = realloc(data, efn->size);
1695 memcpy(data, efn->data, size);
1697 if (!read_data_from_disk(ef, efn, data, size))
1700 if (efn->ciphered && cipher_key)
1702 if (eet_decipher(data, efn->size, cipher_key, strlen(cipher_key),
1703 &data_deciphered, &data_deciphered_sz))
1705 if (data_deciphered)
1706 free(data_deciphered);
1712 data = data_deciphered;
1713 size = data_deciphered_sz;
1716 /* compressed data */
1719 void *tmp_data = NULL;
1720 void *data_deciphered = NULL;
1721 unsigned int data_deciphered_sz = 0;
1723 int compr_size = efn->size;
1726 /* if we already have the data in ram... copy that */
1728 tmp_data = efn->data;
1731 tmp_data = malloc(compr_size);
1737 if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
1744 if (efn->ciphered && cipher_key)
1746 if (eet_decipher(tmp_data, compr_size, cipher_key,
1747 strlen(cipher_key), &data_deciphered,
1748 &data_deciphered_sz))
1753 if (data_deciphered)
1754 free(data_deciphered);
1762 tmp_data = data_deciphered;
1763 compr_size = data_deciphered_sz;
1768 if (uncompress((Bytef *)data, &dlen,
1769 tmp_data, (uLongf)compr_size))
1787 if (data[size - 1] != '\0')
1790 tmp = eet_read_cipher(ef, data, size_ret, cipher_key);
1797 /* fill in return values */
1810 eet_read(Eet_File *ef,
1814 return eet_read_cipher(ef, name, size_ret, NULL);
1818 eet_read_direct(Eet_File *ef,
1823 const char *data = NULL;
1829 /* check to see its' an eet file pointer */
1830 if (eet_check_pointer(ef))
1836 if ((ef->mode != EET_FILE_MODE_READ) &&
1837 (ef->mode != EET_FILE_MODE_READ_WRITE))
1840 /* no header, return NULL */
1841 if (eet_check_header(ef))
1846 /* hunt hash bucket */
1847 efn = find_node_by_name(ef, name);
1851 /* trick to detect data in memory instead of mmaped from disk */
1852 if (efn->offset > ef->data_size && !efn->data)
1855 /* get size (uncompressed, if compressed at all) */
1856 size = efn->data_size;
1860 data = efn->data ? efn->data : ef->data + efn->offset;
1862 /* handle alias case */
1863 if (efn->compression)
1866 int compr_size = efn->size;
1869 tmp = alloca(sizeof (compr_size));
1872 if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data,
1873 (uLongf)compr_size))
1876 if (tmp[compr_size - 1] != '\0')
1881 return eet_read_direct(ef, tmp, size_ret);
1887 if (data[size - 1] != '\0')
1892 return eet_read_direct(ef, data, size_ret);
1895 /* uncompressed data */
1896 if (efn->compression == 0
1897 && efn->ciphered == 0)
1898 data = efn->data ? efn->data : ef->data + efn->offset; /* compressed data */
1902 /* fill in return values */
1916 eet_alias_get(Eet_File *ef,
1920 const char *data = NULL;
1923 /* check to see its' an eet file pointer */
1924 if (eet_check_pointer(ef))
1930 if ((ef->mode != EET_FILE_MODE_READ) &&
1931 (ef->mode != EET_FILE_MODE_READ_WRITE))
1934 /* no header, return NULL */
1935 if (eet_check_header(ef))
1940 /* hunt hash bucket */
1941 efn = find_node_by_name(ef, name);
1945 /* trick to detect data in memory instead of mmaped from disk */
1946 if (efn->offset > ef->data_size && !efn->data)
1949 /* get size (uncompressed, if compressed at all) */
1950 size = efn->data_size;
1952 if (!efn->alias) return NULL;
1953 data = efn->data ? efn->data : ef->data + efn->offset;
1955 /* handle alias case */
1956 if (efn->compression)
1959 int compr_size = efn->size;
1962 tmp = alloca(sizeof (compr_size));
1965 if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data,
1966 (uLongf)compr_size))
1969 if (tmp[compr_size - 1] != '\0')
1974 return eina_stringshare_add(tmp);
1980 if (data[size - 1] != '\0')
1985 return eina_stringshare_add(data);
1993 eet_alias(Eet_File *ef,
1995 const char *destination,
2000 Eina_Bool exists_already = EINA_FALSE;
2004 /* check to see its' an eet file pointer */
2005 if (eet_check_pointer(ef))
2008 if ((!name) || (!destination))
2011 if ((ef->mode != EET_FILE_MODE_WRITE) &&
2012 (ef->mode != EET_FILE_MODE_READ_WRITE))
2019 /* allocate header */
2020 ef->header = eet_file_header_calloc(1);
2024 ef->header->magic = EET_MAGIC_FILE_HEADER;
2025 /* allocate directory block in ram */
2026 ef->header->directory = eet_file_directory_calloc(1);
2027 if (!ef->header->directory)
2029 eet_file_header_mp_free(ef->header);
2034 /* 8 bit hash table (256 buckets) */
2035 ef->header->directory->size = 8;
2036 /* allocate base hash table */
2037 ef->header->directory->nodes =
2038 calloc(1, sizeof(Eet_File_Node *) *
2039 (1 << ef->header->directory->size));
2040 if (!ef->header->directory->nodes)
2042 eet_file_directory_mp_free(ef->header->directory);
2048 /* figure hash bucket */
2049 hash = _eet_hash_gen(name, ef->header->directory->size);
2052 12 + (((strlen(destination) + 1) * 101) / 100)
2053 : strlen(destination) + 1;
2055 data2 = malloc(data_size);
2059 /* if we want to compress */
2064 /* compress the data with max compression */
2065 buflen = (uLongf)data_size;
2066 if (compress2((Bytef *)data2, &buflen, (Bytef *)destination,
2067 (uLong)strlen(destination) + 1,
2068 Z_BEST_COMPRESSION) != Z_OK)
2074 /* record compressed chunk size */
2075 data_size = (int)buflen;
2076 if (data_size < 0 || data_size >= (int)(strlen(destination) + 1))
2079 data_size = strlen(destination) + 1;
2085 data3 = realloc(data2, data_size);
2092 memcpy(data2, destination, data_size);
2094 /* Does this node already exist? */
2095 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2098 if ((efn->name) && (eet_string_match(efn->name, name)))
2103 efn->compression = !!comp;
2104 efn->size = data_size;
2105 efn->data_size = strlen(destination) + 1;
2107 /* Put the offset above the limit to avoid direct access */
2108 efn->offset = ef->data_size + 1;
2109 exists_already = EINA_TRUE;
2114 if (!exists_already)
2116 efn = eet_file_node_malloc(1);
2123 efn->name = strdup(name);
2124 efn->name_size = strlen(efn->name) + 1;
2127 efn->next = ef->header->directory->nodes[hash];
2128 ef->header->directory->nodes[hash] = efn;
2129 /* Put the offset above the limit to avoid direct access */
2130 efn->offset = ef->data_size + 1;
2133 efn->compression = !!comp;
2134 efn->size = data_size;
2135 efn->data_size = strlen(destination) + 1;
2139 /* flags that writes are pending */
2140 ef->writes_pending = 1;
2151 eet_write_cipher(Eet_File *ef,
2156 const char *cipher_key)
2160 int exists_already = 0;
2164 /* check to see its' an eet file pointer */
2165 if (eet_check_pointer(ef))
2168 if ((!name) || (!data) || (size <= 0))
2171 if ((ef->mode != EET_FILE_MODE_WRITE) &&
2172 (ef->mode != EET_FILE_MODE_READ_WRITE))
2179 /* allocate header */
2180 ef->header = eet_file_header_calloc(1);
2184 ef->header->magic = EET_MAGIC_FILE_HEADER;
2185 /* allocate directory block in ram */
2186 ef->header->directory = eet_file_directory_calloc(1);
2187 if (!ef->header->directory)
2189 eet_file_header_mp_free(ef->header);
2194 /* 8 bit hash table (256 buckets) */
2195 ef->header->directory->size = 8;
2196 /* allocate base hash table */
2197 ef->header->directory->nodes =
2198 calloc(1, sizeof(Eet_File_Node *) *
2199 (1 << ef->header->directory->size));
2200 if (!ef->header->directory->nodes)
2202 eet_file_directory_mp_free(ef->header->directory);
2208 /* figure hash bucket */
2209 hash = _eet_hash_gen(name, ef->header->directory->size);
2211 data_size = comp ? 12 + ((size * 101) / 100) : size;
2213 if (comp || !cipher_key)
2215 data2 = malloc(data_size);
2220 /* if we want to compress */
2225 /* compress the data with max compression */
2226 buflen = (uLongf)data_size;
2227 if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
2228 (uLong)size, Z_BEST_COMPRESSION) != Z_OK)
2234 /* record compressed chunk size */
2235 data_size = (int)buflen;
2236 if (data_size < 0 || data_size >= size)
2245 data3 = realloc(data2, data_size);
2253 void *data_ciphered = NULL;
2254 unsigned int data_ciphered_sz = 0;
2257 tmp = comp ? data2 : data;
2258 if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key),
2259 &data_ciphered, &data_ciphered_sz))
2264 data2 = data_ciphered;
2265 data_size = data_ciphered_sz;
2270 free(data_ciphered);
2277 memcpy(data2, data, size);
2279 /* Does this node already exist? */
2280 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2283 if ((efn->name) && (eet_string_match(efn->name, name)))
2287 efn->ciphered = cipher_key ? 1 : 0;
2288 efn->compression = !!comp;
2289 efn->size = data_size;
2290 efn->data_size = size;
2292 /* Put the offset above the limit to avoid direct access */
2293 efn->offset = ef->data_size + 1;
2298 if (!exists_already)
2300 efn = eet_file_node_malloc(1);
2307 efn->name = strdup(name);
2308 efn->name_size = strlen(efn->name) + 1;
2311 efn->next = ef->header->directory->nodes[hash];
2312 ef->header->directory->nodes[hash] = efn;
2313 /* Put the offset above the limit to avoid direct access */
2314 efn->offset = ef->data_size + 1;
2316 efn->ciphered = cipher_key ? 1 : 0;
2317 efn->compression = !!comp;
2318 efn->size = data_size;
2319 efn->data_size = size;
2323 /* flags that writes are pending */
2324 ef->writes_pending = 1;
2334 eet_write(Eet_File *ef,
2340 return eet_write_cipher(ef, name, data, size, comp, NULL);
2344 eet_delete(Eet_File *ef,
2348 Eet_File_Node *pefn;
2350 int exists_already = 0;
2352 /* check to see its' an eet file pointer */
2353 if (eet_check_pointer(ef))
2359 /* deleting keys is only possible in RW or WRITE mode */
2360 if (ef->mode == EET_FILE_MODE_READ)
2363 if (eet_check_header(ef))
2368 /* figure hash bucket */
2369 hash = _eet_hash_gen(name, ef->header->directory->size);
2371 /* Does this node already exist? */
2372 for (pefn = NULL, efn = ef->header->directory->nodes[hash];
2374 pefn = efn, efn = efn->next)
2377 if (eet_string_match(efn->name, name))
2383 ef->header->directory->nodes[hash] = efn->next;
2385 pefn->next = efn->next;
2390 eet_file_node_mp_free(efn);
2395 /* flags that writes are pending */
2397 ef->writes_pending = 1;
2401 /* update access time */
2402 return exists_already;
2405 EAPI Eet_Dictionary *
2406 eet_dictionary_get(Eet_File *ef)
2408 if (eet_check_pointer(ef))
2415 eet_list(Eet_File *ef,
2420 char **list_ret = NULL;
2422 int list_count_alloc = 0;
2425 /* check to see its' an eet file pointer */
2426 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2428 ((ef->mode != EET_FILE_MODE_READ) &&
2429 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2437 if (!strcmp(glob, "*"))
2442 /* loop through all entries */
2443 num = (1 << ef->header->directory->size);
2444 for (i = 0; i < num; i++)
2446 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2448 /* if the entry matches the input glob
2449 * check for * explicitly, because on some systems, * isn't well
2452 if ((!glob) || !fnmatch(glob, efn->name, 0))
2454 /* add it to our list */
2457 /* only realloc in 32 entry chunks */
2458 if (list_count > list_count_alloc)
2460 char **new_list = NULL;
2462 list_count_alloc += 64;
2464 realloc(list_ret, list_count_alloc * (sizeof(char *)));
2472 list_ret = new_list;
2475 /* put pointer of name string in */
2476 list_ret[list_count - 1] = efn->name;
2483 /* return count and list */
2485 *count_ret = list_count;
2499 eet_num_entries(Eet_File *ef)
2501 int i, num, ret = 0;
2504 /* check to see its' an eet file pointer */
2505 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2506 ((ef->mode != EET_FILE_MODE_READ) &&
2507 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2512 /* loop through all entries */
2513 num = (1 << ef->header->directory->size);
2514 for (i = 0; i < num; i++)
2516 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2525 static Eet_File_Node *
2526 find_node_by_name(Eet_File *ef,
2532 /* get hash bucket this should be in */
2533 hash = _eet_hash_gen(name, ef->header->directory->size);
2535 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2537 if (eet_string_match(efn->name, name))
2545 read_data_from_disk(Eet_File *ef,
2550 if (efn->offset > ef->data_size)
2556 if ((efn->offset + len) > ef->data_size)
2559 memcpy(buf, ef->data + efn->offset, len);