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.107 2018/04/28 18:48:22 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 #ifdef HAVE_SIGNAL_H 51 #include <signal.h> 52 # ifndef HAVE_SIG_T 53 typedef void (*sig_t)(int); 54 # endif /* HAVE_SIG_T */ 55 #endif 56 #if !defined(__MINGW32__) && !defined(WIN32) 57 #include <sys/ioctl.h> 58 #endif 59 #ifdef HAVE_SYS_WAIT_H 60 #include <sys/wait.h> 61 #endif 62 #if defined(HAVE_SYS_TIME_H) 63 #include <sys/time.h> 64 #endif 65 #if defined(HAVE_ZLIB_H) && defined(ZLIBSUPPORT) 66 #define BUILTIN_DECOMPRESS 67 #include <zlib.h> 68 #endif 69 #ifdef DEBUG 70 int tty = -1; 71 #define DPRINTF(...) do { \ 72 if (tty == -1) \ 73 tty = open("/dev/tty", O_RDWR); \ 74 if (tty == -1) \ 75 abort(); \ 76 dprintf(tty, __VA_ARGS__); \ 77 } while (/*CONSTCOND*/0) 78 #else 79 #define DPRINTF(...) 80 #endif 81 82 #ifdef ZLIBSUPPORT 83 /* 84 * The following python code is not really used because ZLIBSUPPORT is only 85 * defined if we have a built-in zlib, and the built-in zlib handles that. 86 * That is not true for android where we have zlib.h and not -lz. 87 */ 88 static const char zlibcode[] = 89 "import sys, zlib; sys.stdout.write(zlib.decompress(sys.stdin.read()))"; 90 91 static const char *zlib_args[] = { "python", "-c", zlibcode, NULL }; 92 93 static int 94 zlibcmp(const unsigned char *buf) 95 { 96 unsigned short x = 1; 97 unsigned char *s = CAST(unsigned char *, CAST(void *, &x)); 98 99 if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0) 100 return 0; 101 if (s[0] != 1) /* endianness test */ 102 x = buf[0] | (buf[1] << 8); 103 else 104 x = buf[1] | (buf[0] << 8); 105 if (x % 31) 106 return 0; 107 return 1; 108 } 109 #endif 110 111 #define gzip_flags "-cd" 112 #define lrzip_flags "-do" 113 #define lzip_flags gzip_flags 114 115 static const char *gzip_args[] = { 116 "gzip", gzip_flags, NULL 117 }; 118 static const char *uncompress_args[] = { 119 "uncompress", "-c", NULL 120 }; 121 static const char *bzip2_args[] = { 122 "bzip2", "-cd", NULL 123 }; 124 static const char *lzip_args[] = { 125 "lzip", lzip_flags, NULL 126 }; 127 static const char *xz_args[] = { 128 "xz", "-cd", NULL 129 }; 130 static const char *lrzip_args[] = { 131 "lrzip", lrzip_flags, NULL 132 }; 133 static const char *lz4_args[] = { 134 "lz4", "-cd", NULL 135 }; 136 static const char *zstd_args[] = { 137 "zstd", "-cd", NULL 138 }; 139 140 private const struct { 141 const void *magic; 142 size_t maglen; 143 const char **argv; 144 } compr[] = { 145 { "\037\235", 2, gzip_args }, /* compressed */ 146 /* Uncompress can get stuck; so use gzip first if we have it 147 * Idea from Damien Clark, thanks! */ 148 { "\037\235", 2, uncompress_args }, /* compressed */ 149 { "\037\213", 2, gzip_args }, /* gzipped */ 150 { "\037\236", 2, gzip_args }, /* frozen */ 151 { "\037\240", 2, gzip_args }, /* SCO LZH */ 152 /* the standard pack utilities do not accept standard input */ 153 { "\037\036", 2, gzip_args }, /* packed */ 154 { "PK\3\4", 4, gzip_args }, /* pkzipped, */ 155 /* ...only first file examined */ 156 { "BZh", 3, bzip2_args }, /* bzip2-ed */ 157 { "LZIP", 4, lzip_args }, /* lzip-ed */ 158 { "\3757zXZ\0", 6, xz_args }, /* XZ Utils */ 159 { "LRZI", 4, lrzip_args }, /* LRZIP */ 160 { "\004\"M\030",4, lz4_args }, /* LZ4 */ 161 { "\x28\xB5\x2F\xFD", 4, zstd_args }, /* zstd */ 162 #ifdef ZLIBSUPPORT 163 { RCAST(const void *, zlibcmp), 0, zlib_args }, /* zlib */ 164 #endif 165 }; 166 167 #define OKDATA 0 168 #define NODATA 1 169 #define ERRDATA 2 170 171 private ssize_t swrite(int, const void *, size_t); 172 #if HAVE_FORK 173 private size_t ncompr = sizeof(compr) / sizeof(compr[0]); 174 private int uncompressbuf(int, size_t, size_t, const unsigned char *, 175 unsigned char **, size_t *); 176 #ifdef BUILTIN_DECOMPRESS 177 private int uncompresszlib(const unsigned char *, unsigned char **, size_t, 178 size_t *, int); 179 private int uncompressgzipped(const unsigned char *, unsigned char **, size_t, 180 size_t *); 181 #endif 182 static int makeerror(unsigned char **, size_t *, const char *, ...) 183 __attribute__((__format__(__printf__, 3, 4))); 184 private const char *methodname(size_t); 185 186 private int 187 format_decompression_error(struct magic_set *ms, size_t i, unsigned char *buf) 188 { 189 unsigned char *p; 190 int mime = ms->flags & MAGIC_MIME; 191 192 if (!mime) 193 return file_printf(ms, "ERROR:[%s: %s]", methodname(i), buf); 194 195 for (p = buf; *p; p++) 196 if (!isalnum(*p)) 197 *p = '-'; 198 199 return file_printf(ms, "application/x-decompression-error-%s-%s", 200 methodname(i), buf); 201 } 202 203 protected int 204 file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) 205 { 206 unsigned char *newbuf = NULL; 207 size_t i, nsz; 208 char *rbuf; 209 file_pushbuf_t *pb; 210 int urv, prv, rv = 0; 211 int mime = ms->flags & MAGIC_MIME; 212 int fd = b->fd; 213 const unsigned char *buf = b->fbuf; 214 size_t nbytes = b->flen; 215 #ifdef HAVE_SIGNAL_H 216 sig_t osigpipe; 217 #endif 218 219 if ((ms->flags & MAGIC_COMPRESS) == 0) 220 return 0; 221 222 #ifdef HAVE_SIGNAL_H 223 osigpipe = signal(SIGPIPE, SIG_IGN); 224 #endif 225 for (i = 0; i < ncompr; i++) { 226 int zm; 227 if (nbytes < compr[i].maglen) 228 continue; 229 #ifdef ZLIBSUPPORT 230 if (compr[i].maglen == 0) 231 zm = (RCAST(int (*)(const unsigned char *), 232 CCAST(void *, compr[i].magic)))(buf); 233 else 234 #endif 235 zm = memcmp(buf, compr[i].magic, compr[i].maglen) == 0; 236 237 if (!zm) 238 continue; 239 nsz = nbytes; 240 urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz); 241 DPRINTF("uncompressbuf = %d, %s, %zu\n", urv, (char *)newbuf, 242 nsz); 243 switch (urv) { 244 case OKDATA: 245 case ERRDATA: 246 ms->flags &= ~MAGIC_COMPRESS; 247 if (urv == ERRDATA) 248 prv = format_decompression_error(ms, i, newbuf); 249 else 250 prv = file_buffer(ms, -1, name, newbuf, nsz); 251 if (prv == -1) 252 goto error; 253 rv = 1; 254 if ((ms->flags & MAGIC_COMPRESS_TRANSP) != 0) 255 goto out; 256 if (mime != MAGIC_MIME && mime != 0) 257 goto out; 258 if ((file_printf(ms, 259 mime ? " compressed-encoding=" : " (")) == -1) 260 goto error; 261 if ((pb = file_push_buffer(ms)) == NULL) 262 goto error; 263 /* 264 * XXX: If file_buffer fails here, we overwrite 265 * the compressed text. FIXME. 266 */ 267 if (file_buffer(ms, -1, NULL, buf, nbytes) == -1) 268 goto error; 269 if ((rbuf = file_pop_buffer(ms, pb)) != NULL) { 270 if (file_printf(ms, "%s", rbuf) == -1) { 271 free(rbuf); 272 goto error; 273 } 274 free(rbuf); 275 } 276 if (!mime && file_printf(ms, ")") == -1) 277 goto error; 278 /*FALLTHROUGH*/ 279 case NODATA: 280 break; 281 default: 282 abort(); 283 /*NOTREACHED*/ 284 error: 285 rv = -1; 286 break; 287 } 288 } 289 out: 290 DPRINTF("rv = %d\n", rv); 291 292 #ifdef HAVE_SIGNAL_H 293 (void)signal(SIGPIPE, osigpipe); 294 #endif 295 free(newbuf); 296 ms->flags |= MAGIC_COMPRESS; 297 DPRINTF("Zmagic returns %d\n", rv); 298 return rv; 299 } 300 #endif 301 /* 302 * `safe' write for sockets and pipes. 303 */ 304 private ssize_t 305 swrite(int fd, const void *buf, size_t n) 306 { 307 ssize_t rv; 308 size_t rn = n; 309 310 do 311 switch (rv = write(fd, buf, n)) { 312 case -1: 313 if (errno == EINTR) 314 continue; 315 return -1; 316 default: 317 n -= rv; 318 buf = CAST(const char *, buf) + rv; 319 break; 320 } 321 while (n > 0); 322 return rn; 323 } 324 325 326 /* 327 * `safe' read for sockets and pipes. 328 */ 329 protected ssize_t 330 sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__))) 331 { 332 ssize_t rv; 333 #ifdef FIONREAD 334 int t = 0; 335 #endif 336 size_t rn = n; 337 338 if (fd == STDIN_FILENO) 339 goto nocheck; 340 341 #ifdef FIONREAD 342 if (canbepipe && (ioctl(fd, FIONREAD, &t) == -1 || t == 0)) { 343 #ifdef FD_ZERO 344 ssize_t cnt; 345 for (cnt = 0;; cnt++) { 346 fd_set check; 347 struct timeval tout = {0, 100 * 1000}; 348 int selrv; 349 350 FD_ZERO(&check); 351 FD_SET(fd, &check); 352 353 /* 354 * Avoid soft deadlock: do not read if there 355 * is nothing to read from sockets and pipes. 356 */ 357 selrv = select(fd + 1, &check, NULL, NULL, &tout); 358 if (selrv == -1) { 359 if (errno == EINTR || errno == EAGAIN) 360 continue; 361 } else if (selrv == 0 && cnt >= 5) { 362 return 0; 363 } else 364 break; 365 } 366 #endif 367 (void)ioctl(fd, FIONREAD, &t); 368 } 369 370 if (t > 0 && (size_t)t < n) { 371 n = t; 372 rn = n; 373 } 374 #endif 375 376 nocheck: 377 do 378 switch ((rv = read(fd, buf, n))) { 379 case -1: 380 if (errno == EINTR) 381 continue; 382 return -1; 383 case 0: 384 return rn - n; 385 default: 386 n -= rv; 387 buf = CAST(char *, CCAST(void *, buf)) + rv; 388 break; 389 } 390 while (n > 0); 391 return rn; 392 } 393 394 protected int 395 file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, 396 size_t nbytes) 397 { 398 char buf[4096]; 399 ssize_t r; 400 int tfd; 401 402 (void)strlcpy(buf, "/tmp/file.XXXXXX", sizeof buf); 403 #ifndef HAVE_MKSTEMP 404 { 405 char *ptr = mktemp(buf); 406 tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600); 407 r = errno; 408 (void)unlink(ptr); 409 errno = r; 410 } 411 #else 412 { 413 int te; 414 tfd = mkstemp(buf); 415 te = errno; 416 (void)unlink(buf); 417 errno = te; 418 } 419 #endif 420 if (tfd == -1) { 421 file_error(ms, errno, 422 "cannot create temporary file for pipe copy"); 423 return -1; 424 } 425 426 if (swrite(tfd, startbuf, nbytes) != (ssize_t)nbytes) 427 r = 1; 428 else { 429 while ((r = sread(fd, buf, sizeof(buf), 1)) > 0) 430 if (swrite(tfd, buf, (size_t)r) != r) 431 break; 432 } 433 434 switch (r) { 435 case -1: 436 file_error(ms, errno, "error copying from pipe to temp file"); 437 return -1; 438 case 0: 439 break; 440 default: 441 file_error(ms, errno, "error while writing to temp file"); 442 return -1; 443 } 444 445 /* 446 * We duplicate the file descriptor, because fclose on a 447 * tmpfile will delete the file, but any open descriptors 448 * can still access the phantom inode. 449 */ 450 if ((fd = dup2(tfd, fd)) == -1) { 451 file_error(ms, errno, "could not dup descriptor for temp file"); 452 return -1; 453 } 454 (void)close(tfd); 455 if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { 456 file_badseek(ms); 457 return -1; 458 } 459 return fd; 460 } 461 #if HAVE_FORK 462 #ifdef BUILTIN_DECOMPRESS 463 464 #define FHCRC (1 << 1) 465 #define FEXTRA (1 << 2) 466 #define FNAME (1 << 3) 467 #define FCOMMENT (1 << 4) 468 469 470 private int 471 uncompressgzipped(const unsigned char *old, unsigned char **newch, 472 size_t bytes_max, size_t *n) 473 { 474 unsigned char flg = old[3]; 475 size_t data_start = 10; 476 477 if (flg & FEXTRA) { 478 if (data_start + 1 >= *n) 479 goto err; 480 data_start += 2 + old[data_start] + old[data_start + 1] * 256; 481 } 482 if (flg & FNAME) { 483 while(data_start < *n && old[data_start]) 484 data_start++; 485 data_start++; 486 } 487 if (flg & FCOMMENT) { 488 while(data_start < *n && old[data_start]) 489 data_start++; 490 data_start++; 491 } 492 if (flg & FHCRC) 493 data_start += 2; 494 495 if (data_start >= *n) 496 goto err; 497 498 *n -= data_start; 499 old += data_start; 500 return uncompresszlib(old, newch, bytes_max, n, 0); 501 err: 502 return makeerror(newch, n, "File too short"); 503 } 504 505 private int 506 uncompresszlib(const unsigned char *old, unsigned char **newch, 507 size_t bytes_max, size_t *n, int zlib) 508 { 509 int rc; 510 z_stream z; 511 512 if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL) 513 return makeerror(newch, n, "No buffer, %s", strerror(errno)); 514 515 z.next_in = CCAST(Bytef *, old); 516 z.avail_in = CAST(uint32_t, *n); 517 z.next_out = *newch; 518 z.avail_out = CAST(unsigned int, bytes_max); 519 z.zalloc = Z_NULL; 520 z.zfree = Z_NULL; 521 z.opaque = Z_NULL; 522 523 /* LINTED bug in header macro */ 524 rc = zlib ? inflateInit(&z) : inflateInit2(&z, -15); 525 if (rc != Z_OK) 526 goto err; 527 528 rc = inflate(&z, Z_SYNC_FLUSH); 529 if (rc != Z_OK && rc != Z_STREAM_END) 530 goto err; 531 532 *n = (size_t)z.total_out; 533 rc = inflateEnd(&z); 534 if (rc != Z_OK) 535 goto err; 536 537 /* let's keep the nul-terminate tradition */ 538 (*newch)[*n] = '\0'; 539 540 return OKDATA; 541 err: 542 strlcpy((char *)*newch, z.msg ? z.msg : zError(rc), bytes_max); 543 *n = strlen((char *)*newch); 544 return ERRDATA; 545 } 546 #endif 547 548 static int 549 makeerror(unsigned char **buf, size_t *len, const char *fmt, ...) 550 { 551 char *msg; 552 va_list ap; 553 int rv; 554 555 va_start(ap, fmt); 556 rv = vasprintf(&msg, fmt, ap); 557 va_end(ap); 558 if (rv < 0) { 559 *buf = NULL; 560 *len = 0; 561 return NODATA; 562 } 563 *buf = (unsigned char *)msg; 564 *len = strlen(msg); 565 return ERRDATA; 566 } 567 568 static void 569 closefd(int *fd, size_t i) 570 { 571 if (fd[i] == -1) 572 return; 573 (void) close(fd[i]); 574 fd[i] = -1; 575 } 576 577 static void 578 closep(int *fd) 579 { 580 size_t i; 581 for (i = 0; i < 2; i++) 582 closefd(fd, i); 583 } 584 585 static void 586 copydesc(int i, int *fd) 587 { 588 int j = fd[i == STDIN_FILENO ? 0 : 1]; 589 if (j == i) 590 return; 591 if (dup2(j, i) == -1) { 592 DPRINTF("dup(%d, %d) failed (%s)\n", j, i, strerror(errno)); 593 exit(1); 594 } 595 closep(fd); 596 } 597 598 static void 599 writechild(int fdp[3][2], const void *old, size_t n) 600 { 601 int status; 602 603 closefd(fdp[STDIN_FILENO], 0); 604 /* 605 * fork again, to avoid blocking because both 606 * pipes filled 607 */ 608 switch (fork()) { 609 case 0: /* child */ 610 closefd(fdp[STDOUT_FILENO], 0); 611 if (swrite(fdp[STDIN_FILENO][1], old, n) != (ssize_t)n) { 612 DPRINTF("Write failed (%s)\n", strerror(errno)); 613 exit(1); 614 } 615 exit(0); 616 /*NOTREACHED*/ 617 618 case -1: 619 DPRINTF("Fork failed (%s)\n", strerror(errno)); 620 exit(1); 621 /*NOTREACHED*/ 622 623 default: /* parent */ 624 if (wait(&status) == -1) { 625 DPRINTF("Wait failed (%s)\n", strerror(errno)); 626 exit(1); 627 } 628 DPRINTF("Grandchild wait return %#x\n", status); 629 } 630 closefd(fdp[STDIN_FILENO], 1); 631 } 632 633 static ssize_t 634 filter_error(unsigned char *ubuf, ssize_t n) 635 { 636 char *p; 637 char *buf; 638 639 ubuf[n] = '\0'; 640 buf = (char *)ubuf; 641 while (isspace((unsigned char)*buf)) 642 buf++; 643 DPRINTF("Filter error[[[%s]]]\n", buf); 644 if ((p = strchr((char *)buf, '\n')) != NULL) 645 *p = '\0'; 646 if ((p = strchr((char *)buf, ';')) != NULL) 647 *p = '\0'; 648 if ((p = strrchr((char *)buf, ':')) != NULL) { 649 ++p; 650 while (isspace((unsigned char)*p)) 651 p++; 652 n = strlen(p); 653 memmove(ubuf, p, CAST(size_t, n + 1)); 654 } 655 DPRINTF("Filter error after[[[%s]]]\n", (char *)ubuf); 656 if (islower(*ubuf)) 657 *ubuf = toupper(*ubuf); 658 return n; 659 } 660 661 private const char * 662 methodname(size_t method) 663 { 664 #ifdef BUILTIN_DECOMPRESS 665 /* FIXME: This doesn't cope with bzip2 */ 666 if (method == 2 || compr[method].maglen == 0) 667 return "zlib"; 668 #endif 669 return compr[method].argv[0]; 670 } 671 672 private int 673 uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old, 674 unsigned char **newch, size_t* n) 675 { 676 int fdp[3][2]; 677 int status, rv; 678 size_t i; 679 ssize_t r; 680 681 #ifdef BUILTIN_DECOMPRESS 682 /* FIXME: This doesn't cope with bzip2 */ 683 if (method == 2) 684 return uncompressgzipped(old, newch, bytes_max, n); 685 if (compr[method].maglen == 0) 686 return uncompresszlib(old, newch, bytes_max, n, 1); 687 #endif 688 (void)fflush(stdout); 689 (void)fflush(stderr); 690 691 for (i = 0; i < __arraycount(fdp); i++) 692 fdp[i][0] = fdp[i][1] = -1; 693 694 if ((fd == -1 && pipe(fdp[STDIN_FILENO]) == -1) || 695 pipe(fdp[STDOUT_FILENO]) == -1 || pipe(fdp[STDERR_FILENO]) == -1) { 696 closep(fdp[STDIN_FILENO]); 697 closep(fdp[STDOUT_FILENO]); 698 return makeerror(newch, n, "Cannot create pipe, %s", 699 strerror(errno)); 700 } 701 switch (fork()) { 702 case 0: /* child */ 703 if (fd != -1) { 704 fdp[STDIN_FILENO][0] = fd; 705 (void) lseek(fd, (off_t)0, SEEK_SET); 706 } 707 708 for (i = 0; i < __arraycount(fdp); i++) 709 copydesc(CAST(int, i), fdp[i]); 710 711 (void)execvp(compr[method].argv[0], 712 (char *const *)(intptr_t)compr[method].argv); 713 dprintf(STDERR_FILENO, "exec `%s' failed, %s", 714 compr[method].argv[0], strerror(errno)); 715 exit(1); 716 /*NOTREACHED*/ 717 case -1: 718 return makeerror(newch, n, "Cannot fork, %s", 719 strerror(errno)); 720 721 default: /* parent */ 722 for (i = 1; i < __arraycount(fdp); i++) 723 closefd(fdp[i], 1); 724 725 /* Write the buffer data to the child, if we don't have fd */ 726 if (fd == -1) 727 writechild(fdp, old, *n); 728 729 *newch = CAST(unsigned char *, malloc(bytes_max + 1)); 730 if (*newch == NULL) { 731 rv = makeerror(newch, n, "No buffer, %s", 732 strerror(errno)); 733 goto err; 734 } 735 rv = OKDATA; 736 if ((r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0)) > 0) 737 break; 738 DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0], 739 r != -1 ? strerror(errno) : "no data"); 740 741 rv = ERRDATA; 742 if (r == 0 && 743 (r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0) 744 { 745 r = filter_error(*newch, r); 746 break; 747 } 748 free(*newch); 749 if (r == 0) 750 rv = makeerror(newch, n, "Read failed, %s", 751 strerror(errno)); 752 else 753 rv = makeerror(newch, n, "No data"); 754 goto err; 755 } 756 757 *n = r; 758 /* NUL terminate, as every buffer is handled here. */ 759 (*newch)[*n] = '\0'; 760 err: 761 closefd(fdp[STDIN_FILENO], 1); 762 closefd(fdp[STDOUT_FILENO], 0); 763 closefd(fdp[STDERR_FILENO], 0); 764 if (wait(&status) == -1) { 765 free(*newch); 766 rv = makeerror(newch, n, "Wait failed, %s", strerror(errno)); 767 DPRINTF("Child wait return %#x\n", status); 768 } else if (!WIFEXITED(status)) { 769 DPRINTF("Child not exited (%#x)\n", status); 770 } else if (WEXITSTATUS(status) != 0) { 771 DPRINTF("Child exited (%#x)\n", WEXITSTATUS(status)); 772 } 773 774 closefd(fdp[STDIN_FILENO], 0); 775 DPRINTF("Returning %p n=%zu rv=%d\n", *newch, *n, rv); 776 777 return rv; 778 } 779 #endif 780