Annotation of src/usr.bin/file/compress.c, Revision 1.7
1.7 ! ian 1: /* $OpenBSD: compress.c,v 1.6 2003/03/03 22:24:08 ian Exp $ */
1.3 millert 2:
1.1 deraadt 3: /*
4: * compress routines:
5: * zmagic() - returns 0 if not recognized, uncompresses and prints
6: * information if recognized
7: * uncompress(method, old, n, newch) - uncompress old into new,
8: * using method, return sizeof new
1.7 ! ian 9: *
! 10: * Copyright (c) Ian F. Darwin 1986-1995.
! 11: * Software written by Ian F. Darwin and others;
! 12: * maintained 1995-present by Christos Zoulas and others.
! 13: *
! 14: * Redistribution and use in source and binary forms, with or without
! 15: * modification, are permitted provided that the following conditions
! 16: * are met:
! 17: * 1. Redistributions of source code must retain the above copyright
! 18: * notice immediately at the beginning of the file, without modification,
! 19: * this list of conditions, and the following disclaimer.
! 20: * 2. Redistributions in binary form must reproduce the above copyright
! 21: * notice, this list of conditions and the following disclaimer in the
! 22: * documentation and/or other materials provided with the distribution.
! 23: * 3. All advertising materials mentioning features or use of this software
! 24: * must display the following acknowledgement:
! 25: * This product includes software developed by Ian F. Darwin and others.
! 26: * 4. The name of the author may not be used to endorse or promote products
! 27: * derived from this software without specific prior written permission.
! 28: *
! 29: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 30: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 31: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 32: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
! 33: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 34: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 35: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 36: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 37: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 38: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 39: * SUCH DAMAGE.
1.1 deraadt 40: */
1.7 ! ian 41:
1.6 ian 42: #include "file.h"
43: #include <stdlib.h>
44: #ifdef HAVE_UNISTD_H
45: #include <unistd.h>
46: #endif
47: #include <string.h>
48: #ifdef HAVE_SYS_WAIT_H
1.4 mickey 49: #include <sys/wait.h>
1.6 ian 50: #endif
1.1 deraadt 51: #include <stdio.h>
52: #include <stdlib.h>
1.4 mickey 53: #include <err.h>
1.6 ian 54: #ifdef HAVE_LIBZ
55: #include <zlib.h>
56: #endif
1.1 deraadt 57:
58: static struct {
1.6 ian 59: const char *magic;
1.1 deraadt 60: int maglen;
1.6 ian 61: const char *const argv[3];
1.1 deraadt 62: int silent;
63: } compr[] = {
64: { "\037\235", 2, { "uncompress", "-c", NULL }, 0 }, /* compressed */
65: { "\037\213", 2, { "gzip", "-cdq", NULL }, 1 }, /* gzipped */
66: { "\037\236", 2, { "gzip", "-cdq", NULL }, 1 }, /* frozen */
67: { "\037\240", 2, { "gzip", "-cdq", NULL }, 1 }, /* SCO LZH */
68: /* the standard pack utilities do not accept standard input */
69: { "\037\036", 2, { "gzip", "-cdq", NULL }, 0 }, /* packed */
70: };
71:
72: static int ncompr = sizeof(compr) / sizeof(compr[0]);
73:
74:
1.6 ian 75: static int swrite(int, const void *, size_t);
76: static int sread(int, void *, size_t);
1.5 millert 77: static int uncompress(int, const unsigned char *, unsigned char **, int);
1.1 deraadt 78:
79: int
80: zmagic(buf, nbytes)
81: unsigned char *buf;
82: int nbytes;
83: {
84: unsigned char *newbuf;
85: int newsize;
86: int i;
87:
88: for (i = 0; i < ncompr; i++) {
89: if (nbytes < compr[i].maglen)
90: continue;
91: if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0)
92: break;
93: }
94:
95: if (i == ncompr)
96: return 0;
97:
98: if ((newsize = uncompress(i, buf, &newbuf, nbytes)) != 0) {
99: tryit(newbuf, newsize, 1);
100: free(newbuf);
101: printf(" (");
102: tryit(buf, nbytes, 0);
103: printf(")");
104: }
105: return 1;
106: }
107:
1.6 ian 108: /*
109: * `safe' write for sockets and pipes.
110: */
111: static int
112: swrite(int fd, const void *buf, size_t n)
113: {
114: int rv;
115: size_t rn = n;
116:
117: do
118: switch (rv = write(fd, buf, n)) {
119: case -1:
120: if (errno == EINTR)
121: continue;
122: return -1;
123: default:
124: n -= rv;
125: buf = ((const char *)buf) + rv;
126: break;
127: }
128: while (n > 0);
129: return rn;
130: }
131:
132: /*
133: * `safe' read for sockets and pipes.
134: */
135: static int
136: sread(int fd, void *buf, size_t n)
137: {
138: int rv;
139: size_t rn = n;
140:
141: do
142: switch (rv = read(fd, buf, n)) {
143: case -1:
144: if (errno == EINTR)
145: continue;
146: return -1;
147: case 0:
148: return rn - n;
149: default:
150: n -= rv;
151: buf = ((char *)buf) + rv;
152: break;
153: }
154: while (n > 0);
155: return rn;
156: }
157:
158: int
159: pipe2file(int fd, void *startbuf, size_t nbytes)
160: {
161: char buf[4096];
162: int r, tfd;
163:
164: (void)strcpy(buf, "/tmp/file.XXXXXX");
165: #ifndef HAVE_MKSTEMP
166: {
167: char *ptr = mktemp(buf);
168: tfd = open(ptr, O_RDWR|O_TRUNC|O_EXCL|O_CREAT, 0600);
169: r = errno;
170: (void)unlink(ptr);
171: errno = r;
172: }
173: #else
174: tfd = mkstemp(buf);
175: r = errno;
176: (void)unlink(buf);
177: errno = r;
178: #endif
179: if (tfd == -1) {
180: error("Can't create temporary file for pipe copy (%s)\n",
181: strerror(errno));
182: /*NOTREACHED*/
183: }
184:
185: if (swrite(tfd, startbuf, nbytes) != nbytes)
186: r = 1;
187: else {
188: while ((r = sread(fd, buf, sizeof(buf))) > 0)
189: if (swrite(tfd, buf, r) != r)
190: break;
191: }
192:
193: switch (r) {
194: case -1:
195: error("Error copying from pipe to temp file (%s)\n",
196: strerror(errno));
197: /*NOTREACHED*/
198: case 0:
199: break;
200: default:
201: error("Error while writing to temp file (%s)\n",
202: strerror(errno));
203: /*NOTREACHED*/
204: }
205:
206: /*
207: * We duplicate the file descriptor, because fclose on a
208: * tmpfile will delete the file, but any open descriptors
209: * can still access the phantom inode.
210: */
211: if ((fd = dup2(tfd, fd)) == -1) {
212: error("Couldn't dup destcriptor for temp file(%s)\n",
213: strerror(errno));
214: /*NOTREACHED*/
215: }
216: (void)close(tfd);
217: if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
218: error("Couldn't seek on temp file (%s)\n", strerror(errno));
219: /*NOTREACHED*/
220: }
221: return fd;
222: }
1.1 deraadt 223:
224: static int
225: uncompress(method, old, newch, n)
226: int method;
227: const unsigned char *old;
228: unsigned char **newch;
229: int n;
230: {
231: int fdin[2], fdout[2];
232:
233: if (pipe(fdin) == -1 || pipe(fdout) == -1) {
1.4 mickey 234: err(1, "cannot create pipe");
1.1 deraadt 235: /*NOTREACHED*/
236: }
237: switch (fork()) {
238: case 0: /* child */
239: (void) close(0);
240: (void) dup(fdin[0]);
241: (void) close(fdin[0]);
242: (void) close(fdin[1]);
243:
244: (void) close(1);
245: (void) dup(fdout[1]);
246: (void) close(fdout[0]);
247: (void) close(fdout[1]);
248: if (compr[method].silent)
249: (void) close(2);
250:
1.6 ian 251: execvp(compr[method].argv[0], (char *const *)compr[method].argv);
1.4 mickey 252: err(1, "could not execute `%s'", compr[method].argv[0]);
1.1 deraadt 253: /*NOTREACHED*/
254: case -1:
1.4 mickey 255: err(1, "could not fork");
1.1 deraadt 256: /*NOTREACHED*/
257:
258: default: /* parent */
259: (void) close(fdin[0]);
260: (void) close(fdout[1]);
261: if (write(fdin[1], old, n) != n) {
1.4 mickey 262: err(1, "write failed");
1.1 deraadt 263: /*NOTREACHED*/
264: }
265: (void) close(fdin[1]);
266: if ((*newch = (unsigned char *) malloc(n)) == NULL) {
1.4 mickey 267: err(1, "malloc");
1.1 deraadt 268: /*NOTREACHED*/
269: }
270: if ((n = read(fdout[0], *newch, n)) <= 0) {
271: free(*newch);
1.4 mickey 272: err(1, "read failed");
1.1 deraadt 273: /*NOTREACHED*/
274: }
275: (void) close(fdout[0]);
276: (void) wait(NULL);
277: return n;
278: }
279: }