1 /* $NetBSD: compress.c,v 1.19 2019/12/17 02:31:05 christos Exp $ */ 2 3 /* 4 * Copyright (c) Ian F. Darwin 1986-1995. 5 * Software written by Ian F. Darwin and others; 6 * maintained 1995-present by Christos Zoulas and others. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice immediately at the beginning of the file, without modification, 13 * this list of conditions, and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 /* 31 * compress routines: 32 * zmagic() - returns 0 if not recognized, uncompresses and prints 33 * information if recognized 34 * uncompress(method, old, n, newch) - uncompress old into new, 35 * using method, return sizeof new 36 */ 37 #include "file.h" 38 39 #ifndef lint 40 #if 0 41 FILE_RCSID("@(#)$File: compress.c,v 1.124 2019/07/21 11:42:09 christos Exp $") 42 #else 43 __RCSID("$NetBSD: compress.c,v 1.19 2019/12/17 02:31:05 christos Exp $"); 44 #endif 45 #endif 46 47 #include "magic.h" 48 #include <stdlib.h> 49 #ifdef HAVE_UNISTD_H 50 #include <unistd.h> 51 #endif 52 #include <string.h> 53 #include <errno.h> 54 #include <ctype.h> 55 #include <stdarg.h> 56 #include <signal.h> 57 #ifndef HAVE_SIG_T 58 typedef void (*sig_t)(int); 59 #endif /* HAVE_SIG_T */ 60 #if !defined(__MINGW32__) && !defined(WIN32) 61 #include <sys/ioctl.h> 62 #endif 63 #ifdef HAVE_SYS_WAIT_H 64 #include <sys/wait.h> 65 #endif 66 #if defined(HAVE_SYS_TIME_H) 67 #include <sys/time.h> 68 #endif 69 70 #if defined(HAVE_ZLIB_H) && defined(ZLIBSUPPORT) 71 #define BUILTIN_DECOMPRESS 72 #include <zlib.h> 73 #endif 74 75 #if defined(HAVE_BZLIB_H) || defined(BZLIBSUPPORT) 76 #define BUILTIN_BZLIB 77 #include <bzlib.h> 78 #endif 79 80 #if defined(HAVE_XZLIB_H) || defined(XZLIBSUPPORT) 81 #define BUILTIN_XZLIB 82 #include <lzma.h> 83 #endif 84 85 #ifdef DEBUG 86 int tty = -1; 87 #define DPRINTF(...) do { \ 88 if (tty == -1) \ 89 tty = open("/dev/tty", O_RDWR); \ 90 if (tty == -1) \ 91 abort(); \ 92 dprintf(tty, __VA_ARGS__); \ 93 } while (/*CONSTCOND*/0) 94 #else 95 #define DPRINTF(...) 96 #endif 97 98 #ifdef ZLIBSUPPORT 99 /* 100 * The following python code is not really used because ZLIBSUPPORT is only 101 * defined if we have a built-in zlib, and the built-in zlib handles that. 102 * That is not true for android where we have zlib.h and not -lz. 103 */ 104 static const char zlibcode[] = 105 "import sys, zlib; sys.stdout.write(zlib.decompress(sys.stdin.read()))"; 106 107 static const char *zlib_args[] = { "python", "-c", zlibcode, NULL }; 108 109 static int 110 zlibcmp(const unsigned char *buf) 111 { 112 unsigned short x = 1; 113 unsigned char *s = CAST(unsigned char *, CAST(void *, &x)); 114 115 if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0) 116 return 0; 117 if (s[0] != 1) /* endianness test */ 118 x = buf[0] | (buf[1] << 8); 119 else 120 x = buf[1] | (buf[0] << 8); 121 if (x % 31) 122 return 0; 123 return 1; 124 } 125 #endif 126 127 static int 128 lzmacmp(const unsigned char *buf) 129 { 130 if (buf[0] != 0x5d || buf[1] || buf[2]) 131 return 0; 132 if (buf[12] && buf[12] != 0xff) 133 return 0; 134 return 1; 135 } 136 137 #define gzip_flags "-cd" 138 #define lrzip_flags "-do" 139 #define lzip_flags gzip_flags 140 141 static const char *gzip_args[] = { 142 "gzip", gzip_flags, NULL 143 }; 144 static const char *uncompress_args[] = { 145 "uncompress", "-c", NULL 146 }; 147 static const char *bzip2_args[] = { 148 "bzip2", "-cd", NULL 149 }; 150 static const char *lzip_args[] = { 151 "lzip", lzip_flags, NULL 152 }; 153 static const char *xz_args[] = { 154 "xz", "-cd", NULL 155 }; 156 static const char *lrzip_args[] = { 157 "lrzip", lrzip_flags, NULL 158 }; 159 static const char *lz4_args[] = { 160 "lz4", "-cd", NULL 161 }; 162 static const char *zstd_args[] = { 163 "zstd", "-cd", NULL 164 }; 165 166 #define do_zlib NULL 167 #define do_bzlib NULL 168 169 private const struct { 170 const void *magic; 171 int maglen; 172 const char **argv; 173 void *unused; 174 } compr[] = { 175 #define METH_FROZEN 2 176 #define METH_BZIP 7 177 #define METH_XZ 9 178 #define METH_LZMA 13 179 #define METH_ZLIB 14 180 { "\037\235", 2, gzip_args, NULL }, /* 0, compressed */ 181 /* Uncompress can get stuck; so use gzip first if we have it 182 * Idea from Damien Clark, thanks! */ 183 { "\037\235", 2, uncompress_args, NULL }, /* 1, compressed */ 184 { "\037\213", 2, gzip_args, do_zlib }, /* 2, gzipped */ 185 { "\037\236", 2, gzip_args, NULL }, /* 3, frozen */ 186 { "\037\240", 2, gzip_args, NULL }, /* 4, SCO LZH */ 187 /* the standard pack utilities do not accept standard input */ 188 { "\037\036", 2, gzip_args, NULL }, /* 5, packed */ 189 { "PK\3\4", 4, gzip_args, NULL }, /* 6, pkzipped, */ 190 /* ...only first file examined */ 191 { "BZh", 3, bzip2_args, do_bzlib }, /* 7, bzip2-ed */ 192 { "LZIP", 4, lzip_args, NULL }, /* 8, lzip-ed */ 193 { "\3757zXZ\0", 6, xz_args, NULL }, /* 9, XZ Utils */ 194 { "LRZI", 4, lrzip_args, NULL }, /* 10, LRZIP */ 195 { "\004\"M\030",4, lz4_args, NULL }, /* 11, LZ4 */ 196 { "\x28\xB5\x2F\xFD", 4, zstd_args, NULL }, /* 12, zstd */ 197 { RCAST(const void *, lzmacmp), -13, xz_args, NULL }, /* 13, lzma */ 198 #ifdef ZLIBSUPPORT 199 { RCAST(const void *, zlibcmp), -2, zlib_args, NULL }, /* 14, zlib */ 200 #endif 201 }; 202 203 #define OKDATA 0 204 #define NODATA 1 205 #define ERRDATA 2 206 207 private ssize_t swrite(int, const void *, size_t); 208 #if HAVE_FORK 209 private size_t ncompr = __arraycount(compr); 210 private int uncompressbuf(int, size_t, size_t, const unsigned char *, 211 unsigned char **, size_t *); 212 #ifdef BUILTIN_DECOMPRESS 213 private int uncompresszlib(const unsigned char *, unsigned char **, size_t, 214 size_t *, int); 215 private int uncompressgzipped(const unsigned char *, unsigned char **, size_t, 216 size_t *); 217 #endif 218 #ifdef BUILTIN_BZLIB 219 private int uncompressbzlib(const unsigned char *, unsigned char **, size_t, 220 size_t *); 221 #endif 222 #ifdef BUILTIN_XZLIB 223 private int uncompressxzlib(const unsigned char *, unsigned char **, size_t, 224 size_t *); 225 #endif 226 227 static int makeerror(unsigned char **, size_t *, const char *, ...) 228 __attribute__((__format__(__printf__, 3, 4))); 229 private const char *methodname(size_t); 230 231 private int 232 format_decompression_error(struct magic_set *ms, size_t i, unsigned char *buf) 233 { 234 unsigned char *p; 235 int mime = ms->flags & MAGIC_MIME; 236 237 if (!mime) 238 return file_printf(ms, "ERROR:[%s: %s]", methodname(i), buf); 239 240 for (p = buf; *p; p++) 241 if (!isalnum(*p)) 242 *p = '-'; 243 244 return file_printf(ms, "application/x-decompression-error-%s-%s", 245 methodname(i), buf); 246 } 247 248 protected int 249 file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) 250 { 251 unsigned char *newbuf = NULL; 252 size_t i, nsz; 253 char *rbuf; 254 file_pushbuf_t *pb; 255 int urv, prv, rv = 0; 256 int mime = ms->flags & MAGIC_MIME; 257 int fd = b->fd; 258 const unsigned char *buf = CAST(const unsigned char *, b->fbuf); 259 size_t nbytes = b->flen; 260 int sa_saved = 0; 261 struct sigaction sig_act; 262 263 if ((ms->flags & MAGIC_COMPRESS) == 0) 264 return 0; 265 266 for (i = 0; i < ncompr; i++) { 267 int zm; 268 if (nbytes < CAST(size_t, abs(compr[i].maglen))) 269 continue; 270 if (compr[i].maglen < 0) { 271 zm = (RCAST(int (*)(const unsigned char *), 272 CCAST(void *, compr[i].magic)))(buf); 273 } else { 274 zm = memcmp(buf, compr[i].magic, 275 CAST(size_t, compr[i].maglen)) == 0; 276 } 277 278 if (!zm) 279 continue; 280 281 /* Prevent SIGPIPE death if child dies unexpectedly */ 282 if (!sa_saved) { 283 //We can use sig_act for both new and old, but 284 struct sigaction new_act; 285 memset(&new_act, 0, sizeof(new_act)); 286 new_act.sa_handler = SIG_IGN; 287 sa_saved = sigaction(SIGPIPE, &new_act, &sig_act) != -1; 288 } 289 290 nsz = nbytes; 291 urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz); 292 DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv, 293 (char *)newbuf, nsz); 294 switch (urv) { 295 case OKDATA: 296 case ERRDATA: 297 ms->flags &= ~MAGIC_COMPRESS; 298 if (urv == ERRDATA) 299 prv = format_decompression_error(ms, i, newbuf); 300 else 301 prv = file_buffer(ms, -1, NULL, name, newbuf, nsz); 302 if (prv == -1) 303 goto error; 304 rv = 1; 305 if ((ms->flags & MAGIC_COMPRESS_TRANSP) != 0) 306 goto out; 307 if (mime != MAGIC_MIME && mime != 0) 308 goto out; 309 if ((file_printf(ms, 310 mime ? " compressed-encoding=" : " (")) == -1) 311 goto error; 312 if ((pb = file_push_buffer(ms)) == NULL) 313 goto error; 314 /* 315 * XXX: If file_buffer fails here, we overwrite 316 * the compressed text. FIXME. 317 */ 318 if (file_buffer(ms, -1, NULL, NULL, buf, nbytes) == -1) { 319 if (file_pop_buffer(ms, pb) != NULL) 320 abort(); 321 goto error; 322 } 323 if ((rbuf = file_pop_buffer(ms, pb)) != NULL) { 324 if (file_printf(ms, "%s", rbuf) == -1) { 325 free(rbuf); 326 goto error; 327 } 328 free(rbuf); 329 } 330 if (!mime && file_printf(ms, ")") == -1) 331 goto error; 332 /*FALLTHROUGH*/ 333 case NODATA: 334 break; 335 default: 336 abort(); 337 /*NOTREACHED*/ 338 error: 339 rv = -1; 340 break; 341 } 342 } 343 out: 344 DPRINTF("rv = %d\n", rv); 345 346 if (sa_saved && sig_act.sa_handler != SIG_IGN) 347 (void)sigaction(SIGPIPE, &sig_act, NULL); 348 349 free(newbuf); 350 ms->flags |= MAGIC_COMPRESS; 351 DPRINTF("Zmagic returns %d\n", rv); 352 return rv; 353 } 354 #endif 355 /* 356 * `safe' write for sockets and pipes. 357 */ 358 private ssize_t 359 swrite(int fd, const void *buf, size_t n) 360 { 361 ssize_t rv; 362 size_t rn = n; 363 364 do 365 switch (rv = write(fd, buf, n)) { 366 case -1: 367 if (errno == EINTR) 368 continue; 369 return -1; 370 default: 371 n -= rv; 372 buf = CAST(const char *, buf) + rv; 373 break; 374 } 375 while (n > 0); 376 return rn; 377 } 378 379 380 /* 381 * `safe' read for sockets and pipes. 382 */ 383 protected ssize_t 384 sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__))) 385 { 386 ssize_t rv; 387 #ifdef FIONREAD 388 int t = 0; 389 #endif 390 size_t rn = n; 391 392 if (fd == STDIN_FILENO) 393 goto nocheck; 394 395 #ifdef FIONREAD 396 if (canbepipe && (ioctl(fd, FIONREAD, &t) == -1 || t == 0)) { 397 #ifdef FD_ZERO 398 ssize_t cnt; 399 for (cnt = 0;; cnt++) { 400 fd_set check; 401 struct timeval tout = {0, 100 * 1000}; 402 int selrv; 403 404 FD_ZERO(&check); 405 FD_SET(fd, &check); 406 407 /* 408 * Avoid soft deadlock: do not read if there 409 * is nothing to read from sockets and pipes. 410 */ 411 selrv = select(fd + 1, &check, NULL, NULL, &tout); 412 if (selrv == -1) { 413 if (errno == EINTR || errno == EAGAIN) 414 continue; 415 } else if (selrv == 0 && cnt >= 5) { 416 return 0; 417 } else 418 break; 419 } 420 #endif 421 (void)ioctl(fd, FIONREAD, &t); 422 } 423 424 if (t > 0 && CAST(size_t, t) < n) { 425 n = t; 426 rn = n; 427 } 428 #endif 429 430 nocheck: 431 do 432 switch ((rv = read(fd, buf, n))) { 433 case -1: 434 if (errno == EINTR) 435 continue; 436 return -1; 437 case 0: 438 return rn - n; 439 default: 440 n -= rv; 441 buf = CAST(char *, CCAST(void *, buf)) + rv; 442 break; 443 } 444 while (n > 0); 445 return rn; 446 } 447 448 protected int 449 file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, 450 size_t nbytes) 451 { 452 char buf[4096]; 453 ssize_t r; 454 int tfd; 455 456 (void)strlcpy(buf, "/tmp/file.XXXXXX", sizeof buf); 457 #ifndef HAVE_MKSTEMP 458 { 459 char *ptr = mktemp(buf); 460 tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600); 461 r = errno; 462 (void)unlink(ptr); 463 errno = r; 464 } 465 #else 466 { 467 int te; 468 mode_t ou = umask(0); 469 tfd = mkstemp(buf); 470 (void)umask(ou); 471 te = errno; 472 (void)unlink(buf); 473 errno = te; 474 } 475 #endif 476 if (tfd == -1) { 477 file_error(ms, errno, 478 "cannot create temporary file for pipe copy"); 479 return -1; 480 } 481 482 if (swrite(tfd, startbuf, nbytes) != CAST(ssize_t, nbytes)) 483 r = 1; 484 else { 485 while ((r = sread(fd, buf, sizeof(buf), 1)) > 0) 486 if (swrite(tfd, buf, CAST(size_t, r)) != r) 487 break; 488 } 489 490 switch (r) { 491 case -1: 492 file_error(ms, errno, "error copying from pipe to temp file"); 493 return -1; 494 case 0: 495 break; 496 default: 497 file_error(ms, errno, "error while writing to temp file"); 498 return -1; 499 } 500 501 /* 502 * We duplicate the file descriptor, because fclose on a 503 * tmpfile will delete the file, but any open descriptors 504 * can still access the phantom inode. 505 */ 506 if ((fd = dup2(tfd, fd)) == -1) { 507 file_error(ms, errno, "could not dup descriptor for temp file"); 508 return -1; 509 } 510 (void)close(tfd); 511 if (lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1)) { 512 file_badseek(ms); 513 return -1; 514 } 515 return fd; 516 } 517 #if HAVE_FORK 518 #ifdef BUILTIN_DECOMPRESS 519 520 #define FHCRC (1 << 1) 521 #define FEXTRA (1 << 2) 522 #define FNAME (1 << 3) 523 #define FCOMMENT (1 << 4) 524 525 526 private int 527 uncompressgzipped(const unsigned char *old, unsigned char **newch, 528 size_t bytes_max, size_t *n) 529 { 530 unsigned char flg = old[3]; 531 size_t data_start = 10; 532 533 if (flg & FEXTRA) { 534 if (data_start + 1 >= *n) 535 goto err; 536 data_start += 2 + old[data_start] + old[data_start + 1] * 256; 537 } 538 if (flg & FNAME) { 539 while(data_start < *n && old[data_start]) 540 data_start++; 541 data_start++; 542 } 543 if (flg & FCOMMENT) { 544 while(data_start < *n && old[data_start]) 545 data_start++; 546 data_start++; 547 } 548 if (flg & FHCRC) 549 data_start += 2; 550 551 if (data_start >= *n) 552 goto err; 553 554 *n -= data_start; 555 old += data_start; 556 return uncompresszlib(old, newch, bytes_max, n, 0); 557 err: 558 return makeerror(newch, n, "File too short"); 559 } 560 561 private int 562 uncompresszlib(const unsigned char *old, unsigned char **newch, 563 size_t bytes_max, size_t *n, int zlib) 564 { 565 int rc; 566 z_stream z; 567 568 if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) 569 return makeerror(newch, n, "No buffer, %s", strerror(errno)); 570 571 z.next_in = CCAST(Bytef *, old); 572 z.avail_in = CAST(uint32_t, *n); 573 z.next_out = *newch; 574 z.avail_out = CAST(unsigned int, bytes_max); 575 z.zalloc = Z_NULL; 576 z.zfree = Z_NULL; 577 z.opaque = Z_NULL; 578 579 /* LINTED bug in header macro */ 580 rc = zlib ? inflateInit(&z) : inflateInit2(&z, -15); 581 if (rc != Z_OK) 582 goto err; 583 584 rc = inflate(&z, Z_SYNC_FLUSH); 585 if (rc != Z_OK && rc != Z_STREAM_END) 586 goto err; 587 588 *n = CAST(size_t, z.total_out); 589 rc = inflateEnd(&z); 590 if (rc != Z_OK) 591 goto err; 592 593 /* let's keep the nul-terminate tradition */ 594 (*newch)[*n] = '\0'; 595 596 return OKDATA; 597 err: 598 strlcpy(RCAST(char *, *newch), z.msg ? z.msg : zError(rc), bytes_max); 599 *n = strlen(RCAST(char *, *newch)); 600 return ERRDATA; 601 } 602 #endif 603 604 #ifdef BUILTIN_BZLIB 605 private int 606 uncompressbzlib(const unsigned char *old, unsigned char **newch, 607 size_t bytes_max, size_t *n) 608 { 609 int rc; 610 bz_stream bz; 611 612 memset(&bz, 0, sizeof(bz)); 613 rc = BZ2_bzDecompressInit(&bz, 0, 0); 614 if (rc != BZ_OK) 615 goto err; 616 617 if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) 618 return makeerror(newch, n, "No buffer, %s", strerror(errno)); 619 620 bz.next_in = CCAST(char *, RCAST(const char *, old)); 621 bz.avail_in = CAST(uint32_t, *n); 622 bz.next_out = RCAST(char *, *newch); 623 bz.avail_out = CAST(unsigned int, bytes_max); 624 625 rc = BZ2_bzDecompress(&bz); 626 if (rc != BZ_OK && rc != BZ_STREAM_END) 627 goto err; 628 629 /* Assume byte_max is within 32bit */ 630 /* assert(bz.total_out_hi32 == 0); */ 631 *n = CAST(size_t, bz.total_out_lo32); 632 rc = BZ2_bzDecompressEnd(&bz); 633 if (rc != BZ_OK) 634 goto err; 635 636 /* let's keep the nul-terminate tradition */ 637 (*newch)[*n] = '\0'; 638 639 return OKDATA; 640 err: 641 snprintf(RCAST(char *, *newch), bytes_max, "bunzip error %d", rc); 642 *n = strlen(RCAST(char *, *newch)); 643 return ERRDATA; 644 } 645 #endif 646 647 #ifdef BUILTIN_XZLIB 648 private int 649 uncompressxzlib(const unsigned char *old, unsigned char **newch, 650 size_t bytes_max, size_t *n) 651 { 652 int rc; 653 lzma_stream xz; 654 655 memset(&xz, 0, sizeof(xz)); 656 rc = lzma_auto_decoder(&xz, UINT64_MAX, 0); 657 if (rc != LZMA_OK) 658 goto err; 659 660 if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) 661 return makeerror(newch, n, "No buffer, %s", strerror(errno)); 662 663 xz.next_in = CCAST(const uint8_t *, old); 664 xz.avail_in = CAST(uint32_t, *n); 665 xz.next_out = RCAST(uint8_t *, *newch); 666 xz.avail_out = CAST(unsigned int, bytes_max); 667 668 rc = lzma_code(&xz, LZMA_RUN); 669 if (rc != LZMA_OK && rc != LZMA_STREAM_END) 670 goto err; 671 672 *n = CAST(size_t, xz.total_out); 673 674 lzma_end(&xz); 675 676 /* let's keep the nul-terminate tradition */ 677 (*newch)[*n] = '\0'; 678 679 return OKDATA; 680 err: 681 snprintf(RCAST(char *, *newch), bytes_max, "unxz error %d", rc); 682 *n = strlen(RCAST(char *, *newch)); 683 return ERRDATA; 684 } 685 #endif 686 687 688 static int 689 makeerror(unsigned char **buf, size_t *len, const char *fmt, ...) 690 { 691 char *msg; 692 va_list ap; 693 int rv; 694 695 va_start(ap, fmt); 696 rv = vasprintf(&msg, fmt, ap); 697 va_end(ap); 698 if (rv < 0) { 699 *buf = NULL; 700 *len = 0; 701 return NODATA; 702 } 703 *buf = RCAST(unsigned char *, msg); 704 *len = strlen(msg); 705 return ERRDATA; 706 } 707 708 static void 709 closefd(int *fd, size_t i) 710 { 711 if (fd[i] == -1) 712 return; 713 (void) close(fd[i]); 714 fd[i] = -1; 715 } 716 717 static void 718 closep(int *fd) 719 { 720 size_t i; 721 for (i = 0; i < 2; i++) 722 closefd(fd, i); 723 } 724 725 static int 726 copydesc(int i, int fd) 727 { 728 if (fd == i) 729 return 0; /* "no dup was necessary" */ 730 if (dup2(fd, i) == -1) { 731 DPRINTF("dup(%d, %d) failed (%s)\n", fd, i, strerror(errno)); 732 exit(1); 733 } 734 return 1; 735 } 736 737 static pid_t 738 writechild(int fd, const void *old, size_t n) 739 { 740 pid_t pid; 741 742 /* 743 * fork again, to avoid blocking because both 744 * pipes filled 745 */ 746 pid = fork(); 747 if (pid == -1) { 748 DPRINTF("Fork failed (%s)\n", strerror(errno)); 749 exit(1); 750 } 751 if (pid == 0) { 752 /* child */ 753 if (swrite(fd, old, n) != CAST(ssize_t, n)) { 754 DPRINTF("Write failed (%s)\n", strerror(errno)); 755 exit(1); 756 } 757 exit(0); 758 } 759 /* parent */ 760 return pid; 761 } 762 763 static ssize_t 764 filter_error(unsigned char *ubuf, ssize_t n) 765 { 766 char *p; 767 char *buf; 768 769 ubuf[n] = '\0'; 770 buf = RCAST(char *, ubuf); 771 while (isspace(CAST(unsigned char, *buf))) 772 buf++; 773 DPRINTF("Filter error[[[%s]]]\n", buf); 774 if ((p = strchr(CAST(char *, buf), '\n')) != NULL) 775 *p = '\0'; 776 if ((p = strchr(CAST(char *, buf), ';')) != NULL) 777 *p = '\0'; 778 if ((p = strrchr(CAST(char *, buf), ':')) != NULL) { 779 ++p; 780 while (isspace(CAST(unsigned char, *p))) 781 p++; 782 n = strlen(p); 783 memmove(ubuf, p, CAST(size_t, n + 1)); 784 } 785 DPRINTF("Filter error after[[[%s]]]\n", (char *)ubuf); 786 if (islower(*ubuf)) 787 *ubuf = toupper(*ubuf); 788 return n; 789 } 790 791 private const char * 792 methodname(size_t method) 793 { 794 switch (method) { 795 #ifdef BUILTIN_DECOMPRESS 796 case METH_FROZEN: 797 case METH_ZLIB: 798 return "zlib"; 799 #endif 800 #ifdef BUILTIN_BZLIB 801 case METH_BZIP: 802 return "bzlib"; 803 #endif 804 #ifdef BUILTIN_XZLIB 805 case METH_XZ: 806 case METH_LZMA: 807 return "xzlib"; 808 #endif 809 default: 810 return compr[method].argv[0]; 811 } 812 } 813 814 private int 815 uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, 816 unsigned char **newch, size_t* n) 817 { 818 int fdp[3][2]; 819 int status, rv, w; 820 pid_t pid; 821 pid_t writepid = -1; 822 size_t i; 823 ssize_t r; 824 825 switch (method) { 826 #ifdef BUILTIN_DECOMPRESS 827 case METH_FROZEN: 828 return uncompressgzipped(old, newch, bytes_max, n); 829 case METH_ZLIB: 830 return uncompresszlib(old, newch, bytes_max, n, 1); 831 #endif 832 #ifdef BUILTIN_BZLIB 833 case METH_BZIP: 834 return uncompressbzlib(old, newch, bytes_max, n); 835 #endif 836 #ifdef BUILTIN_XZLIB 837 case METH_XZ: 838 case METH_LZMA: 839 return uncompressxzlib(old, newch, bytes_max, n); 840 #endif 841 default: 842 break; 843 } 844 845 (void)fflush(stdout); 846 (void)fflush(stderr); 847 848 for (i = 0; i < __arraycount(fdp); i++) 849 fdp[i][0] = fdp[i][1] = -1; 850 851 if ((fd == -1 && pipe(fdp[STDIN_FILENO]) == -1) || 852 pipe(fdp[STDOUT_FILENO]) == -1 || pipe(fdp[STDERR_FILENO]) == -1) { 853 closep(fdp[STDIN_FILENO]); 854 closep(fdp[STDOUT_FILENO]); 855 return makeerror(newch, n, "Cannot create pipe, %s", 856 strerror(errno)); 857 } 858 859 /* For processes with large mapped virtual sizes, vfork 860 * may be _much_ faster (10-100 times) than fork. 861 */ 862 pid = vfork(); 863 if (pid == -1) { 864 return makeerror(newch, n, "Cannot vfork, %s", 865 strerror(errno)); 866 } 867 if (pid == 0) { 868 /* child */ 869 /* Note: we are after vfork, do not modify memory 870 * in a way which confuses parent. In particular, 871 * do not modify fdp[i][j]. 872 */ 873 if (fd != -1) { 874 (void) lseek(fd, CAST(off_t, 0), SEEK_SET); 875 if (copydesc(STDIN_FILENO, fd)) 876 (void) close(fd); 877 } else { 878 if (copydesc(STDIN_FILENO, fdp[STDIN_FILENO][0])) 879 (void) close(fdp[STDIN_FILENO][0]); 880 if (fdp[STDIN_FILENO][1] > 2) 881 (void) close(fdp[STDIN_FILENO][1]); 882 } 883 ///FIXME: if one of the fdp[i][j] is 0 or 1, this can bomb spectacularly 884 if (copydesc(STDOUT_FILENO, fdp[STDOUT_FILENO][1])) 885 (void) close(fdp[STDOUT_FILENO][1]); 886 if (fdp[STDOUT_FILENO][0] > 2) 887 (void) close(fdp[STDOUT_FILENO][0]); 888 889 if (copydesc(STDERR_FILENO, fdp[STDERR_FILENO][1])) 890 (void) close(fdp[STDERR_FILENO][1]); 891 if (fdp[STDERR_FILENO][0] > 2) 892 (void) close(fdp[STDERR_FILENO][0]); 893 894 (void)execvp(compr[method].argv[0], 895 RCAST(char *const *, RCAST(intptr_t, compr[method].argv))); 896 dprintf(STDERR_FILENO, "exec `%s' failed, %s", 897 compr[method].argv[0], strerror(errno)); 898 _exit(1); /* _exit(), not exit(), because of vfork */ 899 } 900 /* parent */ 901 /* Close write sides of child stdout/err pipes */ 902 for (i = 1; i < __arraycount(fdp); i++) 903 closefd(fdp[i], 1); 904 /* Write the buffer data to child stdin, if we don't have fd */ 905 if (fd == -1) { 906 closefd(fdp[STDIN_FILENO], 0); 907 writepid = writechild(fdp[STDIN_FILENO][1], old, *n); 908 closefd(fdp[STDIN_FILENO], 1); 909 } 910 911 *newch = CAST(unsigned char *, malloc(bytes_max + 1)); 912 if (*newch == NULL) { 913 rv = makeerror(newch, n, "No buffer, %s", 914 strerror(errno)); 915 goto err; 916 } 917 rv = OKDATA; 918 r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0); 919 if (r <= 0) { 920 DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0], 921 r != -1 ? strerror(errno) : "no data"); 922 923 rv = ERRDATA; 924 if (r == 0 && 925 (r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0) 926 { 927 r = filter_error(*newch, r); 928 goto ok; 929 } 930 free(*newch); 931 if (r == 0) 932 rv = makeerror(newch, n, "Read failed, %s", 933 strerror(errno)); 934 else 935 rv = makeerror(newch, n, "No data"); 936 goto err; 937 } 938 ok: 939 *n = r; 940 /* NUL terminate, as every buffer is handled here. */ 941 (*newch)[*n] = '\0'; 942 err: 943 closefd(fdp[STDIN_FILENO], 1); 944 closefd(fdp[STDOUT_FILENO], 0); 945 closefd(fdp[STDERR_FILENO], 0); 946 947 w = waitpid(pid, &status, 0); 948 wait_err: 949 if (w == -1) { 950 free(*newch); 951 rv = makeerror(newch, n, "Wait failed, %s", strerror(errno)); 952 DPRINTF("Child wait return %#x\n", status); 953 } else if (!WIFEXITED(status)) { 954 DPRINTF("Child not exited (%#x)\n", status); 955 } else if (WEXITSTATUS(status) != 0) { 956 DPRINTF("Child exited (%#x)\n", WEXITSTATUS(status)); 957 } 958 if (writepid > 0) { 959 /* _After_ we know decompressor has exited, our input writer 960 * definitely will exit now (at worst, writing fails in it, 961 * since output fd is closed now on the reading size). 962 */ 963 w = waitpid(writepid, &status, 0); 964 writepid = -1; 965 goto wait_err; 966 } 967 968 closefd(fdp[STDIN_FILENO], 0); //why? it is already closed here! 969 DPRINTF("Returning %p n=%" SIZE_T_FORMAT "u rv=%d\n", *newch, *n, rv); 970 971 return rv; 972 } 973 #endif 974