[BACK]Return to compress.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / file

Annotation of src/usr.bin/file/compress.c, Revision 1.10

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