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