Coverage Report

Created: 2026-10-01 06:41

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