2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
20 #define _FILE_OFFSET_BITS 64
21 #define _LARGEFILE_SOURCE
22 #define _LARGEFILE64_SOURCE
48 static GHashTable *file_name_hash;
51 static struct cache *file_cache;
53 struct file_cache_id {
58 } __attribute__ ((packed));
61 file_create(char *name, enum file_flags flags)
64 struct file *file= g_new0(struct file,1);
66 file->fd=open(name, O_RDONLY|O_LARGEFILE | O_BINARY);
71 dbg(1,"fd=%d\n", file->fd);
72 fstat(file->fd, &stat);
73 file->size=stat.st_size;
74 dbg(1,"size=%Ld\n", file->size);
75 file->name = g_strdup(name);
76 file->name_id = (int)atom(name);
77 if (file_cache && !(flags & file_flag_nocache))
79 dbg_assert(file != NULL);
85 file_create_url(char *url)
87 struct file *file= g_new0(struct file,1);
88 char *cmd=g_strdup_printf("curl %s",url);
89 file->name = g_strdup(url);
90 file->stdfile=popen(cmd,"r");
91 file->fd=fileno(file->stdfile);
98 int file_is_dir(char *name)
101 if (! stat(name, &buf)) {
102 return S_ISDIR(buf.st_mode);
109 file_size(struct file *file)
114 int file_mkdir(char *name, int pflag)
116 char buffer[strlen(name)+1];
119 dbg(1,"enter %s %d\n",name,pflag);
121 if (file_is_dir(name))
123 #ifdef HAVE_API_WIN32_BASE
126 return mkdir(name, 0777);
129 strcpy(buffer, name);
131 while ((next=strchr(next, '/'))) {
134 ret=file_mkdir(buffer, 0);
142 return file_mkdir(buffer, 0);
146 file_mmap(struct file *file)
149 int mmap_size=file->size+1024*1024;
151 int mmap_size=file->size;
153 #ifdef HAVE_API_WIN32_BASE
154 file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
156 file->begin=mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0);
157 dbg_assert(file->begin != NULL);
158 if (file->begin == (void *)0xffffffff) {
163 dbg_assert(file->begin != (void *)0xffffffff);
164 file->mmap_end=file->begin+mmap_size;
165 file->end=file->begin+file->size;
171 file_data_read(struct file *file, long long offset, int size)
177 return file->begin+offset;
179 struct file_cache_id id={offset,size,file->name_id,0};
180 ret=cache_lookup(file_cache,&id);
183 ret=cache_insert_new(file_cache,&id,size);
186 lseek(file->fd, offset, SEEK_SET);
187 if (read(file->fd, ret, size) != size) {
188 file_data_free(file, ret);
196 file_data_read_special(struct file *file, int size, int *size_ret)
202 *size_ret=read(file->fd, ret, size);
207 file_data_read_all(struct file *file)
209 return file_data_read(file, 0, file->size);
213 file_data_write(struct file *file, long long offset, int size, unsigned char *data)
216 struct file_cache_id id={offset,size,file->name_id,0};
217 cache_flush(file_cache,&id);
219 lseek(file->fd, offset, SEEK_SET);
220 if (write(file->fd, data, size) != size)
222 if (file->size < offset+size)
223 file->size=offset+size;
228 file_get_contents(char *name, unsigned char **buffer, int *size)
231 file=file_create(name, 0);
234 *size=file_size(file);
235 *buffer=file_data_read_all(file);
242 uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
247 stream.next_in = (Bytef*)source;
248 stream.avail_in = (uInt)sourceLen;
249 stream.next_out = dest;
250 stream.avail_out = (uInt)*destLen;
252 stream.zalloc = (alloc_func)0;
253 stream.zfree = (free_func)0;
255 err = inflateInit2(&stream, -MAX_WBITS);
256 if (err != Z_OK) return err;
258 err = inflate(&stream, Z_FINISH);
259 if (err != Z_STREAM_END) {
261 if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
265 *destLen = stream.total_out;
267 err = inflateEnd(&stream);
272 file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp)
276 uLongf destLen=size_uncomp;
279 struct file_cache_id id={offset,size,file->name_id,1};
280 ret=cache_lookup(file_cache,&id);
283 ret=cache_insert_new(file_cache,&id,size_uncomp);
285 ret=g_malloc(size_uncomp);
286 lseek(file->fd, offset, SEEK_SET);
288 buffer = (char *)g_malloc(size);
289 if (read(file->fd, buffer, size) != size) {
293 if (uncompress_int(ret, &destLen, (Bytef *)buffer, size) != Z_OK) {
294 dbg(0,"uncompress failed\n");
305 file_data_free(struct file *file, unsigned char *data)
308 if (data == file->begin)
310 if (data >= file->begin && data < file->end)
313 if (file->cache && data) {
314 cache_entry_destroy(file_cache, data);
320 file_exists(char *name)
323 if (! stat(name, &buf))
329 file_remap_readonly(struct file *f)
331 #if defined(_WIN32) || defined(__CEGCC__)
334 munmap(f->begin, f->size);
335 begin=mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
336 if (f->begin != begin)
337 printf("remap failed\n");
342 file_unmap(struct file *f)
344 #if defined(_WIN32) || defined(__CEGCC__)
345 mmap_unmap_win32( f->begin, f->map_handle , f->map_file );
347 munmap(f->begin, f->size);
352 file_opendir(char *dir)
358 file_readdir(void *hnd)
369 file_closedir(void *hnd)
375 file_create_caseinsensitive(char *name, enum file_flags flags)
377 char dirname[strlen(name)+1];
383 ret=file_create(name, flags);
387 strcpy(dirname, name);
388 p=dirname+strlen(name);
389 while (p > dirname) {
395 d=file_opendir(dirname);
398 while ((filename=file_readdir(d))) {
399 if (!strcasecmp(filename, p)) {
401 ret=file_create(dirname, flags);
412 file_destroy(struct file *f)
414 switch (f->special) {
425 if ( f->begin != NULL )
434 struct file_wordexp {
439 struct file_wordexp *
440 file_wordexp_new(const char *pattern)
442 struct file_wordexp *ret=g_new0(struct file_wordexp, 1);
444 ret->err=wordexp(pattern, &ret->we, 0);
446 dbg(0,"wordexp('%s') returned %d\n", pattern, ret->err);
451 file_wordexp_get_count(struct file_wordexp *wexp)
453 return wexp->we.we_wordc;
457 file_wordexp_get_array(struct file_wordexp *wexp)
459 return wexp->we.we_wordv;
463 file_wordexp_destroy(struct file_wordexp *wexp)
472 file_get_param(struct file *file, struct param_list *param, int count)
475 param_add_string("Filename", file->name, ¶m, &count);
476 param_add_hex("Size", file->size, ¶m, &count);
481 file_version(struct file *file, int mode)
483 #ifndef HAVE_API_WIN32_BASE
487 long long size=lseek(file->fd, 0, SEEK_END);
488 if (file->begin && file->begin+size > file->mmap_end) {
493 file->end=file->begin+file->size;
497 error=stat(file->name, &st);
499 error=fstat(file->fd, &st);
500 if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime) {
501 file->mtime=st.st_mtime;
502 file->ctime=st.st_ctime;
504 dbg(1,"%s now version %d\n", file->name, file->version);
507 return file->version;
514 file_get_os_handle(struct file *file)
516 return GINT_TO_POINTER(file->fd);
523 file_name_hash=g_hash_table_new(g_str_hash, g_str_equal);
524 file_cache=cache_new(sizeof(struct file_cache_id), CACHE_SIZE);