⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gzio.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
字号:
/* gzio.c -- IO on .gz files * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h * * This has been seriously re-arranged for use within MicroMonitor. * The majority of the rework is to strip out unnecessary parts because this * will reside in flash space.  Also, there is no file system interface, all * decompression is done from one point in memory to another point in memory. */#include "config.h"#include "tfs.h"#include "tfsprivate.h"#include "genlib.h"#include "zutil.h"struct internal_state {int dummy;}; /* for buggy compilers */#ifndef Z_BUFSIZE#  ifdef MAXSEG_64K#    define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */#  else#    define Z_BUFSIZE 16384#  endif#endif#ifndef Z_PRINTF_BUFSIZE#  define Z_PRINTF_BUFSIZE 4096#endif#define ALLOC(size) malloc(size)#define TRYFREE(p) {if (p) free((char *)p);}static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header *//* gzip flag byte */#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */#define ORIG_NAME    0x08 /* bit 3 set: original file name present */#define COMMENT      0x10 /* bit 4 set: file comment present */#define RESERVED     0xE0 /* bits 5..7: reserved */typedef struct gz_stream {    z_stream stream;    int      z_err;         /* error code for last stream operation */    int      z_eof;         /* set if end of input file */    Byte     *outbuf;       /* output buffer */    uLong    crc;           /* crc32 of uncompressed data */    char     *msg;          /* error message */    int      transparent;    /* 1 if input file is not a .gz file */    char     mode;          /* 'w' or 'r' */} gz_stream;local int    get_byte     OF((gz_stream *s));local void   check_header OF((gz_stream *s));local int    destroy      OF((gz_stream *s));local uLong  getLong      OF((gz_stream *s));/* ===========================================================================    gzInit():    Rewritten (from gzopen()) to support only decompression of data in    memory.  The next_in member points directly to the compressed data and    avail_in is the number of bytes remaining.    Things get simpler because of the removal of the file system interface    as well as the "only decompression" mode.*/gz_stream *gzInit(compressed_data, size)int  size;unsigned char *compressed_data;{    int err;    gz_stream *s;    s = (gz_stream *)ALLOC(sizeof(gz_stream));    if (!s)        return Z_NULL;    s->stream.zalloc = (alloc_func)0;    s->stream.zfree = (free_func)0;    s->stream.opaque = (voidpf)0;    s->stream.next_in = compressed_data;    s->stream.next_out = s->outbuf = Z_NULL;    s->stream.avail_in = size;    s->stream.avail_out = 0;    s->z_err = Z_OK;    s->z_eof = 0;    s->crc = zcrc32(0L, Z_NULL, 0);    s->msg = NULL;    s->transparent = 0;    s->mode = 'r';    err = inflateInit2(&(s->stream), -MAX_WBITS);    /* windowBits is passed < 0 to tell that there is no zlib header.     * Note that in this case inflate *requires* an extra "dummy" byte     * after the compressed stream in order to complete decompression and     * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are     * present after the compressed stream.     */    if (err != Z_OK) {        destroy(s);        return((gz_stream *)Z_NULL);    }        s->stream.avail_out = Z_BUFSIZE;    check_header(s); /* skip the .gz header */    return(s);}/* ===========================================================================    get_byte()    Simple now because we assume that avail_in is pointing to the number    of bytes in the source buffer that are remaining to be decompressed    and next_in is the pointer to the next byte to be retrieved from the    buffer.*/local intget_byte(s)gz_stream *s;{    if (s->z_eof)         return EOF;    if (s->stream.avail_in == 0) {        s->z_eof = 1;        return EOF;    }    s->stream.avail_in--;    return *(s->stream.next_in)++;}/* ===========================================================================    check_header():    Check the gzip header of a gz_stream opened for reading. Set the stream    mode to transparent if the gzip magic header is not present; set s->err    to Z_DATA_ERROR if the magic header is present but the rest of the header    is incorrect.    IN assertion: the stream s has already been created sucessfully;       s->stream.avail_in is zero for the first time, but may be non-zero       for concatenated .gz files.*/local voidcheck_header(s)gz_stream *s;{    int method; /* method byte */    int flags;  /* flags byte */    uInt len;    int c;    /* Check the gzip magic header */    for (len = 0; len < 2; len++) {        c = get_byte(s);        if (c != gz_magic[len]) {            if (len != 0) {                s->stream.avail_in++;                s->stream.next_in--;            }            if (c != EOF) {                s->stream.avail_in++;                s->stream.next_in--;                s->transparent = 1;            }            s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;            return;        }    }    method = get_byte(s);    flags = get_byte(s);    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {        s->z_err = Z_DATA_ERROR;        return;    }    /* Discard time, xflags and OS code: */    for (len = 0; len < 6; len++)        (void)get_byte(s);    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */        len  =  (uInt)get_byte(s);        len += ((uInt)get_byte(s))<<8;        /* len is garbage if EOF but the loop below will quit anyway */        while (len-- != 0 && get_byte(s) != EOF) ;    }    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */        while ((c = get_byte(s)) != 0 && c != EOF) ;    }    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */        while ((c = get_byte(s)) != 0 && c != EOF) ;    }    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */        for (len = 0; len < 2; len++) (void)get_byte(s);    }    s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;}/* ===========================================================================    destroy():    Cleanup then free the given gz_stream. Return a zlib error code.    Try freeing in the reverse order of allocations.*/local intdestroy (s)gz_stream *s;{    int err = Z_OK;    if (!s) return Z_STREAM_ERROR;    TRYFREE(s->msg);    if (s->stream.state != NULL)        err = inflateEnd(&(s->stream));        if (s->z_err < 0)        err = s->z_err;    TRYFREE(s->outbuf);    TRYFREE(s);    return err;}/* ===========================================================================    gzRead():    Reads the given number of uncompressed bytes from the compressed file.    gzRead returns the number of bytes actually read (0 for end of file).*/int ZEXPORTgzRead (file, buf, len)gzFile file;voidp buf;unsigned len;{    gz_stream *s = (gz_stream*)file;    Bytef *start = (Bytef*)buf; /* starting point for crc computation */    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */    if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;    if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;    if (s->z_err == Z_STREAM_END) return 0;  /* EOF */    next_out = (Byte*)buf;    s->stream.next_out = (Bytef*)buf;    s->stream.avail_out = len;    while (s->stream.avail_out != 0) {        if (s->transparent) {            /* Copy first the lookahead bytes: */            uInt n = s->stream.avail_in;            if (n > s->stream.avail_out) n = s->stream.avail_out;            if (n > 0) {                zmemcpy(s->stream.next_out, s->stream.next_in, n);                next_out += n;                s->stream.next_out = next_out;                s->stream.next_in   += n;                s->stream.avail_out -= n;                s->stream.avail_in  -= n;            }            if (s->stream.avail_out > 0) {                int     i, c;                Byte    *next;                next = next_out;                for(i=0;i<(int)(s->stream.avail_out);i++) {                    c = get_byte(s);                    if (c == EOF)                        break;                    *next_out++ = (Byte)c;                    s->stream.avail_out--;                }            }            len -= s->stream.avail_out;            s->stream.total_in  += (uLong)len;            s->stream.total_out += (uLong)len;            if (len == 0)                s->z_eof = 1;            return (int)len;        }        s->z_err = inflate(&(s->stream), Z_NO_FLUSH);            if (s->z_err == Z_STREAM_END) {            /* Check CRC and original size */            s->crc = zcrc32(s->crc, start, (uInt)(s->stream.next_out - start));            start = s->stream.next_out;                if (getLong(s) != s->crc) {            s->z_err = Z_DATA_ERROR;            } else {                (void)getLong(s);                    /* The uncompressed length returned by above getlong() may                     * be different from s->stream.total_out) in case of             * concatenated .gz files. Check for such files:             */            check_header(s);            if (s->z_err == Z_OK) {                uLong total_in = s->stream.total_in;                uLong total_out = s->stream.total_out;                    inflateReset(&(s->stream));                s->stream.total_in = total_in;                s->stream.total_out = total_out;                s->crc = zcrc32(0L, Z_NULL, 0);            }            }        }        if (s->z_err != Z_OK || s->z_eof)            break;    }    s->crc = zcrc32(s->crc, start, (uInt)(s->stream.next_out - start));    return (int)(len - s->stream.avail_out);}/* ===========================================================================    getLong():    Reads a long in LSB order from the given gz_stream. Sets z_err in case    of error.*/local uLonggetLong (s)gz_stream *s;{    uLong x = (uLong)get_byte(s);    int c;    x += ((uLong)get_byte(s))<<8;    x += ((uLong)get_byte(s))<<16;    c = get_byte(s);    if (c == EOF) s->z_err = Z_DATA_ERROR;    x += ((uLong)c)<<24;    return x;}/* ===========================================================================    unZip():    This is the front end to the whole zlib decompressor.    It is a chop-up of the original minigzip.c code that came with    the zlib source.*/intunZip(char *src, int srclen, char *dest, int destlen){    int len;    gz_stream   *s;    if ((s = gzInit(src,srclen)) == Z_NULL) {        printf("gzInit(0x%lx,%d) failed!\n",(ulong)src,srclen);        return(-1);    }    len = gzRead(s,dest,destlen);    if (len < 0)        printf("gzRead() returned %d\n",len);    destroy(s);    return(len);}char *UnzipHelp[] = {    "Decompress block of memory to some other block of memory.",    "-[s:d:]",    " -s {source}         filename or 'addr,len' (required option)",    " -d {destination}    'addr[,len]' (default=APPRAMBASE,99999999)",    "",    "Works in conjunction with zlib's minigzip on host.",    0,};/* Unzip():    Access ZLIB decompressor from monitor command line.*/intUnzip(int argc,char *argv[]){    extern  char *optarg;    char    *asc_src, *asc_dst, *comma, *src, *dest;    int     opt, tot;    ulong   srclen, destlen;    destlen = 99999999;    dest = (char *)getAppRamStart();    asc_src = asc_dst = (char *)0;    while((opt=getopt(argc,argv,"d:s:")) != -1) {        switch(opt) {        case 's':            asc_src = optarg;            break;        case 'd':            asc_dst = optarg;            break;        default:            return(0);        }    }    if (!asc_src)        return(-1);    comma = strchr(asc_src,',');    if (comma) {        *comma = 0;        src = (char *)strtoul(asc_src,(char **)0,0);        srclen = strtoul(comma+1,(char **)0,0);    }    else {        TFILE *tfp;        tfp = tfsstat(asc_src);        if (!tfp)            return(-1);        src = TFS_BASE(tfp);        srclen = TFS_SIZE(tfp);    }    if (asc_dst) {        comma = strchr(asc_dst,',');        if (comma) {            *comma = 0;            destlen = strtoul(comma+1,(char **)0,0);        }        dest = (char *)strtoul(asc_dst,(char **)0,0);    }    tot = unZip(src,srclen,dest,destlen);    printf("Decompressed %ld bytes from 0x%lx to %d bytes at 0x%lx.\n",        srclen,(ulong)src,tot,(ulong)dest);    return(0);}/* Front end to the rest of the unZip() stuff...    Return the size of the decompressed data or -1 if failure.    The same front API end is available if unpack is used instead of unzip.*/intdecompress(char *src,int srclen, char *dest){    return(unZip(src,srclen,dest,99999999));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -