From 441eeeb95625bd3d25963d23944808a9550a9437 Mon Sep 17 00:00:00 2001 From: cedric Date: Tue, 29 Jun 2010 16:20:23 +0000 Subject: [PATCH] * eet: add support for eet_alias. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eet@49939 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- ChangeLog | 5 ++ src/lib/Eet.h | 17 ++++ src/lib/eet_lib.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++---- src/tests/eet_suite.c | 16 +++- 4 files changed, 250 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7d96e98..0fa13cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -389,3 +389,8 @@ * On Windows 64, long is of size 32 bits and not 64 bits. Also LONG_BIT is not defined on Windows. + +2010-06-29 Cedric BAIL + + * Add eet_alias support. + * Fix possible dead lock in eet_write_cipher. diff --git a/src/lib/Eet.h b/src/lib/Eet.h index 24ee00b..7853218 100644 --- a/src/lib/Eet.h +++ b/src/lib/Eet.h @@ -445,6 +445,23 @@ extern "C" { EAPI int eet_delete(Eet_File *ef, const char *name); /** + * Alias a specific section to another one. Destination may exist or not, + * no check are done. + * @param ef A valid eet file handle opened for writing. + * @param name Name of the entry. eg: "/base/file_i_want". + * @param destination Destionation of the alias. eg: "/base/the_real_stuff_i_want". + * @param compress Compression flags (1 == compress, 0 = don't compress). + * @return EINA_TRUE on success, EINA_FALSE on failure. + * + * Name and Destination must not be NULL, otherwhise EINA_FALSE will be returned. + * + * @since 1.3.3 + * @ingroup Eet_File_Group + */ + EAPI Eina_Bool eet_alias(Eet_File *ef, const char *name, const char *destination, int compress); + + + /** * List all entries in eet file matching shell glob. * @param ef A valid eet file handle. * @param glob A shell glob to match against. diff --git a/src/lib/eet_lib.c b/src/lib/eet_lib.c index 0d4b619..cc87909 100644 --- a/src/lib/eet_lib.c +++ b/src/lib/eet_lib.c @@ -146,6 +146,7 @@ struct _Eet_File_Node unsigned char free_name : 1; unsigned char compression : 1; unsigned char ciphered : 1; + unsigned char alias : 1; }; #if 0 @@ -181,7 +182,11 @@ struct int data_size; /* size of the (uncompressed) data chunk */ int name_offset; /* bytes offset into file for name string */ int name_size; /* length in bytes of the name field */ - int flags; /* flags - for now 0 = uncompressed, 1 = compressed */ + int flags; /* bit flags - for now: + bit 0 => compresion on/off + bit 1 => ciphered on/off + bit 2 => alias + */ } directory[num_directory_entries]; struct { @@ -521,7 +526,7 @@ eet_flush2(Eet_File *ef) unsigned int flag; int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT]; - flag = (efn->ciphered << 1) | efn->compression; + flag = (efn->alias << 2) | (efn->ciphered << 1) | efn->compression; ibuf[0] = (int) htonl ((unsigned int) efn->offset); ibuf[1] = (int) htonl ((unsigned int) efn->size); @@ -889,6 +894,7 @@ eet_internal_read2(Eet_File *ef) efn->compression = flag & 0x1 ? 1 : 0; efn->ciphered = flag & 0x2 ? 1 : 0; + efn->alias = flag & 0x4 ? 1 : 0; #define EFN_TEST(Test, Ef, Efn) \ if (eet_test_close(Test, Ef)) \ @@ -1120,6 +1126,7 @@ eet_internal_read1(Eet_File *ef) efn->name_size = name_size; efn->ciphered = 0; + efn->alias = 0; /* invalid size */ if (eet_test_close(efn->size <= 0, ef)) @@ -1570,9 +1577,9 @@ eet_close(Eet_File *ef) EAPI void * eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *cipher_key) { - void *data = NULL; - int size = 0; - Eet_File_Node *efn; + Eet_File_Node *efn; + char *data = NULL; + int size = 0; if (size_ret) *size_ret = 0; @@ -1609,6 +1616,7 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe void *data_deciphered = NULL; unsigned int data_deciphered_sz = 0; /* if we alreayd have the data in ram... copy that */ + if (efn->data) memcpy(data, efn->data, efn->size); else @@ -1677,12 +1685,27 @@ eet_read_cipher(Eet_File *ef, const char *name, int *size_ret, const char *ciphe free(tmp_data); } - /* fill in return values */ - if (size_ret) - *size_ret = size; - 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: @@ -1700,9 +1723,9 @@ eet_read(Eet_File *ef, const char *name, int *size_ret) EAPI const void * eet_read_direct(Eet_File *ef, const char *name, int *size_ret) { - const void *data = NULL; - int size = 0; Eet_File_Node *efn; + const char *data = NULL; + int size = 0; if (size_ret) *size_ret = 0; @@ -1732,13 +1755,42 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret) /* get size (uncompressed, if compressed at all) */ size = efn->data_size; - /* uncompressed data */ - if (efn->compression == 0 - && efn->ciphered == 0) - data = efn->data ? efn->data : ef->data + efn->offset; - /* compressed data */ + if (efn->alias) + { + data = efn->data ? efn->data : ef->data + efn->offset; + + /* handle alias case */ + if (efn->compression) + { + char *tmp; + int compr_size = efn->size; + uLongf dlen; + + tmp = alloca(sizeof (compr_size)); + dlen = size; + + if (uncompress((Bytef *)tmp, &dlen, (Bytef *) data, (uLongf)compr_size)) + goto on_error; + + if (tmp[compr_size - 1] != '\0') + goto on_error; + + return eet_read_direct(ef, tmp, size_ret); + } + + if (!data) goto on_error; + if (data[size - 1] != '\0') goto on_error; + + return eet_read_direct(ef, data, size_ret); + } else - data = NULL; + /* 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) @@ -1753,6 +1805,150 @@ eet_read_direct(Eet_File *ef, const char *name, int *size_ret) 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; + int hash; + + /* 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 = calloc(1, sizeof(Eet_File_Header)); + if (!ef->header) + goto on_error; + + ef->header->magic = EET_MAGIC_FILE_HEADER; + /* allocate directory block in ram */ + ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); + if (!ef->header->directory) + { + 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) + { + free(ef->header->directory); + ef->header = NULL; + goto on_error; + } + } + + /* figure hash bucket */ + hash = _eet_hash_gen(name, ef->header->directory->size); + + data_size = comp ? + 12 + (((strlen(destination) + 1) * 101) / 100) + : strlen(destination) + 1; + + data2 = malloc(data_size); + if (!data2) goto on_error; + + /* if we want to compress */ + if (comp) + { + uLongf buflen; + + /* compress the data with max compression */ + buflen = (uLongf)data_size; + if (compress2((Bytef *)data2, &buflen, (Bytef *)destination, + (uLong)strlen(destination) + 1, Z_BEST_COMPRESSION) != Z_OK) + { + free(data2); + goto on_error; + } + /* record compressed chunk size */ + data_size = (int)buflen; + 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->size = data_size; + efn->data_size = strlen(destination) + 1; + efn->data = data2; + efn->offset = -1; + exists_already = EINA_TRUE; + break; + } + } + if (!exists_already) + { + efn = malloc(sizeof(Eet_File_Node)); + 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; + efn->offset = -1; + efn->alias = 1; + efn->ciphered = 0; + efn->compression = !!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) { @@ -1824,7 +2020,7 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int (uLong)size, Z_BEST_COMPRESSION) != Z_OK) { free(data2); - return 0; + goto on_error; } /* record compressed chunk size */ data_size = (int)buflen; @@ -1874,6 +2070,7 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int 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->size = data_size; @@ -1899,6 +2096,7 @@ eet_write_cipher(Eet_File *ef, const char *name, const void *data, int size, int efn->next = ef->header->directory->nodes[hash]; ef->header->directory->nodes[hash] = efn; efn->offset = -1; + efn->alias = 0; efn->ciphered = cipher_key ? 1 : 0; efn->compression = !!comp; efn->size = data_size; diff --git a/src/tests/eet_suite.c b/src/tests/eet_suite.c index d138e25..576e153 100644 --- a/src/tests/eet_suite.c +++ b/src/tests/eet_suite.c @@ -364,7 +364,7 @@ _eet_build_ex_descriptor(Eet_Data_Descriptor *edd) static Eet_Test_Ex_Type* _eet_test_ex_set(Eet_Test_Ex_Type *res, int offset) { - int i; + unsigned int i; if (!res) res = malloc( sizeof(Eet_Test_Ex_Type)); if (!res) return NULL; @@ -671,6 +671,8 @@ START_TEST(eet_file_simple_write) fail_if(!ef); fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 1)); + fail_if(!eet_alias(ef, "keys/alias", "keys/tests", 0)); + fail_if(!eet_alias(ef, "keys/alias2", "keys/alias", 1)); fail_if(eet_mode_get(ef) != EET_FILE_MODE_WRITE); @@ -689,8 +691,14 @@ START_TEST(eet_file_simple_write) fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0); + test = eet_read(ef, "keys/alias2", &size); + fail_if(!test); + fail_if(size != (int) strlen(buffer) + 1); + + fail_if(eet_read_direct(ef, "key/alias2", &size)); + fail_if(eet_mode_get(ef) != EET_FILE_MODE_READ); - fail_if(eet_num_entries(ef) != 1); + fail_if(eet_num_entries(ef) != 3); eet_close(ef); @@ -1324,7 +1332,7 @@ static int pass_get(char *pass, int size, __UNUSED__ int rwflags, __UNUSED__ voi { memset(pass, 0, size); - if (strlen("password") > size) + if ((int) strlen("password") > size) return 0; snprintf(pass, size, "%s", "password"); return strlen(pass); @@ -1334,7 +1342,7 @@ static int badpass_get(char *pass, int size, __UNUSED__ int rwflags, __UNUSED__ { memset(pass, 0, size); - if (strlen("bad password") > size) + if ((int) strlen("bad password") > size) return 0; snprintf(pass, size, "%s", "bad password"); return strlen(pass); -- 2.7.4