diff options
Diffstat (limited to 'usr.bin/file/compress.c')
-rw-r--r-- | usr.bin/file/compress.c | 140 |
1 files changed, 132 insertions, 8 deletions
diff --git a/usr.bin/file/compress.c b/usr.bin/file/compress.c index 081cf713c51..3d7d1e13266 100644 --- a/usr.bin/file/compress.c +++ b/usr.bin/file/compress.c @@ -1,4 +1,4 @@ -/* $OpenBSD: compress.c,v 1.5 2002/02/16 21:27:46 millert Exp $ */ +/* $OpenBSD: compress.c,v 1.6 2003/03/03 22:24:08 ian Exp $ */ /* * compress routines: @@ -7,19 +7,26 @@ * uncompress(method, old, n, newch) - uncompress old into new, * using method, return sizeof new */ -#include <sys/wait.h> -#include <stdio.h> +#include "file.h" #include <stdlib.h> +#ifdef HAVE_UNISTD_H #include <unistd.h> +#endif #include <string.h> +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#include <stdio.h> +#include <stdlib.h> #include <err.h> - -#include "file.h" +#ifdef HAVE_LIBZ +#include <zlib.h> +#endif static struct { - char *magic; + const char *magic; int maglen; - char *argv[3]; + const char *const argv[3]; int silent; } compr[] = { { "\037\235", 2, { "uncompress", "-c", NULL }, 0 }, /* compressed */ @@ -33,6 +40,8 @@ static struct { static int ncompr = sizeof(compr) / sizeof(compr[0]); +static int swrite(int, const void *, size_t); +static int sread(int, void *, size_t); static int uncompress(int, const unsigned char *, unsigned char **, int); int @@ -64,6 +73,121 @@ int nbytes; return 1; } +/* + * `safe' write for sockets and pipes. + */ +static int +swrite(int fd, const void *buf, size_t n) +{ + int rv; + size_t rn = n; + + do + switch (rv = write(fd, buf, n)) { + case -1: + if (errno == EINTR) + continue; + return -1; + default: + n -= rv; + buf = ((const char *)buf) + rv; + break; + } + while (n > 0); + return rn; +} + +/* + * `safe' read for sockets and pipes. + */ +static int +sread(int fd, void *buf, size_t n) +{ + int rv; + size_t rn = n; + + do + switch (rv = read(fd, buf, n)) { + case -1: + if (errno == EINTR) + continue; + return -1; + case 0: + return rn - n; + default: + n -= rv; + buf = ((char *)buf) + rv; + break; + } + while (n > 0); + return rn; +} + +int +pipe2file(int fd, void *startbuf, size_t nbytes) +{ + char buf[4096]; + int r, tfd; + + (void)strcpy(buf, "/tmp/file.XXXXXX"); +#ifndef HAVE_MKSTEMP + { + char *ptr = mktemp(buf); + tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600); + r = errno; + (void)unlink(ptr); + errno = r; + } +#else + tfd = mkstemp(buf); + r = errno; + (void)unlink(buf); + errno = r; +#endif + if (tfd == -1) { + error("Can't create temporary file for pipe copy (%s)\n", + strerror(errno)); + /*NOTREACHED*/ + } + + if (swrite(tfd, startbuf, nbytes) != nbytes) + r = 1; + else { + while ((r = sread(fd, buf, sizeof(buf))) > 0) + if (swrite(tfd, buf, r) != r) + break; + } + + switch (r) { + case -1: + error("Error copying from pipe to temp file (%s)\n", + strerror(errno)); + /*NOTREACHED*/ + case 0: + break; + default: + error("Error while writing to temp file (%s)\n", + strerror(errno)); + /*NOTREACHED*/ + } + + /* + * We duplicate the file descriptor, because fclose on a + * tmpfile will delete the file, but any open descriptors + * can still access the phantom inode. + */ + if ((fd = dup2(tfd, fd)) == -1) { + error("Couldn't dup destcriptor for temp file(%s)\n", + strerror(errno)); + /*NOTREACHED*/ + } + (void)close(tfd); + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { + error("Couldn't seek on temp file (%s)\n", strerror(errno)); + /*NOTREACHED*/ + } + return fd; +} static int uncompress(method, old, newch, n) @@ -92,7 +216,7 @@ int n; if (compr[method].silent) (void) close(2); - execvp(compr[method].argv[0], compr[method].argv); + execvp(compr[method].argv[0], (char *const *)compr[method].argv); err(1, "could not execute `%s'", compr[method].argv[0]); /*NOTREACHED*/ case -1: |