vms.c

来自「压缩算法的源代码」· C语言 代码 · 共 2,500 行 · 第 1/5 页

C
2,500
字号
	{   if( WriteRecord(rawbuf+start, end-start) )
		return PK_DISK;
	    start = end + eol_len;
	}
	else
	{   got_eol = rawbuf[end];
	    end = size;
	    continue;
	}
    }

    rest = size - start;

    if (rest > 0)
    {	if( rest > BUFS512 )
	{   int	recsize;

	    recsize = rest - (got_eol ? 1:0 );
	    fprintf(stderr, "[ Warning: Record too long (%d) ]\n", recsize);
	    got_eol = 0;
	    return WriteRecord(rawbuf+start,recsize) ? PK_DISK : PK_COOL;
	}
	else
	{   memcpy(locptr, rawbuf + start, rest);
	    locptr += rest;
	    loccnt += rest;
	}
    }
    return PK_COOL;
}



static int WriteBuffer(buf, len)
    unsigned char *buf;
    int len;
{
    int status;

    status = sys$wait(outrab);
    if (ERR(status))
    {
	message("[ WriteBuffer failed ]\n", status);
	message("", outrab->rab$l_stv);
    }
    outrab->rab$w_rsz = len;
    outrab->rab$l_rbf = (char *) buf;

    if (ERR(status = sys$write(outrab)))
    {
	message("[ WriteBuffer failed ]\n", status);
	message("", outrab->rab$l_stv);
	return PK_DISK;
    }
    return PK_COOL;
}



static int WriteRecord(rec, len)
    unsigned char *rec;
    int len;
{
    int status;

    if (ERR(status = sys$wait(outrab)))
    {
	message("[ WriteRecord failed ]\n", status);
	message("", outrab->rab$l_stv);
    }
    outrab->rab$w_rsz = len;
    outrab->rab$l_rbf = (char *) rec;

    if (ERR(status = sys$put(outrab)))
    {
	message("[ WriteRecord failed ]\n", status);
	message("", outrab->rab$l_stv);
	return PK_DISK;
    }
    return PK_COOL;
}



void close_outfile()
{
    int status;

    status = (*_flush_routine)(0, 0, 1);     
    if (status)
        return /* PK_DISK */;
    if (cflag)
        return;         /* Don't close stdout */
    /* return */ (*_close_routine)();
}



static int _close_rms()
{
    int status;
    struct XABPRO pro;

    /* Link XABRDT,XABDAT and optionaly XABPRO */
    if (xabrdt != 0L)
    {
	xabrdt->xab$l_nxt = 0L;
	outfab->fab$l_xab = (void *) xabrdt;
    }
    else
    {
	rdt.xab$l_nxt = 0L;
	outfab->fab$l_xab = (void *) &rdt;
    }
    if (xabdat != 0L)
    {
	xabdat->xab$l_nxt = outfab->fab$l_xab;
	outfab->fab$l_xab = (void *)xabdat;
    }

    if( xabpro != 0L )
    {
	if( !secinf )
	    xabpro->xab$l_uic = 0;    /* Use default (user's) uic */
	xabpro->xab$l_nxt = outfab->fab$l_xab;
	outfab->fab$l_xab = (void *) xabpro;
    }
    else
    {	pro = cc$rms_xabpro;
	pro.xab$w_pro = pInfo->file_attr;
	pro.xab$l_nxt = outfab->fab$l_xab;
	outfab->fab$l_xab = (void *) &pro;
    }

    sys$wait(outrab);

    status = sys$close(outfab);
#ifdef DEBUG
    if (ERR(status))
    {
	message("\r[ Warning: cannot set owner/protection/time attributes ]\n",
	  status);
	message("", outfab->fab$l_stv);
    }
#endif
    free_up();
    return PK_COOL;
}



static int _close_qio()
{   int status;

    pka_fib.FIB$L_ACCTL =
	FIB$M_WRITE | FIB$M_NOTRUNC ;
    pka_fib.FIB$W_EXCTL = 0;

    pka_fib.FIB$W_FID[0] =
    pka_fib.FIB$W_FID[1] =
    pka_fib.FIB$W_FID[2] =
    pka_fib.FIB$W_DID[0] =
    pka_fib.FIB$W_DID[1] =
    pka_fib.FIB$W_DID[2] = 0;

    status = sys$qiow(0, pka_devchn, IO$_DEACCESS, &pka_acp_sb,
	    0, 0,
	    &pka_fibdsc, 0, 0, 0,
	    &pka_atr, 0);

    sys$dassgn(pka_devchn);
    if( !ERR(status) )
	status = pka_acp_sb.status;
    if( ERR(status) )
    {	message("[ Deaccess QIO failed ]\n",status);
	return PK_DISK;
    }
    return PK_COOL;
}



