/[zanavi_public1]/navit/navit/file.c
ZANavi

Contents of /navit/navit/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 50 - (hide annotations) (download)
Wed Jun 22 07:33:35 2016 UTC (6 years, 7 months ago) by zoff99
File MIME type: text/plain
File size: 29906 byte(s)
v2.0.51
1 zoff99 2 /**
2 zoff99 50 * ZANavi, Zoff Android Navigation system.
3     * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
4     *
5     * This program is free software; you can redistribute it and/or
6     * modify it under the terms of the GNU General Public License
7     * version 2 as published by the Free Software Foundation.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the
16     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     * Boston, MA 02110-1301, USA.
18     */
19    
20     /**
21 zoff99 2 * Navit, a modular navigation system.
22     * Copyright (C) 2005-2011 Navit Team
23     *
24     * This program is free software; you can redistribute it and/or
25     * modify it under the terms of the GNU General Public License
26     * version 2 as published by the Free Software Foundation.
27     *
28     * This program is distributed in the hope that it will be useful,
29     * but WITHOUT ANY WARRANTY; without even the implied warranty of
30     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31     * GNU General Public License for more details.
32     *
33     * You should have received a copy of the GNU General Public License
34     * along with this program; if not, write to the
35     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36     * Boston, MA 02110-1301, USA.
37     */
38    
39     #define _FILE_OFFSET_BITS 64
40     #define _LARGEFILE_SOURCE
41     #define _LARGEFILE64_SOURCE
42     #include "config.h"
43 zoff99 50
44 zoff99 2 #ifdef HAVE_UNISTD_H
45     #include <unistd.h>
46     #endif
47 zoff99 50
48 zoff99 2 #ifdef _MSC_VER
49     #include <windows.h>
50     #else
51     #include <dirent.h>
52     #endif /* _MSC_VER */
53 zoff99 50
54 zoff99 2 #include <string.h>
55     #include <fcntl.h>
56     #include <sys/stat.h>
57     #include <sys/mman.h>
58     #include <stdio.h>
59     #include <stdlib.h>
60     #include <wordexp.h>
61     #include <glib.h>
62     #include <zlib.h>
63     #include "debug.h"
64     #include "cache.h"
65     #include "file.h"
66     #include "atom.h"
67     #include "item.h"
68     #include "util.h"
69     #include "types.h"
70 zoff99 50
71 zoff99 2 #ifdef HAVE_SOCKET
72     #include <sys/socket.h>
73     #include <netdb.h>
74     #endif
75    
76 zoff99 50 #include "navit.h"
77    
78 zoff99 2 extern char *version;
79    
80     #ifdef HAVE_LIBCRYPTO
81     #include <openssl/sha.h>
82     #include <openssl/hmac.h>
83     #include <openssl/aes.h>
84     #include <openssl/evp.h>
85     #include <openssl/rand.h>
86     #endif
87    
88     #ifdef HAVE_API_ANDROID
89     #define lseek lseek64
90     #endif
91    
92     #ifndef O_LARGEFILE
93     #define O_LARGEFILE 0
94     #endif
95    
96     #ifndef O_BINARY
97     #define O_BINARY 0
98     #endif
99    
100     #ifdef CACHE_SIZE
101     static GHashTable *file_name_hash;
102     #endif
103    
104     static struct cache *file_cache;
105    
106     #ifdef _MSC_VER
107     #pragma pack(push,1)
108     #endif /* _MSC_VER */
109 zoff99 50 struct file_cache_id
110     {
111 zoff99 2 long long offset;
112     int size;
113     int file_name_id;
114     int method;
115     #ifndef _MSC_VER
116     }__attribute__ ((packed));
117     #else /* _MSC_VER */
118     };
119     #pragma pack(pop)
120     #endif /* _MSC_VER */
121    
122     #ifdef HAVE_SOCKET
123     static int
124     file_socket_connect(char *host, char *service)
125     {
126 zoff99 50 //dbg(0,"_enterXX %s %s\n", host, service);
127     int fd;
128 zoff99 2 return fd;
129     }
130    
131     static void
132     file_http_request(struct file *file, char *method, char *host, char *path, char *header, int persistent)
133     {
134 zoff99 50 //dbg(0,"_enterXX %s\n", path);
135 zoff99 2 }
136    
137     static int
138     file_request_do(struct file *file, struct attr **options, int connect)
139     {
140 zoff99 50 //dbg(0,"_enterXX %s\n", file->name);
141 zoff99 2 return 1;
142     }
143     #endif
144    
145     static unsigned char *
146     file_http_header_end(unsigned char *str, int len)
147     {
148 zoff99 50 //dbg(0,"_enterXX %s\n", str);
149     return NULL;
150 zoff99 2 }
151    
152 zoff99 50 int file_request(struct file *f, struct attr **options)
153 zoff99 2 {
154 zoff99 50 //dbg(0,"_enterXX %s\n", f->name);
155 zoff99 2 return 0;
156     }
157    
158     char *
159     file_http_header(struct file *f, char *header)
160     {
161 zoff99 50 //dbg(0,"_enterXX %s\n", f->name);
162     return NULL;
163 zoff99 2 }
164    
165     struct file *
166     file_create(char *name, struct attr **options)
167     {
168 zoff99 50 //dbg(0,"_enterPP %s\n", name);
169 zoff99 2 struct stat stat;
170     struct file *file= g_new0(struct file,1);
171     struct attr *attr;
172 zoff99 50 int open_flags = O_LARGEFILE | O_BINARY;
173 zoff99 2
174 zoff99 50 if (options && (attr = attr_search(options, NULL, attr_url)))
175     {
176 zoff99 2 #ifdef HAVE_SOCKET
177 zoff99 50 //dbg(0,"_HAVE_SOCKET\n");
178 zoff99 2 file_request_do(file, options, 1);
179     #endif
180 zoff99 50 }
181     else
182     {
183     if (options && (attr = attr_search(options, NULL, attr_readwrite)) && attr->u.num)
184     {
185 zoff99 2 open_flags |= O_RDWR;
186 zoff99 50 if ((attr = attr_search(options, NULL, attr_create)) && attr->u.num)
187     {
188 zoff99 2 open_flags |= O_CREAT;
189 zoff99 50 }
190     }
191     else
192     {
193 zoff99 2 open_flags |= O_RDONLY;
194 zoff99 50 }
195    
196 zoff99 2 file->name = g_strdup(name);
197 zoff99 50 file->fd = open(name, open_flags, 0666);
198     file->current_splitter = 0; // ORIG file opened
199     if (file->fd == -1)
200     {
201 zoff99 2 g_free(file);
202     return NULL;
203     }
204 zoff99 50 dbg(0, "_fd=%d\n", file->fd);
205    
206     // set default value
207     file->num_splits = 0;
208     file->size = file_size(file);
209    
210     dbg(0,"_size="LONGLONG_FMT"\n", file->size);
211     file->name_id = (long) atom(name);
212 zoff99 2 }
213     #ifdef CACHE_SIZE
214 zoff99 50 //if (!options || !(attr=attr_search(options, NULL, attr_cache)) || attr->u.num)
215     //{
216     dbg(0,"_cache=1 for %s\n",name);
217     file->cache=1;
218     //}
219 zoff99 2 #endif
220     dbg_assert(file != NULL);
221     return file;
222     }
223    
224     #ifndef S_ISDIR
225     #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
226     #endif
227     #ifndef S_ISREG
228     #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
229     #endif
230    
231     int file_is_dir(char *name)
232     {
233 zoff99 50 //dbg(0,"_enterOO %s\n", name);
234 zoff99 2 struct stat buf;
235 zoff99 50 if (!stat(name, &buf))
236     {
237 zoff99 2 return S_ISDIR(buf.st_mode);
238     }
239     return 0;
240     }
241    
242     int file_is_reg(char *name)
243     {
244 zoff99 50 //dbg(0,"_enterOO\n");
245 zoff99 2 struct stat buf;
246 zoff99 50 if (!stat(name, &buf))
247     {
248 zoff99 2 return S_ISREG(buf.st_mode);
249     }
250     return 0;
251     }
252    
253 zoff99 50 long long file_size(struct file *file)
254 zoff99 2 {
255 zoff99 50 dbg(0, "_enterPP %s\n", file->name);
256    
257     // first get and set orig file size
258     struct stat buf2;
259     stat(file->name, &buf2);
260     file->size = buf2.st_size;
261     dbg(0,"_orig_size="LONGLONG_FMT"\n", file->size);
262    
263     // use initial size
264     long long f_size = file->size;
265     file->split_size_in_bytes = 0;
266     file->last_splitter_size_in_bytes = 0;
267    
268     // size of all the splitters (assume all the splitter have SAME byte size!!)
269     file->split_size_in_bytes = file->size;
270    
271     int i;
272     int j = 0;
273     int finished = 0;
274     for (i = 0; i < MAX_SPLIT_FILES; i++)
275     {
276     if (finished == 0)
277     {
278     char *name = g_strdup_printf("%s.%d", file->name, (i + 1));
279     dbg(0, "_i=%d name=%s\n", (i + 1), name);
280     struct stat buf;
281     if (!stat(name, &buf))
282     {
283     dbg(0,"_st_size="LONGLONG_FMT"\n", buf.st_size);
284     f_size = f_size + buf.st_size;
285     j = i + 1;
286     if (i == 0)
287     {
288     }
289     else
290     {
291     // size of last splitter (will be most likely smaller since its the last part)
292     file->last_splitter_size_in_bytes = buf.st_size;
293     }
294     }
295     else
296     {
297     finished = 1;
298     }
299     g_free(name);
300     }
301     }
302    
303     // set num. of split files
304     file->num_splits = j;
305     dbg(0, "_num_splits=%d\n", file->num_splits);
306    
307     dbg(0,"_all_size="LONGLONG_FMT"\n", f_size);
308     return f_size;
309     // return file->size;
310 zoff99 2 }
311    
312     int file_mkdir(char *name, int pflag)
313     {
314 zoff99 50 //dbg(0,"_enterOO %s\n", name);
315     char *buffer = g_alloca(sizeof(char) * (strlen(name) + 1));
316 zoff99 2 int ret;
317     char *next;
318 zoff99 50 // dbg(1, "enter %s %d\n", name, pflag);
319     if (!pflag)
320     {
321 zoff99 2 if (file_is_dir(name))
322 zoff99 50 {
323 zoff99 2 return 0;
324 zoff99 50 }
325 zoff99 2 #if defined HAVE_API_WIN32_BASE || defined _MSC_VER
326     return mkdir(name);
327     #else
328     return mkdir(name, 0777);
329     #endif
330     }
331     strcpy(buffer, name);
332 zoff99 50 next = buffer;
333     while ((next = strchr(next, '/')))
334     {
335     *next = '\0';
336     if (*buffer)
337     {
338     ret = file_mkdir(buffer, 0);
339 zoff99 2 if (ret)
340 zoff99 50 {
341 zoff99 2 return ret;
342 zoff99 50 }
343 zoff99 2 }
344 zoff99 50 *next++ = '/';
345 zoff99 2 }
346     if (pflag == 2)
347 zoff99 50 {
348 zoff99 2 return 0;
349 zoff99 50 }
350 zoff99 2 return file_mkdir(buffer, 0);
351     }
352    
353 zoff99 50 int file_mmap(struct file *file)
354 zoff99 2 {
355 zoff99 50 //dbg(0,"_enterP? %s\n", file->name);
356     int mmap_size = file->size;
357    
358     // turn off mmap!!
359     if (file->num_splits > 0)
360     {
361     file->begin = NULL;
362     return 0;
363     }
364     // turn off mmap!!
365    
366 zoff99 2 #ifdef HAVE_API_WIN32_BASE
367     file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
368     #else
369 zoff99 50 file->begin = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, file->fd, 0);
370 zoff99 2 dbg_assert(file->begin != NULL);
371 zoff99 50 if (file->begin == (void *) 0xffffffff)
372     {
373 zoff99 2 perror("mmap");
374     return 0;
375     }
376     #endif
377    
378 zoff99 50 dbg_assert(file->begin != (void *) 0xffffffff);
379     file->mmap_end = file->begin + mmap_size;
380     file->end = file->begin + file->size;
381    
382 zoff99 2 return 1;
383     }
384    
385     unsigned char *
386     file_data_read(struct file *file, long long offset, int size)
387     {
388 zoff99 50 //dbg(0,"_enterPP %s "LONGLONG_FMT" %d\n", file->name, offset, size);
389 zoff99 2 void *ret;
390     if (file->special)
391 zoff99 50 {
392 zoff99 2 return NULL;
393 zoff99 50 }
394    
395     // turn off mmap
396     if (file->num_splits == 0)
397     // turn off mmap
398     {
399     if (file->begin)
400     {
401     //dbg(0,"_leave:begin\n");
402     return file->begin + offset;
403     }
404     }
405    
406     if (file_cache)
407     {
408     //dbg(0,"_file_cache\n");
409     struct file_cache_id id = { offset, size, file->name_id, 0 };
410     ret = cache_lookup(file_cache, &id);
411 zoff99 2 if (ret)
412 zoff99 50 {
413     //dbg(0,"_file_cache:found\n");
414 zoff99 2 return ret;
415 zoff99 50 }
416     //dbg(0,"_file_cache:insert\n");
417     ret = cache_insert_new(file_cache, &id, size);
418 zoff99 2 }
419 zoff99 50 else
420     {
421     //dbg(0,"_g_malloc\n");
422     ret = g_malloc(size);
423     }
424    
425     if (file->num_splits == 0)
426     {
427     //dbg(0,"_num_splits=0\n");
428     lseek(file->fd, offset, SEEK_SET);
429     if (read(file->fd, ret, size) != size)
430     {
431     file_data_free(file, ret);
432     ret = NULL;
433     }
434     }
435     else
436     {
437     //dbg(0,"_num_splits=1\n");
438    
439     /* ++++++++++++++++++++++++++++++++++++++++++ */
440     /* ++++++++++++++++++++++++++++++++++++++++++ */
441     int start_splitter;
442     long long offset_split;
443     long long offset2;
444     int size2;
445     int read_size;
446     int need_more = 1;
447     char *ret2; // just define any sort of pointer, maybe this can be done better??
448    
449     ret2 = ret; // copy startaddress of buffer
450     offset2 = offset;
451     size2 = size;
452    
453     while (need_more == 1)
454     {
455     //dbg(0,"_X:of2="LONGLONG_FMT" split_size_in_bytes=%d\n", offset2, file->split_size_in_bytes);
456     start_splitter = (offset2 / file->split_size_in_bytes);
457     offset_split = offset2 - (file->split_size_in_bytes * start_splitter);
458     //dbg(0,"_X:sp=%d ofs="LONGLONG_FMT"\n", start_splitter, offset_split);
459    
460     // open
461     if (file->current_splitter != start_splitter)
462     {
463     //dbg(0,"_X:curr=%d want=%d\n", file->current_splitter, start_splitter);
464     // close file
465     close(file->fd);
466     // open new file
467     int open_flags = O_LARGEFILE | O_BINARY;
468     open_flags |= O_RDONLY;
469     char *name;
470     if (start_splitter == 0)
471     {
472     name = g_strdup_printf("%s", file->name);
473     }
474     else
475     {
476     name = g_strdup_printf("%s.%d", file->name, start_splitter);
477     }
478     //dbg(0,"_X:open=%s\n", name);
479     file->fd = open(name, open_flags, 0666);
480     //dbg(0,"_X:isopen=%d\n", file->fd);
481     file->current_splitter = start_splitter; // set which file is currently open
482     g_free(name);
483     }
484    
485     if (start_splitter == file->num_splits)
486     {
487     // in last splitter, so just read to the end
488     read_size = size2;
489     // read
490     lseek(file->fd, offset_split, SEEK_SET);
491     // ***** int result = lseek(file->fd, offset_split, SEEK_SET);
492     // dbg(0,"_1:seek="LONGLONG_FMT" read=%d result=%d\n", offset_split, read_size, result);
493     int did_read = read(file->fd, ret2, read_size);
494     if (did_read != read_size)
495     {
496     file_data_free(file, ret);
497     ret = NULL;
498     //dbg(0,"_leave:error 001 read:%d\n", did_read);
499     return ret;
500     }
501     //dbg(0,"_1:read ok:%d\n", did_read);
502     // +++
503     need_more = 0;
504     }
505     else if ((offset_split + size2) > file->split_size_in_bytes)
506     {
507     read_size = file->split_size_in_bytes - offset_split;
508     // read
509     lseek(file->fd, offset_split, SEEK_SET);
510     //dbg(0,"_2:seek="LONGLONG_FMT" read=%d\n", offset_split, read_size);
511     int did_read = read(file->fd, ret2, read_size);
512     if (did_read != read_size)
513     {
514     file_data_free(file, ret);
515     ret = NULL;
516     //dbg(0,"_leave:error 002 read:%d\n", did_read);
517     return ret;
518     }
519     //dbg(0,"_2:read ok:%d\n", did_read);
520     // +++
521     if (read_size < size2)
522     {
523     // set new values
524     offset2 = offset2 + read_size; // advance offset
525     ret2 = ret2 + read_size; // advance buffer
526     size2 = size2 - read_size; // calc new size
527     need_more = 1;
528     }
529     else
530     {
531     need_more = 0;
532     }
533     }
534     else
535     {
536     // the read size is inside 1 splitter, so just read it
537     read_size = size2;
538     // read
539     lseek(file->fd, offset_split, SEEK_SET);
540     //dbg(0,"_3:seek="LONGLONG_FMT" read=%d\n", offset_split, read_size);
541     int did_read = read(file->fd, ret2, read_size);
542     if (did_read != read_size)
543     {
544     file_data_free(file, ret);
545     ret = NULL;
546     //dbg(0,"_leave:error 003 read:%d\n", did_read);
547     return ret;
548     }
549     //dbg(0,"_3:read ok:%d\n", did_read);
550     // +++
551     need_more = 0;
552     }
553     }
554     /* ++++++++++++++++++++++++++++++++++++++++++ */
555     /* ++++++++++++++++++++++++++++++++++++++++++ */
556     }
557    
558     //dbg(0,"_leave:normal\n");
559 zoff99 2 return ret;
560     }
561    
562 zoff99 50 static void file_process_headers(struct file *file, unsigned char *headers)
563 zoff99 2 {
564 zoff99 50 //dbg(0,"_enter %s\n", file->name);
565 zoff99 2 char *tok;
566     char *cl;
567     if (file->headers)
568 zoff99 50 {
569 zoff99 2 g_hash_table_destroy(file->headers);
570 zoff99 50 }
571     file->headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free_func, NULL);
572     while ((tok = strtok((char*) headers, "\r\n")))
573     {
574 zoff99 2 char *sep;
575 zoff99 50 tok = g_strdup(tok);
576     sep = strchr(tok, ':');
577 zoff99 2 if (!sep)
578 zoff99 50 {
579     sep = strchr(tok, '/');
580     }
581     if (!sep)
582     {
583 zoff99 2 g_free(tok);
584     continue;
585     }
586 zoff99 50 *sep++ = '\0';
587 zoff99 2 if (*sep == ' ')
588 zoff99 50 {
589 zoff99 2 sep++;
590 zoff99 50 }
591 zoff99 2 strtolower(tok, tok);
592 zoff99 50 // dbg(1, "header '%s'='%s'\n", tok, sep);
593 zoff99 2 g_hash_table_insert(file->headers, tok, sep);
594 zoff99 50 headers = NULL;
595 zoff99 2 }
596 zoff99 50 cl = g_hash_table_lookup(file->headers, "content-length");
597     if (cl)
598     {
599 zoff99 2 #ifdef HAVE__ATOI64
600     file->size=_atoi64(cl);
601     #else
602 zoff99 50 file->size = atoll(cl);
603 zoff99 2 #endif
604 zoff99 50 }
605 zoff99 2 }
606    
607 zoff99 50 static void file_shift_buffer(struct file *file, int amount)
608 zoff99 2 {
609 zoff99 50 //dbg(0,"_enter %s %d\n", file->name, amount);
610     memmove(file->buffer, file->buffer + amount, file->buffer_len - amount);
611     file->buffer_len -= amount;
612 zoff99 2 }
613    
614     unsigned char *
615     file_data_read_special(struct file *file, int size, int *size_ret)
616     {
617 zoff99 50 //dbg(0,"_enter %s %d\n", file->name, size);
618     unsigned char *ret, *hdr;
619     int rets = 0, rd;
620     int buffer_size = 8192;
621     int eof = 0;
622    
623 zoff99 2 if (!file->special)
624 zoff99 50 {
625 zoff99 2 return NULL;
626 zoff99 50 }
627    
628 zoff99 2 if (!file->buffer)
629 zoff99 50 {
630     file->buffer = g_malloc(buffer_size);
631     }
632    
633     ret = g_malloc(size);
634     while ((size > 0 || file->requests) && (!eof || file->buffer_len))
635     {
636     int toread = buffer_size - file->buffer_len;
637     if (toread >= 4096 && !eof)
638     {
639 zoff99 2 if (!file->requests && toread > size)
640 zoff99 50 toread = size;
641     rd = read(file->fd, file->buffer + file->buffer_len, toread);
642     if (rd > 0)
643     {
644     file->buffer_len += rd;
645     }
646     else
647     eof = 1;
648 zoff99 2 }
649 zoff99 50 if (file->requests)
650     {
651     // dbg(1, "checking header\n");
652     if ((hdr = file_http_header_end(file->buffer, file->buffer_len)))
653     {
654     hdr[-1] = '\0';
655     // dbg(1, "found %s (%d bytes)\n", file->buffer, sizeof(file->buffer));
656 zoff99 2 file_process_headers(file, file->buffer);
657 zoff99 50 file_shift_buffer(file, hdr - file->buffer);
658 zoff99 2 file->requests--;
659     if (file_http_header(file, "location"))
660 zoff99 50 {
661 zoff99 2 break;
662 zoff99 50 }
663 zoff99 2 }
664     }
665 zoff99 50 if (!file->requests)
666     {
667     rd = file->buffer_len;
668 zoff99 2 if (rd > size)
669 zoff99 50 rd = size;
670     memcpy(ret + rets, file->buffer, rd);
671 zoff99 2 file_shift_buffer(file, rd);
672 zoff99 50 rets += rd;
673     size -= rd;
674 zoff99 2 }
675     }
676 zoff99 50 *size_ret = rets;
677 zoff99 2 return ret;
678     }
679    
680     unsigned char *
681     file_data_read_all(struct file *file)
682     {
683 zoff99 50 //dbg(0,"_enter %s\n", file->name);
684 zoff99 2 return file_data_read(file, 0, file->size);
685     }
686    
687 zoff99 50 void file_data_flush(struct file *file, long long offset, int size)
688 zoff99 2 {
689 zoff99 50 //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size);
690 zoff99 2 }
691    
692 zoff99 50 int file_data_write(struct file *file, long long offset, int size, unsigned char *data)
693 zoff99 2 {
694 zoff99 50 //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size);
695 zoff99 2 return 1;
696     }
697    
698 zoff99 50 int file_get_contents(char *name, unsigned char **buffer, int *size)
699 zoff99 2 {
700 zoff99 50 //dbg(0,"_enter %s\n", name);
701 zoff99 2 struct file *file;
702 zoff99 50 file = file_create(name, 0);
703 zoff99 2 if (!file)
704 zoff99 50 {
705 zoff99 2 return 0;
706 zoff99 50 }
707     *size = file_size(file);
708     *buffer = file_data_read_all(file);
709 zoff99 2 file_destroy(file);
710 zoff99 50 return 1;
711 zoff99 2 }
712    
713 zoff99 50 static int uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
714 zoff99 2 {
715 zoff99 50 //dbg(0,"_enter %d %d\n", sourceLen, destLen);
716 zoff99 2 z_stream stream;
717     int err;
718    
719 zoff99 50 stream.next_in = (Bytef*) source;
720     stream.avail_in = (uInt) sourceLen;
721 zoff99 2 stream.next_out = dest;
722 zoff99 50 stream.avail_out = (uInt) * destLen;
723 zoff99 2
724 zoff99 50 stream.zalloc = (alloc_func) 0;
725     stream.zfree = (free_func) 0;
726 zoff99 2
727     err = inflateInit2(&stream, -MAX_WBITS);
728 zoff99 50 if (err != Z_OK)
729     {
730     return err;
731     }
732 zoff99 2
733     err = inflate(&stream, Z_FINISH);
734 zoff99 50 if (err != Z_STREAM_END)
735     {
736     inflateEnd(&stream);
737     if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
738     {
739     return Z_DATA_ERROR;
740     }
741 zoff99 2 return err;
742     }
743 zoff99 50
744 zoff99 2 *destLen = stream.total_out;
745    
746     err = inflateEnd(&stream);
747     return err;
748     }
749    
750     unsigned char *
751     file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp)
752     {
753 zoff99 50 //dbg(0,"_enterPP %s "LONGLONG_FMT" %d\n", file->name, offset, size);
754 zoff99 2 void *ret;
755     char *buffer = 0;
756 zoff99 50 uLongf destLen = size_uncomp;
757 zoff99 2
758 zoff99 50 if (file_cache)
759     {
760     //dbg(0,"_file_cache 2\n");
761     struct file_cache_id id = { offset, size, file->name_id, 1 };
762     ret = cache_lookup(file_cache, &id);
763 zoff99 2 if (ret)
764 zoff99 50 {
765     //dbg(0,"_file_cache found 2\n");
766 zoff99 2 return ret;
767 zoff99 50 }
768     //dbg(0,"_file_cache create new 2\n");
769     ret = cache_insert_new(file_cache, &id, size_uncomp);
770     }
771     else
772     {
773     ret = g_malloc(size_uncomp);
774     }
775 zoff99 2
776 zoff99 50 buffer = (char *) g_malloc(size);
777    
778     if (file->num_splits == 0)
779     {
780     //dbg(0,"_num_splits=0\n");
781     lseek(file->fd, offset, SEEK_SET);
782     if (read(file->fd, buffer, size) != size)
783     {
784 zoff99 2 g_free(ret);
785 zoff99 50 ret = NULL;
786 zoff99 2 }
787 zoff99 50 else
788     {
789     if (uncompress_int(ret, &destLen, (Bytef *) buffer, size) != Z_OK)
790     {
791     //dbg(0, "_uncompress failed\n");
792     g_free(ret);
793     ret = NULL;
794     }
795     }
796 zoff99 2 }
797 zoff99 50 else
798     {
799     //dbg(0,"_num_splits=1\n");
800    
801     /* ++++++++++++++++++++++++++++++++++++++++++ */
802     /* ++++++++++++++++++++++++++++++++++++++++++ */
803     int start_splitter;
804     long long offset_split;
805     long long offset2;
806     int size2;
807     int read_size;
808     int need_more = 1;
809     char *ret2 = 0; // just define any sort of pointer, maybe this can be done better??
810    
811     ret2 = buffer; // copy startaddress of buffer
812     offset2 = offset;
813     size2 = size;
814    
815     while (need_more == 1)
816     {
817     //dbg(0,"_X:of2="LONGLONG_FMT" split_size_in_bytes=%d\n", offset2, file->split_size_in_bytes);
818     start_splitter = (offset2 / file->split_size_in_bytes);
819     offset_split = offset2 - (file->split_size_in_bytes * start_splitter);
820     //dbg(0,"_X:sp=%d ofs="LONGLONG_FMT"\n", start_splitter, offset_split);
821    
822     // open
823     if (file->current_splitter != start_splitter)
824     {
825     //dbg(0,"_X:curr=%d want=%d\n", file->current_splitter, start_splitter);
826     // close file
827     close(file->fd);
828     // open new file
829     int open_flags = O_LARGEFILE | O_BINARY;
830     open_flags |= O_RDONLY;
831     char *name;
832     if (start_splitter == 0)
833     {
834     name = g_strdup_printf("%s", file->name);
835     }
836     else
837     {
838     name = g_strdup_printf("%s.%d", file->name, start_splitter);
839     }
840     //dbg(0,"_X:open=%s\n", name);
841     file->fd = open(name, open_flags, 0666);
842     //dbg(0,"_X:isopen=%d\n", file->fd);
843     file->current_splitter = start_splitter; // set which file is currently open
844     g_free(name);
845     }
846    
847     if (start_splitter == file->num_splits)
848     {
849     // in last splitter, so just read to the end
850     read_size = size2;
851     // read
852     lseek(file->fd, offset_split, SEEK_SET);
853     // *** int result = lseek(file->fd, offset_split, SEEK_SET);
854     //dbg(0,"_1:seek="LONGLONG_FMT" read=%d result=%d\n", offset_split, read_size, result);
855     int did_read = read(file->fd, ret2, read_size);
856     if (did_read != read_size)
857     {
858     g_free(buffer);
859     buffer = NULL;
860     g_free(ret);
861     ret = NULL;
862     //dbg(0,"_leave:error 001 read:%d\n", did_read);
863     return ret;
864     }
865     //dbg(0,"_1:read ok:%d\n", did_read);
866     // +++
867     need_more = 0;
868     }
869     else if ((offset_split + size2) > file->split_size_in_bytes)
870     {
871     read_size = file->split_size_in_bytes - offset_split;
872     // read
873     lseek(file->fd, offset_split, SEEK_SET);
874     //dbg(0,"_2:seek="LONGLONG_FMT" read=%d\n", offset_split, read_size);
875     int did_read = read(file->fd, ret2, read_size);
876     if (did_read != read_size)
877     {
878     g_free(buffer);
879     buffer = NULL;
880     g_free(ret);
881     ret = NULL;
882     //dbg(0,"_leave:error 002 read:%d\n", did_read);
883     return ret;
884     }
885     //dbg(0,"_2:read ok:%d\n", did_read);
886     // +++
887     if (read_size < size2)
888     {
889     // set new values
890     offset2 = offset2 + read_size; // advance offset
891     ret2 = ret2 + read_size; // advance buffer
892     size2 = size2 - read_size; // calc new size
893     need_more = 1;
894     }
895     else
896     {
897     need_more = 0;
898     }
899     }
900     else
901     {
902     // the read size is inside 1 splitter, so just read it
903     read_size = size2;
904     // read
905     lseek(file->fd, offset_split, SEEK_SET);
906     //dbg(0,"_3:seek="LONGLONG_FMT" read=%d\n", offset_split, read_size);
907     int did_read = read(file->fd, ret2, read_size);
908     if (did_read != read_size)
909     {
910     g_free(buffer);
911     buffer = NULL;
912     g_free(ret);
913     ret = NULL;
914     //dbg(0,"_leave:error 003 read:%d\n", did_read);
915     return ret;
916     }
917     //dbg(0,"_3:read ok:%d\n", did_read);
918     // +++
919     need_more = 0;
920     }
921     }
922     /* ++++++++++++++++++++++++++++++++++++++++++ */
923     /* ++++++++++++++++++++++++++++++++++++++++++ */
924    
925     if (buffer != NULL)
926     {
927     if (uncompress_int(ret, &destLen, (Bytef *) buffer, size) != Z_OK)
928     {
929     //dbg(0, "_uncompress failed\n");
930     g_free(ret);
931     ret = NULL;
932     }
933     }
934    
935     }
936    
937 zoff99 2 g_free(buffer);
938    
939     return ret;
940     }
941    
942     unsigned char *
943     file_data_read_encrypted(struct file *file, long long offset, int size, int size_uncomp, int compressed, char *passwd)
944     {
945 zoff99 50 //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size);
946 zoff99 2 #ifdef HAVE_LIBCRYPTO
947     void *ret;
948     unsigned char *buffer = 0;
949     uLongf destLen=size_uncomp;
950    
951 zoff99 50 if (file_cache)
952     {
953     //dbg(0,"_file_cache 3\n");
954     struct file_cache_id id =
955     { offset,size,file->name_id,1};
956     ret=cache_lookup(file_cache,&id);
957 zoff99 2 if (ret)
958 zoff99 50 {
959     //dbg(0,"_file_cache found 3\n");
960 zoff99 2 return ret;
961 zoff99 50 }
962     //dbg(0,"_file_cache create new 3\n");
963 zoff99 2 ret=cache_insert_new(file_cache,&id,size_uncomp);
964 zoff99 50 }
965     else
966     {
967 zoff99 2 ret=g_malloc(size_uncomp);
968 zoff99 50 }
969 zoff99 2 lseek(file->fd, offset, SEEK_SET);
970    
971     buffer = (unsigned char *)g_malloc(size);
972 zoff99 50 if (read(file->fd, buffer, size) != size)
973     {
974 zoff99 2 g_free(ret);
975     ret=NULL;
976 zoff99 50 }
977     else
978     {
979 zoff99 2 unsigned char key[34], salt[8], verify[2], counter[16], xor[16], mac[10], *datap;
980     int overhead=sizeof(salt)+sizeof(verify)+sizeof(mac);
981     int esize=size-overhead;
982     PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), (unsigned char *)buffer, 8, 1000, 34, key);
983 zoff99 50 if (key[32] == buffer[8] && key[33] == buffer[9] && esize >= 0)
984     {
985 zoff99 2 AES_KEY aeskey;
986     AES_set_encrypt_key(key, 128, &aeskey);
987     datap=buffer+sizeof(salt)+sizeof(verify);
988     memset(counter, 0, sizeof(counter));
989 zoff99 50 while (esize > 0)
990     {
991 zoff99 2 int i,curr_size,idx=0;
992 zoff99 50 do
993     {
994 zoff99 2 counter[idx]++;
995 zoff99 50 }while (!counter[idx++]);
996    
997 zoff99 2 AES_encrypt(counter, xor, &aeskey);
998     curr_size=esize;
999     if (curr_size > sizeof(xor))
1000 zoff99 50 curr_size=sizeof(xor);
1001     for (i = 0; i < curr_size; i++)
1002     *datap++^=xor[i];
1003 zoff99 2 esize-=curr_size;
1004     }
1005     size-=overhead;
1006     datap=buffer+sizeof(salt)+sizeof(verify);
1007 zoff99 50 if (compressed)
1008     {
1009     if (uncompress_int(ret, &destLen, (Bytef *)datap, size) != Z_OK)
1010     {
1011     //dbg(0,"_uncompress failed\n");
1012 zoff99 2 g_free(ret);
1013     ret=NULL;
1014     }
1015 zoff99 50 }
1016     else
1017     {
1018     if (size == destLen)
1019     memcpy(ret, buffer, destLen);
1020     else
1021     {
1022     //dbg(0,"_memcpy failed\n");
1023 zoff99 2 g_free(ret);
1024     ret=NULL;
1025     }
1026     }
1027 zoff99 50 }
1028     else
1029     {
1030 zoff99 2 g_free(ret);
1031     ret=NULL;
1032     }
1033     }
1034     g_free(buffer);
1035    
1036     return ret;
1037     #else
1038     return NULL;
1039     #endif
1040     }
1041    
1042 zoff99 50 void file_data_free(struct file *file, unsigned char *data)
1043 zoff99 2 {
1044 zoff99 50 //dbg(0,"_enter %s\n", file->name);
1045     if (file->begin)
1046     {
1047 zoff99 2 if (data == file->begin)
1048     return;
1049     if (data >= file->begin && data < file->end)
1050     return;
1051     }
1052 zoff99 50
1053     if (file->cache && data)
1054     {
1055     // print statistics to DEBUG OUT
1056     //if (file_cache)
1057     //{
1058     //cache_stats(file_cache);
1059     //}
1060     // print statistics to DEBUG OUT
1061 zoff99 2 cache_entry_destroy(file_cache, data);
1062 zoff99 50 }
1063     else
1064     {
1065 zoff99 2 g_free(data);
1066 zoff99 50 }
1067     //dbg(0,"_leave\n");
1068 zoff99 2 }
1069    
1070 zoff99 50 void file_data_remove(struct file *file, unsigned char *data)
1071 zoff99 2 {
1072 zoff99 50 //dbg(0,"_enter %s\n", file->name);
1073     if (file->begin)
1074     {
1075 zoff99 2 if (data == file->begin)
1076 zoff99 50 {
1077 zoff99 2 return;
1078 zoff99 50 }
1079 zoff99 2 if (data >= file->begin && data < file->end)
1080 zoff99 50 {
1081 zoff99 2 return;
1082 zoff99 50 }
1083 zoff99 2 }
1084 zoff99 50 if (file->cache && data)
1085     {
1086 zoff99 2 cache_flush_data(file_cache, data);
1087 zoff99 50 }
1088     else
1089     {
1090 zoff99 2 g_free(data);
1091 zoff99 50 }
1092 zoff99 2 }
1093    
1094 zoff99 50 int file_exists(char const *name)
1095 zoff99 2 {
1096 zoff99 50 //dbg(0,"_enter %s\n", name);
1097 zoff99 2 struct stat buf;
1098 zoff99 50 if (!stat(name, &buf))
1099     {
1100 zoff99 2 return 1;
1101 zoff99 50 }
1102 zoff99 2 return 0;
1103     }
1104    
1105 zoff99 50 void file_remap_readonly(struct file *f)
1106 zoff99 2 {
1107 zoff99 50 //dbg(0,"_enter %s\n", f->name);
1108 zoff99 2 #if defined(_WIN32) || defined(__CEGCC__)
1109     #else
1110     void *begin;
1111     munmap(f->begin, f->size);
1112 zoff99 50 begin = mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
1113 zoff99 2 if (f->begin != begin)
1114 zoff99 50 {
1115 zoff99 2 printf("remap failed\n");
1116 zoff99 50 }
1117 zoff99 2 #endif
1118     }
1119    
1120 zoff99 50 void file_unmap(struct file *f)
1121 zoff99 2 {
1122 zoff99 50 //dbg(0,"_enter %s\n", f->name);
1123 zoff99 2 #if defined(_WIN32) || defined(__CEGCC__)
1124 zoff99 50 mmap_unmap_win32( f->begin, f->map_handle , f->map_file );
1125 zoff99 2 #else
1126     munmap(f->begin, f->size);
1127     #endif
1128     }
1129    
1130     #ifndef _MSC_VER
1131     void *
1132     file_opendir(char *dir)
1133     {
1134 zoff99 50 //dbg(0,"_enter %s\n", dir);
1135 zoff99 2 return opendir(dir);
1136     }
1137     #else
1138     void *
1139     file_opendir(char *dir)
1140     {
1141 zoff99 50 //dbg(0,"_enter %s\n", dir);
1142 zoff99 2 WIN32_FIND_DATAA FindFileData;
1143     HANDLE hFind = INVALID_HANDLE_VALUE;
1144     #undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string
1145     char* fname=g_alloca(sizeof(char)*(strlen(dir)+4));
1146     sprintf(fname,"%s\\*",dir);
1147     hFind = FindFirstFileA(fname, &FindFileData);
1148     return hFind;
1149     }
1150     #endif
1151    
1152     #ifndef _MSC_VER
1153     char *
1154     file_readdir(void *hnd)
1155     {
1156 zoff99 50 //dbg(0,"_enter\n");
1157 zoff99 2 struct dirent *ent;
1158    
1159 zoff99 50 ent = readdir(hnd);
1160     if (!ent)
1161 zoff99 2 return NULL;
1162     return ent->d_name;
1163     }
1164     #else
1165     char *
1166     file_readdir(void *hnd)
1167     {
1168 zoff99 50 //dbg(0,"_enter\n");
1169 zoff99 2 WIN32_FIND_DATA FindFileData;
1170    
1171 zoff99 50 if (FindNextFile(hnd, &FindFileData) )
1172     {
1173 zoff99 2 return FindFileData.cFileName;
1174 zoff99 50 }
1175     else
1176     {
1177 zoff99 2 return NULL;
1178     }
1179     }
1180     #endif /* _MSC_VER */
1181    
1182     #ifndef _MSC_VER
1183 zoff99 50 void file_closedir(void *hnd)
1184 zoff99 2 {
1185 zoff99 50 //dbg(0,"_enter\n");
1186 zoff99 2 closedir(hnd);
1187     }
1188     #else
1189     void
1190     file_closedir(void *hnd)
1191     {
1192 zoff99 50 //dbg(0,"_enter\n");
1193 zoff99 2 FindClose(hnd);
1194     }
1195     #endif /* _MSC_VER */
1196    
1197     struct file *
1198     file_create_caseinsensitive(char *name, struct attr **options)
1199     {
1200 zoff99 50 //dbg(0,"_enter %s\n", name);
1201     char *dirname = g_alloca(sizeof(char) * (strlen(name) + 1));
1202 zoff99 2 char *filename;
1203     char *p;
1204     void *d;
1205     struct file *ret;
1206    
1207 zoff99 50 ret = file_create(name, options);
1208 zoff99 2 if (ret)
1209 zoff99 50 {
1210 zoff99 2 return ret;
1211 zoff99 50 }
1212 zoff99 2
1213     strcpy(dirname, name);
1214 zoff99 50 p = dirname + strlen(name);
1215     while (p > dirname)
1216     {
1217 zoff99 2 if (*p == '/')
1218     break;
1219     p--;
1220     }
1221 zoff99 50 *p = 0;
1222     d = file_opendir(dirname);
1223     if (d)
1224     {
1225     *p++ = '/';
1226     while ((filename = file_readdir(d)))
1227     {
1228     if (!g_strcasecmp(filename, p))
1229     {
1230 zoff99 2 strcpy(p, filename);
1231 zoff99 50 ret = file_create(dirname, options);
1232 zoff99 2 if (ret)
1233     break;
1234     }
1235     }
1236     file_closedir(d);
1237     }
1238     return ret;
1239     }
1240    
1241 zoff99 50 void file_destroy(struct file *f)
1242 zoff99 2 {
1243 zoff99 50 dbg(0, "_enter %s\n", f->name);
1244    
1245     // print statistics to DEBUG OUT
1246     //if (file_cache)
1247     //{
1248     //cache_stats(file_cache);
1249     //}
1250     // print statistics to DEBUG OUT
1251    
1252 zoff99 2 if (f->headers)
1253 zoff99 50 {
1254 zoff99 2 g_hash_table_destroy(f->headers);
1255     }
1256 zoff99 50 switch (f->special)
1257     {
1258     case 0:
1259     case 1:
1260     close(f->fd);
1261     break;
1262     }
1263 zoff99 2
1264 zoff99 50 if (f->begin != NULL)
1265     {
1266     file_unmap(f);
1267     }
1268 zoff99 2
1269     g_free(f->buffer);
1270     g_free(f->name);
1271     g_free(f);
1272     }
1273    
1274 zoff99 50 struct file_wordexp
1275     {
1276 zoff99 2 int err;
1277 zoff99 50 char *pattern;
1278 zoff99 2 wordexp_t we;
1279     };
1280    
1281     struct file_wordexp *
1282     file_wordexp_new(const char *pattern)
1283     {
1284 zoff99 50 dbg(0, "_enter\n");
1285 zoff99 2 struct file_wordexp *ret=g_new0(struct file_wordexp, 1);
1286 zoff99 50 dbg(0, "fexp 001 p=%p\n", ret);
1287 zoff99 2
1288 zoff99 50 ret->pattern = g_strdup(pattern);
1289     dbg(0, "fexp 002 p=%p p2=%p, str1=%s, str2=%s\n", ret->pattern, pattern, ret->pattern, pattern);
1290     ret->err = wordexp(pattern, &ret->we, 0);
1291     dbg(0, "fexp 003\n");
1292 zoff99 2 if (ret->err)
1293 zoff99 50 {
1294     // dbg(0, "wordexp('%s') returned %d\n", pattern, ret->err);
1295     }
1296     dbg(0, "leave\n");
1297 zoff99 2 return ret;
1298     }
1299    
1300 zoff99 50 int file_wordexp_get_count(struct file_wordexp *wexp)
1301 zoff99 2 {
1302 zoff99 50 //dbg(0,"_enter\n");
1303    
1304     if (wexp->err)
1305     {
1306     return 1;
1307     }
1308 zoff99 2 return wexp->we.we_wordc;
1309     }
1310    
1311     char **
1312     file_wordexp_get_array(struct file_wordexp *wexp)
1313     {
1314 zoff99 50 //dbg(0,"_enter\n");
1315    
1316     if (wexp->err)
1317     {
1318     return &wexp->pattern;
1319     }
1320 zoff99 2 return wexp->we.we_wordv;
1321     }
1322    
1323 zoff99 50 void file_wordexp_destroy(struct file_wordexp *wexp)
1324 zoff99 2 {
1325 zoff99 50 //dbg(0,"_enter\n");
1326     if (!wexp->err)
1327     {
1328 zoff99 2 wordfree(&wexp->we);
1329 zoff99 50 }
1330     g_free(wexp->pattern);
1331 zoff99 2 g_free(wexp);
1332     }
1333    
1334 zoff99 50 int file_get_param(struct file *file, struct param_list *param, int count)
1335 zoff99 2 {
1336 zoff99 50 //dbg(0,"_enter %s\n", file->name);
1337     int i = count;
1338 zoff99 2 param_add_string("Filename", file->name, &param, &count);
1339     param_add_hex("Size", file->size, &param, &count);
1340 zoff99 50 return i - count;
1341 zoff99 2 }
1342    
1343 zoff99 50 int file_version(struct file *file, int mode)
1344 zoff99 2 {
1345 zoff99 50 //dbg(0,"_enter %s\n", file->name);
1346 zoff99 2 #ifndef HAVE_API_WIN32_BASE
1347     struct stat st;
1348     int error;
1349 zoff99 50 if (mode == 3)
1350     {
1351     long long size = lseek(file->fd, 0, SEEK_END);
1352     if (file->begin && file->begin + size > file->mmap_end)
1353     {
1354 zoff99 2 file->version++;
1355 zoff99 50 }
1356     else
1357     {
1358     file->size = size;
1359 zoff99 2 if (file->begin)
1360 zoff99 50 {
1361     file->end = file->begin + file->size;
1362     }
1363 zoff99 2 }
1364 zoff99 50 }
1365     else
1366     {
1367 zoff99 2 if (mode == 2)
1368 zoff99 50 {
1369     error = stat(file->name, &st);
1370     }
1371 zoff99 2 else
1372 zoff99 50 {
1373     error = fstat(file->fd, &st);
1374     }
1375     if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime)
1376     {
1377     file->mtime = st.st_mtime;
1378     file->ctime = st.st_ctime;
1379 zoff99 2 file->version++;
1380 zoff99 50 // dbg(1, "%s now version %d\n", file->name, file->version);
1381 zoff99 2 }
1382     }
1383     return file->version;
1384     #else
1385     return 0;
1386     #endif
1387     }
1388    
1389     void *
1390     file_get_os_handle(struct file *file)
1391     {
1392 zoff99 50 //dbg(0,"_enter %s\n", file->name);
1393 zoff99 2 return GINT_TO_POINTER(file->fd);
1394     }
1395    
1396 zoff99 50 void file_cache_init(void)
1397 zoff99 2 {
1398     #ifdef CACHE_SIZE
1399 zoff99 50 dbg(0,"enter\n");
1400     dbg(0,"_have 2 CACHE_SIZE=%d\n", CACHE_SIZE);
1401     dbg(0,"_have 2 cache_size_file=%d\n", cache_size_file);
1402     if (file_cache == NULL)
1403     {
1404     file_cache=cache_new(sizeof(struct file_cache_id), cache_size_file);
1405     dbg(0,"_file_cache created!\n");
1406     }
1407     dbg(0,"leave\n");
1408 zoff99 2 #endif
1409     }
1410    
1411 zoff99 50 void file_init(void)
1412 zoff99 29 {
1413 zoff99 50 #ifdef CACHE_SIZE
1414     dbg(0,"enter\n");
1415     //**// dbg(0,"_have 1 CACHE_SIZE=%d\n", CACHE_SIZE);
1416     //**// dbg(0,"_have 1 cache_size_file=%d\n", cache_size_file);
1417     file_name_hash=g_hash_table_new(g_str_hash, g_str_equal);
1418     // file_cache=cache_new(sizeof(struct file_cache_id), cache_size_file);
1419     file_cache = NULL; // set later!!
1420     dbg(0,"leave\n");
1421     #endif
1422 zoff99 29 }
1423    

   
Visit the ZANavi Wiki