Coverage Report

Created: 2025-01-09 06:24

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