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 4367 : return (struct fzp *)calloc_w(1, sizeof(struct fzp), __func__);
16 : }
17 :
18 4367 : static void fzp_free(struct fzp **fzp)
19 : {
20 8734 : if(!fzp || !*fzp) return;
21 4367 : free_w(&(*fzp)->buf);
22 4367 : free_v((void **)fzp);
23 : }
24 :
25 3076 : static FILE *open_fp(const char *fname, const char *mode)
26 : {
27 3076 : FILE *fp=NULL;
28 3076 : if(!(fp=fopen(fname, mode)))
29 50 : logp("could not open %s: %s\n", fname, strerror(errno));
30 3076 : return fp;
31 : }
32 :
33 1250 : static gzFile open_zp(const char *fname, const char *mode)
34 : {
35 1250 : gzFile zp=NULL;
36 :
37 1250 : if(!(zp=gzopen(fname, mode)))
38 3 : logp("could not open %s: %s\n", fname, strerror(errno));
39 1250 : return zp;
40 : }
41 :
42 3117 : static int close_fp(FILE **fp)
43 : {
44 3117 : int ret=0;
45 3117 : if(!*fp) return ret;
46 3067 : if(fclose(*fp))
47 : {
48 0 : logp("fclose failed: %s\n", strerror(errno));
49 0 : ret=-1;
50 : }
51 3067 : *fp=NULL;
52 3067 : return ret;
53 : }
54 :
55 1250 : static int close_zp(gzFile *zp)
56 : {
57 : int e;
58 1250 : int ret=0;
59 1250 : if(!*zp) return ret;
60 1247 : 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 4326 : static struct fzp *fzp_do_open(const char *path, const char *mode,
85 : enum fzp_type type)
86 : {
87 4326 : struct fzp *fzp=NULL;
88 :
89 4326 : if(!(fzp=fzp_alloc())) goto error;
90 4326 : fzp->type=type;
91 4326 : switch(type)
92 : {
93 : case FZP_FILE:
94 3076 : if(!(fzp->fp=open_fp(path, mode)))
95 : goto error;
96 3026 : return fzp;
97 : case FZP_COMPRESSED:
98 1250 : if(!(fzp->zp=open_zp(path, mode)))
99 : goto error;
100 1247 : return fzp;
101 : default:
102 0 : unknown_type(fzp->type, __func__);
103 : goto error;
104 : }
105 : error:
106 53 : fzp_close(&fzp);
107 53 : return NULL;
108 : }
109 :
110 3076 : struct fzp *fzp_open(const char *path, const char *mode)
111 : {
112 3076 : return fzp_do_open(path, mode, FZP_FILE);
113 : }
114 :
115 1250 : struct fzp *fzp_gzopen(const char *path, const char *mode)
116 : {
117 1250 : return fzp_do_open(path, mode, FZP_COMPRESSED);
118 : }
119 :
120 124313 : int fzp_close(struct fzp **fzp)
121 : {
122 124313 : int ret=-1;
123 124313 : if(!fzp || !*fzp) return 0;
124 4367 : switch((*fzp)->type)
125 : {
126 : case FZP_FILE:
127 3117 : ret=close_fp(&((*fzp)->fp));
128 3117 : break;
129 : case FZP_COMPRESSED:
130 1250 : ret=close_zp(&((*fzp)->zp));
131 1250 : break;
132 : default:
133 0 : unknown_type((*fzp)->type, __func__);
134 : break;
135 : }
136 4367 : fzp_free(fzp);
137 4367 : return ret;
138 : }
139 :
140 740129 : int fzp_read(struct fzp *fzp, void *ptr, size_t nmemb)
141 : {
142 740129 : if(fzp) switch(fzp->type)
143 : {
144 : case FZP_FILE:
145 919700 : return (int)fread(ptr, 1, nmemb, fzp->fp);
146 : case FZP_COMPRESSED:
147 280278 : 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 479057 : size_t fzp_write(struct fzp *fzp, const void *ptr, size_t nmemb)
158 : {
159 479057 : if(fzp) switch(fzp->type)
160 : {
161 : case FZP_FILE:
162 302623 : return fwrite(ptr, 1, nmemb, fzp->fp);
163 : case FZP_COMPRESSED:
164 176433 : 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 705 : int fzp_eof(struct fzp *fzp)
175 : {
176 705 : if(fzp) switch(fzp->type)
177 : {
178 : case FZP_FILE:
179 350 : return feof(fzp->fp);
180 : case FZP_COMPRESSED:
181 354 : 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 22 : int fzp_flush(struct fzp *fzp)
193 : {
194 22 : if(fzp) switch(fzp->type)
195 : {
196 : case FZP_FILE:
197 15 : 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 262 : int fzp_seek(struct fzp *fzp, off_t offset, int whence)
210 : {
211 262 : if(fzp) switch(fzp->type)
212 : {
213 : case FZP_FILE:
214 10 : return fseeko(fzp->fp, offset, whence);
215 : case FZP_COMPRESSED:
216 : // Notice that gzseek returns the new offset.
217 251 : 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 13001 : off_t fzp_tell(struct fzp *fzp)
230 : {
231 13001 : if(fzp) switch(fzp->type)
232 : {
233 : case FZP_FILE:
234 12895 : return ftello(fzp->fp);
235 : case FZP_COMPRESSED:
236 105 : 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 209 : int fzp_truncate(const char *path, enum fzp_type type, off_t length,
277 : int compression)
278 : {
279 209 : switch(type)
280 : {
281 : case FZP_FILE:
282 205 : return truncate(path, length);
283 : case FZP_COMPRESSED:
284 4 : return gztruncate(path, length, compression);
285 : default:
286 : unknown_type(type, __func__);
287 : goto error;
288 : }
289 : error:
290 0 : return -1;
291 : }
292 : #endif
293 :
294 942677 : int fzp_printf(struct fzp *fzp, const char *format, ...)
295 : {
296 942677 : int ret=-1;
297 : int n;
298 :
299 942677 : if(!fzp)
300 : {
301 : not_open(__func__);
302 1 : return ret;
303 : }
304 :
305 942676 : if(!fzp->buf)
306 : {
307 1549 : fzp->s=128;
308 1549 : if(!(fzp->buf=(char *)malloc_w(fzp->s, __func__)))
309 : return ret;
310 : }
311 :
312 : // Avoid fixed size buffer.
313 : while(1)
314 : {
315 : va_list ap;
316 942676 : va_start(ap, format);
317 1885352 : n=vsnprintf(fzp->buf, fzp->s, format, ap);
318 942676 : va_end(ap);
319 942676 : if(n<0)
320 : {
321 0 : logp("Failed to vsnprintf in %s: %s\n",
322 0 : __func__, strerror(errno));
323 0 : return ret;
324 : }
325 942676 : if(fzp->s<(size_t)n)
326 : {
327 0 : fzp->s*=2;
328 0 : if(!(fzp->buf=(char *)
329 0 : realloc_w(fzp->buf, fzp->s, __func__)))
330 : return ret;
331 0 : continue;
332 : }
333 :
334 942676 : break;
335 : }
336 :
337 942676 : switch(fzp->type)
338 : {
339 : case FZP_FILE:
340 1179502 : ret=fprintf(fzp->fp, "%s", fzp->buf);
341 589751 : break;
342 : case FZP_COMPRESSED:
343 352925 : ret=gzprintf(fzp->zp, "%s", fzp->buf);
344 352925 : break;
345 : default:
346 0 : unknown_type(fzp->type, __func__);
347 : break;
348 : }
349 :
350 942676 : return ret;
351 : }
352 :
353 13 : void fzp_setlinebuf(struct fzp *fzp)
354 : {
355 : #ifndef HAVE_WIN32
356 13 : if(fzp) switch(fzp->type)
357 : {
358 : case FZP_FILE:
359 12 : setlinebuf(fzp->fp);
360 12 : return;
361 : case FZP_COMPRESSED:
362 0 : logp("gzsetlinebuf() does not exist in %s\n", __func__);
363 0 : return;
364 : default:
365 0 : unknown_type(fzp->type, __func__);
366 : return;
367 : }
368 : not_open(__func__);
369 : #endif
370 : }
371 :
372 1221 : char *fzp_gets(struct fzp *fzp, char *s, int size)
373 : {
374 1221 : if(fzp) switch(fzp->type)
375 : {
376 : case FZP_FILE:
377 2440 : return fgets(s, size, fzp->fp);
378 : case FZP_COMPRESSED:
379 0 : return gzgets(fzp->zp, s, size);
380 : default:
381 0 : unknown_type(fzp->type, __func__);
382 : goto error;
383 : }
384 : not_open(__func__);
385 : error:
386 : return NULL;
387 : }
388 :
389 12 : extern int fzp_fileno(struct fzp *fzp)
390 : {
391 12 : if(fzp) switch(fzp->type)
392 : {
393 : case FZP_FILE:
394 11 : return fileno(fzp->fp);
395 : case FZP_COMPRESSED:
396 0 : logp("gzfileno() does not exist in %s\n", __func__);
397 0 : goto error;
398 : default:
399 0 : unknown_type(fzp->type, __func__);
400 : goto error;
401 : }
402 : not_open(__func__);
403 : error:
404 : return -1;
405 : }
406 :
407 41 : static struct fzp *fzp_do_dopen(int fd, const char *mode,
408 : enum fzp_type type)
409 : {
410 41 : struct fzp *fzp=NULL;
411 :
412 41 : if(!(fzp=fzp_alloc())) goto error;
413 41 : fzp->type=type;
414 41 : switch(type)
415 : {
416 : case FZP_FILE:
417 41 : if(!(fzp->fp=fdopen(fd, mode)))
418 : goto error;
419 41 : return fzp;
420 : case FZP_COMPRESSED:
421 0 : if(!(fzp->zp=gzdopen(fd, mode)))
422 : goto error;
423 0 : return fzp;
424 : default:
425 0 : unknown_type(fzp->type, __func__);
426 : goto error;
427 : }
428 : error:
429 0 : fzp_close(&fzp);
430 0 : return NULL;
431 : }
432 :
433 41 : struct fzp *fzp_dopen(int fd, const char *mode)
434 : {
435 41 : return fzp_do_dopen(fd, mode, FZP_FILE);
436 : }
437 :
438 0 : struct fzp *fzp_gzdopen(int fd, const char *mode)
439 : {
440 0 : return fzp_do_dopen(fd, mode, FZP_COMPRESSED);
441 : }
442 :
443 1 : void fzp_ERR_print_errors_fp(struct fzp *fzp)
444 : {
445 1 : if(fzp) switch(fzp->type)
446 : {
447 : case FZP_FILE:
448 0 : ERR_print_errors_fp(fzp->fp);
449 0 : break;
450 : case FZP_COMPRESSED:
451 0 : logp("ERR_print_errors_zp() does not exist in %s\n",
452 : __func__);
453 0 : break;
454 : default:
455 0 : unknown_type(fzp->type, __func__);
456 : break;
457 : }
458 1 : }
459 :
460 1 : X509 *fzp_PEM_read_X509(struct fzp *fzp)
461 : {
462 1 : if(fzp) switch(fzp->type)
463 : {
464 : case FZP_FILE:
465 0 : return PEM_read_X509(fzp->fp, NULL, NULL, NULL);
466 : case FZP_COMPRESSED:
467 0 : logp("PEM_read_X509() does not exist in %s\n",
468 : __func__);
469 0 : goto error;
470 : default:
471 0 : unknown_type(fzp->type, __func__);
472 : goto error;
473 : }
474 : not_open(__func__);
475 : error:
476 : return NULL;
477 : }
478 :
479 : static void pass_msg(size_t nmemb, size_t got, int pass)
480 : {
481 59 : logp("Tried to read %lu bytes, got %lu by pass %d\n",
482 : (unsigned long)nmemb, (unsigned long)got, pass);
483 : }
484 :
485 736334 : int fzp_read_ensure(struct fzp *fzp, void *ptr, size_t nmemb, const char *func)
486 : {
487 : static int f;
488 : static int r;
489 : static size_t got;
490 : static int pass;
491 1472060 : for(r=0, got=0, pass=0; got!=nmemb; pass++)
492 : {
493 736393 : r=fzp_read(fzp, ((char *)ptr)+got, nmemb-got);
494 736393 : if(r>0)
495 : {
496 735726 : got+=r;
497 735726 : continue;
498 : }
499 667 : if(r<0)
500 : {
501 0 : pass_msg(nmemb, got, pass);
502 0 : logp("Error in %s, called from %s: %s\n",
503 0 : __func__, func, strerror(errno));
504 0 : return -1;
505 : }
506 667 : f=fzp_eof(fzp);
507 667 : if(!f) continue; // Not yet end of file, keep trying.
508 667 : if(f>0)
509 : {
510 : // End of file.
511 667 : if(!got) return 1;
512 59 : pass_msg(nmemb, got, pass);
513 59 : logp("Error in %s, called from %s: %lu bytes, eof\n",
514 : __func__, func, (unsigned long)got);
515 59 : return -1;
516 : }
517 : else
518 : {
519 0 : pass_msg(nmemb, got, pass);
520 0 : logp("Error in %s by fzp_feof, called from %s: %s\n",
521 0 : __func__, func, strerror(errno));
522 0 : return -1;
523 : }
524 : }
525 : return 0;
526 : }
|