📄 vms.c
字号:
/*--------------------------------------------------------------------------- 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 screenlines() version() --------------------------------------------------------------------------- Portions copyright (C) 1992-93 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. ---------------------------------------------------------------------------*/#ifdef VMS /* VMS only! */#define UNZIP_INTERNAL#include "unzip.h"#include "vms.h"#include "vmsdefs.h"#include <lib$routines.h>#include <unixlib.h>#define ASYNCH_QIO /* Try out asynchronous PK-style QIO writes */#define BUFS512 (OUTBUFSIZ&(~512)) /* Must be a multiple of 512 ! */#define BUFDBLS512 (BUFS512 * 2) /* locbuf size, max. record 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 int text_output = 0, bin_fixed = 0;#ifdef USE_ORIG_DOSstatic int hostnum;#endifstatic uch rfm;static uch locbuf[BUFDBLS512]; /* 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 uch *extract_block(__GPRO__ struct IZ_block *p, int *retlen, uch *init, int needlen);static void decompress_bits(uch *outptr, int needlen, uch *bitptr);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);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", 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", 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 */static int vet;/* * 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 */int open_outfile(__G) /* return 1 (PK_WARN) if fail */ __GDEF{ switch(vet = 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; hh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f; mm = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f; ss = (G.lrec.last_mod_dos_datetime << 1) & 0x3e; }#else /* !USE_EF_UT_TIME */ 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; hh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f; mm = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f; ss = (G.lrec.last_mod_dos_datetime << 1) & 0x1f;#endif /* ?USE_EF_UT_TIME */ dattim = cc$rms_xabdat; /* fill XABs with default values */ rdt = cc$rms_xabrdt; sprintf(timbuf, "%02u-%3s-%04u %02u:%02u:%02u.00", dy, month[mo], yr, hh, mm, ss); sys$bintim(&date_str, &dattim.xab$q_cdt); memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));}static int create_default_output(__GPRO) /* return 1 (PK_WARN) if fail */{ int ierr; text_output = G.pInfo->textmode || uO.cflag; /* extract the file in text * (variable-length) format */ bin_fixed = text_output || (uO.bflag == 0) ? 0 : ((uO.bflag - 1) ? 1 : !G.pInfo->textfile);#ifdef USE_ORIG_DOS hostnum = G.pInfo->hostnum;#endif rfm = FAB$C_STMLF; /* Default, stream-LF format from VMS or UNIX */ if (!uO.cflag) /* Redirect output */ { rab = cc$rms_rab; /* fill RAB with default values */ fileblk = cc$rms_fab; /* fill FAB with default values */ outfab = &fileblk; outfab->fab$l_xab = NULL; if (text_output) { /* Default format for output `real' text file */ outfab->fab$b_rfm = FAB$C_VAR; /* variable length records */ outfab->fab$b_rat = FAB$M_CR; /* implied (CR) carriage ctrl */ } else if (bin_fixed) { /* Default format for output `real' binary file */ outfab->fab$b_rfm = FAB$C_FIX; /* fixed length record format */ outfab->fab$w_mrs = 512; /* record size 512 bytes */ outfab->fab$b_rat = 0; /* no carriage ctrl */ } else { /* Default format for output misc (bin or text) file */ outfab->fab$b_rfm = FAB$C_STMLF; /* stream-LF record format */ outfab->fab$b_rat = FAB$M_CR; /* implied (CR) carriage ctrl */ } outfab->fab$l_fna = G.filename; outfab->fab$b_fns = strlen(outfab->fab$l_fna); { set_default_datetime_XABs(__G); dattim.xab$l_nxt = outfab->fab$l_xab; outfab->fab$l_xab = (void *) &dattim; } outfab->fab$w_ifi = 0; /* Clear IFI. It may be nonzero after ZIP */ outfab->fab$b_fac = FAB$M_BRO | FAB$M_PUT; /* {block|record} output */ ierr = sys$create(outfab); if (ierr == RMS$_FEX) ierr = replace(__G); if (ierr == 0) /* Canceled */ return (free_up(), PK_WARN); if (ERR(ierr)) { char buf[256]; sprintf(buf, "[ Cannot create output file %s ]\n", G.filename); vms_msg(__G__ buf, ierr); vms_msg(__G__ "", outfab->fab$l_stv); free_up(); return PK_WARN; } outrab = &rab; rab.rab$l_fab = outfab; if (!text_output) { rab.rab$l_rop |= (RAB$M_BIO | RAB$M_ASY); } rab.rab$b_rac = RAB$C_SEQ; if ((ierr = sys$connect(outrab)) != RMS$_NORMAL) {#ifdef DEBUG vms_msg(__G__ "create_default_output: sys$connect failed.\n", ierr); vms_msg(__G__ "", outfab->fab$l_stv);#endif Info(slide, 1, ((char *)slide, "Can't create output file: %s\n", G.filename)); free_up(); return PK_WARN; } } /* end if (!uO.cflag) */ init_buf_ring(); _flush_routine = text_output ? got_eol=0,_flush_stream : _flush_blocks; _close_routine = _close_rms; return PK_COOL;}static int create_rms_output(__GPRO) /* return 1 (PK_WARN) if fail */{ int ierr; text_output = uO.cflag; /* extract the file in text * (variable-length) format; * we ignore "-a" when attributes saved */#ifdef USE_ORIG_DOS hostnum = G.pInfo->hostnum;#endif rfm = outfab->fab$b_rfm; /* Use record format from VMS extra field */ if (uO.cflag) { if (!PRINTABLE_FORMAT(rfm)) { Info(slide, 1, ((char *)slide, "[ File %s has illegal record format to put to screen ]\n", G.filename)); free_up(); return PK_WARN; } } else /* Redirect output */ { rab = cc$rms_rab; /* fill RAB with default values */ /* The output FAB has already been initialized with the values * found in the Zip file's "VMS attributes" extra field */ outfab->fab$l_fna = G.filename; outfab->fab$b_fns = strlen(outfab->fab$l_fna); if (!(xabdat && xabrdt)) /* Use date/time info * from zipfile if * no attributes given */ { set_default_datetime_XABs(__G); if (xabdat == NULL) { dattim.xab$l_nxt = outfab->fab$l_xab; outfab->fab$l_xab = (void *) &dattim; } } outfab->fab$w_ifi = 0; /* Clear IFI. It may be nonzero after ZIP */ outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT; /* block-mode output */ ierr = sys$create(outfab); if (ierr == RMS$_FEX) ierr = replace(__G); if (ierr == 0) /* Canceled */ return (free_up(), PK_WARN); if (ERR(ierr)) { char buf[256];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -