Coverage Report

Created: 2023-09-25 07:18

/src/file/src/compress.c
Line
Count
Source (jump to first uncovered line)
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.157 2023/05/21 15:59:58 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
#ifdef HAVE_SPAWN_H
47
#include <spawn.h>
48
#endif
49
#include <string.h>
50
#include <errno.h>
51
#include <ctype.h>
52
#include <stdarg.h>
53
#include <signal.h>
54
#ifndef HAVE_SIG_T
55
typedef void (*sig_t)(int);
56
#endif /* HAVE_SIG_T */
57
#ifdef HAVE_SYS_IOCTL_H
58
#include <sys/ioctl.h>
59
#endif
60
#ifdef HAVE_SYS_WAIT_H
61
#include <sys/wait.h>
62
#endif
63
#if defined(HAVE_SYS_TIME_H)
64
#include <sys/time.h>
65
#endif
66
67
#if defined(HAVE_ZLIB_H) && defined(ZLIBSUPPORT)
68
#define BUILTIN_DECOMPRESS
69
#include <zlib.h>
70
#endif
71
72
#if defined(HAVE_BZLIB_H) && defined(BZLIBSUPPORT)
73
#define BUILTIN_BZLIB
74
#include <bzlib.h>
75
#endif
76
77
#if defined(HAVE_LZMA_H) && defined(XZLIBSUPPORT)
78
#define BUILTIN_XZLIB
79
#include <lzma.h>
80
#endif
81
82
#if defined(HAVE_ZSTD_H) && defined(ZSTDLIBSUPPORT)
83
#define BUILTIN_ZSTDLIB
84
#include <zstd.h>
85
#include <zstd_errors.h>
86
#endif
87
88
#if defined(HAVE_LZLIB_H) && defined(LZLIBSUPPORT)
89
#define BUILTIN_LZLIB
90
#include <lzlib.h>
91
#endif
92
93
#ifdef DEBUG
94
int tty = -1;
95
#define DPRINTF(...)  do { \
96
  if (tty == -1) \
97
    tty = open("/dev/tty", O_RDWR); \
98
  if (tty == -1) \
99
    abort(); \
100
  dprintf(tty, __VA_ARGS__); \
101
} while (/*CONSTCOND*/0)
102
#else
103
#define DPRINTF(...)
104
#endif
105
106
#ifdef ZLIBSUPPORT
107
/*
108
 * The following python code is not really used because ZLIBSUPPORT is only
109
 * defined if we have a built-in zlib, and the built-in zlib handles that.
110
 * That is not true for android where we have zlib.h and not -lz.
111
 */
112
static const char zlibcode[] =
113
    "import sys, zlib; sys.stdout.write(zlib.decompress(sys.stdin.read()))";
114
115
static const char *zlib_args[] = { "python", "-c", zlibcode, NULL };
116
117
static int
118
zlibcmp(const unsigned char *buf)
119
7.48k
{
120
7.48k
  unsigned short x = 1;
121
7.48k
  unsigned char *s = CAST(unsigned char *, CAST(void *, &x));
122
123
7.48k
  if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0)
124
7.43k
    return 0;
125
54
  if (s[0] != 1)  /* endianness test */
126
0
    x = buf[0] | (buf[1] << 8);
127
54
  else
128
54
    x = buf[1] | (buf[0] << 8);
129
54
  if (x % 31)
130
26
    return 0;
131
28
  return 1;
132
54
}
133
#endif
134
135
static int
136
lzmacmp(const unsigned char *buf)
137
4.60k
{
138
4.60k
  if (buf[0] != 0x5d || buf[1] || buf[2])
139
4.59k
    return 0;
140
13
  if (buf[12] && buf[12] != 0xff)
141
10
    return 0;
142
3
  return 1;
143
13
}
144
145
#define gzip_flags "-cd"
146
#define lzip_flags gzip_flags
147
148
static const char *gzip_args[] = {
149
  "gzip", gzip_flags, NULL
150
};
151
static const char *uncompress_args[] = {
152
  "uncompress", "-c", NULL
153
};
154
static const char *bzip2_args[] = {
155
  "bzip2", "-cd", NULL
156
};
157
static const char *lzip_args[] = {
158
  "lzip", lzip_flags, NULL
159
};
160
static const char *xz_args[] = {
161
  "xz", "-cd", NULL
162
};
163
static const char *lrzip_args[] = {
164
  "lrzip", "-qdf", "-", NULL
165
};
166
static const char *lz4_args[] = {
167
  "lz4", "-cd", NULL
168
};
169
static const char *zstd_args[] = {
170
  "zstd", "-cd", NULL
171
};
172
173
#define do_zlib   NULL
174
#define do_bzlib  NULL
175
176
file_private const struct {
177
  union {
178
    const char *magic;
179
    int (*func)(const unsigned char *);
180
  } u;
181
  int maglen;
182
  const char **argv;
183
  void *unused;
184
} compr[] = {
185
22
#define METH_FROZEN 2
186
14
#define METH_BZIP 7
187
4
#define METH_XZ   9
188
#define METH_LZIP 8
189
6
#define METH_ZSTD 12
190
10
#define METH_LZMA 13
191
67
#define METH_ZLIB 14
192
    { { .magic = "\037\235" },  2, gzip_args, NULL }, /* 0, compressed */
193
    /* Uncompress can get stuck; so use gzip first if we have it
194
     * Idea from Damien Clark, thanks! */
195
    { { .magic = "\037\235" },  2, uncompress_args, NULL },/* 1, compressed */
196
    { { .magic = "\037\213" },  2, gzip_args, do_zlib },/* 2, gzipped */
197
    { { .magic = "\037\236" },  2, gzip_args, NULL }, /* 3, frozen */
198
    { { .magic = "\037\240" },  2, gzip_args, NULL }, /* 4, SCO LZH */
199
    /* the standard pack utilities do not accept standard input */
200
    { { .magic = "\037\036" },  2, gzip_args, NULL }, /* 5, packed */
201
    { { .magic = "PK\3\4" },  4, gzip_args, NULL }, /* 6, pkziped */
202
    /* ...only first file examined */
203
    { { .magic = "BZh" }, 3, bzip2_args, do_bzlib },/* 7, bzip2-ed */
204
    { { .magic = "LZIP" },  4, lzip_args, NULL }, /* 8, lzip-ed */
205
    { { .magic = "\3757zXZ\0" },6, xz_args, NULL }, /* 9, XZ Util */
206
    { { .magic = "LRZI" },  4, lrzip_args, NULL },  /* 10, LRZIP */
207
    { { .magic = "\004\"M\030" },4, lz4_args, NULL }, /* 11, LZ4 */
208
    { { .magic = "\x28\xB5\x2F\xFD" }, 4, zstd_args, NULL },/* 12, zstd */
209
    { { .func = lzmacmp },  -13, xz_args, NULL }, /* 13, lzma */
210
#ifdef ZLIBSUPPORT
211
    { { .func = zlibcmp },  -2, zlib_args, NULL },  /* 14, zlib */
212
#endif
213
};
214
215
5.23k
#define OKDATA  0
216
2.74k
#define NODATA  1
217
5.77k
#define ERRDATA 2
218
219
file_private ssize_t swrite(int, const void *, size_t);
220
#if HAVE_FORK
221
file_private size_t ncompr = __arraycount(compr);
222
file_private int uncompressbuf(int, size_t, size_t, int, const unsigned char *,
223
    unsigned char **, size_t *);
