Line data Source code
1 : #include "burp.h"
2 : #include "alloc.h"
3 : #include "cmd.h"
4 : #include "fsops.h"
5 : #include "fzp.h"
6 : #include "log.h"
7 : #include "prepend.h"
8 : #ifndef HAVE_WIN32
9 : #include "server/compress.h"
10 : #include "server/protocol1/zlibio.h"
11 : #endif
12 :
13 : static struct fzp *fzp_alloc(void)
14 : {
15 3662 : return (struct fzp *)calloc_w(1, sizeof(struct fzp), __func__);
16 : }
17 :
18 : static void fzp_free(struct fzp **fzp)
19 : {
20 3662 : if(!fzp || !*fzp) return;
21 3662 : free_v((void **)fzp);
22 : }
23 :
24 3006 : FILE *open_fp(const char *fname, const char *mode)
25 : {
26 3006 : FILE *fp=NULL;
27 3006 : if(!(fp=fopen(fname, mode)))
28 27 : logp("could not open %s: %s\n", fname, strerror(errno));
29 3006 : return fp;
30 : }
31 :
32 656 : gzFile open_zp(const char *fname, const char *mode)
33 : {
34 656 : gzFile zp=NULL;
35 :
36 656 : if(!(zp=gzopen(fname, mode)))
37 1 : logp("could not open %s: %s\n", fname, strerror(errno));
38 656 : return zp;
39 : }
40 :
41 3006 : static int close_fp(FILE **fp)
42 : {
43 3006 : int ret=0;
44 3006 : if(!*fp) return ret;
45 2979 : if(fclose(*fp))
46 : {
47 0 : logp("fclose failed: %s\n", strerror(errno));
48 0 : ret=-1;
49 : }
50 2979 : *fp=NULL;
51 2979 : return ret;
52 : }
53 :
54 656 : static int close_zp(gzFile *zp)
55 : {
56 : int e;
57 656 : int ret=0;
58 656 : if(!*zp) return ret;
59 655 : if((e=gzclose(*zp)))
60 : {
61 0 : const char *str=NULL;
62 0 : if(e==Z_ERRNO) str=strerror(errno);
63 0 : else str=gzerror(*zp, &e);
64 0 : logp("gzclose failed: %d (%s)\n", e, str?:"");
65 0 : ret=-1;
66 : }
67 655 : return ret;
68 : }
69 :
70 : static void unknown_type(enum fzp_type type, const char *func)
71 : {
72 0 : logp("unknown type in %s: %d\n", func, type);
73 : }
74 :
75 : static void not_open(const char *func)
76 : {
77 11 : logp("File pointer not open in %s\n", func);
78 : }
79 :
80 3662 : static struct fzp *fzp_do_open(const char *path, const char *mode,
81 : enum fzp_type type)
82 : {
83 3662 : struct fzp *fzp=NULL;
84 :
85 3662 : if(!(fzp=fzp_alloc())) goto error;
86 3662 : fzp->type=type;
87 3662 : switch(type)
88 : {
89 : case FZP_FILE:
90 3006 : if(!(fzp->fp=open_fp(path, mode)))
91 : goto error;
92 2979 : return fzp;
93 : case FZP_COMPRESSED:
94 656 : if(!(fzp->zp=open_zp(path, mode)))
95 : goto error;
96 655 : return fzp;
97 : default:
98 0 : unknown_type(fzp->type, __func__);
99 : goto error;
100 : }
101 : error:
102 28 : fzp_close(&fzp);
103 28 : return NULL;
104 : }
105 :
106 3006 : struct fzp *fzp_open(const char *path, const char *mode)
107 : {
108 3006 : return fzp_do_open(path, mode, FZP_FILE);
109 : }
110 :
111 656 : struct fzp *fzp_gzopen(const char *path, const char *mode)
112 : {
113 656 : return fzp_do_open(path, mode, FZP_COMPRESSED);
114 : }
115 :
116 122079 : int fzp_close(struct fzp **fzp)
117 : {
118 122079 : int ret=-1;
119 122079 : if(!fzp || !*fzp) return 0;
120 3662 : switch((*fzp)->type)
121 : {
122 : case FZP_FILE:
123 3006 : ret=close_fp(&((*fzp)->fp));
124 3006 : break;
125 : case FZP_COMPRESSED:
126 656 : ret=close_zp(&((*fzp)->zp));
127 656 : break;
128 : default:
129 0 : unknown_type((*fzp)->type, __func__);
130 : break;
131 : }
132 : fzp_free(fzp);
133 3662 : return ret;
134 : }
135 :
136 737139 : int fzp_read(struct fzp *fzp, void *ptr, size_t nmemb)
137 : {
138 737139 : if(fzp) switch(fzp->type)
139 : {
140 : case FZP_FILE:
141 922204 : return (int)fread(ptr, 1, nmemb, fzp->fp);
142 : case FZP_COMPRESSED:
143 276036 : return gzread(fzp->zp, ptr, (unsigned)nmemb);
144 : default:
145 0 : unknown_type(fzp->type, __func__);
146 : goto error;
147 : }
148 : not_open(__func__);
149 : error:
150 : return 0;
151 : }
152 :
153 468950 : size_t fzp_write(struct fzp *fzp, const void *ptr, size_t nmemb)
154 : {
155 468950 : if(fzp) switch(fzp->type)
156 : {
157 : case FZP_FILE:
158 294834 : return fwrite(ptr, 1, nmemb, fzp->fp);
159 : case FZP_COMPRESSED:
160 174115 : return gzwrite(fzp->zp, ptr, (unsigned)nmemb);
161 : default:
162 0 : unknown_type(fzp->type, __func__);
163 : goto error;
164 : }
165 : not_open(__func__);
166 : error:
167 : return 0;
168 : }
169 :
170 476 : int fzp_eof(struct fzp *fzp)
171 : {
172 476 : if(fzp) switch(fzp->type)
173 : {
174 : case FZP_FILE:
175 338 : return feof(fzp->fp);
176 : case FZP_COMPRESSED:
177 137 : return gzeof(fzp->zp);
178 : default:
179 0 : unknown_type(fzp->type, __func__);
180 : goto error;
181 : }
182 : not_open(__func__);
183 : error:
184 : // Non-zero means end of file. Should be OK to use -1 here.
185 : return -1;
186 : }
187 :
188 13 : int fzp_flush(struct fzp *fzp)
189 : {
190 13 : if(fzp) switch(fzp->type)
191 : {
192 : case FZP_FILE:
193 6 : return fflush(fzp->fp);
194 : case FZP_COMPRESSED:
195 6 : return gzflush(fzp->zp, Z_FINISH);
196 : default:
197 0 : unknown_type(fzp->type, __func__);
198 : goto error;
199 : }
200 : not_open(__func__);
201 : error:
202 : return EOF;
203 : }
204 :
205 261 : int fzp_seek(struct fzp *fzp, off_t offset, int whence)
206 : {
207 261 : if(fzp) switch(fzp->type)
208 : {
209 : case FZP_FILE:
210 9 : return fseeko(fzp->fp, offset, whence);
211 : case FZP_COMPRESSED:
212 : // Notice that gzseek returns the new offset.
213 251 : if(gzseek(fzp->zp, offset, whence)==offset)
214 : return 0;
215 : goto error;
216 : default:
217 0 : unknown_type(fzp->type, __func__);
218 : goto error;
219 : }
220 : not_open(__func__);
221 : error:
222 : return -1;
223 : }
224 :
225 13001 : off_t fzp_tell(struct fzp *fzp)
226 : {
227 13001 : if(fzp) switch(fzp->type)
228 : {
229 : case FZP_FILE:
230 12895 : return ftello(fzp->fp);
231 : case FZP_COMPRESSED:
232 105 : return gztell(fzp->zp);
233 : default:
234 0 : unknown_type(fzp->type, __func__);
235 : goto error;
236 : }
237 : not_open(__func__);
238 : error:
239 : return -1;
240 : }
241 :
242 : #ifndef HAVE_WIN32
243 : // There is no zlib gztruncate. Inflate it, truncate it, recompress it.
244 4 : static int gztruncate(const char *path, off_t length, int compression)
245 : {
246 4 : int ret=1;
247 : char tmp[16];
248 4 : char *dest=NULL;
249 4 : char *dest2=NULL;
250 4 : snprintf(tmp, sizeof(tmp), ".%d", getpid());
251 8 : if(!(dest=prepend(path, tmp))
252 4 : || !(dest2=prepend(dest, "-2"))
253 8 : || zlib_inflate(NULL, path, dest, NULL))
254 : goto end;
255 4 : if(truncate(dest, length))
256 : {
257 0 : logp("truncate of %s failed in %s\n", dest, __func__);
258 0 : goto end;
259 : }
260 4 : if(compress_file(dest, dest2, compression))
261 : goto end;
262 4 : unlink(dest);
263 4 : ret=do_rename(dest2, path);
264 : end:
265 4 : if(dest) unlink(dest);
266 4 : if(dest2) unlink(dest2);
267 4 : free_w(&dest);
268 4 : free_w(&dest2);
269 4 : return ret;
270 : }
271 :
272 209 : int fzp_truncate(const char *path, enum fzp_type type, off_t length,
273 : int compression)
274 : {
275 209 : switch(type)
276 : {
277 : case FZP_FILE:
278 205 : return truncate(path, length);
279 : case FZP_COMPRESSED:
280 4 : return gztruncate(path, length, compression);
281 : default:
282 : unknown_type(type, __func__);
283 : goto error;
284 : }
285 : error:
286 0 : return -1;
287 : }
288 : #endif
289 :
290 924988 : int fzp_printf(struct fzp *fzp, const char *format, ...)
291 : {
292 : static char buf[4096];
293 924988 : int ret=-1;
294 : va_list ap;
295 924988 : va_start(ap, format);
296 : vsnprintf(buf, sizeof(buf), format, ap);
297 :
298 924988 : if(fzp) switch(fzp->type)
299 : {
300 : case FZP_FILE:
301 1153520 : ret=fprintf(fzp->fp, "%s", buf);
302 576760 : break;
303 : case FZP_COMPRESSED:
304 348227 : ret=gzprintf(fzp->zp, "%s", buf);
305 348227 : break;
306 : default:
307 0 : unknown_type(fzp->type, __func__);
308 : break;
309 : }
310 : else
311 : not_open(__func__);
312 924988 : va_end(ap);
313 924988 : return ret;
314 : }
315 :
316 6 : void fzp_setlinebuf(struct fzp *fzp)
317 : {
318 : #ifndef HAVE_WIN32
319 6 : if(fzp) switch(fzp->type)
320 : {
321 : case FZP_FILE:
322 5 : setlinebuf(fzp->fp);
323 5 : return;
324 : case FZP_COMPRESSED:
325 0 : logp("gzsetlinebuf() does not exist in %s\n", __func__);
326 0 : return;
327 : default:
328 0 : unknown_type(fzp->type, __func__);
329 : return;
330 : }
331 : not_open(__func__);
332 : #endif
333 : }
334 :
335 1238 : char *fzp_gets(struct fzp *fzp, char *s, int size)
336 : {
337 1238 : if(fzp) switch(fzp->type)
338 : {
339 : case FZP_FILE:
340 2474 : return fgets(s, size, fzp->fp);
341 : case FZP_COMPRESSED:
342 0 : return gzgets(fzp->zp, s, size);
343 : default:
344 0 : unknown_type(fzp->type, __func__);
345 : goto error;
346 : }
347 : not_open(__func__);
348 : error:
349 : return NULL;
350 : }
351 :
352 1 : extern int fzp_fileno(struct fzp *fzp)
353 : {
354 1 : if(fzp) switch(fzp->type)
355 : {
356 : case FZP_FILE:
357 0 : return fileno(fzp->fp);
358 : case FZP_COMPRESSED:
359 0 : logp("gzfileno() does not exist in %s\n", __func__);
360 0 : goto error;
361 : default:
362 0 : unknown_type(fzp->type, __func__);
363 : goto error;
364 : }
365 : not_open(__func__);
366 : error:
367 : return -1;
368 : }
369 :
370 0 : static struct fzp *fzp_do_dopen(int fd, const char *mode,
371 : enum fzp_type type)
372 : {
373 0 : struct fzp *fzp=NULL;
374 :
375 0 : if(!(fzp=fzp_alloc())) goto error;
376 0 : fzp->type=type;
377 0 : switch(type)
378 : {
379 : case FZP_FILE:
380 0 : if(!(fzp->fp=fdopen(fd, mode)))
381 : goto error;
382 0 : return fzp;
383 : case FZP_COMPRESSED:
384 0 : if(!(fzp->zp=gzdopen(fd, mode)))
385 : goto error;
386 0 : return fzp;
387 : default:
388 0 : unknown_type(fzp->type, __func__);
389 : goto error;
390 : }
391 : error:
392 0 : fzp_close(&fzp);
393 0 : return NULL;
394 : }
395 :
396 0 : struct fzp *fzp_dopen(int fd, const char *mode)
397 : {
398 0 : return fzp_do_dopen(fd, mode, FZP_FILE);
399 : }
400 :
401 0 : struct fzp *fzp_gzdopen(int fd, const char *mode)
402 : {
403 0 : return fzp_do_dopen(fd, mode, FZP_COMPRESSED);
404 : }
405 :
406 1 : void fzp_ERR_print_errors_fp(struct fzp *fzp)
407 : {
408 1 : if(fzp) switch(fzp->type)
409 : {
410 : case FZP_FILE:
411 0 : ERR_print_errors_fp(fzp->fp);
412 0 : break;
413 : case FZP_COMPRESSED:
414 : logp("ERR_print_errors_zp() does not exist in %s\n",
415 0 : __func__);
416 0 : break;
417 : default:
418 0 : unknown_type(fzp->type, __func__);
419 : break;
420 : }
421 1 : }
422 :
423 1 : X509 *fzp_PEM_read_X509(struct fzp *fzp)
424 : {
425 1 : if(fzp) switch(fzp->type)
426 : {
427 : case FZP_FILE:
428 0 : return PEM_read_X509(fzp->fp, NULL, NULL, NULL);
429 : case FZP_COMPRESSED:
430 : logp("PEM_read_X509() does not exist in %s\n",
431 0 : __func__);
432 0 : goto error;
433 : default:
434 0 : unknown_type(fzp->type, __func__);
435 : goto error;
436 : }
437 : not_open(__func__);
438 : error:
439 : return NULL;
440 : }
441 :
442 : static void pass_msg(size_t nmemb, size_t got, int pass)
443 : {
444 : logp("Tried to read %u bytes, got %u by pass %d\n",
445 59 : nmemb, got, pass);
446 : }
447 :
448 732042 : int fzp_read_ensure(struct fzp *fzp, void *ptr, size_t nmemb, const char *func)
449 : {
450 : static int f;
451 : static int r;
452 : static size_t got;
453 : static int pass;
454 1463700 : for(r=0, got=0, pass=0; got!=nmemb; pass++)
455 : {
456 732101 : r=fzp_read(fzp, ((char *)ptr)+got, nmemb-got);
457 732101 : if(r>0)
458 : {
459 731658 : got+=r;
460 731658 : continue;
461 : }
462 443 : if(r<0)
463 : {
464 0 : pass_msg(nmemb, got, pass);
465 : logp("Error in %s, called from %s: %s\n",
466 0 : __func__, func, strerror(errno));
467 0 : return -1;
468 : }
469 443 : f=fzp_eof(fzp);
470 443 : if(!f) continue; // Not yet end of file, keep trying.
471 443 : if(f>0)
472 : {
473 : // End of file.
474 443 : if(!got) return 1;
475 59 : pass_msg(nmemb, got, pass);
476 : logp("Error in %s, called from %s: %u bytes, eof\n",
477 59 : __func__, func, got);
478 59 : return -1;
479 : }
480 : else
481 : {
482 0 : pass_msg(nmemb, got, pass);
483 : logp("Error in %s by fzp_feof, called from %s: %s\n",
484 0 : __func__, func, strerror(errno));
485 0 : return -1;
486 : }
487 : }
488 : return 0;
489 : }
|