#ifdef DEBUG
dump_rms_block(p)
    unsigned char *p;
{
    unsigned char bid, len;
    int err;
    char *type;
    char buf[132];
    int i;

    err = 0;
    bid = p[0];
    len = p[1];
    switch (bid)
    {
	case FAB$C_BID:
	    type = "FAB";
	    break;
	case XAB$C_ALL:
	    type = "xabALL";
	    break;
	case XAB$C_KEY:
	    type = "xabKEY";
	    break;
	case XAB$C_DAT:
	    type = "xabDAT";
	    break;
	case XAB$C_RDT:
	    type = "xabRDT";
	    break;
	case XAB$C_FHC:
	    type = "xabFHC";
	    break;
	case XAB$C_PRO:
	    type = "xabPRO";
	    break;
	default:
	    type = "Unknown";
	    err = 1;
	    break;
    }
    printf("Block @%08X of type %s (%d).", p, type, bid);
    if (err)
    {
	printf("\n");
	return;
    }
    printf(" Size = %d\n", len);
    printf(" Offset - Hex - Dec\n");
    for (i = 0; i < len; i += 8)
    {
	int j;

	printf("%3d - ", i);
	for (j = 0; j < 8; j++)
	    if (i + j < len)
		printf("%02X ", p[i + j]);
	    else
		printf("   ");
	printf(" - ");
	for (j = 0; j < 8; j++)
	    if (i + j < len)
		printf("%03d ", p[i + j]);
	    else
		printf("    ");
	printf("\n");
    }
}

#endif				/* DEBUG */



static void message(string, status)
    int status;
char *string;
{
    char msgbuf[256];

    $DESCRIPTOR(msgd, msgbuf);
    int msglen = 0;

    if (ERR(lib$sys_getmsg(&status, &msglen, &msgd, 0, 0)))
	fprintf(stderr, "%s[ VMS status = %d ]\n", string, status);
    else
    {
	msgbuf[msglen] = 0;
	fprintf(stderr, "%s[ %s ]\n", string, msgbuf);
    }
}



#ifndef SFX

char *do_wild( wld )
    char *wld;
{
    int status;

    static char filename[256];
    static char efn[256];
    static char last_wild[256];
    static struct FAB fab;
    static struct NAM nam;
    static int first_call=1;
    static char deflt[] = "*.zip";

    if( first_call || strcmp(wld, last_wild) )
    {   /* (Re)Initialize everything */

        strcpy( last_wild, wld );
        first_call = 1;            /* New wild spec */

        fab = cc$rms_fab;
        fab.fab$l_fna = last_wild;
        fab.fab$b_fns = strlen(last_wild);
        fab.fab$l_dna = deflt;
        fab.fab$b_dns = strlen(deflt);
        fab.fab$l_nam = &nam;
        nam = cc$rms_nam;
        nam.nam$l_esa = efn;
        nam.nam$b_ess = sizeof(efn)-1;
        nam.nam$l_rsa = filename;
        nam.nam$b_rss = sizeof(filename)-1;

        if(!OK(sys$parse(&fab)))
            return (char *)NULL;     /* Initialization failed */
        first_call = 0;
        if( !OK(sys$search(&fab)) )
        {
            strcpy( filename, wld );
            return filename;
        }
    }
    else
    {
        if( !OK(sys$search(&fab)) )
        {
            first_call = 1;        /* Reinitialize next time */
            return (char *)NULL;
        }
    }
    filename[nam.nam$b_rsl] = 0;
    return filename;

} /* end function do_wild() */

#endif /* !SFX */



static ulg unix_to_vms[8]={ /* Map from UNIX rwx to VMS rwed */
			    /* Note that unix w bit is mapped to VMS wd bits */
    XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE,    /* --- no access*/
    XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL,                  /* --x */
    XAB$M_NOREAD |                               XAB$M_NOEXE,    /* -w- */
    XAB$M_NOREAD,                                                /* -wx */
                   XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE,    /* r-- */
                   XAB$M_NOWRITE | XAB$M_NODEL,                  /* r-x */
                                                 XAB$M_NOEXE,    /* rw- */
    0                                                            /* rwx full access*/
};

#define SETDFPROT   /* We are using undocumented VMS System Service	*/
		    /* SYS$SETDFPROT here. If your version of VMS does	*/
		    /* not have that service, undef SETDFPROT.		*/
		    /* IM: Maybe it's better to put this to Makefile	*/
		    /* and DESCRIP.MMS */



