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