svn update: 60246 (latest:60246)
[framework/uifw/eet.git] / src / lib / eet_lib.c
index 4c694e5..7b04ff4 100644 (file)
@@ -34,9 +34,9 @@ void *    alloca (size_t);
 #include <fcntl.h>
 #include <zlib.h>
 
-#ifndef _MSC_VER
+#ifdef HAVE_UNISTD_H
 # include <unistd.h>
-#endif /* ifndef _MSC_VER */
+#endif /* ifdef HAVE_UNISTD_H */
 
 #ifdef HAVE_NETINET_IN_H
 # include <netinet/in.h>
@@ -46,6 +46,8 @@ void *    alloca (size_t);
 # include <Evil.h>
 #endif /* ifdef HAVE_EVIL */
 
+#include <Eina.h>
+
 #ifdef HAVE_GNUTLS
 # include <gnutls/gnutls.h>
 # include <gcrypt.h>
@@ -56,14 +58,11 @@ void *    alloca (size_t);
 # include <openssl/evp.h>
 #endif /* ifdef HAVE_OPENSSL */
 
-#ifdef EFL_HAVE_POSIX_THREADS
-# include <pthread.h>
+#ifdef EINA_HAVE_THREADS
 # ifdef HAVE_GNUTLS
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
 # endif /* ifdef HAVE_GNUTLS */
-#endif /* ifdef EFL_HAVE_POSIX_THREADS */
-
-#include <Eina.h>
+#endif /* ifdef EINA_HAVE_THREADS */
 
 #include "Eet.h"
 #include "Eet_private.h"
@@ -87,7 +86,7 @@ typedef struct _Eet_File_Directory   Eet_File_Directory;
 struct _Eet_File
 {
    char                *path;
-   FILE                *readfp;
+   Eina_File           *readfp;
    Eet_File_Header     *header;
    Eet_Dictionary      *ed;
    Eet_Key             *key;
@@ -101,20 +100,12 @@ struct _Eet_File
    int                  magic;
    int                  references;
 
-   int                  data_size;
+   unsigned long int    data_size;
    int                  x509_length;
    unsigned int         signature_length;
    int                  sha1_length;
 
-   time_t               mtime;
-
-#ifdef EFL_HAVE_THREADS
-# ifdef EFL_HAVE_POSIX_THREADS
-   pthread_mutex_t      file_lock;
-# else /* ifdef EFL_HAVE_POSIX_THREADS */
-   HANDLE               file_lock;
-# endif /* ifdef EFL_HAVE_POSIX_THREADS */
-#endif /* ifdef EFL_HAVE_THREADS */
+   Eina_Lock            file_lock;
 
    unsigned char        writes_pending : 1;
    unsigned char        delete_me_now : 1;
@@ -138,13 +129,13 @@ struct _Eet_File_Node
    void          *data;
    Eet_File_Node *next;  /* FIXME: make buckets linked lists */
 
-   int            offset;
-   int            dictionary_offset;
-   int            name_offset;
+   unsigned long int   offset;
+   unsigned long int   dictionary_offset;
+   unsigned long int   name_offset;
 
-   int            name_size;
-   int            size;
-   int            data_size;
+   unsigned int   name_size;
+   unsigned int   size;
+   unsigned int   data_size;
 
    unsigned char  free_name : 1;
    unsigned char  compression : 1;
@@ -244,45 +235,15 @@ static int                read_data_from_disk(Eet_File      *ef,
 
 static Eet_Error          eet_internal_close(Eet_File *ef, Eina_Bool locked);
 
-#ifdef EFL_HAVE_THREADS
-
-# ifdef EFL_HAVE_POSIX_THREADS
-
-static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER;
-
-#  define LOCK_CACHE   pthread_mutex_lock(&eet_cache_lock)
-#  define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock)
-
-#  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)
-#  define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock)
-
-# else /* EFL_HAVE_WIN32_THREADS */
-
-static HANDLE eet_cache_lock = NULL;
-
-#  define LOCK_CACHE   WaitForSingleObject(eet_cache_lock, INFINITE)
-#  define UNLOCK_CACHE ReleaseMutex(eet_cache_lock)
-
-#  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)
-#  define DESTROY_FILE(File) CloseHandle(File->file_lock)
+static Eina_Lock          eet_cache_lock;
 
-# endif /* EFL_HAVE_WIN32_THREADS */
+#define LOCK_CACHE        eina_lock_take(&eet_cache_lock)
+#define UNLOCK_CACHE      eina_lock_release(&eet_cache_lock)
 
-#else /* ifdef EFL_HAVE_THREADS */
-
-# define LOCK_CACHE   do {} while (0)
-# define UNLOCK_CACHE do {} while (0)
-
-# define INIT_FILE(File)    do {} while (0)
-# define LOCK_FILE(File)    do {} while (0)
-# define UNLOCK_FILE(File)  do {} while (0)
-# define DESTROY_FILE(File) do {} while (0)
-
-#endif /* EFL_HAVE_THREADS */
+#define INIT_FILE(File)    eina_lock_new(&File->file_lock)
+#define LOCK_FILE(File)    eina_lock_take(&File->file_lock)
+#define UNLOCK_FILE(File)  eina_lock_release(&File->file_lock)
+#define DESTROY_FILE(File) eina_lock_free(&File->file_lock)
 
 /* cache. i don't expect this to ever be large, so arrays will do */
 static int eet_writers_num = 0;
@@ -717,6 +678,8 @@ eet_init(void)
         goto shutdown_eina;
      }
 
+   eina_lock_new(&eet_cache_lock);
+
    if (!eet_node_init())
      {
         EINA_LOG_ERR("Eet: Eet_Node mempool creation failed");
@@ -743,12 +706,12 @@ eet_init(void)
               "BIG FAT WARNING: I AM UNABLE TO REQUEST SECMEM, Cryptographic operation are at risk !");
      }
 
