?? vms.c
字號:
/* Copyright (c) 1990-2002 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 <lib$routines.h>#include <unixlib.h>#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);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{ 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; 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; int text_output, bin_fixed; /* extract the file in text (variable-length) format, when * a) explicitely requested by the user (through the -a option) * or * b) piping to SYS$OUTPUT, unless "binary" piping was requested * by the user (through the -b option) */ text_output = G.pInfo->textmode || (uO.cflag && (!uO.bflag || (!(uO.bflag - 1) && G.pInfo->textfile))); /* use fixed length 512 byte record format for disk file when * a) explicitly requested by the user (-b option) * and * b) entry is not extracted in text mode */ bin_fixed = !text_output && (uO.bflag != 0) && ((uO.bflag != 1) || !G.pInfo->textfile); 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", FnFilter1(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; int text_output; /* extract the file in text (variable-length) format, when * piping to SYS$OUTPUT, unless "binary" piping was requested * by the user (through the -b option); the "-a" option is * ignored when extracting zip entries with VMS attributes saved */ text_output = uO.cflag && (!uO.bflag || (!(uO.bflag - 1) && G.pInfo->textfile)); rfm = outfab->fab$b_rfm; /* Use record format from VMS extra field */ if (uO.cflag) { if (text_output && !PRINTABLE_FORMAT(rfm)) { Info(slide, 1, ((char *)slide, "[ File %s has illegal record format to put to screen ]\n", FnFilter1(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);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -