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

Contents of /navit/navit/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (hide annotations) (download)
Mon Apr 9 21:27:36 2012 UTC (10 years, 9 months ago) by zoff99
File MIME type: text/plain
File size: 19203 byte(s)
lots of new stuff, tranlsations, bug fixes ...
1 zoff99 2 /**
2     * Navit, a modular navigation system.
3     * Copyright (C) 2005-2011 Navit Team
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     #define _FILE_OFFSET_BITS 64
21     #define _LARGEFILE_SOURCE
22     #define _LARGEFILE64_SOURCE
23     #include "config.h"
24     #ifdef HAVE_UNISTD_H
25     #include <unistd.h>
26     #endif
27     #ifdef _MSC_VER
28     #include <windows.h>
29     #else
30     #include <dirent.h>
31     #endif /* _MSC_VER */
32     #include <string.h>
33     #include <fcntl.h>
34     #include <sys/stat.h>
35     #include <sys/mman.h>
36     #include <stdio.h>
37     #include <stdlib.h>
38     #include <wordexp.h>
39     #include <glib.h>
40     #include <zlib.h>
41     #include "debug.h"
42     #include "cache.h"
43     #include "file.h"
44     #include "atom.h"
45     #include "item.h"
46     #include "util.h"
47     #include "types.h"
48     #ifdef HAVE_SOCKET
49     #include <sys/socket.h>
50     #include <netdb.h>
51     #endif
52    
53     extern char *version;
54    
55     #ifdef HAVE_LIBCRYPTO
56     #include <openssl/sha.h>
57     #include <openssl/hmac.h>
58     #include <openssl/aes.h>
59     #include <openssl/evp.h>
60     #include <openssl/rand.h>
61     #endif
62    
63     #ifdef HAVE_API_ANDROID
64     #define lseek lseek64
65     #endif
66    
67     #ifndef O_LARGEFILE
68     #define O_LARGEFILE 0
69     #endif
70    
71     #ifndef O_BINARY
72     #define O_BINARY 0
73     #endif
74    
75     #ifdef CACHE_SIZE
76     static GHashTable *file_name_hash;
77     #endif
78    
79     static struct cache *file_cache;
80    
81     #ifdef _MSC_VER
82     #pragma pack(push,1)
83     #endif /* _MSC_VER */
84     struct file_cache_id {
85     long long offset;
86     int size;
87     int file_name_id;
88     int method;
89     #ifndef _MSC_VER
90     }__attribute__ ((packed));
91     #else /* _MSC_VER */
92     };
93     #pragma pack(pop)
94     #endif /* _MSC_VER */
95    
96     #ifdef HAVE_SOCKET
97     static int
98     file_socket_connect(char *host, char *service)
99     {
100     struct addrinfo hints;
101     struct addrinfo *result, *rp;
102     int fd=-1,s;
103    
104     memset(&hints, 0, sizeof(struct addrinfo));
105     hints.ai_family = AF_UNSPEC;
106     hints.ai_socktype = SOCK_STREAM;
107     hints.ai_flags = 0;
108     hints.ai_protocol = 0;
109     s = getaddrinfo(host, service, &hints, &result);
110     if (s != 0) {
111     dbg(0,"getaddrinfo error %s\n",gai_strerror(s));
112     return -1;
113     }
114     for (rp = result; rp != NULL; rp = rp->ai_next) {
115     fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
116     if (fd != -1) {
117     if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
118     break;
119     close(fd);
120     fd=-1;
121     }
122     }
123     freeaddrinfo(result);
124     return fd;
125     }
126    
127     static void
128     file_http_request(struct file *file, char *method, char *host, char *path, char *header, int persistent)
129     {
130     char *request=g_strdup_printf("%s %s HTTP/1.0\r\nUser-Agent: navit %s\r\nHost: %s\r\n%s%s%s\r\n",method,path,version,host,persistent?"Connection: Keep-Alive\r\n":"",header?header:"",header?"\r\n":"");
131     write(file->fd, request, strlen(request));
132     dbg(1,"%s\n",request);
133     file->requests++;
134     }
135    
136     static int
137     file_request_do(struct file *file, struct attr **options, int connect)
138     {
139     struct attr *attr;
140     char *name;
141    
142     if (!options)
143     return 0;
144     attr=attr_search(options, NULL, attr_url);
145     if (!attr)
146     return 0;
147     name=attr->u.str;
148     if (!name)
149     return 0;
150     g_free(file->name);
151     file->name = g_strdup(name);
152     if (!strncmp(name,"http://",7)) {
153     char *host=g_strdup(name+7);
154     char *port=strchr(host,':');
155     char *path=strchr(name+7,'/');
156     char *method="GET";
157     char *header=NULL;
158     int persistent=0;
159     if ((attr=attr_search(options, NULL, attr_http_method)) && attr->u.str)
160     method=attr->u.str;
161     if ((attr=attr_search(options, NULL, attr_http_header)) && attr->u.str)
162     header=attr->u.str;
163     if ((attr=attr_search(options, NULL, attr_persistent)))
164     persistent=attr->u.num;
165     if (path)
166     host[path-name-7]='\0';
167     if (port)
168     *port++='\0';
169     dbg(1,"host=%s path=%s\n",host,path);
170     if (connect)
171     file->fd=file_socket_connect(host,port?port:"80");
172     file_http_request(file,method,host,path,header,persistent);
173     file->special=1;
174     g_free(host);
175     }
176     return 1;
177     }
178     #endif
179    
180     static unsigned char *
181     file_http_header_end(unsigned char *str, int len)
182     {
183     int i;
184     for (i=0; i+1<len; i+=2) {
185     if (str[i+1]=='\n') {
186     if (str[i]=='\n')
187     return str+i+2;
188     else if (str[i]=='\r' && i+3<len && str[i+2]=='\r' && str[i+3]=='\n')
189     return str+i+4;
190     --i;
191     } else if (str[i+1]=='\r') {
192     if (i+4<len && str[i+2]=='\n' && str[i+3]=='\r' && str[i+4]=='\n')
193     return str+i+5;
194     --i;
195     }
196     }
197     return NULL;
198     }
199    
200     int
201     file_request(struct file *f, struct attr **options)
202     {
203     #ifdef HAVE_SOCKET
204     return file_request_do(f, options, 0);
205     #else
206     return 0;
207     #endif
208     }
209    
210     char *
211     file_http_header(struct file *f, char *header)
212     {
213     if (!f->headers)
214     return NULL;
215     return g_hash_table_lookup(f->headers, header);
216     }
217    
218     struct file *
219     file_create(char *name, struct attr **options)
220     {
221     struct stat stat;
222     struct file *file= g_new0(struct file,1);
223     struct attr *attr;
224     int open_flags=O_LARGEFILE|O_BINARY;
225    
226     if (options && (attr=attr_search(options, NULL, attr_url))) {
227     #ifdef HAVE_SOCKET
228     file_request_do(file, options, 1);
229     #endif
230     } else {
231     if (options && (attr=attr_search(options, NULL, attr_readwrite)) && attr->u.num) {
232     open_flags |= O_RDWR;
233     if ((attr=attr_search(options, NULL, attr_create)) && attr->u.num)
234     open_flags |= O_CREAT;
235     } else
236     open_flags |= O_RDONLY;
237     file->name = g_strdup(name);
238     file->fd=open(name, open_flags, 0666);
239     if (file->fd == -1) {
240     g_free(file);
241     return NULL;
242     }
243     dbg(1,"fd=%d\n", file->fd);
244     fstat(file->fd, &stat);
245     file->size=stat.st_size;
246     dbg(1,"size="LONGLONG_FMT"\n", file->size);
247     file->name_id = (long)atom(name);
248     }
249     #ifdef CACHE_SIZE
250     if (!options || !(attr=attr_search(options, NULL, attr_cache)) || attr->u.num)
251     file->cache=1;
252     #endif
253     dbg_assert(file != NULL);
254     return file;
255     }
256    
257     #if 0
258     struct file *
259     file_create_url(char *url)
260     {
261     }
262     #endif
263    
264     #ifndef S_ISDIR
265     #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
266     #endif
267     #ifndef S_ISREG
268     #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
269     #endif
270    
271     int file_is_dir(char *name)
272     {
273     struct stat buf;
274     if (! stat(name, &buf)) {
275     return S_ISDIR(buf.st_mode);
276     }
277     return 0;
278    
279     }
280    
281     int file_is_reg(char *name)
282     {
283     struct stat buf;
284     if (! stat(name, &buf)) {
285     return S_ISREG(buf.st_mode);
286     }
287     return 0;
288     }
289    
290     long long
291     file_size(struct file *file)
292     {
293     return file->size;
294     }
295    
296     int file_mkdir(char *name, int pflag)
297     {
298     char *buffer=g_alloca(sizeof(char)*(strlen(name)+1));
299     int ret;
300     char *next;
301     dbg(1,"enter %s %d\n",name,pflag);
302     if (!pflag) {
303     if (file_is_dir(name))
304     return 0;
305     #if defined HAVE_API_WIN32_BASE || defined _MSC_VER
306     return mkdir(name);
307     #else
308     return mkdir(name, 0777);
309     #endif
310     }
311     strcpy(buffer, name);
312     next=buffer;
313     while ((next=strchr(next, '/'))) {
314     *next='\0';
315     if (*buffer) {
316     ret=file_mkdir(buffer, 0);
317     if (ret)
318     return ret;
319     }
320     *next++='/';
321     }
322     if (pflag == 2)
323     return 0;
324     return file_mkdir(buffer, 0);
325     }
326    
327     int
328     file_mmap(struct file *file)
329     {
330     #if 0
331     int mmap_size=file->size+1024*1024;
332     #else
333     int mmap_size=file->size;
334     #endif
335     #ifdef HAVE_API_WIN32_BASE
336     file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
337     #else
338     file->begin=mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0);
339     dbg_assert(file->begin != NULL);
340     if (file->begin == (void *)0xffffffff) {
341     perror("mmap");
342     return 0;
343     }
344     #endif
345     dbg_assert(file->begin != (void *)0xffffffff);
346     file->mmap_end=file->begin+mmap_size;
347     file->end=file->begin+file->size;
348    
349     return 1;
350     }
351    
352     unsigned char *
353     file_data_read(struct file *file, long long offset, int size)
354     {
355     void *ret;
356     if (file->special)
357     return NULL;
358     if (file->begin)
359     return file->begin+offset;
360     if (file_cache) {
361     struct file_cache_id id={offset,size,file->name_id,0};
362     ret=cache_lookup(file_cache,&id);
363     if (ret)
364     return ret;
365     ret=cache_insert_new(file_cache,&id,size);
366     } else
367     ret=g_malloc(size);
368     lseek(file->fd, offset, SEEK_SET);
369     if (read(file->fd, ret, size) != size) {
370     file_data_free(file, ret);
371     ret=NULL;
372     }
373     return ret;
374    
375     }
376    
377     static void
378     file_process_headers(struct file *file, unsigned char *headers)
379     {
380     char *tok;
381     char *cl;
382     if (file->headers)
383     g_hash_table_destroy(file->headers);
384     file->headers=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
385     while ((tok=strtok((char*)headers, "\r\n"))) {
386     char *sep;
387     tok=g_strdup(tok);
388     sep=strchr(tok,':');
389     if (!sep)
390     sep=strchr(tok,'/');
391     if (!sep) {
392     g_free(tok);
393     continue;
394     }
395     *sep++='\0';
396     if (*sep == ' ')
397     sep++;
398     strtolower(tok, tok);
399     dbg(1,"header '%s'='%s'\n",tok,sep);
400     g_hash_table_insert(file->headers, tok, sep);
401     headers=NULL;
402     }
403     cl=g_hash_table_lookup(file->headers, "content-length");
404     if (cl)
405     #ifdef HAVE__ATOI64
406     file->size=_atoi64(cl);
407     #else
408     file->size=atoll(cl);
409     #endif
410     }
411    
412     static void
413     file_shift_buffer(struct file *file, int amount)
414     {
415     memmove(file->buffer, file->buffer+amount, file->buffer_len-amount);
416     file->buffer_len-=amount;
417     }
418    
419     unsigned char *
420     file_data_read_special(struct file *file, int size, int *size_ret)
421     {
422     unsigned char *ret,*hdr;
423     int rets=0,rd;
424     int buffer_size=8192;
425     int eof=0;
426     if (!file->special)
427     return NULL;
428     if (!file->buffer)
429     file->buffer=g_malloc(buffer_size);
430     ret=g_malloc(size);
431     while ((size > 0 || file->requests) && (!eof || file->buffer_len)) {
432     int toread=buffer_size-file->buffer_len;
433     if (toread >= 4096 && !eof) {
434     if (!file->requests && toread > size)
435     toread=size;
436     rd=read(file->fd, file->buffer+file->buffer_len, toread);
437     if (rd > 0) {
438     file->buffer_len+=rd;
439     } else
440     eof=1;
441     }
442     if (file->requests) {
443     dbg(1,"checking header\n");
444     if ((hdr=file_http_header_end(file->buffer, file->buffer_len))) {
445     hdr[-1]='\0';
446     dbg(1,"found %s (%d bytes)\n",file->buffer,sizeof(file->buffer));
447     file_process_headers(file, file->buffer);
448     file_shift_buffer(file, hdr-file->buffer);
449     file->requests--;
450     if (file_http_header(file, "location"))
451     break;
452     }
453     }
454     if (!file->requests) {
455     rd=file->buffer_len;
456     if (rd > size)
457     rd=size;
458     memcpy(ret+rets, file->buffer, rd);
459     file_shift_buffer(file, rd);
460     rets+=rd;
461     size-=rd;
462     }
463     }
464     *size_ret=rets;
465     return ret;
466     }
467    
468     unsigned char *
469     file_data_read_all(struct file *file)
470     {
471     return file_data_read(file, 0, file->size);
472     }
473    
474     void
475     file_data_flush(struct file *file, long long offset, int size)
476     {
477     if (file_cache) {
478     struct file_cache_id id={offset,size,file->name_id,0};
479     cache_flush(file_cache,&id);
480     dbg(1,"Flushing "LONGLONG_FMT" %d bytes\n",offset,size);
481     }
482     }
483    
484     int
485     file_data_write(struct file *file, long long offset, int size, unsigned char *data)
486     {
487     file_data_flush(file, offset, size);
488     lseek(file->fd, offset, SEEK_SET);
489     if (write(file->fd, data, size) != size)
490     return 0;
491     if (file->size < offset+size)
492     file->size=offset+size;
493     return 1;
494     }
495    
496     int
497     file_get_contents(char *name, unsigned char **buffer, int *size)
498     {
499     struct file *file;
500     file=file_create(name, 0);
501     if (!file)
502     return 0;
503     *size=file_size(file);
504     *buffer=file_data_read_all(file);
505     file_destroy(file);
506     return 1;
507     }
508    
509    
510     static int
511     uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
512     {
513     z_stream stream;
514     int err;
515    
516     stream.next_in = (Bytef*)source;
517     stream.avail_in = (uInt)sourceLen;
518     stream.next_out = dest;
519     stream.avail_out = (uInt)*destLen;
520    
521     stream.zalloc = (alloc_func)0;
522     stream.zfree = (free_func)0;
523    
524     err = inflateInit2(&stream, -MAX_WBITS);
525     if (err != Z_OK) return err;
526    
527     err = inflate(&stream, Z_FINISH);
528     if (err != Z_STREAM_END) {
529     inflateEnd(&stream);
530     if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
531     return Z_DATA_ERROR;
532     return err;
533     }
534     *destLen = stream.total_out;
535    
536     err = inflateEnd(&stream);
537     return err;
538     }
539    
540     unsigned char *
541     file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp)
542     {
543     void *ret;
544     char *buffer = 0;
545     uLongf destLen=size_uncomp;
546    
547     if (file_cache) {
548     struct file_cache_id id={offset,size,file->name_id,1};
549     ret=cache_lookup(file_cache,&id);
550     if (ret)
551     return ret;
552     ret=cache_insert_new(file_cache,&id,size_uncomp);
553     } else
554     ret=g_malloc(size_uncomp);
555     lseek(file->fd, offset, SEEK_SET);
556    
557     buffer = (char *)g_malloc(size);
558     if (read(file->fd, buffer, size) != size) {
559     g_free(ret);
560     ret=NULL;
561     } else {
562     if (uncompress_int(ret, &destLen, (Bytef *)buffer, size) != Z_OK) {
563     dbg(0,"uncompress failed\n");
564     g_free(ret);
565     ret=NULL;
566     }
567     }
568     g_free(buffer);
569    
570     return ret;
571     }
572    
573     unsigned char *
574     file_data_read_encrypted(struct file *file, long long offset, int size, int size_uncomp, int compressed, char *passwd)
575     {
576     #ifdef HAVE_LIBCRYPTO
577     void *ret;
578     unsigned char *buffer = 0;
579     uLongf destLen=size_uncomp;
580    
581     if (file_cache) {
582     struct file_cache_id id={offset,size,file->name_id,1};
583     ret=cache_lookup(file_cache,&id);
584     if (ret)
585     return ret;
586     ret=cache_insert_new(file_cache,&id,size_uncomp);
587     } else
588     ret=g_malloc(size_uncomp);
589     lseek(file->fd, offset, SEEK_SET);
590    
591     buffer = (unsigned char *)g_malloc(size);
592     if (read(file->fd, buffer, size) != size) {
593     g_free(ret);
594     ret=NULL;
595     } else {
596     unsigned char key[34], salt[8], verify[2], counter[16], xor[16], mac[10], *datap;
597     int overhead=sizeof(salt)+sizeof(verify)+sizeof(mac);
598     int esize=size-overhead;
599     PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), (unsigned char *)buffer, 8, 1000, 34, key);
600     if (key[32] == buffer[8] && key[33] == buffer[9] && esize >= 0) {
601     AES_KEY aeskey;
602     AES_set_encrypt_key(key, 128, &aeskey);
603     datap=buffer+sizeof(salt)+sizeof(verify);
604     memset(counter, 0, sizeof(counter));
605     while (esize > 0) {
606     int i,curr_size,idx=0;
607     do {
608     counter[idx]++;
609     } while (!counter[idx++]);
610     AES_encrypt(counter, xor, &aeskey);
611     curr_size=esize;
612     if (curr_size > sizeof(xor))
613     curr_size=sizeof(xor);
614     for (i = 0 ; i < curr_size ; i++)
615     *datap++^=xor[i];
616     esize-=curr_size;
617     }
618     size-=overhead;
619     datap=buffer+sizeof(salt)+sizeof(verify);
620     if (compressed) {
621     if (uncompress_int(ret, &destLen, (Bytef *)datap, size) != Z_OK) {
622     dbg(0,"uncompress failed\n");
623     g_free(ret);
624     ret=NULL;
625     }
626     } else {
627     if (size == destLen)
628     memcpy(ret, buffer, destLen);
629     else {
630     dbg(0,"memcpy failed\n");
631     g_free(ret);
632     ret=NULL;
633     }
634     }
635     } else {
636     g_free(ret);
637     ret=NULL;
638     }
639     }
640     g_free(buffer);
641    
642     return ret;
643     #else
644     return NULL;
645     #endif
646     }
647    
648     void
649     file_data_free(struct file *file, unsigned char *data)
650     {
651     if (file->begin) {
652     if (data == file->begin)
653     return;
654     if (data >= file->begin && data < file->end)
655     return;
656     }
657     if (file->cache && data) {
658     cache_entry_destroy(file_cache, data);
659     } else
660     g_free(data);
661     }
662    
663     void
664     file_data_remove(struct file *file, unsigned char *data)
665     {
666     if (file->begin) {
667     if (data == file->begin)
668     return;
669     if (data >= file->begin && data < file->end)
670     return;
671     }
672     if (file->cache && data) {
673     cache_flush_data(file_cache, data);
674     } else
675     g_free(data);
676     }
677    
678     int
679     file_exists(char const *name)
680     {
681     struct stat buf;
682     if (! stat(name, &buf))
683     return 1;
684     return 0;
685     }
686    
687     void
688     file_remap_readonly(struct file *f)
689     {
690     #if defined(_WIN32) || defined(__CEGCC__)
691     #else
692     void *begin;
693     munmap(f->begin, f->size);
694     begin=mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
695     if (f->begin != begin)
696     printf("remap failed\n");
697     #endif
698     }
699    
700     void
701     file_unmap(struct file *f)
702     {
703     #if defined(_WIN32) || defined(__CEGCC__)
704     mmap_unmap_win32( f->begin, f->map_handle , f->map_file );
705     #else
706     munmap(f->begin, f->size);
707     #endif
708     }
709    
710     #ifndef _MSC_VER
711     void *
712     file_opendir(char *dir)
713     {
714     return opendir(dir);
715     }
716     #else
717     void *
718     file_opendir(char *dir)
719     {
720     WIN32_FIND_DATAA FindFileData;
721     HANDLE hFind = INVALID_HANDLE_VALUE;
722     #undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string
723     char* fname=g_alloca(sizeof(char)*(strlen(dir)+4));
724     sprintf(fname,"%s\\*",dir);
725     hFind = FindFirstFileA(fname, &FindFileData);
726     return hFind;
727     }
728     #endif
729    
730     #ifndef _MSC_VER
731     char *
732     file_readdir(void *hnd)
733     {
734     struct dirent *ent;
735    
736     ent=readdir(hnd);
737     if (! ent)
738     return NULL;
739     return ent->d_name;
740     }
741     #else
742     char *
743     file_readdir(void *hnd)
744     {
745     WIN32_FIND_DATA FindFileData;
746    
747     if (FindNextFile(hnd, &FindFileData) ) {
748     return FindFileData.cFileName;
749     } else {
750     return NULL;
751     }
752     }
753     #endif /* _MSC_VER */
754    
755     #ifndef _MSC_VER
756     void
757     file_closedir(void *hnd)
758     {
759     closedir(hnd);
760     }
761     #else
762     void
763     file_closedir(void *hnd)
764     {
765     FindClose(hnd);
766     }
767     #endif /* _MSC_VER */
768    
769     struct file *
770     file_create_caseinsensitive(char *name, struct attr **options)
771     {
772     char *dirname=g_alloca(sizeof(char)*(strlen(name)+1));
773     char *filename;
774     char *p;
775     void *d;
776     struct file *ret;
777    
778     ret=file_create(name, options);
779     if (ret)
780     return ret;
781    
782     strcpy(dirname, name);
783     p=dirname+strlen(name);
784     while (p > dirname) {
785     if (*p == '/')
786     break;
787     p--;
788     }
789     *p=0;
790     d=file_opendir(dirname);
791     if (d) {
792     *p++='/';
793     while ((filename=file_readdir(d))) {
794     if (!g_strcasecmp(filename, p)) {
795     strcpy(p, filename);
796     ret=file_create(dirname, options);
797     if (ret)
798     break;
799     }
800     }
801     file_closedir(d);
802     }
803     return ret;
804     }
805    
806     void
807     file_destroy(struct file *f)
808     {
809     if (f->headers)
810     g_hash_table_destroy(f->headers);
811     switch (f->special) {
812     case 0:
813     case 1:
814     close(f->fd);
815     break;
816     }
817    
818     if ( f->begin != NULL )
819     {
820     file_unmap( f );
821     }
822    
823     g_free(f->buffer);
824     g_free(f->name);
825     g_free(f);
826     }
827    
828     struct file_wordexp {
829     int err;
830     wordexp_t we;
831     };
832    
833     struct file_wordexp *
834     file_wordexp_new(const char *pattern)
835     {
836     struct file_wordexp *ret=g_new0(struct file_wordexp, 1);
837    
838     ret->err=wordexp(pattern, &ret->we, 0);
839     if (ret->err)
840     dbg(0,"wordexp('%s') returned %d\n", pattern, ret->err);
841     return ret;
842     }
843    
844     int
845     file_wordexp_get_count(struct file_wordexp *wexp)
846     {
847     return wexp->we.we_wordc;
848     }
849    
850     char **
851     file_wordexp_get_array(struct file_wordexp *wexp)
852     {
853     return wexp->we.we_wordv;
854     }
855    
856     void
857     file_wordexp_destroy(struct file_wordexp *wexp)
858     {
859     if (! wexp->err)
860     wordfree(&wexp->we);
861     g_free(wexp);
862     }
863    
864    
865     int
866     file_get_param(struct file *file, struct param_list *param, int count)
867     {
868     int i=count;
869     param_add_string("Filename", file->name, &param, &count);
870     param_add_hex("Size", file->size, &param, &count);
871     return i-count;
872     }
873    
874     int
875     file_version(struct file *file, int mode)
876     {
877     #ifndef HAVE_API_WIN32_BASE
878     struct stat st;
879     int error;
880     if (mode == 3) {
881     long long size=lseek(file->fd, 0, SEEK_END);
882     if (file->begin && file->begin+size > file->mmap_end) {
883     file->version++;
884     } else {
885     file->size=size;
886     if (file->begin)
887     file->end=file->begin+file->size;
888     }
889     } else {
890     if (mode == 2)
891     error=stat(file->name, &st);
892     else
893     error=fstat(file->fd, &st);
894     if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime) {
895     file->mtime=st.st_mtime;
896     file->ctime=st.st_ctime;
897     file->version++;
898     dbg(1,"%s now version %d\n", file->name, file->version);
899     }
900     }
901     return file->version;
902     #else
903     return 0;
904     #endif
905     }
906    
907     void *
908     file_get_os_handle(struct file *file)
909     {
910     return GINT_TO_POINTER(file->fd);
911     }
912    
913     void
914     file_init(void)
915     {
916     #ifdef CACHE_SIZE
917     file_name_hash=g_hash_table_new(g_str_hash, g_str_equal);
918     file_cache=cache_new(sizeof(struct file_cache_id), CACHE_SIZE);
919     #endif
920     }
921    

   
Visit the ZANavi Wiki