diff options
Diffstat (limited to 'contrib/file/compress.c')
-rw-r--r-- | contrib/file/compress.c | 83 |
1 files changed, 75 insertions, 8 deletions
diff --git a/contrib/file/compress.c b/contrib/file/compress.c index 5f18d82..e84d62d 100644 --- a/contrib/file/compress.c +++ b/contrib/file/compress.c @@ -16,7 +16,7 @@ #include <sys/wait.h> #endif #ifndef lint -FILE_RCSID("@(#)$Id: compress.c,v 1.17 2000/08/05 17:36:47 christos Exp $") +FILE_RCSID("@(#)$Id: compress.c,v 1.19 2001/03/20 04:22:02 christos Exp $") #endif @@ -26,8 +26,10 @@ static struct { const char *const argv[3]; int silent; } compr[] = { - { "\037\235", 2, { "uncompress", "-c", NULL }, 0 }, /* compressed */ { "\037\235", 2, { "gzip", "-cdq", NULL }, 1 }, /* compressed */ + /* Uncompress can get stuck; so use gzip first if we have it + * Idea from Damien Clark, thanks! */ + { "\037\235", 2, { "uncompress", "-c", NULL }, 1 }, /* compressed */ { "\037\213", 2, { "gzip", "-cdq", NULL }, 1 }, /* gzipped */ { "\037\236", 2, { "gzip", "-cdq", NULL }, 1 }, /* frozen */ { "\037\240", 2, { "gzip", "-cdq", NULL }, 1 }, /* SCO LZH */ @@ -40,6 +42,8 @@ static int ncompr = sizeof(compr) / sizeof(compr[0]); static int uncompress __P((int, const unsigned char *, unsigned char **, int)); +static int swrite __P((int, const void *, size_t)); +static int sread __P((int, void *, size_t)); int zmagic(buf, nbytes) @@ -70,6 +74,60 @@ zmagic(buf, nbytes) return 1; } +/* + * `safe' write for sockets and pipes. + */ +static int +swrite(fd, buf, n) + 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 = ((char *)buf) + rv; + break; + } + while (n > 0); + return rn; +} + + +/* + * `safe' read for sockets and pipes. + */ +static int +sread(fd, buf, n) + 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; + default: + n -= rv; + buf = ((char *)buf) + rv; + break; + } + while (n > 0); + return rn; +} static int uncompress(method, old, newch, n) @@ -109,15 +167,24 @@ uncompress(method, old, newch, n) default: /* parent */ (void) close(fdin[0]); (void) close(fdout[1]); - if (write(fdin[1], old, n) != n) - return 0; + if (swrite(fdin[1], old, n) != n) { + n = 0; + goto err; + } (void) close(fdin[1]); - if ((*newch = (unsigned char *) malloc(n)) == NULL) - return 0; - if ((n = read(fdout[0], *newch, n)) <= 0) { + fdin[1] = -1; + if ((*newch = (unsigned char *) malloc(n)) == NULL) { + n = 0; + goto err; + } + if ((n = sread(fdout[0], *newch, n)) <= 0) { free(*newch); - return 0; + n = 0; + goto err; } +err: + if (fdin[1] != -1) + (void) close(fdin[1]); (void) close(fdout[0]); (void) wait(NULL); return n; |