224
#ifdef BUILTIN_DECOMPRESS
225
file_private int uncompresszlib(const unsigned char *, unsigned char **, size_t,
226
    size_t *, int);
227
file_private int uncompressgzipped(const unsigned char *, unsigned char **, size_t,
228
    size_t *, int);
229
#endif
230
#ifdef BUILTIN_BZLIB
231
file_private int uncompressbzlib(const unsigned char *, unsigned char **, size_t,
232
    size_t *, int);
233
#endif
234
#ifdef BUILTIN_XZLIB
235
file_private int uncompressxzlib(const unsigned char *, unsigned char **, size_t,
236
    size_t *, int);
237
#endif
238
#ifdef BUILTIN_ZSTDLIB
239
file_private int uncompresszstd(const unsigned char *, unsigned char **, size_t,
240
    size_t *, int);
241
#endif
242
#ifdef BUILTIN_LZLIB
243
file_private int uncompresslzlib(const unsigned char *, unsigned char **, size_t,
244
    size_t *, int);
245
#endif
246
247
static int makeerror(unsigned char **, size_t *, const char *, ...)
248
    __attribute__((__format__(__printf__, 3, 4)));
249
file_private const char *methodname(size_t);
250
251
file_private int
252
format_decompression_error(struct magic_set *ms, size_t i, unsigned char *buf)
253
242
{
254
242
  unsigned char *p;
255
242
  int mime = ms->flags & MAGIC_MIME;
256
257
242
  if (!mime)
258
242
    return file_printf(ms, "ERROR:[%s: %s]", methodname(i), buf);
259
260
0
  for (p = buf; *p; p++)
261
0
    if (!isalnum(*p))
262
0
      *p = '-';
263
264
0
  return file_printf(ms, "application/x-decompression-error-%s-%s",
265
0
      methodname(i), buf);
266
242
}
267
268
file_protected int
269
file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
270
12.7k
{
271
12.7k
  unsigned char *newbuf = NULL;
272
12.7k
  size_t i, nsz;
273
12.7k
  char *rbuf;
274
12.7k
  file_pushbuf_t *pb;
275
12.7k
  int urv, prv, rv = 0;
276
12.7k
  int mime = ms->flags & MAGIC_MIME;
277
12.7k
  int fd = b->fd;
278
12.7k
  const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
279
12.7k
  size_t nbytes = b->flen;
280
12.7k
  int sa_saved = 0;
281
12.7k
  struct sigaction sig_act;
282
283
12.7k
  if ((ms->flags & MAGIC_COMPRESS) == 0)
284
5.25k
    return 0;
285
286
119k
  for (i = 0; i < ncompr; i++) {
287
112k
    int zm;
288
112k
    if (nbytes < CAST(size_t, abs(compr[i].maglen)))
289
6.91k
      continue;
290
105k
    if (compr[i].maglen < 0) {
291
12.0k
      zm = (*compr[i].u.func)(buf);
292
93.2k
    } else {
293
93.2k
      zm = memcmp(buf, compr[i].u.magic,
294
93.2k
          CAST(size_t, compr[i].maglen)) == 0;
295
93.2k
    }
296
297
105k
    if (!zm)
298
102k
      continue;
299
300
    /* Prevent SIGPIPE death if child dies unexpectedly */
301
2.76k
    if (!sa_saved) {
302
      //We can use sig_act for both new and old, but
303
2.47k
      struct sigaction new_act;
304
2.47k
      memset(&new_act, 0, sizeof(new_act));
305
2.47k
      new_act.sa_handler = SIG_IGN;
306
2.47k
      sa_saved = sigaction(SIGPIPE, &new_act, &sig_act) != -1;
307
2.47k
    }
308
309
2.76k
    nsz = nbytes;
310
2.76k
    free(newbuf);
311
2.76k
    urv = uncompressbuf(fd, ms->bytes_max, i, 
312
2.76k
        (ms->flags & MAGIC_NO_COMPRESS_FORK), buf, &newbuf, &nsz);
313
2.76k
    DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv,
314
2.76k
        (char *)newbuf, nsz);
315
2.76k
    switch (urv) {
316
2.52k
    case OKDATA:
317
2.76k
    case ERRDATA:
318
2.76k
      ms->flags &= ~MAGIC_COMPRESS;
319
2.76k
      if (urv == ERRDATA)
320
242
        prv = format_decompression_error(ms, i, newbuf);
321
2.52k
      else
322
2.52k
        prv = file_buffer(ms, -1, NULL, name, newbuf,
323
2.52k
            nsz);
324
2.76k
      if (prv == -1)
325
0
        goto error;
326
2.76k
      rv = 1;
327
2.76k
      if ((ms->flags & MAGIC_COMPRESS_TRANSP) != 0)
328
0
        goto out;
329
2.76k
      if (mime != MAGIC_MIME && mime != 0)
330
0
        goto out;
331
2.76k
      if ((file_printf(ms,
332
2.76k
          mime ? " compressed-encoding=" : " (")) == -1)
333
0
        goto error;
334
2.76k
      if ((pb = file_push_buffer(ms)) == NULL)
335
16
        goto error;
336
      /*
337
       * XXX: If file_buffer fails here, we overwrite
338
       * the compressed text. FIXME.
339
       */
340
2.74k
      if (file_buffer(ms, -1, NULL, NULL, buf, nbytes) == -1)
341
0
      {
342
0
        if (file_pop_buffer(ms, pb) != NULL)
343
0
          abort();
344
0
        goto error;
345
0
      }
346
2.74k
      if ((rbuf = file_pop_buffer(ms, pb)) != NULL) {
347
2.74k
        if (file_printf(ms, "%s", rbuf) == -1) {
348
1
          free(rbuf);
349
1
          goto error;
350
1
        }
351
2.74k
        free(rbuf);
352
2.74k
      }
353
2.74k
      if (!mime && file_printf(ms, ")") == -1)
354
0
        goto error;
355
      /*FALLTHROUGH*/
356
2.74k
    case NODATA:
357
2.74k
      break;
358
0
    default:
359
0
      abort();
360
      /*NOTREACHED*/
361
17
    error:
362
17
      rv = -1;
363
17
      break;
364
2.76k
    }
365
2.76k
  }
