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