summaryrefslogtreecommitdiff
path: root/usr.bin/file/compress.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/file/compress.c')
-rw-r--r--usr.bin/file/compress.c140
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: