Fix:Core:Renamed src to navit for cleanup of includes
[navit-package] / navit / file.c
1 #define _FILE_OFFSET_BITS 64
2 #define _LARGEFILE_SOURCE
3 #define _LARGEFILE64_SOURCE
4 #include <unistd.h>
5 #include <string.h>
6 #include <fcntl.h>
7 #include <sys/stat.h>
8 #include <sys/mman.h>
9 #include <dirent.h>
10 #include <stdio.h>
11 #include <wordexp.h>
12 #include <glib.h>
13 #include <zlib.h>
14 #include "debug.h"
15 #include "file.h"
16 #include "config.h"
17
18 #ifndef O_LARGEFILE
19 #define O_LARGEFILE 0
20 #endif
21
22 #ifndef O_BINARY
23 #define O_BINARY 0
24 #endif
25
26 static struct file *file_list;
27
28 struct file *
29 file_create(char *name)
30 {
31         struct stat stat;
32         struct file *file= g_new0(struct file,1);
33
34         if (! file)
35                 return file;
36         file->fd=open(name, O_RDONLY|O_LARGEFILE | O_BINARY);
37         if (file->fd < 0) {
38                 g_free(file);
39                 return NULL;
40         }
41         fstat(file->fd, &stat);
42         file->size=stat.st_size;
43         file->name = g_strdup(name);
44         g_assert(file != NULL);
45         file->next=file_list;
46         file_list=file;
47         return file;
48 }
49
50 int
51 file_mmap(struct file *file)
52 {
53 #ifdef _WIN32
54     file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
55 #else
56         file->begin=mmap(NULL, file->size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0);
57         g_assert(file->begin != NULL);
58         if (file->begin == (void *)0xffffffff) {
59                 perror("mmap");
60                 return 0;
61         }
62 #endif
63         g_assert(file->begin != (void *)0xffffffff);
64         file->end=file->begin+file->size;
65
66         return 1;
67 }
68
69 unsigned char *
70 file_data_read(struct file *file, long long offset, int size)
71 {
72         void *ret;
73         if (file->begin)
74                 return file->begin+offset;
75         ret=g_malloc(size);
76         lseek(file->fd, offset, SEEK_SET);
77         if (read(file->fd, ret, size) != size) {
78                 g_free(ret);
79                 ret=NULL;
80         }
81         return ret;
82
83 }
84
85 static int
86 uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
87 {
88         z_stream stream;
89         int err;
90
91         stream.next_in = (Bytef*)source;
92         stream.avail_in = (uInt)sourceLen;
93         stream.next_out = dest;
94         stream.avail_out = (uInt)*destLen;
95
96         stream.zalloc = (alloc_func)0;
97         stream.zfree = (free_func)0;
98
99         err = inflateInit2(&stream, -MAX_WBITS);
100         if (err != Z_OK) return err;
101
102         err = inflate(&stream, Z_FINISH);
103         if (err != Z_STREAM_END) {
104         inflateEnd(&stream);
105         if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
106                 return Z_DATA_ERROR;
107                 return err;
108         }
109         *destLen = stream.total_out;
110
111         err = inflateEnd(&stream);
112         return err;
113 }
114
115 unsigned char *
116 file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp)
117 {
118         void *ret;
119         char buffer[size];
120         uLongf destLen=size_uncomp;
121
122         ret=g_malloc(size_uncomp);
123         lseek(file->fd, offset, SEEK_SET);
124         if (read(file->fd, buffer, size) != size) {
125                 g_free(ret);
126                 ret=NULL;
127         } else {
128                 if (uncompress_int(ret, &destLen, (Bytef *)buffer, size) != Z_OK) {
129                         dbg(0,"uncompress failed\n");
130                         g_free(ret);
131                         ret=NULL;
132                 }
133         }
134         return ret;
135 }
136
137 void
138 file_data_free(struct file *file, unsigned char *data)
139 {
140         if (file->begin && data >= file->begin && data < file->end)
141                 return;
142         g_free(data);
143 }
144
145 int
146 file_exists(char *name)
147 {
148         struct stat buf;
149         if (! stat(name, &buf))
150                 return 1;
151         return 0;
152 }
153
154 void
155 file_remap_readonly(struct file *f)
156 {
157 #ifdef _WIN32
158 #else
159         void *begin;
160         munmap(f->begin, f->size);
161         begin=mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
162         if (f->begin != begin)
163                 printf("remap failed\n");
164 #endif
165 }
166
167 void
168 file_remap_readonly_all(void)
169 {
170         struct file *f=file_list;
171         int limit=1000;
172
173         while (f && limit-- > 0) {
174                 file_remap_readonly(f);
175                 f=f->next;
176         }
177 }
178
179 void
180 file_unmap(struct file *f)
181 {
182 #ifdef _WIN32
183     mmap_unmap_win32( f->begin, f->map_handle , f->map_file );
184 #else
185         munmap(f->begin, f->size);
186 #endif
187 }
188
189 void
190 file_unmap_all(void)
191 {
192         struct file *f=file_list;
193         int limit=1000;
194
195         while (f && limit-- > 0) {
196                 file_unmap(f);
197                 f=f->next;
198         }
199 }
200
201
202
203 void *
204 file_opendir(char *dir)
205 {
206         return opendir(dir);
207 }
208
209 char *
210 file_readdir(void *hnd)
211 {
212         struct dirent *ent;
213
214         ent=readdir(hnd);
215         if (! ent)
216                 return NULL;
217         return ent->d_name;
218 }
219
220 void
221 file_closedir(void *hnd)
222 {
223         closedir(hnd);
224 }
225
226 struct file *
227 file_create_caseinsensitive(char *name)
228 {
229         char dirname[strlen(name)+1];
230         char *filename;
231         char *p;
232         void *d;
233         struct file *ret;
234
235         ret=file_create(name);
236         if (ret)
237                 return ret;
238
239         strcpy(dirname, name);
240         p=dirname+strlen(name);
241         while (p > dirname) {
242                 if (*p == '/')
243                         break;
244                 p--;
245         }
246         *p=0;
247         d=file_opendir(dirname);
248         if (d) {
249                 *p++='/';
250                 while ((filename=file_readdir(d))) {
251                         if (!strcasecmp(filename, p)) {
252                                 strcpy(p, filename);
253                                 ret=file_create(dirname);
254                                 if (ret)
255                                         break;
256                         }
257                 }
258                 file_closedir(d);
259         }
260         return ret;
261 }
262
263 void
264 file_destroy(struct file *f)
265 {
266         close(f->fd);
267
268     if ( f->begin != NULL )
269     {
270         file_unmap( f );
271     }
272
273         g_free(f->name);
274         g_free(f);
275 }
276
277 struct file_wordexp {
278         wordexp_t we;
279 };
280
281 struct file_wordexp *
282 file_wordexp_new(const char *pattern)
283 {
284         struct file_wordexp *ret=g_new(struct file_wordexp, 1);
285         wordexp(pattern, &ret->we, 0);
286         return ret;
287 }
288
289 int
290 file_wordexp_get_count(struct file_wordexp *wexp)
291 {
292         return wexp->we.we_wordc;
293 }
294
295 char **
296 file_wordexp_get_array(struct file_wordexp *wexp)
297 {
298         return wexp->we.we_wordv;
299 }
300
301 void
302 file_wordexp_destroy(struct file_wordexp *wexp)
303 {
304         wordfree(&wexp->we);
305         g_free(wexp);
306 }
307
308
309 int
310 file_get_param(struct file *file, struct param_list *param, int count)
311 {
312         int i=count;
313         param_add_string("Filename", file->name, &param, &count);
314         param_add_hex("Size", file->size, &param, &count);
315         return i-count;
316 }