2008-03-07 23:28:12 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2008-03-28 10:17:43 -07:00
|
|
|
# include <config.h>
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_CONFIG_H */
|
2008-03-07 23:28:12 -08:00
|
|
|
|
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
|
2010-07-30 18:54:48 -07:00
|
|
|
#else /* ifdef HAVE_ALLOCA_H */
|
2008-03-28 10:17:43 -07:00
|
|
|
# include <stddef.h>
|
|
|
|
# ifdef __cplusplus
|
|
|
|
extern "C"
|
2010-07-30 18:54:48 -07:00
|
|
|
# endif /* ifdef __cplusplus */
|
|
|
|
void * alloca (size_t);
|
|
|
|
#endif /* ifdef HAVE_ALLOCA_H */
|
2008-01-27 05:17:22 -08:00
|
|
|
|
2010-04-02 23:11:19 -07:00
|
|
|
#ifdef _WIN32
|
|
|
|
# include <winsock2.h>
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef _WIN32 */
|
2010-04-02 23:11:19 -07: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>
|
|
|
|
|
2011-01-07 07:56:54 -08:00
|
|
|
#ifndef _MSC_VER
|
2009-02-19 12:31:21 -08:00
|
|
|
# include <unistd.h>
|
2011-01-07 07:56:54 -08:00
|
|
|
#endif /* ifndef _MSC_VER */
|
2009-02-19 12:31:21 -08:00
|
|
|
|
2008-03-28 10:17:43 -07:00
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
# include <netinet/in.h>
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_NETINET_IN_H */
|
2008-03-28 10:17:43 -07:00
|
|
|
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_EVIL */
|
2008-03-28 10:17:43 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
#ifdef HAVE_GNUTLS
|
|
|
|
# include <gnutls/gnutls.h>
|
|
|
|
# include <gcrypt.h>
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_GNUTLS */
|
2008-11-13 08:31:13 -08:00
|
|
|
|
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>
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_OPENSSL */
|
2008-10-13 04:51:10 -07:00
|
|
|
|
2010-07-14 23:34:32 -07:00
|
|
|
#ifdef EFL_HAVE_POSIX_THREADS
|
2009-12-03 07:35:04 -08:00
|
|
|
# include <pthread.h>
|
2010-07-27 19:10:44 -07:00
|
|
|
# ifdef HAVE_GNUTLS
|
|
|
|
GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
2010-07-30 18:54:48 -07:00
|
|
|
# endif /* ifdef HAVE_GNUTLS */
|
|
|
|
#endif /* ifdef EFL_HAVE_POSIX_THREADS */
|
2009-12-03 07:35:04 -08:00
|
|
|
|
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
|
|
|
|
2010-05-21 07:07:25 -07:00
|
|
|
static Eet_Version _version = { VMAJ, VMIN, VMIC, VREV };
|
2010-07-31 11:54:54 -07:00
|
|
|
EAPI Eet_Version *eet_version = &_version;
|
2010-05-21 07:07:25 -07:00
|
|
|
|
2004-08-28 01:41:19 -07:00
|
|
|
#ifdef HAVE_REALPATH
|
2009-08-23 02:36:43 -07:00
|
|
|
# undef HAVE_REALPATH
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_REALPATH */
|
2004-08-28 01:41:19 -07:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#define EET_MAGIC_FILE 0x1ee7ff00
|
|
|
|
#define EET_MAGIC_FILE_HEADER 0x1ee7ff01
|
2002-12-02 15:39:26 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#define EET_MAGIC_FILE2 0x1ee70f42
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-30 18:54:48 -07: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;
|
2002-12-02 15:39:26 -08:00
|
|
|
|
|
|
|
struct _Eet_File
|
|
|
|
{
|
2010-07-31 11:57:35 -07:00
|
|
|
char *path;
|
|
|
|
FILE *readfp;
|
|
|
|
Eet_File_Header *header;
|
|
|
|
Eet_Dictionary *ed;
|
|
|
|
Eet_Key *key;
|
2010-07-31 11:54:54 -07:00
|
|
|
const unsigned char *data;
|
2010-07-31 11:57:35 -07:00
|
|
|
const void *x509_der;
|
|
|
|
const void *signature;
|
|
|
|
void *sha1;
|
2010-07-31 11:54:54 -07:00
|
|
|
|
|
|
|
Eet_File_Mode mode;
|
2008-11-26 02:45:47 -08:00
|
|
|
|
2010-07-31 11:54:54 -07:00
|
|
|
int magic;
|
|
|
|
int references;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-07-31 11:54:54 -07:00
|
|
|
int data_size;
|
|
|
|
int x509_length;
|
|
|
|
unsigned int signature_length;
|
|
|
|
int sha1_length;
|
2008-11-26 02:45:47 -08:00
|
|
|
|
2010-07-31 11:54:54 -07:00
|
|
|
time_t mtime;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-07-14 23:34:32 -07:00
|
|
|
#ifdef EFL_HAVE_THREADS
|
|
|
|
# ifdef EFL_HAVE_POSIX_THREADS
|
2010-07-31 11:54:54 -07:00
|
|
|
pthread_mutex_t file_lock;
|
2010-07-30 18:54:48 -07:00
|
|
|
# else /* ifdef EFL_HAVE_POSIX_THREADS */
|
2010-07-31 11:54:54 -07:00
|
|
|
HANDLE file_lock;
|
2010-07-30 18:54:48 -07:00
|
|
|
# endif /* ifdef EFL_HAVE_POSIX_THREADS */
|
|
|
|
#endif /* ifdef EFL_HAVE_THREADS */
|
|
|
|
|
2010-07-31 11:54:54 -07: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
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
int magic;
|
|
|
|
Eet_File_Directory *directory;
|
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_Directory
|
|
|
|
{
|
2010-07-31 11:54:54 -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
|
|
|
{
|
2010-07-31 11:57:35 -07:00
|
|
|
char *name;
|
|
|
|
void *data;
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *next; /* FIXME: make buckets linked lists */
|
|
|
|
|
|
|
|
int offset;
|
|
|
|
int dictionary_offset;
|
|
|
|
int name_offset;
|
|
|
|
|
|
|
|
int name_size;
|
|
|
|
int size;
|
|
|
|
int data_size;
|
|
|
|
|
|
|
|
unsigned char free_name : 1;
|
|
|
|
unsigned char compression : 1;
|
|
|
|
unsigned char ciphered : 1;
|
|
|
|
unsigned char alias : 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
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
int offset; /* bytes offset into file for data chunk */
|
|
|
|
int flags; /* flags - for now 0 = uncompressed and clear, 1 = compressed and clear, 2 = uncompressed and ciphered, 3 = compressed and ciphered */
|
|
|
|
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... */
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* if 0 */
|
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
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
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; /* bit flags - for now:
|
|
|
|
bit 0 => compresion on/off
|
|
|
|
bit 1 => ciphered on/off
|
|
|
|
bit 2 => alias
|
|
|
|
*/
|
2008-02-29 22:38:09 -08:00
|
|
|
} directory[num_directory_entries];
|
|
|
|
struct
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
int hash;
|
|
|
|
int offset;
|
|
|
|
int size;
|
|
|
|
int prev;
|
|
|
|
int next;
|
2008-02-29 22:38:09 -08:00
|
|
|
} 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. */
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* if 0 */
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#define EET_FILE2_HEADER_COUNT 3
|
|
|
|
#define EET_FILE2_DIRECTORY_ENTRY_COUNT 6
|
|
|
|
#define EET_FILE2_DICTIONARY_ENTRY_COUNT 5
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#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)
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
/* prototypes of internal calls */
|
2010-07-31 11:54:54 -07:00
|
|
|
static Eet_File * eet_cache_find(const char *path,
|
2010-07-31 11:57:35 -07:00
|
|
|
Eet_File **cache,
|
2010-07-31 11:54:54 -07:00
|
|
|
int cache_num);
|
2010-07-31 11:57:35 -07:00
|
|
|
static void eet_cache_add(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File ***cache,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *cache_num,
|
|
|
|
int *cache_alloc);
|
|
|
|
static void eet_cache_del(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File ***cache,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *cache_num,
|
|
|
|
int *cache_alloc);
|
2010-07-31 11:54:54 -07:00
|
|
|
static int eet_string_match(const char *s1, const char *s2);
|
2008-04-03 12:30:08 -07:00
|
|
|
#if 0 /* Unused */
|
2010-07-31 11:54:54 -07:00
|
|
|
static Eet_Error eet_flush(Eet_File *ef);
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* if 0 */
|
2010-07-31 11:54:54 -07:00
|
|
|
static Eet_Error eet_flush2(Eet_File *ef);
|
|
|
|
static Eet_File_Node * find_node_by_name(Eet_File *ef, const char *name);
|
2010-07-31 11:57:35 -07:00
|
|
|
static int read_data_from_disk(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn,
|
2010-07-31 11:57:35 -07:00
|
|
|
void *buf,
|
2010-07-31 11:54:54 -07:00
|
|
|
int len);
|
2002-12-02 15:39:26 -08:00
|
|
|
|
2010-07-31 11:54:54 -07:00
|
|
|
static Eet_Error eet_internal_close(Eet_File *ef, Eina_Bool locked);
|
2010-01-04 20:40:12 -08:00
|
|
|
|
2010-07-14 23:34:32 -07:00
|
|
|
#ifdef EFL_HAVE_THREADS
|
|
|
|
|
|
|
|
# ifdef EFL_HAVE_POSIX_THREADS
|
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
# define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock)
|
2010-07-14 23:34:32 -07:00
|
|
|
# define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock)
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
# define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL)
|
|
|
|
# define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock)
|
|
|
|
# define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock)
|
2010-07-14 23:34:32 -07:00
|
|
|
# define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock)
|
|
|
|
|
|
|
|
# else /* EFL_HAVE_WIN32_THREADS */
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-14 23:34:32 -07:00
|
|
|
static HANDLE eet_cache_lock = NULL;
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
# define LOCK_CACHE WaitForSingleObject(eet_cache_lock, INFINITE)
|
2010-07-14 23:34:32 -07:00
|
|
|
# define UNLOCK_CACHE ReleaseMutex(eet_cache_lock)
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
# define INIT_FILE(File) File->file_lock = CreateMutex(NULL, FALSE, NULL)
|
|
|
|
# define LOCK_FILE(File) WaitForSingleObject(File->file_lock, INFINITE)
|
|
|
|
# define UNLOCK_FILE(File) ReleaseMutex(File->file_lock)
|
2010-07-14 23:34:32 -07:00
|
|
|
# define DESTROY_FILE(File) CloseHandle(File->file_lock)
|
|
|
|
|
|
|
|
# endif /* EFL_HAVE_WIN32_THREADS */
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#else /* ifdef EFL_HAVE_THREADS */
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
# define LOCK_CACHE do {} while (0)
|
2010-07-14 23:34:32 -07:00
|
|
|
# define UNLOCK_CACHE do {} while (0)
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
# define INIT_FILE(File) do {} while (0)
|
|
|
|
# define LOCK_FILE(File) do {} while (0)
|
|
|
|
# define UNLOCK_FILE(File) do {} while (0)
|
2010-07-14 23:34:32 -07:00
|
|
|
# define DESTROY_FILE(File) do {} while (0)
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-14 23:34:32 -07:00
|
|
|
#endif /* EFL_HAVE_THREADS */
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
/* cache. i don't expect this to ever be large, so arrays will do */
|
2010-07-27 18:45:57 -07:00
|
|
|
static int eet_writers_num = 0;
|
|
|
|
static int eet_writers_alloc = 0;
|
2010-07-31 11:54:54 -07:00
|
|
|
static Eet_File **eet_writers = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
static int eet_readers_num = 0;
|
|
|
|
static int eet_readers_alloc = 0;
|
2010-07-31 11:54:54 -07:00
|
|
|
static Eet_File **eet_readers = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
static int eet_init_count = 0;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2009-09-15 04:22:11 -07:00
|
|
|
/* log domain variable */
|
2009-10-01 20:59:17 -07:00
|
|
|
int _eet_log_dom_global = -1;
|
2009-09-15 04:22:11 -07:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
/* Check to see its' an eet file pointer */
|
|
|
|
static inline int
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_check_pointer(const Eet_File *ef)
|
2006-06-13 03:20:22 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if ((!ef) || (ef->magic != EET_MAGIC_FILE))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_check_pointer */
|
2006-06-13 03:20:22 -07:00
|
|
|
|
|
|
|
static inline int
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_check_header(const Eet_File *ef)
|
2006-06-13 03:20:22 -07:00
|
|
|
{
|
|
|
|
if (!ef->header)
|
2010-07-27 18:45:57 -07:00
|
|
|
return 1;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (!ef->header->directory)
|
2010-07-27 18:45:57 -07:00
|
|
|
return 1;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
return 0;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_check_header */
|
2006-06-13 03:20:22 -07:00
|
|
|
|
|
|
|
static inline int
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_test_close(int test,
|
|
|
|
Eet_File *ef)
|
2006-06-13 03:20:22 -07:00
|
|
|
{
|
|
|
|
if (test)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->delete_me_now = 1;
|
2010-07-30 18:54:48 -07:00
|
|
|
eet_internal_close(ef, EINA_TRUE);
|
2006-06-13 03:20:22 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
return test;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_test_close */
|
2002-12-02 15:39:26 -08:00
|
|
|
|
|
|
|
/* find an eet file in the currently in use cache */
|
|
|
|
static Eet_File *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_cache_find(const char *path,
|
2010-07-31 11:57:35 -07:00
|
|
|
Eet_File **cache,
|
2010-07-31 11:54:54 -07:00
|
|
|
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++)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* if matches real path - return it */
|
|
|
|
if (eet_string_match(cache[i]->path, path))
|
|
|
|
if (!cache[i]->delete_me_now)
|
|
|
|
return cache[i];
|
|
|
|
|
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;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_cache_find */
|
2002-12-02 15:39:26 -08:00
|
|
|
|
|
|
|
/* add to end of cache */
|
2010-03-15 07:47:51 -07:00
|
|
|
/* this should only be called when the cache lock is already held */
|
2002-12-02 15:39:26 -08:00
|
|
|
static void
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_cache_add(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File ***cache,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *cache_num,
|
|
|
|
int *cache_alloc)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File **new_cache;
|
2010-07-27 18:45:57 -07:00
|
|
|
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
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File *del_ef = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
int i;
|
|
|
|
|
|
|
|
new_cache = *cache;
|
|
|
|
for (i = 0; i < new_cache_num; i++)
|
|
|
|
{
|
|
|
|
if (new_cache[i]->references == 0)
|
|
|
|
{
|
|
|
|
del_ef = new_cache[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (del_ef)
|
|
|
|
{
|
|
|
|
del_ef->delete_me_now = 1;
|
2010-04-23 16:01:29 -07:00
|
|
|
eet_internal_close(del_ef, EINA_TRUE);
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
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
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
new_cache_alloc += 16;
|
|
|
|
new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
|
|
|
|
if (!new_cache)
|
|
|
|
{
|
|
|
|
CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
|
|
|
|
abort();
|
|
|
|
}
|
2004-10-20 23:16:55 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -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;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_cache_add */
|
2002-12-02 15:39:26 -08:00
|
|
|
|
|
|
|
/* delete from cache */
|
2010-03-15 07:47:51 -07:00
|
|
|
/* this should only be called when the cache lock is already held */
|
2002-12-02 15:39:26 -08:00
|
|
|
static void
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_cache_del(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File ***cache,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *cache_num,
|
|
|
|
int *cache_alloc)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07: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)
|
2010-07-27 18:45:57 -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++)
|
|
|
|
{
|
2010-07-27 18:45:57 -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)
|
2010-07-27 18:45:57 -07:00
|
|
|
return;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
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++)
|
2010-07-27 18:45:57 -07:00
|
|
|
new_cache[j] = new_cache[j + 1];
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2008-08-22 07:35:21 -07:00
|
|
|
if (new_cache_num <= (new_cache_alloc - 16))
|
2003-09-24 00:08:57 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
new_cache_alloc -= 16;
|
|
|
|
if (new_cache_num > 0)
|
|
|
|
{
|
|
|
|
new_cache = realloc(new_cache, new_cache_alloc * sizeof(Eet_File *));
|
|
|
|
if (!new_cache)
|
|
|
|
{
|
|
|
|
CRIT("BAD ERROR! Eet realloc of cache list failed. Abort");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
free(new_cache);
|
|
|
|
new_cache = NULL;
|
|
|
|
}
|
2003-09-24 00:08:57 -07:00
|
|
|
}
|
2010-07-27 18:45: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;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_cache_del */
|
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
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_string_match(const char *s1,
|
|
|
|
const char *s2)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
|
|
|
/* both null- no match */
|
2010-07-27 18:45:57 -07:00
|
|
|
if ((!s1) || (!s2))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (s1 == s2)
|
|
|
|
return 1;
|
|
|
|
|
2005-11-03 05:05:52 -08:00
|
|
|
return (!strcmp(s1, s2));
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_string_match */
|
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
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_flush2(Eet_File *ef)
|
2008-02-29 22:38:09 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
FILE *fp;
|
2010-04-09 06:45:25 -07:00
|
|
|
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;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
if (eet_check_pointer(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_BAD_OBJECT;
|
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
if (eet_check_header(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_EMPTY;
|
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
if (!ef->writes_pending)
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_NONE;
|
2010-04-09 06:45:25 -07:00
|
|
|
|
|
|
|
if ((ef->mode == EET_FILE_MODE_READ_WRITE)
|
|
|
|
|| (ef->mode == EET_FILE_MODE_WRITE))
|
2008-08-13 09:40:53 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
int fd;
|
|
|
|
|
|
|
|
/* opening for write - delete old copy of file right away */
|
|
|
|
unlink(ef->path);
|
|
|
|
fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
|
|
|
|
fp = fdopen(fd, "wb");
|
|
|
|
if (!fp)
|
|
|
|
return EET_ERROR_NOT_WRITABLE;
|
|
|
|
|
|
|
|
fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
|
2008-08-13 09:40:53 -07:00
|
|
|
}
|
2010-04-09 06:45:25 -07:00
|
|
|
else
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_NOT_WRITABLE;
|
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)
|
2010-07-27 18:45:57 -07:00
|
|
|
bytes_strings += ef->ed->all[i].len;
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* calculate section bytes size */
|
2010-07-27 18:45:57 -07:00
|
|
|
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;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* calculate per entry offset */
|
|
|
|
strings_offset = bytes_directory_entries + bytes_dictionary_entries;
|
2010-07-27 18:45:57 -07:00
|
|
|
data_offset = bytes_directory_entries + bytes_dictionary_entries +
|
|
|
|
bytes_strings;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
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)
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->ed->offset = strings_offset;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* go thru and write the header */
|
2010-07-30 18:54:48 -07:00
|
|
|
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);
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-04-09 06:45:25 -07:00
|
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
if (fwrite(head, sizeof (head), 1, fp) != 1)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto write_error;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* write directories entry */
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int flag;
|
2008-11-13 08:31:13 -08:00
|
|
|
int ibuf[EET_FILE2_DIRECTORY_ENTRY_COUNT];
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
flag = (efn->alias << 2) | (efn->ciphered << 1) | efn->compression;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-30 18:54:48 -07: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);
|
|
|
|
ibuf[5] = (int)htonl((unsigned int)flag);
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-04-09 06:45:25 -07:00
|
|
|
if (fwrite(ibuf, sizeof(ibuf), 1, fp) != 1)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto write_error;
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write dictionnary */
|
|
|
|
if (ef->ed)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
int offset = strings_offset;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
for (j = 0; j < ef->ed->count; ++j)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
int sbuf[EET_FILE2_DICTIONARY_ENTRY_COUNT];
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
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);
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
offset += ef->ed->all[j].len;
|
|
|
|
|
2010-04-09 06:45:25 -07:00
|
|
|
if (fwrite(sbuf, sizeof (sbuf), 1, fp) != 1)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto write_error;
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write directories name */
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
|
|
|
|
{
|
2010-04-09 06:45:25 -07:00
|
|
|
if (fwrite(efn->name, efn->name_size, 1, fp) != 1)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto write_error;
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write strings */
|
|
|
|
if (ef->ed)
|
2010-07-27 18:45:57 -07:00
|
|
|
for (j = 0; j < ef->ed->count; ++j)
|
|
|
|
{
|
2010-11-29 06:04:16 -08:00
|
|
|
if (fwrite(ef->ed->all[j].str, ef->ed->all[j].len, 1, fp) != 1)
|
|
|
|
goto write_error;
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
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)
|
|
|
|
{
|
2010-04-09 06:45:25 -07:00
|
|
|
if (fwrite(efn->data, efn->size, 1, fp) != 1)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto write_error;
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-08 02:19:57 -07:00
|
|
|
/* flush all write to the file. */
|
2010-04-09 06:45:25 -07:00
|
|
|
fflush(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
|
2010-04-09 06:45:25 -07:00
|
|
|
// fsync(fileno(fp));
|
2008-09-08 02:19:57 -07:00
|
|
|
|
|
|
|
/* append signature if required */
|
|
|
|
if (ef->key)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
error = eet_identity_sign(fp, ef->key);
|
|
|
|
if (error != EET_ERROR_NONE)
|
|
|
|
goto sign_error;
|
2008-09-08 02:19:57 -07:00
|
|
|
}
|
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
/* no more writes pending */
|
|
|
|
ef->writes_pending = 0;
|
|
|
|
|
2010-04-09 06:45:25 -07:00
|
|
|
fclose(fp);
|
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
return EET_ERROR_NONE;
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
write_error:
|
2010-04-09 06:45:25 -07:00
|
|
|
if (ferror(fp))
|
2008-02-29 22:38:09 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -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;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* switch */
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
sign_error:
|
2010-07-13 19:05:47 -07:00
|
|
|
fclose(fp);
|
2008-02-29 22:38:09 -08:00
|
|
|
return error;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_flush2 */
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2005-11-03 07:05:21 -08:00
|
|
|
eet_init(void)
|
|
|
|
{
|
2009-10-07 23:04:03 -07:00
|
|
|
if (++eet_init_count != 1)
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_init_count;
|
2008-09-08 02:19:57 -07:00
|
|
|
|
2009-10-08 22:07:26 -07:00
|
|
|
if (!eina_init())
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
fprintf(stderr, "Eet: Eina init failed");
|
|
|
|
return --eet_init_count;
|
2009-10-08 22:07:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2010-10-07 16:51:20 -07:00
|
|
|
_eet_log_dom_global = eina_log_domain_register("eet", EET_DEFAULT_LOG_COLOR);
|
2009-10-08 22:07:26 -07:00
|
|
|
if (_eet_log_dom_global < 0)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
EINA_LOG_ERR("Eet Can not create a general log domain.");
|
|
|
|
goto shutdown_eina;
|
2009-10-08 22:07:26 -07:00
|
|
|
}
|
|
|
|
|
2010-01-17 06:32:58 -08:00
|
|
|
if (!eet_node_init())
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
|
|
|
|
goto unregister_log_domain;
|
2010-01-17 06:32:58 -08:00
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
#ifdef HAVE_GNUTLS
|
2009-03-25 09:26:46 -07:00
|
|
|
/* Before the library can be used, it must initialize itself if needed. */
|
2010-07-30 18:54:48 -07:00
|
|
|
if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -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))
|
2010-07-27 20:03:10 -07:00
|
|
|
goto shutdown_eet; /* This command is used to allocate a pool of secure memory and thus
|
|
|
|
enabling the use of secure memory. It also drops all extra privileges the
|
|
|
|
process has (i.e. if it is run as setuid (root)). If the argument nbytes
|
|
|
|
is 0, secure memory will be disabled. The minimum amount of secure memory
|
|
|
|
allocated is currently 16384 bytes; you may thus use a value of 1 to
|
|
|
|
request that default size. */
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0))
|
|
|
|
WRN(
|
|
|
|
"BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
2010-07-27 19:49:01 -07:00
|
|
|
|
2010-09-18 18:25:30 -07:00
|
|
|
# ifdef EFL_HAVE_POSIX_THREADS
|
2010-07-27 19:10:44 -07:00
|
|
|
if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread))
|
2010-07-30 18:54:48 -07:00
|
|
|
WRN(
|
2010-07-27 19:49:01 -07:00
|
|
|
"YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!");
|
|
|
|
|
2010-09-18 18:25:30 -07:00
|
|
|
# endif /* ifdef EFL_HAVE_POSIX_THREADS */
|
2009-07-08 07:43:20 -07:00
|
|
|
if (gnutls_global_init())
|
2010-07-27 18:45:57 -07:00
|
|
|
goto shutdown_eet;
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_GNUTLS */
|
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();
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_OPENSSL */
|
2008-09-19 04:30:42 -07:00
|
|
|
|
2009-10-07 23:04:03 -07:00
|
|
|
return eet_init_count;
|
2009-10-01 20:59:17 -07:00
|
|
|
|
2010-09-18 18:25:30 -07:00
|
|
|
#ifdef HAVE_GNUTLS
|
2010-07-27 18:45:57 -07:00
|
|
|
shutdown_eet:
|
2010-09-18 18:25:30 -07:00
|
|
|
#endif
|
2010-01-17 06:32:58 -08:00
|
|
|
eet_node_shutdown();
|
2010-07-27 18:45:57 -07:00
|
|
|
unregister_log_domain:
|
2009-10-08 22:07:26 -07:00
|
|
|
eina_log_domain_unregister(_eet_log_dom_global);
|
|
|
|
_eet_log_dom_global = -1;
|
2010-07-27 18:45:57 -07:00
|
|
|
shutdown_eina:
|
2009-09-15 04:22:11 -07:00
|
|
|
eina_shutdown();
|
2009-10-08 14:16:26 -07:00
|
|
|
return --eet_init_count;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_init */
|
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)
|
|
|
|
{
|
2009-10-07 23:04:03 -07:00
|
|
|
if (--eet_init_count != 0)
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_init_count;
|
2008-09-19 04:30:42 -07:00
|
|
|
|
|
|
|
eet_clearcache();
|
2010-01-17 06:32:58 -08:00
|
|
|
eet_node_shutdown();
|
2008-11-13 08:31:13 -08:00
|
|
|
#ifdef HAVE_GNUTLS
|
|
|
|
gnutls_global_deinit();
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_GNUTLS */
|
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();
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_OPENSSL */
|
2009-10-08 22:07:26 -07:00
|
|
|
eina_log_domain_unregister(_eet_log_dom_global);
|
|
|
|
_eet_log_dom_global = -1;
|
|
|
|
eina_shutdown();
|
2005-11-03 07:05:21 -08:00
|
|
|
|
2009-10-07 23:04:03 -07:00
|
|
|
return eet_init_count;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_shutdown */
|
2005-11-03 07:05:21 -08:00
|
|
|
|
2010-04-09 06:45:25 -07:00
|
|
|
EAPI Eet_Error
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_sync(Eet_File *ef)
|
2010-04-09 06:45:25 -07:00
|
|
|
{
|
|
|
|
Eet_Error ret;
|
|
|
|
|
|
|
|
if (eet_check_pointer(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_BAD_OBJECT;
|
2010-04-09 06:45:25 -07:00
|
|
|
|
|
|
|
if ((ef->mode != EET_FILE_MODE_WRITE) &&
|
|
|
|
(ef->mode != EET_FILE_MODE_READ_WRITE))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_NOT_WRITABLE;
|
2010-04-09 06:45:25 -07:00
|
|
|
|
|
|
|
if (!ef->writes_pending)
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_NONE;
|
2010-04-09 06:45:25 -07:00
|
|
|
|
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
|
|
|
ret = eet_flush2(ef);
|
|
|
|
|
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
return ret;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_sync */
|
2010-04-09 06:45:25 -07:00
|
|
|
|
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
|
|
|
{
|
2010-07-27 18:45:57 -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.
|
|
|
|
*/
|
2010-03-15 07:47:51 -07:00
|
|
|
LOCK_CACHE;
|
2006-06-13 03:20:22 -07:00
|
|
|
for (i = 0; i < eet_writers_num; i++)
|
|
|
|
{
|
2010-07-27 18:45:57 -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++)
|
|
|
|
{
|
2010-07-27 18:45:57 -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
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File **closelist = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
closelist = alloca(num * sizeof(Eet_File *));
|
|
|
|
num = 0;
|
|
|
|
for (i = 0; i < eet_writers_num; i++)
|
|
|
|
{
|
|
|
|
if (eet_writers[i]->references <= 0)
|
|
|
|
{
|
|
|
|
closelist[num] = eet_writers[i];
|
|
|
|
eet_writers[i]->delete_me_now = 1;
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < eet_readers_num; i++)
|
|
|
|
{
|
|
|
|
if (eet_readers[i]->references <= 0)
|
|
|
|
{
|
|
|
|
closelist[num] = eet_readers[i];
|
|
|
|
eet_readers[i]->delete_me_now = 1;
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
eet_internal_close(closelist[i], EINA_TRUE);
|
|
|
|
}
|
2005-11-03 05:05:52 -08:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2010-03-15 07:47:51 -07:00
|
|
|
UNLOCK_CACHE;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_clearcache */
|
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 *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_internal_read2(Eet_File *ef)
|
2008-01-20 17:09:51 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
const int *data = (const int *)ef->data;
|
|
|
|
const char *start = (const char *)ef->data;
|
2010-07-27 18:45:57 -07:00
|
|
|
int idx = 0;
|
|
|
|
int num_directory_entries;
|
|
|
|
int bytes_directory_entries;
|
|
|
|
int num_dictionary_entries;
|
|
|
|
int bytes_dictionary_entries;
|
|
|
|
int signature_base_offset;
|
|
|
|
int i;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
idx += sizeof(int);
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close((int)ntohl(*data) != EET_MAGIC_FILE2, ef))
|
|
|
|
return NULL;
|
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
data++;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#define GET_INT(Value, Pointer, Index)\
|
|
|
|
{\
|
|
|
|
Value = ntohl(*Pointer);\
|
|
|
|
Pointer++;\
|
|
|
|
Index += sizeof(int);\
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* get entries count and byte count */
|
2010-07-27 18:45:57 -07:00
|
|
|
GET_INT(num_directory_entries, data, idx);
|
2008-02-29 22:38:09 -08:00
|
|
|
/* get dictionary count and byte count */
|
2010-03-01 03:03:35 -08:00
|
|
|
GET_INT(num_dictionary_entries, data, idx);
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
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;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-09-07 20:26:19 -07:00
|
|
|
/* we can't have <= 0 values here - invalid */
|
2008-02-29 22:38:09 -08:00
|
|
|
if (eet_test_close((num_directory_entries <= 0), ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-09-07 20:26:19 -07:00
|
|
|
/* we can't have more bytes directory and bytes in dictionaries than the size of the file */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close((bytes_directory_entries + bytes_dictionary_entries) >
|
|
|
|
ef->data_size, ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* allocate header */
|
|
|
|
ef->header = calloc(1, sizeof(Eet_File_Header));
|
|
|
|
if (eet_test_close(!ef->header, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* 8 bit hash table (256 buckets) */
|
|
|
|
ef->header->directory->size = 8;
|
|
|
|
/* allocate base hash table */
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->header->directory->nodes =
|
|
|
|
calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
|
2008-02-29 22:38:09 -08:00
|
|
|
if (eet_test_close(!ef->header->directory->nodes, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
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)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name;
|
|
|
|
Eet_File_Node *efn;
|
2010-07-27 18:45:57 -07:00
|
|
|
int name_offset;
|
|
|
|
int name_size;
|
|
|
|
int hash;
|
|
|
|
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 */
|
2010-08-22 15:21:41 -07:00
|
|
|
efn = malloc(sizeof(Eet_File_Node));
|
2008-02-29 22:38:09 -08:00
|
|
|
if (eet_test_close(!efn, ef))
|
2010-08-22 15:21:41 -07:00
|
|
|
{
|
|
|
|
if (efn) free(efn); /* yes i know - we only get here if
|
|
|
|
* efn is null/0 -> trying to shut up
|
|
|
|
* warning tools like cppcheck */
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* get entrie header */
|
2010-07-27 18:45:57 -07:00
|
|
|
GET_INT(efn->offset, data, idx);
|
|
|
|
GET_INT(efn->size, data, idx);
|
2010-03-01 03:03:35 -08:00
|
|
|
GET_INT(efn->data_size, data, idx);
|
2010-07-27 18:45:57 -07:00
|
|
|
GET_INT(name_offset, data, idx);
|
|
|
|
GET_INT(name_size, data, idx);
|
|
|
|
GET_INT(flag, data, idx);
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
efn->compression = flag & 0x1 ? 1 : 0;
|
|
|
|
efn->ciphered = flag & 0x2 ? 1 : 0;
|
|
|
|
efn->alias = flag & 0x4 ? 1 : 0;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#define EFN_TEST(Test, Ef, Efn)\
|
|
|
|
if (eet_test_close(Test, Ef))\
|
|
|
|
{\
|
|
|
|
free(Efn);\
|
|
|
|
return NULL;\
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* check data pointer position */
|
|
|
|
EFN_TEST(!((efn->size > 0)
|
|
|
|
&& (efn->offset + efn->size <= ef->data_size)
|
2010-07-27 18:45:57 -07:00
|
|
|
&& (efn->offset > bytes_dictionary_entries +
|
|
|
|
bytes_directory_entries)), ef, efn);
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* check name position */
|
|
|
|
EFN_TEST(!((name_size > 0)
|
|
|
|
&& (name_offset + name_size < ef->data_size)
|
2010-07-27 18:45:57 -07:00
|
|
|
&& (name_offset >= bytes_dictionary_entries +
|
|
|
|
bytes_directory_entries)), ef, efn);
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
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;
|
2010-07-27 18:45:57 -07:00
|
|
|
efn->name = (char *)name;
|
2008-02-29 22:38:09 -08:00
|
|
|
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)
|
2010-07-27 20:03:10 -07:00
|
|
|
efn->data = NULL; /* read-write mode - read everything into ram */
|
2008-02-29 22:38:09 -08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
efn->data = malloc(efn->size);
|
|
|
|
if (efn->data)
|
2010-07-27 18:45:57 -07:00
|
|
|
memcpy(efn->data, ef->data + efn->offset, efn->size);
|
2008-02-29 22:38:09 -08:00
|
|
|
}
|
2008-09-08 02:19:57 -07:00
|
|
|
|
2010-07-27 18:45: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)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
const int *dico = (const int *)ef->data +
|
2010-07-27 18:45:57 -07:00
|
|
|
EET_FILE2_DIRECTORY_ENTRY_COUNT * num_directory_entries +
|
|
|
|
EET_FILE2_HEADER_COUNT;
|
|
|
|
int j;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close((num_dictionary_entries *
|
|
|
|
(int)EET_FILE2_DICTIONARY_ENTRY_SIZE + idx) >
|
|
|
|
(bytes_dictionary_entries + bytes_directory_entries),
|
|
|
|
ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
ef->ed = calloc(1, sizeof (Eet_Dictionary));
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close(!ef->ed, ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
ef->ed->all = calloc(num_dictionary_entries, sizeof (Eet_String));
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close(!ef->ed->all, ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
ef->ed->count = num_dictionary_entries;
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->ed->total = num_dictionary_entries;
|
|
|
|
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)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
int hash;
|
|
|
|
int offset;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
GET_INT(hash, dico, idx);
|
|
|
|
GET_INT(offset, dico, idx);
|
|
|
|
GET_INT(ef->ed->all[j].len, dico, idx);
|
2010-03-01 03:03:35 -08:00
|
|
|
GET_INT(ef->ed->all[j].prev, dico, idx);
|
|
|
|
GET_INT(ef->ed->all[j].next, dico, idx);
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* 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. */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close(hash & 0xFFFFFF00, ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
/* Check string position */
|
|
|
|
if (eet_test_close(!((ef->ed->all[j].len > 0)
|
2010-07-27 18:45:57 -07:00
|
|
|
&& (offset >
|
|
|
|
(bytes_dictionary_entries +
|
|
|
|
bytes_directory_entries))
|
|
|
|
&& (offset + ef->ed->all[j].len <
|
|
|
|
ef->data_size)), ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-11-29 06:04:16 -08:00
|
|
|
ef->ed->all[j].str = start + offset;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-11-29 06:04:16 -08:00
|
|
|
if (ef->ed->all[j].str + ef->ed->all[j].len > ef->ed->end)
|
|
|
|
ef->ed->end = ef->ed->all[j].str + ef->ed->all[j].len;
|
2008-03-06 09:52:59 -08:00
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
/* Check '\0' at the end of the string */
|
2010-11-29 06:04:16 -08:00
|
|
|
if (eet_test_close(ef->ed->all[j].str[ef->ed->all[j].len - 1] !=
|
2010-07-27 18:45:57 -07:00
|
|
|
'\0', ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->ed->all[j].hash = hash;
|
2008-02-29 22:38:09 -08:00
|
|
|
if (ef->ed->all[j].prev == -1)
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->ed->hash[hash] = j;
|
2008-09-08 02:19:57 -07:00
|
|
|
|
2010-07-27 18:45: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
|
2010-07-31 11:54:54 -07:00
|
|
|
const unsigned char *buffer = ((const unsigned char *)ef->data) +
|
2010-07-27 18:45:57 -07:00
|
|
|
signature_base_offset;
|
|
|
|
ef->x509_der = eet_identity_check(ef->data,
|
|
|
|
signature_base_offset,
|
|
|
|
&ef->sha1,
|
|
|
|
&ef->sha1_length,
|
|
|
|
buffer,
|
|
|
|
ef->data_size - signature_base_offset,
|
|
|
|
&ef->signature,
|
|
|
|
&ef->signature_length,
|
|
|
|
&ef->x509_length);
|
|
|
|
|
2010-08-21 06:52:25 -07:00
|
|
|
if (eet_test_close(!ef->x509_der, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#else /* ifdef HAVE_SIGNATURE */
|
2010-07-27 18:45:57 -07:00
|
|
|
ERR(
|
|
|
|
"This file could be signed but you didn't compile the necessary code to check the signature.");
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_SIGNATURE */
|
2008-09-08 02:19:57 -07:00
|
|
|
}
|
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
return ef;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_internal_read2 */
|
2008-02-29 22:38:09 -08:00
|
|
|
|
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 *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_internal_read1(Eet_File *ef)
|
2008-02-29 22:38:09 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
const unsigned char *dyn_buf = NULL;
|
|
|
|
const unsigned char *p = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
int idx = 0;
|
|
|
|
int num_entries;
|
|
|
|
int byte_entries;
|
|
|
|
int i;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
WRN(
|
|
|
|
"EET file format of '%s' is deprecated. You should just open it one time with mode == EET_FILE_MODE_READ_WRITE to solve this issue.",
|
|
|
|
ef->path);
|
2008-05-19 08:23:41 -07:00
|
|
|
|
2008-01-20 17:09:51 -08:00
|
|
|
/* build header table if read mode */
|
|
|
|
/* geat header */
|
2010-03-01 03:03:35 -08:00
|
|
|
idx += sizeof(int);
|
2008-01-20 17:09:51 -08:00
|
|
|
if (eet_test_close((int)ntohl(*((int *)ef->data)) != EET_MAGIC_FILE, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#define EXTRACT_INT(Value, Pointer, Index)\
|
|
|
|
{\
|
|
|
|
int tmp;\
|
|
|
|
memcpy(&tmp, Pointer + Index, sizeof(int));\
|
|
|
|
Value = ntohl(tmp);\
|
|
|
|
Index += sizeof(int);\
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
2008-01-20 17:09:51 -08:00
|
|
|
|
|
|
|
/* get entries count and byte count */
|
2010-07-27 18:45:57 -07:00
|
|
|
EXTRACT_INT(num_entries, ef->data, idx);
|
2010-03-01 03:03:35 -08:00
|
|
|
EXTRACT_INT(byte_entries, ef->data, idx);
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2010-09-07 20:26:19 -07:00
|
|
|
/* we can't have <= 0 values here - invalid */
|
2008-01-20 17:09:51 -08:00
|
|
|
if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
|
|
|
/* we can't have more entires than minimum bytes for those! invalid! */
|
|
|
|
if (eet_test_close((num_entries * 20) > byte_entries, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
/* check we will not outrun the file limit */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close(((byte_entries + (int)sizeof(int) * 3) > ef->data_size),
|
|
|
|
ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
|
|
|
/* 8 bit hash table (256 buckets) */
|
|
|
|
ef->header->directory->size = 8;
|
|
|
|
/* allocate base hash table */
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->header->directory->nodes =
|
|
|
|
calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
|
2008-01-20 17:09:51 -08:00
|
|
|
if (eet_test_close(!ef->header->directory->nodes, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
|
|
|
/* actually read the directory block - all of it, into ram */
|
2010-03-01 03:03:35 -08:00
|
|
|
dyn_buf = ef->data + idx;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
|
|
|
/* parse directory block */
|
|
|
|
p = dyn_buf;
|
|
|
|
|
|
|
|
for (i = 0; i < num_entries; i++)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
void *data = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
int indexn = 0;
|
|
|
|
int name_size;
|
|
|
|
int hash;
|
|
|
|
int k;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
|
|
|
#define HEADER_SIZE (sizeof(int) * 5)
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
/* 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;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
/* allocate all the ram needed for this stored node accounting */
|
|
|
|
efn = malloc (sizeof(Eet_File_Node));
|
|
|
|
if (eet_test_close(!efn, ef))
|
2010-08-22 15:21:41 -07:00
|
|
|
{
|
|
|
|
if (efn) free(efn); /* yes i know - we only get here if
|
|
|
|
* efn is null/0 -> trying to shut up
|
|
|
|
* warning tools like cppcheck */
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
/* get entrie header */
|
2010-07-27 18:45:57 -07: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-01-20 17:09:51 -08:00
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
efn->name_size = name_size;
|
2010-07-27 18:45:57 -07:00
|
|
|
efn->ciphered = 0;
|
|
|
|
efn->alias = 0;
|
|
|
|
|
|
|
|
/* invalid size */
|
|
|
|
if (eet_test_close(efn->size <= 0, ef))
|
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
free(efn);
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* invalid name_size */
|
|
|
|
if (eet_test_close(name_size <= 0, ef))
|
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
free(efn);
|
2010-07-27 18:45:57 -07:00
|
|
|
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))
|
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
free(efn);
|
2010-07-27 18:45:57 -07:00
|
|
|
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);
|
2010-08-21 06:52:25 -07:00
|
|
|
if (eet_test_close(!efn->name, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
{
|
|
|
|
free(efn);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
|
|
|
|
efn->name[name_size] = 0;
|
|
|
|
|
|
|
|
WRN(
|
|
|
|
"File: %s is not up to date for key \"%s\" - needs rebuilding sometime",
|
|
|
|
ef->path,
|
|
|
|
efn->name);
|
|
|
|
}
|
|
|
|
else
|
2010-09-07 20:26:19 -07:00
|
|
|
/* The only really useful peace of code for efn->name (no backward compatibility) */
|
2010-07-27 18:45:57 -07:00
|
|
|
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)
|
2010-07-27 20:03:10 -07:00
|
|
|
efn->data = NULL; /* read-write mode - read everything into ram */
|
2010-07-27 18:45:57 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
data = malloc(efn->size);
|
|
|
|
if (data)
|
|
|
|
memcpy(data, ef->data + efn->offset, efn->size);
|
|
|
|
|
|
|
|
efn->data = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* advance */
|
|
|
|
p += HEADER_SIZE + name_size;
|
2008-01-20 17:09:51 -08:00
|
|
|
}
|
|
|
|
return ef;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_internal_read1 */
|
|
|
|
|
|
|
|
#endif /* if EET_OLD_EET_FILE_FORMAT */
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2010-03-15 07:47:51 -07:00
|
|
|
/*
|
|
|
|
* this should only be called when the cache lock is already held
|
|
|
|
* (We could drop this restriction if we add a parameter to eet_test_close
|
|
|
|
* that indicates if the lock is held or not. For now it is easiest
|
|
|
|
* to just require that it is always held.)
|
|
|
|
*/
|
2008-03-28 07:37:29 -07:00
|
|
|
static Eet_File *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_internal_read(Eet_File *ef)
|
2008-02-29 22:38:09 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
const int *data = (const int *)ef->data;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-08-21 06:52:25 -07:00
|
|
|
if (eet_test_close((ef->data == (void *)-1) || (!ef->data), ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-03-29 00:28:18 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_test_close(ef->data_size < (int)sizeof(int) * 3, ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
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:
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_internal_read1(ef);
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* if EET_OLD_EET_FILE_FORMAT */
|
2008-02-29 22:38:09 -08:00
|
|
|
case EET_MAGIC_FILE2:
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_internal_read2(ef);
|
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
default:
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->delete_me_now = 1;
|
|
|
|
eet_internal_close(ef, EINA_TRUE);
|
|
|
|
break;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* switch */
|
2008-03-29 00:28:18 -07:00
|
|
|
|
2008-02-29 22:38:09 -08:00
|
|
|
return NULL;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_internal_read */
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-01-04 20:40:12 -08:00
|
|
|
static Eet_Error
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_internal_close(Eet_File *ef,
|
|
|
|
Eina_Bool locked)
|
2010-01-04 20:40:12 -08:00
|
|
|
{
|
|
|
|
Eet_Error err;
|
|
|
|
|
|
|
|
/* check to see its' an eet file pointer */
|
|
|
|
if (eet_check_pointer(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_ERROR_BAD_OBJECT;
|
2010-03-15 07:47:51 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!locked)
|
|
|
|
LOCK_CACHE;
|
2010-03-15 07:47:51 -07:00
|
|
|
|
2010-01-04 20:40:12 -08:00
|
|
|
/* deref */
|
|
|
|
ef->references--;
|
|
|
|
/* if its still referenced - dont go any further */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (ef->references > 0)
|
2010-07-27 20:03:10 -07:00
|
|
|
goto on_error; /* flush any writes */
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2010-01-04 20:40:12 -08:00
|
|
|
err = eet_flush2(ef);
|
|
|
|
|
|
|
|
eet_identity_unref(ef->key);
|
|
|
|
ef->key = NULL;
|
|
|
|
|
|
|
|
/* if not urgent to delete it - dont free it - leave it in cache */
|
|
|
|
if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
|
2010-07-27 18:45:57 -07:00
|
|
|
goto on_error;
|
2010-03-05 09:19:03 -08:00
|
|
|
|
|
|
|
/* remove from cache */
|
2010-01-04 20:40:12 -08:00
|
|
|
if (ef->mode == EET_FILE_MODE_READ)
|
2010-07-27 18:45:57 -07:00
|
|
|
eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
|
|
|
|
else if ((ef->mode == EET_FILE_MODE_WRITE) ||
|
2010-07-27 20:03:10 -07:00
|
|
|
(
|
|
|
|
ef
|
|
|
|
->
|
|
|
|
mode == EET_FILE_MODE_READ_WRITE))
|
2010-07-27 18:45:57 -07:00
|
|
|
eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
|
2010-03-15 07:47:51 -07:00
|
|
|
|
|
|
|
/* we can unlock the cache now */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!locked)
|
|
|
|
UNLOCK_CACHE;
|
2010-01-04 20:40:12 -08:00
|
|
|
|
|
|
|
DESTROY_FILE(ef);
|
|
|
|
|
|
|
|
/* free up data */
|
|
|
|
if (ef->header)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (ef->header->directory)
|
|
|
|
{
|
|
|
|
if (ef->header->directory->nodes)
|
|
|
|
{
|
|
|
|
int i, num;
|
|
|
|
|
|
|
|
num = (1 << ef->header->directory->size);
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
while ((efn = ef->header->directory->nodes[i]))
|
|
|
|
{
|
|
|
|
if (efn->data)
|
|
|
|
free(efn->data);
|
|
|
|
|
|
|
|
ef->header->directory->nodes[i] = efn->next;
|
|
|
|
|
|
|
|
if (efn->free_name)
|
|
|
|
free(efn->name);
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
free(efn);
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
|
|
|
}
|
2010-07-30 18:54:48 -07:00
|
|
|
free(ef->header->directory->nodes);
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
free(ef->header->directory);
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
free(ef->header);
|
2010-01-04 20:40:12 -08:00
|
|
|
}
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
eet_dictionary_free(ef->ed);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (ef->sha1)
|
|
|
|
free(ef->sha1);
|
2010-01-04 20:40:12 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (ef->data)
|
|
|
|
munmap((void *)ef->data, ef->data_size);
|
|
|
|
|
|
|
|
if (ef->readfp)
|
|
|
|
fclose(ef->readfp);
|
2010-01-04 20:40:12 -08:00
|
|
|
|
|
|
|
/* zero out ram for struct - caution tactic against stale memory use */
|
|
|
|
memset(ef, 0, sizeof(Eet_File));
|
|
|
|
|
|
|
|
/* free it */
|
|
|
|
free(ef);
|
|
|
|
return err;
|
2010-03-15 07:47:51 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
on_error:
|
|
|
|
if (!locked)
|
|
|
|
UNLOCK_CACHE;
|
|
|
|
|
2010-03-15 07:47:51 -07:00
|
|
|
return EET_ERROR_NONE;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_internal_close */
|
2010-01-04 20:40:12 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI Eet_File *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_memopen_read(const void *data,
|
|
|
|
size_t size)
|
2008-01-20 17:09:51 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File *ef;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2010-08-21 06:52:25 -07:00
|
|
|
if (!data || size == 0)
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
|
|
|
ef = malloc (sizeof (Eet_File));
|
|
|
|
if (!ef)
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
INIT_FILE(ef);
|
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;
|
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
|
|
|
|
2010-03-15 07:47:51 -07:00
|
|
|
/* eet_internal_read expects the cache lock to be held when it is called */
|
|
|
|
LOCK_CACHE;
|
|
|
|
ef = eet_internal_read(ef);
|
|
|
|
UNLOCK_CACHE;
|
|
|
|
return ef;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_memopen_read */
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI Eet_File *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_open(const char *file,
|
2010-07-30 18:54:48 -07:00
|
|
|
Eet_File_Mode mode)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
FILE *fp;
|
|
|
|
Eet_File *ef;
|
2010-07-27 18:45:57 -07:00
|
|
|
int file_len;
|
|
|
|
struct stat file_stat;
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (!file)
|
2010-07-27 18:45:57 -07:00
|
|
|
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;
|
2009-12-03 07:35:04 -08:00
|
|
|
LOCK_CACHE;
|
2002-12-02 15:39:26 -08:00
|
|
|
if (mode == EET_FILE_MODE_READ)
|
2005-11-03 07:05:21 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
|
|
|
|
if (ef)
|
|
|
|
{
|
|
|
|
eet_sync(ef);
|
|
|
|
ef->references++;
|
|
|
|
ef->delete_me_now = 1;
|
2010-03-15 07:47:51 -07:00
|
|
|
eet_internal_close(ef, EINA_TRUE);
|
2010-07-27 18:45:57 -07: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) ||
|
2010-07-27 18:45:57 -07:00
|
|
|
(mode == EET_FILE_MODE_READ_WRITE))
|
2005-11-03 07:05:21 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
|
|
|
|
if (ef)
|
|
|
|
{
|
|
|
|
ef->delete_me_now = 1;
|
|
|
|
ef->references++;
|
2010-03-15 07:47:51 -07:00
|
|
|
eet_internal_close(ef, EINA_TRUE);
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
|
2005-11-03 07:05:21 -08:00
|
|
|
}
|
2010-04-09 06:45:25 -07:00
|
|
|
|
|
|
|
/* try open the file based on mode */
|
2008-01-20 17:09:51 -08:00
|
|
|
if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
|
2006-06-13 03:20:22 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* Prevent garbage in futur comparison. */
|
|
|
|
file_stat.st_mtime = 0;
|
|
|
|
|
|
|
|
fp = fopen(file, "rb");
|
|
|
|
if (!fp)
|
|
|
|
goto open_error;
|
|
|
|
|
|
|
|
if (fstat(fileno(fp), &file_stat))
|
|
|
|
{
|
|
|
|
fclose(fp);
|
|
|
|
fp = NULL;
|
2010-11-12 04:19:41 -08:00
|
|
|
|
|
|
|
memset(&file_stat, 0, sizeof(file_stat));
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
goto open_error;
|
|
|
|
}
|
|
|
|
|
2010-11-12 02:31:07 -08:00
|
|
|
if (file_stat.st_size < ((int)sizeof(int) * 3))
|
2010-07-27 18:45:57 -07:00
|
|
|
{
|
|
|
|
fclose(fp);
|
|
|
|
fp = NULL;
|
2010-11-12 04:19:41 -08:00
|
|
|
|
|
|
|
memset(&file_stat, 0, sizeof(file_stat));
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
goto open_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
open_error:
|
2010-08-21 06:52:25 -07:00
|
|
|
if (!fp && mode == EET_FILE_MODE_READ)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto on_error;
|
2008-01-20 17:09:51 -08:00
|
|
|
}
|
|
|
|
else
|
2007-11-11 22:15:08 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (mode != EET_FILE_MODE_WRITE)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memset(&file_stat, 0, sizeof(file_stat));
|
2010-04-09 06:45:25 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
fp = 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 */
|
2010-07-20 09:13:51 -07:00
|
|
|
if (ef &&
|
2010-07-27 18:45:57 -07:00
|
|
|
((file_stat.st_mtime != ef->mtime) ||
|
|
|
|
(file_stat.st_size != ef->data_size)))
|
2006-06-13 03:20:22 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->delete_me_now = 1;
|
|
|
|
ef->references++;
|
2010-03-16 05:10:28 -07:00
|
|
|
eet_internal_close(ef, EINA_TRUE);
|
2010-07-27 18:45:57 -07:00
|
|
|
ef = NULL;
|
2006-06-13 03:20:22 -07:00
|
|
|
}
|
2008-01-20 17:09:51 -08:00
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
if (ef)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* reference it up and return it */
|
2010-08-21 06:52:25 -07:00
|
|
|
if (fp)
|
2010-07-27 18:45:57 -07:00
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
ef->references++;
|
|
|
|
UNLOCK_CACHE;
|
|
|
|
return ef;
|
2002-12-02 15:39:26 -08:00
|
|
|
}
|
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)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto on_error;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
/* fill some of the members */
|
2009-12-03 07:35:04 -08:00
|
|
|
INIT_FILE(ef);
|
2008-09-08 02:19:57 -07:00
|
|
|
ef->key = NULL;
|
2010-04-09 06:45:25 -07:00
|
|
|
ef->readfp = fp;
|
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)
|
2010-08-25 18:34:13 -07:00
|
|
|
|| (!ef->readfp && mode == EET_FILE_MODE_READ_WRITE) ?
|
2010-07-27 18:45:57 -07:00
|
|
|
eet_dictionary_add() : NULL;
|
2008-05-16 03:00:54 -07:00
|
|
|
|
2010-08-25 18:34:13 -07:00
|
|
|
if (!ef->readfp &&
|
2010-04-09 06:45:25 -07:00
|
|
|
(mode == EET_FILE_MODE_READ_WRITE || mode == EET_FILE_MODE_WRITE))
|
2010-07-27 18:45:57 -07:00
|
|
|
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 */
|
2010-04-09 06:45:25 -07:00
|
|
|
if (eet_test_close(!ef->readfp, ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
goto on_error;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2010-04-09 06:45:25 -07:00
|
|
|
fcntl(fileno(ef->readfp), 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
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->data_size = file_stat.st_size;
|
|
|
|
ef->data = mmap(NULL, ef->data_size, PROT_READ,
|
|
|
|
MAP_SHARED, fileno(ef->readfp), 0);
|
|
|
|
if (eet_test_close((ef->data == MAP_FAILED), ef))
|
|
|
|
goto on_error;
|
|
|
|
|
|
|
|
ef = eet_internal_read(ef);
|
|
|
|
if (!ef)
|
|
|
|
goto on_error;
|
2002-12-02 15:39:26 -08:00
|
|
|
}
|
2004-10-19 20:13:44 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
empty_file:
|
2002-12-02 15:39:26 -08:00
|
|
|
/* add to cache */
|
2005-11-03 07:05:21 -08:00
|
|
|
if (ef->references == 1)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (ef->mode == EET_FILE_MODE_READ)
|
|
|
|
eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
|
|
|
|
else
|
|
|
|
if ((ef->mode == EET_FILE_MODE_WRITE) ||
|
|
|
|
(ef->mode == EET_FILE_MODE_READ_WRITE))
|
|
|
|
eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
|
2005-11-03 07:05:21 -08:00
|
|
|
}
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2010-03-15 07:47:51 -07:00
|
|
|
UNLOCK_CACHE;
|
2002-12-02 15:39:26 -08:00
|
|
|
return ef;
|
2010-03-15 07:47:51 -07:00
|
|
|
|
|
|
|
on_error:
|
|
|
|
UNLOCK_CACHE;
|
|
|
|
return NULL;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_open */
|
2002-12-02 15:39:26 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI Eet_File_Mode
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_mode_get(Eet_File *ef)
|
2005-02-07 10:10:20 -08:00
|
|
|
{
|
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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EET_FILE_MODE_INVALID;
|
2005-02-07 10:10:20 -08:00
|
|
|
else
|
2010-07-27 18:45:57 -07:00
|
|
|
return ef->mode;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_mode_get */
|
2005-02-07 10:10:20 -08:00
|
|
|
|
2008-09-08 02:19:57 -07:00
|
|
|
EAPI const void *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_identity_x509(Eet_File *ef,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *der_length)
|
2008-09-08 02:19:57 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!ef->x509_der)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (der_length)
|
|
|
|
*der_length = ef->x509_length;
|
2008-09-08 02:19:57 -07:00
|
|
|
|
|
|
|
return ef->x509_der;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_identity_x509 */
|
2008-09-08 02:19:57 -07:00
|
|
|
|
2008-11-26 02:45:47 -08:00
|
|
|
EAPI const void *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_identity_signature(Eet_File *ef,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *signature_length)
|
2008-11-26 02:45:47 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!ef->signature)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (signature_length)
|
|
|
|
*signature_length = ef->signature_length;
|
2008-11-26 02:45:47 -08:00
|
|
|
|
|
|
|
return ef->signature;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_identity_signature */
|
2008-11-26 02:45:47 -08:00
|
|
|
|
2009-02-09 05:53:20 -08:00
|
|
|
EAPI const void *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_identity_sha1(Eet_File *ef,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *sha1_length)
|
2009-02-09 05:53:20 -08:00
|
|
|
{
|
|
|
|
if (!ef->sha1)
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->sha1 = eet_identity_compute_sha1(ef->data,
|
|
|
|
ef->data_size,
|
|
|
|
&ef->sha1_length);
|
|
|
|
|
|
|
|
if (sha1_length)
|
|
|
|
*sha1_length = ef->sha1_length;
|
2009-02-09 05:53:20 -08:00
|
|
|
|
|
|
|
return ef->sha1;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_identity_sha1 */
|
2009-02-09 05:53:20 -08:00
|
|
|
|
2008-09-08 02:19:57 -07:00
|
|
|
EAPI Eet_Error
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_identity_set(Eet_File *ef,
|
2010-07-31 11:57:35 -07:00
|
|
|
Eet_Key *key)
|
2008-09-08 02:19:57 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_Key *tmp = ef->key;
|
2008-09-08 02:19:57 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!ef)
|
|
|
|
return EET_ERROR_BAD_OBJECT;
|
2008-09-08 02:19:57 -07:00
|
|
|
|
|
|
|
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;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_identity_set */
|
2008-09-08 02:19:57 -07:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI Eet_Error
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_close(Eet_File *ef)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-03-15 07:47:51 -07:00
|
|
|
return eet_internal_close(ef, EINA_FALSE);
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_close */
|
2002-12-02 15:39:26 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_read_cipher(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *size_ret,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *cipher_key)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
char *data = NULL;
|
2010-06-29 09:20:23 -07:00
|
|
|
int size = 0;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
|
|
|
if (size_ret)
|
2010-07-27 18:45:57 -07:00
|
|
|
*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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (!name)
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if ((ef->mode != EET_FILE_MODE_READ) &&
|
|
|
|
(ef->mode != EET_FILE_MODE_READ_WRITE))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2005-11-29 10:49:30 -08:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
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);
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!efn)
|
|
|
|
goto on_error;
|
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);
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!data)
|
|
|
|
goto on_error;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-11-29 10:49:30 -08:00
|
|
|
/* uncompressed data */
|
|
|
|
if (efn->compression == 0)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *data_deciphered = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int data_deciphered_sz = 0;
|
2010-09-07 20:26:19 -07:00
|
|
|
/* if we already have the data in ram... copy that */
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2010-11-18 02:30:53 -08:00
|
|
|
if (efn->ciphered && efn->size > size)
|
|
|
|
{
|
|
|
|
size = efn->size;
|
|
|
|
data = realloc(data, efn->size);
|
|
|
|
}
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (efn->data)
|
2010-11-18 02:30:53 -08:00
|
|
|
memcpy(data, efn->data, size);
|
2010-07-27 18:45:57 -07:00
|
|
|
else
|
2010-11-18 02:30:53 -08:00
|
|
|
if (!read_data_from_disk(ef, efn, data, size))
|
|
|
|
goto on_error;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
if (efn->ciphered && cipher_key)
|
2010-07-27 18:45:57 -07:00
|
|
|
{
|
2010-11-18 02:30:53 -08:00
|
|
|
if (eet_decipher(data, efn->size, cipher_key, strlen(cipher_key),
|
2010-07-27 18:45:57 -07:00
|
|
|
&data_deciphered, &data_deciphered_sz))
|
|
|
|
{
|
|
|
|
if (data_deciphered)
|
|
|
|
free(data_deciphered);
|
|
|
|
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
free(data);
|
2010-07-27 18:45:57 -07:00
|
|
|
data = data_deciphered;
|
|
|
|
size = data_deciphered_sz;
|
|
|
|
}
|
2005-11-29 10:49:30 -08:00
|
|
|
}
|
|
|
|
/* compressed data */
|
|
|
|
else
|
|
|
|
{
|
2010-11-20 21:18:19 -08:00
|
|
|
void *tmp_data = NULL;
|
2010-07-31 11:54:54 -07:00
|
|
|
void *data_deciphered = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int data_deciphered_sz = 0;
|
|
|
|
int free_tmp = 0;
|
|
|
|
int compr_size = efn->size;
|
|
|
|
uLongf dlen;
|
|
|
|
|
|
|
|
/* if we already have the data in ram... copy that */
|
|
|
|
if (efn->data)
|
|
|
|
tmp_data = efn->data;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmp_data = malloc(compr_size);
|
|
|
|
if (!tmp_data)
|
|
|
|
goto on_error;
|
|
|
|
|
|
|
|
free_tmp = 1;
|
|
|
|
|
|
|
|
if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
|
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
free(tmp_data);
|
2010-07-27 18:45:57 -07:00
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (efn->ciphered && cipher_key)
|
|
|
|
{
|
|
|
|
if (eet_decipher(tmp_data, compr_size, cipher_key,
|
|
|
|
strlen(cipher_key), &data_deciphered,
|
|
|
|
&data_deciphered_sz))
|
|
|
|
{
|
|
|
|
if (free_tmp)
|
|
|
|
free(tmp_data);
|
|
|
|
|
|
|
|
if (data_deciphered)
|
|
|
|
free(data_deciphered);
|
|
|
|
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
2010-11-20 21:18:19 -08:00
|
|
|
if (free_tmp)
|
|
|
|
free(tmp_data);
|
|
|
|
free_tmp = 1;
|
2010-07-27 18:45:57 -07:00
|
|
|
tmp_data = data_deciphered;
|
|
|
|
compr_size = data_deciphered_sz;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* decompress it */
|
|
|
|
dlen = size;
|
|
|
|
if (uncompress((Bytef *)data, &dlen,
|
|
|
|
tmp_data, (uLongf)compr_size))
|
2010-11-20 21:18:19 -08:00
|
|
|
{
|
|
|
|
if (free_tmp)
|
|
|
|
free(tmp_data);
|
|
|
|
goto on_error;
|
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (free_tmp)
|
2010-07-30 18:54:48 -07:00
|
|
|
free(tmp_data);
|
2002-12-02 15:39:26 -08:00
|
|
|
}
|
2005-11-29 10:49:30 -08:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
UNLOCK_FILE(ef);
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-06-29 09:20:23 -07:00
|
|
|
/* handle alias */
|
|
|
|
if (efn->alias)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *tmp;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (data[size - 1] != '\0')
|
|
|
|
goto on_error;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
tmp = eet_read_cipher(ef, data, size_ret, cipher_key);
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
free(data);
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
data = tmp;
|
2010-06-29 09:20:23 -07:00
|
|
|
}
|
|
|
|
else
|
2010-07-27 18:45:57 -07:00
|
|
|
/* fill in return values */
|
|
|
|
if (size_ret)
|
|
|
|
*size_ret = size;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
return data;
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
on_error:
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
free(data);
|
|
|
|
return NULL;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_read_cipher */
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_read(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *size_ret)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
|
|
|
return eet_read_cipher(ef, name, size_ret, NULL);
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_read */
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI const void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_read_direct(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *size_ret)
|
2006-06-13 03:20:22 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
const char *data = NULL;
|
2010-06-29 09:20:23 -07:00
|
|
|
int size = 0;
|
2008-01-24 00:41:23 -08:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (size_ret)
|
2010-07-27 18:45:57 -07:00
|
|
|
*size_ret = 0;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
|
|
|
/* check to see its' an eet file pointer */
|
|
|
|
if (eet_check_pointer(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (!name)
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if ((ef->mode != EET_FILE_MODE_READ) &&
|
|
|
|
(ef->mode != EET_FILE_MODE_READ_WRITE))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
|
|
|
/* no header, return NULL */
|
|
|
|
if (eet_check_header(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
/* hunt hash bucket */
|
|
|
|
efn = find_node_by_name(ef, name);
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!efn)
|
|
|
|
goto on_error;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2010-08-25 18:34:13 -07:00
|
|
|
if (efn->offset < 0 && !efn->data)
|
2010-07-27 18:45:57 -07:00
|
|
|
goto on_error;
|
2008-05-16 07:03:11 -07:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
/* get size (uncompressed, if compressed at all) */
|
|
|
|
size = efn->data_size;
|
|
|
|
|
2010-06-29 09:20:23 -07:00
|
|
|
if (efn->alias)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
data = efn->data ? efn->data : ef->data + efn->offset;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
/* handle alias case */
|
|
|
|
if (efn->compression)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
char *tmp;
|
2010-07-27 18:45:57 -07:00
|
|
|
int compr_size = efn->size;
|
|
|
|
uLongf dlen;
|
|
|
|
|
|
|
|
tmp = alloca(sizeof (compr_size));
|
|
|
|
dlen = size;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (uncompress((Bytef *)tmp, &dlen, (Bytef *)data,
|
|
|
|
(uLongf)compr_size))
|
|
|
|
goto on_error;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (tmp[compr_size - 1] != '\0')
|
|
|
|
goto on_error;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-08-09 10:21:10 -07:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_read_direct(ef, tmp, size_ret);
|
|
|
|
}
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!data)
|
|
|
|
goto on_error;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (data[size - 1] != '\0')
|
|
|
|
goto on_error;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2010-08-09 10:21:10 -07:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_read_direct(ef, data, size_ret);
|
2010-06-29 09:20:23 -07:00
|
|
|
}
|
2006-06-13 03:20:22 -07:00
|
|
|
else
|
2010-07-27 18:45:57 -07:00
|
|
|
/* uncompressed data */
|
|
|
|
if (efn->compression == 0
|
|
|
|
&& efn->ciphered == 0)
|
2010-07-27 20:03:10 -07:00
|
|
|
data = efn->data ? efn->data : ef->data + efn->offset; /* compressed data */
|
2010-07-27 18:45:57 -07:00
|
|
|
else
|
|
|
|
data = NULL;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
|
|
|
/* fill in return values */
|
|
|
|
if (size_ret)
|
2010-07-27 18:45:57 -07:00
|
|
|
*size_ret = size;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
return data;
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
on_error:
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
return NULL;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_read_direct */
|
2002-12-02 15:39:26 -08:00
|
|
|
|
2010-06-29 09:20:23 -07:00
|
|
|
EAPI Eina_Bool
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_alias(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name,
|
|
|
|
const char *destination,
|
|
|
|
int comp)
|
2010-06-29 09:20:23 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
void *data2;
|
2010-06-29 09:20:23 -07:00
|
|
|
Eina_Bool exists_already = EINA_FALSE;
|
|
|
|
int data_size;
|
|
|
|
int hash;
|
|
|
|
|
|
|
|
/* check to see its' an eet file pointer */
|
|
|
|
if (eet_check_pointer(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
|
2010-06-29 09:20:23 -07:00
|
|
|
if ((!name) || (!destination))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
|
2010-06-29 09:20:23 -07:00
|
|
|
if ((ef->mode != EET_FILE_MODE_WRITE) &&
|
|
|
|
(ef->mode != EET_FILE_MODE_READ_WRITE))
|
2010-07-27 18:45:57 -07:00
|
|
|
return EINA_FALSE;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
|
|
|
if (!ef->header)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* 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;
|
|
|
|
}
|
2010-06-29 09:20:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* figure hash bucket */
|
|
|
|
hash = _eet_hash_gen(name, ef->header->directory->size);
|
|
|
|
|
|
|
|
data_size = comp ?
|
2010-07-27 18:45:57 -07:00
|
|
|
12 + (((strlen(destination) + 1) * 101) / 100)
|
|
|
|
: strlen(destination) + 1;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
|
|
|
data2 = malloc(data_size);
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!data2)
|
|
|
|
goto on_error;
|
2010-06-29 09:20:23 -07:00
|
|
|
|
|
|
|
/* if we want to compress */
|
|
|
|
if (comp)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
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
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *data3;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
data3 = realloc(data2, data_size);
|
|
|
|
if (data3)
|
|
|
|
data2 = data3;
|
|
|
|
}
|
2010-06-29 09:20:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!comp)
|
2010-07-27 18:45:57 -07:00
|
|
|
memcpy(data2, destination, data_size);
|
2010-06-29 09:20:23 -07:00
|
|
|
|
|
|
|
/* Does this node already exist? */
|
|
|
|
for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* 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;
|
|
|
|
}
|
2010-06-29 09:20:23 -07:00
|
|
|
}
|
|
|
|
if (!exists_already)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
efn = malloc(sizeof(Eet_File_Node));
|
|
|
|
if (!efn)
|
|
|
|
{
|
|
|
|
free(data2);
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
efn->name = strdup(name);
|
2010-06-29 09:20:23 -07:00
|
|
|
efn->name_size = strlen(efn->name) + 1;
|
|
|
|
efn->free_name = 1;
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
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;
|
2010-06-29 09:20:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* flags that writes are pending */
|
|
|
|
ef->writes_pending = 1;
|
|
|
|
|
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
on_error:
|
2010-06-29 09:20:23 -07:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
return EINA_FALSE;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_alias */
|
2010-06-29 09:20:23 -07:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_write_cipher(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name,
|
|
|
|
const void *data,
|
|
|
|
int size,
|
|
|
|
int comp,
|
|
|
|
const char *cipher_key)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
void *data2 = NULL;
|
2010-07-27 18:45:57 -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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return 0;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if ((!name) || (!data) || (size <= 0))
|
2010-07-27 18:45:57 -07:00
|
|
|
return 0;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if ((ef->mode != EET_FILE_MODE_WRITE) &&
|
|
|
|
(ef->mode != EET_FILE_MODE_READ_WRITE))
|
2010-07-27 18:45:57 -07:00
|
|
|
return 0;
|
2002-12-02 15:39:26 -08:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
if (!ef->header)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* 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)
|
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
free(ef->header->directory);
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->header = NULL;
|
|
|
|
goto on_error;
|
|
|
|
}
|
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
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
data_size = comp ? 12 + ((size * 101) / 100) : size;
|
2005-05-26 03:53:53 -07:00
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp || !cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
data2 = malloc(data_size);
|
|
|
|
if (!data2)
|
|
|
|
goto on_error;
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
2005-11-04 09:44:01 -08:00
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
/* if we want to compress */
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
uLongf buflen;
|
|
|
|
|
|
|
|
/* compress the data with max compression */
|
|
|
|
buflen = (uLongf)data_size;
|
|
|
|
if (compress2((Bytef *)data2, &buflen, (Bytef *)data,
|
|
|
|
(uLong)size, Z_BEST_COMPRESSION) != Z_OK)
|
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
free(data2);
|
2010-07-27 18:45:57 -07:00
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* record compressed chunk size */
|
|
|
|
data_size = (int)buflen;
|
|
|
|
if (data_size < 0 || data_size >= size)
|
|
|
|
{
|
|
|
|
comp = 0;
|
|
|
|
data_size = size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *data3;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
data3 = realloc(data2, data_size);
|
|
|
|
if (data3)
|
|
|
|
data2 = data3;
|
|
|
|
}
|
2002-12-02 15:39:26 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
|
|
|
if (cipher_key)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *data_ciphered = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int data_ciphered_sz = 0;
|
2010-07-31 11:54:54 -07:00
|
|
|
const void *tmp;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2010-09-06 03:54:03 -07:00
|
|
|
tmp = comp ? data2 : data;
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!eet_cipher(tmp, data_size, cipher_key, strlen(cipher_key),
|
|
|
|
&data_ciphered, &data_ciphered_sz))
|
|
|
|
{
|
|
|
|
if (data2)
|
|
|
|
free(data2);
|
|
|
|
|
|
|
|
data2 = data_ciphered;
|
|
|
|
data_size = data_ciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (data_ciphered)
|
|
|
|
free(data_ciphered);
|
|
|
|
|
|
|
|
cipher_key = NULL;
|
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
else
|
2010-09-06 03:54:03 -07:00
|
|
|
if (!comp)
|
|
|
|
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
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* if it matches */
|
|
|
|
if ((efn->name) && (eet_string_match(efn->name, name)))
|
|
|
|
{
|
|
|
|
free(efn->data);
|
|
|
|
efn->alias = 0;
|
|
|
|
efn->ciphered = cipher_key ? 1 : 0;
|
|
|
|
efn->compression = !!comp;
|
|
|
|
efn->size = data_size;
|
|
|
|
efn->data_size = size;
|
|
|
|
efn->data = data2;
|
|
|
|
efn->offset = -1;
|
|
|
|
exists_already = 1;
|
|
|
|
break;
|
|
|
|
}
|
2002-12-02 15:39:26 -08:00
|
|
|
}
|
2004-10-19 20:13:44 -07:00
|
|
|
if (!exists_already)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
efn = malloc(sizeof(Eet_File_Node));
|
|
|
|
if (!efn)
|
|
|
|
{
|
|
|
|
free(data2);
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
efn->name = strdup(name);
|
2008-02-29 22:38:09 -08:00
|
|
|
efn->name_size = strlen(efn->name) + 1;
|
|
|
|
efn->free_name = 1;
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
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;
|
|
|
|
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;
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
2003-06-16 06:39:42 -07:00
|
|
|
return data_size;
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
on_error:
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
return 0;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_write_cipher */
|
2002-12-02 15:39:26 -08:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_write(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name,
|
|
|
|
const void *data,
|
|
|
|
int size,
|
|
|
|
int comp)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_write_cipher(ef, name, data, size, comp, NULL);
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_write */
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_delete(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name)
|
2004-12-01 20:25:25 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
Eet_File_Node *pefn;
|
2010-07-27 18:45:57 -07:00
|
|
|
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))
|
2010-07-27 18:45:57 -07:00
|
|
|
return 0;
|
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (!name)
|
2010-07-27 18:45:57 -07:00
|
|
|
return 0;
|
2004-12-01 20:25:25 -08:00
|
|
|
|
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)
|
2010-07-27 18:45:57 -07:00
|
|
|
return 0;
|
2005-01-12 11:59:11 -08:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (eet_check_header(ef))
|
2010-07-27 18:45:57 -07:00
|
|
|
return 0;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
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];
|
2010-07-27 18:45:57 -07:00
|
|
|
efn;
|
|
|
|
pefn = efn, efn = efn->next)
|
2004-12-01 20:25:25 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
/* if it matches */
|
|
|
|
if (eet_string_match(efn->name, name))
|
|
|
|
{
|
|
|
|
if (efn->data)
|
|
|
|
free(efn->data);
|
|
|
|
|
2010-08-21 06:52:25 -07:00
|
|
|
if (!pefn)
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->header->directory->nodes[hash] = efn->next;
|
|
|
|
else
|
|
|
|
pefn->next = efn->next;
|
|
|
|
|
|
|
|
if (efn->free_name)
|
|
|
|
free(efn->name);
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
free(efn);
|
2010-07-27 18:45:57 -07: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)
|
2010-07-27 18:45:57 -07:00
|
|
|
ef->writes_pending = 1;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
|
2004-12-01 20:25:25 -08:00
|
|
|
/* update access time */
|
|
|
|
return exists_already;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_delete */
|
2004-12-01 20:25:25 -08:00
|
|
|
|
2008-03-28 07:37:29 -07:00
|
|
|
EAPI Eet_Dictionary *
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_dictionary_get(Eet_File *ef)
|
2008-02-29 22:38:09 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_check_pointer(ef))
|
|
|
|
return NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
|
|
|
return ef->ed;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_dictionary_get */
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI char **
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_list(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *glob,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *count_ret)
|
2002-12-02 15:39:26 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
|
|
|
char **list_ret = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
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
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (count_ret)
|
|
|
|
*count_ret = 0;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2002-12-02 15:39:26 -08:00
|
|
|
}
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!strcmp(glob, "*"))
|
|
|
|
glob = NULL;
|
2010-02-04 12:02:45 -08:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
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++)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
|
|
|
|
{
|
|
|
|
/* if the entry matches the input glob
|
|
|
|
* check for * explicitly, because on some systems, * isn't well
|
|
|
|
* supported
|
|
|
|
*/
|
|
|
|
if ((!glob) || !fnmatch(glob, efn->name, 0))
|
|
|
|
{
|
|
|
|
/* add it to our list */
|
|
|
|
list_count++;
|
|
|
|
|
|
|
|
/* only realloc in 32 entry chunks */
|
|
|
|
if (list_count > list_count_alloc)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
char **new_list = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
list_count_alloc += 64;
|
|
|
|
new_list =
|
|
|
|
realloc(list_ret, list_count_alloc * (sizeof(char *)));
|
|
|
|
if (!new_list)
|
|
|
|
{
|
|
|
|
free(list_ret);
|
|
|
|
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
list_ret = new_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* put pointer of name string in */
|
|
|
|
list_ret[list_count - 1] = efn->name;
|
|
|
|
}
|
|
|
|
}
|
2002-12-02 15:39:26 -08:00
|
|
|
}
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
/* return count and list */
|
2006-06-13 03:20:22 -07:00
|
|
|
if (count_ret)
|
2010-07-27 18:45:57 -07:00
|
|
|
*count_ret = list_count;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2002-12-02 15:39:26 -08:00
|
|
|
return list_ret;
|
2009-12-03 07:35:04 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
on_error:
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
|
|
|
|
if (count_ret)
|
2010-07-27 18:45:57 -07:00
|
|
|
*count_ret = 0;
|
2009-12-03 07:35:04 -08:00
|
|
|
|
|
|
|
return NULL;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_list */
|
2004-01-17 06:58:50 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-07-31 11:54:54 -07:00
|
|
|
eet_num_entries(Eet_File *ef)
|
2005-07-15 13:37:29 -07:00
|
|
|
{
|
|
|
|
int i, num, ret = 0;
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
2005-07-15 13:37:29 -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) ||
|
2005-07-15 13:37:29 -07:00
|
|
|
((ef->mode != EET_FILE_MODE_READ) &&
|
|
|
|
(ef->mode != EET_FILE_MODE_READ_WRITE)))
|
2010-07-27 18:45:57 -07:00
|
|
|
return -1;
|
2005-07-15 13:37:29 -07:00
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
LOCK_FILE(ef);
|
|
|
|
|
2005-07-15 13:37:29 -07:00
|
|
|
/* loop through all entries */
|
|
|
|
num = (1 << ef->header->directory->size);
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
|
|
|
|
ret++;
|
2005-07-15 13:37:29 -07:00
|
|
|
}
|
|
|
|
|
2009-12-03 07:35:04 -08:00
|
|
|
UNLOCK_FILE(ef);
|
|
|
|
|
2005-07-15 13:37:29 -07:00
|
|
|
return ret;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* eet_num_entries */
|
2005-11-29 10:49:30 -08:00
|
|
|
|
|
|
|
static Eet_File_Node *
|
2010-07-31 11:57:35 -07:00
|
|
|
find_node_by_name(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
const char *name)
|
2005-11-29 10:49:30 -08:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn;
|
2005-11-29 10:49:30 -08:00
|
|
|
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
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (eet_string_match(efn->name, name))
|
|
|
|
return efn;
|
2006-06-13 03:20:22 -07:00
|
|
|
}
|
2005-11-29 10:49:30 -08:00
|
|
|
|
|
|
|
return NULL;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* find_node_by_name */
|
2005-11-29 10:49:30 -08:00
|
|
|
|
|
|
|
static int
|
2010-07-31 11:57:35 -07:00
|
|
|
read_data_from_disk(Eet_File *ef,
|
2010-07-31 11:54:54 -07:00
|
|
|
Eet_File_Node *efn,
|
2010-07-31 11:57:35 -07:00
|
|
|
void *buf,
|
2010-07-31 11:54:54 -07:00
|
|
|
int len)
|
2005-11-29 10:49:30 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (efn->offset < 0)
|
|
|
|
return 0;
|
2008-05-16 07:03:11 -07:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
if (ef->data)
|
2006-10-16 08:02:11 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if ((efn->offset + len) > ef->data_size)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
memcpy(buf, ef->data + efn->offset, len);
|
2006-10-16 08:02:11 -07:00
|
|
|
}
|
2006-06-13 03:20:22 -07:00
|
|
|
else
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!ef->readfp)
|
|
|
|
return 0;
|
2010-04-09 06:45:25 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
/* seek to data location */
|
|
|
|
if (fseek(ef->readfp, efn->offset, SEEK_SET) < 0)
|
|
|
|
return 0;
|
2008-01-24 00:41:23 -08:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
/* read it */
|
|
|
|
len = fread(buf, len, 1, ef->readfp);
|
2006-06-13 03:20:22 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2006-06-13 03:20:22 -07:00
|
|
|
return len;
|
2010-07-30 18:54:48 -07:00
|
|
|
} /* read_data_from_disk */
|
|
|
|
|