diff options
author | 2008-05-08 01:40:56 +0000 | |
---|---|---|
committer | 2008-05-08 01:40:56 +0000 | |
commit | 380b5c7d6f55f6a87af6c6189307b5cf65aa3391 (patch) | |
tree | 585bbc19cfb13bc3f8c9f0b4691efa3b0f1d7d41 /usr.bin/file/compress.c | |
parent | fix TIOCSIG definition; from Hannah Schroeter <hannah at schlund dot de> (diff) | |
download | wireguard-openbsd-380b5c7d6f55f6a87af6c6189307b5cf65aa3391.tar.xz wireguard-openbsd-380b5c7d6f55f6a87af6c6189307b5cf65aa3391.zip |
Update file to 4.21.
tested by ian@ sthen@
OK ian@, "move ahead with it" deraadt@
Diffstat (limited to 'usr.bin/file/compress.c')
-rw-r--r-- | usr.bin/file/compress.c | 185 |
1 files changed, 134 insertions, 51 deletions
diff --git a/usr.bin/file/compress.c b/usr.bin/file/compress.c index 1c70d56bb5b..a17a1d32861 100644 --- a/usr.bin/file/compress.c +++ b/usr.bin/file/compress.c @@ -1,4 +1,4 @@ -/* $OpenBSD: compress.c,v 1.11 2004/05/19 02:32:35 tedu Exp $ */ +/* $OpenBSD: compress.c,v 1.12 2008/05/08 01:40:56 chl Exp $ */ /* * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; @@ -43,19 +43,22 @@ #include <string.h> #include <errno.h> #include <sys/types.h> +#include <sys/ioctl.h> #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> #endif -#undef HAVE_LIBZ +#if defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#endif #ifdef HAVE_LIBZ #include <zlib.h> #endif + #ifndef lint -FILE_RCSID("@(#)$Id: compress.c,v 1.11 2004/05/19 02:32:35 tedu Exp $") +FILE_RCSID("@(#)$Id: compress.c,v 1.12 2008/05/08 01:40:56 chl Exp $") #endif - private struct { const char *magic; size_t maglen; @@ -71,23 +74,27 @@ private struct { { "\037\240", 2, { "gzip", "-cdq", NULL }, 1 }, /* SCO LZH */ /* the standard pack utilities do not accept standard input */ { "\037\036", 2, { "gzip", "-cdq", NULL }, 0 }, /* packed */ + { "PK\3\4", 4, { "gzip", "-cdq", NULL }, 1 }, /* pkzipped, */ + /* ...only first file examined */ { "BZh", 3, { "bzip2", "-cd", NULL }, 1 }, /* bzip2-ed */ }; -private int ncompr = sizeof(compr) / sizeof(compr[0]); +private size_t ncompr = sizeof(compr) / sizeof(compr[0]); + +#define NODATA ((size_t)~0) private ssize_t swrite(int, const void *, size_t); -private ssize_t sread(int, void *, size_t); -private size_t uncompressbuf(struct magic_set *, size_t, const unsigned char *, - unsigned char **, size_t); +private size_t uncompressbuf(struct magic_set *, int, size_t, + const unsigned char *, unsigned char **, size_t); #ifdef HAVE_LIBZ private size_t uncompressgzipped(struct magic_set *, const unsigned char *, unsigned char **, size_t); #endif protected int -file_zmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes) +file_zmagic(struct magic_set *ms, int fd, const char *name, + const unsigned char *buf, size_t nbytes) { unsigned char *newbuf = NULL; size_t i, nsz; @@ -100,14 +107,15 @@ file_zmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes) if (nbytes < compr[i].maglen) continue; if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0 && - (nsz = uncompressbuf(ms, i, buf, &newbuf, nbytes)) != 0) { + (nsz = uncompressbuf(ms, fd, i, buf, &newbuf, + nbytes)) != NODATA) { ms->flags &= ~MAGIC_COMPRESS; rv = -1; - if (file_buffer(ms, newbuf, nsz) == -1) + if (file_buffer(ms, -1, name, newbuf, nsz) == -1) goto error; if (file_printf(ms, " (") == -1) goto error; - if (file_buffer(ms, buf, nbytes) == -1) + if (file_buffer(ms, -1, NULL, buf, nbytes) == -1) goto error; if (file_printf(ms, ")") == -1) goto error; @@ -150,14 +158,55 @@ swrite(int fd, const void *buf, size_t n) /* * `safe' read for sockets and pipes. */ -private ssize_t -sread(int fd, void *buf, size_t n) +protected ssize_t +sread(int fd, void *buf, size_t n, int canbepipe) { - int rv; + int rv, cnt; +#ifdef FIONREAD + int t = 0; +#endif size_t rn = n; + if (fd == STDIN_FILENO) + goto nocheck; + +#ifdef FIONREAD + if ((canbepipe && (ioctl(fd, FIONREAD, &t) == -1)) || (t == 0)) { +#ifdef FD_ZERO + for (cnt = 0;; cnt++) { + fd_set check; + struct timeval tout = {0, 100 * 1000}; + int selrv; + + FD_ZERO(&check); + FD_SET(fd, &check); + + /* + * Avoid soft deadlock: do not read if there + * is nothing to read from sockets and pipes. + */ + selrv = select(fd + 1, &check, NULL, NULL, &tout); + if (selrv == -1) { + if (errno == EINTR || errno == EAGAIN) + continue; + } else if (selrv == 0 && cnt >= 5) { + return 0; + } else + break; + } +#endif + (void)ioctl(fd, FIONREAD, &t); + } + + if (t > 0 && (size_t)t < n) { + n = t; + rn = n; + } +#endif + +nocheck: do - switch (rv = read(fd, buf, n)) { + switch ((rv = read(fd, buf, n))) { case -1: if (errno == EINTR) continue; @@ -204,7 +253,7 @@ file_pipe2file(struct magic_set *ms, int fd, const void *startbuf, if (swrite(tfd, startbuf, nbytes) != (ssize_t)nbytes) r = 1; else { - while ((r = sread(fd, buf, sizeof(buf))) > 0) + while ((r = sread(fd, buf, sizeof(buf), 1)) > 0) if (swrite(tfd, buf, (size_t)r) != r) break; } @@ -300,82 +349,116 @@ uncompressgzipped(struct magic_set *ms, const unsigned char *old, } n = (size_t)z.total_out; - inflateEnd(&z); + (void)inflateEnd(&z); /* let's keep the nul-terminate tradition */ - (*newch)[n++] = '\0'; + (*newch)[n] = '\0'; return n; } #endif private size_t -uncompressbuf(struct magic_set *ms, size_t method, const unsigned char *old, - unsigned char **newch, size_t n) +uncompressbuf(struct magic_set *ms, int fd, size_t method, + const unsigned char *old, unsigned char **newch, size_t n) { int fdin[2], fdout[2]; int r; - /* The buffer is NUL terminated, and we don't need that. */ - n--; - #ifdef HAVE_LIBZ if (method == 2) return uncompressgzipped(ms, old, newch, n); #endif + (void)fflush(stdout); + (void)fflush(stderr); - if (pipe(fdin) == -1 || pipe(fdout) == -1) { + if ((fd != -1 && pipe(fdin) == -1) || pipe(fdout) == -1) { file_error(ms, errno, "cannot create pipe"); - return 0; + return NODATA; } switch (fork()) { case 0: /* child */ (void) close(0); - (void) dup(fdin[0]); - (void) close(fdin[0]); - (void) close(fdin[1]); + if (fd != -1) { + (void) dup(fd); + (void) lseek(0, (off_t)0, SEEK_SET); + } else { + (void) dup(fdin[0]); + (void) close(fdin[0]); + (void) close(fdin[1]); + } (void) close(1); (void) dup(fdout[1]); (void) close(fdout[0]); (void) close(fdout[1]); +#ifndef DEBUG if (compr[method].silent) - (void) close(2); + (void)close(2); +#endif - execvp(compr[method].argv[0], - (char *const *)compr[method].argv); + (void)execvp(compr[method].argv[0], + (char *const *)(intptr_t)compr[method].argv); +#ifdef DEBUG + (void)fprintf(stderr, "exec `%s' failed (%s)\n", + compr[method].argv[0], strerror(errno)); +#endif exit(1); /*NOTREACHED*/ case -1: file_error(ms, errno, "could not fork"); - return 0; + return NODATA; default: /* parent */ - (void) close(fdin[0]); (void) close(fdout[1]); - /* fork again, to avoid blocking because both pipes filled */ - switch (fork()) { - case 0: /* child */ - (void)close(fdout[0]); - if (swrite(fdin[1], old, n) != n) + if (fd == -1) { + (void) close(fdin[0]); + /* + * fork again, to avoid blocking because both + * pipes filled + */ + switch (fork()) { + case 0: /* child */ + (void)close(fdout[0]); + if (swrite(fdin[1], old, n) != (ssize_t)n) { +#ifdef DEBUG + (void)fprintf(stderr, + "Write failed (%s)\n", + strerror(errno)); +#endif + exit(1); + } + exit(0); + /*NOTREACHED*/ + + case -1: +#ifdef DEBUG + (void)fprintf(stderr, "Fork failed (%s)\n", + strerror(errno)); +#endif exit(1); - exit(0); - /*NOTREACHED*/ + /*NOTREACHED*/ - case -1: - exit(1); - /*NOTREACHED*/ - - default: /* parent */ - break; + default: /* parent */ + break; + } + (void) close(fdin[1]); + fdin[1] = -1; } - (void) close(fdin[1]); - fdin[1] = -1; + if ((*newch = (unsigned char *) malloc(HOWMANY + 1)) == NULL) { +#ifdef DEBUG + (void)fprintf(stderr, "Malloc failed (%s)\n", + strerror(errno)); +#endif n = 0; goto err; } - if ((r = sread(fdout[0], *newch, HOWMANY)) <= 0) { + if ((r = sread(fdout[0], *newch, HOWMANY, 0)) <= 0) { +#ifdef DEBUG + (void)fprintf(stderr, "Read failed (%s)\n", + strerror(errno)); +#endif free(*newch); n = 0; newch[0] = '\0'; @@ -384,7 +467,7 @@ uncompressbuf(struct magic_set *ms, size_t method, const unsigned char *old, n = r; } /* NUL terminate, as every buffer is handled here. */ - (*newch)[n++] = '\0'; + (*newch)[n] = '\0'; err: if (fdin[1] != -1) (void) close(fdin[1]); |