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