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