2005-01-12 11:59:11 -08:00
/*
* vim : ts = 8 : sw = 3 : sts = 8 : noexpandtab : cino = > 5 n - 3f 0 ^ - 2 { 2
*/
2008-03-07 23:28:12 -08:00
# ifdef HAVE_CONFIG_H
2008-03-28 10:17:43 -07:00
# include <config.h>
2008-03-07 23:28:12 -08:00
# endif
2009-02-19 12:17:14 -08:00
# if defined(_WIN32) && ! defined(__CEGCC__)
# include <winsock2.h>
# endif
2008-03-28 10:17:43 -07:00
# 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
# include <stddef.h>
# ifdef __cplusplus
extern " C "
# endif
void * alloca ( size_t ) ;
# endif
2008-01-27 05:17:22 -08:00
2008-03-28 10:17:43 -07:00
# include <stdio.h>
# include <errno.h>
2006-07-25 02:47:47 -07:00
# include <sys/types.h>
2008-03-28 10:17:43 -07:00
# include <sys/stat.h>
2008-03-01 22:49:48 -08:00
# include <sys/mman.h>
2008-03-28 10:17:43 -07:00
# include <time.h>
2008-03-28 10:29:22 -07:00
# include <string.h>
2008-03-28 10:17:43 -07:00
# include <fnmatch.h>
# include <fcntl.h>
# include <zlib.h>
2009-02-19 12:31:21 -08:00
# ifndef _MSC_VER
# include <unistd.h>
# endif
2008-11-13 08:31:13 -08:00
# ifdef HAVE_OPENSSL
# include <openssl/err.h>
# endif
2008-03-28 10:17:43 -07:00
# ifdef HAVE_NETINET_IN_H
# include <netinet / in.h>
# endif
# ifdef HAVE_EVIL
# include <Evil.h>
# endif
2008-11-13 08:31:13 -08:00
# ifdef HAVE_GNUTLS
# include <gnutls / gnutls.h>
# include <gcrypt.h>
# endif
2008-10-13 04:51:10 -07:00
# ifdef HAVE_OPENSSL
# include <openssl / err.h>
2008-11-14 09:34:51 -08:00
# include <openssl / evp.h>
2008-10-13 04:51:10 -07:00
# endif
2008-10-20 02:44:34 -07:00
# include <Eina.h>
2008-03-28 10:17:43 -07:00
# include "Eet.h"
# include "Eet_private.h"
2006-06-13 03:20:22 -07:00
2004-08-28 01:41:19 -07:00
# ifdef HAVE_REALPATH
# undef HAVE_REALPATH
# endif
2002-12-02 15:39:26 -08:00
# define EET_MAGIC_FILE 0x1ee7ff00
# define EET_MAGIC_FILE_HEADER 0x1ee7ff01
2008-02-29 22:38:09 -08:00
# define EET_MAGIC_FILE2 0x1ee70f42
2002-12-02 15:39:26 -08:00
typedef struct _Eet_File_Header Eet_File_Header ;
typedef struct _Eet_File_Node Eet_File_Node ;
typedef struct _Eet_File_Directory Eet_File_Directory ;
struct _Eet_File
{
2008-01-20 17:09:51 -08:00
char * path ;
FILE * fp ;
2008-03-09 09:16:40 -07:00
FILE * readfp ;
2008-01-20 17:09:51 -08:00
Eet_File_Header * header ;
2008-02-29 22:38:09 -08:00
Eet_Dictionary * ed ;
2008-09-08 02:19:57 -07:00
Eet_Key * key ;
const unsigned char * data ;
const void * x509_der ;
2008-11-26 02:45:47 -08:00
const void * signature ;
2009-02-09 05:53:20 -08:00
void * sha1 ;
2008-11-26 02:45:47 -08:00
Eet_File_Mode mode ;
2008-01-20 17:09:51 -08:00
int magic ;
int references ;
2005-05-22 21:32:04 -07:00
2008-01-20 17:09:51 -08:00
int data_size ;
2008-09-08 02:19:57 -07:00
int x509_length ;
2008-11-26 02:45:47 -08:00
unsigned int signature_length ;
2009-02-26 14:14:14 -08:00
int sha1_length ;
2008-11-26 02:45:47 -08:00
2008-01-20 17:09:51 -08:00
time_t mtime ;
2005-05-22 21:32:04 -07:00
2008-01-20 17:09:51 -08:00
unsigned char writes_pending : 1 ;
unsigned char delete_me_now : 1 ;
2002-12-02 15:39:26 -08:00
} ;
2004-10-20 23:16:55 -07:00
2002-12-02 15:39:26 -08:00
struct _Eet_File_Header
{
int magic ;
Eet_File_Directory * directory ;
} ;
2004-10-20 23:16:55 -07:00
2002-12-02 15:39:26 -08:00
struct _Eet_File_Directory
{
2005-05-25 20:57:57 -07:00
int size ;
Eet_File_Node * * nodes ;
2002-12-02 15:39:26 -08:00
} ;
2004-10-20 23:16:55 -07:00
2005-05-25 20:57:57 -07:00
struct _Eet_File_Node
2002-12-02 15:39:26 -08:00
{
2008-02-29 22:38:09 -08:00
char * name ;
void * data ;
Eet_File_Node * next ; /* FIXME: make buckets linked lists */
2008-01-24 00:41:23 -08:00
2008-02-29 22:38:09 -08:00
int offset ;
int dictionary_offset ;
int name_offset ;
2006-06-13 03:20:22 -07:00
2008-02-29 22:38:09 -08:00
int name_size ;
int size ;
int data_size ;
unsigned char free_name : 1 ;
unsigned char compression : 1 ;
2008-11-13 08:31:13 -08:00
unsigned char ciphered : 1 ;
2002-12-02 15:39:26 -08:00
} ;
#if 0
2008-02-29 22:38:09 -08:00
/* Version 2 */
2002-12-02 15:39:26 -08:00
/* NB: all int's are stored in network byte order on disk */
/* file format: */
int magic ; /* magic number ie 0x1ee7ff00 */
int num_directory_entries ; /* number of directory entries to follow */
int bytes_directory_entries ; /* bytes of directory entries to follow */
2005-05-22 21:32:04 -07:00
struct
2002-12-02 15:39:26 -08:00
{
int offset ; /* bytes offset into file for data chunk */
2008-11-13 08:31:13 -08:00
int flags ; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */
2002-12-02 15:39:26 -08:00
int size ; /* size of the data chunk */
int data_size ; /* size of the (uncompressed) data chunk */
int name_size ; /* length in bytes of the name field */
2008-02-29 22:38:09 -08:00
char name [ name_size ] ; /* name string (variable length) and \0 terminated */
2002-12-02 15:39:26 -08:00
} directory [ num_directory_entries ] ;
/* and now startes the data stream... */
2005-05-22 21:32:04 -07:00
# endif
2002-12-02 15:39:26 -08:00
2008-02-29 22:38:09 -08:00
#if 0
/* Version 3 */
/* NB: all int's are stored in network byte order on disk */
/* file format: */
int magic ; /* magic number ie 0x1ee70f42 */
int num_directory_entries ; /* number of directory entries to follow */
int num_dictionary_entries ; /* number of dictionary entries to follow */
struct
{
int data_offset ; /* bytes offset into file for data chunk */
int size ; /* size of the data chunk */
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 */
} directory [ num_directory_entries ] ;
struct
{
int hash ;
int offset ;
int size ;
int prev ;
int next ;
} dictionary [ num_dictionary_entries ] ;
/* now start the string stream. */
/* and right after them the data stream. */
2008-09-08 02:19:57 -07:00
int magic_sign ; /* Optional, only if the eet file is signed. */
int signature_length ; /* Signature length. */
int x509_length ; /* Public certificate that signed the file. */
char signature [ signature_length ] ; /* The signature. */
char x509 [ x509_length ] ; /* The public certificate. */
2008-02-29 22:38:09 -08:00
# endif
# 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)
2002-12-02 15:39:26 -08:00
/* prototypes of internal calls */
2006-06-13 03:20:22 -07:00
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 ) ;
2008-04-03 12:30:08 -07:00
#if 0 /* Unused */
2006-06-13 03:20:22 -07:00
static Eet_Error eet_flush ( Eet_File * ef ) ;
2008-04-03 12:30:08 -07:00
# endif
2008-02-29 22:38:09 -08:00
static Eet_Error eet_flush2 ( Eet_File * ef ) ;
2006-06-13 03:20:22 -07:00
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 ) ;
2002-12-02 15:39:26 -08:00
/* cache. i don't expect this to ever be large, so arrays will do */
2005-11-03 05:05:52 -08:00
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_initcount = 0 ;
2006-06-13 03:20:22 -07:00
/* 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_close ( ef ) ;
}
return test ;
}
2002-12-02 15:39:26 -08:00
/* find an eet file in the currently in use cache */
static Eet_File *
2006-03-03 18:11:03 -08:00
eet_cache_find ( const char * path , Eet_File * * cache , int cache_num )
2002-12-02 15:39:26 -08:00
{
int i ;
2005-05-22 21:32:04 -07:00
2002-12-02 15:39:26 -08:00
/* walk list */
for ( i = 0 ; i < cache_num ; i + + )
{
/* if matches real path - return it */
2005-11-03 19:22:22 -08:00
if ( eet_string_match ( cache [ i ] - > path , path ) )
2005-11-03 07:05:21 -08:00
{
2006-06-13 03:20:22 -07:00
if ( ! cache [ i ] - > delete_me_now )
return cache [ i ] ;
2005-11-03 07:05:21 -08:00
}
2002-12-02 15:39:26 -08:00
}
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
/* not found */
return NULL ;
}
/* add to end of cache */
static void
2005-11-03 05:05:52 -08:00
eet_cache_add ( Eet_File * ef , Eet_File * * * cache , int * cache_num , int * cache_alloc )
2002-12-02 15:39:26 -08:00
{
2006-06-13 03:20:22 -07:00
Eet_File * * new_cache ;
int new_cache_num ;
int new_cache_alloc ;
2005-05-22 21:32:04 -07:00
2005-11-06 19:15:22 -08:00
new_cache_num = * cache_num ;
2006-06-22 12:21:31 -07:00
if ( new_cache_num > = 64 ) /* avoid fd overruns - limit to 128 (most recent) in the cache */
2005-11-06 19:15:22 -08:00
{
2006-06-13 03:20:22 -07:00
Eet_File * del_ef = NULL ;
int i ;
2008-01-24 00:41:23 -08:00
2005-11-06 19:15:22 -08:00
new_cache = * cache ;
for ( i = 0 ; i < new_cache_num ; i + + )
{
if ( new_cache [ i ] - > references = = 0 )
{
del_ef = new_cache [ i ] ;
break ;
}
}
2008-01-24 00:41:23 -08:00
2005-11-06 19:15:22 -08:00
if ( del_ef )
{
2006-06-13 03:20:22 -07:00
del_ef - > delete_me_now = 1 ;
2005-11-06 22:16:26 -08:00
eet_close ( del_ef ) ;
2005-11-06 19:15:22 -08:00
}
}
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
new_cache = * cache ;
2005-11-03 05:05:52 -08:00
new_cache_num = * cache_num ;
new_cache_alloc = * cache_alloc ;
2002-12-02 15:39:26 -08:00
new_cache_num + + ;
2005-11-03 05:05:52 -08:00
if ( new_cache_num > new_cache_alloc )
2004-10-20 23:16:55 -07:00
{
2006-06-22 12:21:31 -07:00
new_cache_alloc + = 16 ;
2005-11-03 05:05:52 -08:00
new_cache = realloc ( new_cache , new_cache_alloc * sizeof ( Eet_File * ) ) ;
if ( ! new_cache )
{
fprintf ( stderr , " BAD ERROR! Eet realloc of cache list failed. Abort \n " ) ;
abort ( ) ;
}
2004-10-20 23:16:55 -07:00
}
2002-12-02 15:39:26 -08:00
new_cache [ new_cache_num - 1 ] = ef ;
* cache = new_cache ;
2005-05-22 21:32:04 -07:00
* cache_num = new_cache_num ;
2005-11-03 05:05:52 -08:00
* cache_alloc = new_cache_alloc ;
2002-12-02 15:39:26 -08:00
}
/* delete from cache */
static void
2005-11-03 05:05:52 -08:00
eet_cache_del ( Eet_File * ef , Eet_File * * * cache , int * cache_num , int * cache_alloc )
2002-12-02 15:39:26 -08:00
{
Eet_File * * new_cache ;
2005-11-03 05:05:52 -08:00
int new_cache_num , new_cache_alloc ;
2002-12-02 15:39:26 -08:00
int i , j ;
new_cache = * cache ;
2005-11-03 05:05:52 -08:00
new_cache_num = * cache_num ;
new_cache_alloc = * cache_alloc ;
2004-10-20 23:16:55 -07:00
if ( new_cache_num < = 0 )
2006-06-13 03:20:22 -07:00
return ;
2008-01-24 00:41:23 -08:00
2002-12-02 15:39:26 -08:00
for ( i = 0 ; i < new_cache_num ; i + + )
{
2006-06-13 03:20:22 -07:00
if ( new_cache [ i ] = = ef )
break ;
2002-12-02 15:39:26 -08:00
}
2006-06-13 03:20:22 -07:00
2004-10-20 23:16:55 -07:00
if ( i > = new_cache_num )
2006-06-13 03:20:22 -07:00
return ;
2002-12-02 15:39:26 -08:00
new_cache_num - - ;
2006-06-13 03:20:22 -07:00
for ( j = i ; j < new_cache_num ; j + + )
new_cache [ j ] = new_cache [ j + 1 ] ;
2008-08-22 07:35:21 -07:00
if ( new_cache_num < = ( new_cache_alloc - 16 ) )
2003-09-24 00:08:57 -07:00
{
2006-06-22 12:21:31 -07:00
new_cache_alloc - = 16 ;
2005-11-03 05:05:52 -08:00
if ( new_cache_num > 0 )
2004-10-20 23:16:55 -07:00
{
2005-11-03 05:05:52 -08:00
new_cache = realloc ( new_cache , new_cache_alloc * sizeof ( Eet_File * ) ) ;
if ( ! new_cache )
{
fprintf ( stderr , " BAD ERROR! Eet realloc of cache list failed. Abort \n " ) ;
abort ( ) ;
}
}
else
{
free ( new_cache ) ;
new_cache = NULL ;
2004-10-20 23:16:55 -07:00
}
2003-09-24 00:08:57 -07:00
}
2002-12-02 15:39:26 -08:00
* cache = new_cache ;
2005-11-03 05:05:52 -08:00
* cache_num = new_cache_num ;
* cache_alloc = new_cache_alloc ;
2002-12-02 15:39:26 -08:00
}
2008-03-28 07:37:29 -07:00
/* internal string match. null friendly, catches same ptr */
2002-12-02 15:39:26 -08:00
static int
2006-03-03 18:11:03 -08:00
eet_string_match ( const char * s1 , const char * s2 )
2002-12-02 15:39:26 -08:00
{
/* both null- no match */
if ( ( ! s1 ) | | ( ! s2 ) ) return 0 ;
2008-03-28 07:37:29 -07:00
if ( s1 = = s2 ) return 1 ;
2005-11-03 05:05:52 -08:00
return ( ! strcmp ( s1 , s2 ) ) ;
2002-12-02 15:39:26 -08:00
}
2008-02-29 22:38:09 -08:00
/* flush out writes to a v2 eet file */
static Eet_Error
eet_flush2 ( Eet_File * ef )
{
Eet_File_Node * efn ;
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 - > 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 ;
2008-08-13 09:40:53 -07:00
if ( ef - > mode = = EET_FILE_MODE_READ_WRITE & & ef - > fp = = NULL )
{
2008-09-08 02:19:57 -07:00
int fd ;
2008-08-13 09:40:53 -07:00
unlink ( ef - > path ) ;
2008-09-08 04:11:51 -07:00
fd = open ( ef - > path , O_CREAT | O_TRUNC | O_RDWR , S_IRUSR | S_IWUSR ) ;
2008-09-08 02:19:57 -07:00
ef - > fp = fdopen ( fd , " wb " ) ;
2008-08-13 09:40:53 -07:00
if ( ! ef - > fp ) return EET_ERROR_NOT_WRITABLE ;
fcntl ( fileno ( ef - > fp ) , F_SETFD , FD_CLOEXEC ) ;
}
2008-02-29 22:38:09 -08:00
/* 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 ( ef - > fp , 0 , SEEK_SET ) ;
if ( fwrite ( head , sizeof ( head ) , 1 , ef - > 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 )
{
2008-11-13 08:31:13 -08:00
unsigned int flag ;
int ibuf [ EET_FILE2_DIRECTORY_ENTRY_COUNT ] ;
flag = ( efn - > ciphered < < 1 ) | efn - > compression ;
2008-02-29 22:38:09 -08:00
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 ) ;
2008-11-13 08:31:13 -08:00
ibuf [ 5 ] = ( int ) htonl ( ( unsigned int ) flag ) ;
2008-02-29 22:38:09 -08:00
if ( fwrite ( ibuf , sizeof ( ibuf ) , 1 , ef - > fp ) ! = 1 )
goto write_error ;
}
}
/* write dictionnary */
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 , ef - > 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 , ef - > fp ) ! = 1 )
goto write_error ;
}
}
/* write strings */
if ( ef - > ed )
2008-04-10 02:12:43 -07:00
{
for ( j = 0 ; j < ef - > ed - > count ; + + j )
{
if ( ef - > ed - > all [ j ] . str )
{
if ( fwrite ( ef - > ed - > all [ j ] . str , ef - > ed - > all [ j ] . len , 1 , ef - > fp ) ! = 1 )
goto write_error ;
}
else
{
if ( fwrite ( ef - > ed - > all [ j ] . mmap , ef - > ed - > all [ j ] . len , 1 , ef - > fp ) ! = 1 )
goto write_error ;
}
}
}
2008-02-29 22:38:09 -08:00
/* 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 , ef - > fp ) ! = 1 )
goto write_error ;
}
}
2008-09-08 02:19:57 -07:00
/* flush all write to the file. */
fflush ( ef - > fp ) ;
2009-03-17 18:47:33 -07:00
// this is going to really cause trouble. if ANYTHING this needs to go into a
// thread spawned off - but even then...
// in this case... ext4 is "wrong". (yes we can jump up and down and point posix
// manual pages at eachother, but ext4 broke behavior that has been in place
// for decades and that 1000's of apps rely on daily - that is that one operation
// to disk is committed to disk BEFORE following operations, so the fs retains
// a consistent state
// fsync(fileno(ef->fp));
2008-09-08 02:19:57 -07:00
/* append signature if required */
if ( ef - > key )
{
error = eet_identity_sign ( ef - > fp , ef - > key ) ;
if ( error ! = EET_ERROR_NONE )
goto sign_error ;
}
2008-02-29 22:38:09 -08:00
/* no more writes pending */
ef - > writes_pending = 0 ;
return EET_ERROR_NONE ;
2008-03-28 07:37:29 -07:00
write_error :
2008-10-13 05:09:31 -07:00
if ( ferror ( ef - > fp ) )
2008-02-29 22:38:09 -08:00
{
2008-10-13 05:09:31 -07:00
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 ;
}
2008-02-29 22:38:09 -08:00
}
2008-09-08 04:17:04 -07:00
sign_error :
2008-08-13 09:40:53 -07:00
if ( ef - > fp ) fclose ( ef - > fp ) ;
2008-02-29 22:38:09 -08:00
ef - > fp = NULL ;
return error ;
}
2008-04-03 12:30:08 -07:00
#if 0 /* Unused */
2002-12-02 15:39:26 -08:00
/* flush out writes to an eet file */
2006-05-19 19:44:24 -07:00
static Eet_Error
2002-12-02 15:39:26 -08:00
eet_flush ( Eet_File * ef )
{
2006-06-13 03:20:22 -07:00
Eet_File_Node * efn ;
int head [ 3 ] ;
int count = 0 ;
int size = 0 ;
int offset = 0 ;
int i ;
int num ;
2005-05-22 21:32:04 -07:00
/* check to see its' an eet file pointer */
2006-06-13 03:20:22 -07:00
if ( eet_check_pointer ( ef ) )
2006-05-19 19:44:24 -07:00
return EET_ERROR_BAD_OBJECT ;
2006-06-13 03:20:22 -07:00
if ( eet_check_header ( ef ) )
return EET_ERROR_EMPTY ;
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 ;
2002-12-02 15:39:26 -08:00
/* calculate total size in bytes of directory block */
2005-05-25 23:15:48 -07:00
num = ( 1 < < ef - > header - > directory - > size ) ;
2002-12-02 15:39:26 -08:00
for ( i = 0 ; i < num ; i + + )
{
2005-05-25 20:57:57 -07:00
for ( efn = ef - > header - > directory - > nodes [ i ] ; efn ; efn = efn - > next )
2002-12-02 15:39:26 -08:00
{
2007-05-02 04:08:41 -07:00
size + = 20 + strlen ( efn - > name ) + 1 ;
count + + ;
2002-12-02 15:39:26 -08:00
}
}
2006-06-13 03:20:22 -07:00
/* calculate offsets per entry */
2002-12-02 15:39:26 -08:00
offset = 0 ;
for ( i = 0 ; i < num ; i + + )
{
2005-05-25 20:57:57 -07:00
for ( efn = ef - > header - > directory - > nodes [ i ] ; efn ; efn = efn - > next )
2002-12-02 15:39:26 -08:00
{
2007-05-02 04:08:41 -07:00
efn - > offset = 12 + size + offset ;
offset + = efn - > size ;
2002-12-02 15:39:26 -08:00
}
}
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
/* go thru and write the header */
2007-09-10 08:26:42 -07:00
head [ 0 ] = ( int ) htonl ( ( unsigned int ) EET_MAGIC_FILE ) ;
head [ 1 ] = ( int ) htonl ( ( unsigned int ) count ) ;
head [ 2 ] = ( int ) htonl ( ( unsigned int ) size ) ;
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
fseek ( ef - > fp , 0 , SEEK_SET ) ;
2006-06-13 03:20:22 -07:00
if ( fwrite ( head , 12 , 1 , ef - > fp ) ! = 1 )
goto write_error ;
2002-12-02 15:39:26 -08:00
for ( i = 0 ; i < num ; i + + )
{
2005-05-25 20:57:57 -07:00
for ( efn = ef - > header - > directory - > nodes [ i ] ; efn ; efn = efn - > next )
2002-12-02 15:39:26 -08:00
{
2007-09-10 08:26:42 -07:00
unsigned int ibuf [ 5 ] ;
2007-05-02 04:08:41 -07:00
int name_size ;
2008-01-24 00:41:23 -08:00
2007-05-02 04:08:41 -07:00
name_size = strlen ( efn - > name ) + 1 ;
2008-01-24 00:41:23 -08:00
2007-09-10 08:26:42 -07:00
ibuf [ 0 ] = ( int ) htonl ( ( unsigned int ) efn - > offset ) ;
ibuf [ 1 ] = ( int ) htonl ( ( unsigned int ) efn - > compression ) ;
ibuf [ 2 ] = ( int ) htonl ( ( unsigned int ) efn - > size ) ;
ibuf [ 3 ] = ( int ) htonl ( ( unsigned int ) efn - > data_size ) ;
ibuf [ 4 ] = ( int ) htonl ( ( unsigned int ) name_size ) ;
2008-01-24 00:41:23 -08:00
2007-05-02 04:08:41 -07:00
if ( fwrite ( ibuf , sizeof ( ibuf ) , 1 , ef - > fp ) ! = 1 )
goto write_error ;
if ( fwrite ( efn - > name , name_size , 1 , ef - > fp ) ! = 1 )
goto write_error ;
2002-12-02 15:39:26 -08:00
}
}
2008-01-24 00:41:23 -08:00
2002-12-02 15:39:26 -08:00
/* write data */
for ( i = 0 ; i < num ; i + + )
{
2005-05-25 20:57:57 -07:00
for ( efn = ef - > header - > directory - > nodes [ i ] ; efn ; efn = efn - > next )
2002-12-02 15:39:26 -08:00
{
2007-05-02 04:08:41 -07:00
if ( fwrite ( efn - > data , efn - > size , 1 , ef - > fp ) ! = 1 )
goto write_error ;
2002-12-02 15:39:26 -08:00
}
}
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
/* no more writes pending */
ef - > writes_pending = 0 ;
2008-01-24 00:41:23 -08:00
2006-05-19 19:44:24 -07:00
return EET_ERROR_NONE ;
2008-01-24 00:41:23 -08:00
2008-03-28 07:37:29 -07:00
write_error :
2008-10-13 05:09:31 -07:00
if ( ferror ( ef - > fp ) )
2006-06-13 03:20:22 -07:00
{
2008-10-13 05:09:31 -07:00
switch ( errno )
{
case EFBIG :
fclose ( ef - > fp ) ;
ef - > fp = NULL ;
return EET_ERROR_WRITE_ERROR_FILE_TOO_BIG ;
case EIO :
fclose ( ef - > fp ) ;
ef - > fp = NULL ;
return EET_ERROR_WRITE_ERROR_IO_ERROR ;
case ENOSPC :
fclose ( ef - > fp ) ;
ef - > fp = NULL ;
return EET_ERROR_WRITE_ERROR_OUT_OF_SPACE ;
case EPIPE :
fclose ( ef - > fp ) ;
ef - > fp = NULL ;
return EET_ERROR_WRITE_ERROR_FILE_CLOSED ;
default :
fclose ( ef - > fp ) ;
ef - > fp = NULL ;
return EET_ERROR_WRITE_ERROR ;
}
2006-06-13 03:20:22 -07:00
}
2008-09-08 02:19:57 -07:00
sign_error :
2008-10-13 05:09:31 -07:00
if ( ef - > fp ) fclose ( ef - > fp ) ;
2006-08-14 23:45:51 -07:00
ef - > fp = NULL ;
2006-06-13 03:20:22 -07:00
return EET_ERROR_WRITE_ERROR ;
2002-12-02 15:39:26 -08:00
}
2008-04-03 12:30:08 -07:00
# endif
2002-12-02 15:39:26 -08:00
2008-03-07 01:59:37 -08:00
EAPI int
2005-11-03 07:05:21 -08:00
eet_init ( void )
{
2008-09-19 04:30:42 -07:00
eet_initcount + + ;
2008-09-08 02:19:57 -07:00
2008-09-19 04:30:42 -07:00
if ( eet_initcount > 1 ) return eet_initcount ;
2008-09-08 02:19:57 -07:00
2008-11-13 08:31:13 -08:00
# ifdef HAVE_GNUTLS
if ( gnutls_global_init ( ) )
return - - eet_initcount ;
2009-03-25 09:26:46 -07:00
/* Before the library can be used, it must initialize itself if needed. */
if ( gcry_control ( GCRYCTL_ANY_INITIALIZATION_P ) = = 0 )
2008-11-13 08:31:13 -08:00
{
2009-03-25 09:26:46 -07:00
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 ) )
{
gnutls_global_deinit ( ) ;
return - - eet_initcount ;
}
/* 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 ) )
{
gnutls_global_deinit ( ) ;
return - - eet_initcount ;
}
2008-11-13 08:31:13 -08:00
}
# endif
2008-09-19 04:30:42 -07:00
# ifdef HAVE_OPENSSL
ERR_load_crypto_strings ( ) ;
2008-11-14 09:34:51 -08:00
OpenSSL_add_all_algorithms ( ) ;
2008-09-08 02:19:57 -07:00
# endif
2008-09-19 04:30:42 -07:00
2008-10-20 02:44:34 -07:00
eina_init ( ) ;
2008-09-19 04:30:42 -07:00
return eet_initcount ;
2005-11-03 07:05:21 -08:00
}
2008-03-07 01:59:37 -08:00
EAPI int
2005-11-03 07:05:21 -08:00
eet_shutdown ( void )
{
2008-09-19 04:30:42 -07:00
eet_initcount - - ;
if ( eet_initcount > 0 ) return eet_initcount ;
eet_clearcache ( ) ;
2008-11-13 08:31:13 -08:00
# ifdef HAVE_GNUTLS
gnutls_global_deinit ( ) ;
# endif
2008-09-19 04:30:42 -07:00
# ifdef HAVE_OPENSSL
2008-11-14 09:34:51 -08:00
EVP_cleanup ( ) ;
2008-09-19 04:30:42 -07:00
ERR_free_strings ( ) ;
# endif
2005-11-03 07:05:21 -08:00
2008-10-20 02:44:34 -07:00
eina_shutdown ( ) ;
2005-11-03 07:05:21 -08:00
return eet_initcount ;
}
2008-03-07 01:59:37 -08:00
EAPI void
2006-06-13 03:20:22 -07:00
eet_clearcache ( void )
2005-11-03 05:05:52 -08:00
{
2006-06-13 03:20:22 -07:00
int num = 0 ;
int i ;
2008-01-24 00:41:23 -08:00
2006-06-13 03:20:22 -07:00
/*
2008-03-28 07:37:29 -07:00
* 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 .
*/
2006-06-13 03:20:22 -07:00
for ( i = 0 ; i < eet_writers_num ; i + + )
{
2008-03-28 07:37:29 -07:00
if ( eet_writers [ i ] - > references < = 0 ) num + + ;
2006-06-13 03:20:22 -07:00
}
2008-01-24 00:41:23 -08:00
2006-06-13 03:20:22 -07:00
for ( i = 0 ; i < eet_readers_num ; i + + )
{
2008-03-28 07:37:29 -07:00
if ( eet_readers [ i ] - > references < = 0 ) num + + ;
2006-06-13 03:20:22 -07:00
}
if ( num > 0 )
2005-11-03 05:05:52 -08:00
{
2006-06-13 03:20:22 -07:00
Eet_File * * closelist = NULL ;
2008-01-24 00:41:23 -08:00
2006-06-13 03:20:22 -07:00
closelist = alloca ( num * sizeof ( Eet_File * ) ) ;
2005-11-03 05:05:52 -08:00
num = 0 ;
for ( i = 0 ; i < eet_writers_num ; i + + )
{
2006-06-22 12:21:31 -07:00
if ( eet_writers [ i ] - > references < = 0 )
2006-06-13 03:20:22 -07:00
{
closelist [ num ] = eet_writers [ i ] ;
2006-06-22 12:21:31 -07:00
eet_writers [ i ] - > delete_me_now = 1 ;
2006-06-13 03:20:22 -07:00
num + + ;
}
2005-11-03 05:05:52 -08:00
}
2008-01-24 00:41:23 -08:00
2005-11-03 05:05:52 -08:00
for ( i = 0 ; i < eet_readers_num ; i + + )
{
2006-06-22 12:21:31 -07:00
if ( eet_readers [ i ] - > references < = 0 )
2005-11-03 05:05:52 -08:00
{
2006-06-13 03:20:22 -07:00
closelist [ num ] = eet_readers [ i ] ;
2006-06-22 12:21:31 -07:00
eet_readers [ i ] - > delete_me_now = 1 ;
2006-06-13 03:20:22 -07:00
num + + ;
2005-11-03 05:05:52 -08:00
}
}
2008-01-20 17:09:51 -08:00
2006-06-13 03:20:22 -07:00
for ( i = 0 ; i < num ; i + + )
2008-03-01 20:56:57 -08:00
{
eet_close ( closelist [ i ] ) ;
}
2005-11-03 05:05:52 -08:00
}
}
2008-02-29 22:38:09 -08:00
/* FIXME: MMAP race condition in READ_WRITE_MODE */
2008-03-28 07:37:29 -07:00
static Eet_File *
2008-02-29 22:38:09 -08:00
eet_internal_read2 ( Eet_File * ef )
2008-01-20 17:09:51 -08:00
{
2008-02-29 22:38:09 -08:00
const int * data = ( const int * ) ef - > data ;
const char * start = ( const char * ) ef - > data ;
int index = 0 ;
int num_directory_entries ;
int bytes_directory_entries ;
int num_dictionary_entries ;
int bytes_dictionary_entries ;
2008-09-08 02:19:57 -07:00
int signature_base_offset ;
2008-02-29 22:38:09 -08:00
int i ;
2008-01-20 17:09:51 -08:00
2008-02-29 22:38:09 -08:00
index + = sizeof ( int ) ;
if ( eet_test_close ( ( int ) ntohl ( * data ) ! = EET_MAGIC_FILE2 , ef ) )
2008-01-20 17:09:51 -08:00
return NULL ;
2008-02-29 22:38:09 -08:00
data + + ;
2008-01-20 17:09:51 -08:00
2008-02-29 22:38:09 -08:00
# 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 , index ) ;
/* get dictionary count and byte count */
GET_INT ( num_dictionary_entries , data , index ) ;
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 cant have <= 0 values here - invalid */
if ( eet_test_close ( ( num_directory_entries < = 0 ) , ef ) )
return NULL ;
/* we cant 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 = calloc ( 1 , sizeof ( Eet_File_Header ) ) ;
if ( eet_test_close ( ! ef - > header , ef ) )
2008-01-20 17:09:51 -08:00
return NULL ;
2008-02-29 22:38:09 -08:00
ef - > header - > magic = EET_MAGIC_FILE_HEADER ;
/* allocate directory block in ram */
ef - > header - > directory = calloc ( 1 , sizeof ( Eet_File_Directory ) ) ;
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 ;
2008-09-08 02:19:57 -07:00
signature_base_offset = 0 ;
2008-02-29 22:38:09 -08:00
/* 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 ;
int name_offset ;
int name_size ;
int hash ;
2008-11-13 08:31:13 -08:00
int flag ;
2008-02-29 22:38:09 -08:00
/* out directory block is inconsistent - we have oveerun our */
/* dynamic block buffer before we finished scanning dir entries */
efn = malloc ( sizeof ( Eet_File_Node ) ) ;
if ( eet_test_close ( ! efn , ef ) )
return NULL ;
/* get entrie header */
GET_INT ( efn - > offset , data , index ) ;
GET_INT ( efn - > size , data , index ) ;
GET_INT ( efn - > data_size , data , index ) ;
GET_INT ( name_offset , data , index ) ;
GET_INT ( name_size , data , index ) ;
2008-11-13 08:31:13 -08:00
GET_INT ( flag , data , index ) ;
efn - > compression = flag & 0x1 ? 1 : 0 ;
efn - > ciphered = flag & 0x2 ? 1 : 0 ;
2008-02-29 22:38:09 -08:00
# define EFN_TEST(Test, Ef, Efn) \
if ( eet_test_close ( Test , Ef ) ) \
{ \
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 ) ;
}
2008-09-08 02:19:57 -07:00
/* compute the possible position of a signature */
if ( signature_base_offset < efn - > offset + efn - > size )
signature_base_offset = efn - > offset + efn - > size ;
2008-02-29 22:38:09 -08:00
}
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 ;
2008-10-13 04:51:10 -07:00
if ( eet_test_close ( ( num_dictionary_entries * ( int ) EET_FILE2_DICTIONARY_ENTRY_SIZE + index ) > ( bytes_dictionary_entries + bytes_directory_entries ) , ef ) )
2008-02-29 22:38:09 -08:00
return NULL ;
ef - > ed = calloc ( 1 , sizeof ( Eet_Dictionary ) ) ;
if ( eet_test_close ( ! ef - > ed , ef ) ) return NULL ;
ef - > ed - > all = calloc ( num_dictionary_entries , sizeof ( Eet_String ) ) ;
if ( eet_test_close ( ! ef - > ed - > all , ef ) ) return NULL ;
ef - > ed - > count = num_dictionary_entries ;
2008-03-09 09:16:40 -07:00
ef - > ed - > total = num_dictionary_entries ;
2008-03-06 09:52:59 -08:00
ef - > ed - > start = start + bytes_dictionary_entries + bytes_directory_entries ;
ef - > ed - > end = ef - > ed - > start ;
2008-03-07 01:59:37 -08:00
2008-02-29 22:38:09 -08:00
for ( j = 0 ; j < ef - > ed - > count ; + + j )
{
int hash ;
int offset ;
GET_INT ( hash , dico , index ) ;
GET_INT ( offset , dico , index ) ;
GET_INT ( ef - > ed - > all [ j ] . len , dico , index ) ;
GET_INT ( ef - > ed - > all [ j ] . prev , dico , index ) ;
GET_INT ( ef - > ed - > all [ j ] . next , dico , index ) ;
/* 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 ] . mmap = start + offset ;
ef - > ed - > all [ j ] . str = NULL ;
2008-03-06 09:52:59 -08:00
if ( ef - > ed - > all [ j ] . mmap + ef - > ed - > all [ j ] . len > ef - > ed - > end )
ef - > ed - > end = ef - > ed - > all [ j ] . mmap + ef - > ed - > all [ j ] . len ;
2008-02-29 22:38:09 -08:00
/* Check '\0' at the end of the string */
if ( eet_test_close ( ef - > ed - > all [ j ] . mmap [ ef - > ed - > all [ j ] . len - 1 ] ! = ' \0 ' , ef ) ) return NULL ;
2008-07-17 08:33:40 -07:00
ef - > ed - > all [ j ] . hash = hash ;
2008-02-29 22:38:09 -08:00
if ( ef - > ed - > all [ j ] . prev = = - 1 )
ef - > ed - > hash [ hash ] = j ;
2008-09-08 02:19:57 -07:00
/* 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 ;
2008-02-29 22:38:09 -08:00
}
}
2008-09-08 02:19:57 -07:00
/* Check if the file is signed */
ef - > x509_der = NULL ;
ef - > x509_length = 0 ;
2008-11-26 02:45:47 -08:00
ef - > signature = NULL ;
ef - > signature_length = 0 ;
2008-09-08 02:19:57 -07:00
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 ,
2009-04-16 05:15:56 -07:00
& ef - > sha1 , & ef - > sha1_length ,
2008-09-08 02:19:57 -07:00
buffer , ef - > data_size - signature_base_offset ,
2008-11-26 02:45:47 -08:00
& ef - > signature , & ef - > signature_length ,
2008-09-08 02:19:57 -07:00
& ef - > x509_length ) ;
2008-09-11 07:49:47 -07:00
if ( eet_test_close ( ef - > x509_der = = NULL , ef ) ) return NULL ;
2008-09-08 02:19:57 -07:00
# else
fprintf ( stderr , " This file could be signed but you didn't compile the necessary code to check the signature. \n " ) ;
# endif
}
2008-02-29 22:38:09 -08:00
return ef ;
}
2008-05-19 08:23:41 -07:00
# if EET_OLD_EET_FILE_FORMAT
2008-03-28 07:37:29 -07:00
static Eet_File *
2008-02-29 22:38:09 -08:00
eet_internal_read1 ( Eet_File * ef )
{
const unsigned char * dyn_buf = NULL ;
const unsigned char * p = NULL ;
int index = 0 ;
int num_entries ;
int byte_entries ;
int i ;
2008-05-19 08:23:41 -07:00
fprintf ( stderr , " 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 ) ;
2008-01-20 17:09:51 -08:00
/* build header table if read mode */
/* geat header */
index + = 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 , index ) ;
EXTRACT_INT ( byte_entries , ef - > data , index ) ;
/* we cant have <= 0 values here - invalid */
if ( eet_test_close ( ( num_entries < = 0 ) | | ( byte_entries < = 0 ) , 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 ;
2008-02-29 22:38:09 -08:00
/* check we will not outrun the file limit */
2008-10-13 04:51:10 -07:00
if ( eet_test_close ( ( ( byte_entries + ( int ) sizeof ( int ) * 3 ) > ef - > data_size ) , ef ) )
2008-02-29 22:38:09 -08:00
return NULL ;
2008-01-20 17:09:51 -08:00
/* allocate header */
ef - > header = calloc ( 1 , sizeof ( Eet_File_Header ) ) ;
if ( eet_test_close ( ! ef - > header , ef ) )
return NULL ;
ef - > header - > magic = EET_MAGIC_FILE_HEADER ;
/* allocate directory block in ram */
ef - > header - > directory = calloc ( 1 , sizeof ( Eet_File_Directory ) ) ;
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 + index ;
/* 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 oveerun 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 = malloc ( sizeof ( Eet_File_Node ) ) ;
if ( eet_test_close ( ! efn , ef ) )
return NULL ;
2008-02-29 22:38:09 -08:00
/* get entrie header */
2008-01-20 17:09:51 -08:00
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 ) ;
2008-02-29 22:38:09 -08:00
efn - > name_size = name_size ;
2008-11-13 08:31:13 -08:00
efn - > ciphered = 0 ;
2008-02-29 22:38:09 -08:00
2008-01-20 17:09:51 -08:00
/* invalid size */
if ( eet_test_close ( efn - > size < = 0 , ef ) )
{
free ( efn ) ;
return NULL ;
}
/* invalid name_size */
if ( eet_test_close ( name_size < = 0 , ef ) )
{
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 ) )
{
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 = = NULL , ef ) )
{
free ( efn ) ;
return NULL ;
}
strncpy ( efn - > name , ( char * ) p + HEADER_SIZE , name_size ) ;
efn - > name [ name_size ] = 0 ;
printf ( " File: %s is not up to date for key \" %s \" - needs rebuilding sometime \n " , ef - > path , efn - > name ) ;
}
else
/* The only really usefull 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 ;
}
2008-05-19 08:23:41 -07:00
# endif
2008-01-20 17:09:51 -08:00
2008-03-28 07:37:29 -07:00
static Eet_File *
2008-02-29 22:38:09 -08:00
eet_internal_read ( Eet_File * ef )
{
const int * data = ( const int * ) ef - > data ;
if ( eet_test_close ( ( ef - > data = = ( void * ) - 1 ) | | ( ef - > data = = NULL ) , ef ) )
return NULL ;
2008-03-29 00:28:18 -07:00
2008-10-13 04:51:10 -07:00
if ( eet_test_close ( ef - > data_size < ( int ) sizeof ( int ) * 3 , ef ) )
2008-02-29 22:38:09 -08:00
return NULL ;
switch ( ntohl ( * data ) )
{
2008-05-19 08:23:41 -07:00
# if EET_OLD_EET_FILE_FORMAT
2008-02-29 22:38:09 -08:00
case EET_MAGIC_FILE :
2008-03-28 07:37:29 -07:00
return eet_internal_read1 ( ef ) ;
2008-05-19 08:23:41 -07:00
# endif
2008-02-29 22:38:09 -08:00
case EET_MAGIC_FILE2 :
2008-03-28 07:37:29 -07:00
return eet_internal_read2 ( ef ) ;
2008-02-29 22:38:09 -08:00
default :
2008-03-28 07:37:29 -07:00
ef - > delete_me_now = 1 ;
eet_close ( ef ) ;
break ;
2008-02-29 22:38:09 -08:00
}
2008-03-29 00:28:18 -07:00
2008-02-29 22:38:09 -08:00
return NULL ;
}
2008-03-07 01:59:37 -08:00
EAPI Eet_File *
2008-01-20 17:09:51 -08:00
eet_memopen_read ( const void * data , size_t size )
{
Eet_File * ef ;
if ( data = = NULL | | size = = 0 )
return NULL ;
ef = malloc ( sizeof ( Eet_File ) ) ;
if ( ! ef )
return NULL ;
2008-02-29 22:38:09 -08:00
ef - > ed = NULL ;
2008-01-20 17:09:51 -08:00
ef - > path = NULL ;
2008-09-08 02:19:57 -07:00
ef - > key = NULL ;
2008-01-20 17:09:51 -08:00
ef - > magic = EET_MAGIC_FILE ;
ef - > references = 1 ;
ef - > mode = EET_FILE_MODE_READ ;
ef - > header = NULL ;
ef - > mtime = 0 ;
ef - > delete_me_now = 1 ;
ef - > fp = NULL ;
2008-09-03 06:52:45 -07:00
ef - > readfp = NULL ;
2008-01-20 17:09:51 -08:00
ef - > data = data ;
ef - > data_size = size ;
2009-02-09 05:53:20 -08:00
ef - > sha1 = NULL ;
ef - > sha1_length = 0 ;
2008-01-20 17:09:51 -08:00
return eet_internal_read ( ef ) ;
}
2008-03-07 01:59:37 -08:00
EAPI Eet_File *
2005-01-17 00:27:23 -08:00
eet_open ( const char * file , Eet_File_Mode mode )
2002-12-02 15:39:26 -08:00
{
2008-01-20 17:09:51 -08:00
FILE * fp ;
2006-06-13 03:20:22 -07:00
Eet_File * ef ;
2008-05-19 08:25:46 -07:00
int file_len ;
2008-01-20 17:09:51 -08:00
struct stat file_stat ;
2006-06-13 03:20:22 -07:00
if ( ! file )
return NULL ;
2003-01-12 22:22:02 -08:00
2002-12-02 15:39:26 -08:00
/* find the current file handle in cache*/
ef = NULL ;
if ( mode = = EET_FILE_MODE_READ )
2005-11-03 07:05:21 -08:00
{
2005-11-03 19:22:22 -08:00
ef = eet_cache_find ( ( char * ) file , eet_writers , eet_writers_num ) ;
2005-11-03 07:05:21 -08:00
if ( ef )
{
2008-02-29 22:38:09 -08:00
eet_flush2 ( ef ) ;
2008-03-09 09:16:40 -07:00
ef - > references + + ;
2005-11-03 07:05:21 -08:00
ef - > delete_me_now = 1 ;
2006-06-13 03:20:22 -07:00
eet_close ( ef ) ;
2005-11-03 07:05:21 -08:00
}
2005-11-03 19:22:22 -08:00
ef = eet_cache_find ( ( char * ) file , eet_readers , eet_readers_num ) ;
2005-11-03 07:05:21 -08:00
}
2008-01-24 00:41:23 -08:00
else if ( ( mode = = EET_FILE_MODE_WRITE ) | |
2008-01-20 17:09:51 -08:00
( mode = = EET_FILE_MODE_READ_WRITE ) )
2005-11-03 07:05:21 -08:00
{
2005-11-03 19:22:22 -08:00
ef = eet_cache_find ( ( char * ) file , eet_readers , eet_readers_num ) ;
2006-06-13 03:20:22 -07:00
if ( ef )
{
ef - > delete_me_now = 1 ;
2008-03-09 09:16:40 -07:00
ef - > references + + ;
2006-06-13 03:20:22 -07:00
eet_close ( ef ) ;
}
2005-11-03 19:22:22 -08:00
ef = eet_cache_find ( ( char * ) file , eet_writers , eet_writers_num ) ;
2005-11-03 07:05:21 -08:00
}
2006-06-13 03:20:22 -07:00
2008-01-20 17:09:51 -08:00
/* try open the file based on mode */
if ( ( mode = = EET_FILE_MODE_READ ) | | ( mode = = EET_FILE_MODE_READ_WRITE ) )
2006-06-13 03:20:22 -07:00
{
2008-01-20 17:09:51 -08:00
fp = fopen ( file , " rb " ) ;
2008-05-16 03:00:54 -07:00
if ( ! fp ) goto on_error ;
2008-01-20 17:09:51 -08:00
if ( fstat ( fileno ( fp ) , & file_stat ) )
{
fclose ( fp ) ;
2008-05-16 03:00:54 -07:00
fp = NULL ;
goto on_error ;
2008-01-20 17:09:51 -08:00
}
if ( ( mode = = EET_FILE_MODE_READ ) & &
2008-10-13 04:51:10 -07:00
( file_stat . st_size < ( ( int ) sizeof ( int ) * 3 ) ) )
2008-01-20 17:09:51 -08:00
{
fclose ( fp ) ;
2008-05-16 03:00:54 -07:00
fp = NULL ;
goto on_error ;
2008-01-20 17:09:51 -08:00
}
2008-05-16 03:00:54 -07:00
on_error :
if ( fp = = NULL & & mode = = EET_FILE_MODE_READ ) return NULL ;
2008-01-20 17:09:51 -08:00
}
else
2007-11-11 22:15:08 -08:00
{
2008-09-08 04:53:59 -07:00
int fd ;
2008-01-20 17:09:51 -08:00
if ( mode ! = EET_FILE_MODE_WRITE ) return NULL ;
memset ( & file_stat , 0 , sizeof ( file_stat ) ) ;
/* opening for write - delete old copy of file right away */
unlink ( file ) ;
2008-09-08 04:53:59 -07:00
fd = open ( file , O_CREAT | O_TRUNC | O_RDWR , S_IRUSR | S_IWUSR ) ;
fp = fdopen ( fd , " wb " ) ;
if ( ! fp ) return NULL ;
2007-11-11 22:15:08 -08:00
}
2008-01-24 00:41:23 -08:00
2006-06-13 03:20:22 -07:00
/* We found one */
if ( ef & & ( file_stat . st_mtime ! = ef - > mtime ) )
{
ef - > delete_me_now = 1 ;
2008-03-01 20:56:57 -08:00
ef - > references + + ;
2006-06-13 03:20:22 -07:00
eet_close ( ef ) ;
ef = NULL ;
}
2008-01-20 17:09:51 -08:00
2002-12-02 15:39:26 -08:00
if ( ef )
{
/* reference it up and return it */
2008-05-16 03:00:54 -07:00
if ( fp ! = NULL ) fclose ( fp ) ;
2002-12-02 15:39:26 -08:00
ef - > references + + ;
return ef ;
}
2005-05-22 21:32:04 -07:00
2008-05-19 08:25:46 -07:00
file_len = strlen ( file ) + 1 ;
2006-06-13 03:20:22 -07:00
/* Allocate struct for eet file and have it zero'd out */
2008-05-19 08:25:46 -07:00
ef = malloc ( sizeof ( Eet_File ) + file_len ) ;
2006-06-13 03:20:22 -07:00
if ( ! ef )
return NULL ;
2005-05-22 21:32:04 -07:00
2002-12-02 15:39:26 -08:00
/* fill some of the members */
2008-01-20 17:09:51 -08:00
ef - > fp = fp ;
2008-09-08 02:19:57 -07:00
ef - > key = NULL ;
2008-03-09 09:16:40 -07:00
ef - > readfp = NULL ;
2005-11-03 19:22:22 -08:00
ef - > path = ( ( char * ) ef ) + sizeof ( Eet_File ) ;
2008-05-19 08:25:46 -07:00
memcpy ( ef - > path , file , file_len ) ;
2002-12-02 15:39:26 -08:00
ef - > magic = EET_MAGIC_FILE ;
ef - > references = 1 ;
ef - > mode = mode ;
2006-06-13 03:20:22 -07:00
ef - > header = NULL ;
ef - > mtime = file_stat . st_mtime ;
2008-06-08 20:19:25 -07:00
ef - > writes_pending = 0 ;
2006-06-13 03:20:22 -07:00
ef - > delete_me_now = 0 ;
2006-08-17 13:22:23 -07:00
ef - > data = NULL ;
ef - > data_size = 0 ;
2009-02-09 05:53:20 -08:00
ef - > sha1 = NULL ;
ef - > sha1_length = 0 ;
2002-12-02 15:39:26 -08:00
2008-05-16 03:00:54 -07:00
ef - > ed = ( mode = = EET_FILE_MODE_WRITE )
| | ( ef - > fp = = NULL & & mode = = EET_FILE_MODE_READ_WRITE ) ?
eet_dictionary_add ( ) : NULL ;
if ( ef - > fp = = NULL & & mode = = EET_FILE_MODE_READ_WRITE ) goto empty_file ;
2008-02-29 22:38:09 -08:00
2002-12-02 15:39:26 -08:00
/* if we can't open - bail out */
2006-06-13 03:20:22 -07:00
if ( eet_test_close ( ! ef - > fp , ef ) )
return NULL ;
2006-06-22 12:21:31 -07:00
fcntl ( fileno ( ef - > fp ) , F_SETFD , FD_CLOEXEC ) ;
2004-10-19 20:13:44 -07:00
/* if we opened for read or read-write */
2005-03-03 09:26:46 -08:00
if ( ( mode = = EET_FILE_MODE_READ ) | | ( mode = = EET_FILE_MODE_READ_WRITE ) )
2002-12-02 15:39:26 -08:00
{
2006-06-13 03:20:22 -07:00
ef - > data_size = file_stat . st_size ;
2006-09-15 22:57:36 -07:00
ef - > data = mmap ( NULL , ef - > data_size , PROT_READ ,
MAP_SHARED , fileno ( ef - > fp ) , 0 ) ;
2008-06-08 20:07:35 -07:00
if ( eet_test_close ( ( ef - > data = = MAP_FAILED ) , ef ) )
return NULL ;
2008-01-20 17:09:51 -08:00
ef = eet_internal_read ( ef ) ;
if ( ! ef )
2006-06-13 03:20:22 -07:00
return NULL ;
2002-12-02 15:39:26 -08:00
}
2004-10-19 20:13:44 -07:00
2008-05-16 03:00:54 -07:00
empty_file :
2004-10-19 20:13:44 -07:00
/* we need to delete the original file in read-write mode and re-open for writing */
2005-03-03 09:26:46 -08:00
if ( ef - > mode = = EET_FILE_MODE_READ_WRITE )
2004-10-19 20:13:44 -07:00
{
2008-03-09 09:16:40 -07:00
ef - > readfp = ef - > fp ;
2008-08-13 09:40:53 -07:00
ef - > fp = NULL ;
2004-10-19 20:13:44 -07:00
}
2002-12-02 15:39:26 -08:00
/* add to cache */
2005-11-03 07:05:21 -08:00
if ( ef - > references = = 1 )
{
if ( ef - > mode = = EET_FILE_MODE_READ )
eet_cache_add ( ef , & eet_readers , & eet_readers_num , & eet_readers_alloc ) ;
2006-06-13 03:20:22 -07:00
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 ) ;
2005-11-03 07:05:21 -08:00
}
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
return ef ;
}
2008-03-07 01:59:37 -08:00
EAPI Eet_File_Mode
2005-02-07 10:10:20 -08:00
eet_mode_get ( Eet_File * ef )
{
2005-05-22 21:32:04 -07:00
/* check to see its' an eet file pointer */
2005-02-07 10:10:20 -08:00
if ( ( ! ef ) | | ( ef - > magic ! = EET_MAGIC_FILE ) )
return EET_FILE_MODE_INVALID ;
else
return ef - > mode ;
}
2008-09-08 02:19:57 -07:00
EAPI const void *
eet_identity_x509 ( Eet_File * ef , int * der_length )
{
if ( ! ef - > x509_der ) return NULL ;
if ( der_length ) * der_length = ef - > x509_length ;
return ef - > x509_der ;
}
2008-11-26 02:45:47 -08:00
EAPI const void *
eet_identity_signature ( Eet_File * ef , int * signature_length )
{
if ( ! ef - > signature ) return NULL ;
if ( signature_length ) * signature_length = ef - > signature_length ;
return ef - > signature ;
}
2009-02-09 05:53:20 -08:00
EAPI const void *
eet_identity_sha1 ( Eet_File * ef , int * sha1_length )
{
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 ;
}
2008-09-08 02:19:57 -07:00
EAPI Eet_Error
eet_identity_set ( Eet_File * ef , Eet_Key * key )
{
Eet_Key * tmp = ef - > key ;
if ( ! ef ) return EET_ERROR_BAD_OBJECT ;
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 ;
}
2008-03-07 01:59:37 -08:00
EAPI Eet_Error
2002-12-02 15:39:26 -08:00
eet_close ( Eet_File * ef )
{
2006-05-19 19:44:24 -07:00
Eet_Error err ;
2006-06-13 03:20:22 -07:00
2005-05-22 21:32:04 -07:00
/* check to see its' an eet file pointer */
2006-06-13 03:20:22 -07:00
if ( eet_check_pointer ( ef ) )
2006-05-19 19:44:24 -07:00
return EET_ERROR_BAD_OBJECT ;
2002-12-02 15:39:26 -08:00
/* deref */
ef - > references - - ;
/* if its still referenced - dont go any further */
2006-05-19 19:44:24 -07:00
if ( ef - > references > 0 ) return EET_ERROR_NONE ;
2006-06-13 03:20:22 -07:00
/* flush any writes */
2008-02-29 22:38:09 -08:00
err = eet_flush2 ( ef ) ;
2006-06-13 03:20:22 -07:00
2008-09-08 02:19:57 -07:00
eet_identity_unref ( ef - > key ) ;
ef - > key = NULL ;
2006-06-13 03:20:22 -07:00
/* if not urgent to delete it - dont free it - leave it in cache */
if ( ( ! ef - > delete_me_now ) & & ( ef - > mode = = EET_FILE_MODE_READ ) )
return EET_ERROR_NONE ;
2008-01-24 00:41:23 -08:00
2002-12-02 15:39:26 -08:00
/* remove from cache */
if ( ef - > mode = = EET_FILE_MODE_READ )
2005-11-03 05:05:52 -08:00
eet_cache_del ( ef , & eet_readers , & eet_readers_num , & eet_readers_alloc ) ;
2005-03-03 09:26:46 -08:00
else if ( ( ef - > mode = = EET_FILE_MODE_WRITE ) | | ( ef - > mode = = EET_FILE_MODE_READ_WRITE ) )
2005-11-03 05:05:52 -08:00
eet_cache_del ( ef , & eet_writers , & eet_writers_num , & eet_writers_alloc ) ;
2002-12-02 15:39:26 -08:00
/* free up data */
2005-05-22 21:32:04 -07:00
if ( ef - > header )
2002-12-02 15:39:26 -08:00
{
if ( ef - > header - > directory )
{
2005-05-25 20:57:57 -07:00
if ( ef - > header - > directory - > nodes )
2002-12-02 15:39:26 -08:00
{
int i , num ;
2008-01-24 00:41:23 -08:00
2005-05-25 20:57:57 -07:00
num = ( 1 < < ef - > header - > directory - > size ) ;
2002-12-02 15:39:26 -08:00
for ( i = 0 ; i < num ; i + + )
{
2005-05-25 20:57:57 -07:00
Eet_File_Node * efn ;
2008-01-24 00:41:23 -08:00
2005-05-25 20:57:57 -07:00
while ( ( efn = ef - > header - > directory - > nodes [ i ] ) )
2002-12-02 15:39:26 -08:00
{
2006-06-13 03:20:22 -07:00
if ( efn - > data )
free ( efn - > data ) ;
2005-05-25 20:57:57 -07:00
ef - > header - > directory - > nodes [ i ] = efn - > next ;
2006-06-13 03:20:22 -07:00
if ( efn - > free_name )
free ( efn - > name ) ;
2005-05-25 20:57:57 -07:00
free ( efn ) ;
2002-12-02 15:39:26 -08:00
}
}
2005-05-25 20:57:57 -07:00
free ( ef - > header - > directory - > nodes ) ;
2002-12-02 15:39:26 -08:00
}
free ( ef - > header - > directory ) ;
}
free ( ef - > header ) ;
}
2008-01-20 17:09:51 -08:00
2008-02-29 22:38:09 -08:00
eet_dictionary_free ( ef - > ed ) ;
2009-04-16 05:15:56 -07:00
if ( ef - > sha1 ) free ( ef - > sha1 ) ;
2008-01-20 17:09:51 -08:00
if ( ef - > data ) munmap ( ( void * ) ef - > data , ef - > data_size ) ;
2006-06-22 12:21:31 -07:00
if ( ef - > fp ) fclose ( ef - > fp ) ;
2008-03-09 09:16:40 -07:00
if ( ef - > readfp ) fclose ( ef - > readfp ) ;
2005-05-22 21:32:04 -07:00
2002-12-02 15:39:26 -08:00
/* zero out ram for struct - caution tactic against stale memory use */
memset ( ef , 0 , sizeof ( Eet_File ) ) ;
2008-01-20 17:09:51 -08:00
2002-12-02 15:39:26 -08:00
/* free it */
free ( ef ) ;
2006-05-19 19:44:24 -07:00
return err ;
2002-12-02 15:39:26 -08:00
}
2008-03-07 01:59:37 -08:00
EAPI void *
2008-11-13 08:31:13 -08:00
eet_read_cipher ( Eet_File * ef , const char * name , int * size_ret , const char * cipher_key )
2002-12-02 15:39:26 -08:00
{
2006-06-13 03:20:22 -07:00
void * data = NULL ;
int size = 0 ;
Eet_File_Node * efn ;
if ( size_ret )
* size_ret = 0 ;
2005-11-29 10:49:30 -08:00
2002-12-02 15:39:26 -08:00
/* check to see its' an eet file pointer */
2006-06-13 03:20:22 -07:00
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 ;
2003-01-12 20:31:00 -08:00
/* no header, return NULL */
2006-06-13 03:20:22 -07:00
if ( eet_check_header ( ef ) )
return NULL ;
2005-11-29 10:49:30 -08:00
2002-12-02 15:39:26 -08:00
/* hunt hash bucket */
2005-11-29 10:49:30 -08:00
efn = find_node_by_name ( ef , name ) ;
2006-06-13 03:20:22 -07:00
if ( ! efn )
return NULL ;
2005-05-22 21:32:04 -07:00
2005-11-29 10:49:30 -08:00
/* get size (uncompressed, if compressed at all) */
size = efn - > data_size ;
2005-11-29 03:44:51 -08:00
2005-11-29 10:49:30 -08:00
/* allocate data */
data = malloc ( size ) ;
2006-06-13 03:20:22 -07:00
if ( ! data )
return NULL ;
2005-05-22 21:32:04 -07:00
2005-11-29 10:49:30 -08:00
/* uncompressed data */
if ( efn - > compression = = 0 )
{
2008-11-13 08:31:13 -08:00
void * data_deciphered = NULL ;
unsigned int data_deciphered_sz = 0 ;
2005-11-29 10:49:30 -08:00
/* if we alreayd have the data in ram... copy that */
if ( efn - > data )
memcpy ( data , efn - > data , efn - > size ) ;
2006-06-13 03:20:22 -07:00
else
if ( ! read_data_from_disk ( ef , efn , data , size ) )
{
free ( data ) ;
return NULL ;
}
2008-11-13 08:31:13 -08:00
if ( efn - > ciphered & & cipher_key )
{
if ( eet_decipher ( data , size , cipher_key , strlen ( cipher_key ) , & data_deciphered , & data_deciphered_sz ) )
{
free ( data ) ;
if ( data_deciphered ) free ( data_deciphered ) ;
return NULL ;
}
free ( data ) ;
data = data_deciphered ;
size = data_deciphered_sz ;
}
2005-11-29 10:49:30 -08:00
}
/* compressed data */
else
{
2006-06-13 03:20:22 -07:00
void * tmp_data ;
2008-11-13 08:31:13 -08:00
void * data_deciphered = NULL ;
unsigned int data_deciphered_sz = 0 ;
2006-06-13 03:20:22 -07:00
int free_tmp = 0 ;
int compr_size = efn - > size ;
uLongf dlen ;
2005-11-29 03:44:51 -08:00
2005-11-29 10:49:30 -08:00
/* 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 )
{
free ( data ) ;
return NULL ;
}
2005-11-29 03:44:51 -08:00
2005-11-29 10:49:30 -08:00
free_tmp = 1 ;
2005-11-29 03:44:51 -08:00
2005-11-29 10:49:30 -08:00
if ( ! read_data_from_disk ( ef , efn , tmp_data , compr_size ) )
{
2006-06-13 03:20:22 -07:00
free ( tmp_data ) ;
2005-11-29 10:49:30 -08:00
free ( data ) ;
return NULL ;
2002-12-02 15:39:26 -08:00
}
}
2005-11-29 10:49:30 -08:00
2008-11-13 08:31:13 -08:00
if ( efn - > ciphered & & cipher_key )
{
if ( eet_decipher ( tmp_data , compr_size , cipher_key , strlen ( cipher_key ) , & data_deciphered , & data_deciphered_sz ) )
{
free ( data ) ;
if ( free_tmp ) free ( tmp_data ) ;
if ( data_deciphered ) free ( data_deciphered ) ;
return NULL ;
}
free ( tmp_data ) ;
tmp_data = data_deciphered ;
compr_size = data_deciphered_sz ;
}
2005-11-29 10:49:30 -08:00
/* decompress it */
dlen = size ;
if ( uncompress ( ( Bytef * ) data , & dlen ,
tmp_data , ( uLongf ) compr_size ) )
{
free ( data ) ;
return NULL ;
}
2006-06-13 03:20:22 -07:00
if ( free_tmp )
free ( tmp_data ) ;
2002-12-02 15:39:26 -08:00
}
2005-11-29 10:49:30 -08:00
2002-12-02 15:39:26 -08:00
/* fill in return values */
2006-06-13 03:20:22 -07:00
if ( size_ret )
* size_ret = size ;
return data ;
}
2008-11-13 08:31:13 -08:00
EAPI void *
eet_read ( Eet_File * ef , const char * name , int * size_ret )
{
return eet_read_cipher ( ef , name , size_ret , NULL ) ;
}
2008-03-07 01:59:37 -08:00
EAPI const void *
2006-06-13 03:20:22 -07:00
eet_read_direct ( Eet_File * ef , const char * name , int * size_ret )
{
2008-01-20 17:09:51 -08:00
const void * data = NULL ;
int size = 0 ;
2006-06-13 03:20:22 -07:00
Eet_File_Node * efn ;
2008-01-24 00:41:23 -08:00
2006-06-13 03:20:22 -07:00
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 ;
/* hunt hash bucket */
efn = find_node_by_name ( ef , name ) ;
if ( ! efn )
return NULL ;
2008-05-16 07:03:11 -07:00
if ( efn - > offset < 0 & & efn - > data = = NULL )
return NULL ;
2006-06-13 03:20:22 -07:00
/* get size (uncompressed, if compressed at all) */
size = efn - > data_size ;
/* uncompressed data */
2008-11-13 08:31:13 -08:00
if ( efn - > compression = = 0
& & efn - > ciphered = = 0 )
2006-06-13 03:20:22 -07:00
data = efn - > data ? efn - > data : ef - > data + efn - > offset ;
/* compressed data */
else
data = NULL ;
/* fill in return values */
if ( size_ret )
* size_ret = size ;
2002-12-02 15:39:26 -08:00
return data ;
}
2008-03-07 01:59:37 -08:00
EAPI int
2008-11-13 08:31:13 -08:00
eet_write_cipher ( Eet_File * ef , const char * name , const void * data , int size , int compress , const char * cipher_key )
2002-12-02 15:39:26 -08:00
{
2006-06-13 03:20:22 -07:00
Eet_File_Node * efn ;
2008-11-13 08:31:13 -08:00
void * data2 = NULL ;
2006-06-13 03:20:22 -07:00
int exists_already = 0 ;
int data_size ;
int hash ;
2005-05-22 21:32:04 -07:00
/* check to see its' an eet file pointer */
2006-06-13 03:20:22 -07:00
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 ) )
2002-12-02 15:39:26 -08:00
return 0 ;
if ( ! ef - > header )
{
/* allocate header */
2005-05-25 20:57:57 -07:00
ef - > header = calloc ( 1 , sizeof ( Eet_File_Header ) ) ;
2006-06-13 03:20:22 -07:00
if ( ! ef - > header )
return 0 ;
2002-12-02 15:39:26 -08:00
ef - > header - > magic = EET_MAGIC_FILE_HEADER ;
/* allocate directory block in ram */
2005-05-25 20:57:57 -07:00
ef - > header - > directory = calloc ( 1 , sizeof ( Eet_File_Directory ) ) ;
2006-06-13 03:20:22 -07:00
if ( ! ef - > header - > directory )
return 0 ;
2002-12-02 15:39:26 -08:00
/* 8 bit hash table (256 buckets) */
ef - > header - > directory - > size = 8 ;
/* allocate base hash table */
2005-05-25 20:57:57 -07:00
ef - > header - > directory - > nodes = calloc ( 1 , sizeof ( Eet_File_Node * ) * ( 1 < < ef - > header - > directory - > size ) ) ;
2006-06-13 03:20:22 -07:00
if ( ! ef - > header - > directory - > nodes )
return 0 ;
2002-12-02 15:39:26 -08:00
}
2005-05-26 03:53:53 -07:00
2005-05-26 03:51:50 -07:00
/* figure hash bucket */
2006-12-28 07:23:47 -08:00
hash = _eet_hash_gen ( name , ef - > header - > directory - > size ) ;
2005-05-26 03:53:53 -07:00
2006-06-13 03:20:22 -07:00
data_size = compress ? 12 + ( ( size * 101 ) / 100 ) : size ;
2005-05-26 03:53:53 -07:00
2008-11-13 08:31:13 -08:00
if ( compress | | ! cipher_key )
{
data2 = malloc ( data_size ) ;
if ( ! data2 )
return 0 ;
}
2005-11-04 09:44:01 -08:00
2002-12-02 15:39:26 -08:00
/* if we want to compress */
2005-05-26 03:02:10 -07:00
if ( compress )
2002-12-02 15:39:26 -08:00
{
uLongf buflen ;
2005-05-22 21:32:04 -07:00
2002-12-02 15:39:26 -08:00
/* compress the data with max compression */
2002-12-14 17:32:13 -08:00
buflen = ( uLongf ) data_size ;
2005-05-26 03:22:56 -07:00
if ( compress2 ( ( Bytef * ) data2 , & buflen , ( Bytef * ) data ,
2005-05-26 03:28:41 -07:00
( uLong ) size , Z_BEST_COMPRESSION ) ! = Z_OK )
2002-12-02 15:39:26 -08:00
{
free ( data2 ) ;
return 0 ;
}
/* record compressed chunk size */
data_size = ( int ) buflen ;
2005-05-26 03:58:22 -07:00
if ( data_size < 0 | | data_size > = size )
2002-12-02 15:39:26 -08:00
{
compress = 0 ;
data_size = size ;
}
2002-12-14 17:32:13 -08:00
else
{
void * data3 ;
2005-05-22 21:32:04 -07:00
2002-12-14 17:32:13 -08:00
data3 = realloc ( data2 , data_size ) ;
2006-06-13 03:20:22 -07:00
if ( data3 )
data2 = data3 ;
2002-12-14 17:32:13 -08:00
}
2002-12-02 15:39:26 -08:00
}
2008-11-13 08:31:13 -08:00
if ( cipher_key )
{
void * data_ciphered = NULL ;
unsigned int data_ciphered_sz = 0 ;
const void * tmp ;
tmp = data2 ? 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 ;
size = ( data_size > size ) ? data_size : size ;
}
else
{
if ( data_ciphered ) free ( data_ciphered ) ;
cipher_key = NULL ;
}
}
else
if ( ! compress )
memcpy ( data2 , data , size ) ;
2004-10-19 20:13:44 -07:00
/* Does this node already exist? */
2007-05-23 05:07:14 -07:00
for ( efn = ef - > header - > directory - > nodes [ hash ] ; efn ; efn = efn - > next )
2002-12-02 15:39:26 -08:00
{
2007-05-23 05:07:14 -07:00
/* if it matches */
if ( ( efn - > name ) & & ( eet_string_match ( efn - > name , name ) ) )
2004-10-19 20:13:44 -07:00
{
2007-05-23 05:07:14 -07:00
free ( efn - > data ) ;
2008-11-13 08:31:13 -08:00
efn - > ciphered = cipher_key ? 1 : 0 ;
2007-05-23 05:07:14 -07:00
efn - > compression = ! ! compress ;
efn - > size = data_size ;
efn - > data_size = size ;
efn - > data = data2 ;
2008-05-16 07:03:11 -07:00
efn - > offset = - 1 ;
2007-05-23 05:07:14 -07:00
exists_already = 1 ;
break ;
2004-10-19 20:13:44 -07:00
}
2002-12-02 15:39:26 -08:00
}
2004-10-19 20:13:44 -07:00
if ( ! exists_already )
{
2006-06-13 03:20:22 -07:00
efn = malloc ( sizeof ( Eet_File_Node ) ) ;
2005-05-25 20:57:57 -07:00
if ( ! efn )
2004-10-19 20:13:44 -07:00
{
2005-11-04 09:44:01 -08:00
free ( data2 ) ;
return 0 ;
}
2006-06-13 03:20:22 -07:00
efn - > name = strdup ( name ) ;
2008-02-29 22:38:09 -08:00
efn - > name_size = strlen ( efn - > name ) + 1 ;
efn - > free_name = 1 ;
2005-05-25 20:57:57 -07:00
efn - > next = ef - > header - > directory - > nodes [ hash ] ;
ef - > header - > directory - > nodes [ hash ] = efn ;
2008-05-16 07:03:11 -07:00
efn - > offset = - 1 ;
2008-11-13 08:31:13 -08:00
efn - > ciphered = cipher_key ? 1 : 0 ;
2005-05-26 04:04:42 -07:00
efn - > compression = ! ! compress ;
2005-05-25 20:57:57 -07:00
efn - > size = data_size ;
efn - > data_size = size ;
efn - > data = data2 ;
2004-10-19 20:13:44 -07:00
}
2002-12-02 15:39:26 -08:00
/* flags that writes are pending */
ef - > writes_pending = 1 ;
2003-06-16 06:39:42 -07:00
return data_size ;
2002-12-02 15:39:26 -08:00
}
2008-11-13 08:31:13 -08:00
EAPI int
eet_write ( Eet_File * ef , const char * name , const void * data , int size , int compress )
{
return eet_write_cipher ( ef , name , data , size , compress , NULL ) ;
}
2008-03-07 01:59:37 -08:00
EAPI int
2006-03-03 18:46:24 -08:00
eet_delete ( Eet_File * ef , const char * name )
2004-12-01 20:25:25 -08:00
{
2006-06-13 03:20:22 -07:00
Eet_File_Node * efn ;
Eet_File_Node * pefn ;
int hash ;
int exists_already = 0 ;
2008-01-24 00:41:23 -08:00
2005-05-22 21:32:04 -07:00
/* check to see its' an eet file pointer */
2006-06-13 03:20:22 -07:00
if ( eet_check_pointer ( ef ) )
return 0 ;
if ( ! name )
2004-12-01 20:25:25 -08:00
return 0 ;
2005-11-03 19:22:22 -08:00
/* deleting keys is only possible in RW or WRITE mode */
2006-06-13 03:20:22 -07:00
if ( ef - > mode = = EET_FILE_MODE_READ )
return 0 ;
2005-01-12 11:59:11 -08:00
2006-06-13 03:20:22 -07:00
if ( eet_check_header ( ef ) )
return 0 ;
2005-05-22 21:32:04 -07:00
2004-12-01 20:25:25 -08:00
/* figure hash bucket */
2006-12-28 07:23:47 -08:00
hash = _eet_hash_gen ( name , ef - > header - > directory - > size ) ;
2005-05-22 21:32:04 -07:00
2004-12-01 20:25:25 -08:00
/* Does this node already exist? */
2006-06-13 03:20:22 -07:00
for ( pefn = NULL , efn = ef - > header - > directory - > nodes [ hash ] ;
efn ;
pefn = efn , efn = efn - > next )
2004-12-01 20:25:25 -08:00
{
2005-01-12 11:59:11 -08:00
/* if it matches */
2005-05-25 20:57:57 -07:00
if ( eet_string_match ( efn - > name , name ) )
2004-12-01 20:25:25 -08:00
{
2006-06-13 03:20:22 -07:00
if ( efn - > data )
free ( efn - > data ) ;
2008-12-29 02:51:38 -08:00
if ( pefn = = NULL )
2005-05-25 20:57:57 -07:00
ef - > header - > directory - > nodes [ hash ] = efn - > next ;
else
pefn - > next = efn - > next ;
2008-02-29 22:38:09 -08:00
if ( efn - > free_name ) free ( efn - > name ) ;
2005-05-25 20:57:57 -07:00
free ( efn ) ;
2005-01-12 11:59:11 -08:00
exists_already = 1 ;
break ;
2004-12-01 20:25:25 -08:00
}
}
/* flags that writes are pending */
2006-06-13 03:20:22 -07:00
if ( exists_already )
ef - > writes_pending = 1 ;
2004-12-01 20:25:25 -08:00
/* update access time */
return exists_already ;
}
2008-03-28 07:37:29 -07:00
EAPI Eet_Dictionary *
2008-02-29 22:38:09 -08:00
eet_dictionary_get ( Eet_File * ef )
{
if ( eet_check_pointer ( ef ) ) return NULL ;
return ef - > ed ;
}
2008-03-07 01:59:37 -08:00
EAPI char * *
2006-03-03 18:46:24 -08:00
eet_list ( Eet_File * ef , const char * glob , int * count_ret )
2002-12-02 15:39:26 -08:00
{
2006-06-13 03:20:22 -07:00
Eet_File_Node * efn ;
char * * list_ret = NULL ;
int list_count = 0 ;
int list_count_alloc = 0 ;
int i , num ;
2002-12-02 15:39:26 -08:00
2005-05-22 21:32:04 -07:00
/* check to see its' an eet file pointer */
2006-06-13 03:20:22 -07:00
if ( eet_check_pointer ( ef ) | | eet_check_header ( ef ) | |
( ! glob ) | |
2005-02-07 10:11:49 -08:00
( ( ef - > mode ! = EET_FILE_MODE_READ ) & &
2005-03-03 09:26:46 -08:00
( ef - > mode ! = EET_FILE_MODE_READ_WRITE ) ) )
2002-12-02 15:39:26 -08:00
{
2006-06-13 03:20:22 -07:00
if ( count_ret )
* count_ret = 0 ;
2002-12-02 15:39:26 -08:00
return NULL ;
}
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
/* loop through all entries */
2005-05-25 20:57:57 -07:00
num = ( 1 < < ef - > header - > directory - > size ) ;
2002-12-02 15:39:26 -08:00
for ( i = 0 ; i < num ; i + + )
{
2005-05-25 20:57:57 -07:00
for ( efn = ef - > header - > directory - > nodes [ i ] ; efn ; efn = efn - > next )
2002-12-02 15:39:26 -08:00
{
2005-07-14 09:51:28 -07:00
/* if the entry matches the input glob
* check for * explicitly , because on some systems , * isn ' t well
* supported
*/
if ( ( ! strcmp ( glob , " * " ) ) | | ! fnmatch ( glob , efn - > name , 0 ) )
2002-12-02 15:39:26 -08:00
{
/* add it to our list */
list_count + + ;
2008-01-24 00:41:23 -08:00
2002-12-02 15:39:26 -08:00
/* only realloc in 32 entry chunks */
if ( list_count > list_count_alloc )
{
2006-06-13 03:20:22 -07:00
char * * new_list = NULL ;
2008-01-24 00:41:23 -08:00
2005-11-03 19:22:22 -08:00
list_count_alloc + = 64 ;
2002-12-02 15:39:26 -08:00
new_list = realloc ( list_ret , list_count_alloc * ( sizeof ( char * ) ) ) ;
if ( ! new_list )
{
free ( list_ret ) ;
2008-01-24 00:41:23 -08:00
2006-06-13 03:20:22 -07:00
if ( count_ret )
* count_ret = 0 ;
2008-01-24 00:41:23 -08:00
2005-05-22 21:32:04 -07:00
return NULL ;
2002-12-02 15:39:26 -08:00
}
list_ret = new_list ;
}
2008-01-24 00:41:23 -08:00
2002-12-02 15:39:26 -08:00
/* put pointer of name string in */
2005-05-25 20:57:57 -07:00
list_ret [ list_count - 1 ] = efn - > name ;
2002-12-02 15:39:26 -08:00
}
}
}
2006-06-13 03:20:22 -07:00
2002-12-02 15:39:26 -08:00
/* return count and list */
2006-06-13 03:20:22 -07:00
if ( count_ret )
* count_ret = list_count ;
2002-12-02 15:39:26 -08:00
return list_ret ;
}
2004-01-17 06:58:50 -08:00
2008-03-07 01:59:37 -08:00
EAPI int
2005-07-15 13:37:29 -07:00
eet_num_entries ( Eet_File * ef )
{
int i , num , ret = 0 ;
Eet_File_Node * efn ;
/* check to see its' an eet file pointer */
2006-06-13 03:20:22 -07:00
if ( eet_check_pointer ( ef ) | | eet_check_header ( ef ) | |
2005-07-15 13:37:29 -07:00
( ( ef - > mode ! = EET_FILE_MODE_READ ) & &
( ef - > mode ! = EET_FILE_MODE_READ_WRITE ) ) )
2006-06-13 03:20:22 -07:00
return - 1 ;
2005-07-15 13:37:29 -07:00
/* 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 )
2006-06-13 03:20:22 -07:00
ret + + ;
2005-07-15 13:37:29 -07:00
}
return ret ;
}
2005-11-29 10:49:30 -08:00
static Eet_File_Node *
2006-03-03 18:11:03 -08:00
find_node_by_name ( Eet_File * ef , const char * name )
2005-11-29 10:49:30 -08:00
{
Eet_File_Node * efn ;
int hash ;
/* get hash bucket this should be in */
2006-12-28 07:23:47 -08:00
hash = _eet_hash_gen ( name , ef - > header - > directory - > size ) ;
2005-11-29 10:49:30 -08:00
for ( efn = ef - > header - > directory - > nodes [ hash ] ; efn ; efn = efn - > next )
2006-06-13 03:20:22 -07:00
{
if ( eet_string_match ( efn - > name , name ) )
return efn ;
}
2005-11-29 10:49:30 -08:00
return NULL ;
}
static int
read_data_from_disk ( Eet_File * ef , Eet_File_Node * efn , void * buf , int len )
{
2008-05-16 07:03:11 -07:00
if ( efn - > offset < 0 ) return 0 ;
2006-06-13 03:20:22 -07:00
if ( ef - > data )
2006-10-16 08:02:11 -07:00
{
if ( ( efn - > offset + len ) > ef - > data_size ) return 0 ;
memcpy ( buf , ef - > data + efn - > offset , len ) ;
}
2006-06-13 03:20:22 -07:00
else
{
/* seek to data location */
if ( fseek ( ef - > fp , efn - > offset , SEEK_SET ) < 0 )
return 0 ;
2008-01-24 00:41:23 -08:00
2006-06-13 03:20:22 -07:00
/* read it */
len = fread ( buf , len , 1 , ef - > fp ) ;
}
return len ;
2005-11-29 10:49:30 -08:00
}