-# ifdef EFL_HAVE_POSIX_THREADS
+# ifdef EINA_HAVE_THREADS
    if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread))
       WRN(
          "YOU ARE USING PTHREADS, BUT I CANNOT INITIALIZE THREADSAFE GCRYPT OPERATIONS!");
 
-# endif /* ifdef EFL_HAVE_POSIX_THREADS */
+# endif /* ifdef EINA_HAVE_THREADS */
    if (gnutls_global_init())
       goto shutdown_eet;
 
@@ -762,7 +725,7 @@ eet_init(void)
 
 #ifdef HAVE_GNUTLS
 shutdown_eet:
-#endif   
+#endif
    eet_node_shutdown();
 unregister_log_domain:
    eina_log_domain_unregister(_eet_log_dom_global);
@@ -780,6 +743,9 @@ eet_shutdown(void)
 
    eet_clearcache();
    eet_node_shutdown();
+
+   eina_lock_free(&eet_cache_lock);
+
 #ifdef HAVE_GNUTLS
    gnutls_global_deinit();
 #endif /* ifdef HAVE_GNUTLS */
@@ -882,12 +848,12 @@ eet_internal_read2(Eet_File *ef)
    const int *data = (const int *)ef->data;
    const char *start = (const char *)ef->data;
    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;
+   unsigned long int bytes_directory_entries;
+   unsigned long int bytes_dictionary_entries;
+   unsigned long int signature_base_offset;
+   unsigned long int num_directory_entries;
+   unsigned long int num_dictionary_entries;
+   unsigned int i;
 
    idx += sizeof(int);
    if (eet_test_close((int)ntohl(*data) != EET_MAGIC_FILE2, ef))
