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