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