Fix:maptool:Another name for faroe islands
[navit-package] / navit / file.c
index a17ed4c..b41d269 100644 (file)
@@ -33,6 +33,7 @@
 #include "debug.h"
 #include "cache.h"
 #include "file.h"
+#include "atom.h"
 #include "config.h"
 
 #ifndef O_LARGEFILE
 #define O_BINARY 0
 #endif
 
+#ifdef CACHE_SIZE
 static GHashTable *file_name_hash;
-static int file_name_id;
+#endif
+
 static struct cache *file_cache;
 
 struct file_cache_id {
@@ -52,28 +55,46 @@ struct file_cache_id {
        int size;
        int file_name_id;
        int method;
-};
+} __attribute__ ((packed));
 
 struct file *
-file_create(char *name)
+file_create(char *name, enum file_flags flags)
 {
        struct stat stat;
        struct file *file= g_new0(struct file,1);
 
-       if (! file)
-               return file;
        file->fd=open(name, O_RDONLY|O_LARGEFILE | O_BINARY);
-       if (file->fd < 0) {
+       if (file->fd == -1) {
                g_free(file);
                return NULL;
        }
+       dbg(1,"fd=%d\n", file->fd);
        fstat(file->fd, &stat);
        file->size=stat.st_size;
+       dbg(1,"size=%Ld\n", file->size);
        file->name = g_strdup(name);
+       file->name_id = (int)atom(name);
+       if (file_cache && !(flags & file_flag_nocache)) 
+               file->cache=1;
        dbg_assert(file != NULL);
        return file;
 }
 
+#if 0
+struct file *
+file_create_url(char *url)
+{
+       struct file *file= g_new0(struct file,1);
+       char *cmd=g_strdup_printf("curl %s",url);
+       file->name = g_strdup(url);
+       file->stdfile=popen(cmd,"r");
+       file->fd=fileno(file->stdfile);
+       file->special=1;
+       g_free(cmd);
+       return file;
+}
+#endif
+
 int file_is_dir(char *name)
 {
        struct stat buf;
@@ -84,6 +105,12 @@ int file_is_dir(char *name)
 
 }
 
+long long
+file_size(struct file *file)
+{
+       return file->size;
+}
+
 int file_mkdir(char *name, int pflag)
 {
        char buffer[strlen(name)+1];
@@ -93,7 +120,11 @@ int file_mkdir(char *name, int pflag)
        if (!pflag) {
                if (file_is_dir(name))
                        return 0;
+#ifdef HAVE_API_WIN32_BASE
+               return mkdir(name);
+#else
                return mkdir(name, 0777);
+#endif
        }
        strcpy(buffer, name);
        next=buffer;
@@ -114,10 +145,15 @@ int file_mkdir(char *name, int pflag)
 int
 file_mmap(struct file *file)
 {
-#if defined(_WIN32) || defined(__CEGCC__)
-    file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
+#if 0
+       int mmap_size=file->size+1024*1024;
+#else
+       int mmap_size=file->size;
+#endif
+#ifdef HAVE_API_WIN32_BASE
+       file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
 #else
-       file->begin=mmap(NULL, file->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0);
+       file->begin=mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0);
        dbg_assert(file->begin != NULL);
        if (file->begin == (void *)0xffffffff) {
                perror("mmap");
@@ -125,6 +161,7 @@ file_mmap(struct file *file)
        }
 #endif
        dbg_assert(file->begin != (void *)0xffffffff);
+       file->mmap_end=file->begin+mmap_size;
        file->end=file->begin+file->size;
 
        return 1;
@@ -134,6 +171,8 @@ unsigned char *
 file_data_read(struct file *file, long long offset, int size)
 {
        void *ret;
+       if (file->special)
+               return NULL;
        if (file->begin)
                return file->begin+offset;
        if (file_cache) {
@@ -153,6 +192,52 @@ file_data_read(struct file *file, long long offset, int size)
 
 }
 
+unsigned char *
+file_data_read_special(struct file *file, int size, int *size_ret)
+{
+       void *ret;
+       if (!file->special)
+               return NULL;
+       ret=g_malloc(size);
+       *size_ret=read(file->fd, ret, size);
+       return ret;
+}
+
+unsigned char *
+file_data_read_all(struct file *file)
+{
+       return file_data_read(file, 0, file->size);
+}
+
+int
+file_data_write(struct file *file, long long offset, int size, unsigned char *data)
+{
+       if (file_cache) {
+               struct file_cache_id id={offset,size,file->name_id,0};
+               cache_flush(file_cache,&id);
+       }
+       lseek(file->fd, offset, SEEK_SET);
+       if (write(file->fd, data, size) != size)
+               return 0;
+       if (file->size < offset+size)
+               file->size=offset+size;
+       return 1;
+}
+
+int
+file_get_contents(char *name, unsigned char **buffer, int *size)
+{
+       struct file *file;
+       file=file_create(name, 0);
+       if (!file)
+               return 0;
+       *size=file_size(file);
+       *buffer=file_data_read_all(file);
+       file_destroy(file);
+       return 1;       
+}
+
+
 static int
 uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
 {
@@ -187,7 +272,7 @@ unsigned char *
 file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp)
 {
        void *ret;
-       char buffer[size];
+       char *buffer = 0;
        uLongf destLen=size_uncomp;
 
        if (file_cache) {
@@ -199,6 +284,8 @@ file_data_read_compressed(struct file *file, long long offset, int size, int siz
        } else 
                ret=g_malloc(size_uncomp);
        lseek(file->fd, offset, SEEK_SET);
+
+       buffer = (char *)g_malloc(size);
        if (read(file->fd, buffer, size) != size) {
                g_free(ret);
                ret=NULL;
@@ -209,15 +296,21 @@ file_data_read_compressed(struct file *file, long long offset, int size, int siz
                        ret=NULL;
                }
        }
+       g_free(buffer);
+
        return ret;
 }
 
 void
 file_data_free(struct file *file, unsigned char *data)
 {
-       if (file->begin && data >= file->begin && data < file->end)
-               return;
-       if (file_cache) {
+       if (file->begin) {
+               if (data == file->begin)
+                       return;
+               if (data >= file->begin && data < file->end)
+                       return;
+       }       
+       if (file->cache && data) {
                cache_entry_destroy(file_cache, data);
        } else
                g_free(data);
@@ -279,7 +372,7 @@ file_closedir(void *hnd)
 }
 
 struct file *
-file_create_caseinsensitive(char *name)
+file_create_caseinsensitive(char *name, enum file_flags flags)
 {
        char dirname[strlen(name)+1];
        char *filename;
@@ -287,7 +380,7 @@ file_create_caseinsensitive(char *name)
        void *d;
        struct file *ret;
 
-       ret=file_create(name);
+       ret=file_create(name, flags);
        if (ret)
                return ret;
 
@@ -305,7 +398,7 @@ file_create_caseinsensitive(char *name)
                while ((filename=file_readdir(d))) {
                        if (!strcasecmp(filename, p)) {
                                strcpy(p, filename);
-                               ret=file_create(dirname);
+                               ret=file_create(dirname, flags);
                                if (ret)
                                        break;
                        }
@@ -318,7 +411,16 @@ file_create_caseinsensitive(char *name)
 void
 file_destroy(struct file *f)
 {
-       close(f->fd);
+       switch (f->special) {
+       case 0:
+               close(f->fd);
+               break;
+#if 0
+       case 1:
+               pclose(f->stdfile);
+               break;
+#endif
+       }
 
     if ( f->begin != NULL )
     {
@@ -376,20 +478,31 @@ file_get_param(struct file *file, struct param_list *param, int count)
 }
 
 int
-file_version(struct file *file, int byname)
+file_version(struct file *file, int mode)
 {
-#ifndef __CEGCC__
+#ifndef HAVE_API_WIN32_BASE
        struct stat st;
        int error;
-       if (byname)
-               error=stat(file->name, &st);
-       else
-               error=fstat(file->fd, &st);
-       if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime) {
-               file->mtime=st.st_mtime;
-               file->ctime=st.st_ctime;
-               file->version++;
-               dbg(0,"%s now version %d\n", file->name, file->version);
+       if (mode == 3) {
+               long long size=lseek(file->fd, 0, SEEK_END);
+               if (file->begin && file->begin+size > file->mmap_end) {
+                       file->version++;
+               } else {
+                       file->size=size;
+                       if (file->begin)
+                               file->end=file->begin+file->size;
+               }
+       } else {
+               if (mode == 2)
+                       error=stat(file->name, &st);
+               else
+                       error=fstat(file->fd, &st);
+               if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime) {
+                       file->mtime=st.st_mtime;
+                       file->ctime=st.st_ctime;
+                       file->version++;
+                       dbg(1,"%s now version %d\n", file->name, file->version);
+               }
        }
        return file->version;
 #else
@@ -397,12 +510,18 @@ file_version(struct file *file, int byname)
 #endif
 }
 
+void *
+file_get_os_handle(struct file *file)
+{
+       return GINT_TO_POINTER(file->fd);
+}
+
 void
 file_init(void)
 {
-#if 0
+#ifdef CACHE_SIZE
        file_name_hash=g_hash_table_new(g_str_hash, g_str_equal);
-       file_cache=cache_new(sizeof(struct file_cache_id), 2*1024*1024);
+       file_cache=cache_new(sizeof(struct file_cache_id), CACHE_SIZE);
 #endif
 }