summaryrefslogtreecommitdiff
path: root/legacy/eet
diff options
context:
space:
mode:
authorCarsten Haitzler <raster@rasterman.com>2006-06-13 10:20:22 +0000
committerCarsten Haitzler <raster@rasterman.com>2006-06-13 10:20:22 +0000
commit3a85bfb709d16f65d5445c5d83e2ea67cbdbbf83 (patch)
tree6aae25bc8fa080cf4fc47d6c65378ec5f613b3dc /legacy/eet
parent28dff2e36e77797ec2d28ff69855a2355bf97d3a (diff)
cedric's mmap patch
SVN revision: 23413
Diffstat (limited to 'legacy/eet')
-rw-r--r--legacy/eet/AUTHORS1
-rw-r--r--legacy/eet/src/lib/Eet.h35
-rw-r--r--legacy/eet/src/lib/Eet_private.h36
-rw-r--r--legacy/eet/src/lib/eet_data.c53
-rw-r--r--legacy/eet/src/lib/eet_image.c37
-rw-r--r--legacy/eet/src/lib/eet_lib.c932
6 files changed, 614 insertions, 480 deletions
diff --git a/legacy/eet/AUTHORS b/legacy/eet/AUTHORS
index 54496f5a12..c491082982 100644
--- a/legacy/eet/AUTHORS
+++ b/legacy/eet/AUTHORS
@@ -1,2 +1,3 @@
1The Rasterman (Carsten Haitzler) <raster@rasterman.com> 1The Rasterman (Carsten Haitzler) <raster@rasterman.com>
2David Goodlad <dgoodlad@gmail.com> 2David Goodlad <dgoodlad@gmail.com>
3Cedric Bail <cedric.bail@free.fr>
diff --git a/legacy/eet/src/lib/Eet.h b/legacy/eet/src/lib/Eet.h
index a82bf1d117..8d8bc0af41 100644
--- a/legacy/eet/src/lib/Eet.h
+++ b/legacy/eet/src/lib/Eet.h
@@ -126,18 +126,13 @@ extern "C" {
126 EAPI int eet_shutdown(void); 126 EAPI int eet_shutdown(void);
127 127
128 /** 128 /**
129 * Turn cacheburst on/off 129 * Clear eet cache
130 * 130 *
131 * @param on Set this to 1 to turn on, 0 to turn off. 131 * Eet didn't free items by default. If you are under memory presure, just
132 * 132 * call this function to recall all memory that are not yet referenced anymore.
133 * This enables cacheburst mode. This is where eet will not free items from 133 * The cache take care of modification on disk.
134 * its internal share cache even when their references hit 0. This is
135 * intended to be enabled during bursts where eet may open several eet
136 * files over and over and over again (eg in initialization of an app) and
137 * thius this will avoid repeated openings. It will NOT respect changes
138 * on disk and if you open a LOT of files may use a lot of memory.
139 */ 134 */
140 EAPI void eet_cacheburst(int on); 135 EAPI void eet_clearcache(void);
141 136
142 /** 137 /**
143 * Open an eet file on disk, and returns a handle to it. 138 * Open an eet file on disk, and returns a handle to it.
@@ -236,6 +231,26 @@ extern "C" {
236 EAPI void *eet_read(Eet_File *ef, const char *name, int *size_ret); 231 EAPI void *eet_read(Eet_File *ef, const char *name, int *size_ret);
237 232
238 /** 233 /**
234
235 * Read a specified entry from an eet file and return data
236 * @param ef A valid eet file handle opened for reading.
237 * @param name Name of the entry. eg: "/base/file_i_want".
238 * @param size_ret Number of bytes read from entry and returned.
239 * @return The data stored in that entry in the eet file.
240 *
241 * This function finds an entry in the eet file that is stored under the
242 * name specified, and returns that data if not compressed and successful.
243 * NULL is returned if the lookup fails or if memory errors are
244 * encountered or if the data is comrpessed. The calling program must never
245 * call free() on the returned data. The number of bytes in the returned
246 * data chunk are placed in size_ret.
247 *
248 * If the eet file handle is not valid NULL is returned and size_ret is
249 * filled with 0.
250 */
251 EAPI void *eet_read_direct (Eet_File *ef, const char *name, int *size_ret);
252
253 /**
239 * Write a specified entry to an eet file handle 254 * Write a specified entry to an eet file handle
240 * @param ef A valid eet file handle opened for writing. 255 * @param ef A valid eet file handle opened for writing.
241 * @param name Name of the entry. eg: "/base/file_i_want". 256 * @param name Name of the entry. eg: "/base/file_i_want".
diff --git a/legacy/eet/src/lib/Eet_private.h b/legacy/eet/src/lib/Eet_private.h
index df6eeb0c70..48f244b006 100644
--- a/legacy/eet/src/lib/Eet_private.h
+++ b/legacy/eet/src/lib/Eet_private.h
@@ -46,4 +46,40 @@ void _eet_memfile_shutdown();
46#define PATH_MAX 4096 46#define PATH_MAX 4096
47#endif 47#endif
48 48
49/* caluclate hash table entry valu with bitmask size of hash_size */
50static int
51eet_hash_gen(const char *key, int hash_size)
52{
53 int hash_num = 0;
54 int value, i;
55 unsigned char *ptr;
56
57 const int masks[9] =
58 {
59 0x00,
60 0x01,
61 0x03,
62 0x07,
63 0x0f,
64 0x1f,
65 0x3f,
66 0x7f,
67 0xff
68 };
69
70 /* no string - index 0 */
71 if (!key) return 0;
72
73 /* calc hash num */
74 for (i = 0, ptr = (unsigned char *)key, value = (int)(*ptr);
75 value;
76 ptr++, i++, value = (int)(*ptr))
77 hash_num ^= (value | (value << 8)) >> (i & 0x7);
78
79 /* mask it */
80 hash_num &= masks[hash_size];
81 /* return it */
82 return hash_num;
83}
84
49#endif 85#endif
diff --git a/legacy/eet/src/lib/eet_data.c b/legacy/eet/src/lib/eet_data.c
index fc4ff974ae..023fd8d720 100644
--- a/legacy/eet/src/lib/eet_data.c
+++ b/legacy/eet/src/lib/eet_data.c
@@ -567,7 +567,7 @@ eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
567{ 567{
568 int *size; 568 int *size;
569 int s; 569 int s;
570 int size_ret; 570 int size_ret = 0;
571 571
572 if (!chnk->data) return; 572 if (!chnk->data) return;
573 /* chunk head */ 573 /* chunk head */
@@ -588,37 +588,6 @@ eet_data_chunk_put(Eet_Data_Chunk *chnk, Eet_Data_Stream *ds)
588 588
589/*---*/ 589/*---*/
590 590
591static int
592_eet_descriptor_hash_gen(char *key, int hash_size)
593{
594 int hash_num = 0, i;
595 unsigned char *ptr;
596 const int masks[9] =
597 {
598 0x00,
599 0x01,
600 0x03,
601 0x07,
602 0x0f,
603 0x1f,
604 0x3f,
605 0x7f,
606 0xff
607 };
608
609 /* no string - index 0 */
610 if (!key) return 0;
611
612 /* calc hash num */
613 for (i = 0, ptr = (unsigned char *)key; *ptr; ptr++, i++)
614 hash_num ^= ((int)(*ptr) | ((int)(*ptr) << 8)) >> (i % 8);
615
616 /* mask it */
617 hash_num &= masks[hash_size];
618 /* return it */
619 return hash_num;
620}
621
622static void 591static void
623_eet_descriptor_hash_new(Eet_Data_Descriptor *edd) 592_eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
624{ 593{
@@ -632,7 +601,7 @@ _eet_descriptor_hash_new(Eet_Data_Descriptor *edd)
632 int hash; 601 int hash;
633 602
634 ede = &(edd->elements.set[i]); 603 ede = &(edd->elements.set[i]);
635 hash = _eet_descriptor_hash_gen((char *) ede->name, 6); 604 hash = eet_hash_gen((char *) ede->name, 6);
636 if (!edd->elements.hash.buckets[hash].element) 605 if (!edd->elements.hash.buckets[hash].element)
637 edd->elements.hash.buckets[hash].element = ede; 606 edd->elements.hash.buckets[hash].element = ede;
638 else 607 else
@@ -673,7 +642,7 @@ _eet_descriptor_hash_find(Eet_Data_Descriptor *edd, char *name)
673 int hash; 642 int hash;
674 Eet_Data_Descriptor_Hash *bucket; 643 Eet_Data_Descriptor_Hash *bucket;
675 644
676 hash = _eet_descriptor_hash_gen(name, 6); 645 hash = eet_hash_gen(name, 6);
677 if (!edd->elements.hash.buckets[hash].element) return NULL; 646 if (!edd->elements.hash.buckets[hash].element) return NULL;
678 if (!strcmp(edd->elements.hash.buckets[hash].element->name, name)) 647 if (!strcmp(edd->elements.hash.buckets[hash].element->name, name))
679 return edd->elements.hash.buckets[hash].element; 648 return edd->elements.hash.buckets[hash].element;
@@ -858,12 +827,20 @@ eet_data_read(Eet_File *ef, Eet_Data_Descriptor *edd, char *name)
858{ 827{
859 void *data_dec; 828 void *data_dec;
860 void *data; 829 void *data;
861 int size; 830 int size;
831 int required_free = 0;
862 832
863 data = eet_read(ef, name, &size); 833 data = eet_read_direct (ef, name, &size);
864 if (!data) return NULL; 834 if (!data)
835 {
836 required_free = 1;
837 data = eet_read(ef, name, &size);
838 if (!data) return NULL;
839 }
865 data_dec = eet_data_descriptor_decode(edd, data, size); 840 data_dec = eet_data_descriptor_decode(edd, data, size);
866 free(data); 841 if (required_free)
842 free(data);
843
867 return data_dec; 844 return data_dec;
868} 845}
869 846
diff --git a/legacy/eet/src/lib/eet_image.c b/legacy/eet/src/lib/eet_image.c
index b4fac013f8..e8d678dbdf 100644
--- a/legacy/eet/src/lib/eet_image.c
+++ b/legacy/eet/src/lib/eet_image.c
@@ -716,14 +716,24 @@ eet_data_image_read(Eet_File *ef, const char *name,
716 unsigned int *w, unsigned int *h, int *alpha, 716 unsigned int *w, unsigned int *h, int *alpha,
717 int *compress, int *quality, int *lossy) 717 int *compress, int *quality, int *lossy)
718{ 718{
719 void *data; 719 void *data;
720 int size; 720 int size;
721 unsigned int *d = NULL; 721 unsigned int *d = NULL;
722 int free_data = 0;
723
724 data = eet_read_direct (ef, name, &size);
725 if (!data)
726 {
727 data = eet_read(ef, name, &size);
728 free_data = 1;
729 }
722 730
723 data = eet_read(ef, name, &size);
724 if (!data) return NULL; 731 if (!data) return NULL;
725 d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy); 732 d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy);
726 free(data); 733
734 if (free_data)
735 free(data);
736
727 return d; 737 return d;
728} 738}
729 739
@@ -732,14 +742,23 @@ eet_data_image_header_read(Eet_File *ef, const char *name,
732 unsigned int *w, unsigned int *h, int *alpha, 742 unsigned int *w, unsigned int *h, int *alpha,
733 int *compress, int *quality, int *lossy) 743 int *compress, int *quality, int *lossy)
734{ 744{
735 void *data; 745 void *data = NULL;
736 int size; 746 int size = 0;
737 int d; 747 int d;
748 int free_data = 0;
749
750 data = eet_read_direct (ef, name, &size);
751 if (!data)
752 {
753 data = eet_read(ef, name, &size);
754 free_data = 1;
755 }
738 756
739 data = eet_read(ef, name, &size);
740 if (!data) return 0; 757 if (!data) return 0;
741 d = eet_data_image_header_decode(data, size, w, h, alpha, compress, quality, lossy); 758 d = eet_data_image_header_decode(data, size, w, h, alpha, compress, quality, lossy);
742 free(data); 759 if (free_data)
760 free(data);
761
743 return d; 762 return d;
744} 763}
745 764
diff --git a/legacy/eet/src/lib/eet_lib.c b/legacy/eet/src/lib/eet_lib.c
index 978a693cc2..75862c8ac8 100644
--- a/legacy/eet/src/lib/eet_lib.c
+++ b/legacy/eet/src/lib/eet_lib.c
@@ -2,6 +2,8 @@
2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
3 */ 3 */
4 4
5#include <sys/mman.h>
6
5#include "Eet.h" 7#include "Eet.h"
6#include "Eet_private.h" 8#include "Eet_private.h"
7 9
@@ -30,6 +32,10 @@ struct _Eet_File
30 unsigned char delete_me_now : 1; 32 unsigned char delete_me_now : 1;
31 33
32 Eet_File_Header *header; 34 Eet_File_Header *header;
35
36 uint8_t *data;
37 int data_size;
38 time_t mtime;
33}; 39};
34 40
35struct _Eet_File_Header 41struct _Eet_File_Header
@@ -46,11 +52,14 @@ struct _Eet_File_Directory
46 52
47struct _Eet_File_Node 53struct _Eet_File_Node
48{ 54{
49 char *name; 55 unsigned char free_name : 1;
56 unsigned char compression : 1;
57
50 int offset; 58 int offset;
51 int compression;
52 int size; 59 int size;
53 int data_size; 60 int data_size;
61
62 char *name;
54 void *data; 63 void *data;
55 Eet_File_Node *next; /* FIXME: make buckets linked lists */ 64 Eet_File_Node *next; /* FIXME: make buckets linked lists */
56}; 65};
@@ -74,14 +83,13 @@ struct
74#endif 83#endif
75 84
76/* prototypes of internal calls */ 85/* prototypes of internal calls */
77static Eet_File *eet_cache_find(const char *path, Eet_File **cache, int cache_num); 86static Eet_File *eet_cache_find(const char *path, Eet_File **cache, int cache_num);
78static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc); 87static void eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
79static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc); 88static void eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc);
80static int eet_string_match(const char *s1, const char *s2); 89static int eet_string_match(const char *s1, const char *s2);
81static int eet_hash_gen(const char *key, int hash_size); 90static Eet_Error eet_flush(Eet_File *ef);
82static Eet_Error eet_flush(Eet_File *ef); 91static Eet_File_Node *find_node_by_name(Eet_File *ef, const char *name);
83static Eet_File_Node *find_node_by_name (Eet_File *ef, const char *name); 92static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
84static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len);
85 93
86/* cache. i don't expect this to ever be large, so arrays will do */ 94/* cache. i don't expect this to ever be large, so arrays will do */
87static int eet_writers_num = 0; 95static int eet_writers_num = 0;
@@ -91,7 +99,36 @@ static int eet_readers_num = 0;
91static int eet_readers_alloc = 0; 99static int eet_readers_alloc = 0;
92static Eet_File **eet_readers = NULL; 100static Eet_File **eet_readers = NULL;
93static int eet_initcount = 0; 101static int eet_initcount = 0;
94static int eet_cacheburst_mode = 0; 102
103/* Check to see its' an eet file pointer */
104static inline int
105eet_check_pointer(const Eet_File *ef)
106{
107 if ((!ef) || (ef->magic != EET_MAGIC_FILE))
108 return 1;
109 return 0;
110}
111
112static inline int
113eet_check_header(const Eet_File *ef)
114{
115 if (!ef->header)
116 return 1;
117 if (!ef->header->directory)
118 return 1;
119 return 0;
120}
121
122static inline int
123eet_test_close(int test, Eet_File *ef)
124{
125 if (test)
126 {
127 ef->delete_me_now = 1;
128 eet_close(ef);
129 }
130 return test;
131}
95 132
96/* find an eet file in the currently in use cache */ 133/* find an eet file in the currently in use cache */
97static Eet_File * 134static Eet_File *
@@ -105,9 +142,11 @@ eet_cache_find(const char *path, Eet_File **cache, int cache_num)
105 /* if matches real path - return it */ 142 /* if matches real path - return it */
106 if (eet_string_match(cache[i]->path, path)) 143 if (eet_string_match(cache[i]->path, path))
107 { 144 {
108 if (!cache[i]->delete_me_now) return cache[i]; 145 if (!cache[i]->delete_me_now)
146 return cache[i];
109 } 147 }
110 } 148 }
149
111 /* not found */ 150 /* not found */
112 return NULL; 151 return NULL;
113} 152}
@@ -116,14 +155,15 @@ eet_cache_find(const char *path, Eet_File **cache, int cache_num)
116static void 155static void
117eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc) 156eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
118{ 157{
119 Eet_File **new_cache; 158 Eet_File **new_cache;
120 int new_cache_num, new_cache_alloc; 159 int new_cache_num;
160 int new_cache_alloc;
121 161
122 new_cache_num = *cache_num; 162 new_cache_num = *cache_num;
123 if (new_cache_num > 128) /* avoid fd overruns - limit to 128 (most recent) in the cache */ 163 if (new_cache_num > 128) /* avoid fd overruns - limit to 128 (most recent) in the cache */
124 { 164 {
125 Eet_File *del_ef = NULL; 165 Eet_File *del_ef = NULL;
126 int i; 166 int i;
127 167
128 new_cache = *cache; 168 new_cache = *cache;
129 for (i = 0; i < new_cache_num; i++) 169 for (i = 0; i < new_cache_num; i++)
@@ -134,13 +174,14 @@ eet_cache_add(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
134 break; 174 break;
135 } 175 }
136 } 176 }
177
137 if (del_ef) 178 if (del_ef)
138 { 179 {
139 eet_cacheburst_mode = 0; 180 del_ef->delete_me_now = 1;
140 eet_close(del_ef); 181 eet_close(del_ef);
141 eet_cacheburst_mode = 1;
142 } 182 }
143 } 183 }
184
144 new_cache = *cache; 185 new_cache = *cache;
145 new_cache_num = *cache_num; 186 new_cache_num = *cache_num;
146 new_cache_alloc = *cache_alloc; 187 new_cache_alloc = *cache_alloc;
@@ -169,24 +210,25 @@ eet_cache_del(Eet_File *ef, Eet_File ***cache, int *cache_num, int *cache_alloc)
169 int new_cache_num, new_cache_alloc; 210 int new_cache_num, new_cache_alloc;
170 int i, j; 211 int i, j;
171 212
172 if (eet_cacheburst_mode) return;
173 new_cache = *cache; 213 new_cache = *cache;
174 new_cache_num = *cache_num; 214 new_cache_num = *cache_num;
175 new_cache_alloc = *cache_alloc; 215 new_cache_alloc = *cache_alloc;
176 if (new_cache_num <= 0) 216 if (new_cache_num <= 0)
177 { 217 return;
178 return; 218
179 }
180 for (i = 0; i < new_cache_num; i++) 219 for (i = 0; i < new_cache_num; i++)
181 { 220 {
182 if (new_cache[i] == ef) break; 221 if (new_cache[i] == ef)
222 break;
183 } 223 }
224
184 if (i >= new_cache_num) 225 if (i >= new_cache_num)
185 { 226 return;
186 return; 227
187 }
188 new_cache_num--; 228 new_cache_num--;
189 for (j = i; j < new_cache_num; j++) new_cache[j] = new_cache[j + 1]; 229 for (j = i; j < new_cache_num; j++)
230 new_cache[j] = new_cache[j + 1];
231
190 if (new_cache_num < (new_cache_alloc - 64)) 232 if (new_cache_num < (new_cache_alloc - 64))
191 { 233 {
192 new_cache_alloc -= 64; 234 new_cache_alloc -= 64;
@@ -220,58 +262,29 @@ eet_string_match(const char *s1, const char *s2)
220 return (!strcmp(s1, s2)); 262 return (!strcmp(s1, s2));
221} 263}
222 264
223/* caluclate hash table entry valu with bitmask size of hash_size */
224static int
225eet_hash_gen(const char *key, int hash_size)
226{
227 int hash_num = 0, i;
228 unsigned char *ptr;
229 const int masks[9] =
230 {
231 0x00,
232 0x01,
233 0x03,
234 0x07,
235 0x0f,
236 0x1f,
237 0x3f,
238 0x7f,
239 0xff
240 };
241
242 /* no string - index 0 */
243 if (!key) return 0;
244
245 /* calc hash num */
246 for (i = 0, ptr = (unsigned char *)key; *ptr; ptr++, i++)
247 hash_num ^= ((int)(*ptr) | ((int)(*ptr) << 8)) >> (i % 8);
248
249 /* mask it */
250 hash_num &= masks[hash_size];
251 /* return it */
252 return hash_num;
253}
254
255/* flush out writes to an eet file */ 265/* flush out writes to an eet file */
256static Eet_Error 266static Eet_Error
257eet_flush(Eet_File *ef) 267eet_flush(Eet_File *ef)
258{ 268{
259 int i, count, size, num, offset; 269 Eet_File_Node *efn;
260 int head[3]; 270 int head[3];
261 unsigned long int i1, i2; 271 int count = 0;
262 Eet_File_Node *efn; 272 int size = 0;
273 int offset = 0;
274 int i;
275 int num;
263 276
264 /* check to see its' an eet file pointer */ 277 /* check to see its' an eet file pointer */
265 if ((!ef) || (ef->magic != EET_MAGIC_FILE)) 278 if (eet_check_pointer(ef))
266 return EET_ERROR_BAD_OBJECT; 279 return EET_ERROR_BAD_OBJECT;
267 if (!ef->header) return EET_ERROR_EMPTY; 280 if (eet_check_header(ef))
268 if (!ef->header->directory) return EET_ERROR_EMPTY; 281 return EET_ERROR_EMPTY;
269 if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE)) return EET_ERROR_NOT_WRITABLE; 282 if ((ef->mode != EET_FILE_MODE_WRITE) && (ef->mode != EET_FILE_MODE_READ_WRITE))
270 if (!ef->writes_pending) return EET_ERROR_NONE; 283 return EET_ERROR_NOT_WRITABLE;
284 if (!ef->writes_pending)
285 return EET_ERROR_NONE;
271 286
272 /* calculate total size in bytes of directory block */ 287 /* calculate total size in bytes of directory block */
273 size = 0;
274 count = 0;
275 num = (1 << ef->header->directory->size); 288 num = (1 << ef->header->directory->size);
276 for (i = 0; i < num; i++) 289 for (i = 0; i < num; i++)
277 { 290 {
@@ -279,12 +292,13 @@ eet_flush(Eet_File *ef)
279 { 292 {
280 if (efn->compression >= 0) 293 if (efn->compression >= 0)
281 { 294 {
282 size += 20 + strlen(efn->name); 295 size += 20 + strlen(efn->name) + 1;
283 count++; 296 count++;
284 } 297 }
285 } 298 }
286 } 299 }
287 /* caluclate offsets per entry */ 300
301 /* calculate offsets per entry */
288 offset = 0; 302 offset = 0;
289 for (i = 0; i < num; i++) 303 for (i = 0; i < num; i++)
290 { 304 {
@@ -297,71 +311,42 @@ eet_flush(Eet_File *ef)
297 } 311 }
298 } 312 }
299 } 313 }
314
300 /* go thru and write the header */ 315 /* go thru and write the header */
301 i1 = (unsigned long int)EET_MAGIC_FILE; 316 head[0] = (int) htonl ((uint32_t) EET_MAGIC_FILE);
302 i2 = htonl(i1); 317 head[1] = (int) htonl ((uint32_t) count);
303 head[0] = (int)i2; 318 head[2] = (int) htonl ((uint32_t) size);
304 i1 = (unsigned long int)count; 319
305 i2 = htonl(i1);
306 head[1] = (int)i2;
307 i1 = (unsigned long int)size;
308 i2 = htonl(i1);
309 head[2] = (int)i2;
310 fseek(ef->fp, 0, SEEK_SET); 320 fseek(ef->fp, 0, SEEK_SET);
311 if (fwrite(head, 12, 1, ef->fp) != 1) goto write_error; 321 if (fwrite(head, 12, 1, ef->fp) != 1)
312 offset = 12; 322 goto write_error;
323
313 for (i = 0; i < num; i++) 324 for (i = 0; i < num; i++)
314 { 325 {
315 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) 326 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
316 { 327 {
317 if (efn->compression >= 0) 328 if (efn->compression >= 0)
318 { 329 {
319 unsigned char *buf; 330 uint32_t ibuf[5];
320 int buf_size; 331 int name_size;
321 int name_size; 332
322 333 name_size = strlen(efn->name) + 1;
323 name_size = strlen(efn->name); 334
324 buf_size = 20 + name_size; 335 ibuf[0] = (int) htonl ((uint32_t) efn->offset);
325 buf = alloca(buf_size); 336 ibuf[1] = (int) htonl ((uint32_t) efn->compression);
326 if (!buf) return EET_ERROR_OUT_OF_MEMORY; 337 ibuf[2] = (int) htonl ((uint32_t) efn->size);
327 i1 = (unsigned long int)efn->offset; 338 ibuf[3] = (int) htonl ((uint32_t) efn->data_size);
328 i2 = htonl(i1); 339 ibuf[4] = (int) htonl ((uint32_t) name_size);
329 *((int *)(buf + 0)) = (int)i2; 340
330 i1 = (unsigned long int)efn->compression; 341
331 i2 = htonl(i1); 342 if (fwrite(ibuf, sizeof(ibuf), 1, ef->fp) != 1)
332 *((int *)(buf + 4)) = (int)i2; 343 goto write_error;
333 i1 = (unsigned long int)efn->size; 344 if (fwrite(efn->name, name_size, 1, ef->fp) != 1)
334 i2 = htonl(i1); 345 goto write_error;
335 *((int *)(buf + 8)) = (int)i2;
336 i1 = (unsigned long int)efn->data_size;
337 i2 = htonl(i1);
338 *((int *)(buf + 12)) = (int)i2;
339 i1 = (unsigned long int)name_size;
340 i2 = htonl(i1);
341 *((int *)(buf + 16)) = (int)i2;
342 memcpy(buf + 20, efn->name, name_size);
343 if (fwrite(buf, buf_size, 1, ef->fp) != 1)
344 {
345 write_error:
346 switch (ferror(ef->fp))
347 {
348 case EFBIG:
349 return EET_ERROR_WRITE_ERROR_FILE_TOO_BIG;
350 case EIO:
351 return EET_ERROR_WRITE_ERROR_IO_ERROR;
352 case ENOSPC:
353 return EET_ERROR_WRITE_ERROR_OUT_OF_SPACE;
354 case EPIPE:
355 return EET_ERROR_WRITE_ERROR_FILE_CLOSED;
356 default:
357 return EET_ERROR_WRITE_ERROR;
358 }
359 return EET_ERROR_WRITE_ERROR;
360 }
361 offset += buf_size;
362 } 346 }
363 } 347 }
364 } 348 }
349
365 /* write data */ 350 /* write data */
366 for (i = 0; i < num; i++) 351 for (i = 0; i < num; i++)
367 { 352 {
@@ -374,9 +359,31 @@ eet_flush(Eet_File *ef)
374 } 359 }
375 } 360 }
376 } 361 }
362
377 /* no more writes pending */ 363 /* no more writes pending */
378 ef->writes_pending = 0; 364 ef->writes_pending = 0;
365 fclose(ef->fp);
366 ef->fp = NULL;
367
379 return EET_ERROR_NONE; 368 return EET_ERROR_NONE;
369
370write_error:
371 fclose(ef->fp);
372 ef->fp = NULL;
373 switch (ferror(ef->fp))
374 {
375 case EFBIG:
376 return EET_ERROR_WRITE_ERROR_FILE_TOO_BIG;
377 case EIO:
378 return EET_ERROR_WRITE_ERROR_IO_ERROR;
379 case ENOSPC:
380 return EET_ERROR_WRITE_ERROR_OUT_OF_SPACE;
381 case EPIPE:
382 return EET_ERROR_WRITE_ERROR_FILE_CLOSED;
383 default:
384 return EET_ERROR_WRITE_ERROR;
385 }
386 return EET_ERROR_WRITE_ERROR;
380} 387}
381 388
382EAPI int 389EAPI int
@@ -389,66 +396,71 @@ EAPI int
389eet_shutdown(void) 396eet_shutdown(void)
390{ 397{
391 if (--eet_initcount == 0) 398 if (--eet_initcount == 0)
392 { 399 _eet_memfile_shutdown();
393 eet_cacheburst(0);
394 _eet_memfile_shutdown();
395 }
396 400
397 return eet_initcount; 401 return eet_initcount;
398} 402}
399 403
400EAPI void 404EAPI void
401eet_cacheburst(int on) 405eet_clearcache(void)
402{ 406{
403 if (eet_cacheburst_mode == on) return; 407 int num = 0;
404 eet_cacheburst_mode = on; 408 int i;
405 if (!eet_cacheburst_mode) 409
410 /*
411 We need to compute the list of eet file to close separately from the cache,
412 due to eet_close removing them from the cache after each call.
413 */
414 for (i = 0; i < eet_writers_num; i++)
415 {
416 if (eet_writers[i]->references == 0)
417 num++;
418 }
419
420 for (i = 0; i < eet_readers_num; i++)
421 {
422 if (eet_readers[i]->references == 0)
423 num++;
424 }
425
426 if (num > 0)
406 { 427 {
407 int i; 428 Eet_File **closelist = NULL;
408 int num;
409 429
430 closelist = alloca(num * sizeof(Eet_File *));
410 num = 0; 431 num = 0;
411 for (i = 0; i < eet_writers_num; i++) 432 for (i = 0; i < eet_writers_num; i++)
412 { 433 {
413 if (eet_writers[i]->references == 0) num++; 434 if (eet_writers[i]->references == 0)
435 {
436 closelist[num] = eet_writers[i];
437 num++;
438 }
414 } 439 }
440
415 for (i = 0; i < eet_readers_num; i++) 441 for (i = 0; i < eet_readers_num; i++)
416 { 442 {
417 if (eet_readers[i]->references == 0) num++; 443 if (eet_readers[i]->references == 0)
418 }
419 if (num > 0)
420 {
421 Eet_File **closelist = NULL;
422
423 closelist = alloca(num * sizeof(Eet_File *));
424 num = 0;
425 for (i = 0; i < eet_writers_num; i++)
426 {
427 if (eet_writers[i]->references == 0)
428 {
429 closelist[num] = eet_writers[i];
430 num++;
431 }
432 }
433 for (i = 0; i < eet_readers_num; i++)
434 { 444 {
435 if (eet_readers[i]->references == 0) 445 closelist[num] = eet_readers[i];
436 { 446 num++;
437 closelist[num] = eet_readers[i];
438 num++;
439 }
440 } 447 }
441 for (i = 0; i < num; i++) eet_close(closelist[i]);
442 } 448 }
449
450 for (i = 0; i < num; i++)
451 eet_close(closelist[i]);
443 } 452 }
444} 453}
445 454
446EAPI Eet_File * 455EAPI Eet_File *
447eet_open(const char *file, Eet_File_Mode mode) 456eet_open(const char *file, Eet_File_Mode mode)
448{ 457{
449 Eet_File *ef; 458 Eet_File *ef;
459 struct stat file_stat;
460
461 if (!file)
462 return NULL;
450 463
451 if (!file) return NULL;
452 /* find the current file handle in cache*/ 464 /* find the current file handle in cache*/
453 ef = NULL; 465 ef = NULL;
454 if (mode == EET_FILE_MODE_READ) 466 if (mode == EET_FILE_MODE_READ)
@@ -458,16 +470,37 @@ eet_open(const char *file, Eet_File_Mode mode)
458 { 470 {
459 eet_flush(ef); 471 eet_flush(ef);
460 ef->delete_me_now = 1; 472 ef->delete_me_now = 1;
473 eet_close(ef);
461 } 474 }
462 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); 475 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
463 } 476 }
464 else if ((mode == EET_FILE_MODE_WRITE) || (mode == EET_FILE_MODE_READ_WRITE)) 477 else if ((mode == EET_FILE_MODE_WRITE) || (mode == EET_FILE_MODE_READ_WRITE))
465 { 478 {
466 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num); 479 ef = eet_cache_find((char *)file, eet_readers, eet_readers_num);
467 if (ef) ef->delete_me_now = 1; 480 if (ef)
481 {
482 ef->delete_me_now = 1;
483 eet_close(ef);
484 }
468 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num); 485 ef = eet_cache_find((char *)file, eet_writers, eet_writers_num);
469 } 486 }
470 /* we found one */ 487
488 if (stat(file, &file_stat))
489 {
490 if (mode == EET_FILE_MODE_WRITE)
491 memset(&file_stat, 0, sizeof(file_stat));
492 else
493 return NULL;
494 }
495
496 /* We found one */
497 if (ef && (file_stat.st_mtime != ef->mtime))
498 {
499 ef->delete_me_now = 1;
500 eet_close(ef);
501 ef = NULL;
502 }
503
471 if (ef) 504 if (ef)
472 { 505 {
473 /* reference it up and return it */ 506 /* reference it up and return it */
@@ -475,9 +508,10 @@ eet_open(const char *file, Eet_File_Mode mode)
475 return ef; 508 return ef;
476 } 509 }
477 510
478 /* allocate struct for eet file and have it zero'd out */ 511 /* Allocate struct for eet file and have it zero'd out */
479 ef = calloc(1, sizeof(Eet_File) + strlen(file) + 1); 512 ef = malloc(sizeof(Eet_File) + strlen(file) + 1);
480 if (!ef) return NULL; 513 if (!ef)
514 return NULL;
481 515
482 /* fill some of the members */ 516 /* fill some of the members */
483 ef->path = ((char *)ef) + sizeof(Eet_File); 517 ef->path = ((char *)ef) + sizeof(Eet_File);
@@ -485,199 +519,172 @@ eet_open(const char *file, Eet_File_Mode mode)
485 ef->magic = EET_MAGIC_FILE; 519 ef->magic = EET_MAGIC_FILE;
486 ef->references = 1; 520 ef->references = 1;
487 ef->mode = mode; 521 ef->mode = mode;
522 ef->header = NULL;
523 ef->mtime = file_stat.st_mtime;
524 ef->delete_me_now = 0;
488 525
489 /* try open the file based on mode */ 526 /* try open the file based on mode */
490 if ((ef->mode == EET_FILE_MODE_READ) || (ef->mode == EET_FILE_MODE_READ_WRITE)) 527 if ((ef->mode == EET_FILE_MODE_READ) || (ef->mode == EET_FILE_MODE_READ_WRITE))
491 ef->fp = fopen(ef->path, "rb"); 528 ef->fp = fopen(ef->path, "rb");
492 else if (ef->mode == EET_FILE_MODE_WRITE)
493 {
494 /* opening for write - delete old copy of file right away */
495 unlink(ef->path);
496 ef->fp = fopen(ef->path, "wb");
497 }
498 else 529 else
499 { 530 {
500 ef->delete_me_now = 1; 531 if (eet_test_close(ef->mode != EET_FILE_MODE_WRITE, ef))
501 eet_close(ef); 532 return NULL;
502 return NULL; 533 else
534 {
535 /* opening for write - delete old copy of file right away */
536 unlink(ef->path);
537 ef->fp = fopen(ef->path, "wb");
538 }
503 } 539 }
504 540
505 /* if we can't open - bail out */ 541 /* if we can't open - bail out */
506 if (!ef->fp) 542 if (eet_test_close(!ef->fp, ef))
507 { 543 return NULL;
508 ef->delete_me_now = 1; 544
509 eet_close(ef); 545 ef->data = NULL;
510 return NULL; 546 ef->data_size = 0;
511 }
512 547
513 /* if we opened for read or read-write */ 548 /* if we opened for read or read-write */
514// printf("OPEN!\n");
515 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE)) 549 if ((mode == EET_FILE_MODE_READ) || (mode == EET_FILE_MODE_READ_WRITE))
516 { 550 {
517 unsigned char buf[12]; 551 unsigned char *dyn_buf = NULL;
518 unsigned char *dyn_buf, *p; 552 unsigned char *p = NULL;
519 unsigned long int i1, i2; 553 int index = 0;
520 int num_entries, byte_entries, i; 554 int num_entries;
521 size_t count; 555 int byte_entries;
522 556 int i;
557
558 ef->data_size = file_stat.st_size;
559 ef->data = mmap(NULL, ef->data_size, PROT_READ, MAP_SHARED, fileno(ef->fp), 0);
560
561 if (eet_test_close(ef->data == (void*) -1 || ef->data == NULL, ef))
562 return NULL;
563
523 /* build header table if read mode */ 564 /* build header table if read mode */
524 /* geat header */ 565 /* geat header */
525 count = fread(buf, 12, 1, ef->fp); 566 index += sizeof (int);
526 if (count != 1) 567 if (eet_test_close((int) ntohl (*((int*) ef->data)) != EET_MAGIC_FILE, ef))
527 { 568 return NULL;
528 eet_close(ef); 569
529 return NULL; 570#define EXTRACT_INT(Value, Pointer, Index) \
530 } 571 Value = ntohl (*((int*)(Pointer + Index))); \
531 /* get magic no */ 572 Index += sizeof(int);
532 memcpy(&i1, buf + 0, sizeof(int)); 573
533 i2 = ntohl(i1);
534 if (i2 != EET_MAGIC_FILE)
535 {
536 eet_close(ef);
537 return NULL;
538 }
539 /* get entries count and byte count */ 574 /* get entries count and byte count */
540 memcpy(&i1, buf + 4, sizeof(int)); 575 EXTRACT_INT(num_entries, ef->data, index);
541 i2 = ntohl(i1); 576 EXTRACT_INT(byte_entries, ef->data, index);
542 num_entries = (int)i2; 577
543 memcpy(&i1, buf + 8, sizeof(int));
544 i2 = ntohl(i1);
545 byte_entries = (int)i2;
546 /* we cant have <= 0 values here - invalid */ 578 /* we cant have <= 0 values here - invalid */
547 if ((num_entries <= 0) || (byte_entries <= 0)) 579 if (eet_test_close((num_entries <= 0) || (byte_entries <= 0), ef))
548 { 580 return NULL;
549 ef->delete_me_now = 1; 581
550 eet_close(ef);
551 return NULL;
552 }
553 /* we can't have more entires than minimum bytes for those! invalid! */ 582 /* we can't have more entires than minimum bytes for those! invalid! */
554 if ((num_entries * 20) > byte_entries) 583 if (eet_test_close((num_entries * 20) > byte_entries, ef))
555 { 584 return NULL;
556 ef->delete_me_now = 1; 585
557 eet_close(ef);
558 return NULL;
559 }
560 /* allocate dynamic buffer for entire directory block */
561 dyn_buf = alloca(byte_entries);
562 if (!dyn_buf)
563 {
564 ef->delete_me_now = 1;
565 eet_close(ef);
566 return NULL;
567 }
568 /* allocate header */ 586 /* allocate header */
569 ef->header = calloc(1, sizeof(Eet_File_Header)); 587 ef->header = calloc(1, sizeof(Eet_File_Header));
570 if (!ef->header) 588 if (eet_test_close(!ef->header, ef))
571 { 589 return NULL;
572 ef->delete_me_now = 1; 590
573 eet_close(ef);
574 return NULL;
575 }
576 ef->header->magic = EET_MAGIC_FILE_HEADER; 591 ef->header->magic = EET_MAGIC_FILE_HEADER;
592
577 /* allocate directory block in ram */ 593 /* allocate directory block in ram */
578 ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); 594 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
579 if (!ef->header->directory) 595 if (eet_test_close(!ef->header->directory, ef))
580 { 596 return NULL;
581 ef->delete_me_now = 1; 597
582 eet_close(ef);
583 return NULL;
584 }
585 /* 8 bit hash table (256 buckets) */ 598 /* 8 bit hash table (256 buckets) */
586 ef->header->directory->size = 8; 599 ef->header->directory->size = 8;
587 /* allocate base hash table */ 600 /* allocate base hash table */
588 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); 601 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
589 if (!ef->header->directory->nodes) 602 if (eet_test_close(!ef->header->directory->nodes, ef))
590 { 603 return NULL;
591 ef->delete_me_now = 1; 604
592 eet_close(ef);
593 return NULL;
594 }
595 /* actually read the directory block - all of it, into ram */ 605 /* actually read the directory block - all of it, into ram */
596 count = fread(dyn_buf, byte_entries, 1, ef->fp); 606 dyn_buf = ef->data + index;
597 if (count != 1) 607
598 {
599 ef->delete_me_now = 1;
600 eet_close(ef);
601 return NULL;
602 }
603 /* parse directory block */ 608 /* parse directory block */
604 p = dyn_buf; 609 p = dyn_buf;
605// printf("entries: %i\n", num_entries); 610
606 for (i = 0; i < num_entries; i++) 611 for (i = 0; i < num_entries; i++)
607 { 612 {
608 int offset; 613 Eet_File_Node *efn;
609 int flags; 614 void *data = NULL;
610 int size; 615 int indexn = 0;
611 int data_size; 616 int name_size;
612 int name_size; 617 int hash;
613 int hash; 618 int k;
614 Eet_File_Node *efn; 619
615 void *data = NULL; 620#define HEADER_SIZE sizeof (uint32_t) * 5
616 621
617 /* out directory block is inconsistent - we have oveerun our */ 622 /* out directory block is inconsistent - we have oveerun our */
618 /* dynamic block buffer before we finished scanning dir entries */ 623 /* dynamic block buffer before we finished scanning dir entries */
619 if (p >= (dyn_buf + byte_entries)) 624 if (eet_test_close(p + HEADER_SIZE >= (dyn_buf + byte_entries), ef))
620 { 625 return NULL;
621 ef->delete_me_now = 1; 626
622 eet_close(ef); 627 /* allocate all the ram needed for this stored node accounting */
623 return NULL; 628 efn = malloc (sizeof(Eet_File_Node));
624 } 629 if (eet_test_close (!efn, ef))
630 return NULL;
631
625 /* get entrie header */ 632 /* get entrie header */
626 memcpy(&i1, p + 0, sizeof(int)); 633 EXTRACT_INT(efn->offset, p, indexn);
627 i2 = ntohl(i1); 634 EXTRACT_INT(efn->compression, p, indexn);
628 offset = (int)i2; 635 EXTRACT_INT(efn->size, p, indexn);
629 memcpy(&i1, p + 4, sizeof(int)); 636 EXTRACT_INT(efn->data_size, p, indexn);
630 i2 = ntohl(i1); 637 EXTRACT_INT(name_size, p, indexn);
631 flags = (int)i2; 638
632 memcpy(&i1, p + 8, sizeof(int));
633 i2 = ntohl(i1);
634 size = (int)i2;
635 memcpy(&i1, p + 12, sizeof(int));
636 i2 = ntohl(i1);
637 data_size = (int)i2;
638 memcpy(&i1, p + 16, sizeof(int));
639 i2 = ntohl(i1);
640 name_size = (int)i2;
641 /* invalid size */ 639 /* invalid size */
642 if (size <= 0) 640 if (eet_test_close(efn->size <= 0, ef))
643 { 641 {
644 eet_close(ef); 642 free (efn);
645 return NULL; 643 return NULL;
646 } 644 }
645
647 /* invalid name_size */ 646 /* invalid name_size */
648 if (name_size <= 0) 647 if (eet_test_close(name_size <= 0, ef))
649 { 648 {
650 ef->delete_me_now = 1; 649 free (efn);
651 eet_close(ef);
652 return NULL; 650 return NULL;
653 } 651 }
652
654 /* reading name would mean falling off end of dyn_buf - invalid */ 653 /* reading name would mean falling off end of dyn_buf - invalid */
655 if ((p + 16 + name_size) > (dyn_buf + byte_entries)) 654 if (eet_test_close((p + 16 + name_size) > (dyn_buf + byte_entries), ef))
656 { 655 {
657 ef->delete_me_now = 1; 656 free (efn);
658 eet_close(ef);
659 return NULL; 657 return NULL;
660 } 658 }
661 /* allocate all the ram needed for this stored node accounting */ 659
662 efn = malloc(sizeof(Eet_File_Node) + name_size + 1); 660 /* This code is useless if we dont want backward compatibility */
663 if (!efn) 661 for (k = name_size; k > 0 && ((uint8_t)*(p + HEADER_SIZE + k)) != 0; --k)
662 ;
663
664 efn->free_name = ((uint8_t)*(p + HEADER_SIZE + k)) != 0;
665
666 if (efn->free_name)
664 { 667 {
665 ef->delete_me_now = 1; 668 efn->name = malloc(sizeof (char) * name_size + 1);
666 eet_close(ef); 669 if (eet_test_close(efn->name == NULL, ef))
667 return NULL; 670 {
671 free (efn);
672 return NULL;
673 }
674
675 strncpy(efn->name, (char *)p + HEADER_SIZE, name_size);
676 efn->name[name_size] = 0;
677
678 printf("File: %s is not up to date for key \"%s\" - needs rebuilding sometime\n", ef->path, efn->name);
668 } 679 }
669 efn->name = ((char *)efn) + sizeof(Eet_File_Node); 680 else
670 /* copy name in and terminate it */ 681 /* The only really usefull peace of code for efn->name (no backward compatibility) */
671 strncpy(efn->name, (char *)p + 20, name_size); 682 efn->name = (char*) ((uint8_t*)(p + HEADER_SIZE));
672 efn->name[name_size] = 0; 683
673 /* get hask bucket it should go in */ 684 /* get hash bucket it should go in */
674 hash = eet_hash_gen(efn->name, ef->header->directory->size); 685 hash = eet_hash_gen(efn->name, ef->header->directory->size);
675 efn->next = ef->header->directory->nodes[hash]; 686 efn->next = ef->header->directory->nodes[hash];
676 ef->header->directory->nodes[hash] = efn; 687 ef->header->directory->nodes[hash] = efn;
677 efn->offset = offset;
678 efn->compression = flags;
679 efn->size = size;
680 efn->data_size = data_size;
681 688
682 /* read-only mode, so currently we have no data loaded */ 689 /* read-only mode, so currently we have no data loaded */
683 if (mode == EET_FILE_MODE_READ) 690 if (mode == EET_FILE_MODE_READ)
@@ -685,28 +692,13 @@ eet_open(const char *file, Eet_File_Mode mode)
685 /* read-write mode - read everything into ram */ 692 /* read-write mode - read everything into ram */
686 else 693 else
687 { 694 {
688 data = malloc(size); 695 data = malloc(efn->size);
689 if (data) 696 if (data)
690 { 697 memcpy (data, ef->data + efn->offset, efn->size);
691 if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
692 {
693 free(data);
694 data = NULL;
695 /* XXX die gracefully somehow */
696 break;
697 }
698 if (fread(data, size, 1, ef->fp) != 1)
699 {
700 free(data);
701 data = NULL;
702 /* XXX die gracefully somehow */
703 break;
704 }
705 }
706 efn->data = data; 698 efn->data = data;
707 } 699 }
708 /* advance */ 700 /* advance */
709 p += 20 + name_size; 701 p += HEADER_SIZE + name_size;
710 } 702 }
711 } 703 }
712 704
@@ -723,9 +715,11 @@ eet_open(const char *file, Eet_File_Mode mode)
723 { 715 {
724 if (ef->mode == EET_FILE_MODE_READ) 716 if (ef->mode == EET_FILE_MODE_READ)
725 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); 717 eet_cache_add(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
726 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE)) 718 else
727 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); 719 if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
720 eet_cache_add(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
728 } 721 }
722
729 return ef; 723 return ef;
730} 724}
731 725
@@ -743,29 +737,25 @@ EAPI Eet_Error
743eet_close(Eet_File *ef) 737eet_close(Eet_File *ef)
744{ 738{
745 Eet_Error err; 739 Eet_Error err;
746 740
747 /* check to see its' an eet file pointer */ 741 /* check to see its' an eet file pointer */
748 if ((!ef) || (ef->magic != EET_MAGIC_FILE)) 742 if (eet_check_pointer(ef))
749 return EET_ERROR_BAD_OBJECT; 743 return EET_ERROR_BAD_OBJECT;
750 /* deref */ 744 /* deref */
751 ef->references--; 745 ef->references--;
752 /* if its still referenced - dont go any further */ 746 /* if its still referenced - dont go any further */
753 if (ef->references > 0) return EET_ERROR_NONE; 747 if (ef->references > 0) return EET_ERROR_NONE;
754 /* if we are in cacheburst mode - dont free it - leave it in cache */ 748 /* flush any writes */
755 if (eet_cacheburst_mode) 749 err = eet_flush(ef);
756 { 750
757 if (!ef->delete_me_now) return EET_ERROR_NONE; 751 /* if not urgent to delete it - dont free it - leave it in cache */
758 } 752 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
753 return EET_ERROR_NONE;
759 /* remove from cache */ 754 /* remove from cache */
760 if (ef->mode == EET_FILE_MODE_READ) 755 if (ef->mode == EET_FILE_MODE_READ)
761 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc); 756 eet_cache_del(ef, &eet_readers, &eet_readers_num, &eet_readers_alloc);
762 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE)) 757 else if ((ef->mode == EET_FILE_MODE_WRITE) || (ef->mode == EET_FILE_MODE_READ_WRITE))
763 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc); 758 eet_cache_del(ef, &eet_writers, &eet_writers_num, &eet_writers_alloc);
764 /* flush any writes */
765 err = eet_flush(ef);
766
767 /* free up members */
768 if (ef->fp) fclose(ef->fp);
769 759
770 /* free up data */ 760 /* free up data */
771 if (ef->header) 761 if (ef->header)
@@ -775,7 +765,7 @@ eet_close(Eet_File *ef)
775 if (ef->header->directory->nodes) 765 if (ef->header->directory->nodes)
776 { 766 {
777 int i, num; 767 int i, num;
778 768
779 num = (1 << ef->header->directory->size); 769 num = (1 << ef->header->directory->size);
780 for (i = 0; i < num; i++) 770 for (i = 0; i < num; i++)
781 { 771 {
@@ -783,8 +773,14 @@ eet_close(Eet_File *ef)
783 773
784 while ((efn = ef->header->directory->nodes[i])) 774 while ((efn = ef->header->directory->nodes[i]))
785 { 775 {
786 if (efn->data) free(efn->data); 776 if (efn->data)
777 free(efn->data);
778
787 ef->header->directory->nodes[i] = efn->next; 779 ef->header->directory->nodes[i] = efn->next;
780
781 if (efn->free_name)
782 free(efn->name);
783
788 free(efn); 784 free(efn);
789 } 785 }
790 } 786 }
@@ -794,6 +790,8 @@ eet_close(Eet_File *ef)
794 } 790 }
795 free(ef->header); 791 free(ef->header);
796 } 792 }
793 if (ef->data)
794 munmap(ef->data, ef->data_size);
797 795
798 /* zero out ram for struct - caution tactic against stale memory use */ 796 /* zero out ram for struct - caution tactic against stale memory use */
799 memset(ef, 0, sizeof(Eet_File)); 797 memset(ef, 0, sizeof(Eet_File));
@@ -805,34 +803,38 @@ eet_close(Eet_File *ef)
805EAPI void * 803EAPI void *
806eet_read(Eet_File *ef, const char *name, int *size_ret) 804eet_read(Eet_File *ef, const char *name, int *size_ret)
807{ 805{
808 void *data = NULL; 806 void *data = NULL;
809 int size = 0; 807 int size = 0;
810 Eet_File_Node *efn; 808 Eet_File_Node *efn;
811 809
812 if (size_ret) *size_ret = 0; 810 if (size_ret)
811 *size_ret = 0;
813 812
814 /* check to see its' an eet file pointer */ 813 /* check to see its' an eet file pointer */
815 if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name) || 814 if (eet_check_pointer(ef))
816 ((ef->mode != EET_FILE_MODE_READ) && 815 return NULL;
817 (ef->mode != EET_FILE_MODE_READ_WRITE))) 816 if (!name)
818 { 817 return NULL;
819 return NULL; 818 if ((ef->mode != EET_FILE_MODE_READ) &&
820 } 819 (ef->mode != EET_FILE_MODE_READ_WRITE))
820 return NULL;
821
821 /* no header, return NULL */ 822 /* no header, return NULL */
822 if (!ef->header) return NULL; 823 if (eet_check_header(ef))
823 /* no directory, return NULL */ 824 return NULL;
824 if (!ef->header->directory) return NULL;
825 825
826 /* hunt hash bucket */ 826 /* hunt hash bucket */
827 efn = find_node_by_name(ef, name); 827 efn = find_node_by_name(ef, name);
828 if (!efn) return NULL; 828 if (!efn)
829 return NULL;
829 830
830 /* get size (uncompressed, if compressed at all) */ 831 /* get size (uncompressed, if compressed at all) */
831 size = efn->data_size; 832 size = efn->data_size;
832 833
833 /* allocate data */ 834 /* allocate data */
834 data = malloc(size); 835 data = malloc(size);
835 if (!data) return NULL; 836 if (!data)
837 return NULL;
836 838
837 /* uncompressed data */ 839 /* uncompressed data */
838 if (efn->compression == 0) 840 if (efn->compression == 0)
@@ -840,18 +842,20 @@ eet_read(Eet_File *ef, const char *name, int *size_ret)
840 /* if we alreayd have the data in ram... copy that */ 842 /* if we alreayd have the data in ram... copy that */
841 if (efn->data) 843 if (efn->data)
842 memcpy(data, efn->data, efn->size); 844 memcpy(data, efn->data, efn->size);
843 else if (!read_data_from_disk(ef, efn, data, size)) 845 else
844 { 846 if (!read_data_from_disk(ef, efn, data, size))
845 free(data); 847 {
846 return NULL; 848 free(data);
847 } 849 return NULL;
850 }
848 } 851 }
849 /* compressed data */ 852 /* compressed data */
850 else 853 else
851 { 854 {
852 void *tmp_data; 855 void *tmp_data;
853 int free_tmp = 0, compr_size = efn->size; 856 int free_tmp = 0;
854 uLongf dlen; 857 int compr_size = efn->size;
858 uLongf dlen;
855 859
856 /* if we already have the data in ram... copy that */ 860 /* if we already have the data in ram... copy that */
857 if (efn->data) 861 if (efn->data)
@@ -869,6 +873,7 @@ eet_read(Eet_File *ef, const char *name, int *size_ret)
869 873
870 if (!read_data_from_disk(ef, efn, tmp_data, compr_size)) 874 if (!read_data_from_disk(ef, efn, tmp_data, compr_size))
871 { 875 {
876 free(tmp_data);
872 free(data); 877 free(data);
873 return NULL; 878 return NULL;
874 } 879 }
@@ -883,56 +888,109 @@ eet_read(Eet_File *ef, const char *name, int *size_ret)
883 return NULL; 888 return NULL;
884 } 889 }
885 890
886 if (free_tmp) free(tmp_data); 891 if (free_tmp)
892 free(tmp_data);
887 } 893 }
888 894
889 /* fill in return values */ 895 /* fill in return values */
890 if (size_ret) *size_ret = size; 896 if (size_ret)
897 *size_ret = size;
898
899 return data;
900}
901
902EAPI void *
903eet_read_direct(Eet_File *ef, const char *name, int *size_ret)
904{
905 void *data = NULL;
906 int size = 0;
907 Eet_File_Node *efn;
908
909 if (size_ret)
910 *size_ret = 0;
911
912 /* check to see its' an eet file pointer */
913 if (eet_check_pointer(ef))
914 return NULL;
915 if (!name)
916 return NULL;
917 if ((ef->mode != EET_FILE_MODE_READ) &&
918 (ef->mode != EET_FILE_MODE_READ_WRITE))
919 return NULL;
920
921 /* no header, return NULL */
922 if (eet_check_header(ef))
923 return NULL;
924
925 /* hunt hash bucket */
926 efn = find_node_by_name(ef, name);
927 if (!efn)
928 return NULL;
929
930 /* get size (uncompressed, if compressed at all) */
931 size = efn->data_size;
932
933 /* uncompressed data */
934 if (efn->compression == 0)
935 data = efn->data ? efn->data : ef->data + efn->offset;
936 /* compressed data */
937 else
938 data = NULL;
939
940 /* fill in return values */
941 if (size_ret)
942 *size_ret = size;
943
891 return data; 944 return data;
892} 945}
893 946
894EAPI int 947EAPI int
895eet_write(Eet_File *ef, const char *name, const void *data, int size, int compress) 948eet_write(Eet_File *ef, const char *name, const void *data, int size, int compress)
896{ 949{
897 int data_size; 950 Eet_File_Node *efn;
898 int hash; 951 void *data2;
899 Eet_File_Node *efn; 952 int exists_already = 0;
900 void *data2; 953 int data_size;
901 int exists_already = 0; 954 int hash;
902 955
903 /* check to see its' an eet file pointer */ 956 /* check to see its' an eet file pointer */
904 if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name) || (!data) || 957 if (eet_check_pointer(ef))
905 (size <= 0) || ((ef->mode != EET_FILE_MODE_WRITE) && 958 return 0;
906 (ef->mode != EET_FILE_MODE_READ_WRITE))) 959 if ((!name) || (!data) || (size <= 0))
960 return 0;
961 if ((ef->mode != EET_FILE_MODE_WRITE) &&
962 (ef->mode != EET_FILE_MODE_READ_WRITE))
907 return 0; 963 return 0;
908 964
909 if (!ef->header) 965 if (!ef->header)
910 { 966 {
911 /* allocate header */ 967 /* allocate header */
912 ef->header = calloc(1, sizeof(Eet_File_Header)); 968 ef->header = calloc(1, sizeof(Eet_File_Header));
913 if (!ef->header) return 0; 969 if (!ef->header)
970 return 0;
971
914 ef->header->magic = EET_MAGIC_FILE_HEADER; 972 ef->header->magic = EET_MAGIC_FILE_HEADER;
915 /* allocate directory block in ram */ 973 /* allocate directory block in ram */
916 ef->header->directory = calloc(1, sizeof(Eet_File_Directory)); 974 ef->header->directory = calloc(1, sizeof(Eet_File_Directory));
917 if (!ef->header->directory) return 0; 975 if (!ef->header->directory)
976 return 0;
977
918 /* 8 bit hash table (256 buckets) */ 978 /* 8 bit hash table (256 buckets) */
919 ef->header->directory->size = 8; 979 ef->header->directory->size = 8;
920 /* allocate base hash table */ 980 /* allocate base hash table */
921 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size)); 981 ef->header->directory->nodes = calloc(1, sizeof(Eet_File_Node *) * (1 << ef->header->directory->size));
922 if (!ef->header->directory->nodes) return 0; 982 if (!ef->header->directory->nodes)
983 return 0;
923 } 984 }
924 985
925 /* figure hash bucket */ 986 /* figure hash bucket */
926 hash = eet_hash_gen(name, ef->header->directory->size); 987 hash = eet_hash_gen(name, ef->header->directory->size);
927 988
928 /* dup data */ 989 data_size = compress ? 12 + ((size * 101) / 100) : size;
929 data_size = size;
930
931 /* have bigger buffer for compress */
932 if (compress) data_size = 12 + ((size * 101) / 100);
933 990
934 data2 = malloc(data_size); 991 data2 = malloc(data_size);
935 if (!data2) return 0; 992 if (!data2)
993 return 0;
936 994
937 /* if we want to compress */ 995 /* if we want to compress */
938 if (compress) 996 if (compress)
@@ -959,7 +1017,8 @@ eet_write(Eet_File *ef, const char *name, const void *data, int size, int compre
959 void *data3; 1017 void *data3;
960 1018
961 data3 = realloc(data2, data_size); 1019 data3 = realloc(data2, data_size);
962 if (data3) data2 = data3; 1020 if (data3)
1021 data2 = data3;
963 } 1022 }
964 } 1023 }
965 if (!compress) 1024 if (!compress)
@@ -985,14 +1044,14 @@ eet_write(Eet_File *ef, const char *name, const void *data, int size, int compre
985 } 1044 }
986 if (!exists_already) 1045 if (!exists_already)
987 { 1046 {
988 efn = malloc(sizeof(Eet_File_Node) + strlen(name) + 1); 1047 efn = malloc(sizeof(Eet_File_Node));
989 if (!efn) 1048 if (!efn)
990 { 1049 {
991 free(data2); 1050 free(data2);
992 return 0; 1051 return 0;
993 } 1052 }
994 efn->name = (char *)efn + sizeof(Eet_File_Node); 1053 efn->name = strdup(name);
995 strcpy(efn->name, name); 1054 efn->free_name = 1;
996 efn->next = ef->header->directory->nodes[hash]; 1055 efn->next = ef->header->directory->nodes[hash];
997 ef->header->directory->nodes[hash] = efn; 1056 ef->header->directory->nodes[hash] = efn;
998 efn->offset = 0; 1057 efn->offset = 0;
@@ -1010,29 +1069,38 @@ eet_write(Eet_File *ef, const char *name, const void *data, int size, int compre
1010EAPI int 1069EAPI int
1011eet_delete(Eet_File *ef, const char *name) 1070eet_delete(Eet_File *ef, const char *name)
1012{ 1071{
1013 int hash; 1072 Eet_File_Node *efn;
1014 int exists_already = 0; 1073 Eet_File_Node *pefn;
1015 Eet_File_Node *efn, *pefn; 1074 int hash;
1075 int exists_already = 0;
1016 1076
1017 /* check to see its' an eet file pointer */ 1077 /* check to see its' an eet file pointer */
1018 if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!name)) 1078 if (eet_check_pointer(ef))
1079 return 0;
1080 if (!name)
1019 return 0; 1081 return 0;
1020 1082
1021 /* deleting keys is only possible in RW or WRITE mode */ 1083 /* deleting keys is only possible in RW or WRITE mode */
1022 if (ef->mode == EET_FILE_MODE_READ) return 0; 1084 if (ef->mode == EET_FILE_MODE_READ)
1085 return 0;
1023 1086
1024 if (!ef->header) return 0; 1087 if (eet_check_header(ef))
1088 return 0;
1025 1089
1026 /* figure hash bucket */ 1090 /* figure hash bucket */
1027 hash = eet_hash_gen(name, ef->header->directory->size); 1091 hash = eet_hash_gen(name, ef->header->directory->size);
1028 1092
1029 /* Does this node already exist? */ 1093 /* Does this node already exist? */
1030 for (pefn = NULL, efn = ef->header->directory->nodes[hash]; efn; pefn = efn, efn = efn->next) 1094 for (pefn = NULL, efn = ef->header->directory->nodes[hash];
1095 efn;
1096 pefn = efn, efn = efn->next)
1031 { 1097 {
1032 /* if it matches */ 1098 /* if it matches */
1033 if (eet_string_match(efn->name, name)) 1099 if (eet_string_match(efn->name, name))
1034 { 1100 {
1035 if (efn->data) free(efn->data); 1101 if (efn->data)
1102 free(efn->data);
1103
1036 if (efn == ef->header->directory->nodes[hash]) 1104 if (efn == ef->header->directory->nodes[hash])
1037 ef->header->directory->nodes[hash] = efn->next; 1105 ef->header->directory->nodes[hash] = efn->next;
1038 else 1106 else
@@ -1043,7 +1111,9 @@ eet_delete(Eet_File *ef, const char *name)
1043 } 1111 }
1044 } 1112 }
1045 /* flags that writes are pending */ 1113 /* flags that writes are pending */
1046 if (exists_already) ef->writes_pending = 1; 1114 if (exists_already)
1115 ef->writes_pending = 1;
1116
1047 /* update access time */ 1117 /* update access time */
1048 return exists_already; 1118 return exists_already;
1049} 1119}
@@ -1051,21 +1121,24 @@ eet_delete(Eet_File *ef, const char *name)
1051EAPI char ** 1121EAPI char **
1052eet_list(Eet_File *ef, const char *glob, int *count_ret) 1122eet_list(Eet_File *ef, const char *glob, int *count_ret)
1053{ 1123{
1054 char **list_ret = NULL; 1124 Eet_File_Node *efn;
1055 int list_count = 0; 1125 char **list_ret = NULL;
1056 int list_count_alloc = 0; 1126 int list_count = 0;
1057 int i, num; 1127 int list_count_alloc = 0;
1058 Eet_File_Node *efn; 1128 int i, num;
1059 1129
1060 /* check to see its' an eet file pointer */ 1130 /* check to see its' an eet file pointer */
1061 if ((!ef) || (ef->magic != EET_MAGIC_FILE) || (!glob) || 1131 if (eet_check_pointer(ef) || eet_check_header(ef) ||
1062 (!ef->header) || (!ef->header->directory) || 1132 (!glob) ||
1063 ((ef->mode != EET_FILE_MODE_READ) && 1133 ((ef->mode != EET_FILE_MODE_READ) &&
1064 (ef->mode != EET_FILE_MODE_READ_WRITE))) 1134 (ef->mode != EET_FILE_MODE_READ_WRITE)))
1065 { 1135 {
1066 if (count_ret) *count_ret = 0; 1136 if (count_ret)
1137 *count_ret = 0;
1138
1067 return NULL; 1139 return NULL;
1068 } 1140 }
1141
1069 /* loop through all entries */ 1142 /* loop through all entries */
1070 num = (1 << ef->header->directory->size); 1143 num = (1 << ef->header->directory->size);
1071 for (i = 0; i < num; i++) 1144 for (i = 0; i < num; i++)
@@ -1078,30 +1151,38 @@ eet_list(Eet_File *ef, const char *glob, int *count_ret)
1078 */ 1151 */
1079 if ((!strcmp (glob, "*")) || !fnmatch(glob, efn->name, 0)) 1152 if ((!strcmp (glob, "*")) || !fnmatch(glob, efn->name, 0))
1080 { 1153 {
1081 char **new_list;
1082
1083 /* add it to our list */ 1154 /* add it to our list */
1084 list_count++; 1155 list_count++;
1156
1085 /* only realloc in 32 entry chunks */ 1157 /* only realloc in 32 entry chunks */
1086 if (list_count > list_count_alloc) 1158 if (list_count > list_count_alloc)
1087 { 1159 {
1160 char **new_list = NULL;
1161
1088 list_count_alloc += 64; 1162 list_count_alloc += 64;
1089 new_list = realloc(list_ret, list_count_alloc * (sizeof(char *))); 1163 new_list = realloc(list_ret, list_count_alloc * (sizeof(char *)));
1090 if (!new_list) 1164 if (!new_list)
1091 { 1165 {
1092 free(list_ret); 1166 free(list_ret);
1093 if (count_ret) *count_ret = 0; 1167
1168 if (count_ret)
1169 *count_ret = 0;
1170
1094 return NULL; 1171 return NULL;
1095 } 1172 }
1096 list_ret = new_list; 1173 list_ret = new_list;
1097 } 1174 }
1175
1098 /* put pointer of name string in */ 1176 /* put pointer of name string in */
1099 list_ret[list_count - 1] = efn->name; 1177 list_ret[list_count - 1] = efn->name;
1100 } 1178 }
1101 } 1179 }
1102 } 1180 }
1181
1103 /* return count and list */ 1182 /* return count and list */
1104 if (count_ret) *count_ret = list_count; 1183 if (count_ret)
1184 *count_ret = list_count;
1185
1105 return list_ret; 1186 return list_ret;
1106} 1187}
1107 1188
@@ -1112,22 +1193,17 @@ eet_num_entries(Eet_File *ef)
1112 Eet_File_Node *efn; 1193 Eet_File_Node *efn;
1113 1194
1114 /* check to see its' an eet file pointer */ 1195 /* check to see its' an eet file pointer */
1115 if ((!ef) || (ef->magic != EET_MAGIC_FILE) || 1196 if (eet_check_pointer(ef) || eet_check_header(ef) ||
1116 (!ef->header) || (!ef->header->directory) ||
1117 ((ef->mode != EET_FILE_MODE_READ) && 1197 ((ef->mode != EET_FILE_MODE_READ) &&
1118 (ef->mode != EET_FILE_MODE_READ_WRITE))) 1198 (ef->mode != EET_FILE_MODE_READ_WRITE)))
1119 { 1199 return -1;
1120 return -1;
1121 }
1122 1200
1123 /* loop through all entries */ 1201 /* loop through all entries */
1124 num = (1 << ef->header->directory->size); 1202 num = (1 << ef->header->directory->size);
1125 for (i = 0; i < num; i++) 1203 for (i = 0; i < num; i++)
1126 { 1204 {
1127 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next) 1205 for (efn = ef->header->directory->nodes[i]; efn; efn = efn->next)
1128 { 1206 ret++;
1129 ret++;
1130 }
1131 } 1207 }
1132 1208
1133 return ret; 1209 return ret;
@@ -1143,7 +1219,10 @@ find_node_by_name(Eet_File *ef, const char *name)
1143 hash = eet_hash_gen(name, ef->header->directory->size); 1219 hash = eet_hash_gen(name, ef->header->directory->size);
1144 1220
1145 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next) 1221 for (efn = ef->header->directory->nodes[hash]; efn; efn = efn->next)
1146 if (eet_string_match(efn->name, name)) return efn; 1222 {
1223 if (eet_string_match(efn->name, name))
1224 return efn;
1225 }
1147 1226
1148 return NULL; 1227 return NULL;
1149} 1228}
@@ -1151,9 +1230,16 @@ find_node_by_name(Eet_File *ef, const char *name)
1151static int 1230static int
1152read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len) 1231read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int len)
1153{ 1232{
1154 /* seek to data location */ 1233 if (ef->data)
1155 if (fseek(ef->fp, efn->offset, SEEK_SET) < 0) return 0; 1234 memcpy (buf, ef->data + efn->offset, len);
1156 1235 else
1157 /* read it */ 1236 {
1158 return (fread(buf, len, 1, ef->fp) == 1); 1237 /* seek to data location */
1238 if (fseek(ef->fp, efn->offset, SEEK_SET) < 0)
1239 return 0;
1240
1241 /* read it */
1242 len = fread(buf, len, 1, ef->fp);
1243 }
1244 return len;
1159} 1245}