summaryrefslogtreecommitdiffstats
path: root/contrib/file/compress.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/file/compress.c')
-rw-r--r--contrib/file/compress.c191
1 files changed, 164 insertions, 27 deletions
diff --git a/contrib/file/compress.c b/contrib/file/compress.c
index 80d24e0..4e1219c 100644
--- a/contrib/file/compress.c
+++ b/contrib/file/compress.c
@@ -6,7 +6,6 @@
* using method, return sizeof new
*/
#include "file.h"
-#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -15,8 +14,12 @@
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
+#ifdef HAVE_LIBZ
+#include <zlib.h>
+#endif
+
#ifndef lint
-FILE_RCSID("@(#)$Id: compress.c,v 1.20 2001/07/22 21:04:15 christos Exp $")
+FILE_RCSID("@(#)$Id: compress.c,v 1.25 2002/07/03 18:26:37 christos Exp $")
#endif
@@ -41,14 +44,15 @@ static struct {
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));
+static int swrite(int, const void *, size_t);
+static int sread(int, void *, size_t);
+static int uncompressbuf(int, const unsigned char *, unsigned char **, int);
+#ifdef HAVE_LIBZ
+static int uncompressgzipped(const unsigned char *, unsigned char **, int);
+#endif
int
-zmagic(buf, nbytes)
- unsigned char *buf;
- int nbytes;
+zmagic(const char *fname, unsigned char *buf, int nbytes)
{
unsigned char *newbuf;
int newsize;
@@ -58,11 +62,11 @@ zmagic(buf, nbytes)
if (nbytes < compr[i].maglen)
continue;
if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0 &&
- (newsize = uncompress(i, buf, &newbuf, nbytes)) != 0) {
- tryit(newbuf, newsize, 1);
+ (newsize = uncompressbuf(i, buf, &newbuf, nbytes)) != 0) {
+ tryit(fname, newbuf, newsize, 1);
free(newbuf);
printf(" (");
- tryit(buf, nbytes, 0);
+ tryit(fname, buf, nbytes, 0);
printf(")");
return 1;
}
@@ -78,10 +82,7 @@ zmagic(buf, nbytes)
* `safe' write for sockets and pipes.
*/
static int
-swrite(fd, buf, n)
- int fd;
- const void *buf;
- size_t n;
+swrite(int fd, const void *buf, size_t n)
{
int rv;
size_t rn = n;
@@ -94,7 +95,7 @@ swrite(fd, buf, n)
return -1;
default:
n -= rv;
- buf = ((char *)buf) + rv;
+ buf = ((const char *)buf) + rv;
break;
}
while (n > 0);
@@ -106,10 +107,7 @@ swrite(fd, buf, n)
* `safe' read for sockets and pipes.
*/
static int
-sread(fd, buf, n)
- int fd;
- void *buf;
- size_t n;
+sread(int fd, void *buf, size_t n)
{
int rv;
size_t rn = n;
@@ -120,6 +118,8 @@ sread(fd, buf, n)
if (errno == EINTR)
continue;
return -1;
+ case 0:
+ return rn - n;
default:
n -= rv;
buf = ((char *)buf) + rv;
@@ -129,15 +129,150 @@ sread(fd, buf, n)
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;
+}
+
+#ifdef HAVE_LIBZ
+
+#define FHCRC (1 << 1)
+#define FEXTRA (1 << 2)
+#define FNAME (1 << 3)
+#define FCOMMENT (1 << 4)
+
+static int
+uncompressgzipped(const unsigned char *old, unsigned char **newch, int n)
+{
+ unsigned char flg = old[3];
+ int data_start = 10;
+ z_stream z;
+ int rc;
+
+ if (flg & FEXTRA)
+ data_start += 2 + old[data_start] + old[data_start + 1] * 256;
+ if (flg & FNAME) {
+ while(old[data_start])
+ data_start++;
+ data_start++;
+ }
+ if(flg & FCOMMENT) {
+ while(old[data_start])
+ data_start++;
+ data_start++;
+ }
+ if(flg & FHCRC)
+ data_start += 2;
+
+ if ((*newch = (unsigned char *)malloc(HOWMANY + 1)) == NULL) {
+ return 0;
+ }
+
+ z.next_in = (Bytef *)(old + data_start);
+ z.avail_in = n - data_start;
+ z.next_out = *newch;
+ z.avail_out = HOWMANY;
+ z.zalloc = Z_NULL;
+ z.zfree = Z_NULL;
+ z.opaque = Z_NULL;
+
+ rc = inflateInit2(&z, -15);
+ if (rc != Z_OK) {
+ (void) fprintf(stderr,"%s: zlib: %s\n", progname, z.msg);
+ return 0;
+ }
+
+ rc = inflate(&z, Z_SYNC_FLUSH);
+ if (rc != Z_OK && rc != Z_STREAM_END) {
+ fprintf(stderr,"%s: zlib: %s\n", progname, z.msg);
+ return 0;
+ }
+
+ n = z.total_out;
+ inflateEnd(&z);
+
+ /* let's keep the nul-terminate tradition */
+ (*newch)[n++] = '\0';
+
+ return n;
+}
+#endif
+
static int
-uncompress(method, old, newch, n)
- int method;
- const unsigned char *old;
- unsigned char **newch;
- int n;
+uncompressbuf(int method, const unsigned char *old, unsigned char **newch,
+ int n)
{
int fdin[2], fdout[2];
+ /* The buffer is NUL terminated, and we don't need that. */
+ n--;
+
+#ifdef HAVE_LIBZ
+ if (method == 2)
+ return uncompressgzipped(old,newch,n);
+#endif
+
if (pipe(fdin) == -1 || pipe(fdout) == -1) {
error("cannot create pipe (%s).\n", strerror(errno));
/*NOTREACHED*/
@@ -173,15 +308,17 @@ uncompress(method, old, newch, n)
}
(void) close(fdin[1]);
fdin[1] = -1;
- if ((*newch = (unsigned char *) malloc(n)) == NULL) {
+ if ((*newch = (unsigned char *) malloc(HOWMANY + 1)) == NULL) {
n = 0;
goto err;
}
- if ((n = sread(fdout[0], *newch, n)) <= 0) {
+ if ((n = sread(fdout[0], *newch, HOWMANY)) <= 0) {
free(*newch);
n = 0;
goto err;
}
+ /* NUL terminate, as every buffer is handled here. */
+ (*newch)[n++] = '\0';
err:
if (fdin[1] != -1)
(void) close(fdin[1]);
OpenPOWER on IntegriCloud