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 + -
显示快捷键?