📄 vms.c
字号:
/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in unzip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html*//*--------------------------------------------------------------------------- vms.c Igor Mandrichenko and others This file contains routines to extract VMS file attributes from a zipfile extra field and create a file with these attributes. The code was almost entirely written by Igor, with a couple of routines by GRR and lots of modifications and fixes by Christian Spieler. Contains: check_format() open_outfile() find_vms_attrs() flush() close_outfile() dos_to_unix_time() (TIMESTAMP only) stamp_file() (TIMESTAMP only) do_wild() mapattr() mapname() checkdir() check_for_newer() return_VMS screensize() screenlinewrap() version() ---------------------------------------------------------------------------*/#ifdef VMS /* VMS only! */#define UNZIP_INTERNAL#include "unzip.h"#include "vms.h"#include "vmsdefs.h"#ifdef MORE# include <ttdef.h>#endif#include <unixlib.h>#include <lib$routines.h>#include <stsdef.h>/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc. Otherwise, lame system headers on VAX cause compiler warnings. (GNU C may define vax but not __VAX.)*/#ifdef vax# define __VAX 1#endif#ifdef __VAX# define GVTC (unsigned int)#else# define GVTC#endif/* With GNU C, some FAB bits may be declared only as masks, not as * structure bits. */#ifdef __GNUC__# define OLD_FABDEF 1#endif#define ASYNCH_QIO /* Use asynchronous PK-style QIO writes *//* buffer size for a single block write (using RMS or QIO WRITEVBLK), must be less than 64k and a multiple of 512 ! */#define BUFS512 (((OUTBUFSIZ>0xFFFF) ? 0xFFFF : OUTBUFSIZ) & (~511))/* buffer size for record output (RMS limit for max. record size) */#define BUFSMAXREC 32767/* allocation size for RMS and QIO output buffers */#define BUFSALLOC (BUFS512 * 2 > BUFSMAXREC ? BUFS512 * 2 : BUFSMAXREC) /* locbuf size */#define OK(s) ((s)&1) /* VMS success or warning status */#define STRICMP(s1,s2) STRNICMP(s1,s2,2147483647)/* * Local static storage */static struct FAB fileblk;static struct XABDAT dattim;static struct XABRDT rdt;static struct RAB rab;static struct NAM nam;static struct FAB *outfab = NULL;static struct RAB *outrab = NULL;static struct XABFHC *xabfhc = NULL;static struct XABDAT *xabdat = NULL;static struct XABRDT *xabrdt = NULL;static struct XABPRO *xabpro = NULL;static struct XABKEY *xabkey = NULL;static struct XABALL *xaball = NULL;static struct XAB *first_xab = NULL, *last_xab = NULL;static char query = '\0';static uch rfm;static uch locbuf[BUFSALLOC]; /* Space for 2 buffers of BUFS512 */static unsigned loccnt = 0;static uch *locptr;static char got_eol = 0;struct bufdsc{ struct bufdsc *next; uch *buf; unsigned bufcnt;};static struct bufdsc b1, b2, *curbuf; /* buffer ring for asynchronous I/O */static int _flush_blocks(__GPRO__ uch *rawbuf, unsigned size, int final_flag), _flush_stream(__GPRO__ uch *rawbuf, unsigned size, int final_flag), _flush_varlen(__GPRO__ uch *rawbuf, unsigned size, int final_flag), _flush_qio(__GPRO__ uch *rawbuf, unsigned size, int final_flag), _close_rms(__GPRO), _close_qio(__GPRO),#ifdef ASYNCH_QIO WriteQIO(__GPRO__ uch *buf, unsigned len),#endif WriteBuffer(__GPRO__ uch *buf, unsigned len), WriteRecord(__GPRO__ uch *rec, unsigned len);static int (*_flush_routine)(__GPRO__ uch *rawbuf, unsigned size, int final_flag), (*_close_routine)(__GPRO);static void init_buf_ring(void);static void set_default_datetime_XABs(__GPRO);static int create_default_output(__GPRO), create_rms_output(__GPRO), create_qio_output(__GPRO);static int replace(__GPRO);static int find_vms_attrs(__GPRO);static void free_up(void);#ifdef CHECK_VERSIONSstatic int get_vms_version(char *verbuf, int len);#endif /* CHECK_VERSIONS */static unsigned find_eol(uch *p, unsigned n, unsigned *l);#ifdef TIMESTAMPstatic time_t mkgmtime(struct tm *tm);static void uxtime2vmstime(time_t utimeval, long int binval[2]);#endif /* TIMESTAMP */static void vms_msg(__GPRO__ char *string, int status);/* 2004-11-23 SMS. * * get_rms_defaults(). * * Get user-specified values from (DCL) SET RMS_DEFAULT. FAB/RAB * items of particular interest are: * * fab$w_deq default extension quantity (blocks) (write). * rab$b_mbc multi-block count. * rab$b_mbf multi-buffer count (used with rah and wbh). */#define DIAG_FLAG (uO.vflag >= 2)/* Default RMS parameter values. * The default extend quantity (deq) should not matter much here, as the * initial allocation should always be set according to the known file * size, and no extension should be needed. */#define RMS_DEQ_DEFAULT 16384 /* About 1/4 the max (65535 blocks). */#define RMS_MBC_DEFAULT 127 /* The max, */#define RMS_MBF_DEFAULT 2 /* Enough to enable rah and wbh. *//* GETJPI item descriptor structure. */typedef struct{ short buf_len; short itm_cod; void *buf; int *ret_len;} jpi_item_t;/* Durable storage */static int rms_defaults_known = 0;/* JPI item buffers. */static unsigned short rms_ext;static char rms_mbc;static unsigned char rms_mbf;/* Active RMS item values. */unsigned short rms_ext_active;char rms_mbc_active;unsigned char rms_mbf_active;/* GETJPI item lengths. */static int rms_ext_len; /* Should come back 2. */static int rms_mbc_len; /* Should come back 1. */static int rms_mbf_len; /* Should come back 1. *//* Desperation attempts to define unknown macros. Probably doomed. * If these get used, expect sys$getjpiw() to return %x00000014 = * %SYSTEM-F-BADPARAM, bad parameter value. * They keep compilers with old header files quiet, though. */#ifndef JPI$_RMS_EXTEND_SIZE# define JPI$_RMS_EXTEND_SIZE 542#endif /* ndef JPI$_RMS_EXTEND_SIZE */#ifndef JPI$_RMS_DFMBC# define JPI$_RMS_DFMBC 535#endif /* ndef JPI$_RMS_DFMBC */#ifndef JPI$_RMS_DFMBFSDK# define JPI$_RMS_DFMBFSDK 536#endif /* ndef JPI$_RMS_DFMBFSDK *//* GETJPI item descriptor set. */struct{ jpi_item_t rms_ext_itm; jpi_item_t rms_mbc_itm; jpi_item_t rms_mbf_itm; int term;} jpi_itm_lst = { { 2, JPI$_RMS_EXTEND_SIZE, &rms_ext, &rms_ext_len }, { 1, JPI$_RMS_DFMBC, &rms_mbc, &rms_mbc_len }, { 1, JPI$_RMS_DFMBFSDK, &rms_mbf, &rms_mbf_len }, 0 };static int get_rms_defaults(){ int sts; /* Get process RMS_DEFAULT values. */ sts = sys$getjpiw(0, 0, 0, &jpi_itm_lst, 0, 0, 0); if ((sts& STS$M_SEVERITY) != STS$M_SUCCESS) { /* Failed. Don't try again. */ rms_defaults_known = -1; } else { /* Fine, but don't come back. */ rms_defaults_known = 1; } /* Limit the active values according to the RMS_DEFAULT values. */ if (rms_defaults_known > 0) { /* Set the default values. */ rms_ext_active = RMS_DEQ_DEFAULT; rms_mbc_active = RMS_MBC_DEFAULT; rms_mbf_active = RMS_MBF_DEFAULT; /* Default extend quantity. Use the user value, if set. */ if (rms_ext > 0) { rms_ext_active = rms_ext; } /* Default multi-block count. Use the user value, if set. */ if (rms_mbc > 0) { rms_mbc_active = rms_mbc; } /* Default multi-buffer count. Use the user value, if set. */ if (rms_mbf > 0) { rms_mbf_active = rms_mbf; } } if (DIAG_FLAG) { fprintf(stderr, "Get RMS defaults. getjpi sts = %%x%08x.\n", sts); if (rms_defaults_known > 0) { fprintf(stderr, " Default: deq = %6d, mbc = %3d, mbf = %3d.\n", rms_ext, rms_mbc, rms_mbf); } } return sts;}int check_format(__G) __GDEF{ int rtype; struct FAB fab; fab = cc$rms_fab; fab.fab$l_fna = G.zipfn; fab.fab$b_fns = strlen(G.zipfn); if ((sys$open(&fab) & 1) == 0) { Info(slide, 1, ((char *)slide, "\n\ error: cannot open zipfile [ %s ] (access denied?).\n\n", FnFilter1(G.zipfn))); return PK_ERR; } rtype = fab.fab$b_rfm; sys$close(&fab); if (rtype == FAB$C_VAR || rtype == FAB$C_VFC) { Info(slide, 1, ((char *)slide, "\n\ Error: zipfile is in variable-length record format. Please\n\ run \"bilf l %s\" to convert the zipfile to stream-LF\n\ record format. (BILF is available at various VMS archives.)\n\n", FnFilter1(G.zipfn))); return PK_ERR; } return PK_COOL;}#define PRINTABLE_FORMAT(x) ( (x) == FAB$C_VAR \ || (x) == FAB$C_STMLF \ || (x) == FAB$C_STMCR \ || (x) == FAB$C_STM )/* VMS extra field types */#define VAT_NONE 0#define VAT_IZ 1 /* old Info-ZIP format */#define VAT_PK 2 /* PKWARE format *//* * open_outfile() assignments: * * VMS attributes ? create_xxx _flush_xxx * ---------------- ---------- ---------- * not found 'default' text mode ? * yes -> 'stream' * no -> 'block' * * yes, in IZ format 'rms' uO.cflag ? * yes -> switch (fab.rfm) * VAR -> 'varlen' * STM* -> 'stream' * default -> 'block' * no -> 'block' * * yes, in PK format 'qio' uO.cflag ? * yes -> switch (pka_rattr) * VAR -> 'varlen' * STM* -> 'stream' * default -> 'block' * no -> 'qio' * * "text mode" == G.pInfo->textmode || (uO.cflag && !uO.bflag) * (simplified, for complete expression see create_default_output() code) */int open_outfile(__G) /* return 1 (PK_WARN) if fail */ __GDEF{ /* Get process RMS_DEFAULT values, if not already done. */ if (rms_defaults_known == 0) { get_rms_defaults(); } switch (find_vms_attrs(__G)) { case VAT_NONE: default: return create_default_output(__G); case VAT_IZ: return create_rms_output(__G); case VAT_PK: return create_qio_output(__G); }}static void init_buf_ring(){ locptr = &locbuf[0]; loccnt = 0; b1.buf = &locbuf[0]; b1.bufcnt = 0; b1.next = &b2; b2.buf = &locbuf[BUFS512]; b2.bufcnt = 0; b2.next = &b1; curbuf = &b1;}/* Static data storage for time conversion: *//* string constants for month names */static ZCONST char *month[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};/* buffer for time string */static char timbuf[24]; /* length = first entry in "date_str" + 1 *//* fixed-length string descriptor for timbuf: */static ZCONST struct dsc$descriptor date_str = {sizeof(timbuf)-1, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};static void set_default_datetime_XABs(__GPRO){ unsigned yr, mo, dy, hh, mm, ss;#ifdef USE_EF_UT_TIME iztimes z_utime; struct tm *t; if (G.extra_field &&#ifdef IZ_CHECK_TZ G.tz_is_valid &&#endif (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0, G.lrec.last_mod_dos_datetime, &z_utime, NULL) & EB_UT_FL_MTIME)) t = localtime(&(z_utime.mtime)); else t = (struct tm *)NULL; if (t != (struct tm *)NULL) { yr = t->tm_year + 1900; mo = t->tm_mon; dy = t->tm_mday; hh = t->tm_hour; mm = t->tm_min; ss = t->tm_sec; } else { yr = ((G.lrec.last_mod_dos_datetime >> 25) & 0x7f) + 1980; mo = ((G.lrec.last_mod_dos_datetime >> 21) & 0x0f) - 1; dy = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -