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

Annotation of src/usr.bin/compress/gzopen.c, Revision 1.1

1.1     ! mickey      1: /*     $OpenBSD$       */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997 Michael Shalayeff
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Michael Shalayeff.
        !            18:  * 4. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  */
        !            34: /* this is partially derived from the zlib's gzio.c file, so the notice: */
        !            35: /*
        !            36:   zlib.h -- interface of the 'zlib' general purpose compression library
        !            37:   version 1.0.4, Jul 24th, 1996.
        !            38:
        !            39:   Copyright (C) 1995-1996 Jean-loup Gailly and Mark Adler
        !            40:
        !            41:   This software is provided 'as-is', without any express or implied
        !            42:   warranty.  In no event will the authors be held liable for any damages
        !            43:   arising from the use of this software.
        !            44:
        !            45:   Permission is granted to anyone to use this software for any purpose,
        !            46:   including commercial applications, and to alter it and redistribute it
        !            47:   freely, subject to the following restrictions:
        !            48:
        !            49:   1. The origin of this software must not be misrepresented; you must not
        !            50:      claim that you wrote the original software. If you use this software
        !            51:      in a product, an acknowledgment in the product documentation would be
        !            52:      appreciated but is not required.
        !            53:   2. Altered source versions must be plainly marked as such, and must not be
        !            54:      misrepresented as being the original software.
        !            55:   3. This notice may not be removed or altered from any source distribution.
        !            56:
        !            57:   Jean-loup Gailly        Mark Adler
        !            58:   gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
        !            59:
        !            60:
        !            61:   The data format used by the zlib library is described by RFCs (Request for
        !            62:   Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
        !            63:   (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
        !            64: */
        !            65:
        !            66: #include <sys/types.h>
        !            67: #include <sys/stat.h>
        !            68: #include <stdio.h>
        !            69: #include <stdlib.h>
        !            70: #include <errno.h>
        !            71: #include <unistd.h>
        !            72: #include <zlib.h>
        !            73: #include "compress.h"
        !            74:
        !            75: /* gzip flag byte */
        !            76: #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
        !            77: #define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
        !            78: #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
        !            79: #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
        !            80: #define COMMENT      0x10 /* bit 4 set: file comment present */
        !            81: #define RESERVED     0xE0 /* bits 5..7: reserved */
        !            82:
        !            83: #define DEF_MEM_LEVEL 8
        !            84: #define OS_CODE 0x03 /* unix */
        !            85:
        !            86: typedef
        !            87: struct gz_stream {
        !            88:        int     z_fd;           /* .gz file */
        !            89:        z_stream z_stream;      /* libz stream */
        !            90:        int     z_eof;          /* set if end of input file */
        !            91:        u_char  z_buf[Z_BUFSIZE]; /* i/o buffer */
        !            92:        u_int32_t z_crc;        /* crc32 of uncompressed data */
        !            93:        char    z_mode;         /* 'w' or 'r' */
        !            94:
        !            95: } gz_stream;
        !            96:
        !            97: static u_char gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
        !            98:
        !            99: static int put_int32 __P((register gz_stream *, u_int32_t));
        !           100: static u_int32_t get_int32 __P((register gz_stream *));
        !           101: static int get_header __P((register gz_stream *));
        !           102: static int get_byte __P((register gz_stream *));
        !           103:
        !           104: int
        !           105: gz_check_header(fd, sb, ofn)
        !           106:        int fd;
        !           107:        struct stat *sb;
        !           108:        const char *ofn;
        !           109: {
        !           110:        int f;
        !           111:        u_char buf[sizeof(gz_magic)];
        !           112:        off_t off = lseek(fd, 0, SEEK_CUR);
        !           113:
        !           114:        f = (read(fd, buf, sizeof(buf)) == sizeof(buf) &&
        !           115:             !memcmp(buf, gz_magic, sizeof(buf)));
        !           116:
        !           117:        lseek (fd, off, SEEK_SET);
        !           118:
        !           119:        return f;
        !           120: }
        !           121:
        !           122: void *
        !           123: gz_open (fd, mode, bits)
        !           124:        int fd;
        !           125:        const char *mode;
        !           126:        int  bits;
        !           127: {
        !           128:        gz_stream *s;
        !           129:
        !           130:        if (fd < 0 || !mode)
        !           131:                return NULL;
        !           132:
        !           133:        if ((mode[0] != 'r' && mode[0] != 'w') || mode[1] != '\0' ||
        !           134:            bits < 0 || bits > Z_BEST_COMPRESSION) {
        !           135:                errno = EINVAL;
        !           136:                return NULL;
        !           137:        }
        !           138:        if ((s = (gz_stream *)calloc(sizeof(gz_stream), 1)) == NULL)
        !           139:                return NULL;
        !           140:
        !           141:        s->z_stream.zalloc = (alloc_func)0;
        !           142:        s->z_stream.zfree = (free_func)0;
        !           143:        s->z_stream.opaque = (voidpf)0;
        !           144:        s->z_stream.next_in = Z_NULL;
        !           145:        s->z_stream.next_out = Z_NULL;
        !           146:        s->z_stream.avail_in = s->z_stream.avail_out = 0;
        !           147:        s->z_fd = 0;
        !           148:        s->z_eof = 0;
        !           149:        s->z_crc = crc32(0L, Z_NULL, 0);
        !           150:        s->z_mode = mode[0];
        !           151:
        !           152:        if (s->z_mode == 'w') {
        !           153:                /* windowBits is passed < 0 to suppress zlib header */
        !           154:                if (deflateInit2(&(s->z_stream), bits, Z_DEFLATED,
        !           155:                                 -MAX_WBITS, DEF_MEM_LEVEL, 0) != Z_OK) {
        !           156:                        free (s);
        !           157:                        return NULL;
        !           158:                }
        !           159:                s->z_stream.next_out = s->z_buf;
        !           160:        } else {
        !           161:                if (inflateInit2(&(s->z_stream), -MAX_WBITS) != Z_OK) {
        !           162:                        free (s);
        !           163:                        return NULL;
        !           164:                }
        !           165:                s->z_stream.next_in = s->z_buf;
        !           166:        }
        !           167:        s->z_stream.avail_out = Z_BUFSIZE;
        !           168:
        !           169:        errno = 0;
        !           170:        s->z_fd = fd;
        !           171:
        !           172:        if (s->z_mode == 'w') {
        !           173:                u_char buf[10];
        !           174:                /* Write a very simple .gz header: */
        !           175:                buf[0] = gz_magic[0];
        !           176:                buf[1] = gz_magic[1];
        !           177:                buf[2] = Z_DEFLATED;
        !           178:                buf[3] = 0 /*flags*/;
        !           179:                buf[4] = buf[5] = buf[6] = buf[7] = 0 /*time*/;
        !           180:                buf[8] = 0 /*xflags*/;
        !           181:                buf[9] = OS_CODE;
        !           182:                if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
        !           183:                        gz_close(s);
        !           184:                        s = NULL;
        !           185:                }
        !           186:        } else {
        !           187:                if (get_header(s) != 0) { /* skip the .gz header */
        !           188:                        gz_close (s);
        !           189:                        s = NULL;
        !           190:                }
        !           191:        }
        !           192:
        !           193:        return s;
        !           194: }
        !           195:
        !           196: int
        !           197: gz_close (cookie)
        !           198:        void *cookie;
        !           199: {
        !           200:        register gz_stream *s = (gz_stream*)cookie;
        !           201:        int err = 0;
        !           202:
        !           203:        if (s == NULL)
        !           204:                return -1;
        !           205:
        !           206:        if (s->z_mode == 'w' && (err = gz_flush (s, Z_FINISH)) == Z_OK) {
        !           207:                if ((err = put_int32 (s, s->z_crc)) == Z_OK)
        !           208:                        err = put_int32 (s, s->z_stream.total_in);
        !           209:        }
        !           210:
        !           211:        if (!err && s->z_stream.state != NULL) {
        !           212:                if (s->z_mode == 'w')
        !           213:                        err = deflateEnd(&s->z_stream);
        !           214:                else if (s->z_mode == 'r')
        !           215:                        err = inflateEnd(&s->z_stream);
        !           216:        }
        !           217:
        !           218:        free(s);
        !           219:
        !           220:        return err;
        !           221: }
        !           222:
        !           223: int
        !           224: gz_flush (cookie, flush)
        !           225:     void *cookie;
        !           226:     int flush;
        !           227: {
        !           228:        register gz_stream *s = (gz_stream*)cookie;
        !           229:        size_t len;
        !           230:        int done = 0;
        !           231:        int err;
        !           232:
        !           233:        if (s == NULL || s->z_mode != 'w') {
        !           234:                errno = EBADF;
        !           235:                return Z_ERRNO;
        !           236:        }
        !           237:
        !           238:        s->z_stream.avail_in = 0; /* should be zero already anyway */
        !           239:
        !           240:        for (;;) {
        !           241:                len = Z_BUFSIZE - s->z_stream.avail_out;
        !           242:
        !           243:                if (len != 0) {
        !           244:                        if (write(s->z_fd, s->z_buf, len) != len)
        !           245:                                return Z_ERRNO;
        !           246:                        s->z_stream.next_out = s->z_buf;
        !           247:                        s->z_stream.avail_out = Z_BUFSIZE;
        !           248:                }
        !           249:                if (done)
        !           250:                        break;
        !           251:                if ((err = deflate(&(s->z_stream), flush)) != Z_OK &&
        !           252:                    err != Z_STREAM_END)
        !           253:                        return err;
        !           254:
        !           255:                /* deflate has finished flushing only when it hasn't
        !           256:                 * used up all the available space in the output buffer
        !           257:                 */
        !           258:                done = (s->z_stream.avail_out != 0 || err == Z_STREAM_END);
        !           259:        }
        !           260:        return 0;
        !           261: }
        !           262:
        !           263: static int
        !           264: put_int32 (s, x)
        !           265:        register gz_stream *s;
        !           266:        u_int32_t x;
        !           267: {
        !           268:        if (write(s->z_fd, &x, 1) != 1)
        !           269:                return Z_ERRNO;
        !           270:        x >>= 8;
        !           271:        if (write(s->z_fd, &x, 1) != 1)
        !           272:                return Z_ERRNO;
        !           273:        x >>= 8;
        !           274:        if (write(s->z_fd, &x, 1) != 1)
        !           275:                return Z_ERRNO;
        !           276:        x >>= 8;
        !           277:        if (write(s->z_fd, &x, 1) != 1)
        !           278:                return Z_ERRNO;
        !           279:        return 0;
        !           280: }
        !           281:
        !           282: static int
        !           283: get_byte(s)
        !           284:        register gz_stream *s;
        !           285: {
        !           286:        if (s->z_eof)
        !           287:                return EOF;
        !           288:
        !           289:        if (s->z_stream.avail_in == 0) {
        !           290:                errno = 0;
        !           291:                s->z_stream.avail_in = read(s->z_fd, s->z_buf, Z_BUFSIZE);
        !           292:                if (s->z_stream.avail_in <= 0) {
        !           293:                        s->z_eof = 1;
        !           294:                        return EOF;
        !           295:                }
        !           296:                s->z_stream.next_in = s->z_buf;
        !           297:        }
        !           298:        s->z_stream.avail_in--;
        !           299:        return *s->z_stream.next_in++;
        !           300: }
        !           301:
        !           302: static u_int32_t
        !           303: get_int32 (s)
        !           304:        register gz_stream *s;
        !           305: {
        !           306:        register u_int32_t x;
        !           307:
        !           308:        x  = ((u_int32_t)(get_byte(s) & 0xff));
        !           309:        x |= ((u_int32_t)(get_byte(s) & 0xff))<<8;
        !           310:        x |= ((u_int32_t)(get_byte(s) & 0xff))<<16;
        !           311:        x |= ((u_int32_t)(get_byte(s) & 0xff))<<24;
        !           312:        return x;
        !           313: }
        !           314:
        !           315: static int
        !           316: get_header(s)
        !           317:        register gz_stream *s;
        !           318: {
        !           319:        int method; /* method byte */
        !           320:        int flags;  /* flags byte */
        !           321:        uInt len;
        !           322:        int c;
        !           323:
        !           324:        /* Check the gzip magic header */
        !           325:        for (len = 0; len < 2; len++) {
        !           326:                c = get_byte(s);
        !           327:                if (c != gz_magic[len]) {
        !           328:                        errno = EFTYPE;
        !           329:                        return -1;
        !           330:                }
        !           331:        }
        !           332:
        !           333:        method = get_byte(s);
        !           334:        flags = get_byte(s);
        !           335:        if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
        !           336:                errno = EFTYPE;
        !           337:                return -1;
        !           338:        }
        !           339:
        !           340:        /* Discard time, xflags and OS code: */
        !           341:        for (len = 0; len < 6; len++)
        !           342:                (void)get_byte(s);
        !           343:
        !           344:        if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
        !           345:                len  =  (uInt)get_byte(s);
        !           346:                len += ((uInt)get_byte(s))<<8;
        !           347:                /* len is garbage if EOF but the loop below will quit anyway */
        !           348:                while (len-- != 0 && get_byte(s) != EOF)
        !           349:                        ;
        !           350:        }
        !           351:
        !           352:        if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
        !           353:                while ((c = get_byte(s)) != 0 && c != EOF) ;
        !           354:        }
        !           355:
        !           356:        if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
        !           357:                while ((c = get_byte(s)) != 0 && c != EOF) ;
        !           358:        }
        !           359:
        !           360:        if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
        !           361:                for (len = 0; len < 2; len++) (void)get_byte(s);
        !           362:        }
        !           363:
        !           364:        if (s->z_eof) {
        !           365:                errno = EFTYPE;
        !           366:                return -1;
        !           367:        }
        !           368:
        !           369:        return 0;
        !           370: }
        !           371:
        !           372: int
        !           373: gz_read(cookie, buf, len)
        !           374:        void *cookie;
        !           375:        char *buf;
        !           376:        int len;
        !           377: {
        !           378:        register gz_stream *s = (gz_stream*)cookie;
        !           379:        u_char *start = buf; /* starting point for crc computation */
        !           380:
        !           381:        s->z_stream.next_out = buf;
        !           382:        s->z_stream.avail_out = len;
        !           383:
        !           384:        while (s->z_stream.avail_out != 0 && !s->z_eof) {
        !           385:
        !           386:                if (s->z_stream.avail_in == 0) {
        !           387:
        !           388:                        errno = 0;
        !           389:                        if ((s->z_stream.avail_in =
        !           390:                             read(s->z_fd, s->z_buf, Z_BUFSIZE)) == 0)
        !           391:                                s->z_eof = 1;
        !           392:                        s->z_stream.next_in = s->z_buf;
        !           393:                }
        !           394:
        !           395:                if (inflate(&(s->z_stream), Z_NO_FLUSH) == Z_STREAM_END) {
        !           396:                        /* Check CRC and original size */
        !           397:                        s->z_crc = crc32(s->z_crc, start,
        !           398:                                       (uInt)(s->z_stream.next_out - start));
        !           399:                        start = s->z_stream.next_out;
        !           400:
        !           401:                        if (get_int32(s) != s->z_crc ||
        !           402:                            get_int32(s) != s->z_stream.total_out) {
        !           403:                                errno = EIO;
        !           404:                                return -1;
        !           405:                        }
        !           406:                        s->z_eof = 1;
        !           407:                        break;
        !           408:                }
        !           409:        }
        !           410:        s->z_crc = crc32(s->z_crc, start,
        !           411:                         (uInt)(s->z_stream.next_out - start));
        !           412:
        !           413:        return (int)(len - s->z_stream.avail_out);
        !           414: }
        !           415:
        !           416: int
        !           417: gz_write(cookie, buf, len)
        !           418:        void *cookie;
        !           419:        const char *buf;
        !           420:        int len;
        !           421: {
        !           422:        register gz_stream *s = (gz_stream*)cookie;
        !           423:
        !           424:        s->z_stream.next_in = (char *)buf;
        !           425:        s->z_stream.avail_in = len;
        !           426:
        !           427:        while (s->z_stream.avail_in != 0) {
        !           428:
        !           429:                if (s->z_stream.avail_out == 0) {
        !           430:
        !           431:                        if (write(s->z_fd, s->z_buf, Z_BUFSIZE) != Z_BUFSIZE)
        !           432:                                break;
        !           433:                        s->z_stream.next_out = s->z_buf;
        !           434:                        s->z_stream.avail_out = Z_BUFSIZE;
        !           435:                }
        !           436:                if (deflate(&(s->z_stream), Z_NO_FLUSH) != Z_OK)
        !           437:                        break;
        !           438:        }
        !           439:        s->z_crc = crc32(s->z_crc, buf, len);
        !           440:
        !           441:        return (int)(len - s->z_stream.avail_in);
        !           442: }
        !           443: