📄 vms_im.c
字号:
/* 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 + -