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

📄 vms_im.c

📁 给出了 zip 压缩算法的完整实现过程。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.  See the accompanying file LICENSE, version 2004-May-22 or later  (the contents of which are also included in zip.h) for terms of use.  If, for some reason, both of these files are missing, the Info-ZIP license  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html*//* *  vms_im.c (zip) by Igor Mandrichenko    Version 2.2-2 * *  Revision history: *  ... *  2.1-1       16-feb-1993     I.Mandrichenko *      Get file size from XABFHC and check bytes rest in file before *      reading. *  2.1-2       2-mar-1993      I.Mandrichenko *      Make code more standard *  2.2         21-jun-1993     I.Mandrichenko *      Free all allocated space, use more static storage. *      Use memcompress() from bits.c (deflation) for block compression. *      To revert to old compression method #define OLD_COMPRESS *  2.2-2       28-sep-1995     C.Spieler *      Reorganized code for easier maintance of the two incompatible *      flavours (IM style and PK style) VMS attribute support. *      Generic functions (common to both flavours) are now collected *      in a `wrapper' source file that includes one of the VMS attribute *      handlers. *  3.0         23-Oct-2004     Steven Schweda *      Changed to maintain compatibility with VMS_PK.C.  Note that *      reading with sys$read() prevents getting any data past EOF, *      regardless of appearances.  Moved the VMS_PK_EXTRA test into *      here from VMS.C to allow more general automatic dependency *      generation. */#ifdef VMS                      /* For VMS only ! */#ifndef VMS_PK_EXTRA#define OLD_COMPRESS            /*To use old compression method define it.*/#ifdef VMS_ZIP#undef VMS_ZIP                  /* do NOT include PK style Zip definitions */#endif#include "vms.h"#ifndef __LIB$ROUTINES_LOADED#include <lib$routines.h>#endif#ifndef UTIL#define RET_ERROR 1#define RET_SUCCESS 0#define RET_EOF 0#define Kbyte 1024typedef struct XAB *xabptr;/* *   Block sizes */#define EXTL0   ((FABL + EXTHL)+        \                (XFHCL + EXTHL)+        \                (XPROL + EXTHL)+        \                (XDATL + EXTHL)+        \                (XRDTL + EXTHL))#ifdef OLD_COMPRESS#define PAD     sizeof(uch)#else#define PAD     10*sizeof(ush)          /* Two extra bytes for compr. header */#endif#define PAD0    (5*PAD)                 /* Reserve space for the case when                                         *  compression fails */static int _compress(uch *from, uch *to, int size);#ifdef DEBUGstatic void dump_rms_block(uch *p);#endif /* DEBUG *//******************************** *   Function set_extra_field   * ********************************//* |   2004-11-11 SMS. |   Changed to use separate storage for ->extra and ->cextra.  Zip64 |   processing may move (reallocate) one and not the other. */static uch *_compress_block(register struct IZ_block *to,                            uch *from, int size, char *sig);static int get_vms_version(char *verbuf, int len);int set_extra_field(z, z_utim)  struct zlist far *z;  iztimes *z_utim;/* *      Get file VMS file attributes and store them into extent fields. *      Store VMS version also. *      On error leave z intact. */{    int status;    uch *xtra;    uch *cxtra;    uch *scan;    extent extra_l;    static struct FAB fab;    static struct XABSUM xabsum;    static struct XABFHC xabfhc;    static struct XABDAT xabdat;    static struct XABPRO xabpro;    static struct XABRDT xabrdt;    xabptr x = (xabptr)NULL, xab_chain = (xabptr)NULL, last_xab = (xabptr)NULL;    int nk, na;    int i;    int rc=RET_ERROR;    char verbuf[80];    int verlen = 0;    if (!vms_native)    {#ifdef USE_EF_UT_TIME       /*        *  A `portable' zipfile entry is created. Create an "UT" extra block        *  containing UNIX style modification time stamp in UTC, which helps        *  maintaining the `real' "last modified" time when the archive is        *  transfered across time zone boundaries.        */#  ifdef IZ_CHECK_TZ        if (!zp_tz_is_valid)            return ZE_OK;       /* skip silently if no valid TZ info */#  endif        if ((xtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)            return ZE_MEM;        if ((cxtra = (uch *) malloc( EB_HEADSIZE+ EB_UT_LEN( 1))) == NULL)            return ZE_MEM;        /* Fill xtra[] with data. */        xtra[ 0] = 'U';        xtra[ 1] = 'T';        xtra[ 2] = EB_UT_LEN(1);        /* length of data part of e.f. */        xtra[ 3] = 0;        xtra[ 4] = EB_UT_FL_MTIME;        xtra[ 5] = (uch) (z_utim->mtime);        xtra[ 6] = (uch) (z_utim->mtime >> 8);        xtra[ 7] = (uch) (z_utim->mtime >> 16);        xtra[ 8] = (uch) (z_utim->mtime >> 24);        /* Copy xtra[] data into cxtra[]. */        memcpy( cxtra, xtra, (EB_HEADSIZE+ EB_UT_LEN( 1)));        /* Set sizes and pointers. */        z->cext = z->ext = (EB_HEADSIZE+ EB_UT_LEN( 1));        z->extra = (char *) xtra;        z->cextra = (char *) cxtra;#endif /* USE_EF_UT_TIME */        return RET_SUCCESS;    }    /*     *  Initialize RMS control blocks and link them     */    fab =    cc$rms_fab;    xabsum = cc$rms_xabsum;    xabdat = cc$rms_xabdat;    xabfhc = cc$rms_xabfhc;    xabpro = cc$rms_xabpro;    xabrdt = cc$rms_xabrdt;    fab.fab$l_xab = (char*)&xabsum;    /*     *  Open the file and read summary information.     */    fab.fab$b_fns = strlen(z->name);    fab.fab$l_fna = z->name;    status = sys$open(&fab);    if (ERR(status))    {#ifdef DEBUG        printf("set_extra_field: sys$open for file %s:\n  error status = %d\n",               z->name, status);#endif        goto err_exit;    }    nk = xabsum.xab$b_nok;    na = xabsum.xab$b_noa;#ifdef DEBUG    printf("%d keys, %d alls\n", nk, na);#endif    /*     *  Allocate XABKEY and XABALL blocks and link them     */    xabfhc.xab$l_nxt = (char*)&xabdat;    xabdat.xab$l_nxt = (char*)&xabpro;    xabpro.xab$l_nxt = (char*)&xabrdt;    xabrdt.xab$l_nxt = NULL;    xab_chain = (xabptr)(&xabfhc);    last_xab  = (xabptr)(&xabrdt);#define INIT(ptr,size,type,init)     \        if ( (ptr = (type *)malloc(size)) == NULL )     \        {                                               \              printf( "set_extra_field: Insufficient memory.\n" );   \                      goto err_exit;                    \        }                                               \        *(ptr) = (init);    /*     *  Allocate and initialize all needed XABKEYs and XABALLs     */    for (i = 0; i < nk; i++)    {        struct XABKEY *k;        INIT(k, XKEYL, struct XABKEY, cc$rms_xabkey);        k->xab$b_ref = i;        if (last_xab != NULL)            last_xab->xab$l_nxt = (char*)k;        last_xab = (xabptr)k;    }    for (i = 0; i < na; i++)    {        struct XABALL *a;        INIT(a, XALLL, struct XABALL, cc$rms_xaball);        a->xab$b_aid = i;        if (last_xab != NULL)            last_xab->xab$l_nxt = (char*)a;        last_xab = (xabptr)a;    }    fab.fab$l_xab = (char*)xab_chain;#ifdef DEBUG    printf("Dump of XAB chain before $DISPLAY:\n");    for (x = xab_chain; x != NULL; x = x->xab$l_nxt)        dump_rms_block((uch *)x);#endif    /*     *  Get information on the file structure etc.     */    status = sys$display(&fab, 0, 0);    if (ERR(status))    {#ifdef DEBUG        printf("set_extra_field: sys$display for file %s:\n  error status = %d\n",               z->name, status);#endif        goto err_exit;    }#ifdef DEBUG    printf("\nDump of XAB chain after $DISPLAY:\n");    for (x = xab_chain; x != NULL; x = x->xab$l_nxt)        dump_rms_block((uch *)x);#endif    fab.fab$l_xab = NULL;  /* Keep XABs */    status = sys$close(&fab);    if (ERR(status))    {#ifdef DEBUG        printf("set_extra_field: sys$close for file %s:\n  error status = %d\n",               z->name, status);#endif        goto err_exit;    }    extra_l = EXTL0 + nk * (XKEYL + EXTHL) + na * (XALLL + EXTHL);#ifndef OLD_COMPRESS    extra_l += PAD0 + (nk+na) * PAD;#endif    if ( (verlen = get_vms_version(verbuf, sizeof(verbuf))) > 0 )    {        extra_l += verlen + EXTHL;#ifndef OLD_COMPRESS        extra_l += PAD;#endif    }    if ((scan = xtra = (uch *) malloc( extra_l)) == (uch*)NULL)    {#ifdef DEBUG        printf(         "set_extra_field: Insufficient memory to allocate extra L buffer\n");#endif        goto err_exit;    }    if ((cxtra = (uch *) malloc( extra_l)) == (uch*)NULL)    {#ifdef DEBUG        printf(         "set_extra_field: Insufficient memory to allocate extra C buffer\n");#endif        goto err_exit;    }    if (verlen > 0)        scan = _compress_block((struct IZ_block *)scan, (uch *)verbuf,                               verlen, VERSIG);    /*     *  Zero all unusable fields to improve compression     */    fab.fab$b_fns = fab.fab$b_shr = fab.fab$b_dns = fab.fab$b_fac = 0;    fab.fab$w_ifi = 0;    fab.fab$l_stv = fab.fab$l_sts = fab.fab$l_ctx = 0;    fab.fab$l_fna = NULL;    fab.fab$l_nam = NULL;    fab.fab$l_xab = NULL;    fab.fab$l_dna = NULL;#ifdef DEBUG    dump_rms_block( (uch *)&fab );#endif    scan = _compress_block((struct IZ_block *)scan, (uch *)&fab, FABL, FABSIG);    for (x = xab_chain; x != NULL;)    {        int bln;        char *sig;        xabptr next;        next = (xabptr)(x->xab$l_nxt);        x->xab$l_nxt = 0;        switch (x->xab$b_cod)        {            case XAB$C_ALL:                bln = XALLL;                sig = XALLSIG;                break;            case XAB$C_KEY:                bln = XKEYL;                sig = XKEYSIG;                break;            case XAB$C_PRO:                bln = XPROL;                sig = XPROSIG;                break;            case XAB$C_FHC:                bln = XFHCL;                sig = XFHCSIG;                break;            case XAB$C_DAT:                bln = XDATL;                sig = XDATSIG;                break;            case XAB$C_RDT:                bln = XRDTL;                sig = XRDTSIG;                break;            default:                bln = 0;                sig = 0L;                break;        }        if (bln > 0)            scan = _compress_block((struct IZ_block *)scan, (uch *)x,                                   bln, sig);        x = next;    }    /* Copy xtra[] data into cxtra[]. */    memcpy( cxtra, xtra, (scan - xtra));    /* Set sizes and pointers. */    z->cext = z->ext = scan - xtra;    z->extra = (char*) xtra;    z->cextra = (char*) cxtra;    rc = RET_SUCCESS;err_exit:    /*     *  Give up all allocated blocks     */    for (x = (struct XAB *)xab_chain; x != NULL; )    {        struct XAB *next;        next = (xabptr)(x->xab$l_nxt);        if (x->xab$b_cod == XAB$C_ALL || x->xab$b_cod == XAB$C_KEY)            free(x);        x = next;    }    return rc;}static int get_vms_version(verbuf, len)char *verbuf;int len;{    int i = SYI$_VERSION;    int verlen = 0;    struct dsc$descriptor version;    char *m;    version.dsc$a_pointer = verbuf;    version.dsc$w_length  = len - 1;    version.dsc$b_dtype   = DSC$K_DTYPE_B;    version.dsc$b_class   = DSC$K_CLASS_S;    if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)        return 0;    /* Cut out trailing spaces "V5.4-3   " -> "V5.4-3" */    for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)        --m;    *m = 0;    /* Cut out release number "V5.4-3" -> "V5.4" */    if ((m = strrchr(verbuf, '-')) != NULL)        *m = 0;

⌨️ 快捷键说明

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