366
7.48k
out:
367
7.48k
  DPRINTF("rv = %d\n", rv);
368
369
7.48k
  if (sa_saved && sig_act.sa_handler != SIG_IGN)
370
2.47k
    (void)sigaction(SIGPIPE, &sig_act, NULL);
371
372
7.48k
  free(newbuf);
373
7.48k
  ms->flags |= MAGIC_COMPRESS;
374
7.48k
  DPRINTF("Zmagic returns %d\n", rv);
375
7.48k
  return rv;
376
7.48k
}
377
#endif
378
/*
379
 * `safe' write for sockets and pipes.
380
 */
381
file_private ssize_t
382
swrite(int fd, const void *buf, size_t n)
383
0
{
384
0
  ssize_t rv;
385
0
  size_t rn = n;
386
387
0
  do
388
0
    switch (rv = write(fd, buf, n)) {
389
0
    case -1:
390
0
      if (errno == EINTR)
391
0
        continue;
392
0
      return -1;
393
0
    default:
394
0
      n -= rv;
395
0
      buf = CAST(const char *, buf) + rv;
396
0
      break;
397
0
    }
398
0
  while (n > 0);
399
0
  return rn;
400
0
}
401
402
403
/*
404
 * `safe' read for sockets and pipes.
405
 */
406
file_protected ssize_t
407
sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__)))
408
5.36k
{
409
5.36k
  ssize_t rv;
410
5.36k
#if defined(FIONREAD) && !defined(__MINGW32__)
411
5.36k
  int t = 0;
412
5.36k
#endif
413
5.36k
  size_t rn = n;
414
415
5.36k
  if (fd == STDIN_FILENO)
416
0
    goto nocheck;
417
418
5.36k
#if defined(FIONREAD) && !defined(__MINGW32__)
419
5.36k
  if (canbepipe && (ioctl(fd, FIONREAD, &t) == -1 || t == 0)) {
420
0
#ifdef FD_ZERO
421
0
    ssize_t cnt;
422
0
    for (cnt = 0;; cnt++) {
423
0
      fd_set check;
424
0
      struct timeval tout = {0, 100 * 1000};
425
0
      int selrv;
426
427
0
      FD_ZERO(&check);
428
0
      FD_SET(fd, &check);
429
430
      /*
431
       * Avoid soft deadlock: do not read if there
432
       * is nothing to read from sockets and pipes.
433
       */
434
0
      selrv = select(fd + 1, &check, NULL, NULL, &tout);
435
0
      if (selrv == -1) {
436
0
        if (errno == EINTR || errno == EAGAIN)
437
0
          continue;
438
0
      } else if (selrv == 0 && cnt >= 5) {
439
0
        return 0;
440
0
      } else
441
0
        break;
442
0
    }
443
0
#endif
444
0
    (void)ioctl(fd, FIONREAD, &t);
445
0
  }
446
447
5.36k
  if (t > 0 && CAST(size_t, t) < n) {
448
0
    n = t;
449
0
    rn = n;
450
0
  }
451
5.36k
#endif
452
453
5.36k
nocheck:
454
5.36k
  do
455
106k
    switch ((rv = read(fd, buf, n))) {
456
43
    case -1:
457
43
      if (errno == EINTR)
458
43
        continue;
459
0
      return -1;
460
5.30k
    case 0:
461
5.30k
      return rn - n;
462
100k
    default:
463
100k
      n -= rv;
464
100k
      buf = CAST(char *, CCAST(void *, buf)) + rv;
465
100k
      break;
466
106k
    }
467
100k
  while (n > 0);
468
60
  return rn;
469
5.36k
}
470
471
file_protected int
472
file_pipe2file(struct magic_set *ms, int fd, const void *startbuf,
473
    size_t nbytes)