int mapattr()
{
    ulg  tmp=crec.external_file_attributes, theprot;
    static ulg  defprot = -1L,
		sysdef,owndef,grpdef,wlddef;  /* Default protection fields */


    /* IM: The only field of XABPRO we need to set here is */
    /*     file protection, so we need not to change type */
    /*     of pInfo->file_attr. WORD is quite enough. */

    if( defprot == -1L )
    {
	/*
	* First time here -- Get user default settings
	*/

#ifdef SETDFPROT    /* Undef this if linker cat't resolve SYS$SETDFPROT */
	defprot = 0L;
	if( !ERR(SYS$SETDFPROT(0,&defprot)) )
	{
	    sysdef = defprot & ( (1L<<XAB$S_SYS)-1 ) << XAB$V_SYS;
	    owndef = defprot & ( (1L<<XAB$S_OWN)-1 ) << XAB$V_OWN;
	    grpdef = defprot & ( (1L<<XAB$S_GRP)-1 ) << XAB$V_GRP;
	    wlddef = defprot & ( (1L<<XAB$S_WLD)-1 ) << XAB$V_WLD;
	}
	else
	{
#endif /* ?SETDFPROT */
	    umask(defprot = umask(0));
	    defprot = ~defprot;
	    wlddef = unix_to_vms[defprot & 07] << XAB$V_WLD;
	    grpdef = unix_to_vms[(defprot>>3) & 07] << XAB$V_GRP;
	    owndef = unix_to_vms[(defprot>>6) & 07] << XAB$V_OWN;
	    sysdef = owndef << (XAB$V_SYS - XAB$V_OWN);
	    defprot = sysdef | owndef | grpdef | wlddef;
#ifdef SETDFPROT
	}
#endif	/* ?SETDFPROT */
    }

    switch (pInfo->hostnum) {
        case UNIX_:
        case VMS_:  /*IM: ??? Does VMS Zip store protection in UNIX format ?*/
                    /* GRR:  Yup.  Bad decision on my part... */
            tmp = (unsigned)(tmp >> 16);  /* drwxrwxrwx */
	    theprot  = (unix_to_vms[tmp & 07] << XAB$V_WLD)
	             | (unix_to_vms[(tmp>>3) & 07] << XAB$V_GRP)
	             | (unix_to_vms[(tmp>>6) & 07] << XAB$V_OWN);

	    if( tmp & 0x4000 )
	    	/* Directory -- set D bits */
		theprot |= (XAB$M_NODEL << XAB$V_SYS)
			| (XAB$M_NODEL << XAB$V_OWN)
			| (XAB$M_NODEL << XAB$V_GRP)
			| (XAB$M_NODEL << XAB$V_WLD);
	    pInfo->file_attr = theprot;
	    break;

        case AMIGA_:
            tmp = (unsigned)(tmp>>16 & 0x0f);   /* Amiga RWED bits */
            pInfo->file_attr = (tmp << XAB$V_OWN) | grpdef | sysdef | wlddef;
            break;

        /* all remaining cases:  expand MSDOS read-only bit into write perms */
        case FS_FAT_:
        case FS_HPFS_:
        case FS_NTFS_:
        case MAC_:
        case ATARI_:             /* (used to set = 0666) */
        case TOPS20_:
        default:
	    theprot = defprot;
	    if( tmp & 1 )   /* Test read-only bit */
	    {	/* Bit is set -- set bits in all fields */
		tmp = XAB$M_NOWRITE | XAB$M_NODEL;
		theprot |= (tmp << XAB$V_SYS) | (tmp << XAB$V_OWN) |
			   (tmp << XAB$V_GRP) | (tmp << XAB$V_WLD);
	    }
            pInfo->file_attr = theprot;
            break;
    } /* end switch (host-OS-created-by) */

    return 0;

} /* end function mapattr() */



#ifndef	EEXIST
#  include <errno.h>	/* For mkdir() status codes */
#endif

#include <fscndef.h> /* for filescan */

#   define FN_MASK   7
#   define USE_DEFAULT	(FN_MASK+1)

/*
 * Checkdir function codes:
 *	ROOT	    -   set root path from unzip qq d:[dir]
 *	INIT	    -   get ready for "filename"
 *	APPEND_DIR  -	append pathcomp
 *	APPEND_NAME -	append filename
 *	APPEND_NAME | USE_DEFAULT   -	expand filename using collected path
 *	GETPATH     -	return resulting filespec
 */

static	int created_dir;

int mapname(renamed)  /* return 0 if no error, 1 if caution (filename trunc),*/
    int renamed;      /* 2 if warning (skip file because dir doesn't exist), */
{                     /* 3 if error (skip file), 10 if no memory (skip file) */
    char pathcomp[FILNAMSIZ];   /* path-component buffer */
    char *pp, *cp=NULL;         /* character pointers */
    char *lastsemi = NULL;      /* pointer to last semi-colon in pathcomp */
    char *last_dot = NULL;      /* last dot not converted to underscore */
    int quote = FALSE;          /* flag:  next char is literal */
    int dotname = FALSE;        /* flag:  path component begins with dot */
    int error = 0;
    register unsigned workch;   /* hold the character being tested */

    if( renamed )
    {
            if( !(error = checkdir(pathcomp, APPEND_NAME | USE_DEFAULT)) )
            strcpy(filename, pathcomp);
        return error;
    }
        
/*---------------------------------------------------------------------------
    Initialize various pointers and counters and stuff.
  ---------------------------------------------------------------------------*/

    /* can create path as long as not just freshening, or if user told us */
    create_dirs = !fflag;

    created_dir = FALSE;        /* not yet */

/* GRR:  for VMS, convert to internal format now or later? or never? */
    if (checkdir(pathcomp, INIT) == 10)
        return 10;              /* initialize path buffer, unless no memory */

    *pathcomp = '\0';           /* initialize translation buffer */
    pp = pathcomp;              /* point to translation buffer */
    if (jflag)              /* junking directories */
/* GRR:  watch out for VMS version... */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?