version 1.5, 2002/02/16 21:27:46 |
version 1.6, 2003/03/03 22:24:08 |
|
|
* uncompress(method, old, n, newch) - uncompress old into new, |
* uncompress(method, old, n, newch) - uncompress old into new, |
* using method, return sizeof new |
* using method, return sizeof new |
*/ |
*/ |
#include <sys/wait.h> |
#include "file.h" |
#include <stdio.h> |
|
#include <stdlib.h> |
#include <stdlib.h> |
|
#ifdef HAVE_UNISTD_H |
#include <unistd.h> |
#include <unistd.h> |
|
#endif |
#include <string.h> |
#include <string.h> |
|
#ifdef HAVE_SYS_WAIT_H |
|
#include <sys/wait.h> |
|
#endif |
|
#include <stdio.h> |
|
#include <stdlib.h> |
#include <err.h> |
#include <err.h> |
|
#ifdef HAVE_LIBZ |
|
#include <zlib.h> |
|
#endif |
|
|
#include "file.h" |
|
|
|
static struct { |
static struct { |
char *magic; |
const char *magic; |
int maglen; |
int maglen; |
char *argv[3]; |
const char *const argv[3]; |
int silent; |
int silent; |
} compr[] = { |
} compr[] = { |
{ "\037\235", 2, { "uncompress", "-c", NULL }, 0 }, /* compressed */ |
{ "\037\235", 2, { "uncompress", "-c", NULL }, 0 }, /* compressed */ |
|
|
static int ncompr = sizeof(compr) / sizeof(compr[0]); |
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); |
static int uncompress(int, const unsigned char *, unsigned char **, int); |
|
|
int |
int |
|
|
return 1; |
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 |
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) |
uncompress(method, old, newch, n) |
int method; |
int method; |
const unsigned char *old; |
const unsigned char *old; |
|
|
if (compr[method].silent) |
if (compr[method].silent) |
(void) close(2); |
(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]); |
err(1, "could not execute `%s'", compr[method].argv[0]); |
/*NOTREACHED*/ |
/*NOTREACHED*/ |
case -1: |
case -1: |