1b6cee71dSXin LI /* 2b6cee71dSXin LI * Copyright (c) Ian F. Darwin 1986-1995. 3b6cee71dSXin LI * Software written by Ian F. Darwin and others; 4b6cee71dSXin LI * maintained 1995-present by Christos Zoulas and others. 5b6cee71dSXin LI * 6b6cee71dSXin LI * Redistribution and use in source and binary forms, with or without 7b6cee71dSXin LI * modification, are permitted provided that the following conditions 8b6cee71dSXin LI * are met: 9b6cee71dSXin LI * 1. Redistributions of source code must retain the above copyright 10b6cee71dSXin LI * notice immediately at the beginning of the file, without modification, 11b6cee71dSXin LI * this list of conditions, and the following disclaimer. 12b6cee71dSXin LI * 2. Redistributions in binary form must reproduce the above copyright 13b6cee71dSXin LI * notice, this list of conditions and the following disclaimer in the 14b6cee71dSXin LI * documentation and/or other materials provided with the distribution. 15b6cee71dSXin LI * 16b6cee71dSXin LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17b6cee71dSXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18b6cee71dSXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19b6cee71dSXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20b6cee71dSXin LI * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21b6cee71dSXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22b6cee71dSXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23b6cee71dSXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24b6cee71dSXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25b6cee71dSXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26b6cee71dSXin LI * SUCH DAMAGE. 27b6cee71dSXin LI */ 28b6cee71dSXin LI /* 29b6cee71dSXin LI * compress routines: 30b6cee71dSXin LI * zmagic() - returns 0 if not recognized, uncompresses and prints 31b6cee71dSXin LI * information if recognized 32b6cee71dSXin LI * uncompress(method, old, n, newch) - uncompress old into new, 33b6cee71dSXin LI * using method, return sizeof new 34b6cee71dSXin LI */ 35b6cee71dSXin LI #include "file.h" 36b6cee71dSXin LI 37b6cee71dSXin LI #ifndef lint 38*898496eeSXin LI FILE_RCSID("@(#)$File: compress.c,v 1.157 2023/05/21 15:59:58 christos Exp $") 39b6cee71dSXin LI #endif 40b6cee71dSXin LI 41b6cee71dSXin LI #include "magic.h" 42b6cee71dSXin LI #include <stdlib.h> 43b6cee71dSXin LI #ifdef HAVE_UNISTD_H 44b6cee71dSXin LI #include <unistd.h> 45b6cee71dSXin LI #endif 46a4d6d3b8SXin LI #ifdef HAVE_SPAWN_H 47a4d6d3b8SXin LI #include <spawn.h> 48a4d6d3b8SXin LI #endif 49b6cee71dSXin LI #include <string.h> 50b6cee71dSXin LI #include <errno.h> 513e41d09dSXin LI #include <ctype.h> 523e41d09dSXin LI #include <stdarg.h> 534460e5b0SXin LI #include <signal.h> 545f0216bdSXin LI #ifndef HAVE_SIG_T 555f0216bdSXin LI typedef void (*sig_t)(int); 565f0216bdSXin LI #endif /* HAVE_SIG_T */ 57a4d6d3b8SXin LI #ifdef HAVE_SYS_IOCTL_H 58b6cee71dSXin LI #include <sys/ioctl.h> 59b6cee71dSXin LI #endif 60b6cee71dSXin LI #ifdef HAVE_SYS_WAIT_H 61b6cee71dSXin LI #include <sys/wait.h> 62b6cee71dSXin LI #endif 63b6cee71dSXin LI #if defined(HAVE_SYS_TIME_H) 64b6cee71dSXin LI #include <sys/time.h> 65b6cee71dSXin LI #endif 6648c779cdSXin LI 6740427ccaSGordon Tetlow #if defined(HAVE_ZLIB_H) && defined(ZLIBSUPPORT) 68b6cee71dSXin LI #define BUILTIN_DECOMPRESS 69b6cee71dSXin LI #include <zlib.h> 703e41d09dSXin LI #endif 7148c779cdSXin LI 722726a701SXin LI #if defined(HAVE_BZLIB_H) && defined(BZLIBSUPPORT) 7348c779cdSXin LI #define BUILTIN_BZLIB 7448c779cdSXin LI #include <bzlib.h> 7548c779cdSXin LI #endif 7648c779cdSXin LI 7743a5ec4eSXin LI #if defined(HAVE_LZMA_H) && defined(XZLIBSUPPORT) 78d38c30c0SXin LI #define BUILTIN_XZLIB 79d38c30c0SXin LI #include <lzma.h> 80d38c30c0SXin LI #endif 81d38c30c0SXin LI 82*898496eeSXin LI #if defined(HAVE_ZSTD_H) && defined(ZSTDLIBSUPPORT) 83*898496eeSXin LI #define BUILTIN_ZSTDLIB 84*898496eeSXin LI #include <zstd.h> 85*898496eeSXin LI #include <zstd_errors.h> 86*898496eeSXin LI #endif 87*898496eeSXin LI 88*898496eeSXin LI #if defined(HAVE_LZLIB_H) && defined(LZLIBSUPPORT) 89*898496eeSXin LI #define BUILTIN_LZLIB 90*898496eeSXin LI #include <lzlib.h> 91*898496eeSXin LI #endif 92*898496eeSXin LI 933e41d09dSXin LI #ifdef DEBUG 943e41d09dSXin LI int tty = -1; 953e41d09dSXin LI #define DPRINTF(...) do { \ 963e41d09dSXin LI if (tty == -1) \ 973e41d09dSXin LI tty = open("/dev/tty", O_RDWR); \ 983e41d09dSXin LI if (tty == -1) \ 993e41d09dSXin LI abort(); \ 1003e41d09dSXin LI dprintf(tty, __VA_ARGS__); \ 1013e41d09dSXin LI } while (/*CONSTCOND*/0) 1023e41d09dSXin LI #else 1033e41d09dSXin LI #define DPRINTF(...) 104b6cee71dSXin LI #endif 105b6cee71dSXin LI 1063e41d09dSXin LI #ifdef ZLIBSUPPORT 1073e41d09dSXin LI /* 1083e41d09dSXin LI * The following python code is not really used because ZLIBSUPPORT is only 1093e41d09dSXin LI * defined if we have a built-in zlib, and the built-in zlib handles that. 11040427ccaSGordon Tetlow * That is not true for android where we have zlib.h and not -lz. 1113e41d09dSXin LI */ 1123e41d09dSXin LI static const char zlibcode[] = 1133e41d09dSXin LI "import sys, zlib; sys.stdout.write(zlib.decompress(sys.stdin.read()))"; 1143e41d09dSXin LI 1153e41d09dSXin LI static const char *zlib_args[] = { "python", "-c", zlibcode, NULL }; 1163e41d09dSXin LI 1173e41d09dSXin LI static int 1183e41d09dSXin LI zlibcmp(const unsigned char *buf) 1193e41d09dSXin LI { 1203e41d09dSXin LI unsigned short x = 1; 12140427ccaSGordon Tetlow unsigned char *s = CAST(unsigned char *, CAST(void *, &x)); 1223e41d09dSXin LI 1233e41d09dSXin LI if ((buf[0] & 0xf) != 8 || (buf[0] & 0x80) != 0) 1243e41d09dSXin LI return 0; 1253e41d09dSXin LI if (s[0] != 1) /* endianness test */ 1263e41d09dSXin LI x = buf[0] | (buf[1] << 8); 1273e41d09dSXin LI else 1283e41d09dSXin LI x = buf[1] | (buf[0] << 8); 1293e41d09dSXin LI if (x % 31) 1303e41d09dSXin LI return 0; 1313e41d09dSXin LI return 1; 1323e41d09dSXin LI } 1333e41d09dSXin LI #endif 1343e41d09dSXin LI 135d38c30c0SXin LI static int 136d38c30c0SXin LI lzmacmp(const unsigned char *buf) 137d38c30c0SXin LI { 138d38c30c0SXin LI if (buf[0] != 0x5d || buf[1] || buf[2]) 139d38c30c0SXin LI return 0; 140d38c30c0SXin LI if (buf[12] && buf[12] != 0xff) 141d38c30c0SXin LI return 0; 142d38c30c0SXin LI return 1; 143d38c30c0SXin LI } 144d38c30c0SXin LI 1453e41d09dSXin LI #define gzip_flags "-cd" 1463e41d09dSXin LI #define lzip_flags gzip_flags 1473e41d09dSXin LI 1483e41d09dSXin LI static const char *gzip_args[] = { 1493e41d09dSXin LI "gzip", gzip_flags, NULL 1503e41d09dSXin LI }; 1513e41d09dSXin LI static const char *uncompress_args[] = { 1523e41d09dSXin LI "uncompress", "-c", NULL 1533e41d09dSXin LI }; 1543e41d09dSXin LI static const char *bzip2_args[] = { 1553e41d09dSXin LI "bzip2", "-cd", NULL 1563e41d09dSXin LI }; 1573e41d09dSXin LI static const char *lzip_args[] = { 1583e41d09dSXin LI "lzip", lzip_flags, NULL 1593e41d09dSXin LI }; 1603e41d09dSXin LI static const char *xz_args[] = { 1613e41d09dSXin LI "xz", "-cd", NULL 1623e41d09dSXin LI }; 1633e41d09dSXin LI static const char *lrzip_args[] = { 164*898496eeSXin LI "lrzip", "-qdf", "-", NULL 1653e41d09dSXin LI }; 1663e41d09dSXin LI static const char *lz4_args[] = { 1673e41d09dSXin LI "lz4", "-cd", NULL 168b6cee71dSXin LI }; 169a5d223e6SXin LI static const char *zstd_args[] = { 170a5d223e6SXin LI "zstd", "-cd", NULL 171a5d223e6SXin LI }; 172b6cee71dSXin LI 17348c779cdSXin LI #define do_zlib NULL 17448c779cdSXin LI #define do_bzlib NULL 17548c779cdSXin LI 176*898496eeSXin LI file_private const struct { 1772726a701SXin LI union { 1782726a701SXin LI const char *magic; 1792726a701SXin LI int (*func)(const unsigned char *); 1802726a701SXin LI } u; 181d38c30c0SXin LI int maglen; 1823e41d09dSXin LI const char **argv; 18348c779cdSXin LI void *unused; 1843e41d09dSXin LI } compr[] = { 185d38c30c0SXin LI #define METH_FROZEN 2 186d38c30c0SXin LI #define METH_BZIP 7 187d38c30c0SXin LI #define METH_XZ 9 188*898496eeSXin LI #define METH_LZIP 8 189*898496eeSXin LI #define METH_ZSTD 12 190d38c30c0SXin LI #define METH_LZMA 13 191d38c30c0SXin LI #define METH_ZLIB 14 1922726a701SXin LI { { .magic = "\037\235" }, 2, gzip_args, NULL }, /* 0, compressed */ 1933e41d09dSXin LI /* Uncompress can get stuck; so use gzip first if we have it 1943e41d09dSXin LI * Idea from Damien Clark, thanks! */ 1952726a701SXin LI { { .magic = "\037\235" }, 2, uncompress_args, NULL },/* 1, compressed */ 1962726a701SXin LI { { .magic = "\037\213" }, 2, gzip_args, do_zlib },/* 2, gzipped */ 1972726a701SXin LI { { .magic = "\037\236" }, 2, gzip_args, NULL }, /* 3, frozen */ 1982726a701SXin LI { { .magic = "\037\240" }, 2, gzip_args, NULL }, /* 4, SCO LZH */ 1993e41d09dSXin LI /* the standard pack utilities do not accept standard input */ 2002726a701SXin LI { { .magic = "\037\036" }, 2, gzip_args, NULL }, /* 5, packed */ 2012726a701SXin LI { { .magic = "PK\3\4" }, 4, gzip_args, NULL }, /* 6, pkziped */ 2023e41d09dSXin LI /* ...only first file examined */ 2032726a701SXin LI { { .magic = "BZh" }, 3, bzip2_args, do_bzlib },/* 7, bzip2-ed */ 2042726a701SXin LI { { .magic = "LZIP" }, 4, lzip_args, NULL }, /* 8, lzip-ed */ 2052726a701SXin LI { { .magic = "\3757zXZ\0" },6, xz_args, NULL }, /* 9, XZ Util */ 2062726a701SXin LI { { .magic = "LRZI" }, 4, lrzip_args, NULL }, /* 10, LRZIP */ 2072726a701SXin LI { { .magic = "\004\"M\030" },4, lz4_args, NULL }, /* 11, LZ4 */ 2082726a701SXin LI { { .magic = "\x28\xB5\x2F\xFD" }, 4, zstd_args, NULL },/* 12, zstd */ 2092726a701SXin LI { { .func = lzmacmp }, -13, xz_args, NULL }, /* 13, lzma */ 2103e41d09dSXin LI #ifdef ZLIBSUPPORT 2112726a701SXin LI { { .func = zlibcmp }, -2, zlib_args, NULL }, /* 14, zlib */ 2123e41d09dSXin LI #endif 2133e41d09dSXin LI }; 2143e41d09dSXin LI 2153e41d09dSXin LI #define OKDATA 0 2163e41d09dSXin LI #define NODATA 1 2173e41d09dSXin LI #define ERRDATA 2 218b6cee71dSXin LI 219*898496eeSXin LI file_private ssize_t swrite(int, const void *, size_t); 220b6cee71dSXin LI #if HAVE_FORK 221*898496eeSXin LI file_private size_t ncompr = __arraycount(compr); 222*898496eeSXin LI file_private int uncompressbuf(int, size_t, size_t, int, const unsigned char *, 2233e41d09dSXin LI unsigned char **, size_t *); 224b6cee71dSXin LI #ifdef BUILTIN_DECOMPRESS 225*898496eeSXin LI file_private int uncompresszlib(const unsigned char *, unsigned char **, size_t, 2263e41d09dSXin LI size_t *, int); 227*898496eeSXin LI file_private int uncompressgzipped(const unsigned char *, unsigned char **, size_t, 228*898496eeSXin LI size_t *, int); 229b6cee71dSXin LI #endif 23048c779cdSXin LI #ifdef BUILTIN_BZLIB 231*898496eeSXin LI file_private int uncompressbzlib(const unsigned char *, unsigned char **, size_t, 232*898496eeSXin LI size_t *, int); 233d38c30c0SXin LI #endif 234d38c30c0SXin LI #ifdef BUILTIN_XZLIB 235*898496eeSXin LI file_private int uncompressxzlib(const unsigned char *, unsigned char **, size_t, 236*898496eeSXin LI size_t *, int); 237*898496eeSXin LI #endif 238*898496eeSXin LI #ifdef BUILTIN_ZSTDLIB 239*898496eeSXin LI file_private int uncompresszstd(const unsigned char *, unsigned char **, size_t, 240*898496eeSXin LI size_t *, int); 241*898496eeSXin LI #endif 242*898496eeSXin LI #ifdef BUILTIN_LZLIB 243*898496eeSXin LI file_private int uncompresslzlib(const unsigned char *, unsigned char **, size_t, 244*898496eeSXin LI size_t *, int); 24548c779cdSXin LI #endif 24648c779cdSXin LI 2473e41d09dSXin LI static int makeerror(unsigned char **, size_t *, const char *, ...) 2483e41d09dSXin LI __attribute__((__format__(__printf__, 3, 4))); 249*898496eeSXin LI file_private const char *methodname(size_t); 250b6cee71dSXin LI 251*898496eeSXin LI file_private int 2522dc4dbb9SEitan Adler format_decompression_error(struct magic_set *ms, size_t i, unsigned char *buf) 2532dc4dbb9SEitan Adler { 2542dc4dbb9SEitan Adler unsigned char *p; 2552dc4dbb9SEitan Adler int mime = ms->flags & MAGIC_MIME; 2562dc4dbb9SEitan Adler 2572dc4dbb9SEitan Adler if (!mime) 2582dc4dbb9SEitan Adler return file_printf(ms, "ERROR:[%s: %s]", methodname(i), buf); 2592dc4dbb9SEitan Adler 2602dc4dbb9SEitan Adler for (p = buf; *p; p++) 2612dc4dbb9SEitan Adler if (!isalnum(*p)) 2622dc4dbb9SEitan Adler *p = '-'; 2632dc4dbb9SEitan Adler 2642dc4dbb9SEitan Adler return file_printf(ms, "application/x-decompression-error-%s-%s", 2652dc4dbb9SEitan Adler methodname(i), buf); 2662dc4dbb9SEitan Adler } 2672dc4dbb9SEitan Adler 268*898496eeSXin LI file_protected int 26958a0f0d0SEitan Adler file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name) 270b6cee71dSXin LI { 271b6cee71dSXin LI unsigned char *newbuf = NULL; 272b6cee71dSXin LI size_t i, nsz; 2733e41d09dSXin LI char *rbuf; 2743e41d09dSXin LI file_pushbuf_t *pb; 27520f8619dSXin LI int urv, prv, rv = 0; 276b6cee71dSXin LI int mime = ms->flags & MAGIC_MIME; 27758a0f0d0SEitan Adler int fd = b->fd; 27848c779cdSXin LI const unsigned char *buf = CAST(const unsigned char *, b->fbuf); 27958a0f0d0SEitan Adler size_t nbytes = b->flen; 28048c779cdSXin LI int sa_saved = 0; 28148c779cdSXin LI struct sigaction sig_act; 282b6cee71dSXin LI 283b6cee71dSXin LI if ((ms->flags & MAGIC_COMPRESS) == 0) 284b6cee71dSXin LI return 0; 285b6cee71dSXin LI 286b6cee71dSXin LI for (i = 0; i < ncompr; i++) { 2873e41d09dSXin LI int zm; 288d38c30c0SXin LI if (nbytes < CAST(size_t, abs(compr[i].maglen))) 289b6cee71dSXin LI continue; 290d38c30c0SXin LI if (compr[i].maglen < 0) { 2912726a701SXin LI zm = (*compr[i].u.func)(buf); 292d38c30c0SXin LI } else { 2932726a701SXin LI zm = memcmp(buf, compr[i].u.magic, 294d38c30c0SXin LI CAST(size_t, compr[i].maglen)) == 0; 295d38c30c0SXin LI } 296b6cee71dSXin LI 2973e41d09dSXin LI if (!zm) 2983e41d09dSXin LI continue; 29948c779cdSXin LI 30048c779cdSXin LI /* Prevent SIGPIPE death if child dies unexpectedly */ 30148c779cdSXin LI if (!sa_saved) { 30248c779cdSXin LI //We can use sig_act for both new and old, but 30348c779cdSXin LI struct sigaction new_act; 30448c779cdSXin LI memset(&new_act, 0, sizeof(new_act)); 30548c779cdSXin LI new_act.sa_handler = SIG_IGN; 30648c779cdSXin LI sa_saved = sigaction(SIGPIPE, &new_act, &sig_act) != -1; 30748c779cdSXin LI } 30848c779cdSXin LI 3093e41d09dSXin LI nsz = nbytes; 310*898496eeSXin LI free(newbuf); 311*898496eeSXin LI urv = uncompressbuf(fd, ms->bytes_max, i, 312*898496eeSXin LI (ms->flags & MAGIC_NO_COMPRESS_FORK), buf, &newbuf, &nsz); 31348c779cdSXin LI DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv, 31448c779cdSXin LI (char *)newbuf, nsz); 31520f8619dSXin LI switch (urv) { 3163e41d09dSXin LI case OKDATA: 3173e41d09dSXin LI case ERRDATA: 3183e41d09dSXin LI ms->flags &= ~MAGIC_COMPRESS; 31920f8619dSXin LI if (urv == ERRDATA) 3202dc4dbb9SEitan Adler prv = format_decompression_error(ms, i, newbuf); 3213e41d09dSXin LI else 322*898496eeSXin LI prv = file_buffer(ms, -1, NULL, name, newbuf, 323*898496eeSXin LI nsz); 32420f8619dSXin LI if (prv == -1) 3253e41d09dSXin LI goto error; 32620f8619dSXin LI rv = 1; 3273e41d09dSXin LI if ((ms->flags & MAGIC_COMPRESS_TRANSP) != 0) 3283e41d09dSXin LI goto out; 3293e41d09dSXin LI if (mime != MAGIC_MIME && mime != 0) 3303e41d09dSXin LI goto out; 3313e41d09dSXin LI if ((file_printf(ms, 3323e41d09dSXin LI mime ? " compressed-encoding=" : " (")) == -1) 3333e41d09dSXin LI goto error; 3343e41d09dSXin LI if ((pb = file_push_buffer(ms)) == NULL) 335b6cee71dSXin LI goto error; 33620f8619dSXin LI /* 33720f8619dSXin LI * XXX: If file_buffer fails here, we overwrite 33820f8619dSXin LI * the compressed text. FIXME. 33920f8619dSXin LI */ 340*898496eeSXin LI if (file_buffer(ms, -1, NULL, NULL, buf, nbytes) == -1) 341*898496eeSXin LI { 34248c779cdSXin LI if (file_pop_buffer(ms, pb) != NULL) 34348c779cdSXin LI abort(); 344b6cee71dSXin LI goto error; 34548c779cdSXin LI } 3463e41d09dSXin LI if ((rbuf = file_pop_buffer(ms, pb)) != NULL) { 3473e41d09dSXin LI if (file_printf(ms, "%s", rbuf) == -1) { 3483e41d09dSXin LI free(rbuf); 349b6cee71dSXin LI goto error; 350b6cee71dSXin LI } 3513e41d09dSXin LI free(rbuf); 3523e41d09dSXin LI } 3533e41d09dSXin LI if (!mime && file_printf(ms, ")") == -1) 3543e41d09dSXin LI goto error; 35520f8619dSXin LI /*FALLTHROUGH*/ 3563e41d09dSXin LI case NODATA: 35720f8619dSXin LI break; 3583e41d09dSXin LI default: 3593e41d09dSXin LI abort(); 36020f8619dSXin LI /*NOTREACHED*/ 36120f8619dSXin LI error: 36220f8619dSXin LI rv = -1; 36320f8619dSXin LI break; 3643e41d09dSXin LI } 3653e41d09dSXin LI } 3663e41d09dSXin LI out: 36720f8619dSXin LI DPRINTF("rv = %d\n", rv); 36820f8619dSXin LI 36948c779cdSXin LI if (sa_saved && sig_act.sa_handler != SIG_IGN) 37048c779cdSXin LI (void)sigaction(SIGPIPE, &sig_act, NULL); 37148c779cdSXin LI 372b6cee71dSXin LI free(newbuf); 373b6cee71dSXin LI ms->flags |= MAGIC_COMPRESS; 3743e41d09dSXin LI DPRINTF("Zmagic returns %d\n", rv); 375b6cee71dSXin LI return rv; 376b6cee71dSXin LI } 377b6cee71dSXin LI #endif 378b6cee71dSXin LI /* 379b6cee71dSXin LI * `safe' write for sockets and pipes. 380b6cee71dSXin LI */ 381*898496eeSXin LI file_private ssize_t 382b6cee71dSXin LI swrite(int fd, const void *buf, size_t n) 383b6cee71dSXin LI { 384b6cee71dSXin LI ssize_t rv; 385b6cee71dSXin LI size_t rn = n; 386b6cee71dSXin LI 387b6cee71dSXin LI do 388b6cee71dSXin LI switch (rv = write(fd, buf, n)) { 389b6cee71dSXin LI case -1: 390b6cee71dSXin LI if (errno == EINTR) 391b6cee71dSXin LI continue; 392b6cee71dSXin LI return -1; 393b6cee71dSXin LI default: 394b6cee71dSXin LI n -= rv; 395b6cee71dSXin LI buf = CAST(const char *, buf) + rv; 396b6cee71dSXin LI break; 397b6cee71dSXin LI } 398b6cee71dSXin LI while (n > 0); 399b6cee71dSXin LI return rn; 400b6cee71dSXin LI } 401b6cee71dSXin LI 402b6cee71dSXin LI 403b6cee71dSXin LI /* 404b6cee71dSXin LI * `safe' read for sockets and pipes. 405b6cee71dSXin LI */ 406*898496eeSXin LI file_protected ssize_t 407b6cee71dSXin LI sread(int fd, void *buf, size_t n, int canbepipe __attribute__((__unused__))) 408b6cee71dSXin LI { 409b6cee71dSXin LI ssize_t rv; 410*898496eeSXin LI #if defined(FIONREAD) && !defined(__MINGW32__) 411b6cee71dSXin LI int t = 0; 412b6cee71dSXin LI #endif 413b6cee71dSXin LI size_t rn = n; 414b6cee71dSXin LI 415b6cee71dSXin LI if (fd == STDIN_FILENO) 416b6cee71dSXin LI goto nocheck; 417b6cee71dSXin LI 418*898496eeSXin LI #if defined(FIONREAD) && !defined(__MINGW32__) 419b6cee71dSXin LI if (canbepipe && (ioctl(fd, FIONREAD, &t) == -1 || t == 0)) { 420b6cee71dSXin LI #ifdef FD_ZERO 421b6cee71dSXin LI ssize_t cnt; 422b6cee71dSXin LI for (cnt = 0;; cnt++) { 423b6cee71dSXin LI fd_set check; 424b6cee71dSXin LI struct timeval tout = {0, 100 * 1000}; 425b6cee71dSXin LI int selrv; 426b6cee71dSXin LI 427b6cee71dSXin LI FD_ZERO(&check); 428b6cee71dSXin LI FD_SET(fd, &check); 429b6cee71dSXin LI 430b6cee71dSXin LI /* 431b6cee71dSXin LI * Avoid soft deadlock: do not read if there 432b6cee71dSXin LI * is nothing to read from sockets and pipes. 433b6cee71dSXin LI */ 434b6cee71dSXin LI selrv = select(fd + 1, &check, NULL, NULL, &tout); 435b6cee71dSXin LI if (selrv == -1) { 436b6cee71dSXin LI if (errno == EINTR || errno == EAGAIN) 437b6cee71dSXin LI continue; 438b6cee71dSXin LI } else if (selrv == 0 && cnt >= 5) { 439b6cee71dSXin LI return 0; 440b6cee71dSXin LI } else 441b6cee71dSXin LI break; 442b6cee71dSXin LI } 443b6cee71dSXin LI #endif 444b6cee71dSXin LI (void)ioctl(fd, FIONREAD, &t); 445b6cee71dSXin LI } 446b6cee71dSXin LI 44748c779cdSXin LI if (t > 0 && CAST(size_t, t) < n) { 448b6cee71dSXin LI n = t; 449b6cee71dSXin LI rn = n; 450b6cee71dSXin LI } 451b6cee71dSXin LI #endif 452b6cee71dSXin LI 453b6cee71dSXin LI nocheck: 454b6cee71dSXin LI do 455b6cee71dSXin LI switch ((rv = read(fd, buf, n))) { 456b6cee71dSXin LI case -1: 457b6cee71dSXin LI if (errno == EINTR) 458b6cee71dSXin LI continue; 459b6cee71dSXin LI return -1; 460b6cee71dSXin LI case 0: 461b6cee71dSXin LI return rn - n; 462b6cee71dSXin LI default: 463b6cee71dSXin LI n -= rv; 464a5d223e6SXin LI buf = CAST(char *, CCAST(void *, buf)) + rv; 465b6cee71dSXin LI break; 466b6cee71dSXin LI } 467b6cee71dSXin LI while (n > 0); 468b6cee71dSXin LI return rn; 469b6cee71dSXin LI } 470b6cee71dSXin LI 471*898496eeSXin LI file_protected int 472b6cee71dSXin LI file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, 473b6cee71dSXin LI size_t nbytes) 474b6cee71dSXin LI { 475b6cee71dSXin LI char buf[4096]; 476b6cee71dSXin LI ssize_t r; 477b6cee71dSXin LI int tfd; 478b6cee71dSXin LI 479a4d6d3b8SXin LI #ifdef WIN32 480a4d6d3b8SXin LI const char *t; 481a4d6d3b8SXin LI buf[0] = '\0'; 482a4d6d3b8SXin LI if ((t = getenv("TEMP")) != NULL) 483a4d6d3b8SXin LI (void)strlcpy(buf, t, sizeof(buf)); 484a4d6d3b8SXin LI else if ((t = getenv("TMP")) != NULL) 485a4d6d3b8SXin LI (void)strlcpy(buf, t, sizeof(buf)); 486a4d6d3b8SXin LI else if ((t = getenv("TMPDIR")) != NULL) 487a4d6d3b8SXin LI (void)strlcpy(buf, t, sizeof(buf)); 488a4d6d3b8SXin LI if (buf[0] != '\0') 489a4d6d3b8SXin LI (void)strlcat(buf, "/", sizeof(buf)); 490a4d6d3b8SXin LI (void)strlcat(buf, "file.XXXXXX", sizeof(buf)); 491a4d6d3b8SXin LI #else 492a4d6d3b8SXin LI (void)strlcpy(buf, "/tmp/file.XXXXXX", sizeof(buf)); 493a4d6d3b8SXin LI #endif 494b6cee71dSXin LI #ifndef HAVE_MKSTEMP 495b6cee71dSXin LI { 496b6cee71dSXin LI char *ptr = mktemp(buf); 497b6cee71dSXin LI tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600); 498b6cee71dSXin LI r = errno; 499b6cee71dSXin LI (void)unlink(ptr); 500b6cee71dSXin LI errno = r; 501b6cee71dSXin LI } 502b6cee71dSXin LI #else 503b6cee71dSXin LI { 504b6cee71dSXin LI int te; 50548c779cdSXin LI mode_t ou = umask(0); 506b6cee71dSXin LI tfd = mkstemp(buf); 50748c779cdSXin LI (void)umask(ou); 508b6cee71dSXin LI te = errno; 509b6cee71dSXin LI (void)unlink(buf); 510b6cee71dSXin LI errno = te; 511b6cee71dSXin LI } 512b6cee71dSXin LI #endif 513b6cee71dSXin LI if (tfd == -1) { 514b6cee71dSXin LI file_error(ms, errno, 515b6cee71dSXin LI "cannot create temporary file for pipe copy"); 516b6cee71dSXin LI return -1; 517b6cee71dSXin LI } 518b6cee71dSXin LI 51948c779cdSXin LI if (swrite(tfd, startbuf, nbytes) != CAST(ssize_t, nbytes)) 520b6cee71dSXin LI r = 1; 521b6cee71dSXin LI else { 522b6cee71dSXin LI while ((r = sread(fd, buf, sizeof(buf), 1)) > 0) 52348c779cdSXin LI if (swrite(tfd, buf, CAST(size_t, r)) != r) 524b6cee71dSXin LI break; 525b6cee71dSXin LI } 526b6cee71dSXin LI 527b6cee71dSXin LI switch (r) { 528b6cee71dSXin LI case -1: 529b6cee71dSXin LI file_error(ms, errno, "error copying from pipe to temp file"); 530b6cee71dSXin LI return -1; 531b6cee71dSXin LI case 0: 532b6cee71dSXin LI break; 533b6cee71dSXin LI default: 534b6cee71dSXin LI file_error(ms, errno, "error while writing to temp file"); 535b6cee71dSXin LI return -1; 536b6cee71dSXin LI } 537b6cee71dSXin LI 538b6cee71dSXin LI /* 539b6cee71dSXin LI * We duplicate the file descriptor, because fclose on a 540b6cee71dSXin LI * tmpfile will delete the file, but any open descriptors 541b6cee71dSXin LI * can still access the phantom inode. 542b6cee71dSXin LI */ 543b6cee71dSXin LI if ((fd = dup2(tfd, fd)) == -1) { 544b6cee71dSXin LI file_error(ms, errno, "could not dup descriptor for temp file"); 545b6cee71dSXin LI return -1; 546b6cee71dSXin LI } 547b6cee71dSXin LI (void)close(tfd); 54848c779cdSXin LI if (lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1)) { 549b6cee71dSXin LI file_badseek(ms); 550b6cee71dSXin LI return -1; 551b6cee71dSXin LI } 552b6cee71dSXin LI return fd; 553b6cee71dSXin LI } 554b6cee71dSXin LI #if HAVE_FORK 555b6cee71dSXin LI #ifdef BUILTIN_DECOMPRESS 556b6cee71dSXin LI 557b6cee71dSXin LI #define FHCRC (1 << 1) 558b6cee71dSXin LI #define FEXTRA (1 << 2) 559b6cee71dSXin LI #define FNAME (1 << 3) 560b6cee71dSXin LI #define FCOMMENT (1 << 4) 561b6cee71dSXin LI 5623e41d09dSXin LI 563*898496eeSXin LI file_private int 5643e41d09dSXin LI uncompressgzipped(const unsigned char *old, unsigned char **newch, 565*898496eeSXin LI size_t bytes_max, size_t *n, int extra __attribute__((__unused__))) 566b6cee71dSXin LI { 567*898496eeSXin LI unsigned char flg; 568b6cee71dSXin LI size_t data_start = 10; 569b6cee71dSXin LI 570*898496eeSXin LI if (*n < 4) { 571*898496eeSXin LI goto err; 572*898496eeSXin LI } 573*898496eeSXin LI 574*898496eeSXin LI flg = old[3]; 575*898496eeSXin LI 576b6cee71dSXin LI if (flg & FEXTRA) { 5773e41d09dSXin LI if (data_start + 1 >= *n) 5783e41d09dSXin LI goto err; 579b6cee71dSXin LI data_start += 2 + old[data_start] + old[data_start + 1] * 256; 580b6cee71dSXin LI } 581b6cee71dSXin LI if (flg & FNAME) { 5823e41d09dSXin LI while(data_start < *n && old[data_start]) 583b6cee71dSXin LI data_start++; 584b6cee71dSXin LI data_start++; 585b6cee71dSXin LI } 586b6cee71dSXin LI if (flg & FCOMMENT) { 5873e41d09dSXin LI while(data_start < *n && old[data_start]) 588b6cee71dSXin LI data_start++; 589b6cee71dSXin LI data_start++; 590b6cee71dSXin LI } 591b6cee71dSXin LI if (flg & FHCRC) 592b6cee71dSXin LI data_start += 2; 593b6cee71dSXin LI 5943e41d09dSXin LI if (data_start >= *n) 5953e41d09dSXin LI goto err; 5963e41d09dSXin LI 5973e41d09dSXin LI *n -= data_start; 5983e41d09dSXin LI old += data_start; 5993e41d09dSXin LI return uncompresszlib(old, newch, bytes_max, n, 0); 6003e41d09dSXin LI err: 6013e41d09dSXin LI return makeerror(newch, n, "File too short"); 602b6cee71dSXin LI } 603b6cee71dSXin LI 604*898496eeSXin LI file_private int 6053e41d09dSXin LI uncompresszlib(const unsigned char *old, unsigned char **newch, 6063e41d09dSXin LI size_t bytes_max, size_t *n, int zlib) 6073e41d09dSXin LI { 6083e41d09dSXin LI int rc; 6093e41d09dSXin LI z_stream z; 6103e41d09dSXin LI 611*898496eeSXin LI DPRINTF("builtin zlib decompression\n"); 6123e41d09dSXin LI z.next_in = CCAST(Bytef *, old); 6133e41d09dSXin LI z.avail_in = CAST(uint32_t, *n); 614b6cee71dSXin LI z.next_out = *newch; 61540427ccaSGordon Tetlow z.avail_out = CAST(unsigned int, bytes_max); 616b6cee71dSXin LI z.zalloc = Z_NULL; 617b6cee71dSXin LI z.zfree = Z_NULL; 618b6cee71dSXin LI z.opaque = Z_NULL; 619b6cee71dSXin LI 620b6cee71dSXin LI /* LINTED bug in header macro */ 6213e41d09dSXin LI rc = zlib ? inflateInit(&z) : inflateInit2(&z, -15); 6223e41d09dSXin LI if (rc != Z_OK) 6233e41d09dSXin LI goto err; 624b6cee71dSXin LI 625b6cee71dSXin LI rc = inflate(&z, Z_SYNC_FLUSH); 626*898496eeSXin LI if (rc != Z_OK && rc != Z_STREAM_END) { 627*898496eeSXin LI inflateEnd(&z); 6283e41d09dSXin LI goto err; 629*898496eeSXin LI } 630b6cee71dSXin LI 63148c779cdSXin LI *n = CAST(size_t, z.total_out); 6323e41d09dSXin LI rc = inflateEnd(&z); 6333e41d09dSXin LI if (rc != Z_OK) 6343e41d09dSXin LI goto err; 635b6cee71dSXin LI 636b6cee71dSXin LI /* let's keep the nul-terminate tradition */ 6373e41d09dSXin LI (*newch)[*n] = '\0'; 638b6cee71dSXin LI 6393e41d09dSXin LI return OKDATA; 6403e41d09dSXin LI err: 641*898496eeSXin LI return makeerror(newch, n, "%s", z.msg ? z.msg : zError(rc)); 642b6cee71dSXin LI } 643b6cee71dSXin LI #endif 644b6cee71dSXin LI 645d38c30c0SXin LI #ifdef BUILTIN_BZLIB 646*898496eeSXin LI file_private int 647d38c30c0SXin LI uncompressbzlib(const unsigned char *old, unsigned char **newch, 648*898496eeSXin LI size_t bytes_max, size_t *n, int extra __attribute__((__unused__))) 649d38c30c0SXin LI { 650d38c30c0SXin LI int rc; 651d38c30c0SXin LI bz_stream bz; 652d38c30c0SXin LI 653*898496eeSXin LI DPRINTF("builtin bzlib decompression\n"); 654d38c30c0SXin LI memset(&bz, 0, sizeof(bz)); 655d38c30c0SXin LI rc = BZ2_bzDecompressInit(&bz, 0, 0); 656d38c30c0SXin LI if (rc != BZ_OK) 657d38c30c0SXin LI goto err; 658d38c30c0SXin LI 659d38c30c0SXin LI bz.next_in = CCAST(char *, RCAST(const char *, old)); 660d38c30c0SXin LI bz.avail_in = CAST(uint32_t, *n); 661d38c30c0SXin LI bz.next_out = RCAST(char *, *newch); 662d38c30c0SXin LI bz.avail_out = CAST(unsigned int, bytes_max); 663d38c30c0SXin LI 664d38c30c0SXin LI rc = BZ2_bzDecompress(&bz); 665*898496eeSXin LI if (rc != BZ_OK && rc != BZ_STREAM_END) { 666*898496eeSXin LI BZ2_bzDecompressEnd(&bz); 667d38c30c0SXin LI goto err; 668*898496eeSXin LI } 669d38c30c0SXin LI 670d38c30c0SXin LI /* Assume byte_max is within 32bit */ 671d38c30c0SXin LI /* assert(bz.total_out_hi32 == 0); */ 672d38c30c0SXin LI *n = CAST(size_t, bz.total_out_lo32); 673d38c30c0SXin LI rc = BZ2_bzDecompressEnd(&bz); 674d38c30c0SXin LI if (rc != BZ_OK) 675d38c30c0SXin LI goto err; 676d38c30c0SXin LI 677d38c30c0SXin LI /* let's keep the nul-terminate tradition */ 678d38c30c0SXin LI (*newch)[*n] = '\0'; 679d38c30c0SXin LI 680d38c30c0SXin LI return OKDATA; 681d38c30c0SXin LI err: 682*898496eeSXin LI return makeerror(newch, n, "bunzip error %d", rc); 683d38c30c0SXin LI } 684d38c30c0SXin LI #endif 685d38c30c0SXin LI 686d38c30c0SXin LI #ifdef BUILTIN_XZLIB 687*898496eeSXin LI file_private int 688d38c30c0SXin LI uncompressxzlib(const unsigned char *old, unsigned char **newch, 689*898496eeSXin LI size_t bytes_max, size_t *n, int extra __attribute__((__unused__))) 690d38c30c0SXin LI { 691d38c30c0SXin LI int rc; 692d38c30c0SXin LI lzma_stream xz; 693d38c30c0SXin LI 694*898496eeSXin LI DPRINTF("builtin xzlib decompression\n"); 695d38c30c0SXin LI memset(&xz, 0, sizeof(xz)); 696d38c30c0SXin LI rc = lzma_auto_decoder(&xz, UINT64_MAX, 0); 697d38c30c0SXin LI if (rc != LZMA_OK) 698d38c30c0SXin LI goto err; 699d38c30c0SXin LI 700d38c30c0SXin LI xz.next_in = CCAST(const uint8_t *, old); 701d38c30c0SXin LI xz.avail_in = CAST(uint32_t, *n); 702d38c30c0SXin LI xz.next_out = RCAST(uint8_t *, *newch); 703d38c30c0SXin LI xz.avail_out = CAST(unsigned int, bytes_max); 704d38c30c0SXin LI 705d38c30c0SXin LI rc = lzma_code(&xz, LZMA_RUN); 706*898496eeSXin LI if (rc != LZMA_OK && rc != LZMA_STREAM_END) { 707*898496eeSXin LI lzma_end(&xz); 708d38c30c0SXin LI goto err; 709*898496eeSXin LI } 710d38c30c0SXin LI 711d38c30c0SXin LI *n = CAST(size_t, xz.total_out); 712d38c30c0SXin LI 713d38c30c0SXin LI lzma_end(&xz); 714d38c30c0SXin LI 715d38c30c0SXin LI /* let's keep the nul-terminate tradition */ 716d38c30c0SXin LI (*newch)[*n] = '\0'; 717d38c30c0SXin LI 718d38c30c0SXin LI return OKDATA; 719d38c30c0SXin LI err: 720*898496eeSXin LI return makeerror(newch, n, "unxz error %d", rc); 721*898496eeSXin LI } 722*898496eeSXin LI #endif 723*898496eeSXin LI 724*898496eeSXin LI #ifdef BUILTIN_ZSTDLIB 725*898496eeSXin LI file_private int 726*898496eeSXin LI uncompresszstd(const unsigned char *old, unsigned char **newch, 727*898496eeSXin LI size_t bytes_max, size_t *n, int extra __attribute__((__unused__))) 728*898496eeSXin LI { 729*898496eeSXin LI size_t rc; 730*898496eeSXin LI ZSTD_DStream *zstd; 731*898496eeSXin LI ZSTD_inBuffer in; 732*898496eeSXin LI ZSTD_outBuffer out; 733*898496eeSXin LI 734*898496eeSXin LI DPRINTF("builtin zstd decompression\n"); 735*898496eeSXin LI if ((zstd = ZSTD_createDStream()) == NULL) { 736*898496eeSXin LI return makeerror(newch, n, "No ZSTD decompression stream, %s", 737*898496eeSXin LI strerror(errno)); 738*898496eeSXin LI } 739*898496eeSXin LI 740*898496eeSXin LI rc = ZSTD_DCtx_reset(zstd, ZSTD_reset_session_only); 741*898496eeSXin LI if (ZSTD_isError(rc)) 742*898496eeSXin LI goto err; 743*898496eeSXin LI 744*898496eeSXin LI in.src = CCAST(const void *, old); 745*898496eeSXin LI in.size = *n; 746*898496eeSXin LI in.pos = 0; 747*898496eeSXin LI out.dst = RCAST(void *, *newch); 748*898496eeSXin LI out.size = bytes_max; 749*898496eeSXin LI out.pos = 0; 750*898496eeSXin LI 751*898496eeSXin LI rc = ZSTD_decompressStream(zstd, &out, &in); 752*898496eeSXin LI if (ZSTD_isError(rc)) 753*898496eeSXin LI goto err; 754*898496eeSXin LI 755*898496eeSXin LI *n = out.pos; 756*898496eeSXin LI 757*898496eeSXin LI ZSTD_freeDStream(zstd); 758*898496eeSXin LI 759*898496eeSXin LI /* let's keep the nul-terminate tradition */ 760*898496eeSXin LI (*newch)[*n] = '\0'; 761*898496eeSXin LI 762*898496eeSXin LI return OKDATA; 763*898496eeSXin LI err: 764*898496eeSXin LI ZSTD_freeDStream(zstd); 765*898496eeSXin LI return makeerror(newch, n, "zstd error %d", ZSTD_getErrorCode(rc)); 766*898496eeSXin LI } 767*898496eeSXin LI #endif 768*898496eeSXin LI 769*898496eeSXin LI #ifdef BUILTIN_LZLIB 770*898496eeSXin LI file_private int 771*898496eeSXin LI uncompresslzlib(const unsigned char *old, unsigned char **newch, 772*898496eeSXin LI size_t bytes_max, size_t *n, int extra __attribute__((__unused__))) 773*898496eeSXin LI { 774*898496eeSXin LI enum LZ_Errno err; 775*898496eeSXin LI size_t old_remaining = *n; 776*898496eeSXin LI size_t new_remaining = bytes_max; 777*898496eeSXin LI size_t total_read = 0; 778*898496eeSXin LI unsigned char *bufp; 779*898496eeSXin LI struct LZ_Decoder *dec; 780*898496eeSXin LI 781*898496eeSXin LI bufp = *newch; 782*898496eeSXin LI 783*898496eeSXin LI DPRINTF("builtin lzlib decompression\n"); 784*898496eeSXin LI dec = LZ_decompress_open(); 785*898496eeSXin LI if (!dec) { 786*898496eeSXin LI return makeerror(newch, n, "unable to allocate LZ_Decoder"); 787*898496eeSXin LI } 788*898496eeSXin LI if (LZ_decompress_errno(dec) != LZ_ok) 789*898496eeSXin LI goto err; 790*898496eeSXin LI 791*898496eeSXin LI for (;;) { 792*898496eeSXin LI // LZ_decompress_read() stops at member boundaries, so we may 793*898496eeSXin LI // have more than one successful read after writing all data 794*898496eeSXin LI // we have. 795*898496eeSXin LI if (old_remaining > 0) { 796*898496eeSXin LI int wr = LZ_decompress_write(dec, old, old_remaining); 797*898496eeSXin LI if (wr < 0) 798*898496eeSXin LI goto err; 799*898496eeSXin LI old_remaining -= wr; 800*898496eeSXin LI old += wr; 801*898496eeSXin LI } 802*898496eeSXin LI 803*898496eeSXin LI int rd = LZ_decompress_read(dec, bufp, new_remaining); 804*898496eeSXin LI if (rd > 0) { 805*898496eeSXin LI new_remaining -= rd; 806*898496eeSXin LI bufp += rd; 807*898496eeSXin LI total_read += rd; 808*898496eeSXin LI } 809*898496eeSXin LI 810*898496eeSXin LI if (rd < 0 || LZ_decompress_errno(dec) != LZ_ok) 811*898496eeSXin LI goto err; 812*898496eeSXin LI if (new_remaining == 0) 813*898496eeSXin LI break; 814*898496eeSXin LI if (old_remaining == 0 && rd == 0) 815*898496eeSXin LI break; 816*898496eeSXin LI } 817*898496eeSXin LI 818*898496eeSXin LI LZ_decompress_close(dec); 819*898496eeSXin LI *n = total_read; 820*898496eeSXin LI 821*898496eeSXin LI /* let's keep the nul-terminate tradition */ 822*898496eeSXin LI *bufp = '\0'; 823*898496eeSXin LI 824*898496eeSXin LI return OKDATA; 825*898496eeSXin LI err: 826*898496eeSXin LI err = LZ_decompress_errno(dec); 827*898496eeSXin LI LZ_decompress_close(dec); 828*898496eeSXin LI return makeerror(newch, n, "lzlib error: %s", LZ_strerror(err)); 829d38c30c0SXin LI } 830d38c30c0SXin LI #endif 831d38c30c0SXin LI 832d38c30c0SXin LI 8333e41d09dSXin LI static int 8343e41d09dSXin LI makeerror(unsigned char **buf, size_t *len, const char *fmt, ...) 835b6cee71dSXin LI { 8363e41d09dSXin LI char *msg; 8373e41d09dSXin LI va_list ap; 8383e41d09dSXin LI int rv; 839b6cee71dSXin LI 840*898496eeSXin LI DPRINTF("Makeerror %s\n", fmt); 841*898496eeSXin LI free(*buf); 8423e41d09dSXin LI va_start(ap, fmt); 8433e41d09dSXin LI rv = vasprintf(&msg, fmt, ap); 8443e41d09dSXin LI va_end(ap); 8453e41d09dSXin LI if (rv < 0) { 846*898496eeSXin LI DPRINTF("Makeerror failed"); 8473e41d09dSXin LI *buf = NULL; 8483e41d09dSXin LI *len = 0; 849b6cee71dSXin LI return NODATA; 850b6cee71dSXin LI } 85148c779cdSXin LI *buf = RCAST(unsigned char *, msg); 8523e41d09dSXin LI *len = strlen(msg); 8533e41d09dSXin LI return ERRDATA; 854b6cee71dSXin LI } 855b6cee71dSXin LI 8563e41d09dSXin LI static void 8573e41d09dSXin LI closefd(int *fd, size_t i) 8583e41d09dSXin LI { 8593e41d09dSXin LI if (fd[i] == -1) 8603e41d09dSXin LI return; 8613e41d09dSXin LI (void) close(fd[i]); 8623e41d09dSXin LI fd[i] = -1; 8633e41d09dSXin LI } 864b6cee71dSXin LI 8653e41d09dSXin LI static void 8663e41d09dSXin LI closep(int *fd) 8673e41d09dSXin LI { 8683e41d09dSXin LI size_t i; 8693e41d09dSXin LI for (i = 0; i < 2; i++) 8703e41d09dSXin LI closefd(fd, i); 8713e41d09dSXin LI } 8723e41d09dSXin LI 873a4d6d3b8SXin LI static void 874a4d6d3b8SXin LI movedesc(void *v, int i, int fd) 8753e41d09dSXin LI { 87648c779cdSXin LI if (fd == i) 877a4d6d3b8SXin LI return; /* "no dup was necessary" */ 878a4d6d3b8SXin LI #ifdef HAVE_POSIX_SPAWNP 879a4d6d3b8SXin LI posix_spawn_file_actions_t *fa = RCAST(posix_spawn_file_actions_t *, v); 880a4d6d3b8SXin LI posix_spawn_file_actions_adddup2(fa, fd, i); 881a4d6d3b8SXin LI posix_spawn_file_actions_addclose(fa, fd); 882a4d6d3b8SXin LI #else 88348c779cdSXin LI if (dup2(fd, i) == -1) { 88448c779cdSXin LI DPRINTF("dup(%d, %d) failed (%s)\n", fd, i, strerror(errno)); 885*898496eeSXin LI exit(EXIT_FAILURE); 8863e41d09dSXin LI } 887a4d6d3b8SXin LI close(v ? fd : fd); 888a4d6d3b8SXin LI #endif 889a4d6d3b8SXin LI } 890a4d6d3b8SXin LI 891a4d6d3b8SXin LI static void 892a4d6d3b8SXin LI closedesc(void *v, int fd) 893a4d6d3b8SXin LI { 894a4d6d3b8SXin LI #ifdef HAVE_POSIX_SPAWNP 895a4d6d3b8SXin LI posix_spawn_file_actions_t *fa = RCAST(posix_spawn_file_actions_t *, v); 896a4d6d3b8SXin LI posix_spawn_file_actions_addclose(fa, fd); 897a4d6d3b8SXin LI #else 898a4d6d3b8SXin LI close(v ? fd : fd); 899a4d6d3b8SXin LI #endif 900a4d6d3b8SXin LI } 901a4d6d3b8SXin LI 902a4d6d3b8SXin LI static void 903a4d6d3b8SXin LI handledesc(void *v, int fd, int fdp[3][2]) 904a4d6d3b8SXin LI { 905a4d6d3b8SXin LI if (fd != -1) { 906a4d6d3b8SXin LI (void) lseek(fd, CAST(off_t, 0), SEEK_SET); 907a4d6d3b8SXin LI movedesc(v, STDIN_FILENO, fd); 908a4d6d3b8SXin LI } else { 909a4d6d3b8SXin LI movedesc(v, STDIN_FILENO, fdp[STDIN_FILENO][0]); 910a4d6d3b8SXin LI if (fdp[STDIN_FILENO][1] > 2) 911a4d6d3b8SXin LI closedesc(v, fdp[STDIN_FILENO][1]); 912a4d6d3b8SXin LI } 913a4d6d3b8SXin LI 914a4d6d3b8SXin LI file_clear_closexec(STDIN_FILENO); 915a4d6d3b8SXin LI 916a4d6d3b8SXin LI ///FIXME: if one of the fdp[i][j] is 0 or 1, this can bomb spectacularly 917a4d6d3b8SXin LI movedesc(v, STDOUT_FILENO, fdp[STDOUT_FILENO][1]); 918a4d6d3b8SXin LI if (fdp[STDOUT_FILENO][0] > 2) 919a4d6d3b8SXin LI closedesc(v, fdp[STDOUT_FILENO][0]); 920a4d6d3b8SXin LI 921a4d6d3b8SXin LI file_clear_closexec(STDOUT_FILENO); 922a4d6d3b8SXin LI 923a4d6d3b8SXin LI movedesc(v, STDERR_FILENO, fdp[STDERR_FILENO][1]); 924a4d6d3b8SXin LI if (fdp[STDERR_FILENO][0] > 2) 925a4d6d3b8SXin LI closedesc(v, fdp[STDERR_FILENO][0]); 926a4d6d3b8SXin LI 927a4d6d3b8SXin LI file_clear_closexec(STDERR_FILENO); 9283e41d09dSXin LI } 929b6cee71dSXin LI 93048c779cdSXin LI static pid_t 93148c779cdSXin LI writechild(int fd, const void *old, size_t n) 9323e41d09dSXin LI { 93348c779cdSXin LI pid_t pid; 9343e41d09dSXin LI 935b6cee71dSXin LI /* 936b6cee71dSXin LI * fork again, to avoid blocking because both 937b6cee71dSXin LI * pipes filled 938b6cee71dSXin LI */ 93948c779cdSXin LI pid = fork(); 94048c779cdSXin LI if (pid == -1) { 94148c779cdSXin LI DPRINTF("Fork failed (%s)\n", strerror(errno)); 942*898496eeSXin LI return -1; 94348c779cdSXin LI } 94448c779cdSXin LI if (pid == 0) { 94548c779cdSXin LI /* child */ 94648c779cdSXin LI if (swrite(fd, old, n) != CAST(ssize_t, n)) { 9473e41d09dSXin LI DPRINTF("Write failed (%s)\n", strerror(errno)); 948*898496eeSXin LI exit(EXIT_FAILURE); 949b6cee71dSXin LI } 950*898496eeSXin LI exit(EXIT_SUCCESS); 951c2931133SXin LI } 95248c779cdSXin LI /* parent */ 95348c779cdSXin LI return pid; 954b6cee71dSXin LI } 955b6cee71dSXin LI 9563e41d09dSXin LI static ssize_t 9573e41d09dSXin LI filter_error(unsigned char *ubuf, ssize_t n) 9583e41d09dSXin LI { 9593e41d09dSXin LI char *p; 9603e41d09dSXin LI char *buf; 961c2931133SXin LI 9623e41d09dSXin LI ubuf[n] = '\0'; 96348c779cdSXin LI buf = RCAST(char *, ubuf); 96448c779cdSXin LI while (isspace(CAST(unsigned char, *buf))) 9653e41d09dSXin LI buf++; 9663e41d09dSXin LI DPRINTF("Filter error[[[%s]]]\n", buf); 96748c779cdSXin LI if ((p = strchr(CAST(char *, buf), '\n')) != NULL) 9683e41d09dSXin LI *p = '\0'; 96948c779cdSXin LI if ((p = strchr(CAST(char *, buf), ';')) != NULL) 9703e41d09dSXin LI *p = '\0'; 97148c779cdSXin LI if ((p = strrchr(CAST(char *, buf), ':')) != NULL) { 9723e41d09dSXin LI ++p; 97348c779cdSXin LI while (isspace(CAST(unsigned char, *p))) 9743e41d09dSXin LI p++; 9753e41d09dSXin LI n = strlen(p); 97640427ccaSGordon Tetlow memmove(ubuf, p, CAST(size_t, n + 1)); 9773e41d09dSXin LI } 9783e41d09dSXin LI DPRINTF("Filter error after[[[%s]]]\n", (char *)ubuf); 9793e41d09dSXin LI if (islower(*ubuf)) 9803e41d09dSXin LI *ubuf = toupper(*ubuf); 981b6cee71dSXin LI return n; 982b6cee71dSXin LI } 9833e41d09dSXin LI 984*898496eeSXin LI file_private const char * 9853e41d09dSXin LI methodname(size_t method) 9863e41d09dSXin LI { 987d38c30c0SXin LI switch (method) { 9883e41d09dSXin LI #ifdef BUILTIN_DECOMPRESS 989d38c30c0SXin LI case METH_FROZEN: 990d38c30c0SXin LI case METH_ZLIB: 9913e41d09dSXin LI return "zlib"; 9923e41d09dSXin LI #endif 993d38c30c0SXin LI #ifdef BUILTIN_BZLIB 994d38c30c0SXin LI case METH_BZIP: 995d38c30c0SXin LI return "bzlib"; 996d38c30c0SXin LI #endif 997d38c30c0SXin LI #ifdef BUILTIN_XZLIB 998d38c30c0SXin LI case METH_XZ: 999d38c30c0SXin LI case METH_LZMA: 1000d38c30c0SXin LI return "xzlib"; 1001d38c30c0SXin LI #endif 1002*898496eeSXin LI #ifdef BUILTIN_ZSTDLIB 1003*898496eeSXin LI case METH_ZSTD: 1004*898496eeSXin LI return "zstd"; 1005*898496eeSXin LI #endif 1006*898496eeSXin LI #ifdef BUILTIN_LZLIB 1007*898496eeSXin LI case METH_LZIP: 1008*898496eeSXin LI return "lzlib"; 1009*898496eeSXin LI #endif 1010d38c30c0SXin LI default: 10113e41d09dSXin LI return compr[method].argv[0]; 10123e41d09dSXin LI } 1013d38c30c0SXin LI } 10143e41d09dSXin LI 1015*898496eeSXin LI file_private int (* 1016*898496eeSXin LI getdecompressor(size_t method))(const unsigned char *, unsigned char **, size_t, 1017*898496eeSXin LI size_t *, int) 1018*898496eeSXin LI { 1019*898496eeSXin LI switch (method) { 1020*898496eeSXin LI #ifdef BUILTIN_DECOMPRESS 1021*898496eeSXin LI case METH_FROZEN: 1022*898496eeSXin LI return uncompressgzipped; 1023*898496eeSXin LI case METH_ZLIB: 1024*898496eeSXin LI return uncompresszlib; 1025*898496eeSXin LI #endif 1026*898496eeSXin LI #ifdef BUILTIN_BZLIB 1027*898496eeSXin LI case METH_BZIP: 1028*898496eeSXin LI return uncompressbzlib; 1029*898496eeSXin LI #endif 1030*898496eeSXin LI #ifdef BUILTIN_XZLIB 1031*898496eeSXin LI case METH_XZ: 1032*898496eeSXin LI case METH_LZMA: 1033*898496eeSXin LI return uncompressxzlib; 1034*898496eeSXin LI #endif 1035*898496eeSXin LI #ifdef BUILTIN_ZSTDLIB 1036*898496eeSXin LI case METH_ZSTD: 1037*898496eeSXin LI return uncompresszstd; 1038*898496eeSXin LI #endif 1039*898496eeSXin LI #ifdef BUILTIN_LZLIB 1040*898496eeSXin LI case METH_LZIP: 1041*898496eeSXin LI return uncompresslzlib; 1042*898496eeSXin LI #endif 1043*898496eeSXin LI default: 1044*898496eeSXin LI return NULL; 1045*898496eeSXin LI } 1046*898496eeSXin LI } 1047*898496eeSXin LI 1048*898496eeSXin LI file_private int 1049*898496eeSXin LI uncompressbuf(int fd, size_t bytes_max, size_t method, int nofork, 1050*898496eeSXin LI const unsigned char *old, unsigned char **newch, size_t* n) 10513e41d09dSXin LI { 10523e41d09dSXin LI int fdp[3][2]; 105348c779cdSXin LI int status, rv, w; 105448c779cdSXin LI pid_t pid; 105548c779cdSXin LI pid_t writepid = -1; 10563e41d09dSXin LI size_t i; 1057*898496eeSXin LI ssize_t r, re; 1058a4d6d3b8SXin LI char *const *args; 1059a4d6d3b8SXin LI #ifdef HAVE_POSIX_SPAWNP 1060a4d6d3b8SXin LI posix_spawn_file_actions_t fa; 1061a4d6d3b8SXin LI #endif 1062*898496eeSXin LI int (*decompress)(const unsigned char *, unsigned char **, 1063*898496eeSXin LI size_t, size_t *, int) = getdecompressor(method); 10643e41d09dSXin LI 1065*898496eeSXin LI *newch = CAST(unsigned char *, malloc(bytes_max + 1)); 1066*898496eeSXin LI if (*newch == NULL) 1067*898496eeSXin LI return makeerror(newch, n, "No buffer, %s", strerror(errno)); 1068*898496eeSXin LI 1069*898496eeSXin LI if (decompress) { 1070*898496eeSXin LI if (nofork) { 1071*898496eeSXin LI return makeerror(newch, n, 1072*898496eeSXin LI "Fork is required to uncompress, but disabled"); 1073*898496eeSXin LI } 1074*898496eeSXin LI return (*decompress)(old, newch, bytes_max, n, 1); 1075d38c30c0SXin LI } 1076d38c30c0SXin LI 10773e41d09dSXin LI (void)fflush(stdout); 10783e41d09dSXin LI (void)fflush(stderr); 10793e41d09dSXin LI 10803e41d09dSXin LI for (i = 0; i < __arraycount(fdp); i++) 10813e41d09dSXin LI fdp[i][0] = fdp[i][1] = -1; 10823e41d09dSXin LI 108343a5ec4eSXin LI /* 108443a5ec4eSXin LI * There are multithreaded users who run magic_file() 108543a5ec4eSXin LI * from dozens of threads. If two parallel magic_file() calls 108643a5ec4eSXin LI * analyze two large compressed files, both will spawn 108743a5ec4eSXin LI * an uncompressing child here, which writes out uncompressed data. 108843a5ec4eSXin LI * We read some portion, then close the pipe, then waitpid() the child. 1089*898496eeSXin LI * If uncompressed data is larger, child should get EPIPE and exit. 109043a5ec4eSXin LI * However, with *parallel* calls OTHER child may unintentionally 109143a5ec4eSXin LI * inherit pipe fds, thus keeping pipe open and making writes in 109243a5ec4eSXin LI * our child block instead of failing with EPIPE! 109343a5ec4eSXin LI * (For the bug to occur, two threads must mutually inherit their pipes, 109443a5ec4eSXin LI * and both must have large outputs. Thus it happens not that often). 109543a5ec4eSXin LI * To avoid this, be sure to create pipes with O_CLOEXEC. 109643a5ec4eSXin LI */ 109743a5ec4eSXin LI if ((fd == -1 && file_pipe_closexec(fdp[STDIN_FILENO]) == -1) || 109843a5ec4eSXin LI file_pipe_closexec(fdp[STDOUT_FILENO]) == -1 || 109943a5ec4eSXin LI file_pipe_closexec(fdp[STDERR_FILENO]) == -1) { 11003e41d09dSXin LI closep(fdp[STDIN_FILENO]); 11013e41d09dSXin LI closep(fdp[STDOUT_FILENO]); 11023e41d09dSXin LI return makeerror(newch, n, "Cannot create pipe, %s", 11033e41d09dSXin LI strerror(errno)); 11043e41d09dSXin LI } 11053e41d09dSXin LI 1106a4d6d3b8SXin LI args = RCAST(char *const *, RCAST(intptr_t, compr[method].argv)); 1107a4d6d3b8SXin LI #ifdef HAVE_POSIX_SPAWNP 1108a4d6d3b8SXin LI posix_spawn_file_actions_init(&fa); 1109a4d6d3b8SXin LI 1110a4d6d3b8SXin LI handledesc(&fa, fd, fdp); 1111a4d6d3b8SXin LI 1112*898496eeSXin LI DPRINTF("Executing %s\n", compr[method].argv[0]); 1113a4d6d3b8SXin LI status = posix_spawnp(&pid, compr[method].argv[0], &fa, NULL, 1114a4d6d3b8SXin LI args, NULL); 1115a4d6d3b8SXin LI 1116a4d6d3b8SXin LI posix_spawn_file_actions_destroy(&fa); 1117a4d6d3b8SXin LI 1118a4d6d3b8SXin LI if (status == -1) { 1119a4d6d3b8SXin LI return makeerror(newch, n, "Cannot posix_spawn `%s', %s", 1120a4d6d3b8SXin LI compr[method].argv[0], strerror(errno)); 1121a4d6d3b8SXin LI } 1122a4d6d3b8SXin LI #else 112348c779cdSXin LI /* For processes with large mapped virtual sizes, vfork 112448c779cdSXin LI * may be _much_ faster (10-100 times) than fork. 112548c779cdSXin LI */ 112648c779cdSXin LI pid = vfork(); 112748c779cdSXin LI if (pid == -1) { 112848c779cdSXin LI return makeerror(newch, n, "Cannot vfork, %s", 112948c779cdSXin LI strerror(errno)); 113048c779cdSXin LI } 113148c779cdSXin LI if (pid == 0) { 113248c779cdSXin LI /* child */ 113348c779cdSXin LI /* Note: we are after vfork, do not modify memory 113448c779cdSXin LI * in a way which confuses parent. In particular, 113548c779cdSXin LI * do not modify fdp[i][j]. 113648c779cdSXin LI */ 1137a4d6d3b8SXin LI handledesc(NULL, fd, fdp); 1138*898496eeSXin LI DPRINTF("Executing %s\n", compr[method].argv[0]); 113943a5ec4eSXin LI 1140a4d6d3b8SXin LI (void)execvp(compr[method].argv[0], args); 11413e41d09dSXin LI dprintf(STDERR_FILENO, "exec `%s' failed, %s", 11423e41d09dSXin LI compr[method].argv[0], strerror(errno)); 1143*898496eeSXin LI _exit(EXIT_FAILURE); /* _exit(), not exit(), because of vfork */ 114448c779cdSXin LI } 1145a4d6d3b8SXin LI #endif 114648c779cdSXin LI /* parent */ 114748c779cdSXin LI /* Close write sides of child stdout/err pipes */ 11483e41d09dSXin LI for (i = 1; i < __arraycount(fdp); i++) 11493e41d09dSXin LI closefd(fdp[i], 1); 115048c779cdSXin LI /* Write the buffer data to child stdin, if we don't have fd */ 115148c779cdSXin LI if (fd == -1) { 115248c779cdSXin LI closefd(fdp[STDIN_FILENO], 0); 115348c779cdSXin LI writepid = writechild(fdp[STDIN_FILENO][1], old, *n); 1154*898496eeSXin LI if (writepid == (pid_t)-1) { 1155*898496eeSXin LI rv = makeerror(newch, n, "Write to child failed, %s", 1156*898496eeSXin LI strerror(errno)); 1157*898496eeSXin LI DPRINTF("Write to child failed\n"); 1158*898496eeSXin LI goto err; 1159*898496eeSXin LI } 116048c779cdSXin LI closefd(fdp[STDIN_FILENO], 1); 116148c779cdSXin LI } 11623e41d09dSXin LI 1163*898496eeSXin LI rv = OKDATA; 1164*898496eeSXin LI r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0); 1165*898496eeSXin LI DPRINTF("read got %zd\n", r); 1166*898496eeSXin LI if (r < 0) { 1167*898496eeSXin LI rv = ERRDATA; 1168*898496eeSXin LI DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0], 11693e41d09dSXin LI strerror(errno)); 11703e41d09dSXin LI goto err; 11713e41d09dSXin LI } 1172*898496eeSXin LI if (CAST(size_t, r) == bytes_max) { 1173*898496eeSXin LI /* 1174*898496eeSXin LI * close fd so that the child exits with sigpipe and ignore 1175*898496eeSXin LI * errors, otherwise we risk the child blocking and never 1176*898496eeSXin LI * exiting. 1177*898496eeSXin LI */ 1178*898496eeSXin LI DPRINTF("Closing stdout for bytes_max\n"); 1179*898496eeSXin LI closefd(fdp[STDOUT_FILENO], 0); 1180a2dfb722SXin LI goto ok; 1181*898496eeSXin LI } 1182*898496eeSXin LI if ((re = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0) { 1183*898496eeSXin LI DPRINTF("Got stuff from stderr %s\n", *newch); 11843e41d09dSXin LI rv = ERRDATA; 11853e41d09dSXin LI r = filter_error(*newch, r); 118648c779cdSXin LI goto ok; 11873e41d09dSXin LI } 1188*898496eeSXin LI if (re == 0) 1189*898496eeSXin LI goto ok; 1190*898496eeSXin LI rv = makeerror(newch, n, "Read stderr failed, %s", 11913e41d09dSXin LI strerror(errno)); 11923e41d09dSXin LI goto err; 119348c779cdSXin LI ok: 11943e41d09dSXin LI *n = r; 11953e41d09dSXin LI /* NUL terminate, as every buffer is handled here. */ 11963e41d09dSXin LI (*newch)[*n] = '\0'; 11973e41d09dSXin LI err: 11983e41d09dSXin LI closefd(fdp[STDIN_FILENO], 1); 11993e41d09dSXin LI closefd(fdp[STDOUT_FILENO], 0); 12003e41d09dSXin LI closefd(fdp[STDERR_FILENO], 0); 120148c779cdSXin LI 120248c779cdSXin LI w = waitpid(pid, &status, 0); 120348c779cdSXin LI wait_err: 120448c779cdSXin LI if (w == -1) { 12053e41d09dSXin LI rv = makeerror(newch, n, "Wait failed, %s", strerror(errno)); 12063e41d09dSXin LI DPRINTF("Child wait return %#x\n", status); 12073e41d09dSXin LI } else if (!WIFEXITED(status)) { 120840427ccaSGordon Tetlow DPRINTF("Child not exited (%#x)\n", status); 12093e41d09dSXin LI } else if (WEXITSTATUS(status) != 0) { 121040427ccaSGordon Tetlow DPRINTF("Child exited (%#x)\n", WEXITSTATUS(status)); 12113e41d09dSXin LI } 121248c779cdSXin LI if (writepid > 0) { 121348c779cdSXin LI /* _After_ we know decompressor has exited, our input writer 121448c779cdSXin LI * definitely will exit now (at worst, writing fails in it, 121548c779cdSXin LI * since output fd is closed now on the reading size). 121648c779cdSXin LI */ 121748c779cdSXin LI w = waitpid(writepid, &status, 0); 121848c779cdSXin LI writepid = -1; 121948c779cdSXin LI goto wait_err; 122048c779cdSXin LI } 12213e41d09dSXin LI 122248c779cdSXin LI closefd(fdp[STDIN_FILENO], 0); //why? it is already closed here! 122348c779cdSXin LI DPRINTF("Returning %p n=%" SIZE_T_FORMAT "u rv=%d\n", *newch, *n, rv); 12243e41d09dSXin LI 12253e41d09dSXin LI return rv; 1226b6cee71dSXin LI } 1227b6cee71dSXin LI #endif 1228