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 + -
显示快捷键?