474
0
{
475
0
  char buf[4096];
476
0
  ssize_t r;
477
0
  int tfd;
478
479
#ifdef WIN32
480
  const char *t;
481
  buf[0] = '\0';
482
  if ((t = getenv("TEMP")) != NULL)
483
    (void)strlcpy(buf, t, sizeof(buf));
484
  else if ((t = getenv("TMP")) != NULL)
485
    (void)strlcpy(buf, t, sizeof(buf));
486
  else if ((t = getenv("TMPDIR")) != NULL)
487
    (void)strlcpy(buf, t, sizeof(buf));
488
  if (buf[0] != '\0')
489
    (void)strlcat(buf, "/", sizeof(buf));
490
  (void)strlcat(buf, "file.XXXXXX", sizeof(buf));
491
#else
492
0
  (void)strlcpy(buf, "/tmp/file.XXXXXX", sizeof(buf));
493
0
#endif
494
#ifndef HAVE_MKSTEMP
495
  {
496
    char *ptr = mktemp(buf);
497
    tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600);
498
    r = errno;
499
    (void)unlink(ptr);
500
    errno = r;
501
  }
502
#else
503
0
  {
504
0
    int te;
505
0
    mode_t ou = umask(0);
506
0
    tfd = mkstemp(buf);
507
0
    (void)umask(ou);
508
0
    te = errno;
509
0
    (void)unlink(buf);
510
0
    errno = te;
511
0
  }
512
0
#endif
513
0
  if (tfd == -1) {
514
0
    file_error(ms, errno,
515
0
        "cannot create temporary file for pipe copy");
516
0
    return -1;
517
0
  }
518
519
0
  if (swrite(tfd, startbuf, nbytes) != CAST(ssize_t, nbytes))
520
0
    r = 1;
521
0
  else {
522
0
    while ((r = sread(fd, buf, sizeof(buf), 1)) > 0)
523
0
      if (swrite(tfd, buf, CAST(size_t, r)) != r)
524
0
        break;
525
0
  }
526
527
0
  switch (r) {
528
0
  case -1:
529
0
    file_error(ms, errno, "error copying from pipe to temp file");
530
0
    return -1;
531
0
  case 0:
532
0
    break;
533
0
  default:
534
0
    file_error(ms, errno, "error while writing to temp file");
535
0
    return -1;
536
0
  }
537
538
  /*
539
   * We duplicate the file descriptor, because fclose on a
540
   * tmpfile will delete the file, but any open descriptors
541
   * can still access the phantom inode.
542
   */
543
0
  if ((fd = dup2(tfd, fd)) == -1) {
544
0
    file_error(ms, errno, "could not dup descriptor for temp file");
545
0
    return -1;
546
0
  }
547
0
  (void)close(tfd);
548
0
  if (lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1)) {
549
0
    file_badseek(ms);
550
0
    return -1;
551
0
  }
552
0
  return fd;
