* eet: add support for eet_alias.

SVN revision: 49939
This commit is contained in:
Cedric BAIL 2010-06-29 16:20:23 +00:00
parent 4e30cb2411
commit 6df28268ca
4 changed files with 250 additions and 22 deletions

View File

@ -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.

View File

@ -444,6 +444,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.

View File

@ -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;

View File

@ -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);