[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.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: }