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