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

Contents of /navit/navit/file.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 50 - (show annotations) (download)
Wed Jun 22 07:33:35 2016 UTC (7 years, 10 months ago) by zoff99
File MIME type: text/plain
File size: 29906 byte(s)
v2.0.51
1 /**
2 * 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 * 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
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47
48 #ifdef _MSC_VER
49 #include <windows.h>
50 #else
51 #include <dirent.h>
52 #endif /* _MSC_VER */
53
54 #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
71 #ifdef HAVE_SOCKET
72 #include <sys/socket.h>
73 #include <netdb.h>
74 #endif
75
76 #include "navit.h"
77
78 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 struct file_cache_id
110 {
111 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 //dbg(0,"_enterXX %s %s\n", host, service);
127 int fd;
128 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 //dbg(0,"_enterXX %s\n", path);
135 }
136
137 static int
138 file_request_do(struct file *file, struct attr **options, int connect)
139 {
140 //dbg(0,"_enterXX %s\n", file->name);
141 return 1;
142 }
143 #endif
144
145 static unsigned char *
146 file_http_header_end(unsigned char *str, int len)
147 {
148 //dbg(0,"_enterXX %s\n", str);
149 return NULL;
150 }
151
152 int file_request(struct file *f, struct attr **options)
153 {
154 //dbg(0,"_enterXX %s\n", f->name);
155 return 0;
156 }
157
158 char *
159 file_http_header(struct file *f, char *header)
160 {
161 //dbg(0,"_enterXX %s\n", f->name);
162 return NULL;
163 }
164
165 struct file *
166 file_create(char *name, struct attr **options)
167 {
168 //dbg(0,"_enterPP %s\n", name);
169 struct stat stat;
170 struct file *file= g_new0(struct file,1);
171 struct attr *attr;
172 int open_flags = O_LARGEFILE | O_BINARY;
173
174 if (options && (attr = attr_search(options, NULL, attr_url)))
175 {
176 #ifdef HAVE_SOCKET
177 //dbg(0,"_HAVE_SOCKET\n");
178 file_request_do(file, options, 1);
179 #endif
180 }
181 else
182 {
183 if (options && (attr = attr_search(options, NULL, attr_readwrite)) && attr->u.num)
184 {
185 open_flags |= O_RDWR;
186 if ((attr = attr_search(options, NULL, attr_create)) && attr->u.num)
187 {
188 open_flags |= O_CREAT;
189 }
190 }
191 else
192 {
193 open_flags |= O_RDONLY;
194 }
195
196 file->name = g_strdup(name);
197 file->fd = open(name, open_flags, 0666);
198 file->current_splitter = 0; // ORIG file opened
199 if (file->fd == -1)
200 {
201 g_free(file);
202 return NULL;
203 }
204 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 }
213 #ifdef CACHE_SIZE
214 //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 #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 //dbg(0,"_enterOO %s\n", name);
234 struct stat buf;
235 if (!stat(name, &buf))
236 {
237 return S_ISDIR(buf.st_mode);
238 }
239 return 0;
240 }
241
242 int file_is_reg(char *name)
243 {
244 //dbg(0,"_enterOO\n");
245 struct stat buf;
246 if (!stat(name, &buf))
247 {
248 return S_ISREG(buf.st_mode);
249 }
250 return 0;
251 }
252
253 long long file_size(struct file *file)
254 {
255 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 }
311
312 int file_mkdir(char *name, int pflag)
313 {
314 //dbg(0,"_enterOO %s\n", name);
315 char *buffer = g_alloca(sizeof(char) * (strlen(name) + 1));
316 int ret;
317 char *next;
318 // dbg(1, "enter %s %d\n", name, pflag);
319 if (!pflag)
320 {
321 if (file_is_dir(name))
322 {
323 return 0;
324 }
325 #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 next = buffer;
333 while ((next = strchr(next, '/')))
334 {
335 *next = '\0';
336 if (*buffer)
337 {
338 ret = file_mkdir(buffer, 0);
339 if (ret)
340 {
341 return ret;
342 }
343 }
344 *next++ = '/';
345 }
346 if (pflag == 2)
347 {
348 return 0;
349 }
350 return file_mkdir(buffer, 0);
351 }
352
353 int file_mmap(struct file *file)
354 {
355 //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 #ifdef HAVE_API_WIN32_BASE
367 file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file );
368 #else
369 file->begin = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, file->fd, 0);
370 dbg_assert(file->begin != NULL);
371 if (file->begin == (void *) 0xffffffff)
372 {
373 perror("mmap");
374 return 0;
375 }
376 #endif
377
378 dbg_assert(file->begin != (void *) 0xffffffff);
379 file->mmap_end = file->begin + mmap_size;
380 file->end = file->begin + file->size;
381
382 return 1;
383 }
384
385 unsigned char *
386 file_data_read(struct file *file, long long offset, int size)
387 {
388 //dbg(0,"_enterPP %s "LONGLONG_FMT" %d\n", file->name, offset, size);
389 void *ret;
390 if (file->special)
391 {
392 return NULL;
393 }
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 if (ret)
412 {
413 //dbg(0,"_file_cache:found\n");
414 return ret;
415 }
416 //dbg(0,"_file_cache:insert\n");
417 ret = cache_insert_new(file_cache, &id, size);
418 }
419 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 return ret;
560 }
561
562 static void file_process_headers(struct file *file, unsigned char *headers)
563 {
564 //dbg(0,"_enter %s\n", file->name);
565 char *tok;
566 char *cl;
567 if (file->headers)
568 {
569 g_hash_table_destroy(file->headers);
570 }
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 char *sep;
575 tok = g_strdup(tok);
576 sep = strchr(tok, ':');
577 if (!sep)
578 {
579 sep = strchr(tok, '/');
580 }
581 if (!sep)
582 {
583 g_free(tok);
584 continue;
585 }
586 *sep++ = '\0';
587 if (*sep == ' ')
588 {
589 sep++;
590 }
591 strtolower(tok, tok);
592 // dbg(1, "header '%s'='%s'\n", tok, sep);
593 g_hash_table_insert(file->headers, tok, sep);
594 headers = NULL;
595 }
596 cl = g_hash_table_lookup(file->headers, "content-length");
597 if (cl)
598 {
599 #ifdef HAVE__ATOI64
600 file->size=_atoi64(cl);
601 #else
602 file->size = atoll(cl);
603 #endif
604 }
605 }
606
607 static void file_shift_buffer(struct file *file, int amount)
608 {
609 //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 }
613
614 unsigned char *
615 file_data_read_special(struct file *file, int size, int *size_ret)
616 {
617 //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 if (!file->special)
624 {
625 return NULL;
626 }
627
628 if (!file->buffer)
629 {
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 if (!file->requests && toread > size)
640 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 }
649 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 file_process_headers(file, file->buffer);
657 file_shift_buffer(file, hdr - file->buffer);
658 file->requests--;
659 if (file_http_header(file, "location"))
660 {
661 break;
662 }
663 }
664 }
665 if (!file->requests)
666 {
667 rd = file->buffer_len;
668 if (rd > size)
669 rd = size;
670 memcpy(ret + rets, file->buffer, rd);
671 file_shift_buffer(file, rd);
672 rets += rd;
673 size -= rd;
674 }
675 }
676 *size_ret = rets;
677 return ret;
678 }
679
680 unsigned char *
681 file_data_read_all(struct file *file)
682 {
683 //dbg(0,"_enter %s\n", file->name);
684 return file_data_read(file, 0, file->size);
685 }
686
687 void file_data_flush(struct file *file, long long offset, int size)
688 {
689 //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size);
690 }
691
692 int file_data_write(struct file *file, long long offset, int size, unsigned char *data)
693 {
694 //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size);
695 return 1;
696 }
697
698 int file_get_contents(char *name, unsigned char **buffer, int *size)
699 {
700 //dbg(0,"_enter %s\n", name);
701 struct file *file;
702 file = file_create(name, 0);
703 if (!file)
704 {
705 return 0;
706 }
707 *size = file_size(file);
708 *buffer = file_data_read_all(file);
709 file_destroy(file);
710 return 1;
711 }
712
713 static int uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
714 {
715 //dbg(0,"_enter %d %d\n", sourceLen, destLen);
716 z_stream stream;
717 int err;
718
719 stream.next_in = (Bytef*) source;
720 stream.avail_in = (uInt) sourceLen;
721 stream.next_out = dest;
722 stream.avail_out = (uInt) * destLen;
723
724 stream.zalloc = (alloc_func) 0;
725 stream.zfree = (free_func) 0;
726
727 err = inflateInit2(&stream, -MAX_WBITS);
728 if (err != Z_OK)
729 {
730 return err;
731 }
732
733 err = inflate(&stream, Z_FINISH);
734 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 return err;
742 }
743
744 *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 //dbg(0,"_enterPP %s "LONGLONG_FMT" %d\n", file->name, offset, size);
754 void *ret;
755 char *buffer = 0;
756 uLongf destLen = size_uncomp;
757
758 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 if (ret)
764 {
765 //dbg(0,"_file_cache found 2\n");
766 return ret;
767 }
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
776 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 g_free(ret);
785 ret = NULL;
786 }
787 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 }
797 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 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 //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size);
946 #ifdef HAVE_LIBCRYPTO
947 void *ret;
948 unsigned char *buffer = 0;
949 uLongf destLen=size_uncomp;
950
951 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 if (ret)
958 {
959 //dbg(0,"_file_cache found 3\n");
960 return ret;
961 }
962 //dbg(0,"_file_cache create new 3\n");
963 ret=cache_insert_new(file_cache,&id,size_uncomp);
964 }
965 else
966 {
967 ret=g_malloc(size_uncomp);
968 }
969 lseek(file->fd, offset, SEEK_SET);
970
971 buffer = (unsigned char *)g_malloc(size);
972 if (read(file->fd, buffer, size) != size)
973 {
974 g_free(ret);
975 ret=NULL;
976 }
977 else
978 {
979 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 if (key[32] == buffer[8] && key[33] == buffer[9] && esize >= 0)
984 {
985 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 while (esize > 0)
990 {
991 int i,curr_size,idx=0;
992 do
993 {
994 counter[idx]++;
995 }while (!counter[idx++]);
996
997 AES_encrypt(counter, xor, &aeskey);
998 curr_size=esize;
999 if (curr_size > sizeof(xor))
1000 curr_size=sizeof(xor);
1001 for (i = 0; i < curr_size; i++)
1002 *datap++^=xor[i];
1003 esize-=curr_size;
1004 }
1005 size-=overhead;
1006 datap=buffer+sizeof(salt)+sizeof(verify);
1007 if (compressed)
1008 {
1009 if (uncompress_int(ret, &destLen, (Bytef *)datap, size) != Z_OK)
1010 {
1011 //dbg(0,"_uncompress failed\n");
1012 g_free(ret);
1013 ret=NULL;
1014 }
1015 }
1016 else
1017 {
1018 if (size == destLen)
1019 memcpy(ret, buffer, destLen);
1020 else
1021 {
1022 //dbg(0,"_memcpy failed\n");
1023 g_free(ret);
1024 ret=NULL;
1025 }
1026 }
1027 }
1028 else
1029 {
1030 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 void file_data_free(struct file *file, unsigned char *data)
1043 {
1044 //dbg(0,"_enter %s\n", file->name);
1045 if (file->begin)
1046 {
1047 if (data == file->begin)
1048 return;
1049 if (data >= file->begin && data < file->end)
1050 return;
1051 }
1052
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 cache_entry_destroy(file_cache, data);
1062 }
1063 else
1064 {
1065 g_free(data);
1066 }
1067 //dbg(0,"_leave\n");
1068 }
1069
1070 void file_data_remove(struct file *file, unsigned char *data)
1071 {
1072 //dbg(0,"_enter %s\n", file->name);
1073 if (file->begin)
1074 {
1075 if (data == file->begin)
1076 {
1077 return;
1078 }
1079 if (data >= file->begin && data < file->end)
1080 {
1081 return;
1082 }
1083 }
1084 if (file->cache && data)
1085 {
1086 cache_flush_data(file_cache, data);
1087 }
1088 else
1089 {
1090 g_free(data);
1091 }
1092 }
1093
1094 int file_exists(char const *name)
1095 {
1096 //dbg(0,"_enter %s\n", name);
1097 struct stat buf;
1098 if (!stat(name, &buf))
1099 {
1100 return 1;
1101 }
1102 return 0;
1103 }
1104
1105 void file_remap_readonly(struct file *f)
1106 {
1107 //dbg(0,"_enter %s\n", f->name);
1108 #if defined(_WIN32) || defined(__CEGCC__)
1109 #else
1110 void *begin;
1111 munmap(f->begin, f->size);
1112 begin = mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0);
1113 if (f->begin != begin)
1114 {
1115 printf("remap failed\n");
1116 }
1117 #endif
1118 }
1119
1120 void file_unmap(struct file *f)
1121 {
1122 //dbg(0,"_enter %s\n", f->name);
1123 #if defined(_WIN32) || defined(__CEGCC__)
1124 mmap_unmap_win32( f->begin, f->map_handle , f->map_file );
1125 #else
1126 munmap(f->begin, f->size);
1127 #endif
1128 }
1129
1130 #ifndef _MSC_VER
1131 void *
1132 file_opendir(char *dir)
1133 {
1134 //dbg(0,"_enter %s\n", dir);
1135 return opendir(dir);
1136 }
1137 #else
1138 void *
1139 file_opendir(char *dir)
1140 {
1141 //dbg(0,"_enter %s\n", dir);
1142 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 //dbg(0,"_enter\n");
1157 struct dirent *ent;
1158
1159 ent = readdir(hnd);
1160 if (!ent)
1161 return NULL;
1162 return ent->d_name;
1163 }
1164 #else
1165 char *
1166 file_readdir(void *hnd)
1167 {
1168 //dbg(0,"_enter\n");
1169 WIN32_FIND_DATA FindFileData;
1170
1171 if (FindNextFile(hnd, &FindFileData) )
1172 {
1173 return FindFileData.cFileName;
1174 }
1175 else
1176 {
1177 return NULL;
1178 }
1179 }
1180 #endif /* _MSC_VER */
1181
1182 #ifndef _MSC_VER
1183 void file_closedir(void *hnd)
1184 {
1185 //dbg(0,"_enter\n");
1186 closedir(hnd);
1187 }
1188 #else
1189 void
1190 file_closedir(void *hnd)
1191 {
1192 //dbg(0,"_enter\n");
1193 FindClose(hnd);
1194 }
1195 #endif /* _MSC_VER */
1196
1197 struct file *
1198 file_create_caseinsensitive(char *name, struct attr **options)
1199 {
1200 //dbg(0,"_enter %s\n", name);
1201 char *dirname = g_alloca(sizeof(char) * (strlen(name) + 1));
1202 char *filename;
1203 char *p;
1204 void *d;
1205 struct file *ret;
1206
1207 ret = file_create(name, options);
1208 if (ret)
1209 {
1210 return ret;
1211 }
1212
1213 strcpy(dirname, name);
1214 p = dirname + strlen(name);
1215 while (p > dirname)
1216 {
1217 if (*p == '/')
1218 break;
1219 p--;
1220 }
1221 *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 strcpy(p, filename);
1231 ret = file_create(dirname, options);
1232 if (ret)
1233 break;
1234 }
1235 }
1236 file_closedir(d);
1237 }
1238 return ret;
1239 }
1240
1241 void file_destroy(struct file *f)
1242 {
1243 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 if (f->headers)
1253 {
1254 g_hash_table_destroy(f->headers);
1255 }
1256 switch (f->special)
1257 {
1258 case 0:
1259 case 1:
1260 close(f->fd);
1261 break;
1262 }
1263
1264 if (f->begin != NULL)
1265 {
1266 file_unmap(f);
1267 }
1268
1269 g_free(f->buffer);
1270 g_free(f->name);
1271 g_free(f);
1272 }
1273
1274 struct file_wordexp
1275 {
1276 int err;
1277 char *pattern;
1278 wordexp_t we;
1279 };
1280
1281 struct file_wordexp *
1282 file_wordexp_new(const char *pattern)
1283 {
1284 dbg(0, "_enter\n");
1285 struct file_wordexp *ret=g_new0(struct file_wordexp, 1);
1286 dbg(0, "fexp 001 p=%p\n", ret);
1287
1288 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 if (ret->err)
1293 {
1294 // dbg(0, "wordexp('%s') returned %d\n", pattern, ret->err);
1295 }
1296 dbg(0, "leave\n");
1297 return ret;
1298 }
1299
1300 int file_wordexp_get_count(struct file_wordexp *wexp)
1301 {
1302 //dbg(0,"_enter\n");
1303
1304 if (wexp->err)
1305 {
1306 return 1;
1307 }
1308 return wexp->we.we_wordc;
1309 }
1310
1311 char **
1312 file_wordexp_get_array(struct file_wordexp *wexp)
1313 {
1314 //dbg(0,"_enter\n");
1315
1316 if (wexp->err)
1317 {
1318 return &wexp->pattern;
1319 }
1320 return wexp->we.we_wordv;
1321 }
1322
1323 void file_wordexp_destroy(struct file_wordexp *wexp)
1324 {
1325 //dbg(0,"_enter\n");
1326 if (!wexp->err)
1327 {
1328 wordfree(&wexp->we);
1329 }
1330 g_free(wexp->pattern);
1331 g_free(wexp);
1332 }
1333
1334 int file_get_param(struct file *file, struct param_list *param, int count)
1335 {
1336 //dbg(0,"_enter %s\n", file->name);
1337 int i = count;
1338 param_add_string("Filename", file->name, &param, &count);
1339 param_add_hex("Size", file->size, &param, &count);
1340 return i - count;
1341 }
1342
1343 int file_version(struct file *file, int mode)
1344 {
1345 //dbg(0,"_enter %s\n", file->name);
1346 #ifndef HAVE_API_WIN32_BASE
1347 struct stat st;
1348 int error;
1349 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 file->version++;
1355 }
1356 else
1357 {
1358 file->size = size;
1359 if (file->begin)
1360 {
1361 file->end = file->begin + file->size;
1362 }
1363 }
1364 }
1365 else
1366 {
1367 if (mode == 2)
1368 {
1369 error = stat(file->name, &st);
1370 }
1371 else
1372 {
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 file->version++;
1380 // dbg(1, "%s now version %d\n", file->name, file->version);
1381 }
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 //dbg(0,"_enter %s\n", file->name);
1393 return GINT_TO_POINTER(file->fd);
1394 }
1395
1396 void file_cache_init(void)
1397 {
1398 #ifdef CACHE_SIZE
1399 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 #endif
1409 }
1410
1411 void file_init(void)
1412 {
1413 #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 }
1423

   
Visit the ZANavi Wiki