Make messages consistent. Stop using fixed input buffer. Volset mount checks

Use the VMS-style messages for all errors,warnings.

Allow selection of full message or just text in getmsg()

Use dynamic buffer for command input (except VMS).

Simplify command input and pre-processing.

Mount command improvements:
  If labels are specified, make sure they match the volumes
  Make sure number of devices specified matches hom block's volset count.
  Verify that all volumes claim to belong to the same volume set
  Verify that volumes are mounted in RVN order, and that labels match VOLSET.SYS
  When a volume set is mounted, announce its name.
  Improve cleanup on mount failure (more to do)

Remove obsolete/unused header.h
This commit is contained in:
Timothe Litt 2016-03-02 17:35:50 -05:00
parent 45e3b4e500
commit 2c8ee0b04c
11 changed files with 424 additions and 425 deletions

View File

@ -119,7 +119,6 @@
<ClInclude Include="descrip.h" />
<ClInclude Include="direct.h" />
<ClInclude Include="fibdef.h" />
<ClInclude Include="header.h" />
<ClInclude Include="memory.h" />
<ClInclude Include="phyio.h" />
<ClInclude Include="resource.h" />

View File

@ -65,9 +65,6 @@
<ClInclude Include="fibdef.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="header.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="memory.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -17,6 +17,7 @@
'RMS' routines.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -25,6 +26,7 @@
#include "access.h"
#include "phyio.h"
#include "compat.h"
#include "sysmsg.h"
#define DEBUGx
@ -78,8 +80,8 @@ void fid_copy(struct fiddef *dst,struct fiddef *src,unsigned rvn)
unsigned deaccesshead(struct VIOC *vioc,struct HEAD *head,unsigned idxblk)
{
if (head && idxblk) {
unsigned short check = checksum((vmsword *) head);
head->fh2$w_checksum = VMSWORD(check);
unsigned short check = checksum((vmsword *) head);
head->fh2$w_checksum = VMSWORD(check);
}
return deaccesschunk(vioc,idxblk,1,1);
}
@ -564,7 +566,7 @@ unsigned deaccessfile(struct FCB *fcb)
cache_refcount((struct CACHE *) fcb->vioc);
if (refcount != 0) {
printf("File reference counts non-zero %d (%d)\n",refcount,
fcb->cache.hashval);
fcb->cache.hashval);
#ifdef DEBUG
printf("File reference counts non-zero %d %d\n",
cache_refcount((struct CACHE *) fcb->wcb),cache_refcount((struct CACHE *) fcb->vioc));
@ -738,24 +740,35 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],stru
register unsigned device,sts = 0;
struct VCB *vcb;
struct VCBDEV *vcbdev;
struct VOLSETREC *volsetSYS = NULL;
UNUSED(label);
#ifdef DEBUG
if (sizeof(struct HOME) != 512 || sizeof(struct HEAD) != 512) return SS$_NOTINSTALL;
vcb = (struct VCB *) malloc(sizeof(struct VCB) + (devices - 1) * sizeof(struct VCBDEV));
#endif
vcb = (struct VCB *) calloc(1, sizeof(struct VCB) + (devices - 1) * sizeof(struct VCBDEV));
if (vcb == NULL) return SS$_INSFMEM;
vcb->status = 0;
if (flags & 1) vcb->status |= VCB_WRITE;
vcb->fcb = NULL;
vcb->dircache = NULL;
vcbdev = vcb->vcbdev;
for (device = 0; device < devices; device++) {
for( device = 0; device < devices; device++, vcbdev++ ) {
sts = SS$_NOSUCHVOL;
vcbdev->dev = NULL;
if (strlen(devnam[device])) {
if (strlen(devnam[device])) { /* Really want to allow skipping volumes? */
unsigned int hba;
if( label[device] != NULL && strlen(label[device]) > sizeof( volsetSYS[0].vsr$t_label ) ) {
sts = SS$_BADPARAM;
break;
}
sts = device_lookup(strlen(devnam[device]),devnam[device],1,&vcbdev->dev);
if (!(sts & 1)) break;
if( !(sts & 1) ) break;
if (vcbdev->dev->vcb != NULL) {
sts = SS$_DEVMOUNT;
break;
}
for (hba = 1; hba <= HOME_LIMIT; hba++) {
sts = phyio_read(vcbdev->dev->handle,hba,sizeof(struct HOME),(char *) &vcbdev->home);
if (!(sts & 1)) break;
@ -763,26 +776,38 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],stru
memcmp(vcbdev->home.hm2$t_format,"DECFILE11B ",12) == 0) break;
sts = SS$_DATACHECK;
}
if (sts & 1) {
if (VMSWORD(vcbdev->home.hm2$w_checksum2) != checksum((unsigned short *) &vcbdev->home)) {
sts = SS$_DATACHECK;
} else {
if (VMSWORD(vcbdev->home.hm2$w_rvn) != device + 1)
if (VMSWORD(vcbdev->home.hm2$w_rvn) > 1 || device != 0)
sts = SS$_UNSUPVOLSET;
if (vcbdev->dev->vcb != NULL) {
sts = SS$_DEVMOUNT;
if( !(sts & 1) ) break;
if (VMSWORD(vcbdev->home.hm2$w_checksum2) != checksum((unsigned short *) &vcbdev->home)) {
sts = SS$_DATACHECK;
break;
}
if( label[device] != NULL ) {
int i;
char lbl[12+1]; /* Pad CLI-supplied label to match ODS */
snprintf( lbl, sizeof(lbl), "%-12s", label[device] );
for( i = 0; i < 12; i++ ) {
if( toupper(lbl[i]) != vcbdev->home.hm2$t_volname[i] ) {
printf( "%%ODS2-W-WRONGVOL, Device %s contains volume '%12.12s', '%s' expected\n",
devnam[device], vcbdev->home.hm2$t_volname, lbl );
sts = SS$_ITEMNOTFOUND;
break;
}
}
if( (sts & 1) == 0 ) break;
}
if( (VMSWORD(vcbdev->home.hm2$w_rvn) != device + 1) &&
!(VMSWORD(vcbdev->home.hm2$w_rvn) == 0 && device == 0) ) {
printf( "%%ODS2-E-WRONGVOL, Device %s contains RVN %u, RVN %u expected\n",
devnam[device], VMSWORD(vcbdev->home.hm2$w_rvn), device+1 );
sts = SS$_UNSUPVOLSET;
}
if (!(sts & 1)) break;
}
vcbdev++;
} /* for(each device) */
}
if (sts & 1) {
vcb->devices = devices;
vcbdev = vcb->vcbdev;
for (device = 0; device < devices; device++) {
for( device = 0; device < devices; device++, vcbdev++ ) {
vcbdev->idxfcb = NULL;
vcbdev->mapfcb = NULL;
vcbdev->clustersize = 0;
@ -791,42 +816,150 @@ unsigned mount(unsigned flags,unsigned devices,char *devnam[],char *label[],stru
if (strlen(devnam[device])) {
struct fiddef idxfid = {1,1,0,0};
idxfid.fid$b_rvn = device + 1;
sts = accessfile(vcb,&idxfid,&vcbdev->idxfcb,flags & 1);
sts = accessfile( vcb, &idxfid, &vcbdev->idxfcb, (vcb->status & VCB_WRITE) != 0 );
if (!(sts & 1)) {
vcbdev->dev = NULL;
} else {
vcbdev->dev->vcb = vcb;
if (flags & 1) {
struct fiddef mapfid = {2,2,0,0};
mapfid.fid$b_rvn = device + 1;
sts = accessfile(vcb,&mapfid,&vcbdev->mapfcb,1);
if (sts & 1) {
struct VIOC *vioc;
struct SCB *scb;
sts = accesschunk(vcbdev->mapfcb,1,&vioc,(char **) &scb,NULL,0);
if (sts & 1) {
if (scb->scb$w_cluster == vcbdev->home.hm2$w_cluster) {
vcbdev->clustersize = vcbdev->home.hm2$w_cluster;
vcbdev->max_cluster = (scb->scb$l_volsize + scb->scb$w_cluster - 1) / scb->scb$w_cluster;
deaccesschunk(vioc,0,0,0);
sts = update_freecount(vcbdev,&vcbdev->free_clusters);
#ifdef DEBUG
printf( "%d of %d blocks are free on %12.12s\n",
vcbdev->free_clusters * vcbdev->clustersize, scb->scb$l_volsize,
vcbdev->home.hm2$t_volname );
#endif
}
vcbdev->dev = NULL; /*** DECREF ***/
continue;
}
vcbdev->dev->vcb = vcb;
if( VMSWORD(vcbdev->home.hm2$w_rvn) != 0 ) {
if( device == 0 ) {
struct fiddef vsfid = {6,6,1,0};
struct FCB *vsfcb = NULL;
struct VIOC *vioc = NULL;
unsigned recs = 0;
int rec;
unsigned int vbn = 1;
struct VOLSETREC *bufp;
int setcount = VMSWORD(vcbdev->home.hm2$w_setcount);
if( setcount != (int)devices ) {
printf( "%%ODS2-E-VOLCOUNT, Volume set %12.12s has %u members, but %u specified\n",
vcbdev->home.hm2$t_strucname, setcount, devices );
sts = SS$_DEVNOTMOUNT;
break;
}
/* Read VOLSET.SYS */
volsetSYS = (struct VOLSETREC *)malloc( (1+setcount) * sizeof( struct VOLSETREC ) );
sts = accessfile( vcb, &vsfid, &vsfcb, 0 );
if( (sts & 1) == 0 ) {
printf( "%%ODS2-E-NOVOLSET, Unable to access VOLSET.SYS: %s\n", getmsg(sts, MSG_TEXT) );
break;
}
for( rec = 0; rec <= setcount; rec++ ) {
if( recs == 0 ) {
if( vbn != 1 ) deaccesschunk(vioc,0,0,0);
sts = accesschunk(vsfcb,vbn, &vioc,(char **)&bufp, &recs, 0);
if( (sts & 1) == 0 ) break;
vbn += recs;
recs *= 512 / sizeof( struct VOLSETREC );
}
memcpy(volsetSYS+rec, bufp++, sizeof( struct VOLSETREC ));
}
deaccesschunk(vioc,0,0,0);
{ int st2;
st2 = deaccessfile(vsfcb);
if( sts & 1 ) sts = st2;
}
if( (sts & 1) == 0 ) {
printf( "%%ODS2-E-VOLIOERR, Error reading VOLSET.SYS: %s\n", getmsg(sts, MSG_TEXT) );
break;
}
if( memcmp(vcbdev->home.hm2$t_strucname, volsetSYS[0].vsr$t_label, 12 ) != 0 ) {
printf( "%%ODS2-E-INCONVOL, Volume set name is '%12.12s', but VOLSET.SYS is for '%12.12s'\n",
vcbdev->home.hm2$t_strucname, volsetSYS[0].vsr$t_label );
sts = SS$_NOSUCHVOL;
break;
}
} else { /* device != 0 */
if( vcb->vcbdev[0].dev == NULL ) {
printf( "%%ODS2-F-NORVN1, RVN 1 must be mounted\n" );
sts = SS$_NOSUCHVOL;
break;
}
if( memcmp(vcbdev->home.hm2$t_strucname, vcb->vcbdev[0].home.hm2$t_strucname, 12) != 0 ) {
printf( "%%ODS2-E-INCONVOL, Volume '%12.12s' on %s is a member of '%12.12s', not a member of '%12.12s'\n",
vcbdev->home.hm2$t_volname, devnam[device], vcbdev->home.hm2$t_strucname,
vcb->vcbdev[0].home.hm2$t_strucname );
sts = SS$_NOSUCHVOL;
break;
}
}
if( memcmp(vcbdev->home.hm2$t_volname, volsetSYS[device+1].vsr$t_label, 12 ) != 0 ) {
printf( "%%ODS2-E-WRONGVOL, RVN %u of '%12.12s' is '%12.12s'. %s contains '%12.12s'\n",
device+1, vcb->vcbdev[0].home.hm2$t_strucname,
volsetSYS[device+1].vsr$t_label, devnam[device], vcbdev->home.hm2$t_volname );
sts = SS$_NOSUCHVOL;
break;
}
} /* rvn != 0 */
if( vcb->status & VCB_WRITE ) {
struct fiddef mapfid = {2,2,0,0};
mapfid.fid$b_rvn = device + 1;
sts = accessfile( vcb, &mapfid, &vcbdev->mapfcb, 1);
if (sts & 1) {
struct VIOC *vioc;
struct SCB *scb;
sts = accesschunk(vcbdev->mapfcb,1,&vioc,(char **) &scb,NULL,0);
if (sts & 1) {
if (scb->scb$w_cluster == vcbdev->home.hm2$w_cluster) {
vcbdev->clustersize = vcbdev->home.hm2$w_cluster;
vcbdev->max_cluster = (scb->scb$l_volsize + scb->scb$w_cluster - 1) / scb->scb$w_cluster;
deaccesschunk(vioc,0,0,0);
sts = update_freecount(vcbdev,&vcbdev->free_clusters);
#ifdef DEBUG
printf( "%d of %d blocks are free on %12.12s\n",
vcbdev->free_clusters * vcbdev->clustersize, scb->scb$l_volsize,
vcbdev->home.hm2$t_volname );
#endif
}
}
} else {
printf( "%%ODS2-E-NOBITMAP, Unable to access BITMAP.SYS: %s\n", getmsg(sts, MSG_TEXT) );
vcbdev->mapfcb = NULL;
break;
}
}
if( (sts & 1) && (flags & 2) ) {
printf("%%MOUNT-I-MOUNTED, Volume %12.12s mounted on %s\n",
vcbdev->home.hm2$t_volname, vcbdev->dev->devnam);
}
} /* device len */
} /* for( each device ) */
if( !(sts & 1) ) {
vcbdev = vcb->vcbdev;
for( device = 0; device < devices; device++, vcbdev++ ) {
if (vcbdev->dev == NULL) continue;
if( vcb->status & VCB_WRITE && vcbdev->mapfcb != NULL ) {
/* sts = */
deaccessfile(vcbdev->mapfcb);
/* if( !(sts & 1) ) ??; */
vcbdev->idxfcb->status &= ~FCB_WRITE;
vcbdev->mapfcb = NULL;
}
cache_remove( &vcb->fcb->cache );
/* sts = */
deaccesshead(vcbdev->idxfcb->headvioc,vcbdev->idxfcb->head,vcbdev->idxfcb->headvbn);
/* if (!(sts & 1)) ??; */
vcbdev->idxfcb->headvioc = NULL;
cache_untouch(&vcbdev->idxfcb->cache,0);
vcbdev->dev->vcb = NULL;
/* ?? vcbdev->dev = NULL *//* **DECREF **/
}
vcbdev++;
cache_remove( &vcb->fcb->cache );
while( vcb->dircache ) cache_delete( (struct CACHE *) vcb->dircache );
}
} else {
} else { /* *** DECREF *** */
free(vcb);
vcb = NULL;
}
if( (sts & 1) && (flags & 2) && VMSWORD(vcb->vcbdev[0].home.hm2$w_rvn) != 0 ) {
printf ( "%%MOUNT-I-MOUNTEDVS, Volume set %12.12s mounted\n", vcb->vcbdev[0].home.hm2$t_strucname );
}
if( volsetSYS != NULL ) free( volsetSYS );
if (retvcb != NULL) *retvcb = vcb;
return sts;
}

View File

@ -173,6 +173,11 @@ struct SCB {
vmsword scb$w_checksum;
};
struct VOLSETREC {
char vsr$t_label[12];
char vsr$b_reserved[52];
};
#ifdef __ALPHA
#pragma member_alignment restore
#endif

View File

@ -55,7 +55,7 @@ cache$(OBJ) : cache.c cache.h ssdef.h
phyvms$(OBJ) : phyvms.c phyio.h ssdef.h
device$(OBJ) : device.c ssdef.h access.h phyio.h
device$(OBJ) : device.c ssdef.h access.h phyio.h sysmsg.h
access$(OBJ) : access.c ssdef.h access.h phyio.h

View File

@ -40,7 +40,10 @@ unsigned read_count = 0;
unsigned write_count = 0;
#define MAX_DEVS 64
FILE *handles[1+MAX_DEVS];
struct handle {
FILE *fh;
int drive;
} handles[1+MAX_DEVS];
void phyio_show(void)
{
@ -152,7 +155,6 @@ int diskio_showdrives( void ) {
}
if( n == 0 ) {
printf( "No drives assigned\n" );
sts = 0;
}
return sts;
}
@ -177,7 +179,7 @@ unsigned phyio_init( int devlen,char *devnam,unsigned *handle,struct phyio_info
info->sectorsize = 0;
*handle = ~0;
for( hi = 1; hi < MAX_DEVS && handles[hi] != NULL; hi++ )
for( hi = 1; hi < MAX_DEVS && handles[hi].fh != NULL; hi++ )
;
if( hi >= MAX_DEVS ) {
@ -195,11 +197,12 @@ unsigned phyio_init( int devlen,char *devnam,unsigned *handle,struct phyio_info
return SS$_NOSUCHFILE;
}
handles[hi] = openf ( diskfiles[i], (drives[i][3] & 1)? "rb+": "rb" );
if( handles[hi] == NULL ) {
handles[hi].fh = openf ( diskfiles[i], (drives[i][3] & 1)? "rb+": "rb" );
if( handles[hi].fh == NULL ) {
perror( diskfiles[i] );
return SS$_NOSUCHFILE;
}
handles[hi].drive = i;
++init_count;
@ -208,25 +211,27 @@ unsigned phyio_init( int devlen,char *devnam,unsigned *handle,struct phyio_info
}
unsigned phyio_close(unsigned handle) {
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
if( handle == 0 || handle > MAX_DEVS || handles[handle].fh == NULL ) {
return SS$_NOIOCHAN;
}
fclose ( handles[handle] );
handles[handle] = NULL;
fclose ( handles[handle].fh );
handles[handle].fh = NULL;
if( diskio_unmapdrive(drives[handles[handle].drive] ) == 0 )
abort();
return SS$_NORMAL;
}
unsigned phyio_read( unsigned handle,unsigned block,unsigned length,char *buffer ) {
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
if( handle == 0 || handle > MAX_DEVS || handles[handle].fh == NULL ) {
return SS$_IVCHAN;
}
if( fseek( handles[handle], block * 512, SEEK_SET ) == -1 ) {
if( fseek( handles[handle].fh, block * 512, SEEK_SET ) == -1 ) {
perror( "seek" );
return SS$_DATACHECK;
}
if( fread( buffer, 1, length, handles[handle] ) != length ) {
if( fread( buffer, 1, length, handles[handle].fh ) != length ) {
perror( "read" );
return SS$_DATACHECK;
}
@ -236,16 +241,16 @@ unsigned phyio_read( unsigned handle,unsigned block,unsigned length,char *buffer
}
unsigned phyio_write( unsigned handle,unsigned block,unsigned length,char *buffer ) {
if( handle == 0 || handle > MAX_DEVS || handles[handle] == NULL ) {
if( handle == 0 || handle > MAX_DEVS || handles[handle].fh == NULL ) {
return SS$_IVCHAN;
}
if( fseek( handles[handle], block * 512, SEEK_SET ) == -1 ) {
if( fseek( handles[handle].fh, block * 512, SEEK_SET ) == -1 ) {
perror( "seek" );
return SS$_DATACHECK;
}
abort();
if( fwrite( buffer, 1, length, handles[handle] ) != length ) {
if( fwrite( buffer, 1, length, handles[handle].fh ) != length ) {
perror( "write" );
return SS$_DATACHECK;
}

View File

@ -1,189 +0,0 @@
/* Header.h v1.0 Definitions for ODS2 file headers */
/* Small macro to swap words in a longword */
#define swapw(w) (w[0]<<16 | w[1])
/* File characteristic definitions */
#define FCH$M_NOBACKUP 0x2
#define FCH$M_CONTIGB 0x20
#define FCH$M_LOCKED 0x40
#define FCH$M_CONTIG 0x80
#define FCH$M_DIRECTORY 0x2000
#define FCH$M_MARKDEL 0x8000
#define FCH$M_ERASE 0x20000
/* File and record attribute definitions */
#define FAT$C_FIXED 0x1
#define FAT$C_VARIABLE 0x2
#define FAT$C_VFC 0x3
#define FAT$C_UNDEFINED 0x0
#define FAT$C_STREAM 0x4
#define FAT$C_STREAMLF 0x5
#define FAT$C_STREAMCR 0x6
#define FAT$C_DIRECT 0x3
#define FAT$C_INDEXED 0x2
#define FAT$C_RELATIVE 0x1
#define FAT$C_SEQUENTIAL 0x0
#define FAT$M_FORTRANCC 0x1
#define FAT$M_IMPLIEDCC 0x2
#define FAT$M_PRINTCC 0x4
#define FAT$M_NOSPAN 0x8
#define FAT$M_MSBRCW 0x10
/* Type definitions for basic data types */
typedef unsigned char u_byte;
typedef unsigned short u_word;
typedef unsigned int u_long;
/* Structure of time */
struct TIME {
unsigned char time[8];
};
/* Definition of a UIC */
struct UIC {
u_word uic$w_mem;
u_word uic$w_grp;
};
/* Definition for a FID */
struct fiddef {
u_word fid$w_num;
u_word fid$w_seq;
u_byte fid$b_rvn;
u_byte fid$b_nmx;
};
/* RMS record definition */
struct RECATTR {
u_byte fat$b_rtype;
u_byte fat$b_rattrib;
u_word fat$w_rsize;
u_word fat$l_hiblk[2];
u_word fat$l_efblk[2];
u_word fat$w_ffbyte;
u_byte fat$b_bktsize;
u_byte fat$b_vfcsize;
u_word fat$w_maxrec;
u_word fat$w_defext;
u_word fat$w_gbc;
u_byte fat$_UU0[8];
u_word fat$w_versions;
};
/* Layout of the volume home block... */
struct HOME {
u_long hm2$l_homelbn;
u_long hm2$l_alhomelbn;
u_long hm2$l_altidxlbn;
u_word hm2$w_struclev;
u_word hm2$w_cluster;
u_word hm2$w_homevbn;
u_word hm2$w_alhomevbn;
u_word hm2$w_altidxvbn;
u_word hm2$w_ibmapvbn;
u_long hm2$l_ibmaplbn;
u_long hm2$l_maxfiles;
u_word hm2$w_ibmapsize;
u_word hm2$w_resfiles;
u_word hm2$w_devtype;
u_word hm2$w_rvn;
u_word hm2$w_setcount;
u_word hm2$w_volchar;
struct UIC hm2$w_volowner;
u_long hm2$l_reserved1;
u_word hm2$w_protect;
u_word hm2$w_fileprot;
u_word hm2$w_reserved2;
u_word hm2$w_checksum1;
struct TIME hm2$q_credate;
u_byte hm2$b_window;
u_byte hm2$b_lru_lim;
u_word hm2$w_extend;
struct TIME hm2$q_retainmin;
struct TIME hm2$q_retainmax;
struct TIME hm2$q_revdate;
u_byte hm2$r_min_class[20];
u_byte hm2$r_max_class[20];
u_byte hm2$t_reserved3[320];
u_long hm2$l_serialnum;
char hm2$t_strucname[12];
char hm2$t_volname[12];
char hm2$t_ownername[12];
char hm2$t_format[12];
u_word hm2$w_reserved4;
u_word hm2$w_checksum2;
};
/* Structure of the header identification area */
struct IDENT {
char fi2$t_filename[20];
u_word fi2$w_revision;
struct TIME fi2$q_credate;
struct TIME fi2$q_revdate;
struct TIME fi2$q_expdate;
struct TIME fi2$q_bakdate;
char fi2$t_filenamext[66];
};
/* File header layout */
struct HEAD {
u_byte fh2$b_idoffset;
u_byte fh2$b_mpoffset;
u_byte fh2$b_acoffset;
u_byte fh2$b_rsoffset;
u_word fh2$w_seg_num;
u_word fh2$w_struclev;
struct fiddef fh2$w_fid;
struct fiddef fh2$w_ext_fid;
struct RECATTR fh2$w_recattr;
u_long fh2$l_filechar;
u_word fh2$w_reserved1;
u_byte fh2$b_map_inuse;
u_byte fh2$b_acc_mode;
struct UIC fh2$l_fileowner;
u_word fh2$w_fileprot;
struct fiddef fh2$w_backlink;
u_byte fh2$b_journal;
u_byte fh2$b_ru_active;
u_word fh2$w_reserved2;
u_long fh2$l_highwater;
u_byte fh2$b_reserved3[8];
u_byte fh2$r_class_prot[20];
u_byte fh2$r_restofit[402];
u_word fh2$w_checksum;
};
/* Storage control block layout */
struct SCB {
u_word scb$w_struclev;
u_word scb$w_cluster;
u_long scb$l_volsize;
u_long scb$l_blksize;
u_long scb$l_sectors;
u_long scb$l_tracks;
u_long scb$l_cylinders;
u_long scb$l_status;
u_long scb$l_status2;
u_word scb$w_writecnt;
char scb$t_volockname[12];
struct TIME scb$q_mounttime;
u_word scb$w_backrev;
u_long scb$q_genernum[2];
char scb$b_reserved[446];
u_word scb$w_checksum;
};

View File

@ -55,7 +55,7 @@ ods2 : $(ODS2_OBJS) $(LIBS)
ods2i : $(ODS2I_OBJS)
$(CC) $(CCFLAGS) -o ods2i $(ODS2I_OBJS) $(LDFLAGS)
access$(OBJ) : access.c ssdef.h access.h phyio.h compat.h
access$(OBJ) : access.c ssdef.h access.h phyio.h compat.h sysmsg.h
$(CC) -c $(CCFLAGS) $(DEFS) access.c
cache$(OBJ) : cache.c cache.h ssdef.h

View File

@ -296,7 +296,7 @@ int prvmstime(VMSTIME vtime, const char *sfx) {
timdsc.dsc_w_length = 23;
timdsc.dsc_a_pointer = tim;
sts = sys_asctim(0,&timdsc,vtime,0);
if ((sts & 1) == 0) printf("Asctim error: %s\n",getmsg(sts));
if ((sts & 1) == 0) printf("%%ODS2-W-TIMERR, SYS$ASCTIM error: %s\n",getmsg(sts, MSG_TEXT));
tim[23] = '\0';
printf(" %s",tim);
} else {
@ -563,7 +563,7 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
}
sts = sys_open(&fab);
if ((sts & 1) == 0) {
printf("Open error: %s\n", getmsg(sts));
printf("%%ODS2-E-OPENERR, Open error: %s\n", getmsg(sts, MSG_TEXT));
} else {
sts = sys_close(&fab);
if (options & dir_fileid) {
@ -739,7 +739,7 @@ Journaling enabled: None
if (sts & 1) {
if (filecount < 1) printf("%%DIRECT-W-NOFILES, no files found\n");
} else {
printf("%%DIR-E-ERROR Status: %s\n",getmsg(sts));
printf("%%DIR-E-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
return sts;
}
@ -784,7 +784,7 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
while ((sts = sys_search(&fab)) & 1) {
sts = sys_open(&fab);
if ((sts & 1) == 0) {
printf("%%COPY-F-OPENFAIL, Open error: %s\n",getmsg(sts));
printf("%%COPY-F-OPENFAIL, Open error: %s\n",getmsg(sts, MSG_TEXT));
perror("-COPY-F-ERR ");
} else {
struct RAB rab = cc$rms_rab;
@ -859,7 +859,7 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
printf("%%COPY-S-COPIED, %s copied to %s (%d record%s)\n",
rsa,name,records,(records == 1 ? "" : "s"));
} else {
printf("%%COPY-F-ERROR Status: %s for %s\n",getmsg(sts),rsa);
printf("%%COPY-F-ERROR Status: %s for %s\n",getmsg(sts, MSG_TEXT),rsa);
sts = 1;
}
}
@ -872,7 +872,7 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
if (filecount > 0) printf("%%COPY-S-NEWFILES, %d file%s created\n",
filecount,(filecount == 1 ? "" : "s"));
} else {
printf("%%COPY-F-ERROR Status: %s\n",getmsg(sts));
printf("%%COPY-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
return sts;
}
@ -916,10 +916,10 @@ unsigned import(int argc,char *argv[],int qualc,char *qualv[])
}
fclose(fromf);
if (!(sts & 1)) {
printf("%%IMPORT-F-ERROR Status: %s\n",getmsg(sts));
printf("%%IMPORT-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
} else {
printf("Can't open %s\n",argv[1]);
printf("%%ODS2-E-OPENERR, Can't open %s\n",argv[1]);
}
return sts;
}
@ -946,7 +946,7 @@ unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
fab.fab$b_fns = strlen(fab.fab$l_fna);
tof = openf(argv[2],"r");
if (tof == NULL) {
printf("Could not open file %s\n",argv[1]);
printf("%%ODS2-E-OPENERR, Could not open file %s\n",argv[1]);
sts = 0;
} else {
if ((sts = sys_open(&fab)) & 1) {
@ -978,7 +978,7 @@ unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
if (sts & 1) {
printf("%%DIFF-I-Compared %d records\n",records);
} else {
printf("%%DIFF-F-Error %s in difference\n",getmsg(sts));
printf("%%DIFF-F-Error %s in difference\n",getmsg(sts, MSG_TEXT));
}
return sts;
}
@ -1021,7 +1021,7 @@ unsigned typ(int argc,char *argv[],int qualc,char *qualv[])
if (sts == RMS$_EOF) sts = 1;
}
if ((sts & 1) == 0) {
printf("%%TYPE-F-ERROR Status: %s\n",getmsg(sts));
printf("%%TYPE-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
return sts;
}
@ -1075,7 +1075,7 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
while ((sts = sys_search(&fab)) & 1) {
sts = sys_open(&fab);
if ((sts & 1) == 0) {
printf("%%SEARCH-F-OPENFAIL, Open error: %s\n",getmsg(sts));
printf("%%SEARCH-F-OPENFAIL, Open error: %s\n",getmsg(sts, MSG_TEXT));
} else {
struct RAB rab = cc$rms_rab;
rab.rab$l_fab = &fab;
@ -1132,7 +1132,7 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
if (findcount < 1) printf("%%SEARCH-I-NOMATCHES, no strings matched\n");
}
} else {
printf("%%SEARCH-F-ERROR Status: %s\n",getmsg(sts));
printf("%%SEARCH-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
return sts;
}
@ -1181,7 +1181,7 @@ unsigned del(int argc,char *argv[],int qualc,char *qualv[])
while ((sts = sys_search(&fab)) & 1) {
sts = sys_erase(&fab);
if ((sts & 1) == 0) {
printf("%%DELETE-F-DELERR, Delete error: %s\n",getmsg(sts));
printf("%%DELETE-F-DELERR, Delete error: %s\n",getmsg(sts, MSG_TEXT));
break;
} else {
filecount++;
@ -1198,7 +1198,7 @@ unsigned del(int argc,char *argv[],int qualc,char *qualv[])
printf("%%DELETE-W-NOFILES, no files deleted\n");
}
} else {
printf("%%DELETE-F-ERROR Status: %s\n",getmsg(sts));
printf("%%DELETE-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
return sts;
@ -1249,7 +1249,7 @@ unsigned extend(int argc,char *argv[],int qualc,char *qualv[])
sys_close(&fab);
}
if ((sts & 1) == 0) {
printf("%%EXTEND-F-ERROR Status: %s\n",getmsg(sts));
printf("%%EXTEND-F-ERROR Status: %s\n",getmsg(sts, MSG_TEXT));
}
return sts;
}
@ -1318,7 +1318,7 @@ unsigned show(int argc,char *argv[],int qualc,char *qualv[]) {
curdir[curlen] = '\0';
printf(" %s\n",curdir);
} else {
printf("Error %s getting default\n",getmsg(sts));
printf("%%ODS2-E-GETDEF, Error %s getting default\n",getmsg(sts, MSG_TEXT));
}
return sts;
}
@ -1338,7 +1338,7 @@ unsigned show(int argc,char *argv[],int qualc,char *qualv[]) {
timstr[timlen] = '\0';
printf(" %s\n",timstr);
} else {
printf("%%SHOW-W-TIMERR error %s\n",getmsg(sts));
printf("%%SHOW-W-TIMERR error %s\n",getmsg(sts, MSG_TEXT));
}
}
return SS$_NORMAL;
@ -1410,7 +1410,7 @@ void setdef(char *newdef)
if ((sts = sys_setddir(&defdsc,NULL,NULL)) & 1) {
setdef_count++;
} else {
printf("Error %s setting default to %s\n",getmsg(sts),newdef);
printf("%%ODS2-E-SETDEF, Error %s setting default to %s\n",getmsg(sts, MSG_TEXT),newdef);
}
}
@ -1490,7 +1490,7 @@ unsigned set(int argc,char *argv[],int qualc,char *qualv[])
return SS$_BADPARAM;
case 0: /* default */
if( qualc ) {
printf( "No qualifiers are permitted\n" );
printf( "%%ODS2-E-NOQUAL, No qualifiers are permitted\n" );
return 0;
}
setdef(argv[2]);
@ -1548,14 +1548,11 @@ unsigned dodismount(int argc,char *argv[],int qualc,char *qualv[])
if (sts & 1) {
if (dev->vcb != NULL) {
sts = dismount(dev->vcb);
#ifdef DISKIMAGE
sts = diskio_unmapdrive( dev->devnam );
#endif
} else {
sts = SS$_DEVNOTMOUNT;
}
}
if ((sts & 1) == 0) printf("%%DISMOUNT-E-STATUS Error: %s\n",getmsg(sts));
if ((sts & 1) == 0) printf("%%DISMOUNT-E-STATUS Error: %s\n",getmsg(sts, MSG_TEXT));
return sts;
}
@ -1589,6 +1586,9 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
UNUSED(argc);
memset( labs, 0, sizeof(labs) );
memset( devs, 0, sizeof(devs) );
while (*lab != '\0') {
labs[devices++] = lab;
while (*lab != ',' && *lab != '\0') lab++;
@ -1609,9 +1609,10 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
}
}
if (devices > 0) {
unsigned i;
struct VCB *vcb;
#ifdef DISKIMAGE
unsigned i;
for( i = 0; i < (unsigned)devices; i++ ) {
char *drive;
drive = diskio_mapfile( devs[i], (options & mnt_write) != 0 );
@ -1620,14 +1621,11 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
devs[i] = drive;
}
#endif
sts = mount(options&mnt_write,devices,devs,labs,&vcb);
sts = mount( ((options & mnt_write) != 0) | 2, devices, devs, labs, &vcb );
if (sts & 1) {
for (i = 0; i < vcb->devices; i++)
if (vcb->vcbdev[i].dev != NULL)
printf("%%MOUNT-I-MOUNTED, Volume %12.12s mounted on %s\n",
vcb->vcbdev[i].home.hm2$t_volname,vcb->vcbdev[i].dev->devnam);
if (setdef_count == 0) {
char *colon,tmp[256],defdir[256];
char *colon,tmp[256],defdir[256];
snprintf( tmp, sizeof(tmp), "%s", vcb->vcbdev[0].dev->devnam);
colon = strchr(tmp,':');
if (colon != NULL) *colon = '\0';
@ -1636,10 +1634,10 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
test_vcb = vcb;
}
} else {
printf("Mount failed with %s\n",getmsg(sts));
printf("%%ODS2-E-MOUNTERR, Mount failed with %s\n", getmsg(sts, MSG_TEXT));
#ifdef DISKIMAGE
for( i = 0; i < (unsigned)devices; i++ ) {
sts = diskio_unmapdrive( devs[i] );
(void) diskio_unmapdrive( devs[i] );
}
#endif
}
@ -2026,13 +2024,13 @@ int cmdsplit(char *str)
continue;
}
if( qualc >= MAXITEMS ) {
printf( "Too many qualifiers specified\n" );
printf( "%%ODS2-E-CMDERR, Too many qualifiers specified\n" );
return 0;
}
qualv[qualc++] = sp;
} else {
if( argc >= MAXITEMS ) {
printf( "Too many arguments specified\n" );
printf( "%%ODS2-E-CMDERR, Too many arguments specified\n" );
return 0;
}
argv[argc++] = sp;
@ -2045,11 +2043,11 @@ int cmdsplit(char *str)
if( *sp == '"' ) {
*sp++ = '\0';
if( *sp && *sp != ' ' ) {
printf( "Unterminated string\n" );
printf( "%%ODS2-E-CMDERR, Unterminated string\n" );
return 0;
}
} else {
printf( "Unterminated string\n" );
printf( "%%ODS2-E-CMDERR, Unterminated string\n" );
return 0;
}
continue;
@ -2072,38 +2070,75 @@ int cmdsplit(char *str)
#include <smgdef.h>
#include <smg$routines.h>
char *getcmd(char *inp, char *prompt)
{
struct dsc_descriptor prompt_d = {strlen(prompt),DSC$K_DTYPE_T,
DSC$K_CLASS_S, prompt};
struct dsc_descriptor input_d = {1024,DSC$K_DTYPE_T,
DSC$K_CLASS_S, inp};
char *getcmd( char *inp, size_t max, char *prompt ) {
struct dsc_descriptor prompt_d = { strlen(prompt),DSC$K_DTYPE_T,
DSC$K_CLASS_S, prompt };
struct dsc_descriptor input_d = { max -1,DSC$K_DTYPE_T,
DSC$K_CLASS_S, inp };
int status;
char *retstat;
static unsigned long key_table_id = 0;
static unsigned long keyboard_id = 0;
if (key_table_id == 0) {
status = smg$create_key_table (&key_table_id);
if (status & 1)
status = smg$create_virtual_keyboard (&keyboard_id);
if (!(status & 1)) return (NULL);
status = smg$create_key_table( &key_table_id );
if (status & 1)
status = smg$create_virtual_keyboard( &keyboard_id );
if (!(status & 1)) return (NULL);
}
status = smg$read_composed_line (&keyboard_id, &key_table_id,
&input_d, &prompt_d, &input_d, 0,0,0,0,0,0,0);
&input_d, &prompt_d, &input_d, 0,0,0,0,0,0,0);
if (status == SMG$_EOF)
retstat = NULL;
retstat = NULL;
else {
inp[input_d.dsc_w_length] = '\0';
retstat = inp;
inp[input_d.dsc_w_length] = '\0';
retstat = inp;
}
return(retstat);
}
#endif /* VMS */
/* Read a line of input - unlimited length
* Removes \n, returns NULL at EOF
* Caller responsible for free()
*/
char *fgetline( FILE *stream ) {
size_t bufsize = 0,
xpnsize = 80,
idx = 0;
char *buf = NULL;
int c;
while( (c = fgetc(stream)) != EOF && c != '\n' ) {
if( idx + 2 > bufsize ) {
char *nbuf;
bufsize += xpnsize;
nbuf = (char *) realloc( buf, bufsize );
if( nbuf == NULL ) {
perror( "realloc" );
abort();
}
buf = nbuf;
}
buf[idx++] = c;
}
if( c == EOF && idx == 0 ) {
free( buf );
return NULL;
}
if( bufsize == 0 ) {
buf = (char *) malloc( 1 );
if( buf == NULL ) {
perror( "malloc" );
abort();
}
}
buf[idx] = '\0';
return buf;
}
/* main: the simple mainline of this puppy... */
@ -2120,20 +2155,20 @@ char *getcmd(char *inp, char *prompt)
* ./ods2 -c 'mount scd1 $ set def [hartmut] $ copy *.com $ exit'
*
* The same command concatenation can be implemented for the prompted input.
* As for indirect command files (@), it isn't checked if one of the chained
* commands fails. The user has to be careful, all the subsequent commands
* are executed!
*/
int main(int argc,char *argv[])
{
char str[2048];
int sts;
char *command_line = NULL;
FILE *atfile = NULL;
char *rl = NULL;
#ifdef VMS
char str[2048];
#endif
#ifdef USE_READLINE
char *p;
wordexp_t wex;
char *rl = NULL;
char *hfname = NULL;
char mname[3+sizeof( MNAME(MODULE_NAME) )];
@ -2154,127 +2189,128 @@ int main(int argc,char *argv[])
}
#endif
if (argc>1) {
int i, l = 0;
for (i=1; i<argc; i++) {
int al;
char *newp;
if( argc > 1 ) {
int i, l = 0;
for( i = 1; i < argc; i++ ) {
int al;
char *newp;
if (command_line == NULL) {
command_line = (char *)malloc(1);
*command_line = '\0';
l = 0;
}
al = strlen(argv[i]);
newp = (char *)realloc(command_line,l+1+al+1);
if( newp == NULL ) {
perror( "realloc" );
exit (1);
}
command_line = newp;
snprintf(command_line+l,1+al+1," %s",argv[i]);
l += 1+al;
}
} else command_line = NULL;
while (1) {
char *ptr;
if (command_line) {
static int i=0;
unsigned j=0;
for (; j < sizeof str && command_line[i]; i++)
if (command_line[i] == '$') {
++i;
break;
} else str[j++] = command_line[i];
if (j<sizeof str)
str[j]= '\0';
else str[j-1]= '\0';
if (command_line[i] =='\0') {
free(command_line);
command_line = NULL;
}
ptr = str;
} else {
if (atfile != NULL) {
if (fgets(str,sizeof(str),atfile) == NULL) {
fclose(atfile);
atfile = NULL;
*str = '\0';
} else {
#ifndef _WIN32
ptr = strchr(str, '\r' );
if( ptr == NULL ) /* Do not separate from the next line */
#endif
ptr = strchr(str,'\n');
if (ptr != NULL) *ptr = '\0';
if( verify_cmd )
printf("$> %s\n",str);
}
ptr = str;
} else {
#ifdef VMS
if (getcmd (str, "$> ") == NULL) break;
ptr = str;
#elif( defined USE_READLINE )
if (rl != NULL) {
free( rl );
if (command_line == NULL) {
command_line = (char *)malloc(1);
*command_line = '\0';
l = 0;
}
rl =
ptr = readline( MNAME(MODULE_NAME) "$> " );
if (rl == NULL) {
break;
} else {
if (*rl != '\0') {
add_history( rl );
}
al = strlen(argv[i]);
newp = (char *)realloc(command_line,l+1+al+1);
if( newp == NULL ) {
perror( "realloc" );
exit (1);
}
#else
printf("$> ");
if (fgets(str, sizeof(str), stdin) == NULL) break;
ptr = strchr(str, '\n');
if(ptr != NULL) *ptr = '\0';
ptr = str;
#endif
command_line = newp;
snprintf(command_line+l,1+al+1," %s",argv[i]);
l += 1+al;
}
}
}
while( 1 ) {
char *ptr = NULL;
if( command_line ) {
static int i = 0;
char *p;
while (*ptr == ' ' || *ptr == '\t') ptr++;
if (strlen(ptr) && *ptr != '!') {
if (*ptr == '@') {
if (atfile != NULL) {
printf("%%ODS2-W-INDIRECT, indirect indirection not permitted\n");
ptr = command_line + i;
if( (p = strchr( ptr, '$' )) == NULL ) {
if( *ptr == '\0' ) {
free( command_line );
command_line = NULL;
ptr = NULL;
} else {
if ((atfile = openf(ptr + 1,"r")) == NULL) {
perror("%%Indirection failed");
printf("\n");
free(command_line);
command_line = NULL;
*str = '\0';
}
i += strlen( ptr );
}
} else {
int sts;
sts = cmdsplit(ptr);
if( sts == -1 )
*p = '\0';
i += strlen( ptr ) +1;
}
}
if( ptr == NULL ) {
if (atfile != NULL) {
if( rl != NULL ) free( rl );
if( (rl = fgetline(atfile)) == NULL) {
fclose(atfile);
atfile = NULL;
} else {
#ifndef _WIN32
ptr = strchr( rl, '\r' );
if( ptr != NULL )
*ptr = '\0';
#endif
if( verify_cmd )
printf("$> %s\n", rl);
}
ptr = rl;
} else {
#ifdef VMS
if( getcmd( str, sizeof(str), "$> " ) == NULL ) break;
ptr = str;
#else
if( rl != NULL ) {
free( rl );
}
#ifdef USE_READLINE
rl =
ptr = readline( MNAME(MODULE_NAME) "$> " );
if (rl == NULL) {
break;
if ((sts & 1) == 0) {
if( atfile != NULL ) {
fclose(atfile);
atfile = NULL;
} else {
if( *rl != '\0' ) {
add_history( rl );
}
}
#else
printf("$> ");
if( (rl = fgetline(stdin)) == NULL) break;
ptr = rl;
#endif
#endif
}
}
while( *ptr == ' ' || *ptr == '\t' )
ptr++;
if( !strlen(ptr) || *ptr == '!' || *ptr == ';' )
continue;
if (*ptr == '@') {
if (atfile != NULL) {
printf("%%ODS2-W-INDIRECT, nested indirect command files not supported\n");
} else {
if ((atfile = openf(ptr + 1,"r")) == NULL) {
perror("%%ODS2-E-INDERR, Failed to open indirect command file");
printf("\n");
free(command_line);
command_line = NULL;
*str = '\0';
}
}
}
continue;
}
sts = cmdsplit(ptr);
if( sts == -1 )
break;
if ((sts & 1) == 0) {
if( atfile != NULL ) {
fclose(atfile);
atfile = NULL;
}
free(command_line);
command_line = NULL;
}
} /* while 1 */
if( rl != NULL ) {
free( rl );
}
#ifdef USE_READLINE
if (rl != NULL) {
free( rl );
}
if (hfname != NULL) {
if( hfname != NULL ) {
write_history( hfname );
}
#endif

View File

@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Should replace with lib$sys_getmsg under VMS
@ -13,6 +14,7 @@
#include "ssdef.h"
#include "rms.h"
#include "compat.h"
#include "sysmsg.h"
static
const struct VMSMSG {
@ -70,17 +72,26 @@ const struct VMSMSG {
{0, NULL},
};
const char *getmsg( unsigned int vmscode ) {
char fmt[] = "%SYSTEM-E-NOSUCHMSG, Unknown message code %08X";
static char buf[sizeof(fmt)+8+1];
const char *getmsg( unsigned int vmscode, unsigned int flags ) {
const char fmt[] = "%%SYSTEM-E-NOSUCHMSG, Unknown message code %08X";
static char buf[sizeof(fmt)+8+1];
const char *txtp = NULL;
for( mp = vms2text; mp->text; mp++ ) {
if( vmscode == mp-> code ) {
return mp->text;
for( mp = vms2text; mp->text; mp++ ) {
if( vmscode == mp-> code ) {
txtp = mp->text;
break;
}
}
}
snprintf( buf, sizeof(buf), fmt, vmscode );
return buf;
if( txtp == NULL ) {
txtp = buf;
}
if( flags == MSG_TEXT ) {
txtp = strchr( txtp, ',' );
if( txtp == NULL ) abort();
return txtp+2;
}
return txtp;
}
/*

View File

@ -1,6 +1,8 @@
#ifndef SYSMSG_H
#define SYSMSG_H
const char *getmsg( unsigned int vmscode );
#define MSG_TEXT 0
#define MSG_FULL 1
const char *getmsg( unsigned int vmscode, unsigned int flags );
#endif