|
|
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 | |
1 | /** |
20 | /** |
2 | * Navit, a modular navigation system. |
21 | * Navit, a modular navigation system. |
3 | * Copyright (C) 2005-2011 Navit Team |
22 | * Copyright (C) 2005-2011 Navit Team |
4 | * |
23 | * |
5 | * This program is free software; you can redistribute it and/or |
24 | * This program is free software; you can redistribute it and/or |
… | |
… | |
19 | |
38 | |
20 | #define _FILE_OFFSET_BITS 64 |
39 | #define _FILE_OFFSET_BITS 64 |
21 | #define _LARGEFILE_SOURCE |
40 | #define _LARGEFILE_SOURCE |
22 | #define _LARGEFILE64_SOURCE |
41 | #define _LARGEFILE64_SOURCE |
23 | #include "config.h" |
42 | #include "config.h" |
|
|
43 | |
24 | #ifdef HAVE_UNISTD_H |
44 | #ifdef HAVE_UNISTD_H |
25 | #include <unistd.h> |
45 | #include <unistd.h> |
26 | #endif |
46 | #endif |
|
|
47 | |
27 | #ifdef _MSC_VER |
48 | #ifdef _MSC_VER |
28 | #include <windows.h> |
49 | #include <windows.h> |
29 | #else |
50 | #else |
30 | #include <dirent.h> |
51 | #include <dirent.h> |
31 | #endif /* _MSC_VER */ |
52 | #endif /* _MSC_VER */ |
|
|
53 | |
32 | #include <string.h> |
54 | #include <string.h> |
33 | #include <fcntl.h> |
55 | #include <fcntl.h> |
34 | #include <sys/stat.h> |
56 | #include <sys/stat.h> |
35 | #include <sys/mman.h> |
57 | #include <sys/mman.h> |
36 | #include <stdio.h> |
58 | #include <stdio.h> |
… | |
… | |
43 | #include "file.h" |
65 | #include "file.h" |
44 | #include "atom.h" |
66 | #include "atom.h" |
45 | #include "item.h" |
67 | #include "item.h" |
46 | #include "util.h" |
68 | #include "util.h" |
47 | #include "types.h" |
69 | #include "types.h" |
|
|
70 | |
48 | #ifdef HAVE_SOCKET |
71 | #ifdef HAVE_SOCKET |
49 | #include <sys/socket.h> |
72 | #include <sys/socket.h> |
50 | #include <netdb.h> |
73 | #include <netdb.h> |
51 | #endif |
74 | #endif |
|
|
75 | |
|
|
76 | #include "navit.h" |
52 | |
77 | |
53 | extern char *version; |
78 | extern char *version; |
54 | |
79 | |
55 | #ifdef HAVE_LIBCRYPTO |
80 | #ifdef HAVE_LIBCRYPTO |
56 | #include <openssl/sha.h> |
81 | #include <openssl/sha.h> |
… | |
… | |
79 | static struct cache *file_cache; |
104 | static struct cache *file_cache; |
80 | |
105 | |
81 | #ifdef _MSC_VER |
106 | #ifdef _MSC_VER |
82 | #pragma pack(push,1) |
107 | #pragma pack(push,1) |
83 | #endif /* _MSC_VER */ |
108 | #endif /* _MSC_VER */ |
84 | struct file_cache_id { |
109 | struct file_cache_id |
|
|
110 | { |
85 | long long offset; |
111 | long long offset; |
86 | int size; |
112 | int size; |
87 | int file_name_id; |
113 | int file_name_id; |
88 | int method; |
114 | int method; |
89 | #ifndef _MSC_VER |
115 | #ifndef _MSC_VER |
… | |
… | |
95 | |
121 | |
96 | #ifdef HAVE_SOCKET |
122 | #ifdef HAVE_SOCKET |
97 | static int |
123 | static int |
98 | file_socket_connect(char *host, char *service) |
124 | file_socket_connect(char *host, char *service) |
99 | { |
125 | { |
100 | struct addrinfo hints; |
126 | //dbg(0,"_enterXX %s %s\n", host, service); |
101 | struct addrinfo *result, *rp; |
|
|
102 | int fd=-1,s; |
127 | int fd; |
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; |
128 | return fd; |
125 | } |
129 | } |
126 | |
130 | |
127 | static void |
131 | static void |
128 | file_http_request(struct file *file, char *method, char *host, char *path, char *header, int persistent) |
132 | file_http_request(struct file *file, char *method, char *host, char *path, char *header, int persistent) |
129 | { |
133 | { |
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":""); |
134 | //dbg(0,"_enterXX %s\n", path); |
131 | write(file->fd, request, strlen(request)); |
|
|
132 | dbg(1,"%s\n",request); |
|
|
133 | file->requests++; |
|
|
134 | } |
135 | } |
135 | |
136 | |
136 | static int |
137 | static int |
137 | file_request_do(struct file *file, struct attr **options, int connect) |
138 | file_request_do(struct file *file, struct attr **options, int connect) |
138 | { |
139 | { |
139 | struct attr *attr; |
140 | //dbg(0,"_enterXX %s\n", file->name); |
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; |
141 | return 1; |
177 | } |
142 | } |
178 | #endif |
143 | #endif |
179 | |
144 | |
180 | static unsigned char * |
145 | static unsigned char * |
181 | file_http_header_end(unsigned char *str, int len) |
146 | file_http_header_end(unsigned char *str, int len) |
182 | { |
147 | { |
183 | int i; |
148 | //dbg(0,"_enterXX %s\n", str); |
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; |
149 | return NULL; |
198 | } |
150 | } |
199 | |
151 | |
200 | int |
|
|
201 | file_request(struct file *f, struct attr **options) |
152 | int file_request(struct file *f, struct attr **options) |
202 | { |
153 | { |
203 | #ifdef HAVE_SOCKET |
154 | //dbg(0,"_enterXX %s\n", f->name); |
204 | return file_request_do(f, options, 0); |
|
|
205 | #else |
|
|
206 | return 0; |
155 | return 0; |
207 | #endif |
|
|
208 | } |
156 | } |
209 | |
157 | |
210 | char * |
158 | char * |
211 | file_http_header(struct file *f, char *header) |
159 | file_http_header(struct file *f, char *header) |
212 | { |
160 | { |
213 | if (!f->headers) |
161 | //dbg(0,"_enterXX %s\n", f->name); |
214 | return NULL; |
162 | return NULL; |
215 | return g_hash_table_lookup(f->headers, header); |
|
|
216 | } |
163 | } |
217 | |
164 | |
218 | struct file * |
165 | struct file * |
219 | file_create(char *name, struct attr **options) |
166 | file_create(char *name, struct attr **options) |
220 | { |
167 | { |
|
|
168 | //dbg(0,"_enterPP %s\n", name); |
221 | struct stat stat; |
169 | struct stat stat; |
222 | struct file *file= g_new0(struct file,1); |
170 | struct file *file= g_new0(struct file,1); |
223 | struct attr *attr; |
171 | struct attr *attr; |
224 | int open_flags=O_LARGEFILE|O_BINARY; |
172 | int open_flags = O_LARGEFILE | O_BINARY; |
225 | |
173 | |
226 | if (options && (attr=attr_search(options, NULL, attr_url))) { |
174 | if (options && (attr = attr_search(options, NULL, attr_url))) |
|
|
175 | { |
227 | #ifdef HAVE_SOCKET |
176 | #ifdef HAVE_SOCKET |
|
|
177 | //dbg(0,"_HAVE_SOCKET\n"); |
228 | file_request_do(file, options, 1); |
178 | file_request_do(file, options, 1); |
229 | #endif |
179 | #endif |
230 | } else { |
180 | } |
|
|
181 | else |
|
|
182 | { |
231 | if (options && (attr=attr_search(options, NULL, attr_readwrite)) && attr->u.num) { |
183 | if (options && (attr = attr_search(options, NULL, attr_readwrite)) && attr->u.num) |
|
|
184 | { |
232 | open_flags |= O_RDWR; |
185 | open_flags |= O_RDWR; |
233 | if ((attr=attr_search(options, NULL, attr_create)) && attr->u.num) |
186 | if ((attr = attr_search(options, NULL, attr_create)) && attr->u.num) |
|
|
187 | { |
234 | open_flags |= O_CREAT; |
188 | open_flags |= O_CREAT; |
|
|
189 | } |
|
|
190 | } |
235 | } else |
191 | else |
|
|
192 | { |
236 | open_flags |= O_RDONLY; |
193 | open_flags |= O_RDONLY; |
|
|
194 | } |
|
|
195 | |
237 | file->name = g_strdup(name); |
196 | file->name = g_strdup(name); |
238 | file->fd=open(name, open_flags, 0666); |
197 | file->fd = open(name, open_flags, 0666); |
|
|
198 | file->current_splitter = 0; // ORIG file opened |
239 | if (file->fd == -1) { |
199 | if (file->fd == -1) |
|
|
200 | { |
240 | g_free(file); |
201 | g_free(file); |
241 | return NULL; |
202 | return NULL; |
242 | } |
203 | } |
243 | dbg(1,"fd=%d\n", file->fd); |
204 | dbg(0, "_fd=%d\n", file->fd); |
244 | fstat(file->fd, &stat); |
205 | |
245 | file->size=stat.st_size; |
206 | // set default value |
|
|
207 | file->num_splits = 0; |
|
|
208 | file->size = file_size(file); |
|
|
209 | |
246 | dbg(1,"size="LONGLONG_FMT"\n", file->size); |
210 | dbg(0,"_size="LONGLONG_FMT"\n", file->size); |
247 | file->name_id = (long)atom(name); |
211 | file->name_id = (long) atom(name); |
248 | } |
212 | } |
249 | #ifdef CACHE_SIZE |
213 | #ifdef CACHE_SIZE |
250 | if (!options || !(attr=attr_search(options, NULL, attr_cache)) || attr->u.num) |
214 | //if (!options || !(attr=attr_search(options, NULL, attr_cache)) || attr->u.num) |
|
|
215 | //{ |
|
|
216 | dbg(0,"_cache=1 for %s\n",name); |
251 | file->cache=1; |
217 | file->cache=1; |
|
|
218 | //} |
252 | #endif |
219 | #endif |
253 | dbg_assert(file != NULL); |
220 | dbg_assert(file != NULL); |
254 | return file; |
221 | return file; |
255 | } |
222 | } |
256 | |
223 | |
257 | #if 0 |
|
|
258 | struct file * |
|
|
259 | file_create_url(char *url) |
|
|
260 | { |
|
|
261 | } |
|
|
262 | #endif |
|
|
263 | |
|
|
264 | #ifndef S_ISDIR |
224 | #ifndef S_ISDIR |
265 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
225 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
266 | #endif |
226 | #endif |
267 | #ifndef S_ISREG |
227 | #ifndef S_ISREG |
268 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
228 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
269 | #endif |
229 | #endif |
270 | |
230 | |
271 | int file_is_dir(char *name) |
231 | int file_is_dir(char *name) |
272 | { |
232 | { |
|
|
233 | //dbg(0,"_enterOO %s\n", name); |
273 | struct stat buf; |
234 | struct stat buf; |
274 | if (! stat(name, &buf)) { |
235 | if (!stat(name, &buf)) |
|
|
236 | { |
275 | return S_ISDIR(buf.st_mode); |
237 | return S_ISDIR(buf.st_mode); |
276 | } |
238 | } |
277 | return 0; |
239 | return 0; |
278 | |
|
|
279 | } |
240 | } |
280 | |
241 | |
281 | int file_is_reg(char *name) |
242 | int file_is_reg(char *name) |
282 | { |
243 | { |
|
|
244 | //dbg(0,"_enterOO\n"); |
283 | struct stat buf; |
245 | struct stat buf; |
284 | if (! stat(name, &buf)) { |
246 | if (!stat(name, &buf)) |
|
|
247 | { |
285 | return S_ISREG(buf.st_mode); |
248 | return S_ISREG(buf.st_mode); |
286 | } |
249 | } |
287 | return 0; |
250 | return 0; |
288 | } |
251 | } |
289 | |
252 | |
290 | long long |
|
|
291 | file_size(struct file *file) |
253 | long long file_size(struct file *file) |
292 | { |
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; |
293 | return file->size; |
309 | // return file->size; |
294 | } |
310 | } |
295 | |
311 | |
296 | int file_mkdir(char *name, int pflag) |
312 | int file_mkdir(char *name, int pflag) |
297 | { |
313 | { |
|
|
314 | //dbg(0,"_enterOO %s\n", name); |
298 | char *buffer=g_alloca(sizeof(char)*(strlen(name)+1)); |
315 | char *buffer = g_alloca(sizeof(char) * (strlen(name) + 1)); |
299 | int ret; |
316 | int ret; |
300 | char *next; |
317 | char *next; |
301 | dbg(1,"enter %s %d\n",name,pflag); |
318 | // dbg(1, "enter %s %d\n", name, pflag); |
302 | if (!pflag) { |
319 | if (!pflag) |
|
|
320 | { |
303 | if (file_is_dir(name)) |
321 | if (file_is_dir(name)) |
|
|
322 | { |
304 | return 0; |
323 | return 0; |
|
|
324 | } |
305 | #if defined HAVE_API_WIN32_BASE || defined _MSC_VER |
325 | #if defined HAVE_API_WIN32_BASE || defined _MSC_VER |
306 | return mkdir(name); |
326 | return mkdir(name); |
307 | #else |
327 | #else |
308 | return mkdir(name, 0777); |
328 | return mkdir(name, 0777); |
309 | #endif |
329 | #endif |
310 | } |
330 | } |
311 | strcpy(buffer, name); |
331 | strcpy(buffer, name); |
312 | next=buffer; |
332 | next = buffer; |
313 | while ((next=strchr(next, '/'))) { |
333 | while ((next = strchr(next, '/'))) |
|
|
334 | { |
314 | *next='\0'; |
335 | *next = '\0'; |
315 | if (*buffer) { |
336 | if (*buffer) |
|
|
337 | { |
316 | ret=file_mkdir(buffer, 0); |
338 | ret = file_mkdir(buffer, 0); |
317 | if (ret) |
339 | if (ret) |
|
|
340 | { |
318 | return ret; |
341 | return ret; |
319 | } |
342 | } |
|
|
343 | } |
320 | *next++='/'; |
344 | *next++ = '/'; |
321 | } |
345 | } |
322 | if (pflag == 2) |
346 | if (pflag == 2) |
|
|
347 | { |
323 | return 0; |
348 | return 0; |
|
|
349 | } |
324 | return file_mkdir(buffer, 0); |
350 | return file_mkdir(buffer, 0); |
325 | } |
351 | } |
326 | |
352 | |
327 | int |
|
|
328 | file_mmap(struct file *file) |
353 | int file_mmap(struct file *file) |
329 | { |
354 | { |
330 | #if 0 |
355 | //dbg(0,"_enterP? %s\n", file->name); |
331 | int mmap_size=file->size+1024*1024; |
|
|
332 | #else |
|
|
333 | int mmap_size=file->size; |
356 | int mmap_size = file->size; |
334 | #endif |
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 | |
335 | #ifdef HAVE_API_WIN32_BASE |
366 | #ifdef HAVE_API_WIN32_BASE |
336 | file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file ); |
367 | file->begin = (char*)mmap_readonly_win32( file->name, &file->map_handle, &file->map_file ); |
337 | #else |
368 | #else |
338 | file->begin=mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, file->fd, 0); |
369 | file->begin = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, file->fd, 0); |
339 | dbg_assert(file->begin != NULL); |
370 | dbg_assert(file->begin != NULL); |
340 | if (file->begin == (void *)0xffffffff) { |
371 | if (file->begin == (void *) 0xffffffff) |
|
|
372 | { |
341 | perror("mmap"); |
373 | perror("mmap"); |
342 | return 0; |
374 | return 0; |
343 | } |
375 | } |
344 | #endif |
376 | #endif |
|
|
377 | |
345 | dbg_assert(file->begin != (void *)0xffffffff); |
378 | dbg_assert(file->begin != (void *) 0xffffffff); |
346 | file->mmap_end=file->begin+mmap_size; |
379 | file->mmap_end = file->begin + mmap_size; |
347 | file->end=file->begin+file->size; |
380 | file->end = file->begin + file->size; |
348 | |
381 | |
349 | return 1; |
382 | return 1; |
350 | } |
383 | } |
351 | |
384 | |
352 | unsigned char * |
385 | unsigned char * |
353 | file_data_read(struct file *file, long long offset, int size) |
386 | file_data_read(struct file *file, long long offset, int size) |
354 | { |
387 | { |
|
|
388 | //dbg(0,"_enterPP %s "LONGLONG_FMT" %d\n", file->name, offset, size); |
355 | void *ret; |
389 | void *ret; |
356 | if (file->special) |
390 | if (file->special) |
|
|
391 | { |
357 | return NULL; |
392 | return NULL; |
|
|
393 | } |
|
|
394 | |
|
|
395 | // turn off mmap |
|
|
396 | if (file->num_splits == 0) |
|
|
397 | // turn off mmap |
|
|
398 | { |
358 | if (file->begin) |
399 | if (file->begin) |
|
|
400 | { |
|
|
401 | //dbg(0,"_leave:begin\n"); |
359 | return file->begin+offset; |
402 | return file->begin + offset; |
|
|
403 | } |
|
|
404 | } |
|
|
405 | |
360 | if (file_cache) { |
406 | if (file_cache) |
|
|
407 | { |
|
|
408 | //dbg(0,"_file_cache\n"); |
361 | struct file_cache_id id={offset,size,file->name_id,0}; |
409 | struct file_cache_id id = { offset, size, file->name_id, 0 }; |
362 | ret=cache_lookup(file_cache,&id); |
410 | ret = cache_lookup(file_cache, &id); |
363 | if (ret) |
411 | if (ret) |
|
|
412 | { |
|
|
413 | //dbg(0,"_file_cache:found\n"); |
364 | return ret; |
414 | return ret; |
|
|
415 | } |
|
|
416 | //dbg(0,"_file_cache:insert\n"); |
365 | ret=cache_insert_new(file_cache,&id,size); |
417 | ret = cache_insert_new(file_cache, &id, size); |
|
|
418 | } |
366 | } else |
419 | else |
|
|
420 | { |
|
|
421 | //dbg(0,"_g_malloc\n"); |
367 | ret=g_malloc(size); |
422 | ret = g_malloc(size); |
|
|
423 | } |
|
|
424 | |
|
|
425 | if (file->num_splits == 0) |
|
|
426 | { |
|
|
427 | //dbg(0,"_num_splits=0\n"); |
368 | lseek(file->fd, offset, SEEK_SET); |
428 | lseek(file->fd, offset, SEEK_SET); |
369 | if (read(file->fd, ret, size) != size) { |
429 | if (read(file->fd, ret, size) != size) |
|
|
430 | { |
370 | file_data_free(file, ret); |
431 | file_data_free(file, ret); |
371 | ret=NULL; |
432 | ret = NULL; |
372 | } |
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"); |
373 | return ret; |
559 | return ret; |
374 | |
|
|
375 | } |
560 | } |
376 | |
561 | |
377 | static void |
|
|
378 | file_process_headers(struct file *file, unsigned char *headers) |
562 | static void file_process_headers(struct file *file, unsigned char *headers) |
379 | { |
563 | { |
|
|
564 | //dbg(0,"_enter %s\n", file->name); |
380 | char *tok; |
565 | char *tok; |
381 | char *cl; |
566 | char *cl; |
382 | if (file->headers) |
567 | if (file->headers) |
|
|
568 | { |
383 | g_hash_table_destroy(file->headers); |
569 | g_hash_table_destroy(file->headers); |
|
|
570 | } |
384 | file->headers=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); |
571 | file->headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free_func, NULL); |
385 | while ((tok=strtok((char*)headers, "\r\n"))) { |
572 | while ((tok = strtok((char*) headers, "\r\n"))) |
|
|
573 | { |
386 | char *sep; |
574 | char *sep; |
387 | tok=g_strdup(tok); |
575 | tok = g_strdup(tok); |
388 | sep=strchr(tok,':'); |
576 | sep = strchr(tok, ':'); |
389 | if (!sep) |
577 | if (!sep) |
|
|
578 | { |
390 | sep=strchr(tok,'/'); |
579 | sep = strchr(tok, '/'); |
|
|
580 | } |
391 | if (!sep) { |
581 | if (!sep) |
|
|
582 | { |
392 | g_free(tok); |
583 | g_free(tok); |
393 | continue; |
584 | continue; |
394 | } |
585 | } |
395 | *sep++='\0'; |
586 | *sep++ = '\0'; |
396 | if (*sep == ' ') |
587 | if (*sep == ' ') |
|
|
588 | { |
397 | sep++; |
589 | sep++; |
|
|
590 | } |
398 | strtolower(tok, tok); |
591 | strtolower(tok, tok); |
399 | dbg(1,"header '%s'='%s'\n",tok,sep); |
592 | // dbg(1, "header '%s'='%s'\n", tok, sep); |
400 | g_hash_table_insert(file->headers, tok, sep); |
593 | g_hash_table_insert(file->headers, tok, sep); |
401 | headers=NULL; |
594 | headers = NULL; |
402 | } |
595 | } |
403 | cl=g_hash_table_lookup(file->headers, "content-length"); |
596 | cl = g_hash_table_lookup(file->headers, "content-length"); |
404 | if (cl) |
597 | if (cl) |
|
|
598 | { |
405 | #ifdef HAVE__ATOI64 |
599 | #ifdef HAVE__ATOI64 |
406 | file->size=_atoi64(cl); |
600 | file->size=_atoi64(cl); |
407 | #else |
601 | #else |
408 | file->size=atoll(cl); |
602 | file->size = atoll(cl); |
409 | #endif |
603 | #endif |
|
|
604 | } |
410 | } |
605 | } |
411 | |
606 | |
412 | static void |
|
|
413 | file_shift_buffer(struct file *file, int amount) |
607 | static void file_shift_buffer(struct file *file, int amount) |
414 | { |
608 | { |
|
|
609 | //dbg(0,"_enter %s %d\n", file->name, amount); |
415 | memmove(file->buffer, file->buffer+amount, file->buffer_len-amount); |
610 | memmove(file->buffer, file->buffer + amount, file->buffer_len - amount); |
416 | file->buffer_len-=amount; |
611 | file->buffer_len -= amount; |
417 | } |
612 | } |
418 | |
613 | |
419 | unsigned char * |
614 | unsigned char * |
420 | file_data_read_special(struct file *file, int size, int *size_ret) |
615 | file_data_read_special(struct file *file, int size, int *size_ret) |
421 | { |
616 | { |
|
|
617 | //dbg(0,"_enter %s %d\n", file->name, size); |
422 | unsigned char *ret,*hdr; |
618 | unsigned char *ret, *hdr; |
423 | int rets=0,rd; |
619 | int rets = 0, rd; |
424 | int buffer_size=8192; |
620 | int buffer_size = 8192; |
425 | int eof=0; |
621 | int eof = 0; |
|
|
622 | |
426 | if (!file->special) |
623 | if (!file->special) |
|
|
624 | { |
427 | return NULL; |
625 | return NULL; |
|
|
626 | } |
|
|
627 | |
428 | if (!file->buffer) |
628 | if (!file->buffer) |
|
|
629 | { |
429 | file->buffer=g_malloc(buffer_size); |
630 | file->buffer = g_malloc(buffer_size); |
|
|
631 | } |
|
|
632 | |
430 | ret=g_malloc(size); |
633 | ret = g_malloc(size); |
431 | while ((size > 0 || file->requests) && (!eof || file->buffer_len)) { |
634 | while ((size > 0 || file->requests) && (!eof || file->buffer_len)) |
|
|
635 | { |
432 | int toread=buffer_size-file->buffer_len; |
636 | int toread = buffer_size - file->buffer_len; |
433 | if (toread >= 4096 && !eof) { |
637 | if (toread >= 4096 && !eof) |
|
|
638 | { |
434 | if (!file->requests && toread > size) |
639 | if (!file->requests && toread > size) |
435 | toread=size; |
640 | toread = size; |
436 | rd=read(file->fd, file->buffer+file->buffer_len, toread); |
641 | rd = read(file->fd, file->buffer + file->buffer_len, toread); |
437 | if (rd > 0) { |
642 | if (rd > 0) |
|
|
643 | { |
438 | file->buffer_len+=rd; |
644 | file->buffer_len += rd; |
|
|
645 | } |
439 | } else |
646 | else |
440 | eof=1; |
647 | eof = 1; |
441 | } |
648 | } |
442 | if (file->requests) { |
649 | if (file->requests) |
|
|
650 | { |
443 | dbg(1,"checking header\n"); |
651 | // dbg(1, "checking header\n"); |
444 | if ((hdr=file_http_header_end(file->buffer, file->buffer_len))) { |
652 | if ((hdr = file_http_header_end(file->buffer, file->buffer_len))) |
|
|
653 | { |
445 | hdr[-1]='\0'; |
654 | hdr[-1] = '\0'; |
446 | dbg(1,"found %s (%d bytes)\n",file->buffer,sizeof(file->buffer)); |
655 | // dbg(1, "found %s (%d bytes)\n", file->buffer, sizeof(file->buffer)); |
447 | file_process_headers(file, file->buffer); |
656 | file_process_headers(file, file->buffer); |
448 | file_shift_buffer(file, hdr-file->buffer); |
657 | file_shift_buffer(file, hdr - file->buffer); |
449 | file->requests--; |
658 | file->requests--; |
450 | if (file_http_header(file, "location")) |
659 | if (file_http_header(file, "location")) |
|
|
660 | { |
451 | break; |
661 | break; |
452 | } |
662 | } |
453 | } |
663 | } |
|
|
664 | } |
454 | if (!file->requests) { |
665 | if (!file->requests) |
|
|
666 | { |
455 | rd=file->buffer_len; |
667 | rd = file->buffer_len; |
456 | if (rd > size) |
668 | if (rd > size) |
457 | rd=size; |
669 | rd = size; |
458 | memcpy(ret+rets, file->buffer, rd); |
670 | memcpy(ret + rets, file->buffer, rd); |
459 | file_shift_buffer(file, rd); |
671 | file_shift_buffer(file, rd); |
460 | rets+=rd; |
672 | rets += rd; |
461 | size-=rd; |
673 | size -= rd; |
462 | } |
|
|
463 | } |
674 | } |
|
|
675 | } |
464 | *size_ret=rets; |
676 | *size_ret = rets; |
465 | return ret; |
677 | return ret; |
466 | } |
678 | } |
467 | |
679 | |
468 | unsigned char * |
680 | unsigned char * |
469 | file_data_read_all(struct file *file) |
681 | file_data_read_all(struct file *file) |
470 | { |
682 | { |
|
|
683 | //dbg(0,"_enter %s\n", file->name); |
471 | return file_data_read(file, 0, file->size); |
684 | return file_data_read(file, 0, file->size); |
472 | } |
685 | } |
473 | |
686 | |
474 | void |
|
|
475 | file_data_flush(struct file *file, long long offset, int size) |
687 | void file_data_flush(struct file *file, long long offset, int size) |
476 | { |
688 | { |
477 | if (file_cache) { |
689 | //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size); |
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 | } |
690 | } |
483 | |
691 | |
484 | int |
|
|
485 | file_data_write(struct file *file, long long offset, int size, unsigned char *data) |
692 | int file_data_write(struct file *file, long long offset, int size, unsigned char *data) |
486 | { |
693 | { |
487 | file_data_flush(file, offset, size); |
694 | //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size); |
488 | lseek(file->fd, offset, SEEK_SET); |
695 | return 1; |
489 | if (write(file->fd, data, size) != size) |
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 | { |
490 | return 0; |
705 | return 0; |
491 | if (file->size < offset+size) |
706 | } |
492 | file->size=offset+size; |
707 | *size = file_size(file); |
|
|
708 | *buffer = file_data_read_all(file); |
|
|
709 | file_destroy(file); |
493 | return 1; |
710 | return 1; |
494 | } |
711 | } |
495 | |
712 | |
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) |
713 | static int uncompress_int(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen) |
512 | { |
714 | { |
|
|
715 | //dbg(0,"_enter %d %d\n", sourceLen, destLen); |
513 | z_stream stream; |
716 | z_stream stream; |
514 | int err; |
717 | int err; |
515 | |
718 | |
516 | stream.next_in = (Bytef*)source; |
719 | stream.next_in = (Bytef*) source; |
517 | stream.avail_in = (uInt)sourceLen; |
720 | stream.avail_in = (uInt) sourceLen; |
518 | stream.next_out = dest; |
721 | stream.next_out = dest; |
519 | stream.avail_out = (uInt)*destLen; |
722 | stream.avail_out = (uInt) * destLen; |
520 | |
723 | |
521 | stream.zalloc = (alloc_func)0; |
724 | stream.zalloc = (alloc_func) 0; |
522 | stream.zfree = (free_func)0; |
725 | stream.zfree = (free_func) 0; |
523 | |
726 | |
524 | err = inflateInit2(&stream, -MAX_WBITS); |
727 | err = inflateInit2(&stream, -MAX_WBITS); |
525 | if (err != Z_OK) return err; |
728 | if (err != Z_OK) |
|
|
729 | { |
|
|
730 | return err; |
|
|
731 | } |
526 | |
732 | |
527 | err = inflate(&stream, Z_FINISH); |
733 | err = inflate(&stream, Z_FINISH); |
528 | if (err != Z_STREAM_END) { |
734 | if (err != Z_STREAM_END) |
|
|
735 | { |
529 | inflateEnd(&stream); |
736 | inflateEnd(&stream); |
530 | if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) |
737 | if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) |
|
|
738 | { |
531 | return Z_DATA_ERROR; |
739 | return Z_DATA_ERROR; |
|
|
740 | } |
532 | return err; |
741 | return err; |
533 | } |
742 | } |
|
|
743 | |
534 | *destLen = stream.total_out; |
744 | *destLen = stream.total_out; |
535 | |
745 | |
536 | err = inflateEnd(&stream); |
746 | err = inflateEnd(&stream); |
537 | return err; |
747 | return err; |
538 | } |
748 | } |
539 | |
749 | |
540 | unsigned char * |
750 | unsigned char * |
541 | file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp) |
751 | file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp) |
542 | { |
752 | { |
|
|
753 | //dbg(0,"_enterPP %s "LONGLONG_FMT" %d\n", file->name, offset, size); |
543 | void *ret; |
754 | void *ret; |
544 | char *buffer = 0; |
755 | char *buffer = 0; |
545 | uLongf destLen=size_uncomp; |
756 | uLongf destLen = size_uncomp; |
546 | |
757 | |
547 | if (file_cache) { |
758 | if (file_cache) |
|
|
759 | { |
|
|
760 | //dbg(0,"_file_cache 2\n"); |
548 | struct file_cache_id id={offset,size,file->name_id,1}; |
761 | struct file_cache_id id = { offset, size, file->name_id, 1 }; |
549 | ret=cache_lookup(file_cache,&id); |
762 | ret = cache_lookup(file_cache, &id); |
550 | if (ret) |
763 | if (ret) |
|
|
764 | { |
|
|
765 | //dbg(0,"_file_cache found 2\n"); |
551 | return ret; |
766 | return ret; |
|
|
767 | } |
|
|
768 | //dbg(0,"_file_cache create new 2\n"); |
552 | ret=cache_insert_new(file_cache,&id,size_uncomp); |
769 | ret = cache_insert_new(file_cache, &id, size_uncomp); |
|
|
770 | } |
553 | } else |
771 | else |
|
|
772 | { |
554 | ret=g_malloc(size_uncomp); |
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"); |
555 | lseek(file->fd, offset, SEEK_SET); |
781 | lseek(file->fd, offset, SEEK_SET); |
556 | |
|
|
557 | buffer = (char *)g_malloc(size); |
|
|
558 | if (read(file->fd, buffer, size) != size) { |
782 | if (read(file->fd, buffer, size) != size) |
559 | g_free(ret); |
783 | { |
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); |
784 | g_free(ret); |
565 | ret=NULL; |
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; |
566 | } |
794 | } |
567 | } |
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 | |
568 | g_free(buffer); |
937 | g_free(buffer); |
569 | |
938 | |
570 | return ret; |
939 | return ret; |
571 | } |
940 | } |
572 | |
941 | |
573 | unsigned char * |
942 | unsigned char * |
574 | file_data_read_encrypted(struct file *file, long long offset, int size, int size_uncomp, int compressed, char *passwd) |
943 | file_data_read_encrypted(struct file *file, long long offset, int size, int size_uncomp, int compressed, char *passwd) |
575 | { |
944 | { |
|
|
945 | //dbg(0,"_enter %s "LONGLONG_FMT" %d\n", file->name, offset, size); |
576 | #ifdef HAVE_LIBCRYPTO |
946 | #ifdef HAVE_LIBCRYPTO |
577 | void *ret; |
947 | void *ret; |
578 | unsigned char *buffer = 0; |
948 | unsigned char *buffer = 0; |
579 | uLongf destLen=size_uncomp; |
949 | uLongf destLen=size_uncomp; |
580 | |
950 | |
581 | if (file_cache) { |
951 | if (file_cache) |
582 | struct file_cache_id id={offset,size,file->name_id,1}; |
952 | { |
|
|
953 | //dbg(0,"_file_cache 3\n"); |
|
|
954 | struct file_cache_id id = |
|
|
955 | { offset,size,file->name_id,1}; |
583 | ret=cache_lookup(file_cache,&id); |
956 | ret=cache_lookup(file_cache,&id); |
584 | if (ret) |
957 | if (ret) |
|
|
958 | { |
|
|
959 | //dbg(0,"_file_cache found 3\n"); |
585 | return ret; |
960 | return ret; |
|
|
961 | } |
|
|
962 | //dbg(0,"_file_cache create new 3\n"); |
586 | ret=cache_insert_new(file_cache,&id,size_uncomp); |
963 | ret=cache_insert_new(file_cache,&id,size_uncomp); |
|
|
964 | } |
587 | } else |
965 | else |
|
|
966 | { |
588 | ret=g_malloc(size_uncomp); |
967 | ret=g_malloc(size_uncomp); |
|
|
968 | } |
589 | lseek(file->fd, offset, SEEK_SET); |
969 | lseek(file->fd, offset, SEEK_SET); |
590 | |
970 | |
591 | buffer = (unsigned char *)g_malloc(size); |
971 | buffer = (unsigned char *)g_malloc(size); |
592 | if (read(file->fd, buffer, size) != size) { |
972 | if (read(file->fd, buffer, size) != size) |
|
|
973 | { |
593 | g_free(ret); |
974 | g_free(ret); |
594 | ret=NULL; |
975 | ret=NULL; |
595 | } else { |
976 | } |
|
|
977 | else |
|
|
978 | { |
596 | unsigned char key[34], salt[8], verify[2], counter[16], xor[16], mac[10], *datap; |
979 | unsigned char key[34], salt[8], verify[2], counter[16], xor[16], mac[10], *datap; |
597 | int overhead=sizeof(salt)+sizeof(verify)+sizeof(mac); |
980 | int overhead=sizeof(salt)+sizeof(verify)+sizeof(mac); |
598 | int esize=size-overhead; |
981 | int esize=size-overhead; |
599 | PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), (unsigned char *)buffer, 8, 1000, 34, key); |
982 | 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) { |
983 | if (key[32] == buffer[8] && key[33] == buffer[9] && esize >= 0) |
|
|
984 | { |
601 | AES_KEY aeskey; |
985 | AES_KEY aeskey; |
602 | AES_set_encrypt_key(key, 128, &aeskey); |
986 | AES_set_encrypt_key(key, 128, &aeskey); |
603 | datap=buffer+sizeof(salt)+sizeof(verify); |
987 | datap=buffer+sizeof(salt)+sizeof(verify); |
604 | memset(counter, 0, sizeof(counter)); |
988 | memset(counter, 0, sizeof(counter)); |
605 | while (esize > 0) { |
989 | while (esize > 0) |
|
|
990 | { |
606 | int i,curr_size,idx=0; |
991 | int i,curr_size,idx=0; |
607 | do { |
992 | do |
|
|
993 | { |
608 | counter[idx]++; |
994 | counter[idx]++; |
609 | } while (!counter[idx++]); |
995 | }while (!counter[idx++]); |
|
|
996 | |
610 | AES_encrypt(counter, xor, &aeskey); |
997 | AES_encrypt(counter, xor, &aeskey); |
611 | curr_size=esize; |
998 | curr_size=esize; |
612 | if (curr_size > sizeof(xor)) |
999 | if (curr_size > sizeof(xor)) |
613 | curr_size=sizeof(xor); |
1000 | curr_size=sizeof(xor); |
614 | for (i = 0 ; i < curr_size ; i++) |
1001 | for (i = 0; i < curr_size; i++) |
615 | *datap++^=xor[i]; |
1002 | *datap++^=xor[i]; |
616 | esize-=curr_size; |
1003 | esize-=curr_size; |
617 | } |
1004 | } |
618 | size-=overhead; |
1005 | size-=overhead; |
619 | datap=buffer+sizeof(salt)+sizeof(verify); |
1006 | datap=buffer+sizeof(salt)+sizeof(verify); |
620 | if (compressed) { |
1007 | if (compressed) |
|
|
1008 | { |
621 | if (uncompress_int(ret, &destLen, (Bytef *)datap, size) != Z_OK) { |
1009 | if (uncompress_int(ret, &destLen, (Bytef *)datap, size) != Z_OK) |
|
|
1010 | { |
622 | dbg(0,"uncompress failed\n"); |
1011 | //dbg(0,"_uncompress failed\n"); |
623 | g_free(ret); |
1012 | g_free(ret); |
624 | ret=NULL; |
1013 | ret=NULL; |
625 | } |
1014 | } |
|
|
1015 | } |
626 | } else { |
1016 | else |
|
|
1017 | { |
627 | if (size == destLen) |
1018 | if (size == destLen) |
628 | memcpy(ret, buffer, destLen); |
1019 | memcpy(ret, buffer, destLen); |
629 | else { |
1020 | else |
|
|
1021 | { |
630 | dbg(0,"memcpy failed\n"); |
1022 | //dbg(0,"_memcpy failed\n"); |
631 | g_free(ret); |
1023 | g_free(ret); |
632 | ret=NULL; |
1024 | ret=NULL; |
633 | } |
1025 | } |
634 | } |
1026 | } |
|
|
1027 | } |
635 | } else { |
1028 | else |
|
|
1029 | { |
636 | g_free(ret); |
1030 | g_free(ret); |
637 | ret=NULL; |
1031 | ret=NULL; |
638 | } |
1032 | } |
639 | } |
1033 | } |
640 | g_free(buffer); |
1034 | g_free(buffer); |
… | |
… | |
643 | #else |
1037 | #else |
644 | return NULL; |
1038 | return NULL; |
645 | #endif |
1039 | #endif |
646 | } |
1040 | } |
647 | |
1041 | |
648 | void |
|
|
649 | file_data_free(struct file *file, unsigned char *data) |
1042 | void file_data_free(struct file *file, unsigned char *data) |
650 | { |
1043 | { |
|
|
1044 | //dbg(0,"_enter %s\n", file->name); |
651 | if (file->begin) { |
1045 | if (file->begin) |
|
|
1046 | { |
652 | if (data == file->begin) |
1047 | if (data == file->begin) |
653 | return; |
1048 | return; |
654 | if (data >= file->begin && data < file->end) |
1049 | if (data >= file->begin && data < file->end) |
655 | return; |
1050 | return; |
656 | } |
1051 | } |
|
|
1052 | |
657 | if (file->cache && data) { |
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 |
658 | cache_entry_destroy(file_cache, data); |
1061 | cache_entry_destroy(file_cache, data); |
|
|
1062 | } |
659 | } else |
1063 | else |
|
|
1064 | { |
660 | g_free(data); |
1065 | g_free(data); |
|
|
1066 | } |
|
|
1067 | //dbg(0,"_leave\n"); |
661 | } |
1068 | } |
662 | |
1069 | |
663 | void |
|
|
664 | file_data_remove(struct file *file, unsigned char *data) |
1070 | void file_data_remove(struct file *file, unsigned char *data) |
665 | { |
1071 | { |
|
|
1072 | //dbg(0,"_enter %s\n", file->name); |
666 | if (file->begin) { |
1073 | if (file->begin) |
|
|
1074 | { |
667 | if (data == file->begin) |
1075 | if (data == file->begin) |
|
|
1076 | { |
668 | return; |
1077 | return; |
|
|
1078 | } |
669 | if (data >= file->begin && data < file->end) |
1079 | if (data >= file->begin && data < file->end) |
|
|
1080 | { |
670 | return; |
1081 | return; |
671 | } |
1082 | } |
|
|
1083 | } |
672 | if (file->cache && data) { |
1084 | if (file->cache && data) |
|
|
1085 | { |
673 | cache_flush_data(file_cache, data); |
1086 | cache_flush_data(file_cache, data); |
|
|
1087 | } |
674 | } else |
1088 | else |
|
|
1089 | { |
675 | g_free(data); |
1090 | g_free(data); |
|
|
1091 | } |
676 | } |
1092 | } |
677 | |
1093 | |
678 | int |
|
|
679 | file_exists(char const *name) |
1094 | int file_exists(char const *name) |
680 | { |
1095 | { |
|
|
1096 | //dbg(0,"_enter %s\n", name); |
681 | struct stat buf; |
1097 | struct stat buf; |
682 | if (! stat(name, &buf)) |
1098 | if (!stat(name, &buf)) |
|
|
1099 | { |
683 | return 1; |
1100 | return 1; |
|
|
1101 | } |
684 | return 0; |
1102 | return 0; |
685 | } |
1103 | } |
686 | |
1104 | |
687 | void |
|
|
688 | file_remap_readonly(struct file *f) |
1105 | void file_remap_readonly(struct file *f) |
689 | { |
1106 | { |
|
|
1107 | //dbg(0,"_enter %s\n", f->name); |
690 | #if defined(_WIN32) || defined(__CEGCC__) |
1108 | #if defined(_WIN32) || defined(__CEGCC__) |
691 | #else |
1109 | #else |
692 | void *begin; |
1110 | void *begin; |
693 | munmap(f->begin, f->size); |
1111 | munmap(f->begin, f->size); |
694 | begin=mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0); |
1112 | begin = mmap(f->begin, f->size, PROT_READ, MAP_PRIVATE, f->fd, 0); |
695 | if (f->begin != begin) |
1113 | if (f->begin != begin) |
|
|
1114 | { |
696 | printf("remap failed\n"); |
1115 | printf("remap failed\n"); |
|
|
1116 | } |
697 | #endif |
1117 | #endif |
698 | } |
1118 | } |
699 | |
1119 | |
700 | void |
|
|
701 | file_unmap(struct file *f) |
1120 | void file_unmap(struct file *f) |
702 | { |
1121 | { |
|
|
1122 | //dbg(0,"_enter %s\n", f->name); |
703 | #if defined(_WIN32) || defined(__CEGCC__) |
1123 | #if defined(_WIN32) || defined(__CEGCC__) |
704 | mmap_unmap_win32( f->begin, f->map_handle , f->map_file ); |
1124 | mmap_unmap_win32( f->begin, f->map_handle , f->map_file ); |
705 | #else |
1125 | #else |
706 | munmap(f->begin, f->size); |
1126 | munmap(f->begin, f->size); |
707 | #endif |
1127 | #endif |
708 | } |
1128 | } |
709 | |
1129 | |
710 | #ifndef _MSC_VER |
1130 | #ifndef _MSC_VER |
711 | void * |
1131 | void * |
712 | file_opendir(char *dir) |
1132 | file_opendir(char *dir) |
713 | { |
1133 | { |
|
|
1134 | //dbg(0,"_enter %s\n", dir); |
714 | return opendir(dir); |
1135 | return opendir(dir); |
715 | } |
1136 | } |
716 | #else |
1137 | #else |
717 | void * |
1138 | void * |
718 | file_opendir(char *dir) |
1139 | file_opendir(char *dir) |
719 | { |
1140 | { |
|
|
1141 | //dbg(0,"_enter %s\n", dir); |
720 | WIN32_FIND_DATAA FindFileData; |
1142 | WIN32_FIND_DATAA FindFileData; |
721 | HANDLE hFind = INVALID_HANDLE_VALUE; |
1143 | HANDLE hFind = INVALID_HANDLE_VALUE; |
722 | #undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string |
1144 | #undef UNICODE // we need FindFirstFileA() which takes an 8-bit c-string |
723 | char* fname=g_alloca(sizeof(char)*(strlen(dir)+4)); |
1145 | char* fname=g_alloca(sizeof(char)*(strlen(dir)+4)); |
724 | sprintf(fname,"%s\\*",dir); |
1146 | sprintf(fname,"%s\\*",dir); |
… | |
… | |
729 | |
1151 | |
730 | #ifndef _MSC_VER |
1152 | #ifndef _MSC_VER |
731 | char * |
1153 | char * |
732 | file_readdir(void *hnd) |
1154 | file_readdir(void *hnd) |
733 | { |
1155 | { |
|
|
1156 | //dbg(0,"_enter\n"); |
734 | struct dirent *ent; |
1157 | struct dirent *ent; |
735 | |
1158 | |
736 | ent=readdir(hnd); |
1159 | ent = readdir(hnd); |
737 | if (! ent) |
1160 | if (!ent) |
738 | return NULL; |
1161 | return NULL; |
739 | return ent->d_name; |
1162 | return ent->d_name; |
740 | } |
1163 | } |
741 | #else |
1164 | #else |
742 | char * |
1165 | char * |
743 | file_readdir(void *hnd) |
1166 | file_readdir(void *hnd) |
744 | { |
1167 | { |
|
|
1168 | //dbg(0,"_enter\n"); |
745 | WIN32_FIND_DATA FindFileData; |
1169 | WIN32_FIND_DATA FindFileData; |
746 | |
1170 | |
747 | if (FindNextFile(hnd, &FindFileData) ) { |
1171 | if (FindNextFile(hnd, &FindFileData) ) |
|
|
1172 | { |
748 | return FindFileData.cFileName; |
1173 | return FindFileData.cFileName; |
749 | } else { |
1174 | } |
|
|
1175 | else |
|
|
1176 | { |
750 | return NULL; |
1177 | return NULL; |
751 | } |
1178 | } |
752 | } |
1179 | } |
753 | #endif /* _MSC_VER */ |
1180 | #endif /* _MSC_VER */ |
754 | |
1181 | |
755 | #ifndef _MSC_VER |
1182 | #ifndef _MSC_VER |
756 | void |
|
|
757 | file_closedir(void *hnd) |
1183 | void file_closedir(void *hnd) |
758 | { |
1184 | { |
|
|
1185 | //dbg(0,"_enter\n"); |
759 | closedir(hnd); |
1186 | closedir(hnd); |
760 | } |
1187 | } |
761 | #else |
1188 | #else |
762 | void |
1189 | void |
763 | file_closedir(void *hnd) |
1190 | file_closedir(void *hnd) |
764 | { |
1191 | { |
|
|
1192 | //dbg(0,"_enter\n"); |
765 | FindClose(hnd); |
1193 | FindClose(hnd); |
766 | } |
1194 | } |
767 | #endif /* _MSC_VER */ |
1195 | #endif /* _MSC_VER */ |
768 | |
1196 | |
769 | struct file * |
1197 | struct file * |
770 | file_create_caseinsensitive(char *name, struct attr **options) |
1198 | file_create_caseinsensitive(char *name, struct attr **options) |
771 | { |
1199 | { |
|
|
1200 | //dbg(0,"_enter %s\n", name); |
772 | char *dirname=g_alloca(sizeof(char)*(strlen(name)+1)); |
1201 | char *dirname = g_alloca(sizeof(char) * (strlen(name) + 1)); |
773 | char *filename; |
1202 | char *filename; |
774 | char *p; |
1203 | char *p; |
775 | void *d; |
1204 | void *d; |
776 | struct file *ret; |
1205 | struct file *ret; |
777 | |
1206 | |
778 | ret=file_create(name, options); |
1207 | ret = file_create(name, options); |
779 | if (ret) |
1208 | if (ret) |
|
|
1209 | { |
780 | return ret; |
1210 | return ret; |
|
|
1211 | } |
781 | |
1212 | |
782 | strcpy(dirname, name); |
1213 | strcpy(dirname, name); |
783 | p=dirname+strlen(name); |
1214 | p = dirname + strlen(name); |
784 | while (p > dirname) { |
1215 | while (p > dirname) |
|
|
1216 | { |
785 | if (*p == '/') |
1217 | if (*p == '/') |
786 | break; |
1218 | break; |
787 | p--; |
1219 | p--; |
788 | } |
1220 | } |
789 | *p=0; |
1221 | *p = 0; |
790 | d=file_opendir(dirname); |
1222 | d = file_opendir(dirname); |
791 | if (d) { |
1223 | if (d) |
|
|
1224 | { |
792 | *p++='/'; |
1225 | *p++ = '/'; |
793 | while ((filename=file_readdir(d))) { |
1226 | while ((filename = file_readdir(d))) |
|
|
1227 | { |
794 | if (!g_strcasecmp(filename, p)) { |
1228 | if (!g_strcasecmp(filename, p)) |
|
|
1229 | { |
795 | strcpy(p, filename); |
1230 | strcpy(p, filename); |
796 | ret=file_create(dirname, options); |
1231 | ret = file_create(dirname, options); |
797 | if (ret) |
1232 | if (ret) |
798 | break; |
1233 | break; |
799 | } |
1234 | } |
800 | } |
1235 | } |
801 | file_closedir(d); |
1236 | file_closedir(d); |
802 | } |
1237 | } |
803 | return ret; |
1238 | return ret; |
804 | } |
1239 | } |
805 | |
1240 | |
806 | void |
|
|
807 | file_destroy(struct file *f) |
1241 | void file_destroy(struct file *f) |
808 | { |
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 | |
809 | if (f->headers) |
1252 | if (f->headers) |
|
|
1253 | { |
810 | g_hash_table_destroy(f->headers); |
1254 | g_hash_table_destroy(f->headers); |
|
|
1255 | } |
811 | switch (f->special) { |
1256 | switch (f->special) |
|
|
1257 | { |
812 | case 0: |
1258 | case 0: |
813 | case 1: |
1259 | case 1: |
814 | close(f->fd); |
1260 | close(f->fd); |
815 | break; |
1261 | break; |
816 | } |
1262 | } |
817 | |
1263 | |
818 | if ( f->begin != NULL ) |
1264 | if (f->begin != NULL) |
819 | { |
1265 | { |
820 | file_unmap( f ); |
1266 | file_unmap(f); |
821 | } |
1267 | } |
822 | |
1268 | |
823 | g_free(f->buffer); |
1269 | g_free(f->buffer); |
824 | g_free(f->name); |
1270 | g_free(f->name); |
825 | g_free(f); |
1271 | g_free(f); |
826 | } |
1272 | } |
827 | |
1273 | |
828 | struct file_wordexp { |
1274 | struct file_wordexp |
|
|
1275 | { |
829 | int err; |
1276 | int err; |
|
|
1277 | char *pattern; |
830 | wordexp_t we; |
1278 | wordexp_t we; |
831 | }; |
1279 | }; |
832 | |
1280 | |
833 | struct file_wordexp * |
1281 | struct file_wordexp * |
834 | file_wordexp_new(const char *pattern) |
1282 | file_wordexp_new(const char *pattern) |
835 | { |
1283 | { |
|
|
1284 | dbg(0, "_enter\n"); |
836 | struct file_wordexp *ret=g_new0(struct file_wordexp, 1); |
1285 | struct file_wordexp *ret=g_new0(struct file_wordexp, 1); |
|
|
1286 | dbg(0, "fexp 001 p=%p\n", ret); |
837 | |
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); |
838 | ret->err=wordexp(pattern, &ret->we, 0); |
1290 | ret->err = wordexp(pattern, &ret->we, 0); |
|
|
1291 | dbg(0, "fexp 003\n"); |
839 | if (ret->err) |
1292 | if (ret->err) |
|
|
1293 | { |
840 | dbg(0,"wordexp('%s') returned %d\n", pattern, ret->err); |
1294 | // dbg(0, "wordexp('%s') returned %d\n", pattern, ret->err); |
|
|
1295 | } |
|
|
1296 | dbg(0, "leave\n"); |
841 | return ret; |
1297 | return ret; |
842 | } |
1298 | } |
843 | |
1299 | |
844 | int |
|
|
845 | file_wordexp_get_count(struct file_wordexp *wexp) |
1300 | int file_wordexp_get_count(struct file_wordexp *wexp) |
846 | { |
1301 | { |
|
|
1302 | //dbg(0,"_enter\n"); |
|
|
1303 | |
|
|
1304 | if (wexp->err) |
|
|
1305 | { |
|
|
1306 | return 1; |
|
|
1307 | } |
847 | return wexp->we.we_wordc; |
1308 | return wexp->we.we_wordc; |
848 | } |
1309 | } |
849 | |
1310 | |
850 | char ** |
1311 | char ** |
851 | file_wordexp_get_array(struct file_wordexp *wexp) |
1312 | file_wordexp_get_array(struct file_wordexp *wexp) |
852 | { |
1313 | { |
|
|
1314 | //dbg(0,"_enter\n"); |
|
|
1315 | |
|
|
1316 | if (wexp->err) |
|
|
1317 | { |
|
|
1318 | return &wexp->pattern; |
|
|
1319 | } |
853 | return wexp->we.we_wordv; |
1320 | return wexp->we.we_wordv; |
854 | } |
1321 | } |
855 | |
1322 | |
856 | void |
|
|
857 | file_wordexp_destroy(struct file_wordexp *wexp) |
1323 | void file_wordexp_destroy(struct file_wordexp *wexp) |
858 | { |
1324 | { |
|
|
1325 | //dbg(0,"_enter\n"); |
859 | if (! wexp->err) |
1326 | if (!wexp->err) |
|
|
1327 | { |
860 | wordfree(&wexp->we); |
1328 | wordfree(&wexp->we); |
|
|
1329 | } |
|
|
1330 | g_free(wexp->pattern); |
861 | g_free(wexp); |
1331 | g_free(wexp); |
862 | } |
1332 | } |
863 | |
1333 | |
864 | |
|
|
865 | int |
|
|
866 | file_get_param(struct file *file, struct param_list *param, int count) |
1334 | int file_get_param(struct file *file, struct param_list *param, int count) |
867 | { |
1335 | { |
|
|
1336 | //dbg(0,"_enter %s\n", file->name); |
868 | int i=count; |
1337 | int i = count; |
869 | param_add_string("Filename", file->name, ¶m, &count); |
1338 | param_add_string("Filename", file->name, ¶m, &count); |
870 | param_add_hex("Size", file->size, ¶m, &count); |
1339 | param_add_hex("Size", file->size, ¶m, &count); |
871 | return i-count; |
1340 | return i - count; |
872 | } |
1341 | } |
873 | |
1342 | |
874 | int |
|
|
875 | file_version(struct file *file, int mode) |
1343 | int file_version(struct file *file, int mode) |
876 | { |
1344 | { |
|
|
1345 | //dbg(0,"_enter %s\n", file->name); |
877 | #ifndef HAVE_API_WIN32_BASE |
1346 | #ifndef HAVE_API_WIN32_BASE |
878 | struct stat st; |
1347 | struct stat st; |
879 | int error; |
1348 | int error; |
880 | if (mode == 3) { |
1349 | if (mode == 3) |
|
|
1350 | { |
881 | long long size=lseek(file->fd, 0, SEEK_END); |
1351 | long long size = lseek(file->fd, 0, SEEK_END); |
882 | if (file->begin && file->begin+size > file->mmap_end) { |
1352 | if (file->begin && file->begin + size > file->mmap_end) |
|
|
1353 | { |
883 | file->version++; |
1354 | file->version++; |
|
|
1355 | } |
884 | } else { |
1356 | else |
|
|
1357 | { |
885 | file->size=size; |
1358 | file->size = size; |
886 | if (file->begin) |
1359 | if (file->begin) |
|
|
1360 | { |
887 | file->end=file->begin+file->size; |
1361 | file->end = file->begin + file->size; |
888 | } |
1362 | } |
889 | } else { |
1363 | } |
|
|
1364 | } |
|
|
1365 | else |
|
|
1366 | { |
890 | if (mode == 2) |
1367 | if (mode == 2) |
|
|
1368 | { |
891 | error=stat(file->name, &st); |
1369 | error = stat(file->name, &st); |
|
|
1370 | } |
892 | else |
1371 | else |
|
|
1372 | { |
893 | error=fstat(file->fd, &st); |
1373 | error = fstat(file->fd, &st); |
|
|
1374 | } |
894 | if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime) { |
1375 | if (error || !file->version || file->mtime != st.st_mtime || file->ctime != st.st_ctime) |
|
|
1376 | { |
895 | file->mtime=st.st_mtime; |
1377 | file->mtime = st.st_mtime; |
896 | file->ctime=st.st_ctime; |
1378 | file->ctime = st.st_ctime; |
897 | file->version++; |
1379 | file->version++; |
898 | dbg(1,"%s now version %d\n", file->name, file->version); |
1380 | // dbg(1, "%s now version %d\n", file->name, file->version); |
899 | } |
1381 | } |
900 | } |
1382 | } |
901 | return file->version; |
1383 | return file->version; |
902 | #else |
1384 | #else |
903 | return 0; |
1385 | return 0; |
… | |
… | |
905 | } |
1387 | } |
906 | |
1388 | |
907 | void * |
1389 | void * |
908 | file_get_os_handle(struct file *file) |
1390 | file_get_os_handle(struct file *file) |
909 | { |
1391 | { |
|
|
1392 | //dbg(0,"_enter %s\n", file->name); |
910 | return GINT_TO_POINTER(file->fd); |
1393 | return GINT_TO_POINTER(file->fd); |
911 | } |
1394 | } |
912 | |
1395 | |
913 | void |
1396 | void file_cache_init(void) |
914 | file_init(void) |
|
|
915 | { |
1397 | { |
916 | #ifdef CACHE_SIZE |
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); |
917 | file_name_hash=g_hash_table_new(g_str_hash, g_str_equal); |
1417 | 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); |
1418 | // file_cache=cache_new(sizeof(struct file_cache_id), cache_size_file); |
|
|
1419 | file_cache = NULL; // set later!! |
|
|
1420 | dbg(0,"leave\n"); |
919 | #endif |
1421 | #endif |
920 | } |
1422 | } |
921 | |
1423 | |
922 | |
|
|
923 | |
|
|
924 | void file_cache_init(void) |
|
|
925 | { |
|
|
926 | } |
|
|
927 | |
|
|