@@ -948,8 +914,8 @@ eet_internal_read2(Eet_File *ef)
      {
         const char *name;
         Eet_File_Node *efn;
-        int name_offset;
-        int name_size;
+        unsigned long int name_offset;
+        unsigned long int name_size;
         int hash;
         int flag;
 
@@ -1054,8 +1020,8 @@ eet_internal_read2(Eet_File *ef)
 
         for (j = 0; j < ef->ed->count; ++j)
           {
+             unsigned int offset;
              int hash;
-             int offset;
 
              GET_INT(hash,                dico, idx);
              GET_INT(offset,              dico, idx);
@@ -1136,10 +1102,10 @@ eet_internal_read1(Eet_File *ef)
 {
    const unsigned char *dyn_buf = NULL;
    const unsigned char *p = NULL;
+   unsigned long int byte_entries;
+   unsigned long int num_entries;
+   unsigned int i;
    int idx = 0;
-   int num_entries;
-   int byte_entries;
-   int i;
 
    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.",
@@ -1366,7 +1332,13 @@ eet_internal_close(Eet_File *ef,
    ef->references--;
    /* if its still referenced - dont go any further */
    if (ef->references > 0)
-      goto on_error;  /* flush any writes */
+     {
+        /* flush any writes */
+        if ((ef->mode == EET_FILE_MODE_WRITE) ||
+            (ef->mode == EET_FILE_MODE_READ_WRITE))
+          eet_sync(ef);
+        goto on_error;
+     }
 
    err = eet_flush2(ef);
 
@@ -1381,10 +1353,7 @@ eet_internal_close(Eet_File *ef,
    if (ef->mode == EET_FILE_MODE_READ)
       eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
    else if ((ef->mode == EET_FILE_MODE_WRITE) ||
-            (
-               ef
-               ->
-               mode == EET_FILE_MODE_READ_WRITE))
+            (ef->mode == EET_FILE_MODE_READ_WRITE))
       eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
 
    /* we can unlock the cache now */
@@ -1432,13 +1401,15 @@ eet_internal_close(Eet_File *ef,
    eet_dictionary_free(ef->ed);
 
    if (ef->sha1)
-      free(ef->sha1);
-
-   if (ef->data)
-      munmap((void *)ef->data, ef->data_size);
+     free(ef->sha1);
 
    if (ef->readfp)
-      fclose(ef->readfp);
+     {
+        if (ef->data)
+          eina_file_map_free(ef->readfp, (void *) ef->data);
+
+        eina_file_close(ef->readfp);
+     }
 
    /* zero out ram for struct - caution tactic against stale memory use */
    memset(ef, 0, sizeof(Eet_File));
@@ -1475,7 +1446,6 @@ eet_memopen_read(const void *data,
    ef->references = 1;
    ef->mode = EET_FILE_MODE_READ;
    ef->header = NULL;
-   ef->mtime = 0;
    ef->delete_me_now = 1;
    ef->readfp = NULL;
    ef->data = data;
@@ -1494,10 +1464,10 @@ EAPI Eet_File *
 eet_open(const char   *file,
          Eet_File_Mode mode)
 {
-   FILE *fp;
+   Eina_File *fp;
    Eet_File *ef;
    int file_len;
-   struct stat file_stat;
+   unsigned long int size;
 
    if (!file)
       return NULL;
@@ -1536,28 +1506,18 @@ eet_open(const char   *file,
    if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
      {
         /* Prevent garbage in futur comparison. */
-        file_stat.st_mtime = 0;
-
-        fp = fopen(file, "rb");
+        fp = eina_file_open(file, EINA_FALSE);
         if (!fp)
            goto open_error;
 
-        if (fstat(fileno(fp), &file_stat))
-          {
-             fclose(fp);
-             fp = NULL;
-
-             memset(&file_stat, 0, sizeof(file_stat));
+        size = eina_file_size_get(fp);
 
-             goto open_error;
-          }
-
-        if (file_stat.st_size < ((int)sizeof(int) * 3))
+        if (size < ((int)sizeof(int) * 3))
           {
-             fclose(fp);
+             eina_file_close(fp);
              fp = NULL;
 
-             memset(&file_stat, 0, sizeof(file_stat));
+             size = 0;
 
              goto open_error;
           }
@@ -1571,15 +1531,13 @@ open_error:
         if (mode != EET_FILE_MODE_WRITE)
            return NULL;
 
-        memset(&file_stat, 0, sizeof(file_stat));
+        size = 0;
 
         fp = NULL;
      }
 
    /* We found one */
-   if (ef &&
-       ((file_stat.st_mtime != ef->mtime) ||
-        (file_stat.st_size != ef->data_size)))
+   if (ef && ef->readfp != fp)
      {
         ef->delete_me_now = 1;
         ef->references++;
@@ -1591,7 +1549,7 @@ open_error:
      {
         /* reference it up and return it */
         if (fp)
-           fclose(fp);
+          eina_file_close(fp);
 
         ef->references++;
         UNLOCK_CACHE;
@@ -1615,7 +1573,6 @@ open_error:
    ef->references = 1;
    ef->mode = mode;
    ef->header = NULL;
-   ef->mtime = file_stat.st_mtime;
    ef->writes_pending = 0;
    ef->delete_me_now = 0;
    ef->data = NULL;
@@ -1635,14 +1592,12 @@ open_error:
    if (eet_test_close(!ef->readfp, ef))
       goto on_error;
 
-   fcntl(fileno(ef->readfp), F_SETFD, FD_CLOEXEC);
    /* if we opened for read or read-write */
    if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
      {
-        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))
+        ef->data_size = size;
+        ef->data = eina_file_map_all(fp, EINA_FILE_SEQUENTIAL);
+        if (eet_test_close((ef->data == NULL), ef))
            goto on_error;
 
         ef = eet_internal_read(ef);
@@ -1655,11 +1610,10 @@ empty_file:
    if (ef->references == 1)
      {
         if (ef->mode == EET_FILE_MODE_READ)
-           eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
-        else
-        if ((ef->mode == EET_FILE_MODE_WRITE) ||
-            (ef->mode == EET_FILE_MODE_READ_WRITE))
-           eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
+          eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
+        else if ((ef->mode == EET_FILE_MODE_WRITE) ||
+                 (ef->mode == EET_FILE_MODE_READ_WRITE))
+          eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
      }
 
    UNLOCK_CACHE;
@@ -1755,7 +1709,7 @@ eet_read_cipher(Eet_File   *ef,
 {
    Eet_File_Node *efn;
    char *data = NULL;
-   int size = 0;
+   unsigned long int size = 0;
 
    if (size_ret)
       *size_ret = 0;
@@ -1960,7 +1914,8 @@ eet_read_direct(Eet_File   *ef,
    if (!efn)
       goto on_error;
 
-   if (efn->offset < 0 && !efn->data)
+   /* trick to detect data in memory instead of mmaped from disk */
+   if (efn->offset > ef->data_size && !efn->data)
       goto on_error;
 
    /* get size (uncompressed, if compressed at all) */
@@ -2138,8 +2093,10 @@ eet_alias(Eet_File   *ef,
              efn->size = data_size;
              efn->data_size = strlen(destination) + 1;
              efn->data = data2;
-             efn->offset = -1;
+             /* Put the offset above the limit to avoid direct access */
+             efn->offset = ef->data_size + 1;
              exists_already = EINA_TRUE;
+
              break;
           }
      }
@@ -2158,7 +2115,8 @@ eet_alias(Eet_File   *ef,
 
         efn->next = ef->header->directory->nodes[hash];
         ef->header->directory->nodes[hash] = efn;
-        efn->offset = -1;
+        /* Put the offset above the limit to avoid direct access */
+        efn->offset = ef->data_size + 1;
         efn->alias = 1;
         efn->ciphered = 0;
         efn->compression = !!comp;
@@ -2320,7 +2278,8 @@ eet_write_cipher(Eet_File   *ef,
              efn->size = data_size;
              efn->data_size = size;
              efn->data = data2;
-             efn->offset = -1;
+             /* Put the offset above the limit to avoid direct access */
+             efn->offset = ef->data_size + 1;
              exists_already = 1;
              break;
           }
@@ -2340,7 +2299,8 @@ eet_write_cipher(Eet_File   *ef,
 
         efn->next = ef->header->directory->nodes[hash];
         ef->header->directory->nodes[hash] = efn;
-        efn->offset = -1;
+        /* Put the offset above the limit to avoid direct access */
+        efn->offset = ef->data_size + 1;
         efn->alias = 0;
         efn->ciphered = cipher_key ? 1 : 0;
         efn->compression = !!comp;
@@ -2576,28 +2536,16 @@ read_data_from_disk(Eet_File      *ef,
                     void          *buf,
                     int            len)
 {
-   if (efn->offset < 0)
+   if (efn->offset > ef->data_size)
       return 0;
 
-   if (ef->data)
-     {
-        if ((efn->offset + len) > ef->data_size)
-           return 0;
-
-        memcpy(buf, ef->data + efn->offset, len);
-     }
-   else
-     {
-        if (!ef->readfp)
-           return 0;
+   if (!ef->data)
+     return 0;
 
-        /* seek to data location */
-        if (fseek(ef->readfp, efn->offset, SEEK_SET) < 0)
-           return 0;
+   if ((efn->offset + len) > ef->data_size)
+     return 0;
 
-        /* read it */
-        len = fread(buf, len, 1, ef->readfp);
-     }
+   memcpy(buf, ef->data + efn->offset, len);
 
    return len;
 } /* read_data_from_disk */