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

📄 vms_pk.c

📁 infozip2.2源码
💻 C
字号:
/************************************************************************* *                                                                       * * Copyright (C) 1993 Igor Mandrichenko.                                 * * Permission is granted to any individual or institution to use, copy,  * * or redistribute this software so long as all of the original files    * * are included unmodified, and that this copyright notice is retained.  * *                                                                       * *************************************************************************//* *    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. */#ifdef VMS                      /* For VMS only ! */#ifndef __SSDEF_LOADED#include <ssdef.h>#endif#ifndef VMS_ZIP#define VMS_ZIP#endif#include "vms/vms.h"#include "vms/vmsdefs.h"#ifndef ERR#define ERR(x) (((x)&1)==0)#endif#ifndef NULL#define NULL (void*)(0L)#endif#ifndef UTILstatic struct PK_info 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}};/* Forward declarations of public functions: */struct ioctx *vms_open(char *file, char *how);int  vms_read(register struct ioctx *ctx,              register char *buf, register int size);int  vms_error(struct ioctx *ctx);int  vms_rewind(struct ioctx *ctx);void vms_get_attributes(struct ioctx *ctx, struct zlist far *z,                        iztimes *z_utim);int  vms_close(struct ioctx *ctx);/*---------------* |  vms_open()   | *---------------* |  This routine opens file for reading fetching its attributes. |  Returns pointer to file description structure. */struct ioctx *vms_open(file,how)char *file,*how;{    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 struct ioctx *ctx;    register struct fatdef *fat;    int status;    int i;    ulg efblk,hiblk;    if( (ctx=(struct ioctx *)malloc(sizeof(struct ioctx))) == NULL )        return NULL;    ctx -> PKi = PK_def_info;#define FILL_REQ(ix,id,b)   {       \    Atr[ix].atr$l_addr = &(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 = (byte *)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 && fat -> fat$w_ffbyte == 0 )        ctx -> size =        ctx -> rest = hiblk * 512;    else        ctx -> size =        ctx -> rest = (efblk - 1) * 512 + fat -> fat$w_ffbyte;    ctx -> status = SS$_NORMAL;    ctx -> vbn = 1;    return ctx;}#define KByte 1024/*----------------* |   vms_read()   | *----------------* |   Reads file block by block into the buffer. |   Stops on EOF, returns number of bytes actually read. |   Note: size of the buffer must be greater than or equal to 512 ! */int vms_read(ctx, buf, size)register struct ioctx *ctx;register char *buf;register int size;{    int status;    long nr=0;    if (ctx -> rest <= 0 || ctx -> status == SS$_ENDOFFILE)        return 0;               /* Eof */    if(size <= 0)        return 0;    if(size > 16*KByte)        size = 16*KByte;    else if(size > 512)        size &= ~511L;          /* Round to integer number of blocks */    do    {        status = sys$qiow(0, ctx->chan, IO$_READVBLK,            &ctx->iosb, 0, 0,            buf, size, ctx->vbn,0,0,0);        ctx->vbn += size>>9;        if( size < 512 )                ++ctx->vbn;        if( !ERR(status) )                status = ctx->iosb.status;        if( !ERR(status) || status == SS$_ENDOFFILE )        {            register int count;            if( status == SS$_ENDOFFILE )                count = ctx->rest;            else                count = ctx->iosb.count;            size -= count;            buf  += count;            nr   += count;        }    } while( !ERR(status) && size > 0 );    if (!ERR(status))    {        ctx -> status = SS$_NORMAL;        ctx -> rest -= nr;    }    else if(status == SS$_ENDOFFILE)    {        ctx -> status = SS$_ENDOFFILE;        ctx -> rest = 0;    }    else    {        ctx -> status = status;        ctx -> rest -= nr;    }    return nr;}/*-----------------* |   vms_error()   | *-----------------* |   Returns whether last operation on the file caused an error */int vms_error(ctx)struct ioctx *ctx;{   /* EOF is not actual error */    return ERR(ctx->status) && (ctx->status != SS$_ENDOFFILE);}/*------------------* |   vms_rewind()   | *------------------* |   Rewinds file to the beginning for the next vms_read(). */int vms_rewind(ctx)struct ioctx *ctx;{    ctx -> vbn = 1;    ctx -> rest = ctx -> size;    return 0;}/*--------------------------* |   vms_get_attributes()   | *--------------------------* |   Returns pointer to malloc'ed PKWARE extra field with file attributes. |   File must be open already by vms_open() */void vms_get_attributes(ctx, z, z_utim)struct ioctx *ctx;struct zlist far *z;    /* zip entry to compress */iztimes *z_utim;{    byte    *p, *b;    struct  PK_header    *h;    int     l;    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.         */        if ((b = (uch *)malloc(EB_HEADSIZE+EB_UT_LEN(1))) == NULL)            return;        b[0]  = 'U';        b[1]  = 'T';        b[2]  = EB_UT_LEN(1);          /* length of data part of e.f. */        b[3]  = 0;        b[4]  = EB_UT_FL_MTIME;        b[5]  = (byte)(z_utim->mtime);        b[6]  = (byte)(z_utim->mtime >> 8);        b[7]  = (byte)(z_utim->mtime >> 16);        b[8]  = (byte)(z_utim->mtime >> 24);        z->cext = z->ext = (EB_HEADSIZE+EB_UT_LEN(1));        z->cextra = z->extra = (char*)b;#endif /* USE_EF_UT_TIME */        return;    }    l = PK_HEADER_SIZE+sizeof(ctx->PKi);    if(ctx->acllen > 0)        l += PK_FLDHDR_SIZE + ctx->acllen;    b = (uch *)malloc(l);    if( b==NULL )        return;    h = (struct PK_header *)b;    h->tag = PK_SIGNATURE;    h->size = l - EB_HEADSIZE;    p = (h->data);    /* Copy default set of attributes */    memcpy(h->data,(uch*)&(ctx->PKi),sizeof(ctx->PKi));    p += sizeof(ctx->PKi);    if( ctx->acllen > 0 )    {        struct PK_field *f;        if(dosify)            zipwarn("file has ACL, may be incompatible with PKUNZIP","");        f = (struct PK_field *)p;        f->tag = ATR$C_ADDACLENT;        f->size = ctx->acllen;        memcpy((char *)&(f->value[0]),ctx->aclbuf,ctx->acllen);        p += PK_FLDHDR_SIZE + ctx->acllen;    }    h->crc32 = crc32(0L, (uch *)NULL, 0);   /* Init CRC register */    h->crc32 = crc32(h->crc32, (uch *)(h->data), l - PK_HEADER_SIZE);    z->ext = z->cext = l;    z->extra = z->cextra = (char *)b;}int vms_close(ctx)struct ioctx *ctx;{        sys$dassgn(ctx->chan);        free(ctx);        return 0;}#endif /* !_UTIL */#endif /* VMS */

⌨️ 快捷键说明

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