vms.c
来自「压缩算法的源代码」· C语言 代码 · 共 2,500 行 · 第 1/5 页
C
2,500 行
{ 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();
if( text_output )
switch(rfm)
{
case FAB$C_VAR:
_flush_routine = _flush_varlen;
break;
case FAB$C_STM:
case FAB$C_STMCR:
case FAB$C_STMLF:
_flush_routine = _flush_stream;
got_eol = 0;
break;
default:
_flush_routine = _flush_blocks;
break;
}
else
_flush_routine = _flush_blocks;
_close_routine = _close_rms;
return PK_COOL;
}
static int pka_devchn;
static int pka_vbn;
static struct
{ short status;
long count;
short dummy;
} pka_io_sb;
static struct
{ short status;
short dummy;
void *addr;
} pka_acp_sb;
static struct fibdef pka_fib;
static struct atrdef pka_atr[VMS_MAX_ATRCNT];
static int pka_idx;
static ulg pka_uchar;
static struct fatdef pka_rattr;
static struct dsc$descriptor pka_fibdsc =
{ sizeof(pka_fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (void *) &pka_fib };
static struct dsc$descriptor_s pka_devdsc =
{ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &nam.nam$t_dvi[1] };
static struct dsc$descriptor_s pka_fnam =
{ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
static int create_qio_output()
{ int status;
static char exp_nam[NAM$C_MAXRSS];
static char res_nam[NAM$C_MAXRSS];
int i;
if( cflag )
{ fprintf(stderr,"[ Cannot put to screen ]\n");
return PK_DISK;
}
fileblk = cc$rms_fab;
fileblk.fab$l_fna = filename;
fileblk.fab$b_fns = strlen(filename);
nam = cc$rms_nam;
fileblk.fab$l_nam = &nam;
nam.nam$l_esa = exp_nam;
nam.nam$b_ess = sizeof(exp_nam);
nam.nam$l_rsa = res_nam;
nam.nam$b_rss = sizeof(res_nam);
if( ERR(status = sys$parse(&fileblk)) )
{ message("create_output_file: sys$parse failed.\n", status);
return PK_DISK;
}
pka_devdsc.dsc$w_length = (unsigned short)nam.nam$t_dvi[0];
if( ERR(status = sys$assign(&pka_devdsc,&pka_devchn,0,0)) )
{ message("sys$assign failed.\n",status);
return PK_DISK;
}
pka_fnam.dsc$a_pointer = nam.nam$l_name;
pka_fnam.dsc$w_length = nam.nam$b_name + nam.nam$b_type;
if( V_flag /* keep versions */ )
pka_fnam.dsc$w_length += nam.nam$b_ver;
for (i=0;i<3;i++)
{ pka_fib.FIB$W_DID[i]=nam.nam$w_did[i];
pka_fib.FIB$W_FID[i]=0;
}
pka_fib.FIB$L_ACCTL = FIB$M_WRITE;
/* Allocate space for the file */
pka_fib.FIB$W_EXCTL = FIB$M_EXTEND;
if( pka_uchar & FCH$M_CONTIG )
pka_fib.FIB$W_EXCTL |= FIB$M_ALCON | FIB$M_FILCON;
if( pka_uchar & FCH$M_CONTIGB )
pka_fib.FIB$W_EXCTL |= FIB$M_ALCONB;
#define SWAPW(x) ( (((x)>>16)&0xFFFF) + ((x)<<16) )
pka_fib.fib$l_exsz = SWAPW(pka_rattr.fat$r_hiblk_overlay.fat$l_hiblk);
status = sys$qiow(0, pka_devchn, IO$_CREATE|IO$M_CREATE|IO$M_ACCESS,
&pka_acp_sb, 0, 0,
&pka_fibdsc, &pka_fnam, 0, 0, &pka_atr, 0);
if( !ERR(status) )
status = pka_acp_sb.status;
if( ERR(status) )
{ message("[ Create file QIO failed.\n",status);
return PK_DISK;
sys$dassgn(pka_devchn);
}
pka_vbn = 1;
_flush_routine = _flush_qio;
_close_routine = _close_qio;
return PK_COOL;
}
static int replace()
{ /*
* File exists. Inquire user about further action.
*/
char answ[10];
struct NAM nam;
int ierr;
if (query == 0)
{
do
{
fprintf(stderr,
"%s exists: [o]verwrite, new [v]ersion or [n]o extract?\n\
(uppercase response [O,V,N] = do same for all files): ",
filename);
fflush(stderr);
} while (fgets(answ, 9, stderr) == NULL && !isalpha(answ[0])
&& tolower(answ[0]) != 'o'
&& tolower(answ[0]) != 'v'
&& tolower(answ[0]) != 'n');
if (isupper(answ[0]))
query = answ[0] = tolower(answ[0]);
}
else
answ[0] = query;
switch (answ[0])
{
case 'n':
ierr = 0;
break;
case 'v':
nam = cc$rms_nam;
nam.nam$l_rsa = filename;
nam.nam$b_rss = FILNAMSIZ - 1;
outfab->fab$l_fop |= FAB$M_MXV;
outfab->fab$l_nam = &nam;
ierr = sys$create(outfab);
if (!ERR(ierr))
{
outfab->fab$l_nam = 0L;
filename[outfab->fab$b_fns = nam.nam$b_rsl] = 0;
}
break;
case 'o':
outfab->fab$l_fop |= FAB$M_SUP;
ierr = sys$create(outfab);
break;
}
return ierr;
}
#define W(p) (*(unsigned short*)(p))
#define L(p) (*(unsigned long*)(p))
#define EQL_L(a,b) ( L(a) == L(b) )
#define EQL_W(a,b) ( W(a) == W(b) )
/****************************************************************
* Function find_vms_attrs scans ZIP entry extra field if any *
* and looks for VMS attribute records. Returns 0 if either no *
* attributes found or no fab given. *
****************************************************************/
int find_vms_attrs()
{
uch *scan = extra_field;
struct EB_header *hdr;
int len;
int type=VAT_NONE;
outfab = NULL;
xabfhc = NULL;
xabdat = NULL;
xabrdt = NULL;
xabpro = NULL;
first_xab = last_xab = NULL;
if (scan == NULL)
return PK_COOL;
len = lrec.extra_field_length;
#define LINK(p) { /* Link xaballs and xabkeys into chain */ \
if( first_xab == 0L ) \
first_xab = (void *) p; \
if( last_xab != 0L ) \
last_xab -> xab$l_nxt = (void *) p; \
last_xab = (void *) p; \
p -> xab$l_nxt = 0; \
}
/* End of macro LINK */
while (len > 0)
{
hdr = (struct EB_header *) scan;
if (EQL_W(&hdr->tag, IZ_SIGNATURE))
{
/*
* INFO-ZIP style extra block decoding
*/
struct IZ_block *blk;
uch *block_id;
type = VAT_IZ;
blk = (struct IZ_block *)hdr;
block_id = (uch *) &blk->bid;
if (EQL_L(block_id, FABSIG))
{
outfab = (struct FAB *) extract_block(blk, 0,
&cc$rms_fab, FABL);
}
else if (EQL_L(block_id, XALLSIG))
{
xaball = (struct XABALL *) extract_block(blk, 0,
&cc$rms_xaball, XALLL);
LINK(xaball);
}
else if (EQL_L(block_id, XKEYSIG))
{
xabkey = (struct XABKEY *) extract_block(blk, 0,
&cc$rms_xabkey, XKEYL);
LINK(xabkey);
}
else if (EQL_L(block_id, XFHCSIG))
{
xabfhc = (struct XABFHC *) extract_block(blk, 0,
&cc$rms_xabfhc, XFHCL);
}
else if (EQL_L(block_id, XDATSIG))
{
xabdat = (struct XABDAT *) extract_block(blk, 0,
&cc$rms_xabdat, XDATL);
}
else if (EQL_L(block_id, XRDTSIG))
{
xabrdt = (struct XABRDT *) extract_block(blk, 0,
&cc$rms_xabrdt, XRDTL);
}
else if (EQL_L(block_id, XPROSIG))
{
xabpro = (struct XABPRO *) extract_block(blk, 0,
&cc$rms_xabpro, XPROL);
}
else if (EQL_L(block_id, VERSIG))
{
#ifdef CHECK_VERSIONS
char verbuf[80];
int verlen = 0;
uch *vers;
char *m;
get_vms_version(verbuf, 80);
vers = extract_block(blk, &verlen, 0, 0);
if ((m = strrchr((char *) vers, '-')) != NULL)
*m = 0; /* Cut out release number */
if (strcmp(verbuf, (char *) vers) && qflag < 2)
{
printf("[ Warning: VMS version mismatch.");
printf(" This version %s --", verbuf);
strncpy(verbuf, (char *) vers, verlen);
verbuf[verlen] = 0;
printf(" version made by %s ]\n", verbuf);
}
free(vers);
#endif
}
else
fprintf(stderr, "[ Warning: Unknown block signature %s ]\n",
block_id);
}
else if (hdr->tag == PK_SIGNATURE || hdr->tag == IZ_NEW_SIGNATURE)
{
/*
* PKWARE style extra block decoding
*/
struct PK_header *blk;
register byte *scn;
register int len;
type = VAT_PK;
blk = (struct PK_header *)hdr;
len = blk -> size;
scn = (byte *)(&blk->data);
pka_idx = 0;
while(len > PK_FLDHDR_SIZE)
{ register struct PK_field *fld;
int skip=0;
fld = (struct PK_field *)scn;
switch(fld->tag)
{ case ATR$C_UCHAR:
pka_uchar = L(&fld->value);
break;
case ATR$C_RECATTR:
pka_rattr = *(struct fatdef *)(&fld->value);
break;
case ATR$C_UIC:
case ATR$C_ADDACLENT:
skip = !secinf;
break;
}
if( !skip )
{ pka_atr[pka_idx].atr$w_size = fld->size;
pka_atr[pka_idx].atr$w_type = fld->tag;
pka_atr[pka_idx].atr$l_addr = &fld->value;
++pka_idx;
}
len -= fld->size + PK_FLDHDR_SIZE;
scn += fld->size + PK_FLDHDR_SIZE;
}
pka_atr[pka_idx].atr$w_size = 0; /* End of list */
pka_atr[pka_idx].atr$w_type = 0;
pka_atr[pka_idx].atr$l_addr = 0L;
}
len -= hdr->size + 4;
scan += hdr->size + 4;
}
if( type == VAT_IZ )
{ if (outfab != 0)
{ /* Do not link XABPRO,XABRDT now. Leave them for sys$close() */
outfab->fab$l_xab = 0L;
if (xabfhc != 0L)
{
xabfhc->xab$l_nxt = outfab->fab$l_xab;
outfab->fab$l_xab = (void *) xabfhc;
}
if (xabdat != 0L)
{
xabdat->xab$l_nxt = outfab->fab$l_xab;
outfab->fab$l_xab = (void *) xabdat;
}
if (first_xab != 0L) /* Link xaball,xabkey subchain */
{
last_xab->xab$l_nxt = outfab->fab$l_xab;
outfab->fab$l_xab = (void *) first_xab;
}
}
else
type = VAT_NONE;
}
return type;
}
static void free_up()
{ /*
* Free up all allocated xabs
*/
if (xabdat != 0L) free(xabdat);
if (xabpro != 0L) free(xabpro);
if (xabrdt != 0L) free(xabrdt);
if (xabfhc != 0L) free(xabfhc);
while (first_xab != 0L)
{
struct XAB *x;
x = (struct XAB *) first_xab->xab$l_nxt;
free(first_xab);
first_xab = x;
}
if (outfab != 0L && outfab != &fileblk)
free(outfab);
}
#ifdef CHECK_VERSIONS
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;
return strlen(verbuf) + 1; /* Transmit ending 0 too */
}
#endif /* CHECK_VERSIONS */
/*
* Extracts block from p. If resulting length is less then needed, fill
* extra space with corresponding bytes from 'init'.
* Currently understands 3 formats of block compression:
* - Simple storing
* - Compression of zero bytes to zero bits
* - Deflation (see memextract() in extract.c)
*/
static uch *extract_block(p, retlen, init, needlen)
struct IZ_block *p;
int *retlen;
uch *init;
int needlen;
{
uch *block; /* Pointer to block allocated */
int cmptype;
int usiz, csiz, max;
cmptype = p->flags & BC_MASK;
csiz = p->size - EXTBSL - RESL;
usiz = (cmptype == BC_STORED ? csiz : p->length);
if (needlen == 0)
needlen = usiz;
if (retlen)
*retlen = usiz;
#ifndef MAX
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
#endif
if ((block = (uch *) malloc(MAX(needlen, usiz))) == NULL)
return NULL;
if (init && (usiz < needlen))
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?