553
0
}
554
#if HAVE_FORK
555
#ifdef BUILTIN_DECOMPRESS
556
557
0
#define FHCRC   (1 << 1)
558
0
#define FEXTRA    (1 << 2)
559
0
#define FNAME   (1 << 3)
560
0
#define FCOMMENT  (1 << 4)
561
562
563
file_private int
564
uncompressgzipped(const unsigned char *old, unsigned char **newch,
565
    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
566
0
{
567
0
  unsigned char flg;
568
0
  size_t data_start = 10;
569
570
0
  if (*n < 4) {
571
0
    goto err; 
572
0
  }
573
574
0
  flg = old[3];
575
576
0
  if (flg & FEXTRA) {
577
0
    if (data_start + 1 >= *n)
578
0
      goto err;
579
0
    data_start += 2 + old[data_start] + old[data_start + 1] * 256;
580
0
  }
581
0
  if (flg & FNAME) {
582
0
    while(data_start < *n && old[data_start])
583
0
      data_start++;
584
0
    data_start++;
585
0
  }
586
0
  if (flg & FCOMMENT) {
587
0
    while(data_start < *n && old[data_start])
588
0
      data_start++;
589
0
    data_start++;
590
0
  }
591
0
  if (flg & FHCRC)
592
0
    data_start += 2;
593
594
0
  if (data_start >= *n)
595
0
    goto err;
596
597
0
  *n -= data_start;
598
0
  old += data_start;
599
0
  return uncompresszlib(old, newch, bytes_max, n, 0);
600
0
err:
601
0
  return makeerror(newch, n, "File too short");
602
0
}
603
604
file_private int
605
uncompresszlib(const unsigned char *old, unsigned char **newch,
606
    size_t bytes_max, size_t *n, int zlib)
607
0
{
608
0
  int rc;
609
0
  z_stream z;
610
611
0
  DPRINTF("builtin zlib decompression\n");
612
0
  z.next_in = CCAST(Bytef *, old);
613
0
  z.avail_in = CAST(uint32_t, *n);
614
0
  z.next_out = *newch;
615
0
  z.avail_out = CAST(unsigned int, bytes_max);
616
0
  z.zalloc = Z_NULL;
617
0
  z.zfree = Z_NULL;
618
0
  z.opaque = Z_NULL;
619
620
  /* LINTED bug in header macro */
621
0
  rc = zlib ? inflateInit(&z) : inflateInit2(&z, -15);
622
0
  if (rc != Z_OK)
623
0
    goto err;
624
625
0
  rc = inflate(&z, Z_SYNC_FLUSH);
626
0
  if (rc != Z_OK && rc != Z_STREAM_END) {
627
0
    inflateEnd(&z);
628
0
    goto err;
629
0
  }
630
631
0
  *n = CAST(size_t, z.total_out);
632
0
  rc = inflateEnd(&z);
633
0
  if (rc != Z_OK)
634
0
    goto err;
635
636
  /* let's keep the nul-terminate tradition */
637
0
  (*newch)[*n] = '\0';
638
639
0
  return OKDATA;
640
0
err:
641
0
  return makeerror(newch, n, "%s", z.msg ? z.msg : zError(rc));
642
0
}
643
#endif
644
645
#ifdef BUILTIN_BZLIB
646
file_private int
647
uncompressbzlib(const unsigned char *old, unsigned char **newch,
648
    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
649
0
{
650
0
  int rc;
651
0
  bz_stream bz;
652
653
0
  DPRINTF("builtin bzlib decompression\n");
654
0
  memset(&bz, 0, sizeof(bz));
655
0
  rc = BZ2_bzDecompressInit(&bz, 0, 0);
656
0
  if (rc != BZ_OK)
657
0
    goto err;
658
659
0
  bz.next_in = CCAST(char *, RCAST(const char *, old));
660
0
  bz.avail_in = CAST(uint32_t, *n);
661
0
  bz.next_out = RCAST(char *, *newch);
662
0
  bz.avail_out = CAST(unsigned int, bytes_max);
663
664
0
  rc = BZ2_bzDecompress(&bz);
665
0
  if (rc != BZ_OK && rc != BZ_STREAM_END) {
666
0
    BZ2_bzDecompressEnd(&bz);
667
0
    goto err;
668
0
  }
669
670
  /* Assume byte_max is within 32bit */
671
  /* assert(bz.total_out_hi32 == 0); */
672
0
  *n = CAST(size_t, bz.total_out_lo32);
673
0
  rc = BZ2_bzDecompressEnd(&bz);
674
0
  if (rc != BZ_OK)
675
0
    goto err;
676
677
  /* let's keep the nul-terminate tradition */
678
0
  (*newch)[*n] = '\0';
679
680
0
  return OKDATA;
681
0
err:
682
0
  return makeerror(newch, n, "bunzip error %d", rc);
683
0
}
684
#endif
685
686
#ifdef BUILTIN_XZLIB
687
file_private int
688
uncompressxzlib(const unsigned char *old, unsigned char **newch,
689
    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
690
0
{
691
0
  int rc;
692
0
  lzma_stream xz;
693
694
0
  DPRINTF("builtin xzlib decompression\n");
695
0
  memset(&xz, 0, sizeof(xz));
696
0
  rc = lzma_auto_decoder(&xz, UINT64_MAX, 0);
697
0
  if (rc != LZMA_OK)
698
0
    goto err;
699
700
0
  xz.next_in = CCAST(const uint8_t *, old);
701
0
  xz.avail_in = CAST(uint32_t, *n);
702
0
  xz.next_out = RCAST(uint8_t *, *newch);
703
0
  xz.avail_out = CAST(unsigned int, bytes_max);
704
705
0
  rc = lzma_code(&xz, LZMA_RUN);
706
0
  if (rc != LZMA_OK && rc != LZMA_STREAM_END) {
707
0
    lzma_end(&xz);
708
0
    goto err;
709
0
  }
710
711
0
  *n = CAST(size_t, xz.total_out);
712
713
0
  lzma_end(&xz);
714
715
  /* let's keep the nul-terminate tradition */
716
0
  (*newch)[*n] = '\0';
717
718
0
  return OKDATA;
719
0
err:
720
0
  return makeerror(newch, n, "unxz error %d", rc);
721
0
}
722
#endif
723
724
#ifdef BUILTIN_ZSTDLIB
725
file_private int
726
uncompresszstd(const unsigned char *old, unsigned char **newch,
727
    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
728
0
{
729
0
  size_t rc;
730
0
  ZSTD_DStream *zstd;
731
0
  ZSTD_inBuffer in;
732
0
  ZSTD_outBuffer out;
733
734
0
  DPRINTF("builtin zstd decompression\n");
735
0
  if ((zstd = ZSTD_createDStream()) == NULL) {
736
0
    return makeerror(newch, n, "No ZSTD decompression stream, %s",
737
0
        strerror(errno));
738
0
  }
739
740
0
  rc = ZSTD_DCtx_reset(zstd, ZSTD_reset_session_only);
741
0
  if (ZSTD_isError(rc))
742
0
    goto err;
743
744
0
  in.src = CCAST(const void *, old);
745
0
  in.size = *n;
746
0
  in.pos = 0;
747
0
  out.dst = RCAST(void *, *newch);
748
0
  out.size = bytes_max;
749
0
  out.pos = 0;
750
751
0
  rc = ZSTD_decompressStream(zstd, &out, &in);
752
0
  if (ZSTD_isError(rc))
753
0
    goto err;
754
755
0
  *n = out.pos;
756
757
0
  ZSTD_freeDStream(zstd);
758
759
  /* let's keep the nul-terminate tradition */
760
0
  (*newch)[*n] = '\0';
761
762
0
  return OKDATA;
763
0
err:
764
0
  ZSTD_freeDStream(zstd);
765
0
  return makeerror(newch, n, "zstd error %d", ZSTD_getErrorCode(rc));
766
0
}
767
#endif
768
769
#ifdef BUILTIN_LZLIB
770
file_private int
771
uncompresslzlib(const unsigned char *old, unsigned char **newch,
772
    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
773
{
774
  enum LZ_Errno err;
775
  size_t old_remaining = *n;
776
  size_t new_remaining = bytes_max;
777
  size_t total_read = 0;
778
  unsigned char *bufp;
779
  struct LZ_Decoder *dec;
780
781
  bufp = *newch;
782
783
  DPRINTF("builtin lzlib decompression\n");
784
  dec = LZ_decompress_open();
785
  if (!dec) {
786
    return makeerror(newch, n, "unable to allocate LZ_Decoder");
787
  }
788
  if (LZ_decompress_errno(dec) != LZ_ok)
789
    goto err;
790
791
  for (;;) {
792
    // LZ_decompress_read() stops at member boundaries, so we may
793
    // have more than one successful read after writing all data
794
    // we have.
795
    if (old_remaining > 0) {
796
      int wr = LZ_decompress_write(dec, old, old_remaining);
797
      if (wr < 0)
798
        goto err;
799
      old_remaining -= wr;
800
      old += wr;
801
    }
802
803
    int rd = LZ_decompress_read(dec, bufp, new_remaining);
804
    if (rd > 0) {
805
      new_remaining -= rd;
806
      bufp += rd;
807
      total_read += rd;
808
    }
809
810
    if (rd < 0 || LZ_decompress_errno(dec) != LZ_ok)
811
      goto err;
812
    if (new_remaining == 0)
813
      break;
814
    if (old_remaining == 0 && rd == 0)
815
      break;
816
  }
817
818
  LZ_decompress_close(dec);
819
  *n = total_read;
820
821
  /* let's keep the nul-terminate tradition */
822
  *bufp = '\0';
823
824
  return OKDATA;
825
err:
826
  err = LZ_decompress_errno(dec);
827
  LZ_decompress_close(dec);
828
  return makeerror(newch, n, "lzlib error: %s", LZ_strerror(err));
829
}
830
#endif
831
832
833
static int
834
makeerror(unsigned char **buf, size_t *len, const char *fmt, ...)
835
68
{
836
68
  char *msg;
837
68
  va_list ap;
838
68
  int rv;
839
840
68
  DPRINTF("Makeerror %s\n", fmt);
841
68
  free(*buf);
842
68
  va_start(ap, fmt);
843
68
  rv = vasprintf(&msg, fmt, ap);
844
68
  va_end(ap);
845
68
  if (rv < 0) {
846
0
    DPRINTF("Makeerror failed");
847
0
    *buf = NULL;
848
0
    *len = 0;
849
0
    return NODATA;
850
0
  }
851
68
  *buf = RCAST(unsigned char *, msg);
852
68
  *len = strlen(msg);
853
68
  return ERRDATA;
854
68
}
855
856
static void
857
closefd(int *fd, size_t i)
858
21.7k
{
859
21.7k
  if (fd[i] == -1)
860
5.48k
    return;
861
16.2k
  (void) close(fd[i]);
862
16.2k
  fd[i] = -1;
863
16.2k
}
864
865
static void
866
closep(int *fd)
867
0
{
868
0
  size_t i;
869
0
  for (i = 0; i < 2; i++)
870
0
    closefd(fd, i);
871
0
}
872
873
static void
874
movedesc(void *v, int i, int fd)
875
8.13k
{
876
8.13k
  if (fd == i)
877
0
    return; /* "no dup was necessary" */
878
8.13k
#ifdef HAVE_POSIX_SPAWNP
879
8.13k
  posix_spawn_file_actions_t *fa = RCAST(posix_spawn_file_actions_t *, v);
880
8.13k
  posix_spawn_file_actions_adddup2(fa, fd, i);
881
8.13k
  posix_spawn_file_actions_addclose(fa, fd);
882
#else
883
  if (dup2(fd, i) == -1) {
884
    DPRINTF("dup(%d, %d) failed (%s)\n", fd, i, strerror(errno));
885
    exit(EXIT_FAILURE);
886
  }
887
  close(v ? fd : fd);
888
#endif
889
8.13k
}
890
891
static void
892
closedesc(void *v, int fd)
893
8.13k
{
894
8.13k
#ifdef HAVE_POSIX_SPAWNP
895
8.13k
  posix_spawn_file_actions_t *fa = RCAST(posix_spawn_file_actions_t *, v);
896
8.13k
  posix_spawn_file_actions_addclose(fa, fd);
897
#else
898
  close(v ? fd : fd);
899
#endif
900
8.13k
}
901
902
static void
903
handledesc(void *v, int fd, int fdp[3][2])
904
2.71k
{
905
2.71k
  if (fd != -1) {
906
0
    (void) lseek(fd, CAST(off_t, 0), SEEK_SET);
907
0
    movedesc(v, STDIN_FILENO, fd);
908
2.71k
  } else {
909
2.71k
    movedesc(v, STDIN_FILENO, fdp[STDIN_FILENO][0]);
910
2.71k
    if (fdp[STDIN_FILENO][1] > 2)
911
2.71k
        closedesc(v, fdp[STDIN_FILENO][1]);
912
2.71k
  }
913
914
2.71k
  file_clear_closexec(STDIN_FILENO);
915
916
///FIXME: if one of the fdp[i][j] is 0 or 1, this can bomb spectacularly
917
2.71k
  movedesc(v, STDOUT_FILENO, fdp[STDOUT_FILENO][1]);
918
2.71k
  if (fdp[STDOUT_FILENO][0] > 2)
919
2.71k
    closedesc(v, fdp[STDOUT_FILENO][0]);
920
921
2.71k
  file_clear_closexec(STDOUT_FILENO);
922
923
2.71k
  movedesc(v, STDERR_FILENO, fdp[STDERR_FILENO][1]);
924
2.71k
  if (fdp[STDERR_FILENO][0] > 2)
925
2.71k
    closedesc(v, fdp[STDERR_FILENO][0]);
926
927
2.71k
  file_clear_closexec(STDERR_FILENO);
928
2.71k
}
929
930
static pid_t
931
writechild(int fd, const void *old, size_t n)
932
2.71k
{
933
2.71k
  pid_t pid;
934
935
  /*
936
   * fork again, to avoid blocking because both
937
   * pipes filled
938
   */
939
2.71k
  pid = fork();
940
2.71k
  if (pid == -1) {
941
0
    DPRINTF("Fork failed (%s)\n", strerror(errno));
942
0
    return -1;
943
0
  }
944
2.71k
  if (pid == 0) {
945
    /* child */
946
0
    if (swrite(fd, old, n) != CAST(ssize_t, n)) {
947
0
      DPRINTF("Write failed (%s)\n", strerror(errno));
948
0
      exit(EXIT_FAILURE);
949
0
    }
950
0
    exit(EXIT_SUCCESS);
951
0
  }
952
  /* parent */
953
2.71k
  return pid;
954
2.71k
}
955
956
static ssize_t
957
filter_error(unsigned char *ubuf, ssize_t n)
958
174
{
959
174
  char *p;
960
174
  char *buf;
961
962
174
  ubuf[n] = '\0';
963
174
  buf = RCAST(char *, ubuf);
964
174
  while (isspace(CAST(unsigned char, *buf)))
965
52
    buf++;
966
174
  DPRINTF("Filter error[[[%s]]]\n", buf);
967
174
  if ((p = strchr(CAST(char *, buf), '\n')) != NULL)
968
11
    *p = '\0';
969
174
  if ((p = strchr(CAST(char *, buf), ';')) != NULL)
970
0
    *p = '\0';
971
174
  if ((p = strrchr(CAST(char *, buf), ':')) != NULL) {
972
18
    ++p;
973
18
    while (isspace(CAST(unsigned char, *p)))
974
16
      p++;
975
18
    n = strlen(p);
976
18
    memmove(ubuf, p, CAST(size_t, n + 1));
977
18
  }
978
174
  DPRINTF("Filter error after[[[%s]]]\n", (char *)ubuf);
979
174
  if (islower(*ubuf))
980
14
    *ubuf = toupper(*ubuf);
981
174
  return n;
982
174
}
983
984
file_private const char *
985
methodname(size_t method)
986
242
{
987
242
  switch (method) {
988
0
#ifdef BUILTIN_DECOMPRESS
989
11
  case METH_FROZEN:
990
39
  case METH_ZLIB:
991
39
    return "zlib";
992
0
#endif
993
0
#ifdef BUILTIN_BZLIB
994
7
  case METH_BZIP:
995
7
    return "bzlib";
996
0
#endif
997
0
#ifdef BUILTIN_XZLIB
998
2
  case METH_XZ:
999
5
  case METH_LZMA:
1000
5
    return "xzlib";
1001
0
#endif
1002
0
#ifdef BUILTIN_ZSTDLIB
1003
3
  case METH_ZSTD:
1004
3
    return "zstd";
1005
0
#endif
1006
#ifdef BUILTIN_LZLIB
1007
  case METH_LZIP:
1008
    return "lzlib";
1009
#endif
1010
188
  default:
1011
188
    return compr[method].argv[0];
1012
242
  }
1013
242
}
1014
1015
file_private int (*
1016
getdecompressor(size_t method))(const unsigned char *, unsigned char **, size_t,
1017
    size_t *, int)
1018
2.76k
{
1019
2.76k
  switch (method) {
1020
0
#ifdef BUILTIN_DECOMPRESS
1021
11
  case METH_FROZEN:
1022
11
    return uncompressgzipped;
1023
28
  case METH_ZLIB:
1024
28
    return uncompresszlib;
1025
0
#endif
1026
0
#ifdef BUILTIN_BZLIB
1027
7
  case METH_BZIP:
1028
7
    return uncompressbzlib;
1029
0
#endif
1030
0
#ifdef BUILTIN_XZLIB
1031
2
  case METH_XZ:
1032
5
  case METH_LZMA:
1033
5
    return uncompressxzlib;
1034
0
#endif
1035
0
#ifdef BUILTIN_ZSTDLIB
1036
3
  case METH_ZSTD:
1037
3
    return uncompresszstd;
1038
0
#endif
1039
#ifdef BUILTIN_LZLIB
1040
  case METH_LZIP:
1041
    return uncompresslzlib;
1042
#endif
1043
2.71k
  default:
1044
2.71k
    return NULL;
1045
2.76k
  }
1046
2.76k
}
1047
1048
file_private int
1049
uncompressbuf(int fd, size_t bytes_max, size_t method, int nofork,
1050
    const unsigned char *old, unsigned char **newch, size_t* n)
1051
2.76k
{
1052
2.76k
  int fdp[3][2];
1053
2.76k
  int status, rv, w;
1054
2.76k
  pid_t pid;
1055
2.76k
  pid_t writepid = -1;
1056
2.76k
  size_t i;
1057
2.76k
  ssize_t r, re;
1058
2.76k
  char *const *args;
1059
2.76k
#ifdef HAVE_POSIX_SPAWNP
1060
2.76k
  posix_spawn_file_actions_t fa;
1061
2.76k
#endif
1062
2.76k
  int (*decompress)(const unsigned char *, unsigned char **,
1063
2.76k
      size_t, size_t *, int) = getdecompressor(method);
1064
1065
2.76k
  *newch = CAST(unsigned char *, malloc(bytes_max + 1));
1066
2.76k
  if (*newch == NULL)
1067
0
    return makeerror(newch, n, "No buffer, %s", strerror(errno));
1068
1069
2.76k
  if (decompress) {
1070
54
    if (nofork) {
1071
54
      return makeerror(newch, n,
1072
54
          "Fork is required to uncompress, but disabled");
1073
54
    }
1074
0
    return (*decompress)(old, newch, bytes_max, n, 1);
1075
54
  }
1076
1077
2.71k
  (void)fflush(stdout);
1078
2.71k
  (void)fflush(stderr);
1079
1080
10.8k
  for (i = 0; i < __arraycount(fdp); i++)
1081
8.13k
    fdp[i][0] = fdp[i][1] = -1;
1082
1083
  /*
1084
   * There are multithreaded users who run magic_file()
1085
   * from dozens of threads. If two parallel magic_file() calls
1086
   * analyze two large compressed files, both will spawn
1087
   * an uncompressing child here, which writes out uncompressed data.
1088
   * We read some portion, then close the pipe, then waitpid() the child.
1089
   * If uncompressed data is larger, child should get EPIPE and exit.
1090
   * However, with *parallel* calls OTHER child may unintentionally
1091
   * inherit pipe fds, thus keeping pipe open and making writes in
1092
   * our child block instead of failing with EPIPE!
1093
   * (For the bug to occur, two threads must mutually inherit their pipes,
1094
   * and both must have large outputs. Thus it happens not that often).
1095
   * To avoid this, be sure to create pipes with O_CLOEXEC.
1096
   */
1097
2.71k
  if ((fd == -1 && file_pipe_closexec(fdp[STDIN_FILENO]) == -1) ||
1098
2.71k
      file_pipe_closexec(fdp[STDOUT_FILENO]) == -1 ||
1099
2.71k
      file_pipe_closexec(fdp[STDERR_FILENO]) == -1) {
1100
0
    closep(fdp[STDIN_FILENO]);
1101
0
    closep(fdp[STDOUT_FILENO]);
1102
0
    return makeerror(newch, n, "Cannot create pipe, %s",
1103
0
        strerror(errno));
1104
0
  }
1105
1106
2.71k
  args = RCAST(char *const *, RCAST(intptr_t, compr[method].argv));
1107
2.71k
#ifdef HAVE_POSIX_SPAWNP
1108
2.71k
  posix_spawn_file_actions_init(&fa);
1109
1110
2.71k
  handledesc(&fa, fd, fdp);
1111
1112
2.71k
  DPRINTF("Executing %s\n", compr[method].argv[0]);
1113
2.71k
  status = posix_spawnp(&pid, compr[method].argv[0], &fa, NULL,
1114
2.71k
      args, NULL);
1115
1116
2.71k
  posix_spawn_file_actions_destroy(&fa);
1117
1118
2.71k
  if (status == -1) {
1119
0
    return makeerror(newch, n, "Cannot posix_spawn `%s', %s",
1120
0
        compr[method].argv[0], strerror(errno));
1121
0
  }
1122
#else
1123
  /* For processes with large mapped virtual sizes, vfork
1124
   * may be _much_ faster (10-100 times) than fork.
1125
   */
1126
  pid = vfork();
1127
  if (pid == -1) {
1128
    return makeerror(newch, n, "Cannot vfork, %s",
1129
        strerror(errno));
1130
  }
1131
  if (pid == 0) {
1132
    /* child */
1133
    /* Note: we are after vfork, do not modify memory
1134
     * in a way which confuses parent. In particular,
1135
     * do not modify fdp[i][j].
1136
     */
1137
    handledesc(NULL, fd, fdp);
1138
    DPRINTF("Executing %s\n", compr[method].argv[0]);
1139
1140
    (void)execvp(compr[method].argv[0], args);
1141
    dprintf(STDERR_FILENO, "exec `%s' failed, %s",
1142
        compr[method].argv[0], strerror(errno));
1143
    _exit(EXIT_FAILURE); /* _exit(), not exit(), because of vfork */
1144
  }
1145
#endif
1146
  /* parent */
1147
  /* Close write sides of child stdout/err pipes */
1148
8.13k
  for (i = 1; i < __arraycount(fdp); i++)
1149
5.42k
    closefd(fdp[i], 1);
1150
  /* Write the buffer data to child stdin, if we don't have fd */
1151
2.71k
  if (fd == -1) {
1152
2.71k
    closefd(fdp[STDIN_FILENO], 0);
1153
2.71k
    writepid = writechild(fdp[STDIN_FILENO][1], old, *n);
1154
2.71k
    if (writepid == (pid_t)-1) {
1155
0
      rv = makeerror(newch, n, "Write to child failed, %s",
1156
0
          strerror(errno));
1157
0
      DPRINTF("Write to child failed\n");
1158
0
      goto err;
1159
0
    }
1160
2.71k
    closefd(fdp[STDIN_FILENO], 1);
1161
2.71k
  }
1162
1163
2.71k
  rv = OKDATA;
1164
2.71k
  r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0);
1165
2.71k
  DPRINTF("read got %zd\n", r);
1166
2.71k
  if (r < 0) {
1167
0
    rv = ERRDATA;
1168
0
    DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0],
1169
0
            strerror(errno));
1170
0
    goto err;
1171
0
  } 
1172
2.71k
  if (CAST(size_t, r) == bytes_max) {
1173
    /*
1174
     * close fd so that the child exits with sigpipe and ignore
1175
     * errors, otherwise we risk the child blocking and never
1176
     * exiting.
1177
     */
1178
60
    DPRINTF("Closing stdout for bytes_max\n");
1179
60
    closefd(fdp[STDOUT_FILENO], 0);
1180
60
    goto ok;
1181
60
  }
1182
2.65k
  if ((re = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0) {
1183
174
    DPRINTF("Got stuff from stderr %s\n", *newch);
1184
174
    rv = ERRDATA;
1185
174
    r = filter_error(*newch, r);
1186
174
    goto ok;
1187
174
  }
1188
2.47k
  if  (re == 0)
1189
2.47k
    goto ok;
1190
0
  rv = makeerror(newch, n, "Read stderr failed, %s",
1191
0
      strerror(errno));
1192
0
  goto err;
1193
2.71k
ok:
1194
2.71k
  *n = r;
1195
  /* NUL terminate, as every buffer is handled here. */
1196
2.71k
  (*newch)[*n] = '\0';
1197
2.71k
err:
1198
2.71k
  closefd(fdp[STDIN_FILENO], 1);
1199
2.71k
  closefd(fdp[STDOUT_FILENO], 0);
1200
2.71k
  closefd(fdp[STDERR_FILENO], 0);
1201
1202
2.71k
  w = waitpid(pid, &status, 0);
1203
5.42k
wait_err:
1204
5.42k
  if (w == -1) {
1205
14
    rv = makeerror(newch, n, "Wait failed, %s", strerror(errno));
1206
14
    DPRINTF("Child wait return %#x\n", status);
1207
5.40k
  } else if (!WIFEXITED(status)) {
1208
0
    DPRINTF("Child not exited (%#x)\n", status);
1209
5.40k
  } else if (WEXITSTATUS(status) != 0) {
1210
2.94k
    DPRINTF("Child exited (%#x)\n", WEXITSTATUS(status));
1211
2.94k
  }
1212
5.42k
  if (writepid > 0) {
1213
    /* _After_ we know decompressor has exited, our input writer
1214
     * definitely will exit now (at worst, writing fails in it,
1215
     * since output fd is closed now on the reading size).
1216
     */
1217
2.71k
    w = waitpid(writepid, &status, 0);
1218
2.71k
    writepid = -1;
1219
2.71k
    goto wait_err;
1220
2.71k
  }
1221
1222
2.71k
  closefd(fdp[STDIN_FILENO], 0); //why? it is already closed here!
1223
2.71k
  DPRINTF("Returning %p n=%" SIZE_T_FORMAT "u rv=%d\n", *newch, *n, rv);
1224
1225
2.71k
  return rv;
1226
5.42k
}
1227
#endif