vms_pk.c

来自「给出了 zip 压缩算法的完整实现过程。」· C语言 代码 · 共 551 行 · 第 1/2 页

C
551
字号
/*  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_pk.c  by Igor Mandrichenko * *    version 2.0       20-Mar-1993 *                      Generates PKWARE version of VMS attributes *                      extra field according to appnote 2.0. *                      Uses low level QIO-ACP interface. *    version 2.0-1     10-Apr-1993 *                      Save ACLs *    version 2.1       24-Aug-1993 *                      By default produce 0x010C extra record ID instead of *                      PKWARE's 0x000C. The format is mostly compatible with *                      PKWARE. *                      Incompatibility (?): zip produces multiple ACE *                      fields. *    version 2.1-1     Clean extra fields in vms_get_attributes(). *                      Fixed bug with EOF. *    version 2.1-2     15-Sep-1995, Chr. Spieler *                      Removed extra fields cleanup from vms_get_attributes(). *                      This is now done in zipup.c *                      Modified (according to UnZip's vms.[ch]) the fib stuff *                      for DEC C (AXP,VAX) support. *    version 2.2       28-Sep-1995, Chr. 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. *                      Made extra block header conforming to PKware's *                      specification (extra block header has a length *                      of four bytes, two bytes for a signature, and two *                      bytes for the length of the block excluding this *                      header. *    version 2.2-1     19-Oct-1995, Chr. Spieler *                      Fixed bug in CRC calculation. *                      Use official PK VMS extra field id. *    version 2.2-2     21-Nov-1997, Chr. Spieler *                      Fixed bug in vms_get_attributes() for directory *                      entries (access to uninitialized ioctx record). *                      Removed unused second arg for vms_open(). *    version 2.2-3     04-Apr-1999, Chr. Spieler *                      Changed calling interface of vms_get_attributes() *                      to accept a void pointer as first argument. *    version 2.2-4     26-Jan-2002, Chr. Spieler *                      Modified vms_read() to handle files larger than 2GByte *                      (up to size limit of "unsigned long", resp. 4GByte). *    version 2.3.1     20-Oct-2004, Steven Schweda. *                      Changed vms_read() to read all the allocated *                      blocks in a file, for sure.  Changed the default *                      chunk size from 16K to 32K.  Changed to use the *                      new typedef for the ioctx structure.  Moved the *                      VMS_PK_EXTRA test into here from VMS.C to allow *                      more general automatic dependency generation. */#ifdef VMS                      /* For VMS only ! */#ifdef VMS_PK_EXTRA#include <ssdef.h>#ifndef VMS_ZIP#define VMS_ZIP#endif#include "vms.h"#include "vmsdefs.h"#ifndef ERR#define ERR(x) (((x)&1)==0)#endif#ifndef NULL#define NULL (void*)(0L)#endif#ifndef UTILstatic PK_info_t PK_def_info ={        ATR$C_RECATTR,  ATR$S_RECATTR,  {0},        ATR$C_UCHAR,    ATR$S_UCHAR,    {0},        ATR$C_CREDATE,  ATR$S_CREDATE,  {0},        ATR$C_REVDATE,  ATR$S_REVDATE,  {0},        ATR$C_EXPDATE,  ATR$S_EXPDATE,  {0},        ATR$C_BAKDATE,  ATR$S_BAKDATE,  {0},        ATR$C_ASCDATES, sizeof(ush),    0,        ATR$C_UIC,      ATR$S_UIC,      {0},        ATR$C_FPRO,     ATR$S_FPRO,     {0},        ATR$C_RPRO,     ATR$S_RPRO,     {0},        ATR$C_JOURNAL,  ATR$S_JOURNAL,  {0}};/* File description structure for Zip low level I/O */typedef struct{    struct iosb         iosb;    long                vbn;    unsigned int        size;    unsigned int        rest;    int                 status;    ush                 chan;    ush                 chan_pad;       /* alignment member */    long                acllen;    uch                 aclbuf[ATR$S_READACL];    PK_info_t           PKi;} ioctx_t;/* Forward declarations of public functions: */ioctx_t *vms_open(char *file);size_t  vms_read(register ioctx_t *ctx,                 register char *buf, register size_t size);int  vms_error(ioctx_t *ctx);int  vms_rewind(ioctx_t *ctx);int  vms_get_attributes(ioctx_t *ctx, struct zlist far *z,                        iztimes *z_utim);int  vms_close(ioctx_t *ctx);#define BLOCK_BYTES 512/*---------------* |  vms_open()   | *---------------* |  This routine opens file for reading fetching its attributes. |  Returns pointer to file description structure. */ioctx_t *vms_open(file)char *file;{    static struct atrdef        Atr[VMS_MAX_ATRCNT+1];    static struct NAM           Nam;    static struct fibdef        Fib;    static struct dsc$descriptor FibDesc =        {sizeof(Fib),DSC$K_DTYPE_Z,DSC$K_CLASS_S,(char *)&Fib};    static struct dsc$descriptor_s DevDesc =        {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,&Nam.nam$t_dvi[1]};    static struct dsc$descriptor_s FileName =        {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};    static char EName[NAM$C_MAXRSS];    static char RName[NAM$C_MAXRSS];    struct FAB  Fab;    register ioctx_t *ctx;    register struct fatdef *fat;    int status;    int i;    ulg efblk, hiblk;    if ( (ctx=(ioctx_t *)malloc(sizeof(ioctx_t))) == NULL )        return NULL;    ctx -> PKi = PK_def_info;#define FILL_REQ(ix,id,b)   {       \    Atr[ix].atr$l_addr = GVTC &(b);      \    Atr[ix].atr$w_type = (id);      \    Atr[ix].atr$w_size = sizeof(b); \}    FILL_REQ(0, ATR$C_RECATTR,  ctx->PKi.ra);    FILL_REQ(1, ATR$C_UCHAR,    ctx->PKi.uc);    FILL_REQ(2, ATR$C_REVDATE,  ctx->PKi.rd);    FILL_REQ(3, ATR$C_EXPDATE,  ctx->PKi.ed);    FILL_REQ(4, ATR$C_CREDATE,  ctx->PKi.cd);    FILL_REQ(5, ATR$C_BAKDATE,  ctx->PKi.bd);    FILL_REQ(6, ATR$C_ASCDATES, ctx->PKi.rn);    FILL_REQ(7, ATR$C_JOURNAL,  ctx->PKi.jr);    FILL_REQ(8, ATR$C_RPRO,     ctx->PKi.rp);    FILL_REQ(9, ATR$C_FPRO,     ctx->PKi.fp);    FILL_REQ(10,ATR$C_UIC,      ctx->PKi.ui);    FILL_REQ(11,ATR$C_ACLLENGTH,ctx->acllen);    FILL_REQ(12,ATR$C_READACL,  ctx->aclbuf);    Atr[13].atr$w_type = 0;     /* End of ATR list */    Atr[13].atr$w_size = 0;    Atr[13].atr$l_addr = GVTC NULL;    /* initialize RMS structures, we need a NAM to retrieve the FID */    Fab = cc$rms_fab;    Fab.fab$l_fna = file ; /* name of file */    Fab.fab$b_fns = strlen(file);    Fab.fab$l_nam = &Nam; /* FAB has an associated NAM */    Nam = cc$rms_nam;    Nam.nam$l_esa = EName; /* expanded filename */    Nam.nam$b_ess = sizeof(EName);    Nam.nam$l_rsa = RName; /* resultant filename */    Nam.nam$b_rss = sizeof(RName);    /* do $PARSE and $SEARCH here */    status = sys$parse(&Fab);    if (!(status & 1)) return NULL;    /* search for the first file.. If none signal error */    status = sys$search(&Fab);    if (!(status & 1)) return NULL;    /* initialize Device name length, note that this points into the NAM         to get the device name filled in by the $PARSE, $SEARCH services */    DevDesc.dsc$w_length = Nam.nam$t_dvi[0];    status = sys$assign(&DevDesc,&ctx->chan,0,0);    if (!(status & 1)) return NULL;    FileName.dsc$a_pointer = Nam.nam$l_name;    FileName.dsc$w_length = Nam.nam$b_name+Nam.nam$b_type+Nam.nam$b_ver;    /* Initialize the FIB */    Fib.FIB$L_ACCTL = FIB$M_NOWRITE;    for (i=0;i<3;i++)        Fib.FIB$W_FID[i]=Nam.nam$w_fid[i];    for (i=0;i<3;i++)        Fib.FIB$W_DID[i]=Nam.nam$w_did[i];    /* Use the IO$_ACCESS function to return info about the file */    status = sys$qiow( 0, ctx->chan, (IO$_ACCESS| IO$M_ACCESS),                       &ctx->iosb, 0, 0, &FibDesc, &FileName, 0, 0,                       Atr, 0);    if (ERR(status) || ERR(status = ctx->iosb.status))    {        vms_close(ctx);        return NULL;    }    fat = (struct fatdef *)&(ctx -> PKi.ra);#define SWAPW(x)        ( (((x)>>16)&0xFFFF) + ((x)<<16) )    efblk = SWAPW(fat->fat$l_efblk);    hiblk = SWAPW(fat->fat$l_hiblk);    if (efblk == 0)    {        /* Only known size is all allocated blocks.           (This occurs with a zero-length file, for example.)        */        ctx -> size =        ctx -> rest = hiblk * BLOCK_BYTES;    }    else    {        /* Store normal (used) size in ->size.           If only one -V, store normal (used) size in ->rest.           If multiple -V, store allocated-blocks size in ->rest.        */        ctx -> size =         ((efblk) - 1) * BLOCK_BYTES + fat -> fat$w_ffbyte;        if (vms_native < 2)            ctx -> rest = ctx -> size;        else            ctx -> rest = hiblk * BLOCK_BYTES;    }    ctx -> status = SS$_NORMAL;    ctx -> vbn = 1;    return ctx;}#define KByte (2 * BLOCK_BYTES)#define MAX_READ_BYTES (32 * KByte)/*----------------*

⌨️ 快捷键说明

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