1 /*
2 * Copyright (c) 2005 Michael Schroeder (mls@suse.de)
3 *
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
6 */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <unistd.h>
13
14 #include <zlib.h>
15 #include <bzlib.h>
16 #include <lzma.h>
17
18 #include "cfile.h"
19
20 /*****************************************************************
21 * generic input/output routines
22 */
23
24 static int
cfile_readbuf(struct cfile * f,unsigned char * buf,int len)25 cfile_readbuf(struct cfile *f, unsigned char *buf, int len)
26 {
27 if (len < 0)
28 return -1;
29 if (f->len != CFILE_LEN_UNLIMITED && len > f->len)
30 len = f->len;
31 if (!len)
32 {
33 f->bufN = 0;
34 return 0;
35 }
36 switch (f->fd)
37 {
38 case CFILE_IO_FILE:
39 if (f->len == CFILE_LEN_UNLIMITED)
40 {
41 len = fread(buf, 1, len, (FILE *)f->fp);
42 if (len == 0 && ferror((FILE *)f->fp))
43 return -1;
44 }
45 else if (fread(buf, len, 1, (FILE *)f->fp) != 1)
46 return -1;
47 break;
48 case CFILE_IO_CFILE:
49 len = ((struct cfile *)f->fp)->read((struct cfile *)f->fp, buf, len);
50 break;
51 case CFILE_IO_PUSHBACK:
52 len = ((struct cfile *)f->fp)->read((struct cfile *)f->fp, buf, len);
53 if (((struct cfile *)f->fp)->nunread == 0)
54 {
55 struct cfile *cf = (struct cfile *)f->fp;
56 f->fp = cf->fp;
57 f->fd = cf->fd;
58 cf->close(cf);
59 }
60 break;
61 case CFILE_IO_ALLOC:
62 return -1;
63 case CFILE_IO_BUFFER:
64 memcpy(buf, f->fp, len);
65 f->fp += len;
66 break;
67 case CFILE_IO_NULL:
68 len = 0;
69 break;
70 default:
71 len = read(f->fd, buf, len);
72 break;
73 }
74 if (len < 0)
75 return -1;
76 if (f->len != CFILE_LEN_UNLIMITED)
77 f->len -= len;
78 /*
79 can't do this here because it cannot be undone...
80 if (len && f->ctxup)
81 f->ctxup(f->ctx, buf, len);
82 f->bytes += len;
83 */
84 f->bufN = len;
85 return len;
86 }
87
88 static int
cfile_writebuf(struct cfile * f,unsigned char * buf,int len)89 cfile_writebuf(struct cfile *f, unsigned char *buf, int len)
90 {
91 unsigned char **bp, *nb;
92
93 if (len == 0)
94 return 0;
95 if (f->len != CFILE_LEN_UNLIMITED && f->len < len)
96 return 0;
97 switch (f->fd)
98 {
99 case CFILE_IO_FILE:
100 if (fwrite(buf, len, 1, (FILE *)f->fp) != 1)
101 len = -1;
102 break;
103 case CFILE_IO_CFILE:
104 len = ((struct cfile *)f->fp)->write((struct cfile *)f->fp, buf, len);
105 break;
106 case CFILE_IO_BUFFER:
107 memcpy(f->fp, buf, len);
108 f->fp += len;
109 break;
110 case CFILE_IO_ALLOC:
111 bp = (unsigned char **)f->fp;
112 if (f->bytes + len < f->bytes)
113 return -1;
114 if (!f->bytes || (((f->bytes + len - 1) ^ (f->bytes - 1)) & ~0x1fff) != 0)
115 {
116 int ns = (len + f->bytes + 0x1fff) & ~0x1fff;
117 if (ns < f->bytes + len)
118 return -1;
119 if (!f->bytes)
120 nb = malloc(ns);
121 else
122 nb = realloc(*bp, ns);
123 if (!nb)
124 return -1;
125 *bp = nb;
126 }
127 memcpy(*bp + f->bytes, buf, len);
128 break;
129 case CFILE_IO_NULL:
130 break;
131 default:
132 len = write(f->fd, buf, len);
133 }
134 if (len == -1)
135 return -1;
136 if (f->len != CFILE_LEN_UNLIMITED)
137 f->len -= len;
138 if (len && f->ctxup)
139 f->ctxup(f->ctx, buf, len);
140 f->bytes += len;
141 return len;
142 }
143
144 static void
cwclose_fixupalloc(struct cfile * f)145 cwclose_fixupalloc(struct cfile *f)
146 {
147 unsigned char *n, **bp = (unsigned char **)f->fp;
148 n = *bp;
149 if (!n)
150 return;
151 n = realloc(n, f->bytes);
152 if (n)
153 *bp = n;
154 }
155
156
157 /*****************************************************************
158 * unread stuff
159 */
160
161 static int
crread_ur(struct cfile * f,void * buf,int len)162 crread_ur(struct cfile *f, void *buf, int len)
163 {
164 int l2;
165 l2 = len > f->nunread ? f->nunread : len;
166 if (l2)
167 {
168 memcpy(buf, f->unreadbuf, l2);
169 buf += l2;
170 len -= l2;
171 f->nunread -= l2;
172 if (f->ctxup)
173 f->ctxup(f->ctx, f->unreadbuf, l2);
174 f->bytes += l2;
175 if (f->nunread)
176 memmove(f->unreadbuf, f->unreadbuf + l2, f->nunread);
177 if (!f->nunread && f->unreadbuf != f->buf)
178 {
179 free(f->unreadbuf);
180 f->unreadbuf = 0;
181 }
182 }
183 if (!f->nunread)
184 {
185 f->read = f->oldread;
186 f->oldread = 0;
187 }
188 if (!len)
189 return l2;
190 len = f->read(f, buf, len);
191 return len == -1 ? -1 : l2 + len;
192 }
193
194 static int
cfile_unreadbuf(struct cfile * f,void * buf,int len,int usebuf)195 cfile_unreadbuf(struct cfile *f, void *buf, int len, int usebuf)
196 {
197 unsigned char *newbuf;
198 if (buf == 0 && len == CFILE_UNREAD_GETBYTES)
199 return f->nunread;
200 if (len < 0)
201 return -1;
202 if (len == 0)
203 return 0;
204 if (usebuf && (f->unreadbuf == 0 || f->unreadbuf == f->buf) && len <= sizeof(f->buf) - f->nunread)
205 newbuf = f->buf;
206 else
207 {
208 if (f->unreadbuf && f->unreadbuf != f->buf)
209 newbuf = realloc(f->unreadbuf, f->nunread + len);
210 else
211 {
212 newbuf = malloc(f->nunread + len);
213 if (newbuf && f->nunread)
214 memcpy(newbuf, f->buf, f->nunread);
215 }
216 if (!newbuf)
217 return -1;
218 }
219 if (f->nunread)
220 memmove(newbuf + len, newbuf, f->nunread);
221 memcpy(newbuf, buf, len);
222 f->unreadbuf = newbuf;
223 f->nunread += len;
224 if (f->read != crread_ur)
225 {
226 f->oldread = f->read;
227 f->read = crread_ur;
228 }
229 return 0;
230 }
231
232
233 /*****************************************************************
234 * bzip2 io
235 */
236
237 static int
crread_bz(struct cfile * f,void * buf,int len)238 crread_bz(struct cfile *f, void *buf, int len)
239 {
240 int ret, used;
241 if (f->eof)
242 return 0;
243 f->strm.bz.avail_out = len;
244 f->strm.bz.next_out = buf;
245 for (;;)
246 {
247 if (f->strm.bz.avail_in == 0 && f->bufN)
248 {
249 if (cfile_readbuf(f, f->buf, sizeof(f->buf)) == -1)
250 return -1;
251 f->strm.bz.avail_in = f->bufN;
252 f->strm.bz.next_in = (char *)f->buf;
253 }
254 used = f->strm.bz.avail_in;
255 ret = BZ2_bzDecompress(&f->strm.bz);
256 if (ret != BZ_OK && ret != BZ_STREAM_END)
257 return -1;
258 used -= f->strm.bz.avail_in;
259 if (used && f->ctxup)
260 f->ctxup(f->ctx, (unsigned char *)(f->strm.bz.next_in - used), used);
261 f->bytes += used;
262 if (ret == BZ_STREAM_END)
263 {
264 f->eof = 1;
265 return len - f->strm.bz.avail_out;
266 }
267 if (f->strm.bz.avail_out == 0)
268 return len;
269 if (f->bufN == 0)
270 return -1;
271 }
272 }
273
274 static int
crclose_bz(struct cfile * f)275 crclose_bz(struct cfile *f)
276 {
277 int r;
278 BZ2_bzDecompressEnd(&f->strm.bz);
279 if (f->fd == CFILE_IO_CFILE && f->strm.bz.avail_in)
280 {
281 struct cfile *cf = (struct cfile *)f->fp;
282 if (cf->unread(cf, f->strm.bz.next_in, f->strm.bz.avail_in) != -1)
283 f->strm.bz.avail_in = 0;
284 }
285 r = (f->len != CFILE_LEN_UNLIMITED ? f->len : 0) + f->strm.bz.avail_in;
286 if (f->unreadbuf != f->buf)
287 free(f->unreadbuf);
288 free(f);
289 return r;
290 }
291
292 static struct cfile *
cropen_bz(struct cfile * f)293 cropen_bz(struct cfile *f)
294 {
295 if (BZ2_bzDecompressInit(&f->strm.bz, 0, 0) != BZ_OK)
296 {
297 free(f);
298 return 0;
299 }
300 f->eof = 0;
301 f->strm.bz.avail_in = f->bufN == -1 ? 0 : f->bufN;
302 f->strm.bz.next_in = (char *)f->buf;
303 return f;
304 }
305
306 static int
cwwrite_bz(struct cfile * f,void * buf,int len)307 cwwrite_bz(struct cfile *f, void *buf, int len)
308 {
309 int n, ret;
310
311 if (len <= 0)
312 return len < 0 ? -1 : 0;
313 f->strm.bz.avail_in = len;
314 f->strm.bz.next_in = buf;
315 for (;;)
316 {
317 f->strm.bz.avail_out = sizeof(f->buf);
318 f->strm.bz.next_out = (char *)f->buf;
319 ret = BZ2_bzCompress(&f->strm.bz, BZ_RUN);
320 if (ret != BZ_RUN_OK)
321 return -1;
322 n = sizeof(f->buf) - f->strm.bz.avail_out;
323 if (n > 0)
324 if (cfile_writebuf(f, f->buf, n) != n)
325 return -1;
326 if (f->strm.bz.avail_in == 0)
327 return len;
328 }
329 }
330
331 static int
cwclose_bz(struct cfile * f)332 cwclose_bz(struct cfile *f)
333 {
334 int bytes, ret, n;
335 f->strm.bz.avail_in = 0;
336 f->strm.bz.next_in = 0;
337 for (;;)
338 {
339 f->strm.bz.avail_out = sizeof(f->buf);
340 f->strm.bz.next_out = (char *)f->buf;
341 ret = BZ2_bzCompress(&f->strm.bz, BZ_FINISH);
342 if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END)
343 return -1;
344 n = sizeof(f->buf) - f->strm.bz.avail_out;
345 if (n > 0)
346 if (cfile_writebuf(f, f->buf, n) != n)
347 return -1;
348 if (ret == BZ_STREAM_END)
349 break;
350 }
351 BZ2_bzCompressEnd(&f->strm.bz);
352 if (f->fd == CFILE_IO_ALLOC)
353 cwclose_fixupalloc(f);
354 bytes = f->bytes;
355 free(f);
356 return bytes;
357 }
358
359 static struct cfile *
cwopen_bz(struct cfile * f)360 cwopen_bz(struct cfile *f)
361 {
362 if (!f->level)
363 f->level = 9;
364 if (BZ2_bzCompressInit(&f->strm.bz, f->level, 0, 30) != BZ_OK)
365 {
366 free(f);
367 return 0;
368 }
369 return f;
370 }
371
372 static int
crunread_bz(struct cfile * f,void * buf,int len)373 crunread_bz(struct cfile *f, void *buf, int len)
374 {
375 return cfile_unreadbuf(f, buf, len, 0);
376 }
377
378
379 /*****************************************************************
380 * gzip io
381 */
382
383 static int
crread_gz(struct cfile * f,void * buf,int len)384 crread_gz(struct cfile *f, void *buf, int len)
385 {
386 int ret, used;
387 if (f->eof)
388 return 0;
389 f->strm.gz.avail_out = len;
390 f->strm.gz.next_out = buf;
391 for (;;)
392 {
393 if (f->strm.gz.avail_in == 0 && f->bufN)
394 {
395 if (cfile_readbuf(f, f->buf, sizeof(f->buf)) == -1)
396 return -1;
397 f->strm.gz.avail_in = f->bufN;
398 f->strm.gz.next_in = f->buf;
399 }
400 used = f->strm.gz.avail_in;
401 ret = inflate(&f->strm.gz, Z_NO_FLUSH);
402 if (ret != Z_OK && ret != Z_STREAM_END)
403 return -1;
404 used -= f->strm.gz.avail_in;
405 if (used && f->ctxup)
406 f->ctxup(f->ctx, f->strm.gz.next_in - used, used);
407 f->bytes += used;
408 if (ret == Z_STREAM_END)
409 {
410 f->eof = 1;
411 /* read 8 bytes trailer (crc plus len) */
412 if (f->strm.gz.avail_in < 8) {
413 if (f->strm.gz.avail_in && f->ctxup)
414 f->ctxup(f->ctx, f->strm.gz.next_in, f->strm.gz.avail_in);
415 f->bytes += f->strm.gz.avail_in;
416 /* make trailer available in f->buf */
417 if (f->strm.gz.avail_in && f->buf != f->strm.gz.next_in)
418 memmove(f->buf, f->strm.gz.next_in, f->strm.gz.avail_in);
419 used = 8 - f->strm.gz.avail_in;
420 if (cfile_readbuf(f, f->buf + f->strm.gz.avail_in, used) != used)
421 return -1;
422 f->strm.gz.next_in = f->buf + 8;
423 f->strm.gz.avail_in = 0;
424 } else {
425 f->strm.gz.avail_in -= 8;
426 f->strm.gz.next_in += 8;
427 used = 8;
428 }
429 if (f->ctxup)
430 f->ctxup(f->ctx, f->strm.gz.next_in - used, used);
431 /* make trailer available in f->buf */
432 if (f->strm.gz.next_in != f->buf + 8)
433 memmove(f->buf + 8 - used, f->strm.gz.next_in - used, used);
434 f->bytes += used;
435 return len - f->strm.gz.avail_out;
436 }
437 if (f->strm.gz.avail_out == 0)
438 return len;
439 if (f->bufN == 0)
440 return -1;
441 }
442 }
443
444 static int
crclose_gz(struct cfile * f)445 crclose_gz(struct cfile *f)
446 {
447 int r;
448 inflateEnd(&f->strm.gz);
449 if (f->fd == CFILE_IO_CFILE && f->strm.gz.avail_in)
450 {
451 struct cfile *cf = (struct cfile *)f->fp;
452 if (cf->unread(cf, f->strm.gz.next_in, f->strm.gz.avail_in) != -1)
453 f->strm.gz.avail_in = 0;
454 }
455 if (f->fd == CFILE_IO_PUSHBACK)
456 {
457 struct cfile *cf = (struct cfile *)f->fp;
458 cf->close(cf);
459 }
460 r = (f->len != CFILE_LEN_UNLIMITED ? f->len : 0) + f->strm.gz.avail_in;
461 if (f->unreadbuf != f->buf)
462 free(f->unreadbuf);
463 free(f);
464 return r;
465 }
466
467 static struct cfile *
cropen_gz(struct cfile * f)468 cropen_gz(struct cfile *f)
469 {
470 int ret, flags;
471
472 if (f->bufN == -1)
473 cfile_readbuf(f, f->buf, sizeof(f->buf));
474 if (f->bufN < 10)
475 {
476 free(f);
477 return 0;
478 }
479 flags = f->buf[3];
480 if (f->buf[0] != 0x1f || f->buf[1] != 0x8b || f->buf[2] != 8 || (flags & 0xe0) != 0)
481 {
482 free(f);
483 return 0;
484 }
485 if (f->ctxup)
486 f->ctxup(f->ctx, f->buf, 10);
487 f->bytes += 10;
488 f->strm.gz.avail_in = f->bufN - 10;
489 f->strm.gz.next_in = f->buf + 10;
490 if (flags)
491 {
492 int hstate = 1, l = 0;
493 if ((flags & 2) != 0)
494 flags ^= (32 | 64) ^ 2; /* skip two bytes */
495 if ((flags & 4) != 0)
496 flags |= 3; /* skip two bytes */
497 while (hstate != 64)
498 {
499 if ((flags & hstate) == 0)
500 {
501 hstate *= 2;
502 continue;
503 }
504 if (f->strm.gz.avail_in == 0)
505 {
506 if (cfile_readbuf(f, f->buf, sizeof(f->buf)) == -1)
507 {
508 free(f);
509 return 0;
510 }
511 f->strm.gz.avail_in = f->bufN;
512 f->strm.gz.next_in = f->buf;
513 }
514 if (f->ctxup)
515 f->ctxup(f->ctx, f->strm.gz.next_in, 1);
516 f->bytes++;
517 f->strm.gz.next_in++;
518 f->strm.gz.avail_in--;
519 if (hstate == 1 || hstate == 2 || hstate == 32 || hstate == 64)
520 l = (l >> 8) | ((unsigned char)f->strm.gz.next_in[-1] << 8);
521 else if (hstate == 4 && l-- != 0)
522 continue;
523 else if (f->strm.gz.next_in[-1] != 0)
524 continue;
525 hstate *= 2;
526 }
527 }
528 f->eof = 0;
529 f->strm.gz.avail_out = 0;
530 f->strm.gz.next_out = 0;
531 ret = inflateInit2(&f->strm.gz, -MAX_WBITS);
532 if (ret != Z_OK)
533 {
534 free(f);
535 return 0;
536 }
537 return f;
538 }
539
540 static int
cwwrite_gz(struct cfile * f,void * buf,int len)541 cwwrite_gz(struct cfile *f, void *buf, int len)
542 {
543 int n, ret;
544
545 if (len <= 0)
546 return len < 0 ? -1 : 0;
547 f->strm.gz.avail_in = len;
548 f->strm.gz.next_in = buf;
549 for (;;)
550 {
551 f->strm.gz.avail_out = sizeof(f->buf);
552 f->strm.gz.next_out = f->buf;
553 ret = deflate(&f->strm.gz, Z_NO_FLUSH);
554 if (ret != Z_OK)
555 return -1;
556 n = sizeof(f->buf) - f->strm.gz.avail_out;
557 if (n > 0)
558 if (cfile_writebuf(f, f->buf, n) != n)
559 return -1;
560 if (f->strm.gz.avail_in == 0)
561 {
562 f->crclen += len;
563 f->crc = crc32(f->crc, buf, len);
564 return len;
565 }
566 }
567 }
568
569 static int
cwclose_gz(struct cfile * f)570 cwclose_gz(struct cfile *f)
571 {
572 int bytes, ret, n;
573 for (;;)
574 {
575 f->strm.gz.avail_out = sizeof(f->buf);
576 f->strm.gz.next_out = f->buf;
577 ret = deflate(&f->strm.gz, Z_FINISH);
578 if (ret != Z_OK && ret != Z_STREAM_END)
579 return -1;
580 n = sizeof(f->buf) - f->strm.gz.avail_out;
581 if (n > 0)
582 if (cfile_writebuf(f, f->buf, n) != n)
583 return -1;
584 if (ret == Z_STREAM_END)
585 break;
586 }
587 deflateEnd(&f->strm.gz);
588 f->buf[0] = f->crc & 0xff;
589 f->buf[1] = (f->crc >> 8) & 0xff;
590 f->buf[2] = (f->crc >> 16) & 0xff;
591 f->buf[3] = (f->crc >> 24) & 0xff;
592 f->buf[4] = f->crclen & 0xff;
593 f->buf[5] = (f->crclen >> 8) & 0xff;
594 f->buf[6] = (f->crclen >> 16) & 0xff;
595 f->buf[7] = (f->crclen >> 24) & 0xff;
596 if (cfile_writebuf(f, f->buf, 8) != 8)
597 return -1;
598 if (f->fd == CFILE_IO_ALLOC)
599 cwclose_fixupalloc(f);
600 bytes = f->bytes;
601 free(f);
602 return bytes;
603 }
604
605 static struct cfile *
cwopen_gz(struct cfile * f)606 cwopen_gz(struct cfile *f)
607 {
608 int ret;
609
610 f->crc = crc32(0L, Z_NULL, 0);
611 f->crclen = 0;
612 if (!f->level)
613 f->level = Z_BEST_COMPRESSION;
614 #ifdef Z_RSYNCABLE
615 ret = deflateInit2(&f->strm.gz, f->level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY | (f->comp == CFILE_COMP_GZ_RSYNC ? Z_RSYNCABLE : 0));
616 #else
617 if (f->comp == CFILE_COMP_GZ_RSYNC)
618 ret = Z_VERSION_ERROR;
619 else
620 ret = deflateInit2(&f->strm.gz, f->level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
621 #endif
622 if (ret != Z_OK)
623 {
624 free(f);
625 return 0;
626 }
627 f->strm.gz.avail_in = 0;
628 f->strm.gz.next_in = f->buf;
629 f->buf[0] = 0x1f;
630 f->buf[1] = 0x8b;
631 f->buf[2] = Z_DEFLATED;
632 f->buf[3] = 0;
633 f->buf[4] = f->buf[5] = f->buf[6] = f->buf[7] = 0;
634 f->buf[8] = f->level == 9 ? 2 : f->level < 2 ? 4 : 0;
635 f->buf[9] = 3; /* OS_UNIX */
636 if (cfile_writebuf(f, f->buf, 10) != 10)
637 {
638 free(f);
639 return 0;
640 }
641 return f;
642 }
643
644
645 static int
crunread_gz(struct cfile * f,void * buf,int len)646 crunread_gz(struct cfile *f, void *buf, int len)
647 {
648 return cfile_unreadbuf(f, buf, len, 0);
649 }
650
651
652 /*****************************************************************
653 * lzma io
654 */
655
656 static struct cfile *
cropen_lz(struct cfile * f)657 cropen_lz(struct cfile *f)
658 {
659 lzma_stream tmp = LZMA_STREAM_INIT;
660 f->strm.lz = tmp;
661 if (lzma_auto_decoder(&f->strm.lz, 1 << 25, 0) != LZMA_OK)
662 {
663 free(f);
664 return 0;
665 }
666 f->eof = 0;
667 f->strm.lz.avail_in = f->bufN == -1 ? 0 : f->bufN;
668 f->strm.lz.next_in = (unsigned char *)f->buf;
669 return f;
670 }
671
672 static int
crread_lz(struct cfile * f,void * buf,int len)673 crread_lz(struct cfile *f, void *buf, int len)
674 {
675 int ret, used;
676 if (f->eof)
677 return 0;
678 f->strm.lz.avail_out = len;
679 f->strm.lz.next_out = buf;
680 for (;;)
681 {
682 if (f->strm.lz.avail_in == 0 && f->bufN)
683 {
684 if (cfile_readbuf(f, f->buf, sizeof(f->buf)) == -1)
685 return -1;
686 f->strm.lz.avail_in = f->bufN;
687 f->strm.lz.next_in = (unsigned char *)f->buf;
688 }
689 used = f->strm.lz.avail_in;
690 ret = lzma_code(&f->strm.lz, LZMA_RUN);
691 if (ret != LZMA_OK && ret != LZMA_STREAM_END)
692 return -1;
693 used -= f->strm.lz.avail_in;
694 if (used && f->ctxup)
695 f->ctxup(f->ctx, (unsigned char *)(f->strm.lz.next_in - used), used);
696 f->bytes += used;
697 if (ret == LZMA_STREAM_END)
698 {
699 f->eof = 1;
700 return len - f->strm.lz.avail_out;
701 }
702 if (f->strm.lz.avail_out == 0)
703 return len;
704 if (f->bufN == 0)
705 return -1;
706 }
707 }
708
709 static int
crclose_lz(struct cfile * f)710 crclose_lz(struct cfile *f)
711 {
712 int r;
713 lzma_end(&f->strm.lz);
714 if (f->fd == CFILE_IO_CFILE && f->strm.lz.avail_in)
715 {
716 struct cfile *cf = (struct cfile *)f->fp;
717 if (cf->unread(cf, (void *)f->strm.lz.next_in, f->strm.lz.avail_in) != -1)
718 f->strm.lz.avail_in = 0;
719 }
720 r = (f->len != CFILE_LEN_UNLIMITED ? f->len : 0) + f->strm.lz.avail_in;
721 if (f->unreadbuf != f->buf)
722 free(f->unreadbuf);
723 free(f);
724 return r;
725 }
726
727 static struct cfile *
cwopen_lz(struct cfile * f)728 cwopen_lz(struct cfile *f)
729 {
730 lzma_options_lzma alone;
731 lzma_stream tmp = LZMA_STREAM_INIT;
732
733 if (!f->level)
734 f->level = 2;
735 f->strm.lz = tmp;
736 lzma_lzma_preset(&alone, f->level);
737 if (lzma_alone_encoder(&f->strm.lz, &alone) != LZMA_OK)
738 {
739 free(f);
740 return 0;
741 }
742 return f;
743 }
744
745 static struct cfile *
cwopen_xz(struct cfile * f)746 cwopen_xz(struct cfile *f)
747 {
748 lzma_stream tmp = LZMA_STREAM_INIT;
749
750 if (!f->level)
751 f->level = 3;
752
753 f->strm.lz = tmp;
754 if (lzma_easy_encoder(&f->strm.lz, f->level, LZMA_CHECK_SHA256) != LZMA_OK)
755 {
756 free(f);
757 return 0;
758 }
759 return f;
760 }
761
762 static int
cwclose_lz(struct cfile * f)763 cwclose_lz(struct cfile *f)
764 {
765 int bytes, ret, n;
766 f->strm.lz.avail_in = 0;
767 f->strm.lz.next_in = 0;
768 for (;;)
769 {
770 f->strm.lz.avail_out = sizeof(f->buf);
771 f->strm.lz.next_out = (unsigned char *)f->buf;
772 ret = lzma_code(&f->strm.lz, LZMA_FINISH);
773 if (ret != LZMA_OK && ret != LZMA_STREAM_END)
774 return -1;
775 n = sizeof(f->buf) - f->strm.lz.avail_out;
776 if (n > 0)
777 if (cfile_writebuf(f, f->buf, n) != n)
778 return -1;
779 if (ret == LZMA_STREAM_END)
780 break;
781 }
782 lzma_end(&f->strm.lz);
783 if (f->fd == CFILE_IO_ALLOC)
784 cwclose_fixupalloc(f);
785 bytes = f->bytes;
786 free(f);
787 return bytes;
788 }
789
790 static int
cwwrite_lz(struct cfile * f,void * buf,int len)791 cwwrite_lz(struct cfile *f, void *buf, int len)
792 {
793 int n, ret;
794
795 if (len <= 0)
796 return len < 0 ? -1 : 0;
797 f->strm.lz.avail_in = len;
798 f->strm.lz.next_in = buf;
799 for (;;)
800 {
801 f->strm.lz.avail_out = sizeof(f->buf);
802 f->strm.lz.next_out = (unsigned char *)f->buf;
803 ret = lzma_code(&f->strm.lz, LZMA_RUN);
804 if (ret != LZMA_OK)
805 return -1;
806 n = sizeof(f->buf) - f->strm.lz.avail_out;
807 if (n > 0)
808 if (cfile_writebuf(f, f->buf, n) != n)
809 return -1;
810 if (f->strm.lz.avail_in == 0)
811 return len;
812 }
813 }
814
815 static int
crunread_lz(struct cfile * f,void * buf,int len)816 crunread_lz(struct cfile *f, void *buf, int len)
817 {
818 return cfile_unreadbuf(f, buf, len, 0);
819 }
820
821 /*****************************************************************
822 * uncompressed io
823 */
824
825 static int
crread_un(struct cfile * f,void * buf,int len)826 crread_un(struct cfile *f, void *buf, int len)
827 {
828 int r;
829 r = cfile_readbuf(f, buf, len);
830 if (r == -1)
831 return -1;
832 if (f->ctxup && r)
833 f->ctxup(f->ctx, buf, r);
834 f->bytes += r;
835 return r;
836 }
837
838 static int
crclose_un(struct cfile * f)839 crclose_un(struct cfile *f)
840 {
841 int r = f->len != CFILE_LEN_UNLIMITED ? f->len : 0;
842 if (f->unreadbuf != f->buf)
843 free(f->unreadbuf);
844 free(f);
845 return r;
846 }
847
848 static struct cfile *
cropen_un(struct cfile * f)849 cropen_un(struct cfile *f)
850 {
851 if (f->bufN != -1 && f->bufN != 0)
852 {
853 /* CFILE_COMP_XX read some bytes, set up unread */
854 f->unreadbuf = f->buf;
855 f->nunread = f->bufN;
856 f->oldread = f->read;
857 f->read = crread_ur;
858 }
859 return f;
860 }
861
862 static int
cwwrite_un(struct cfile * f,void * buf,int len)863 cwwrite_un(struct cfile *f, void *buf, int len)
864 {
865 return cfile_writebuf(f, buf, len);
866 }
867
868 static int
cwclose_un(struct cfile * f)869 cwclose_un(struct cfile *f)
870 {
871 int bytes = f->bytes;
872 if (f->fd == CFILE_IO_ALLOC)
873 cwclose_fixupalloc(f);
874 free(f);
875 return bytes;
876 }
877
878 static struct cfile *
cwopen_un(struct cfile * f)879 cwopen_un(struct cfile *f)
880 {
881 return f;
882 }
883
884 static int
crunread_un(struct cfile * f,void * buf,int len)885 crunread_un(struct cfile *f, void *buf, int len)
886 {
887 return cfile_unreadbuf(f, buf, len, 1);
888 }
889
890
891 int
cfile_detect_rsync(struct cfile * f)892 cfile_detect_rsync(struct cfile *f)
893 {
894 unsigned char *b, *b2;
895 int i, len, l, eof, p[2];
896 int comp = CFILE_COMP_GZ;
897 z_stream dstrm, cstrm[2];
898 int done, ret, dret;
899 unsigned char dbuf[4096], cbuf[4096];
900
901 if (f->comp != CFILE_COMP_GZ)
902 return 0;
903 b = malloc(4096 + f->strm.gz.avail_in);
904 if (!b)
905 return -1;
906 len = 0;
907
908 p[0] = p[1] = 0;
909
910 dstrm.zalloc = 0;
911 dstrm.zfree = 0;
912 dstrm.opaque = 0;
913 if (inflateInit2(&dstrm, -MAX_WBITS) != Z_OK)
914 {
915 free(b);
916 return -1;
917 }
918 for (i = 0; i < 2; i++)
919 {
920 #ifndef Z_RSYNCABLE
921 /* Rsync friendly zlib not available, don't set up a compressor for it
922 * */
923 if (i)
924 {
925 break;
926 }
927 #endif
928 cstrm[i].zalloc = 0;
929 cstrm[i].zfree = 0;
930 cstrm[i].opaque = 0;
931 #ifdef Z_RSYNCABLE
932 if (deflateInit2(&cstrm[i], Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY | (i == 1 ? Z_RSYNCABLE : 0)) != Z_OK)
933 #else
934 if (deflateInit2(&cstrm[i], Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
935 #endif
936 {
937 if (i)
938 deflateEnd(&cstrm[0]);
939 inflateEnd(&dstrm);
940 free(b);
941 return -1;
942 }
943 }
944
945 done = eof = 0;
946 dstrm.avail_in = f->strm.gz.avail_in;
947 if (f->strm.gz.avail_in)
948 memcpy(b, f->strm.gz.next_in, f->strm.gz.avail_in);
949 for (;;)
950 {
951 if (dstrm.avail_in == 0)
952 {
953 l = cfile_readbuf(f, b + len, 4096);
954 if (l < 4096)
955 eof = 1;
956 }
957 else
958 l = dstrm.avail_in;
959 if (l >= 0)
960 {
961 dstrm.avail_in = l;
962 dstrm.next_in = b + len;
963 while (dstrm.avail_in && !done)
964 {
965 dstrm.avail_out = sizeof(dbuf);
966 dstrm.next_out = dbuf;
967 dret = inflate(&dstrm, Z_NO_FLUSH);
968 if (dret != Z_OK && dret != Z_STREAM_END)
969 {
970 done = 1;
971 break;
972 }
973 if (dstrm.avail_out != sizeof(dbuf))
974 {
975 for (i = 0; i < 2 && !done; i++)
976 {
977 #ifndef Z_RSYNCABLE
978 /* No rsync friendly zlib so we can only test against
979 * COMP_GZ. This is suboptimal as it's only when we
980 * run into an error that we can cut to the end. So
981 * we're forced to uncompress and recompress the whole
982 * output. Need to determine if we can determine that
983 * we used the other algorithm is being used after
984 * decompressing a certain amount of blocks. Perhaps
985 * after RSYNC_WIN or MAX_DIST blocks have been
986 * decompressed we can know whether COMP_GZ_RSYNC was
987 * used?
988 */
989 if (i)
990 {
991 break;
992 }
993 #endif
994 cstrm[i].avail_in = sizeof(dbuf) - dstrm.avail_out;
995 cstrm[i].next_in = dbuf;
996 while (cstrm[i].avail_in)
997 {
998 cstrm[i].avail_out = sizeof(cbuf);
999 cstrm[i].next_out = cbuf;
1000 ret = deflate(&cstrm[i], dret == Z_STREAM_END ? Z_FINISH : Z_NO_FLUSH);
1001 /* Any errors in compressing, set to the other
1002 * compression algorithm
1003 */
1004 if (ret != Z_OK && ret != Z_STREAM_END)
1005 {
1006 comp = i ? CFILE_COMP_GZ: CFILE_COMP_GZ_RSYNC;
1007 done = 1;
1008 break;
1009 }
1010 /* if compression yielded something
1011 */
1012 if (cstrm[i].avail_out != sizeof(cbuf))
1013 {
1014 /* If the newly compressed block is not equal to
1015 * the original compressed payload, set to the
1016 * opposite compression algorithm
1017 */
1018 if (memcmp(b + p[i], cbuf, sizeof(cbuf) - cstrm[i].avail_out))
1019 {
1020 comp = i ? CFILE_COMP_GZ: CFILE_COMP_GZ_RSYNC;
1021 done = 1;
1022 break;
1023 }
1024 p[i] += sizeof(cbuf) - cstrm[i].avail_out;
1025 }
1026 /* If the input stream is not empty but the
1027 * compressor says that the stream is empty we have
1028 * an error. Set to the opposite compression
1029 * algorithm.
1030 *
1031 * Note -- This code looks wrong:
1032 * Should be Z_STREAM_END, not BZ_STREAM_END
1033 */
1034 if (cstrm[i].avail_in && ret == BZ_STREAM_END)
1035 {
1036 comp = i ? CFILE_COMP_GZ: CFILE_COMP_GZ_RSYNC;
1037 break;
1038 }
1039 }
1040 }
1041 }
1042 if (dret == Z_STREAM_END)
1043 done = 1;
1044 }
1045 len += l;
1046 }
1047 if (done || eof)
1048 break;
1049 b2 = realloc(b, len + 4096);
1050 if (!b2)
1051 {
1052 comp = -1;
1053 break;
1054 }
1055 b = b2;
1056 }
1057 deflateEnd(&cstrm[0]);
1058 #ifdef Z_RSYNCABLE
1059 deflateEnd(&cstrm[1]);
1060 #endif
1061 inflateEnd(&dstrm);
1062 f->bufN = -1;
1063 f->strm.gz.avail_in = 0;
1064 if (comp != -1)
1065 f->comp = comp;
1066 if (len)
1067 {
1068 struct cfile *cf;
1069 if (f->fd == CFILE_IO_CFILE || f->fd == CFILE_IO_PUSHBACK)
1070 {
1071 cf = (struct cfile *)f->fp;
1072 if (!cf->unread(cf, b, len))
1073 {
1074 free(b);
1075 return -1;
1076 }
1077 free(b);
1078 }
1079 else
1080 {
1081 cf = cfile_open(CFILE_OPEN_RD, f->fd, f->fp, CFILE_COMP_UN, CFILE_LEN_UNLIMITED, 0, 0);
1082 if (!cf)
1083 {
1084 free(b);
1085 return -1;
1086 }
1087 f->fp = cf;
1088 f->fd = CFILE_IO_PUSHBACK;
1089 cf->unreadbuf = b;
1090 cf->nunread = len;
1091 cf->oldread = cf->read;
1092 cf->read = crread_ur;
1093 }
1094 if (f->len != CFILE_LEN_UNLIMITED)
1095 f->len += len;
1096 }
1097 else
1098 free(b);
1099 return comp == -1 ? -1 : 0;
1100 }
1101
1102 /*****************************************************************
1103 * our open function
1104 */
1105
1106 struct cfile *
cfile_open(int mode,int fd,void * fp,int comp,size_t len,void (* ctxup)(void *,unsigned char *,unsigned int),void * ctx)1107 cfile_open(int mode, int fd, void *fp, int comp, size_t len, void (*ctxup)(void *, unsigned char *, unsigned int), void *ctx)
1108 {
1109 struct cfile *f;
1110 if (comp == CFILE_COMP_XX && mode == CFILE_OPEN_WR)
1111 return 0;
1112 if (mode != CFILE_OPEN_RD && mode != CFILE_OPEN_WR)
1113 return 0;
1114 if (fd == CFILE_IO_REOPEN)
1115 {
1116 f = fp;
1117 fd = f->fd;
1118 fp = f->fp;
1119 }
1120 else
1121 f = malloc(sizeof(*f));
1122 if (!f)
1123 return 0;
1124 f->fd = fd;
1125 f->fp = fp;
1126 f->bytes = 0;
1127 f->len = len;
1128 f->ctxup = ctxup;
1129 f->ctx = ctx;
1130 f->bufN = -1;
1131 f->nunread = 0;
1132 f->unreadbuf = 0;
1133 f->oldread = 0;
1134 if (mode == CFILE_OPEN_WR && fd == CFILE_IO_ALLOC)
1135 {
1136 unsigned char **bp = (unsigned char **)f->fp;
1137 *bp = 0;
1138 }
1139 if (comp == CFILE_COMP_XX)
1140 {
1141 comp = CFILE_COMP_UN;
1142 if (len == CFILE_LEN_UNLIMITED || len >= 2)
1143 {
1144 int n = cfile_readbuf(f, f->buf, sizeof(f->buf));
1145 if (n == -1)
1146 {
1147 free(f);
1148 return 0;
1149 }
1150 if (f->buf[0] == 'B' && f->buf[1] == 'Z')
1151 comp = CFILE_COMP_BZ;
1152 else if (f->buf[0] == 0x1f && f->buf[1] == 0x8b)
1153 comp = CFILE_COMP_GZ;
1154 else if (f->buf[0] == 255 && f->buf[1] == 'L' && f->buf[2] == 'Z')
1155 comp = CFILE_COMP_LZMA;
1156 else if (f->buf[0] == 0135 && f->buf[1] == 0 && f->buf[2] == 0)
1157 comp = CFILE_COMP_LZMA;
1158 else if (f->buf[0] == 0xfd && f->buf[1] == '7' && f->buf[2] == 'z' && f->buf[3] == 'X' && f->buf[4] == 'Z')
1159 comp = CFILE_COMP_XZ;
1160 }
1161 }
1162 f->comp = CFILE_COMPALGO(comp);
1163 f->level = CFILE_COMPLEVEL(comp);
1164 switch (f->comp)
1165 {
1166 case CFILE_COMP_UN:
1167 f->read = mode == CFILE_OPEN_RD ? crread_un : 0;
1168 f->unread = mode == CFILE_OPEN_RD ? crunread_un : 0;
1169 f->write = mode == CFILE_OPEN_WR ? cwwrite_un : 0;
1170 f->close = mode == CFILE_OPEN_RD ? crclose_un : cwclose_un;
1171 return mode == CFILE_OPEN_RD ? cropen_un(f) : cwopen_un(f);
1172 case CFILE_COMP_GZ:
1173 case CFILE_COMP_GZ_RSYNC:
1174 f->strm.gz.zalloc = 0;
1175 f->strm.gz.zfree = 0;
1176 f->strm.gz.opaque = 0;
1177 f->read = mode == CFILE_OPEN_RD ? crread_gz : 0;
1178 f->unread = mode == CFILE_OPEN_RD ? crunread_gz : 0;
1179 f->write = mode == CFILE_OPEN_WR ? cwwrite_gz : 0;
1180 f->close = mode == CFILE_OPEN_RD ? crclose_gz : cwclose_gz;
1181 return mode == CFILE_OPEN_RD ? cropen_gz(f) : cwopen_gz(f);
1182 case CFILE_COMP_BZ:
1183 f->strm.bz.bzalloc = 0;
1184 f->strm.bz.bzfree = 0;
1185 f->strm.bz.opaque = 0;
1186 f->read = mode == CFILE_OPEN_RD ? crread_bz : 0;
1187 f->unread = mode == CFILE_OPEN_RD ? crunread_bz : 0;
1188 f->write = mode == CFILE_OPEN_WR ? cwwrite_bz : 0;
1189 f->close = mode == CFILE_OPEN_RD ? crclose_bz : cwclose_bz;
1190 return mode == CFILE_OPEN_RD ? cropen_bz(f) : cwopen_bz(f);
1191 case CFILE_COMP_LZMA:
1192 f->strm.lz.allocator = 0;
1193 f->strm.lz.internal = 0;
1194 f->read = mode == CFILE_OPEN_RD ? crread_lz : 0;
1195 f->unread = mode == CFILE_OPEN_RD ? crunread_lz : 0;
1196 f->write = mode == CFILE_OPEN_WR ? cwwrite_lz : 0;
1197 f->close = mode == CFILE_OPEN_RD ? crclose_lz : cwclose_lz;
1198 return mode == CFILE_OPEN_RD ? cropen_lz(f) : cwopen_lz(f);
1199 case CFILE_COMP_XZ:
1200 f->strm.lz.allocator = 0;
1201 f->strm.lz.internal = 0;
1202 f->read = mode == CFILE_OPEN_RD ? crread_lz : 0;
1203 f->unread = mode == CFILE_OPEN_RD ? crunread_lz : 0;
1204 f->write = mode == CFILE_OPEN_WR ? cwwrite_lz : 0;
1205 f->close = mode == CFILE_OPEN_RD ? crclose_lz : cwclose_lz;
1206 return mode == CFILE_OPEN_RD ? cropen_lz(f) : cwopen_xz(f);
1207 default:
1208 free(f);
1209 return 0;
1210 }
1211 }
1212
1213 /*****************************************************************
1214 * copy data from one cfile to another
1215 */
1216
1217 int
cfile_copy(struct cfile * in,struct cfile * out,int flags)1218 cfile_copy(struct cfile *in, struct cfile *out, int flags)
1219 {
1220 unsigned char buf[8192];
1221 int l, r;
1222 if (!in || !out)
1223 return -1;
1224 while((l = in->read(in, buf, sizeof(buf))) > 0)
1225 if (out->write(out, buf, l) != l)
1226 {
1227 l = -1;
1228 break;
1229 }
1230 if (l != -1)
1231 l = 0;
1232 if ((flags & CFILE_COPY_CLOSE_IN))
1233 {
1234 if ((r = in->close(in)) != 0)
1235 if ((flags & CFILE_COPY_CLOSE_OUT) != 0)
1236 r = -1;
1237 if (l != -1)
1238 l = r;
1239 }
1240 if ((flags & CFILE_COPY_CLOSE_OUT))
1241 {
1242 r = out->close(out);
1243 if (l != -1)
1244 l = r;
1245 }
1246 return l;
1247 }
1248
1249 char *
cfile_comp2str(int comp)1250 cfile_comp2str(int comp)
1251 {
1252 if (CFILE_COMPLEVEL(comp))
1253 {
1254 static char buf[64];
1255 sprintf(buf, "%s.%d", cfile_comp2str(CFILE_COMPALGO(comp)), CFILE_COMPLEVEL(comp));
1256 return buf;
1257 }
1258 switch (comp)
1259 {
1260 case CFILE_COMP_UN:
1261 return "uncomp.";
1262 case CFILE_COMP_GZ:
1263 return "gzip";
1264 case CFILE_COMP_GZ_RSYNC:
1265 return "gzip rsyncable";
1266 case CFILE_COMP_BZ:
1267 return "bzip";
1268 case CFILE_COMP_LZMA:
1269 return "lzma";
1270 case CFILE_COMP_XZ:
1271 return "xz";
1272 }
1273 return "???";
1274 }
1275
1276 int
cfile_setlevel(int comp,int level)1277 cfile_setlevel(int comp, int level)
1278 {
1279 int deflevel = 0;
1280 comp = CFILE_COMPALGO(comp);
1281 switch(comp)
1282 {
1283 case CFILE_COMP_GZ:
1284 case CFILE_COMP_GZ_RSYNC:
1285 case CFILE_COMP_BZ:
1286 deflevel = 9;
1287 break;
1288 default:
1289 break;
1290 }
1291 if (level == 0 || level == deflevel)
1292 return comp;
1293 return CFILE_MKCOMP(comp, level);
1294 }
1295