summaryrefslogtreecommitdiff
path: root/src/lib/eet_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/eet_lib.c')
-rw-r--r--src/lib/eet_lib.c2832
1 files changed, 0 insertions, 2832 deletions
diff --git a/src/lib/eet_lib.c b/src/lib/eet_lib.c
deleted file mode 100644
index 6ea5647..0000000
--- a/src/lib/eet_lib.c
+++ /dev/null
@@ -1,2832 +0,0 @@
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* ifdef HAVE_CONFIG_H */
-
-#ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-#elif defined __GNUC__
-# define alloca __builtin_alloca
-#elif defined _AIX
-# define alloca __alloca
-#elif defined _MSC_VER
-# include <malloc.h>
-# define alloca _alloca
-#else /* ifdef HAVE_ALLOCA_H */
-# include <stddef.h>
-# ifdef __cplusplus
-extern "C"
-# endif /* ifdef __cplusplus */
-void *alloca(size_t);
-#endif /* ifdef HAVE_ALLOCA_H */
-
-#ifdef _WIN32
-# include <winsock2.h>
-#endif /* ifdef _WIN32 */
-
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <string.h>
-#include <fnmatch.h>
-#include <fcntl.h>
-#include <zlib.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* ifdef HAVE_UNISTD_H */
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif /* ifdef HAVE_NETINET_IN_H */
-
-#ifdef HAVE_EVIL
-# include <Evil.h>
-#endif /* ifdef HAVE_EVIL */
-
-#include <Eina.h>
-
-#ifdef HAVE_GNUTLS
-# include <gnutls/gnutls.h>
-# include <gcrypt.h>
-#endif /* ifdef HAVE_GNUTLS */
-
-#ifdef HAVE_OPENSSL
-# include <openssl/err.h>
-# include <openssl/evp.h>
-#endif /* ifdef HAVE_OPENSSL */
-
-#ifdef EINA_HAVE_THREADS
-# ifdef HAVE_GNUTLS
-GCRY_THREAD_OPTION_PTHREAD_IMPL;
-# endif /* ifdef HAVE_GNUTLS */
-#endif /* ifdef EINA_HAVE_THREADS */
-
-#include "Eet.h"
-#include "Eet_private.h"
-
-#include "lz4.h"
-#include "lz4hc.h"
-
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-static Eet_Version _version = { VMAJ, VMIN, VMIC, VREV };
-EAPI Eet_Version *eet_version = &_version;
-
-#ifdef HAVE_REALPATH
-# undef HAVE_REALPATH
-#endif /* ifdef HAVE_REALPATH */
-
-#define EET_MAGIC_FILE 0x1ee7ff00
-#define EET_MAGIC_FILE_HEADER 0x1ee7ff01
-
-#define EET_MAGIC_FILE2 0x1ee70f42
-
-#define EET_FILE2_HEADER_COUNT 3
-#define EET_FILE2_DIRECTORY_ENTRY_COUNT 6
-#define EET_FILE2_DICTIONARY_ENTRY_COUNT 5
-
-#define EET_FILE2_HEADER_SIZE (sizeof(int) * \
- EET_FILE2_HEADER_COUNT)
-#define EET_FILE2_DIRECTORY_ENTRY_SIZE (sizeof(int) * \
- EET_FILE2_DIRECTORY_ENTRY_COUNT)
-#define EET_FILE2_DICTIONARY_ENTRY_SIZE (sizeof(int) * \
- EET_FILE2_DICTIONARY_ENTRY_COUNT)
-
-/* prototypes of internal calls */
-static Eet_File *
-eet_cache_find(const char *path,
- Eet_File **cache,
- int cache_num);
-static void
-eet_cache_add(Eet_File *ef,
- Eet_File ***cache,
- int *cache_num,
- int *cache_alloc);
-static void
-eet_cache_del(Eet_File *ef,
- Eet_File ***cache,
- int *cache_num,
- int *cache_alloc);
-static int
-eet_string_match(const char *s1,
- const char *s2);
-#if 0 /* Unused */
-static Eet_Error
-eet_flush(Eet_File *ef);
-#endif /* if 0 */
-static Eet_Error
- eet_flush2(Eet_File *ef);
-static Eet_File_Node *
- find_node_by_name(Eet_File *ef,
- const char *name);
-static int
-read_data_from_disk(Eet_File *ef,
- Eet_File_Node *efn,
- void *buf,
- int len);
-
-static Eet_Error
-eet_internal_close(Eet_File *ef,
- Eina_Bool locked);
-
-static Eina_Lock eet_cache_lock;
-
-#define LOCK_CACHE eina_lock_take(&eet_cache_lock)
-#define UNLOCK_CACHE eina_lock_release(&eet_cache_lock)
-
-#define INIT_FILE(File) eina_lock_new(&File->file_lock)
-#define LOCK_FILE(File) eina_lock_take(&File->file_lock)
-#define UNLOCK_FILE(File) eina_lock_release(&File->file_lock)
-#define DESTROY_FILE(File) eina_lock_free(&File->file_lock)
-
-/* cache. i don't expect this to ever be large, so arrays will do */
-static int eet_writers_num = 0;
-static int eet_writers_alloc = 0;
-static Eet_File **eet_writers = NULL;
-static int eet_readers_num = 0;
-static int eet_readers_alloc = 0;
-static Eet_File **eet_readers = NULL;
-static int eet_init_count = 0;
-
-/* log domain variable */
-int _eet_log_dom_global = -1;
-
-/* Check to see its' an eet file pointer */
-static inline int
-eet_check_pointer(const Eet_File *ef)
-{
- if ((!ef) || (ef->magic != EET_MAGIC_FILE))
- return 1;
-
- return 0;
-}
-
-static inline int
-eet_check_header(const Eet_File *ef)
-{
- if (!ef->header)
- return 1;
-
- if (!ef->header->directory)
- return 1;
-
- return 0;
-}
-
-static inline int
-eet_test_close(int test,
- Eet_File *ef)
-{
- if (test)
- {
- ef->delete_me_now = 1;
- eet_internal_close(ef, EINA_TRUE);
- }
-
- return test;
-}
-
-/* find an eet file in the currently in use cache */
-static Eet_File *
-eet_cache_find(const char *path,
- Eet_File **cache,
- int cache_num)
-{
- int i;
-
- /* walk list */
- for (i = 0; i < cache_num; i++)
- {
- /* if matches real path - return it */
- if (eet_string_match(cache[i]->path, path))
- if (!cache[i]->delete_me_now)
- return cache[i];
- }
-
- /* not found */
- return NULL;
-}
-
-/* add to end of cache */
-/* this should only be called when the cache lock is already held */
-static void
-eet_cache_add(Eet_File *ef,
- Eet_File ***cache,
- int *cache_num,
- int *cache_alloc)
-{
- Eet_File **new_cache;
- int new_cache_num;
- int new_cache_alloc;
-
- new_cache_num = *cache_num;
- if (new_cache_num >= 64) /* avoid fd overruns - limit to 128 (most recent) in the cache */
- {
- Eet_File *del_ef = NULL;
- int i;
-
- new_cache = *cache;
- for (i = 0; i < new_cache_num; i++)
- {
- if (new_cache[i]->references == 0)
- {
- del_ef = new_cache[i];
- break;
- }
- }
-
- if (del_ef)
- {
- del_ef->delete_me_now = 1;
- eet_internal_close(del_ef, EINA_TRUE);
- }
- }
-
- new_cache = *cache;
- new_cache_num = *cache_num;
- new_cache_alloc = *cache_alloc;
- new_cache_num++;
- if (new_cache_num > new_cache_alloc)
- {
- new_cache_alloc += 16;
- new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
- if (!new_cache)
- {
- CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
- abort();
- }
- }
-
- new_cache[new_cache_num - 1] = ef;
- *cache = new_cache;
- *cache_num = new_cache_num;
- *cache_alloc = new_cache_alloc;
-}
-
-/* delete from cache */
-/* this should only be called when the cache lock is already held */
-static void
-eet_cache_del(Eet_File *ef,
- Eet_File ***cache,
- int *cache_num,
- int *cache_alloc)
-{
- Eet_File **new_cache;
- int new_cache_num, new_cache_alloc;
- int i, j;
-
- new_cache = *cache;
- new_cache_num = *cache_num;
- new_cache_alloc = *cache_alloc;
- if (new_cache_num <= 0)
- return;
-
- for (i = 0; i < new_cache_num; i++)
- {
- if (new_cache[i] == ef)
- break;
- }
-
- if (i >= new_cache_num)
- return;
-
- new_cache_num--;
- for (j = i; j < new_cache_num; j++)
- new_cache[j] = new_cache[j + 1];
-
- if (new_cache_num <= (new_cache_alloc - 16))
- {
- new_cache_alloc -= 16;
- if (new_cache_num > 0)
- {
- new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
- if (!new_cache)
- {
- CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
- abort();
- }
- }
- else
- {
- free(new_cache);
- new_cache = NULL;
- }
- }
-
- *cache = new_cache;
- *cache_num = new_cache_num;
- *cache_alloc = new_cache_alloc;
-}
-
-/* internal string match. null friendly, catches same ptr */
-static int
-eet_string_match(const char *s1,
- const char *s2)
-{
- /* both null- no match */
- if ((!s1) || (!s2))
- return 0;
-
- if (s1 == s2)
- return 1;
-
- return !strcmp(s1, s2);
-}
-
-/* flush out writes to a v2 eet file */
-static Eet_Error
-eet_flush2(Eet_File *ef)
-{
- Eet_File_Node *efn;
- FILE *fp;
- Eet_Error error = EET_ERROR_NONE;
- int head[EET_FILE2_HEADER_COUNT];
- int num_directory_entries = 0;
- int num_dictionary_entries = 0;
- int bytes_directory_entries = 0;
- int bytes_dictionary_entries = 0;
- int bytes_strings = 0;
- int data_offset = 0;
- int strings_offset = 0;
- int num;
- int i;
- int j;
-
- if (eet_check_pointer(ef))
- return EET_ERROR_BAD_OBJECT;
-
- if (eet_check_header(ef))
- return EET_ERROR_EMPTY;
-
- if (!ef->writes_pending)
- return EET_ERROR_NONE;
-
- if ((ef->mode == EET_FILE_MODE_READ_WRITE)
- || (ef->mode == EET_FILE_MODE_WRITE))
- {
- int fd;
-
- /* opening for write - delete old copy of file right away */
- unlink(ef->path);
- fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, S_IRUSR | S_IWUSR);
- fp = fdopen(fd, "wb");
- if (!fp)
- return EET_ERROR_NOT_WRITABLE;
-
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- }
- else
- return EET_ERROR_NOT_WRITABLE;
-
- /* calculate string base offset and data base offset */
- num = (1 << ef->header->directory->size);
- for (i = 0; i < num; ++i)
- {
- for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
- {
- num_directory_entries++;
- bytes_strings += strlen(efn->name) + 1;
- }
- }
- if (ef->ed)
- {
- num_dictionary_entries = ef->ed->count;
-
- for (i = 0; i < num_dictionary_entries; ++i)
- bytes_strings += ef->ed->all[i].len;
- }
-
- /* calculate section bytes size */
- bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE *
- num_directory_entries + EET_FILE2_HEADER_SIZE;
- bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE *
- num_dictionary_entries;
-
- /* calculate per entry offset */
- strings_offset = bytes_directory_entries + bytes_dictionary_entries;
- data_offset = bytes_directory_entries + bytes_dictionary_entries +
- bytes_strings;
-
- for (i = 0; i < num; ++i)
- {
- for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
- {
- efn->offset = data_offset;
- data_offset += efn->size;
-
- efn->name_offset = strings_offset;
- strings_offset += efn->name_size;
- }
- }
-
- /* calculate dictionary strings offset */
- if (ef->ed)
- ef->ed->offset = strings_offset;
-
- /* go thru and write the header */
- head[0] = (int)htonl((unsigned int)EET_MAGIC_FILE2);
- head[1] = (int)htonl((unsigned int)num_directory_entries);
- head[2] = (int)htonl((unsigned int)num_dictionary_entries);
-
- fseek(fp, 0, SEEK_SET);
- if (fwrite(head, sizeof (head), 1, fp) != 1)
- goto write_error;
-
- /* write directories entry */
- for (i = 0; i < num; i++)
- {
- for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
- {
- unsigned int flag;
- int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
-
- flag = (efn->alias << 2) | (efn->ciphered << 1) | efn->compression;
- flag |= efn->compression_type << 3;
-
- ibuf[0] = (int)htonl((unsigned int)efn->offset);
- ibuf[1] = (int)htonl((unsigned int)efn->size);
- ibuf[2] = (int)htonl((unsigned int)efn->data_size);
- ibuf[3] = (int)htonl((unsigned int)efn->name_offset);
- ibuf[4] = (int)htonl((unsigned int)efn->name_size);
- ibuf[5] = (int)htonl((unsigned int)flag);
-
- if (fwrite(ibuf, sizeof(ibuf), 1, fp) != 1)
- goto write_error;
- }
- }
-
- /* write dictionary */
- if (ef->ed)
- {
- int offset = strings_offset;
-
- for (j = 0; j < ef->ed->count; ++j)
- {
- int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
-
- sbuf[0] = (int)htonl((unsigned int)ef->ed->all[j].hash);
- sbuf[1] = (int)htonl((unsigned int)offset);
- sbuf[2] = (int)htonl((unsigned int)ef->ed->all[j].len);
- sbuf[3] = (int)htonl((unsigned int)ef->ed->all[j].prev);
- sbuf[4] = (int)htonl((unsigned int)ef->ed->all[j].next);
-
- offset += ef->ed->all[j].len;
-
- if (fwrite(sbuf, sizeof (sbuf), 1, fp) != 1)
- goto write_error;
- }
- }
-
- /* write directories name */
- for (i = 0; i < num; i++)
- {
- for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
- {
- if (fwrite(efn->name, efn->name_size, 1, fp) != 1)
- goto write_error;
- }
- }
-
- /* write strings */
- if (ef->ed)
- for (j = 0; j < ef->ed->count; ++j)
- {
- if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, fp) != 1)
- goto write_error;
- }
-
- /* write data */
- for (i = 0; i < num; i++)
- {
- for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
- {
- if (fwrite(efn->data, efn->size, 1, fp) != 1)
- goto write_error;
- }
- }
-
- /* flush all write to the file. */
- fflush(fp);
-
- /* append signature if required */
- if (ef->key)
- {
- error = eet_identity_sign(fp, ef->key);
- if (error != EET_ERROR_NONE)
- goto sign_error;
- }
-
- /* no more writes pending */
- ef->writes_pending = 0;
-
- fclose(fp);
-
- return EET_ERROR_NONE;
-
-write_error:
- if (ferror(fp))
- {
- switch (errno)
- {
- case EFBIG: error = EET_ERROR_WRITE_ERROR_FILE_TOO_BIG; break;
-
- case EIO: error = EET_ERROR_WRITE_ERROR_IO_ERROR; break;
-
- case ENOSPC: error = EET_ERROR_WRITE_ERROR_OUT_OF_SPACE; break;
-
- case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
-
- default: error = EET_ERROR_WRITE_ERROR; break;
- }
- }
-
-sign_error:
- fclose(fp);
- return error;
-}
-
-EAPI int
-eet_init(void)
-{
- if (++eet_init_count != 1)
- return eet_init_count;
-
- if (!eina_init())
- return --eet_init_count;
-
- _eet_log_dom_global = eina_log_domain_register("eet", EET_DEFAULT_LOG_COLOR);
- if (_eet_log_dom_global < 0)
- {
- EINA_LOG_ERR("Eet Can not create a general log domain.");
- goto shutdown_eina;
- }
-
- eina_lock_new(&eet_cache_lock);
-
- if (!eet_mempool_init())
- {
- EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
- goto unregister_log_domain;
- }
-
- if (!eet_node_init())
- {
- EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
- goto shutdown_mempool;
- }
-
-#ifdef HAVE_GNUTLS
- /* Before the library can be used, it must initialize itself if needed. */
- if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
- {
- gcry_check_version(NULL);
- /* Disable warning messages about problems with the secure memory subsystem.
- This command should be run right after gcry_check_version. */
- if (gcry_control(GCRYCTL_DISABLE_SECMEM_WARN))
- goto shutdown_eet; /* This command is used to allocate a pool of secure memory and thus
- enabling the use of secure memory. It also drops all extra privileges the
- process has (i.e. if it is run as setuid (root)). If the argument nbytes
- is 0, secure memory will be disabled. The minimum amount of secure memory
- allocated is currently 16384 bytes; you may thus use a value of 1 to
- request that default size. */
-
- if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
- WRN(
- "BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
- }
-
-# ifdef EINA_HAVE_THREADS
- if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread))
- WRN(
- "YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!");
-
-# endif /* ifdef EINA_HAVE_THREADS */
- if (gnutls_global_init())
- goto shutdown_eet;
-
-#endif /* ifdef HAVE_GNUTLS */
-#ifdef HAVE_OPENSSL
- ERR_load_crypto_strings();
- OpenSSL_add_all_algorithms();
-#endif /* ifdef HAVE_OPENSSL */
-
- return eet_init_count;
-
-#ifdef HAVE_GNUTLS
-shutdown_eet:
-#endif
- eet_node_shutdown();
-shutdown_mempool:
- eet_mempool_shutdown();
-unregister_log_domain:
- eina_log_domain_unregister(_eet_log_dom_global);
- _eet_log_dom_global = -1;
-shutdown_eina:
- eina_shutdown();
- return --eet_init_count;
-}
-
-EAPI int
-eet_shutdown(void)
-{
- if (eet_init_count <= 0)
- {
- ERR("Init count not greater than 0 in shutdown.");
- return 0;
- }
- if (--eet_init_count != 0)
- return eet_init_count;
-
- eet_clearcache();
-
- if (eet_writers_num || eet_readers_num)
- {
- Eet_File **closelist = NULL;
- int num = 0;
- int i;
-
- closelist = alloca((eet_writers_num + eet_readers_num)
- * sizeof(Eet_File *));
- for (i = 0; i < eet_writers_num; i++)
- {
- closelist[num++] = eet_writers[i];
- eet_writers[i]->delete_me_now = 1;
- }
-
- for (i = 0; i < eet_readers_num; i++)
- {
- closelist[num++] = eet_readers[i];
- eet_readers[i]->delete_me_now = 1;
- }
-
- for (i = 0; i < num; i++)
- {
- ERR("File '%s' is still open !", closelist[i]->path);
- eet_internal_close(closelist[i], EINA_TRUE);
- }
- }
- eet_node_shutdown();
- eet_mempool_shutdown();
-
- eina_lock_free(&eet_cache_lock);
-
-#ifdef HAVE_GNUTLS
- /* Note that gnutls has a leak where it doesnt free stuff it alloced
- * on init. valgrind trace here:
- * 21 bytes in 1 blocks are definitely lost in loss record 24 of 194
- * at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
- * by 0x68AC801: strdup (strdup.c:43)
- * by 0xD215B6A: p11_kit_registered_module_to_name (in /usr/lib/x86_64-linux-gnu/libp11-kit.so.0.0.0)
- * by 0x9571574: gnutls_pkcs11_init (in /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8)
- * by 0x955B031: gnutls_global_init (in /usr/lib/x86_64-linux-gnu/libgnutls.so.26.21.8)
- * by 0x6DFD6D0: eet_init (eet_lib.c:608)
- *
- * yes - i've tried calling gnutls_pkcs11_deinit() by hand but no luck.
- * the leak is in there.
- */
- gnutls_global_deinit();
-#endif /* ifdef HAVE_GNUTLS */
-#ifdef HAVE_OPENSSL
- EVP_cleanup();
- ERR_free_strings();
-#endif /* ifdef HAVE_OPENSSL */
- eina_log_domain_unregister(_eet_log_dom_global);
- _eet_log_dom_global = -1;
- eina_shutdown();
-
- return eet_init_count;
-}
-
-EAPI Eet_Error
-eet_sync(Eet_File *ef)
-{
- Eet_Error ret;
-
- if (eet_check_pointer(ef))
- return EET_ERROR_BAD_OBJECT;
-
- if ((ef->mode != EET_FILE_MODE_WRITE) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE))
- return EET_ERROR_NOT_WRITABLE;
-
- if (!ef->writes_pending)
- return EET_ERROR_NONE;
-
- LOCK_FILE(ef);
-
- ret = eet_flush2(ef);
-
- UNLOCK_FILE(ef);
- return ret;
-}
-
-EAPI void
-eet_clearcache(void)
-{
- int num = 0;
- int i;
-
- /*
- * We need to compute the list of eet file to close separately from the cache,
- * due to eet_close removing them from the cache after each call.
- */
- LOCK_CACHE;
- for (i = 0; i < eet_writers_num; i++)
- {
- if (eet_writers[i]->references <= 0)
- num++;
- }
-
- for (i = 0; i < eet_readers_num; i++)
- {
- if (eet_readers[i]->references <= 0)
- num++;
- }
-
- if (num > 0)
- {
- Eet_File **closelist = NULL;
-
- closelist = alloca(num * sizeof(Eet_File *));
- num = 0;
- for (i = 0; i < eet_writers_num; i++)
- {
- if (eet_writers[i]->references <= 0)
- {
- closelist[num] = eet_writers[i];
- eet_writers[i]->delete_me_now = 1;
- num++;
- }
- }
-
- for (i = 0; i < eet_readers_num; i++)
- {
- if (eet_readers[i]->references <= 0)
- {
- closelist[num] = eet_readers[i];
- eet_readers[i]->delete_me_now = 1;
- num++;
- }
- }
-
- for (i = 0; i < num; i++)
- {
- eet_internal_close(closelist[i], EINA_TRUE);
- }
- }
-
- UNLOCK_CACHE;
-}
-
-/* FIXME: MMAP race condition in READ_WRITE_MODE */
-static Eet_File *
-eet_internal_read2(Eet_File *ef)
-{
- const int *data = (const int *)ef->data;
- const char *start = (const char *)ef->data;
- int idx = 0;
- unsigned long int bytes_directory_entries;
- unsigned long int bytes_dictionary_entries;
- unsigned long int signature_base_offset;
- unsigned long int num_directory_entries;
- unsigned long int num_dictionary_entries;
- unsigned int i;
-
- idx += sizeof(int);
- if (eet_test_close((int)ntohl(*data) != EET_MAGIC_FILE2, ef))
- return NULL;
-
- data++;
-
-#define GET_INT(Value, Pointer, Index) \
- { \
- Value = ntohl(*Pointer); \
- Pointer++; \
- Index += sizeof(int); \
- }
-
- /* get entries count and byte count */
- GET_INT(num_directory_entries, data, idx);
- /* get dictionary count and byte count */
- GET_INT(num_dictionary_entries, data, idx);
-
- bytes_directory_entries = EET_FILE2_DIRECTORY_ENTRY_SIZE *
- num_directory_entries + EET_FILE2_HEADER_SIZE;
- bytes_dictionary_entries = EET_FILE2_DICTIONARY_ENTRY_SIZE *
- num_dictionary_entries;
-
- /* we can't have > 0x7fffffff values here - invalid */
- if (eet_test_close((num_directory_entries > 0x7fffffff), ef))
- return NULL;
-
- /* we can't have more bytes directory and bytes in dictionaries than the size of the file */
- if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) >
- ef->data_size, ef))
- return NULL;
-
- /* allocate header */
- ef->header = eet_file_header_calloc(1);
- if (eet_test_close(!ef->header, ef))
- return NULL;
-
- ef->header->magic = EET_MAGIC_FILE_HEADER;
-
- /* allocate directory block in ram */
- ef->header->directory = eet_file_directory_calloc(1);
- if (eet_test_close(!ef->header->directory, ef))
- return NULL;
-
- /* 8 bit hash table (256 buckets) */
- ef->header->directory->size = 8;
- /* allocate base hash table */
- ef->header->directory->nodes =
- calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
- if (eet_test_close(!ef->header->directory->nodes, ef))
- return NULL;
-
- signature_base_offset = 0;
- if (num_directory_entries == 0)
- {
- signature_base_offset = ef->data_size;
- }
-
- /* actually read the directory block - all of it, into ram */
- for (i = 0; i < num_directory_entries; ++i)
- {
- const char *name;
- Eet_File_Node *efn;
- unsigned long int name_offset;
- unsigned long int name_size;
- int hash;
- int flag;
-
- /* out directory block is inconsistent - we have overrun our */
- /* dynamic block buffer before we finished scanning dir entries */
- efn = eet_file_node_malloc(1);
- if (eet_test_close(!efn, ef))
- {
- if (efn) eet_file_node_mp_free(efn); /* yes i know - we only get here if
- * efn is null/0 -> trying to shut up
- * warning tools like cppcheck */
- return NULL;
- }
-
- /* get entrie header */
- GET_INT(efn->offset, data, idx);
- GET_INT(efn->size, data, idx);
- GET_INT(efn->data_size, data, idx);
- GET_INT(name_offset, data, idx);
- GET_INT(name_size, data, idx);
- GET_INT(flag, data, idx);
-
- efn->compression = flag & 0x1 ? 1 : 0;
- efn->ciphered = flag & 0x2 ? 1 : 0;
- efn->alias = flag & 0x4 ? 1 : 0;
- efn->compression_type = (flag >> 3) & 0xff;
-
-#define EFN_TEST(Test, Ef, Efn) \
- if (eet_test_close(Test, Ef)) \
- { \
- eet_file_node_mp_free(Efn); \
- return NULL; \
- }
-
- /* check data pointer position */
- EFN_TEST(!((efn->size > 0)
- && (efn->offset + efn->size <= ef->data_size)
- && (efn->offset > bytes_dictionary_entries +
- bytes_directory_entries)), ef, efn);
-
- /* check name position */
- EFN_TEST(!((name_size > 0)
- && (name_offset + name_size < ef->data_size)
- && (name_offset >= bytes_dictionary_entries +
- bytes_directory_entries)), ef, efn);
-
- name = start + name_offset;
-
- /* check '\0' at the end of name string */
- EFN_TEST(name[name_size - 1] != '\0', ef, efn);
-
- efn->free_name = 0;
- efn->name = (char *)name;
- efn->name_size = name_size;
-
- hash = _eet_hash_gen(efn->name, ef->header->directory->size);
- efn->next = ef->header->directory->nodes[hash];
- ef->header->directory->nodes[hash] = efn;
-
- /* read-only mode, so currently we have no data loaded */
- if (ef->mode == EET_FILE_MODE_READ)
- efn->data = NULL; /* read-write mode - read everything into ram */
- else
- {
- efn->data = malloc(efn->size);
- if (efn->data)
- memcpy(efn->data, ef->data + efn->offset, efn->size);
- }
-
- /* compute the possible position of a signature */
- if (signature_base_offset < efn->offset + efn->size)
- signature_base_offset = efn->offset + efn->size;
- }
-
- ef->ed = NULL;
-
- if (num_dictionary_entries)
- {
- const int *dico = (const int *)ef->data +
- EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries +
- EET_FILE2_HEADER_COUNT;
- int j;
-
- if (eet_test_close((num_dictionary_entries *
- (int)EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) >
- (bytes_dictionary_entries + bytes_directory_entries),
- ef))
- return NULL;
-
- ef->ed = eet_dictionary_add();
- if (eet_test_close(!ef->ed, ef))
- return NULL;
-
- ef->ed->all = calloc(1, num_dictionary_entries * sizeof(Eet_String));
- if (eet_test_close(!ef->ed->all, ef))
- return NULL;
-
- ef->ed->count = num_dictionary_entries;
- ef->ed->total = num_dictionary_entries;
- ef->ed->start = start + bytes_dictionary_entries +
- bytes_directory_entries;
- ef->ed->end = ef->ed->start;
-
- for (j = 0; j < ef->ed->count; ++j)
- {
- unsigned int offset;
- int hash;
-
- GET_INT(hash, dico, idx);
- GET_INT(offset, dico, idx);
- GET_INT(ef->ed->all[j].len, dico, idx);
- GET_INT(ef->ed->all[j].prev, dico, idx);
- GET_INT(ef->ed->all[j].next, dico, idx);
-
- /* Hash value could be stored on 8bits data, but this will break alignment of all the others data.
- So stick to int and check the value. */
- if (eet_test_close(hash & 0xFFFFFF00, ef))
- return NULL;
-
- /* Check string position */
- if (eet_test_close(!((ef->ed->all[j].len > 0)
- && (offset >
- (bytes_dictionary_entries +
- bytes_directory_entries))
- && (offset + ef->ed->all[j].len <
- ef->data_size)), ef))
- return NULL;
-
- ef->ed->all[j].str = start + offset;
-
- if (ef->ed->all[j].str + ef->ed->all[j].len > ef->ed->end)
- ef->ed->end = ef->ed->all[j].str + ef->ed->all[j].len;
-
- /* Check '\0' at the end of the string */
- if (eet_test_close(ef->ed->all[j].str[ef->ed->all[j].len - 1] !=
- '\0', ef))
- return NULL;
-
- ef->ed->all[j].hash = hash;
- if (ef->ed->all[j].prev == -1)
- ef->ed->hash[hash] = j;
-
- /* compute the possible position of a signature */
- if (signature_base_offset < offset + ef->ed->all[j].len)
- signature_base_offset = offset + ef->ed->all[j].len;
- }
- }
-
- /* Check if the file is signed */
- ef->x509_der = NULL;
- ef->x509_length = 0;
- ef->signature = NULL;
- ef->signature_length = 0;
-
- if (signature_base_offset < ef->data_size)
- {
-#ifdef HAVE_SIGNATURE
- const unsigned char *buffer = ((const unsigned char *)ef->data) +
- signature_base_offset;
- ef->x509_der = eet_identity_check(ef->data,
- signature_base_offset,
- &ef->sha1,
- &ef->sha1_length,
- buffer,
- ef->data_size - signature_base_offset,
- &ef->signature,
- &ef->signature_length,
- &ef->x509_length);
-
- if (eet_test_close(!ef->x509_der, ef))
- return NULL;
-
-#else /* ifdef HAVE_SIGNATURE */
- ERR(
- "This file could be signed but you didn't compile the necessary code to check the signature.");
-#endif /* ifdef HAVE_SIGNATURE */
- }
-
- return ef;
-}
-
-#if EET_OLD_EET_FILE_FORMAT
-static Eet_File *
-eet_internal_read1(Eet_File *ef)
-{
- const unsigned char *dyn_buf = NULL;
- const unsigned char *p = NULL;
- unsigned long int byte_entries;
- unsigned long int num_entries;
- unsigned int i;
- int idx = 0;
-
- 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);
-
- /* build header table if read mode */
- /* geat header */
- idx += sizeof(int);
- if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
- return NULL;
-
-#define EXTRACT_INT(Value, Pointer, Index) \
- { \
- int tmp; \
- memcpy(&tmp, Pointer + Index, sizeof(int)); \
- Value = ntohl(tmp); \
- Index += sizeof(int); \
- }
-
- /* get entries count and byte count */
- EXTRACT_INT(num_entries, ef->data, idx);
- EXTRACT_INT(byte_entries, ef->data, idx);
-
- /* we can't have <= 0 values here - invalid */
- if (eet_test_close((num_entries > 0x7fffffff) ||
- (byte_entries > 0x7fffffff), ef))
- return NULL;
-
- /* we can't have more entires than minimum bytes for those! invalid! */
- if (eet_test_close((num_entries * 20) > byte_entries, ef))
- return NULL;
-
- /* check we will not outrun the file limit */
- if (eet_test_close(((byte_entries + (int)(sizeof(int) * 3)) >
- ef->data_size), ef))
- return NULL;
-
- /* allocate header */
- ef->header = eet_file_header_calloc(1);
- if (eet_test_close(!ef->header, ef))
- return NULL;
-
- ef->header->magic = EET_MAGIC_FILE_HEADER;
-
- /* allocate directory block in ram */
- ef->header->directory = eet_file_directory_calloc(1);
- if (eet_test_close(!ef->header->directory, ef))
- return NULL;
-
- /* 8 bit hash table (256 buckets) */
- ef->header->directory->size = 8;
- /* allocate base hash table */
- ef->header->directory->nodes =
- calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
- if (eet_test_close(!ef->header->directory->nodes, ef))
- return NULL;
-
- /* actually read the directory block - all of it, into ram */
- dyn_buf = ef->data + idx;
-
- /* parse directory block */
- p = dyn_buf;
-
- for (i = 0; i < num_entries; i++)
- {
- Eet_File_Node *efn;
- void *data = NULL;
- int indexn = 0;
- int name_size;
- int hash;
- int k;
-
-#define HEADER_SIZE (sizeof(int) * 5)
-
- /* out directory block is inconsistent - we have overrun our */
- /* dynamic block buffer before we finished scanning dir entries */
- if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
- return NULL;
-
- /* allocate all the ram needed for this stored node accounting */
- efn = eet_file_node_malloc(1);
- if (eet_test_close(!efn, ef))
- {
- if (efn) eet_file_node_mp_free(efn); /* yes i know - we only get here if
- * efn is null/0 -> trying to shut up
- * warning tools like cppcheck */
- return NULL;
- }
-
- /* get entrie header */
- EXTRACT_INT(efn->offset, p, indexn);
- EXTRACT_INT(efn->compression, p, indexn);
- EXTRACT_INT(efn->size, p, indexn);
- EXTRACT_INT(efn->data_size, p, indexn);
- EXTRACT_INT(name_size, p, indexn);
-
- efn->name_size = name_size;
- efn->ciphered = 0;
- efn->alias = 0;
-
- /* invalid size */
- if (eet_test_close(efn->size <= 0, ef))
- {
- eet_file_node_mp_free(efn);
- return NULL;
- }
-
- /* invalid name_size */
- if (eet_test_close(name_size <= 0, ef))
- {
- eet_file_node_mp_free(efn);
- return NULL;
- }
-
- /* reading name would mean falling off end of dyn_buf - invalid */
- if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
- {
- eet_file_node_mp_free(efn);
- return NULL;
- }
-
- /* This code is useless if we dont want backward compatibility */
- for (k = name_size;
- k > 0 && ((unsigned char)*(p + HEADER_SIZE + k)) != 0; --k)
- ;
-
- efn->free_name = ((unsigned char)*(p + HEADER_SIZE + k)) != 0;
-
- if (efn->free_name)
- {
- efn->name = malloc(sizeof(char) * name_size + 1);
- if (eet_test_close(!efn->name, ef))
- {
- eet_file_node_mp_free(efn);
- return NULL;
- }
-
- strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
- efn->name[name_size] = 0;
-
- WRN(
- "File: %s is not up to date for key \"%s\" - needs rebuilding sometime",
- ef->path,
- efn->name);
- }
- else
- /* The only really useful peace of code for efn->name (no backward compatibility) */
- efn->name = (char *)((unsigned char *)(p + HEADER_SIZE));
-
- /* get hash bucket it should go in */
- hash = _eet_hash_gen(efn->name, ef->header->directory->size);
- efn->next = ef->header->directory->nodes[hash];
- ef->header->directory->nodes[hash] = efn;
-
- /* read-only mode, so currently we have no data loaded */
- if (ef->mode == EET_FILE_MODE_READ)
- efn->data = NULL; /* read-write mode - read everything into ram */
- else
- {
- data = malloc(efn->size);
- if (data)
- memcpy(data, ef->data + efn->offset, efn->size);
-
- efn->data = data;
- }
-
- /* advance */
- p += HEADER_SIZE + name_size;
- }
- return ef;
-}
-
-#endif /* if EET_OLD_EET_FILE_FORMAT */
-
-/*
- * this should only be called when the cache lock is already held
- * (We could drop this restriction if we add a parameter to eet_test_close
- * that indicates if the lock is held or not. For now it is easiest
- * to just require that it is always held.)
- */
-static Eet_File *
-eet_internal_read(Eet_File *ef)
-{
- const int *data = (const int *)ef->data;
-
- if (eet_test_close((ef->data == (void *)-1) || (!ef->data), ef))
- return NULL;
-
- if (eet_test_close(ef->data_size < (int)sizeof(int) * 3, ef))
- return NULL;
-
- switch (ntohl(*data))
- {
-#if EET_OLD_EET_FILE_FORMAT
- case EET_MAGIC_FILE:
- return eet_internal_read1(ef);
-
-#endif /* if EET_OLD_EET_FILE_FORMAT */
- case EET_MAGIC_FILE2:
- return eet_internal_read2(ef);
-
- default:
- ef->delete_me_now = 1;
- eet_internal_close(ef, EINA_TRUE);
- break;
- }
-
- return NULL;
-}
-
-static Eet_Error
-eet_internal_close(Eet_File *ef,
- Eina_Bool locked)
-{
- Eet_Error err;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef))
- return EET_ERROR_BAD_OBJECT;
-
- if (!locked)
- LOCK_CACHE;
-
- /* deref */
- ef->references--;
- /* if its still referenced - dont go any further */
- if (ef->references > 0)
- {
- /* flush any writes */
- if ((ef->mode == EET_FILE_MODE_WRITE) ||
- (ef->mode == EET_FILE_MODE_READ_WRITE))
- eet_sync(ef);
- goto on_error;
- }
-
- err = eet_flush2(ef);
-
- eet_identity_unref(ef->key);
- ef->key = NULL;
-
- /* if not urgent to delete it - dont free it - leave it in cache */
- if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
- goto on_error;
-
- /* remove from cache */
- if (ef->mode == EET_FILE_MODE_READ)
- eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
- else if ((ef->mode == EET_FILE_MODE_WRITE) ||
- (ef->mode == EET_FILE_MODE_READ_WRITE))
- eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
-
- /* we can unlock the cache now */
- if (!locked)
- UNLOCK_CACHE;
-
- DESTROY_FILE(ef);
-
- /* free up data */
- if (ef->header)
- {
- if (ef->header->directory)
- {
- if (ef->header->directory->nodes)
- {
- int i, num;
-
- num = (1 << ef->header->directory->size);
- for (i = 0; i < num; i++)
- {
- Eet_File_Node *efn;
-
- while ((efn = ef->header->directory->nodes[i]))
- {
- if (efn->data)
- free(efn->data);
-
- ef->header->directory->nodes[i] = efn->next;
-
- if (efn->free_name)
- free(efn->name);
-
- eet_file_node_mp_free(efn);
- }
- }
- free(ef->header->directory->nodes);
- }
-
- eet_file_directory_mp_free(ef->header->directory);
- }
-
- eet_file_header_mp_free(ef->header);
- }
-
- eet_dictionary_free(ef->ed);
-
- if (ef->sha1)
- free(ef->sha1);
-
- if (ef->readfp)
- {
- if (ef->data)
- eina_file_map_free(ef->readfp, (void *)ef->data);
-
- eina_file_close(ef->readfp);
- }
-
- /* zero out ram for struct - caution tactic against stale memory use */
- memset(ef, 0, sizeof(Eet_File));
-
- /* free it */
- eina_stringshare_del(ef->path);
- eet_file_mp_free(ef);
- return err;
-
-on_error:
- if (!locked)
- UNLOCK_CACHE;
-
- return EET_ERROR_NONE;
-}
-
-EAPI Eet_File *
-eet_memopen_read(const void *data,
- size_t size)
-{
- Eet_File *ef;
-
- if (!data || size == 0)
- return NULL;
-
- ef = eet_file_malloc(1);
- if (!ef)
- return NULL;
-
- INIT_FILE(ef);
- ef->ed = NULL;
- ef->path = NULL;
- ef->key = NULL;
- ef->magic = EET_MAGIC_FILE;
- ef->references = 1;
- ef->mode = EET_FILE_MODE_READ;
- ef->header = NULL;
- ef->delete_me_now = 1;
- ef->readfp = NULL;
- ef->data = data;
- ef->data_size = size;
- ef->sha1 = NULL;
- ef->sha1_length = 0;
-
- /* eet_internal_read expects the cache lock to be held when it is called */
- LOCK_CACHE;
- ef = eet_internal_read(ef);
- UNLOCK_CACHE;
- return ef;
-}
-
-EAPI const char *
-eet_file_get(Eet_File *ef)
-{
- if (eet_check_pointer(ef)) return NULL;
- return ef->path;
-}
-
-EAPI Eet_File *
-eet_open(const char *file,
- Eet_File_Mode mode)
-{
- Eina_File *fp;
- Eet_File *ef;
- int file_len;
- unsigned long int size;
-
- if (!file)
- return NULL;
-
- /* find the current file handle in cache*/
- ef = NULL;
- LOCK_CACHE;
- if (mode == EET_FILE_MODE_READ)
- {
- ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
- if (ef)
- {
- eet_sync(ef);
- ef->references++;
- ef->delete_me_now = 1;
- eet_internal_close(ef, EINA_TRUE);
- }
-
- ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
- }
- else if ((mode == EET_FILE_MODE_WRITE) ||
- (mode == EET_FILE_MODE_READ_WRITE))
- {
- ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
- if (ef)
- {
- ef->delete_me_now = 1;
- ef->references++;
- eet_internal_close(ef, EINA_TRUE);
- }
-
- ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
- }
-
- /* try open the file based on mode */
- if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
- {
- /* Prevent garbage in futur comparison. */
- fp = eina_file_open(file, EINA_FALSE);
- if (!fp)
- {
- size = 0;
- goto open_error;
- }
-
- size = eina_file_size_get(fp);
-
- if (size < ((int)sizeof(int) * 3))
- {
- eina_file_close(fp);
- fp = NULL;
-
- size = 0;
-
- goto open_error;
- }
-
-open_error:
- if (!fp && mode == EET_FILE_MODE_READ)
- goto on_error;
- }
- else
- {
- if (mode != EET_FILE_MODE_WRITE)
- return NULL;
-
- size = 0;
-
- fp = NULL;
- }
-
- /* We found one */
- if (ef && ef->readfp != fp)
- {
- ef->delete_me_now = 1;
- ef->references++;
- eet_internal_close(ef, EINA_TRUE);
- ef = NULL;
- }
-
- if (ef)
- {
- /* reference it up and return it */
- if (fp)
- eina_file_close(fp);
-
- ef->references++;
- UNLOCK_CACHE;
- return ef;
- }
-
- file_len = strlen(file) + 1;
-
- /* Allocate struct for eet file and have it zero'd out */
- ef = eet_file_malloc(1);
- if (!ef)
- goto on_error;
-
- /* fill some of the members */
- INIT_FILE(ef);
- ef->key = NULL;
- ef->readfp = fp;
- ef->path = eina_stringshare_add_length(file, file_len);
- ef->magic = EET_MAGIC_FILE;
- ef->references = 1;
- ef->mode = mode;
- ef->header = NULL;
- ef->writes_pending = 0;
- ef->delete_me_now = 0;
- ef->data = NULL;
- ef->data_size = 0;
- ef->sha1 = NULL;
- ef->sha1_length = 0;
-
- ef->ed = (mode == EET_FILE_MODE_WRITE)
- || (!ef->readfp && mode == EET_FILE_MODE_READ_WRITE) ?
- eet_dictionary_add() : NULL;
-
- if (!ef->readfp &&
- (mode == EET_FILE_MODE_READ_WRITE || mode == EET_FILE_MODE_WRITE))
- goto empty_file;
-
- /* if we can't open - bail out */
- if (eet_test_close(!ef->readfp, ef))
- goto on_error;
-
- /* if we opened for read or read-write */
- if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
- {
- ef->data_size = size;
- ef->data = eina_file_map_all(fp, EINA_FILE_SEQUENTIAL);
- if (eet_test_close((ef->data == NULL), ef))
- goto on_error;
-
- ef = eet_internal_read(ef);
- if (!ef)
- goto on_error;
- }
-
-empty_file:
- /* add to cache */
- if (ef->references == 1)
- {
- if (ef->mode == EET_FILE_MODE_READ)
- eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
- else if ((ef->mode == EET_FILE_MODE_WRITE) ||
- (ef->mode == EET_FILE_MODE_READ_WRITE))
- eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
- }
-
- UNLOCK_CACHE;
- return ef;
-
-on_error:
- UNLOCK_CACHE;
- return NULL;
-}
-
-EAPI Eet_File_Mode
-eet_mode_get(Eet_File *ef)
-{
- /* check to see its' an eet file pointer */
- if ((!ef) || (ef->magic != EET_MAGIC_FILE))
- return EET_FILE_MODE_INVALID;
- else
- return ef->mode;
-}
-
-EAPI const void *
-eet_identity_x509(Eet_File *ef,
- int *der_length)
-{
- if (eet_check_pointer(ef))
- return NULL;
-
- if (!ef->x509_der)
- return NULL;
-
- if (der_length)
- *der_length = ef->x509_length;
-
- return ef->x509_der;
-}
-
-EAPI const void *
-eet_identity_signature(Eet_File *ef,
- int *signature_length)
-{
- if (eet_check_pointer(ef))
- return NULL;
-
- if (!ef->signature)
- return NULL;
-
- if (signature_length)
- *signature_length = ef->signature_length;
-
- return ef->signature;
-}
-
-EAPI const void *
-eet_identity_sha1(Eet_File *ef,
- int *sha1_length)
-{
- if (eet_check_pointer(ef))
- return NULL;
-
- if (!ef->sha1)
- ef->sha1 = eet_identity_compute_sha1(ef->data,
- ef->data_size,
- &ef->sha1_length);
-
- if (sha1_length)
- *sha1_length = ef->sha1_length;
-
- return ef->sha1;
-}
-
-EAPI Eet_Error
-eet_identity_set(Eet_File *ef,
- Eet_Key *key)
-{
- Eet_Key *tmp;
-
- if (!ef)
- return EET_ERROR_BAD_OBJECT;
-
- tmp = ef->key;
- ef->key = key;
- eet_identity_ref(ef->key);
- eet_identity_unref(tmp);
-
- /* flags that writes are pending */
- ef->writes_pending = 1;
-
- return EET_ERROR_NONE;
-}
-
-EAPI Eet_Error
-eet_close(Eet_File *ef)
-{
- return eet_internal_close(ef, EINA_FALSE);
-}
-
-EAPI void *
-eet_read_cipher(Eet_File *ef,
- const char *name,
- int *size_ret,
- const char *cipher_key)
-{
- Eet_File_Node *efn;
- char *data = NULL;
- unsigned long int size = 0;
-
- if (size_ret)
- *size_ret = 0;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef))
- return NULL;
-
- if (!name)
- return NULL;
-
- if ((ef->mode != EET_FILE_MODE_READ) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE))
- return NULL;
-
- /* no header, return NULL */
- if (eet_check_header(ef))
- return NULL;
-
- LOCK_FILE(ef);
-
- /* hunt hash bucket */
- efn = find_node_by_name(ef, name);
- if (!efn)
- goto on_error;
-
- /* get size (uncompressed, if compressed at all) */
- size = efn->data_size;
-
- /* allocate data */
- data = malloc(size);
- if (!data)
- goto on_error;
-
- /* uncompressed data */
- if (efn->compression == 0)
- {
- void *data_deciphered = NULL;
- unsigned int data_deciphered_sz = 0;
- /* if we already have the data in ram... copy that */
-
- if (efn->ciphered && efn->size > size)
- {
- size = efn->size;
- data = realloc(data, efn->size);
- }
-
- if (efn->data)
- memcpy(data, efn->data, size);
- else
- if (!read_data_from_disk(ef, efn, data, size))
- goto on_error;
-
- if (efn->ciphered && cipher_key)
- {
- if (eet_decipher(data, efn->size, cipher_key, strlen(cipher_key),
- &data_deciphered, &data_deciphered_sz))
- {
- if (data_deciphered)
- free(data_deciphered);
-
- goto on_error;
- }
-
- free(data);
- data = data_deciphered;
- size = data_deciphered_sz;
- }
- }
- /* compressed data */
- else
- {
- void *tmp_data = NULL;
- void *data_deciphered = NULL;
- unsigned int data_deciphered_sz = 0;
- int free_tmp = 0, ret;
- int compr_size = efn->size;
- uLongf dlen;
-
- /* if we already have the data in ram... copy that */
- if (efn->data)
- tmp_data = efn->data;
- else
- {
- tmp_data = malloc(compr_size);
- if (!tmp_data)
- goto on_error;
-
- free_tmp = 1;
-
- if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
- {
- free(tmp_data);
- goto on_error;
- }
- }
-
- if (efn->ciphered && cipher_key)
- {
- if (eet_decipher(tmp_data, compr_size, cipher_key,
- strlen(cipher_key), &data_deciphered,
- &data_deciphered_sz))
- {
- if (free_tmp)
- free(tmp_data);
-
- if (data_deciphered)
- free(data_deciphered);
-
- goto on_error;
- }
-
- if (free_tmp)
- free(tmp_data);
- free_tmp = 1;
- tmp_data = data_deciphered;
- compr_size = data_deciphered_sz;
- }
-
- /* decompress it */
- dlen = size;
- switch (efn->compression_type)
- {
- case EET_COMPRESSION_VERYFAST:
- case EET_COMPRESSION_SUPERFAST:
- ret = LZ4_uncompress(tmp_data, data, dlen);
- if (ret != compr_size)
- {
- if (free_tmp)
- free(tmp_data);
- goto on_error;
- }
- break;
- default:
- if (uncompress((Bytef *)data, &dlen,
- tmp_data, (uLongf)compr_size) != Z_OK)
- {
- if (free_tmp)
- free(tmp_data);
- goto on_error;
- }
- break;
- }
-
- if (free_tmp)
- free(tmp_data);
- }
-
- UNLOCK_FILE(ef);
-
- /* handle alias */
- if (efn->alias)
- {
- void *tmp;
-
- if (data[size - 1] != '\0')
- goto on_error;
-
- tmp = eet_read_cipher(ef, data, size_ret, cipher_key);
-
- free(data);
-
- data = tmp;
- }
- else
- /* fill in return values */
- if (size_ret)
- *size_ret = size;
-
- return data;
-
-on_error:
- UNLOCK_FILE(ef);
- free(data);
- return NULL;
-}
-
-EAPI void *
-eet_read(Eet_File *ef,
- const char *name,
- int *size_ret)
-{
- return eet_read_cipher(ef, name, size_ret, NULL);
-}
-
-EAPI const void *
-eet_read_direct(Eet_File *ef,
- const char *name,
- int *size_ret)
-{
- Eet_File_Node *efn;
- const char *data = NULL;
- int size = 0, ret;
-
- if (size_ret)
- *size_ret = 0;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef))
- return NULL;
-
- if (!name)
- return NULL;
-
- if ((ef->mode != EET_FILE_MODE_READ) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE))
- return NULL;
-
- /* no header, return NULL */
- if (eet_check_header(ef))
- return NULL;
-
- LOCK_FILE(ef);
-
- /* hunt hash bucket */
- efn = find_node_by_name(ef, name);
- if (!efn)
- goto on_error;
-
- /* trick to detect data in memory instead of mmaped from disk */
- if (efn->offset > ef->data_size && !efn->data)
- goto on_error;
-
- /* get size (uncompressed, if compressed at all) */
- size = efn->data_size;
-
- if (efn->alias)
- {
- data = efn->data ? efn->data : ef->data + efn->offset;
-
- /* handle alias case */
- if (efn->compression)
- {
- const void *retptr;
- char *tmp;
- int compr_size = efn->size;
- uLongf dlen;
-
- tmp = malloc(compr_size);
- if (!tmp) goto on_error;
- switch (efn->compression_type)
- {
- case EET_COMPRESSION_VERYFAST:
- case EET_COMPRESSION_SUPERFAST:
- ret = LZ4_uncompress(data, tmp, size);
- if (ret != compr_size)
- {
- free(tmp);
- goto on_error;
- }
- break;
- default:
- dlen = size;
-
- if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data,
- (uLongf)compr_size))
- {
- free(tmp);
- goto on_error;
- }
- }
-
- if (tmp[compr_size - 1] != '\0')
- {
- free(tmp);
- goto on_error;
- }
-
- UNLOCK_FILE(ef);
-
- retptr = eet_read_direct(ef, tmp, size_ret);
- free(tmp);
- return retptr;
- }
-
- if (!data)
- goto on_error;
-
- if (data[size - 1] != '\0')
- goto on_error;
-
- UNLOCK_FILE(ef);
-
- return eet_read_direct(ef, data, size_ret);
- }
- else
- /* uncompressed data */
- if ((efn->compression == 0) && (efn->ciphered == 0))
- data = efn->data ? efn->data : ef->data + efn->offset; /* compressed data */
- else
- data = NULL;
-
- /* fill in return values */
- if (size_ret)
- *size_ret = size;
-
- UNLOCK_FILE(ef);
-
- return data;
-
-on_error:
- UNLOCK_FILE(ef);
- return NULL;
-}
-
-EAPI const char *
-eet_alias_get(Eet_File *ef,
- const char *name)
-{
- Eet_File_Node *efn;
- const char *data = NULL;
- int size = 0, ret;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef))
- return NULL;
-
- if (!name)
- return NULL;
-
- if ((ef->mode != EET_FILE_MODE_READ) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE))
- return NULL;
-
- /* no header, return NULL */
- if (eet_check_header(ef))
- return NULL;
-
- LOCK_FILE(ef);
-
- /* hunt hash bucket */
- efn = find_node_by_name(ef, name);
- if (!efn)
- goto on_error;
-
- /* trick to detect data in memory instead of mmaped from disk */
- if (efn->offset > ef->data_size && !efn->data)
- goto on_error;
-
- /* get size (uncompressed, if compressed at all) */
- size = efn->data_size;
-
- if (!efn->alias) return NULL;
- data = efn->data ? efn->data : ef->data + efn->offset;
-
- /* handle alias case */
- if (efn->compression)
- {
- const char *retptr;
- char *tmp;
- int compr_size = efn->size;
- uLongf dlen;
-
- tmp = malloc(compr_size);
- if (!tmp) goto on_error;
- switch (efn->compression_type)
- {
- case EET_COMPRESSION_VERYFAST:
- case EET_COMPRESSION_SUPERFAST:
- ret = LZ4_uncompress(data, tmp, size);
- if (ret != compr_size)
- {
- free(tmp);
- goto on_error;
- }
- break;
- default:
- dlen = size;
-
- if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data,
- (uLongf)compr_size))
- {
- free(tmp);
- goto on_error;
- }
- }
-
- if (tmp[compr_size - 1] != '\0')
- goto on_error;
-
- UNLOCK_FILE(ef);
-
- retptr = eina_stringshare_add(tmp);
- free(tmp);
- return retptr;
- }
-
- if (!data)
- goto on_error;
-
- if (data[size - 1] != '\0')
- goto on_error;
-
- UNLOCK_FILE(ef);
-
- return eina_stringshare_add(data);
-
-on_error:
- UNLOCK_FILE(ef);
- return NULL;
-}
-
-EAPI Eina_Bool
-eet_alias(Eet_File *ef,
- const char *name,
- const char *destination,
- int comp)
-{
- Eet_File_Node *efn;
- void *data2;
- Eina_Bool exists_already = EINA_FALSE;
- int data_size, ret, hash, slen;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef))
- return EINA_FALSE;
-
- if ((!name) || (!destination))
- return EINA_FALSE;
-
- if ((ef->mode != EET_FILE_MODE_WRITE) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE))
- return EINA_FALSE;
-
- LOCK_FILE(ef);
-
- if (!ef->header)
- {
- /* allocate header */
- ef->header = eet_file_header_calloc(1);
- if (!ef->header)
- goto on_error;
-
- ef->header->magic = EET_MAGIC_FILE_HEADER;
- /* allocate directory block in ram */
- ef->header->directory = eet_file_directory_calloc(1);
- if (!ef->header->directory)
- {
- eet_file_header_mp_free(ef->header);
- ef->header = NULL;
- goto on_error;
- }
-
- /* 8 bit hash table (256 buckets) */
- ef->header->directory->size = 8;
- /* allocate base hash table */
- ef->header->directory->nodes =
- calloc(1, sizeof(Eet_File_Node *) *
- (1 << ef->header->directory->size));
- if (!ef->header->directory->nodes)
- {
- eet_file_directory_mp_free(ef->header->directory);
- ef->header = NULL;
- goto on_error;
- }
- }
-
- /* figure hash bucket */
- hash = _eet_hash_gen(name, ef->header->directory->size);
-
- slen = strlen(destination) + 1;
- data_size = comp ?
- 12 + ((slen * 101) / 100)
- : slen;
- if (comp)
- {
- ret = LZ4_compressBound(slen);
- if ((ret > 0) && (ret > data_size)) data_size = ret;
- }
-
- data2 = malloc(data_size);
- if (!data2) goto on_error;
-
- /* if we want to compress */
- if (comp)
- {
- switch (comp)
- {
- case EET_COMPRESSION_VERYFAST:
- ret = LZ4_compressHC((const char *)destination, (char *)data2,
- slen);
- if (ret <= 0)
- {
- free(data2);
- goto on_error;
- }
- data_size = ret;
- break;
- case EET_COMPRESSION_SUPERFAST:
- ret = LZ4_compress((const char *)destination, (char *)data2,
- slen);
- if (ret <= 0)
- {
- free(data2);
- goto on_error;
- }
- data_size = ret;
- break;
- default:
- {
- uLongf buflen;
-
- /* compress the data with max compression */
- buflen = (uLongf)data_size;
- if (compress2((Bytef *)data2, &buflen,
- (const Bytef *)destination,
- (uLong)slen, Z_BEST_COMPRESSION) != Z_OK)
- {
- free(data2);
- goto on_error;
- }
- /* record compressed chunk size */
- data_size = (int)buflen;
- }
- break;
- }
- if ((data_size < 0) ||
- (data_size >= (int)(strlen(destination) + 1)))
- {
- comp = 0;
- data_size = strlen(destination) + 1;
- }
- else
- {
- void *data3;
-
- data3 = realloc(data2, data_size);
- if (data3) data2 = data3;
- }
- }
-
- if (!comp) memcpy(data2, destination, data_size);
-
- /* Does this node already exist? */
- for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
- {
- /* if it matches */
- if ((efn->name) && (eet_string_match(efn->name, name)))
- {
- free(efn->data);
- efn->alias = 1;
- efn->ciphered = 0;
- efn->compression = !!comp;
- efn->compression_type = comp;
- efn->size = data_size;
- efn->data_size = strlen(destination) + 1;
- efn->data = data2;
- /* Put the offset above the limit to avoid direct access */
- efn->offset = ef->data_size + 1;
- exists_already = EINA_TRUE;
- break;
- }
- }
- if (!exists_already)
- {
- efn = eet_file_node_malloc(1);
- if (!efn)
- {
- free(data2);
- goto on_error;
- }
-
- efn->name = strdup(name);
- efn->name_size = strlen(efn->name) + 1;
- efn->free_name = 1;
-
- efn->next = ef->header->directory->nodes[hash];
- ef->header->directory->nodes[hash] = efn;
- /* Put the offset above the limit to avoid direct access */
- efn->offset = ef->data_size + 1;
- efn->alias = 1;
- efn->ciphered = 0;
- efn->compression = !!comp;
- efn->compression_type = comp;
- efn->size = data_size;
- efn->data_size = strlen(destination) + 1;
- efn->data = data2;
- }
-
- /* flags that writes are pending */
- ef->writes_pending = 1;
-
- UNLOCK_FILE(ef);
- return EINA_TRUE;
-
-on_error:
- UNLOCK_FILE(ef);
- return EINA_FALSE;
-}
-
-EAPI int
-eet_write_cipher(Eet_File *ef,
- const char *name,
- const void *data,
- int size,
- int comp,
- const char *cipher_key)
-{
- Eet_File_Node *efn;
- void *data2 = NULL;
- int exists_already = 0, data_size, hash, ret;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef))
- return 0;
-
- if ((!name) || (!data) || (size <= 0))
- return 0;
-
- if ((ef->mode != EET_FILE_MODE_WRITE) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE))
- return 0;
-
- LOCK_FILE(ef);
-
- if (!ef->header)
- {
- /* allocate header */
- ef->header = eet_file_header_calloc(1);
- if (!ef->header)
- goto on_error;
-
- ef->header->magic = EET_MAGIC_FILE_HEADER;
- /* allocate directory block in ram */
- ef->header->directory = eet_file_directory_calloc(1);
- if (!ef->header->directory)
- {
- eet_file_header_mp_free(ef->header);
- ef->header = NULL;
- goto on_error;
- }
-
- /* 8 bit hash table (256 buckets) */
- ef->header->directory->size = 8;
- /* allocate base hash table */
- ef->header->directory->nodes =
- calloc(1, sizeof(Eet_File_Node *) *
- (1 << ef->header->directory->size));
- if (!ef->header->directory->nodes)
- {
- eet_file_directory_mp_free(ef->header->directory);
- ef->header = NULL;
- goto on_error;
- }
- }
-
- /* figure hash bucket */
- hash = _eet_hash_gen(name, ef->header->directory->size);
-
- UNLOCK_FILE(ef);
-
- data_size = comp ? 12 + ((size * 101) / 100) : size;
- if (comp)
- {
- ret = LZ4_compressBound(size);
- if ((ret > 0) && (ret > data_size)) data_size = ret;
- }
-
- if (comp || !cipher_key)
- {
- data2 = malloc(data_size);
- if (!data2)
- goto on_error;
- }
-
- /* if we want to compress */
- if (comp)
- {
- switch (comp)
- {
- case EET_COMPRESSION_VERYFAST:
- ret = LZ4_compressHC((const char *)data, (char *)data2, size);
- if (ret <= 0)
- {
- free(data2);
- LOCK_FILE(ef);
- goto on_error;
- }
- data_size = ret;
- break;
- case EET_COMPRESSION_SUPERFAST:
- ret = LZ4_compress((const char *)data, (char *)data2, size);
- if (ret <= 0)
- {
- free(data2);
- LOCK_FILE(ef);
- goto on_error;
- }
- data_size = ret;
- break;
- default:
- {
- uLongf buflen;
-
- /* compress the data with max compression */
- buflen = (uLongf)data_size;
- if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
- (uLong)size, Z_BEST_COMPRESSION) != Z_OK)
- {
- free(data2);
- LOCK_FILE(ef);
- goto on_error;
- }
- /* record compressed chunk size */
- data_size = (int)buflen;
- }
- }
- if ((data_size < 0) || (data_size >= size))
- {
- comp = 0;
- data_size = size;
- }
- else
- {
- void *data3;
-
- data3 = realloc(data2, data_size);
- if (data3)
- data2 = data3;
- }
- }
-
- if (cipher_key)
- {
- void *data_ciphered = NULL;
- unsigned int data_ciphered_sz = 0;
- const void *tmp;
-
- tmp = comp ? data2 : data;
- if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key),
- &data_ciphered, &data_ciphered_sz))
- {
- if (data2)
- free(data2);
-
- data2 = data_ciphered;
- data_size = data_ciphered_sz;
- }
- else
- {
- if (data_ciphered)
- free(data_ciphered);
-
- cipher_key = NULL;
- }
- }
- else
- if (!comp)
- memcpy(data2, data, size);
-
- LOCK_FILE(ef);
- /* Does this node already exist? */
- for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
- {
- /* if it matches */
- if ((efn->name) && (eet_string_match(efn->name, name)))
- {
- free(efn->data);
- efn->alias = 0;
- efn->ciphered = cipher_key ? 1 : 0;
- efn->compression = !!comp;
- efn->compression_type = comp;
- efn->size = data_size;
- efn->data_size = size;
- efn->data = data2;
- /* Put the offset above the limit to avoid direct access */
- efn->offset = ef->data_size + 1;
- exists_already = 1;
- break;
- }
- }
- if (!exists_already)
- {
- efn = eet_file_node_malloc(1);
- if (!efn)
- {
- free(data2);
- goto on_error;
- }
-
- efn->name = strdup(name);
- efn->name_size = strlen(efn->name) + 1;
- efn->free_name = 1;
-
- efn->next = ef->header->directory->nodes[hash];
- ef->header->directory->nodes[hash] = efn;
- /* Put the offset above the limit to avoid direct access */
- efn->offset = ef->data_size + 1;
- efn->alias = 0;
- efn->ciphered = cipher_key ? 1 : 0;
- efn->compression = !!comp;
- efn->compression_type = comp;
- efn->size = data_size;
- efn->data_size = size;
- efn->data = data2;
- }
-
- /* flags that writes are pending */
- ef->writes_pending = 1;
- UNLOCK_FILE(ef);
- return data_size;
-
-on_error:
- UNLOCK_FILE(ef);
- return 0;
-}
-
-EAPI int
-eet_write(Eet_File *ef,
- const char *name,
- const void *data,
- int size,
- int comp)
-{
- return eet_write_cipher(ef, name, data, size, comp, NULL);
-}
-
-EAPI int
-eet_delete(Eet_File *ef,
- const char *name)
-{
- Eet_File_Node *efn;
- Eet_File_Node *pefn;
- int hash;
- int exists_already = 0;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef))
- return 0;
-
- if (!name)
- return 0;
-
- /* deleting keys is only possible in RW or WRITE mode */
- if (ef->mode == EET_FILE_MODE_READ)
- return 0;
-
- if (eet_check_header(ef))
- return 0;
-
- LOCK_FILE(ef);
-
- /* figure hash bucket */
- hash = _eet_hash_gen(name, ef->header->directory->size);
-
- /* Does this node already exist? */
- for (pefn = NULL, efn = ef->header->directory->nodes[hash];
- efn;
- pefn = efn, efn = efn->next)
- {
- /* if it matches */
- if (eet_string_match(efn->name, name))
- {
- if (efn->data)
- free(efn->data);
-
- if (!pefn)
- ef->header->directory->nodes[hash] = efn->next;
- else
- pefn->next = efn->next;
-
- if (efn->free_name)
- free(efn->name);
-
- eet_file_node_mp_free(efn);
- exists_already = 1;
- break;
- }
- }
- /* flags that writes are pending */
- if (exists_already)
- ef->writes_pending = 1;
-
- UNLOCK_FILE(ef);
-
- /* update access time */
- return exists_already;
-}
-
-EAPI Eet_Dictionary *
-eet_dictionary_get(Eet_File *ef)
-{
- if (eet_check_pointer(ef))
- return NULL;
-
- return ef->ed;
-}
-
-EAPI char **
-eet_list(Eet_File *ef,
- const char *glob,
- int *count_ret)
-{
- Eet_File_Node *efn;
- char **list_ret = NULL;
- int list_count = 0;
- int list_count_alloc = 0;
- int i, num;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef) || eet_check_header(ef) ||
- (!glob) ||
- ((ef->mode != EET_FILE_MODE_READ) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE)))
- {
- if (count_ret)
- *count_ret = 0;
-
- return NULL;
- }
-
- if (!strcmp(glob, "*"))
- glob = NULL;
-
- LOCK_FILE(ef);
-
- /* loop through all entries */
- num = (1 << ef->header->directory->size);
- for (i = 0; i < num; i++)
- {
- for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
- {
- /* if the entry matches the input glob
- * check for * explicitly, because on some systems, * isn't well
- * supported
- */
- if ((!glob) || !fnmatch(glob, efn->name, 0))
- {
- /* add it to our list */
- list_count++;
-
- /* only realloc in 32 entry chunks */
- if (list_count > list_count_alloc)
- {
- char **new_list = NULL;
-
- list_count_alloc += 64;
- new_list =
- realloc(list_ret, list_count_alloc * (sizeof(char *)));
- if (!new_list)
- {
- free(list_ret);
-
- goto on_error;
- }
-
- list_ret = new_list;
- }
-
- /* put pointer of name string in */
- list_ret[list_count - 1] = efn->name;
- }
- }
- }
-
- UNLOCK_FILE(ef);
-
- /* return count and list */
- if (count_ret)
- *count_ret = list_count;
-
- return list_ret;
-
-on_error:
- UNLOCK_FILE(ef);
-
- if (count_ret)
- *count_ret = 0;
-
- return NULL;
-}
-
-EAPI int
-eet_num_entries(Eet_File *ef)
-{
- int i, num, ret = 0;
- Eet_File_Node *efn;
-
- /* check to see its' an eet file pointer */
- if (eet_check_pointer(ef) || eet_check_header(ef) ||
- ((ef->mode != EET_FILE_MODE_READ) &&
- (ef->mode != EET_FILE_MODE_READ_WRITE)))
- return -1;
-
- LOCK_FILE(ef);
-
- /* loop through all entries */
- num = (1 << ef->header->directory->size);
- for (i = 0; i < num; i++)
- {
- for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
- ret++;
- }
-
- UNLOCK_FILE(ef);
-
- return ret;
-}
-
-typedef struct _Eet_Entries_Iterator Eet_Entries_Iterator;
-struct _Eet_Entries_Iterator
-{
- Eina_Iterator iterator;
-
- Eet_File *ef;
- Eet_File_Node *efn;
- int index;
-
- Eet_Entry entry;
-
- Eina_Bool locked;
-};
-
-Eina_Bool
-_eet_entries_iterator_next(Eet_Entries_Iterator *it, void **data)
-{
- if (it->efn == NULL)
- {
- int num;
-
- num = (1 << it->ef->header->directory->size);
-
- do
- {
- it->index++;
-
- if (!(it->index < num))
- return EINA_FALSE;
-
- it->efn = it->ef->header->directory->nodes[it->index];
- }
- while (!it->efn);
- }
-
- /* copy info in public header */
- it->entry.name = it->efn->name;
- it->entry.offset = it->efn->offset;
- it->entry.size = it->efn->size;
- it->entry.data_size = it->efn->data_size;
- it->entry.compression = it->efn->compression;
- it->entry.ciphered = it->efn->ciphered;
- it->entry.alias = it->efn->alias;
-
- *data = &it->entry;
- it->efn = it->efn->next;
- return EINA_TRUE;
-}
-
-void *
-_eet_entries_iterator_container(Eet_Entries_Iterator *it)
-{
- return it->ef;
-}
-
-void
-_eet_entries_iterator_free(Eet_Entries_Iterator *it)
-{
- if (it->locked)
- {
- CRIT("Iterator still LOCKED !");
- UNLOCK_FILE(it->ef);
- }
-}
-
-Eina_Bool
-_eet_entries_iterator_lock(Eet_Entries_Iterator *it)
-{
- if (it->locked)
- {
- CRIT("Iterator already LOCKED !");
- return EINA_TRUE;
- }
-
- LOCK_FILE(it->ef);
- it->locked = EINA_TRUE;
- return EINA_TRUE;
-}
-
-Eina_Bool
-_eet_entries_iterator_unlock(Eet_Entries_Iterator *it)
-{
- if (!it->locked)
- {
- CRIT("Iterator already UNLOCKED !");
- return EINA_TRUE;
- }
-
- UNLOCK_FILE(it->ef);
- it->locked = EINA_FALSE;
- return EINA_TRUE;
-}
-
-EAPI Eina_Iterator *
-eet_list_entries(Eet_File *ef)
-{
- Eet_Entries_Iterator *it;
-
- it = malloc(sizeof (Eet_Entries_Iterator));
- if (!it) return NULL;
-
- EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
- it->ef = ef;
- it->efn = NULL;
- it->index = -1;
- it->locked = EINA_FALSE;
- it->iterator.version = EINA_ITERATOR_VERSION;
- it->iterator.next = FUNC_ITERATOR_NEXT(_eet_entries_iterator_next);
- it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_eet_entries_iterator_container);
- it->iterator.free = FUNC_ITERATOR_FREE(_eet_entries_iterator_free);
- it->iterator.lock = FUNC_ITERATOR_LOCK(_eet_entries_iterator_lock);
- it->iterator.unlock = FUNC_ITERATOR_LOCK(_eet_entries_iterator_unlock);
-
- return &it->iterator;
-}
-
-static Eet_File_Node *
-find_node_by_name(Eet_File *ef,
- const char *name)
-{
- Eet_File_Node *efn;
- int hash;
-
- /* get hash bucket this should be in */
- hash = _eet_hash_gen(name, ef->header->directory->size);
-
- for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
- {
- if (eet_string_match(efn->name, name))
- return efn;
- }
-
- return NULL;
-}
-
-static int
-read_data_from_disk(Eet_File *ef,
- Eet_File_Node *efn,
- void *buf,
- int len)
-{
- if (efn->offset > ef->data_size)
- return 0;
-
- if (!ef->data)
- return 0;
-
- if ((efn->offset + len) > ef->data_size)
- return 0;
-
- memcpy(buf, ef->data + efn->offset, len);
-
- return len;
-}
-