vms.c
来自「压缩算法的源代码」· C语言 代码 · 共 2,500 行 · 第 1/5 页
C
2,500 行
/*---------------------------------------------------------------------------
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 CN.
---------------------------------------------------------------------------
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.
Revision history:
1.x [moved to History.510 for brevity]
2.0 Mandrichenko 7-apr-1993
Implement PKWARE style VMS file attributes
2.0-1 Mandrichenko 10-apr-1993
ACL handling code added.
2.1 Mandrichenko 24-aug-1993
Get both PKWARE and new INFO-ZIP signatures as equivalent
Use vmsmunch.h instead of fatdef.h
2.2 Cave Newt 3-oct-1993
Merged GRR 5.1e changes with latest Igor version: open_outfile,
close_outfile, check_for_newer, UpdateCRC, flush, no ZIPINFO,
ctype.h, pInfo->textmode, etc. Also merged new do_wild/mapname/
checkdir routines from Igor and moved VMSmunch.h into vms.h.
2.2-1 Mandrichenko 14-dec-1993
Bug fixes in mapname/checkdir stuff.
_flush_stream() rewritten to fix some bugs.
2.2-2 Goathunter 3 Jan 94
Fixes for Alpha-VMS.
2.2-3 Cave Newt 11 Jan 94
Disabled version-check by default; enable with CHECK_VERSIONS.
Installed Igor's ctrl-Z patch.
2.2-4 Mandrichenko 18 Jan 94
Fixed auto-appending of ".zip" and inability to create second
level of directory structure.
2.2-5 Cave Newt, Mike Freeman 28 Jan 94
Changed close_outfile() to return void for compatibility;
fixed declaration of second parameter to flush() (ulg size);
changed str[n]icmp() to STR[N]ICMP().
2.2-6 Christian Spieler 9 Apr 94
Numerous bug fixes/improvements.
2.2-7 Cave Newt 11 Apr 94
Fixed version-number/semicolon bug.
2.3 Cave Newt 21 Jun 94
Added prototype version() routine.
2.3-1 Cave Newt 1 Jul 94
*Really* fixed version-number/semicolon bug.
2.3-2 Rodney Brown 10 Jul 94
Added VMS status/severity level (define RETURN_SEVERITY)
2.3-3 Charles Bailey 10 Aug 94
Fixed severity levels.
2.3-4 CN, CS, IM, RB 16 Aug 94
Further severity tweaks; do_wild() bugfix (CS)
2.3-5 CS, CN, IM, GH 18 Aug 94
Further do_wild() modifications and fixes.
2.3-6 Christian Spieler 23 Aug 94
Added lots of typecasts and fixed some initializations for DEC C.
---------------------------------------------------------------------------*/
#ifdef VMS /* VMS only ! */
#include "unzip.h"
#include "vms.h" /* now includes VMSmunch.h */
#define BUFS512 8192*2 /* Must be a multiple of 512 */
#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 = 0;
static struct RAB *outrab = 0;
static struct XABFHC *xabfhc = 0;
static struct XABDAT *xabdat = 0;
static struct XABRDT *xabrdt = 0;
static struct XABPRO *xabpro = 0;
static struct XABKEY *xabkey = 0;
static struct XABALL *xaball = 0;
struct XAB *first_xab = 0L, *last_xab = 0L;
static char query = 0;
static int text_output = 0,
raw_input,
hostnum;
static uch rfm;
static uch locbuf[BUFS512];
static int loccnt = 0;
static uch *locptr;
static char got_eol = 0;
static int _flush_blocks(),
_flush_stream(),
_flush_varlen(),
_flush_qio(),
_close_qio(),
_close_rms(),
WriteRecord(),
WriteBuffer(),
find_eol();
static int (*_flush_routine)(),
(*_close_routine)();
static int get_vms_version();
static int replace();
static uch *extract_block();
static void init_buf_ring();
static void decompress_bits();
static void UpdateCRC();
static void message();
static void free_up();
struct bufdsc
{
struct bufdsc *next;
uch *buf;
int bufcnt;
};
static struct bufdsc b1, b2, *curbuf;
static uch buf1[BUFS512];
int check_format()
{
int rtype;
struct FAB fab;
fab = cc$rms_fab;
fab.fab$l_fna = zipfn;
fab.fab$b_fns = strlen(zipfn);
sys$open(&fab);
rtype = fab.fab$b_rfm;
sys$close(&fab);
if (rtype == FAB$C_VAR || rtype == FAB$C_VFC)
{
fprintf(stderr,
"\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.c and make_bilf.com are included in the\n\
VMS UnZip source distribution.)\n\n", 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;
static int create_default_output(),
create_rms_output(),
create_qio_output();
/*
* open_outfile() assignments:
*
* VMS attributes ? create_xxx _flush_xxx
* ---------------- ---------- ----------
* not found 'default' text mode ?
* yes -> 'stream'
* no -> 'block'
*
* yes, in IZ format 'rms' text mode ?
* yes -> switch(fab.rfm)
* VAR -> 'varlen'
* STM* -> 'stream'
* default -> 'block'
* no -> 'block'
*
* yes, in PK format 'qio' 'qio'
*
* "text mode" == pInfo -> text || cflag
*/
int open_outfile()
{
switch(vet = find_vms_attrs())
{ case VAT_NONE:
default:
return create_default_output();
case VAT_IZ:
return create_rms_output();
case VAT_PK:
return create_qio_output();
}
}
static void init_buf_ring()
{
locptr = &locbuf[0];
loccnt = 0;
b1.buf = &locbuf[0];
b1.bufcnt = 0;
b1.next = &b2;
b2.buf = &buf1[0];
b2.bufcnt = 0;
b2.next = &b1;
curbuf = &b1;
}
static int create_default_output()
{
int ierr, yr, mo, dy, hh, mm, ss;
char timbuf[24]; /* length = first entry in "stupid" + 1 */
int attr_given; /* =1 if VMS attributes are present in
* extra_field */
rab = cc$rms_rab; /* fill FAB & RAB with default values */
fileblk = cc$rms_fab;
text_output = pInfo->textmode || cflag; /* extract the file in text
* (variable-length) format */
hostnum = pInfo -> hostnum;
outfab = &fileblk;
outfab->fab$l_xab = 0L;
rfm = FAB$C_STMLF; /* Default, stream-LF format from VMS
* or UNIX */
if (text_output)
{ /* Default format for output text file */
outfab->fab$b_rfm = FAB$C_VAR; /* variable length records */
outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
}
else
{ /* Default format for output binary file */
outfab->fab$b_rfm = FAB$C_STMLF; /* stream-LF record format */
outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
}
if (!cflag) /* Redirect output */
outfab->fab$l_fna = filename;
else
outfab->fab$l_fna = "sys$output:";
outfab->fab$b_fns = strlen(outfab->fab$l_fna);
{
static char *month[] =
{"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
/* fixed-length string descriptor: */
struct dsc$descriptor stupid =
{23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
dy = (lrec.last_mod_file_date & 0x1f);
hh = (lrec.last_mod_file_time >> 11) & 0x1f;
mm = (lrec.last_mod_file_time >> 5) & 0x3f;
ss = (lrec.last_mod_file_time & 0x1f) * 2;
dattim = cc$rms_xabdat; /* fill XABs with default values */
rdt = cc$rms_xabrdt;
sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
hh, mm, ss);
sys$bintim(&stupid, &dattim.xab$q_cdt);
memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
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 */
ierr = sys$create(outfab);
if (ierr == RMS$_FEX)
ierr = replace();
if (ierr == 0) /* Canceled */
return free_up(), 1;
if (ERR(ierr))
{
char buf[256];
sprintf(buf, "[ Cannot create output file %s ]\n", filename);
message(buf, ierr);
message("", outfab->fab$l_stv);
free_up();
return PK_WARN;
}
if (!text_output) /* Do not reopen text files and stdout
* Just open them in right mode */
{
/*
* Reopen file for Block I/O with no XABs.
*/
if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
{
#ifdef DEBUG
message("[ create_output_file: sys$close failed ]\n", ierr);
message("", outfab->fab$l_stv);
#endif
fprintf(stderr, "Can't create output file: %s\n", filename);
free_up();
return PK_WARN;
}
outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT; /* Get ready for block
* output */
outfab->fab$l_xab = 0L; /* Unlink all XABs */
if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
{
char buf[256];
sprintf(buf, "[ Cannot open output file %s ]\n", filename);
message(buf, ierr);
message("", 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.rab$l_rop |= RAB$M_ASY;
}
rab.rab$b_rac = RAB$C_SEQ;
if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
{
#ifdef DEBUG
message("create_output_file: sys$connect failed.\n", ierr);
message("", outfab->fab$l_stv);
#endif
fprintf(stderr, "Can't create output file: %s\n", filename);
free_up();
return PK_WARN;
}
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()
{
int ierr, yr, mo, dy, hh, mm, ss;
char timbuf[24]; /* length = first entry in "stupid" + 1 */
rab = cc$rms_rab; /* fill FAB & RAB with default values */
fileblk = cc$rms_fab;
text_output = cflag; /* extract the file in text (variable-length)
* format; ignore -a when attributes saved */
hostnum = pInfo -> hostnum;
if (cflag)
{
if(!PRINTABLE_FORMAT(rfm=outfab->fab$b_rfm))
{ printf("[ File %s has illegal record format to put to screen ]\n",
filename);
free_up();
return PK_DISK;
}
}
if (!cflag) /* Redirect output */
outfab->fab$l_fna = filename;
else
outfab->fab$l_fna = "sys$output:";
outfab->fab$b_fns = strlen(outfab->fab$l_fna);
if (!(xabdat && xabrdt)) /* Use date/time info
* from zipfile if
* no attributes given
*/
{
static char *month[] =
{"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
/* fixed-length string descriptor: */
struct dsc$descriptor stupid =
{23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
dy = (lrec.last_mod_file_date & 0x1f);
hh = (lrec.last_mod_file_time >> 11) & 0x1f;
mm = (lrec.last_mod_file_time >> 5) & 0x3f;
ss = (lrec.last_mod_file_time & 0x1f) * 2;
dattim = cc$rms_xabdat; /* fill XABs with default values */
rdt = cc$rms_xabrdt;
sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
hh, mm, ss);
sys$bintim(&stupid, &dattim.xab$q_cdt);
memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
if (xabdat == 0L)
{
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 */
ierr = sys$create(outfab);
if (ierr == RMS$_FEX)
ierr = replace();
if (ierr == 0) /* Canceled */
return free_up(), 1;
if (ERR(ierr))
{
char buf[256];
sprintf(buf, "[ Cannot create output file %s ]\n", filename);
message(buf, ierr);
message("", outfab->fab$l_stv);
free_up();
return PK_WARN;
}
if (!text_output) /* Do not reopen text files and stdout
* Just open them in right mode */
{
/*
* Reopen file for Block I/O with no XABs.
*/
if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
{
#ifdef DEBUG
message("[ create_output_file: sys$close failed ]\n", ierr);
message("", outfab->fab$l_stv);
#endif
fprintf(stderr, "Can't create output file: %s\n", filename);
free_up();
return PK_WARN;
}
outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT; /* Get ready for block
* output */
outfab->fab$l_xab = 0L; /* Unlink all XABs */
if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
{
char buf[256];
sprintf(buf, "[ Cannot open output file %s ]\n", filename);
message(buf, ierr);
message("", outfab->fab$l_stv);
free_up();
return PK_WARN;
}
}
outrab = &rab;
rab.rab$l_fab = outfab;
if (!text_output)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?