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>
46 #include <openssl/err.h>
49 #ifdef HAVE_NETINET_IN_H
50 # include <netinet/in.h>
58 # include <gnutls/gnutls.h>
63 # include <openssl/err.h>
64 # include <openssl/evp.h>
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 unsigned char writes_pending : 1;
111 unsigned char delete_me_now : 1;
114 struct _Eet_File_Header
117 Eet_File_Directory *directory;
120 struct _Eet_File_Directory
123 Eet_File_Node **nodes;
126 struct _Eet_File_Node
130 Eet_File_Node *next; /* FIXME: make buckets linked lists */
133 int dictionary_offset;
140 unsigned char free_name : 1;
141 unsigned char compression : 1;
142 unsigned char ciphered : 1;
148 /* NB: all int's are stored in network byte order on disk */
150 int magic; /* magic number ie 0x1ee7ff00 */
151 int num_directory_entries; /* number of directory entries to follow */
152 int bytes_directory_entries; /* bytes of directory entries to follow */
155 int offset; /* bytes offset into file for data chunk */
156 int flags; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */
157 int size; /* size of the data chunk */
158 int data_size; /* size of the (uncompressed) data chunk */
159 int name_size; /* length in bytes of the name field */
160 char name[name_size]; /* name string (variable length) and \0 terminated */
161 } directory[num_directory_entries];
162 /* and now startes the data stream... */
167 /* NB: all int's are stored in network byte order on disk */
169 int magic; /* magic number ie 0x1ee70f42 */
170 int num_directory_entries; /* number of directory entries to follow */
171 int num_dictionary_entries; /* number of dictionary entries to follow */
174 int data_offset; /* bytes offset into file for data chunk */
175 int size; /* size of the data chunk */
176 int data_size; /* size of the (uncompressed) data chunk */
177 int name_offset; /* bytes offset into file for name string */
178 int name_size; /* length in bytes of the name field */
179 int flags; /* flags - for now 0 = uncompressed, 1 = compressed */
180 } directory[num_directory_entries];
188 } dictionary[num_dictionary_entries];
189 /* now start the string stream. */
190 /* and right after them the data stream. */
191 int magic_sign; /* Optional, only if the eet file is signed. */
192 int signature_length; /* Signature length. */
193 int x509_length; /* Public certificate that signed the file. */
194 char signature[signature_length]; /* The signature. */
195 char x509[x509_length]; /* The public certificate. */
198 #define EET_FILE2_HEADER_COUNT 3
199 #define EET_FILE2_DIRECTORY_ENTRY_COUNT 6
200 #define EET_FILE2_DICTIONARY_ENTRY_COUNT 5
202 #define EET_FILE2_HEADER_SIZE (sizeof(int) * EET_FILE2_HEADER_COUNT)
203 #define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DIRECTORY_ENTRY_COUNT)
204 #define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * EET_FILE2_DICTIONARY_ENTRY_COUNT)
206 /* prototypes of internal calls */
207 static Eet_File *eet_cache_find(const char *path, Eet_File **cache, int cache_num);
208 static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
209 static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
210 static int eet_string_match(const char *s1, const char *s2);
212 static Eet_Error eet_flush(Eet_File *ef);
214 static Eet_Error eet_flush2(Eet_File *ef);
215 static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name);
216 static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
218 /* cache. i don't expect this to ever be large, so arrays will do */
219 static int eet_writers_num = 0;
220 static int eet_writers_alloc = 0;
221 static Eet_File **eet_writers = NULL;
222 static int eet_readers_num = 0;
223 static int eet_readers_alloc = 0;
224 static Eet_File **eet_readers = NULL;
225 static int eet_initcount = 0;
227 /* log domain variable */
228 int _eet_log_dom_global=-1;
230 /* Check to see its' an eet file pointer */
232 eet_check_pointer(const Eet_File *ef)
234 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
240 eet_check_header(const Eet_File *ef)
244 if (!ef->header->directory)
250 eet_test_close(int test, Eet_File *ef)
254 ef->delete_me_now = 1;
260 /* find an eet file in the currently in use cache */
262 eet_cache_find(const char *path, Eet_File **cache, int cache_num)
267 for (i = 0; i < cache_num; i++)
269 /* if matches real path - return it */
270 if (eet_string_match(cache[i]->path, path))
272 if (!cache[i]->delete_me_now)
281 /* add to end of cache */
283 eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
285 Eet_File **new_cache;
289 new_cache_num = *cache_num;
290 if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */
292 Eet_File *del_ef = NULL;
296 for (i = 0; i < new_cache_num; i++)
298 if (new_cache[i]->references == 0)
300 del_ef = new_cache[i];
307 del_ef->delete_me_now = 1;
313 new_cache_num = *cache_num;
314 new_cache_alloc = *cache_alloc;
316 if (new_cache_num > new_cache_alloc)
318 new_cache_alloc += 16;
319 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
322 CRITICAL("BAD ERROR! Eet realloc of cache list failed. Abort\n");
326 new_cache[new_cache_num - 1] = ef;
328 *cache_num = new_cache_num;
329 *cache_alloc = new_cache_alloc;
332 /* delete from cache */
334 eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
336 Eet_File **new_cache;
337 int new_cache_num, new_cache_alloc;
341 new_cache_num = *cache_num;
342 new_cache_alloc = *cache_alloc;
343 if (new_cache_num <= 0)
346 for (i = 0; i < new_cache_num; i++)
348 if (new_cache[i] == ef)
352 if (i >= new_cache_num)
356 for (j = i; j < new_cache_num; j++)
357 new_cache[j] = new_cache[j + 1];
359 if (new_cache_num <= (new_cache_alloc - 16))
361 new_cache_alloc -= 16;
362 if (new_cache_num > 0)
364 new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
367 CRITICAL("BAD ERROR! Eet realloc of cache list failed. Abort\n");
378 *cache_num = new_cache_num;
379 *cache_alloc = new_cache_alloc;
382 /* internal string match. null friendly, catches same ptr */
384 eet_string_match(const char *s1, const char *s2)
386 /* both null- no match */
387 if ((!s1) || (!s2)) return 0;
388 if (s1 == s2) return 1;
389 return (!strcmp(s1, s2));
392 /* flush out writes to a v2 eet file */
394 eet_flush2(Eet_File *ef)
397 Eet_Error error = EET_ERROR_NONE;
398 int head[EET_FILE2_HEADER_COUNT];
399 int num_directory_entries = 0;
400 int num_dictionary_entries = 0;
401 int bytes_directory_entries = 0;
402 int bytes_dictionary_entries = 0;
403 int bytes_strings = 0;
405 int strings_offset = 0;
410 if (eet_check_pointer(ef))
411 return EET_ERROR_BAD_OBJECT;
412 if (eet_check_header(ef))
413 return EET_ERROR_EMPTY;
414 if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
415 return EET_ERROR_NOT_WRITABLE;
416 if (!ef->writes_pending)
417 return EET_ERROR_NONE;
418 if (ef->mode == EET_FILE_MODE_READ_WRITE && ef->fp == NULL)
423 fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
424 ef->fp = fdopen(fd, "wb");
425 if (!ef->fp) return EET_ERROR_NOT_WRITABLE;
426 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
429 /* calculate string base offset and data base offset */
430 num = (1 << ef->header->directory->size);
431 for (i = 0; i < num; ++i)
433 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
435 num_directory_entries++;
436 bytes_strings += strlen(efn->name) + 1;
441 num_dictionary_entries = ef->ed->count;
443 for (i = 0; i < num_dictionary_entries; ++i)
444 bytes_strings += ef->ed->all[i].len;
447 /* calculate section bytes size */
448 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
449 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
451 /* calculate per entry offset */
452 strings_offset = bytes_directory_entries + bytes_dictionary_entries;
453 data_offset = bytes_directory_entries + bytes_dictionary_entries + bytes_strings;
455 for (i = 0; i < num; ++i)
457 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
459 efn->offset = data_offset;
460 data_offset += efn->size;
462 efn->name_offset = strings_offset;
463 strings_offset += efn->name_size;
467 /* calculate dictionary strings offset */
469 ef->ed->offset = strings_offset;
471 /* go thru and write the header */
472 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE2);
473 head[1] = (int) htonl ((unsigned int) num_directory_entries);
474 head[2] = (int) htonl ((unsigned int) num_dictionary_entries);
476 fseek(ef->fp, 0, SEEK_SET);
477 if (fwrite(head, sizeof (head), 1, ef->fp) != 1)
480 /* write directories entry */
481 for (i = 0; i < num; i++)
483 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
486 int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
488 flag = (efn->ciphered << 1) | efn->compression;
490 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
491 ibuf[1] = (int) htonl ((unsigned int) efn->size);
492 ibuf[2] = (int) htonl ((unsigned int) efn->data_size);
493 ibuf[3] = (int) htonl ((unsigned int) efn->name_offset);
494 ibuf[4] = (int) htonl ((unsigned int) efn->name_size);
495 ibuf[5] = (int) htonl ((unsigned int) flag);
497 if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
502 /* write dictionnary */
505 int offset = strings_offset;
507 for (j = 0; j < ef->ed->count; ++j)
509 int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
511 sbuf[0] = (int) htonl ((unsigned int) ef->ed->all[j].hash);
512 sbuf[1] = (int) htonl ((unsigned int) offset);
513 sbuf[2] = (int) htonl ((unsigned int) ef->ed->all[j].len);
514 sbuf[3] = (int) htonl ((unsigned int) ef->ed->all[j].prev);
515 sbuf[4] = (int) htonl ((unsigned int) ef->ed->all[j].next);
517 offset += ef->ed->all[j].len;
519 if (fwrite(sbuf, sizeof (sbuf), 1, ef->fp) != 1)
524 /* write directories name */
525 for (i = 0; i < num; i++)
527 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
529 if (fwrite(efn->name, efn->name_size, 1, ef->fp) != 1)
537 for (j = 0; j < ef->ed->count; ++j)
539 if (ef->ed->all[j].str)
541 if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, ef->fp) != 1)
546 if (fwrite(ef->ed->all[j].mmap, ef->ed->all[j].len, 1, ef->fp) != 1)
553 for (i = 0; i < num; i++)
555 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
557 if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
562 /* flush all write to the file. */
564 // this is going to really cause trouble. if ANYTHING this needs to go into a
565 // thread spawned off - but even then...
566 // in this case... ext4 is "wrong". (yes we can jump up and down and point posix
567 // manual pages at eachother, but ext4 broke behavior that has been in place
568 // for decades and that 1000's of apps rely on daily - that is that one operation
569 // to disk is committed to disk BEFORE following operations, so the fs retains
570 // a consistent state
571 // fsync(fileno(ef->fp));
573 /* append signature if required */
576 error = eet_identity_sign(ef->fp, ef->key);
577 if (error != EET_ERROR_NONE)
581 /* no more writes pending */
582 ef->writes_pending = 0;
584 return EET_ERROR_NONE;
591 case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
592 case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
593 case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
594 case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
595 default: error = EET_ERROR_WRITE_ERROR; break;
599 if (ef->fp) fclose(ef->fp);
605 /* flush out writes to an eet file */
607 eet_flush(Eet_File *ef)
617 /* check to see its' an eet file pointer */
618 if (eet_check_pointer(ef))
619 return EET_ERROR_BAD_OBJECT;
620 if (eet_check_header(ef))
621 return EET_ERROR_EMPTY;
622 if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
623 return EET_ERROR_NOT_WRITABLE;
624 if (!ef->writes_pending)
625 return EET_ERROR_NONE;
627 /* calculate total size in bytes of directory block */
628 num = (1 << ef->header->directory->size);
629 for (i = 0; i < num; i++)
631 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
633 size += 20 + strlen(efn->name) + 1;
638 /* calculate offsets per entry */
640 for (i = 0; i < num; i++)
642 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
644 efn->offset = 12 + size + offset;
649 /* go thru and write the header */
650 head[0] = (int) htonl ((unsigned int) EET_MAGIC_FILE);
651 head[1] = (int) htonl ((unsigned int) count);
652 head[2] = (int) htonl ((unsigned int) size);
654 fseek(ef->fp, 0, SEEK_SET);
655 if (fwrite(head, 12, 1, ef->fp) != 1)
658 for (i = 0; i < num; i++)
660 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
662 unsigned int ibuf[5];
665 name_size = strlen(efn->name) + 1;
667 ibuf[0] = (int) htonl ((unsigned int) efn->offset);
668 ibuf[1] = (int) htonl ((unsigned int) efn->compression);
669 ibuf[2] = (int) htonl ((unsigned int) efn->size);
670 ibuf[3] = (int) htonl ((unsigned int) efn->data_size);
671 ibuf[4] = (int) htonl ((unsigned int) name_size);
674 if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
676 if (fwrite(efn->name, name_size, 1, ef->fp) != 1)
682 for (i = 0; i < num; i++)
684 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
686 if (fwrite(efn->data, efn->size, 1, ef->fp) != 1)
691 /* no more writes pending */
692 ef->writes_pending = 0;
694 return EET_ERROR_NONE;
704 return EET_ERROR_WRITE_ERROR_FILE_TOO_BIG;
708 return EET_ERROR_WRITE_ERROR_IO_ERROR;
712 return EET_ERROR_WRITE_ERROR_OUT_OF_SPACE;
716 return EET_ERROR_WRITE_ERROR_FILE_CLOSED;
720 return EET_ERROR_WRITE_ERROR;
724 if (ef->fp) fclose(ef->fp);
726 return EET_ERROR_WRITE_ERROR;
735 if (eet_initcount > 1) return eet_initcount;
738 /* Before the library can be used, it must initialize itself if needed. */
739 if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P) == 0)
741 gcry_check_version(NULL);
742 /* Disable warning messages about problems with the secure memory subsystem.
743 This command should be run right after gcry_check_version. */
744 if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN))
745 return --eet_initcount;
746 /* This command is used to allocate a pool of secure memory and thus
747 enabling the use of secure memory. It also drops all extra privileges the
748 process has (i.e. if it is run as setuid (root)). If the argument nbytes
749 is 0, secure memory will be disabled. The minimum amount of secure memory
750 allocated is currently 16384 bytes; you may thus use a value of 1 to
751 request that default size. */
752 if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
753 fprintf(stderr, "BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
755 if (gnutls_global_init())
756 return --eet_initcount;
759 ERR_load_crypto_strings();
760 OpenSSL_add_all_algorithms();
765 fprintf(stderr,"Eet: Eina init failed");
766 goto erro_eet_eina_init;
768 _eet_log_dom_global = eina_log_domain_register("Eet",EET_DEFAULT_LOG_COLOR);
769 if(_eet_log_dom_global < 0)
771 fprintf(stderr,"Eet Can not create a general log domain");
772 goto error_eet_eina_log;
774 return eet_initcount;
779 gnutls_global_deinit();
793 if (eet_initcount > 0) return eet_initcount;
796 eina_log_domain_unregister(_eet_log_dom_global);
799 gnutls_global_deinit();
806 return eet_initcount;
816 * We need to compute the list of eet file to close separately from the cache,
817 * due to eet_close removing them from the cache after each call.
819 for (i = 0; i < eet_writers_num; i++)
821 if (eet_writers[i]->references <= 0) num++;
824 for (i = 0; i < eet_readers_num; i++)
826 if (eet_readers[i]->references <= 0) num++;
831 Eet_File **closelist = NULL;
833 closelist = alloca(num * sizeof(Eet_File *));
835 for (i = 0; i < eet_writers_num; i++)
837 if (eet_writers[i]->references <= 0)
839 closelist[num] = eet_writers[i];
840 eet_writers[i]->delete_me_now = 1;
845 for (i = 0; i < eet_readers_num; i++)
847 if (eet_readers[i]->references <= 0)
849 closelist[num] = eet_readers[i];
850 eet_readers[i]->delete_me_now = 1;
855 for (i = 0; i < num; i++)
857 eet_close(closelist[i]);
862 /* FIXME: MMAP race condition in READ_WRITE_MODE */
864 eet_internal_read2(Eet_File *ef)
866 const int *data = (const int*) ef->data;
867 const char *start = (const char*) ef->data;
869 int num_directory_entries;
870 int bytes_directory_entries;
871 int num_dictionary_entries;
872 int bytes_dictionary_entries;
873 int signature_base_offset;
876 index += sizeof(int);
877 if (eet_test_close((int) ntohl(*data) != EET_MAGIC_FILE2, ef))
881 #define GET_INT(Value, Pointer, Index) \
883 Value = ntohl(*Pointer); \
885 Index += sizeof(int); \
888 /* get entries count and byte count */
889 GET_INT(num_directory_entries, data, index);
890 /* get dictionary count and byte count */
891 GET_INT(num_dictionary_entries, data, index);
893 bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE * num_directory_entries + EET_FILE2_HEADER_SIZE;
894 bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE * num_dictionary_entries;
896 /* we cant have <= 0 values here - invalid */
897 if (eet_test_close((num_directory_entries <= 0), ef))
900 /* we cant have more bytes directory and bytes in dictionaries than the size of the file */
901 if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) > ef->data_size, ef))
904 /* allocate header */
905 ef->header = calloc(1, sizeof(Eet_File_Header));
906 if (eet_test_close(!ef->header, ef))
909 ef->header->magic = EET_MAGIC_FILE_HEADER;
911 /* allocate directory block in ram */
912 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
913 if (eet_test_close(!ef->header->directory, ef))
916 /* 8 bit hash table (256 buckets) */
917 ef->header->directory->size = 8;
918 /* allocate base hash table */
919 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
920 if (eet_test_close(!ef->header->directory->nodes, ef))
923 signature_base_offset = 0;
925 /* actually read the directory block - all of it, into ram */
926 for (i = 0; i < num_directory_entries; ++i)
935 /* out directory block is inconsistent - we have oveerun our */
936 /* dynamic block buffer before we finished scanning dir entries */
937 efn = malloc (sizeof(Eet_File_Node));
938 if (eet_test_close(!efn, ef))
941 /* get entrie header */
942 GET_INT(efn->offset, data, index);
943 GET_INT(efn->size, data, index);
944 GET_INT(efn->data_size, data, index);
945 GET_INT(name_offset, data, index);
946 GET_INT(name_size, data, index);
947 GET_INT(flag, data, index);
949 efn->compression = flag & 0x1 ? 1 : 0;
950 efn->ciphered = flag & 0x2 ? 1 : 0;
952 #define EFN_TEST(Test, Ef, Efn) \
953 if (eet_test_close(Test, Ef)) \
959 /* check data pointer position */
960 EFN_TEST(!((efn->size > 0)
961 && (efn->offset + efn->size <= ef->data_size)
962 && (efn->offset > bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
964 /* check name position */
965 EFN_TEST(!((name_size > 0)
966 && (name_offset + name_size < ef->data_size)
967 && (name_offset >= bytes_dictionary_entries + bytes_directory_entries)), ef, efn);
969 name = start + name_offset;
971 /* check '\0' at the end of name string */
972 EFN_TEST(name[name_size - 1] != '\0', ef, efn);
975 efn->name = (char*) name;
976 efn->name_size = name_size;
978 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
979 efn->next = ef->header->directory->nodes[hash];
980 ef->header->directory->nodes[hash] = efn;
982 /* read-only mode, so currently we have no data loaded */
983 if (ef->mode == EET_FILE_MODE_READ)
985 /* read-write mode - read everything into ram */
988 efn->data = malloc(efn->size);
990 memcpy(efn->data, ef->data + efn->offset, efn->size);
993 /* compute the possible position of a signature */
994 if (signature_base_offset < efn->offset + efn->size)
995 signature_base_offset = efn->offset + efn->size;
1000 if (num_dictionary_entries)
1002 const int *dico = (const int*) ef->data + EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries + EET_FILE2_HEADER_COUNT;
1005 if (eet_test_close((num_dictionary_entries * (int) EET_FILE2_DICTIONARY_ENTRY_SIZE + index) > (bytes_dictionary_entries + bytes_directory_entries), ef))
1008 ef->ed = calloc(1, sizeof (Eet_Dictionary));
1009 if (eet_test_close(!ef->ed, ef)) return NULL;
1011 ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String));
1012 if (eet_test_close(!ef->ed->all, ef)) return NULL;
1014 ef->ed->count = num_dictionary_entries;
1015 ef->ed->total = num_dictionary_entries;
1016 ef->ed->start = start + bytes_dictionary_entries + bytes_directory_entries;
1017 ef->ed->end = ef->ed->start;
1019 for (j = 0; j < ef->ed->count; ++j)
1024 GET_INT(hash, dico, index);
1025 GET_INT(offset, dico, index);
1026 GET_INT(ef->ed->all[j].len, dico, index);
1027 GET_INT(ef->ed->all[j].prev, dico, index);
1028 GET_INT(ef->ed->all[j].next, dico, index);
1030 /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
1031 So stick to int and check the value. */
1032 if (eet_test_close(hash & 0xFFFFFF00, ef)) return NULL;
1034 /* Check string position */
1035 if (eet_test_close(!((ef->ed->all[j].len > 0)
1036 && (offset > (bytes_dictionary_entries + bytes_directory_entries))
1037 && (offset + ef->ed->all[j].len < ef->data_size)), ef))
1040 ef->ed->all[j].mmap = start + offset;
1041 ef->ed->all[j].str = NULL;
1043 if (ef->ed->all[j].mmap + ef->ed->all[j].len > ef->ed->end)
1044 ef->ed->end = ef->ed->all[j].mmap + ef->ed->all[j].len;
1046 /* Check '\0' at the end of the string */
1047 if (eet_test_close(ef->ed->all[j].mmap[ef->ed->all[j].len - 1] != '\0', ef)) return NULL;
1049 ef->ed->all[j].hash = hash;
1050 if (ef->ed->all[j].prev == -1)
1051 ef->ed->hash[hash] = j;
1053 /* compute the possible position of a signature */
1054 if (signature_base_offset < offset + ef->ed->all[j].len)
1055 signature_base_offset = offset + ef->ed->all[j].len;
1059 /* Check if the file is signed */
1060 ef->x509_der = NULL;
1061 ef->x509_length = 0;
1062 ef->signature = NULL;
1063 ef->signature_length = 0;
1065 if (signature_base_offset < ef->data_size)
1067 #ifdef HAVE_SIGNATURE
1068 const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset;
1069 ef->x509_der = eet_identity_check(ef->data, signature_base_offset,
1070 &ef->sha1, &ef->sha1_length,
1071 buffer, ef->data_size - signature_base_offset,
1072 &ef->signature, &ef->signature_length,
1075 if (eet_test_close(ef->x509_der == NULL, ef)) return NULL;
1077 ERROR("This file could be signed but you didn't compile the necessary code to check the signature.\n");
1084 #if EET_OLD_EET_FILE_FORMAT
1086 eet_internal_read1(Eet_File *ef)
1088 const unsigned char *dyn_buf = NULL;
1089 const unsigned char *p = NULL;
1095 WARN("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.\n", ef->path);
1097 /* build header table if read mode */
1099 index += sizeof(int);
1100 if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
1103 #define EXTRACT_INT(Value, Pointer, Index) \
1106 memcpy(&tmp, Pointer + Index, sizeof(int)); \
1107 Value = ntohl(tmp); \
1108 Index += sizeof(int); \
1111 /* get entries count and byte count */
1112 EXTRACT_INT(num_entries, ef->data, index);
1113 EXTRACT_INT(byte_entries, ef->data, index);
1115 /* we cant have <= 0 values here - invalid */
1116 if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef))
1119 /* we can't have more entires than minimum bytes for those! invalid! */
1120 if (eet_test_close((num_entries * 20) > byte_entries, ef))
1123 /* check we will not outrun the file limit */
1124 if (eet_test_close(((byte_entries + (int) sizeof(int) * 3) > ef->data_size), ef))
1127 /* allocate header */
1128 ef->header = calloc(1, sizeof(Eet_File_Header));
1129 if (eet_test_close(!ef->header, ef))
1132 ef->header->magic = EET_MAGIC_FILE_HEADER;
1134 /* allocate directory block in ram */
1135 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1136 if (eet_test_close(!ef->header->directory, ef))
1139 /* 8 bit hash table (256 buckets) */
1140 ef->header->directory->size = 8;
1141 /* allocate base hash table */
1142 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1143 if (eet_test_close(!ef->header->directory->nodes, ef))
1146 /* actually read the directory block - all of it, into ram */
1147 dyn_buf = ef->data + index;
1149 /* parse directory block */
1152 for (i = 0; i < num_entries; i++)
1161 #define HEADER_SIZE (sizeof(int) * 5)
1163 /* out directory block is inconsistent - we have oveerun our */
1164 /* dynamic block buffer before we finished scanning dir entries */
1165 if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
1168 /* allocate all the ram needed for this stored node accounting */
1169 efn = malloc (sizeof(Eet_File_Node));
1170 if (eet_test_close(!efn, ef))
1173 /* get entrie header */
1174 EXTRACT_INT(efn->offset, p, indexn);
1175 EXTRACT_INT(efn->compression, p, indexn);
1176 EXTRACT_INT(efn->size, p, indexn);
1177 EXTRACT_INT(efn->data_size, p, indexn);
1178 EXTRACT_INT(name_size, p, indexn);
1180 efn->name_size = name_size;
1184 if (eet_test_close(efn->size <= 0, ef))
1190 /* invalid name_size */
1191 if (eet_test_close(name_size <= 0, ef))
1197 /* reading name would mean falling off end of dyn_buf - invalid */
1198 if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
1204 /* This code is useless if we dont want backward compatibility */
1205 for (k = name_size; k > 0 && ((unsigned char) * (p + HEADER_SIZE + k)) != 0; --k)
1208 efn->free_name = ((unsigned char) * (p + HEADER_SIZE + k)) != 0;
1212 efn->name = malloc(sizeof(char) * name_size + 1);
1213 if (eet_test_close(efn->name == NULL, ef))
1219 strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
1220 efn->name[name_size] = 0;
1222 WARN("File: %s is not up to date for key \"%s\" - needs rebuilding sometime\n", ef->path, efn->name);
1225 /* The only really usefull peace of code for efn->name (no backward compatibility) */
1226 efn->name = (char*)((unsigned char*)(p + HEADER_SIZE));
1228 /* get hash bucket it should go in */
1229 hash = _eet_hash_gen(efn->name, ef->header->directory->size);
1230 efn->next = ef->header->directory->nodes[hash];
1231 ef->header->directory->nodes[hash] = efn;
1233 /* read-only mode, so currently we have no data loaded */
1234 if (ef->mode == EET_FILE_MODE_READ)
1236 /* read-write mode - read everything into ram */
1239 data = malloc(efn->size);
1241 memcpy(data, ef->data + efn->offset, efn->size);
1245 p += HEADER_SIZE + name_size;
1252 eet_internal_read(Eet_File *ef)
1254 const int *data = (const int*) ef->data;
1256 if (eet_test_close((ef->data == (void *)-1) || (ef->data == NULL), ef))
1259 if (eet_test_close(ef->data_size < (int) sizeof(int) * 3, ef))
1262 switch (ntohl(*data))
1264 #if EET_OLD_EET_FILE_FORMAT
1265 case EET_MAGIC_FILE:
1266 return eet_internal_read1(ef);
1268 case EET_MAGIC_FILE2:
1269 return eet_internal_read2(ef);
1271 ef->delete_me_now = 1;
1280 eet_memopen_read(const void *data, size_t size)
1284 if (data == NULL || size == 0)
1287 ef = malloc (sizeof (Eet_File));
1294 ef->magic = EET_MAGIC_FILE;
1296 ef->mode = EET_FILE_MODE_READ;
1299 ef->delete_me_now = 1;
1303 ef->data_size = size;
1305 ef->sha1_length = 0;
1307 return eet_internal_read(ef);
1311 eet_open(const char *file, Eet_File_Mode mode)
1316 struct stat file_stat;
1321 /* find the current file handle in cache*/
1323 if (mode == EET_FILE_MODE_READ)
1325 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1330 ef->delete_me_now = 1;
1333 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1335 else if ((mode == EET_FILE_MODE_WRITE) ||
1336 (mode == EET_FILE_MODE_READ_WRITE))
1338 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
1341 ef->delete_me_now = 1;
1345 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
1348 /* try open the file based on mode */
1349 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1351 fp = fopen(file, "rb");
1352 if (!fp) goto on_error;
1353 if (fstat(fileno(fp), &file_stat))
1359 if ((mode == EET_FILE_MODE_READ) &&
1360 (file_stat.st_size < ((int) sizeof(int) * 3)))
1368 if (fp == NULL && mode == EET_FILE_MODE_READ) return NULL;
1374 if (mode != EET_FILE_MODE_WRITE) return NULL;
1375 memset(&file_stat, 0, sizeof(file_stat));
1376 /* opening for write - delete old copy of file right away */
1378 fd = open(file, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
1379 fp = fdopen(fd, "wb");
1380 if (!fp) return NULL;
1384 if (ef && (file_stat.st_mtime != ef->mtime))
1386 ef->delete_me_now = 1;
1394 /* reference it up and return it */
1395 if (fp != NULL) fclose(fp);
1400 file_len = strlen(file) + 1;
1402 /* Allocate struct for eet file and have it zero'd out */
1403 ef = malloc(sizeof(Eet_File) + file_len);
1407 /* fill some of the members */
1411 ef->path = ((char *)ef) + sizeof(Eet_File);
1412 memcpy(ef->path, file, file_len);
1413 ef->magic = EET_MAGIC_FILE;
1417 ef->mtime = file_stat.st_mtime;
1418 ef->writes_pending = 0;
1419 ef->delete_me_now = 0;
1423 ef->sha1_length = 0;
1425 ef->ed = (mode == EET_FILE_MODE_WRITE)
1426 || (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) ?
1427 eet_dictionary_add() : NULL;
1429 if (ef->fp == NULL && mode == EET_FILE_MODE_READ_WRITE) goto empty_file;
1431 /* if we can't open - bail out */
1432 if (eet_test_close(!ef->fp, ef))
1435 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
1436 /* if we opened for read or read-write */
1437 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
1439 ef->data_size = file_stat.st_size;
1440 ef->data = mmap(NULL, ef->data_size, PROT_READ,
1441 MAP_SHARED, fileno(ef->fp), 0);
1442 if (eet_test_close((ef->data == MAP_FAILED), ef))
1444 ef = eet_internal_read(ef);
1450 /* we need to delete the original file in read-write mode and re-open for writing */
1451 if (ef->mode == EET_FILE_MODE_READ_WRITE)
1453 ef->readfp = ef->fp;
1458 if (ef->references == 1)
1460 if (ef->mode == EET_FILE_MODE_READ)
1461 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1463 if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1464 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1471 eet_mode_get(Eet_File *ef)
1473 /* check to see its' an eet file pointer */
1474 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
1475 return EET_FILE_MODE_INVALID;
1481 eet_identity_x509(Eet_File *ef, int *der_length)
1483 if (!ef->x509_der) return NULL;
1485 if (der_length) *der_length = ef->x509_length;
1486 return ef->x509_der;
1490 eet_identity_signature(Eet_File *ef, int *signature_length)
1492 if (!ef->signature) return NULL;
1494 if (signature_length) *signature_length = ef->signature_length;
1495 return ef->signature;
1499 eet_identity_sha1(Eet_File *ef, int *sha1_length)
1502 ef->sha1 = eet_identity_compute_sha1(ef->data, ef->data_size, &ef->sha1_length);
1504 if (sha1_length) *sha1_length = ef->sha1_length;
1509 eet_identity_set(Eet_File *ef, Eet_Key *key)
1511 Eet_Key *tmp = ef->key;
1513 if (!ef) return EET_ERROR_BAD_OBJECT;
1516 eet_identity_ref(ef->key);
1517 eet_identity_unref(tmp);
1519 /* flags that writes are pending */
1520 ef->writes_pending = 1;
1522 return EET_ERROR_NONE;
1526 eet_close(Eet_File *ef)
1530 /* check to see its' an eet file pointer */
1531 if (eet_check_pointer(ef))
1532 return EET_ERROR_BAD_OBJECT;
1535 /* if its still referenced - dont go any further */
1536 if (ef->references > 0) return EET_ERROR_NONE;
1537 /* flush any writes */
1538 err = eet_flush2(ef);
1540 eet_identity_unref(ef->key);
1543 /* if not urgent to delete it - dont free it - leave it in cache */
1544 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
1545 return EET_ERROR_NONE;
1547 /* remove from cache */
1548 if (ef->mode == EET_FILE_MODE_READ)
1549 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
1550 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
1551 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
1556 if (ef->header->directory)
1558 if (ef->header->directory->nodes)
1562 num = (1 << ef->header->directory->size);
1563 for (i = 0; i < num; i++)
1567 while ((efn = ef->header->directory->nodes[i]))
1572 ef->header->directory->nodes[i] = efn->next;
1580 free(ef->header->directory->nodes);
1582 free(ef->header->directory);
1587 eet_dictionary_free(ef->ed);
1589 if (ef->sha1) free(ef->sha1);
1590 if (ef->data) munmap((void*)ef->data, ef->data_size);
1591 if (ef->fp) fclose(ef->fp);
1592 if (ef->readfp) fclose(ef->readfp);
1594 /* zero out ram for struct - caution tactic against stale memory use */
1595 memset(ef, 0, sizeof(Eet_File));
1603 eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *cipher_key)
1612 /* check to see its' an eet file pointer */
1613 if (eet_check_pointer(ef))
1617 if ((ef->mode != EET_FILE_MODE_READ) &&
1618 (ef->mode != EET_FILE_MODE_READ_WRITE))
1621 /* no header, return NULL */
1622 if (eet_check_header(ef))
1625 /* hunt hash bucket */
1626 efn = find_node_by_name(ef, name);
1630 /* get size (uncompressed, if compressed at all) */
1631 size = efn->data_size;
1634 data = malloc(size);
1638 /* uncompressed data */
1639 if (efn->compression == 0)
1641 void *data_deciphered = NULL;
1642 unsigned int data_deciphered_sz = 0;
1643 /* if we alreayd have the data in ram... copy that */
1645 memcpy(data, efn->data, efn->size);
1647 if (!read_data_from_disk(ef, efn, data, size))
1652 if (efn->ciphered && cipher_key)
1654 if (eet_decipher(data, size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1657 if (data_deciphered) free(data_deciphered);
1661 data = data_deciphered;
1662 size = data_deciphered_sz;
1665 /* compressed data */
1669 void *data_deciphered = NULL;
1670 unsigned int data_deciphered_sz = 0;
1672 int compr_size = efn->size;
1675 /* if we already have the data in ram... copy that */
1677 tmp_data = efn->data;
1680 tmp_data = malloc(compr_size);
1689 if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
1697 if (efn->ciphered && cipher_key)
1699 if (eet_decipher(tmp_data, compr_size, cipher_key, strlen(cipher_key), &data_deciphered, &data_deciphered_sz))
1702 if (free_tmp) free(tmp_data);
1703 if (data_deciphered) free(data_deciphered);
1707 tmp_data = data_deciphered;
1708 compr_size = data_deciphered_sz;
1713 if (uncompress((Bytef *)data, &dlen,
1714 tmp_data, (uLongf)compr_size))
1724 /* fill in return values */
1732 eet_read(Eet_File *ef, const char *name, int *size_ret)
1734 return eet_read_cipher(ef, name, size_ret, NULL);
1738 eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
1740 const void *data = NULL;
1747 /* check to see its' an eet file pointer */
1748 if (eet_check_pointer(ef))
1752 if ((ef->mode != EET_FILE_MODE_READ) &&
1753 (ef->mode != EET_FILE_MODE_READ_WRITE))
1756 /* no header, return NULL */
1757 if (eet_check_header(ef))
1760 /* hunt hash bucket */
1761 efn = find_node_by_name(ef, name);
1765 if (efn->offset < 0 && efn->data == NULL)
1768 /* get size (uncompressed, if compressed at all) */
1769 size = efn->data_size;
1771 /* uncompressed data */
1772 if (efn->compression == 0
1773 && efn->ciphered == 0)
1774 data = efn->data ? efn->data : ef->data + efn->offset;
1775 /* compressed data */
1779 /* fill in return values */
1787 eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int compress, const char *cipher_key)
1791 int exists_already = 0;
1795 /* check to see its' an eet file pointer */
1796 if (eet_check_pointer(ef))
1798 if ((!name) || (!data) || (size <= 0))
1800 if ((ef->mode != EET_FILE_MODE_WRITE) &&
1801 (ef->mode != EET_FILE_MODE_READ_WRITE))
1806 /* allocate header */
1807 ef->header = calloc(1, sizeof(Eet_File_Header));
1811 ef->header->magic = EET_MAGIC_FILE_HEADER;
1812 /* allocate directory block in ram */
1813 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
1814 if (!ef->header->directory)
1817 /* 8 bit hash table (256 buckets) */
1818 ef->header->directory->size = 8;
1819 /* allocate base hash table */
1820 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
1821 if (!ef->header->directory->nodes)
1825 /* figure hash bucket */
1826 hash = _eet_hash_gen(name, ef->header->directory->size);
1828 data_size = compress ? 12 + ((size * 101) / 100) : size;
1830 if (compress || !cipher_key)
1832 data2 = malloc(data_size);
1837 /* if we want to compress */
1842 /* compress the data with max compression */
1843 buflen = (uLongf)data_size;
1844 if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
1845 (uLong)size, Z_BEST_COMPRESSION) != Z_OK)
1850 /* record compressed chunk size */
1851 data_size = (int)buflen;
1852 if (data_size < 0 || data_size >= size)
1861 data3 = realloc(data2, data_size);
1869 void *data_ciphered = NULL;
1870 unsigned int data_ciphered_sz = 0;
1873 tmp = data2 ? data2 : data;
1874 if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key), &data_ciphered, &data_ciphered_sz))
1876 if (data2) free(data2);
1877 data2 = data_ciphered;
1878 data_size = data_ciphered_sz;
1879 size = (data_size > size) ? data_size : size;
1883 if (data_ciphered) free(data_ciphered);
1889 memcpy(data2, data, size);
1891 /* Does this node already exist? */
1892 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
1895 if ((efn->name) && (eet_string_match(efn->name, name)))
1898 efn->ciphered = cipher_key ? 1 : 0;
1899 efn->compression = !!compress;
1900 efn->size = data_size;
1901 efn->data_size = size;
1908 if (!exists_already)
1910 efn = malloc(sizeof(Eet_File_Node));
1916 efn->name = strdup(name);
1917 efn->name_size = strlen(efn->name) + 1;
1920 efn->next = ef->header->directory->nodes[hash];
1921 ef->header->directory->nodes[hash] = efn;
1923 efn->ciphered = cipher_key ? 1 : 0;
1924 efn->compression = !!compress;
1925 efn->size = data_size;
1926 efn->data_size = size;
1930 /* flags that writes are pending */
1931 ef->writes_pending = 1;
1936 eet_write(Eet_File *ef, const char *name, const void *data, int size, int compress)
1938 return eet_write_cipher(ef, name, data, size, compress, NULL);
1942 eet_delete(Eet_File *ef, const char *name)
1945 Eet_File_Node *pefn;
1947 int exists_already = 0;
1949 /* check to see its' an eet file pointer */
1950 if (eet_check_pointer(ef))
1955 /* deleting keys is only possible in RW or WRITE mode */
1956 if (ef->mode == EET_FILE_MODE_READ)
1959 if (eet_check_header(ef))
1962 /* figure hash bucket */
1963 hash = _eet_hash_gen(name, ef->header->directory->size);
1965 /* Does this node already exist? */
1966 for (pefn = NULL, efn = ef->header->directory->nodes[hash];
1968 pefn = efn, efn = efn->next)
1971 if (eet_string_match(efn->name, name))
1977 ef->header->directory->nodes[hash] = efn->next;
1979 pefn->next = efn->next;
1981 if (efn->free_name) free(efn->name);
1987 /* flags that writes are pending */
1989 ef->writes_pending = 1;
1991 /* update access time */
1992 return exists_already;
1995 EAPI Eet_Dictionary *
1996 eet_dictionary_get(Eet_File *ef)
1998 if (eet_check_pointer(ef)) return NULL;
2005 eet_list(Eet_File *ef, const char *glob, int *count_ret)
2008 char **list_ret = NULL;
2010 int list_count_alloc = 0;
2013 /* check to see its' an eet file pointer */
2014 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2016 ((ef->mode != EET_FILE_MODE_READ) &&
2017 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2025 /* loop through all entries */
2026 num = (1 << ef->header->directory->size);
2027 for (i = 0; i < num; i++)
2029 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2031 /* if the entry matches the input glob
2032 * check for * explicitly, because on some systems, * isn't well
2035 if ((!strcmp (glob, "*")) || !fnmatch(glob, efn->name, 0))
2037 /* add it to our list */
2040 /* only realloc in 32 entry chunks */
2041 if (list_count > list_count_alloc)
2043 char **new_list = NULL;
2045 list_count_alloc += 64;
2046 new_list = realloc(list_ret, list_count_alloc * (sizeof(char *)));
2056 list_ret = new_list;
2059 /* put pointer of name string in */
2060 list_ret[list_count - 1] = efn->name;
2065 /* return count and list */
2067 *count_ret = list_count;
2073 eet_num_entries(Eet_File *ef)
2075 int i, num, ret = 0;
2078 /* check to see its' an eet file pointer */
2079 if (eet_check_pointer(ef) || eet_check_header(ef) ||
2080 ((ef->mode != EET_FILE_MODE_READ) &&
2081 (ef->mode != EET_FILE_MODE_READ_WRITE)))
2084 /* loop through all entries */
2085 num = (1 << ef->header->directory->size);
2086 for (i = 0; i < num; i++)
2088 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
2095 static Eet_File_Node *
2096 find_node_by_name(Eet_File *ef, const char *name)
2101 /* get hash bucket this should be in */
2102 hash = _eet_hash_gen(name, ef->header->directory->size);
2104 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
2106 if (eet_string_match(efn->name, name))
2114 read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len)
2116 if (efn->offset < 0) return 0;
2120 if ((efn->offset + len) > ef->data_size) return 0;
2121 memcpy(buf, ef->data + efn->offset, len);
2125 /* seek to data location */
2126 if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
2130 len = fread(buf, len, 1, ef->fp);