diff --git a/extracters/ods2/ODS2.vcxproj b/extracters/ods2/ODS2.vcxproj index 84603f5..7d7938c 100644 --- a/extracters/ods2/ODS2.vcxproj +++ b/extracters/ods2/ODS2.vcxproj @@ -119,7 +119,6 @@ - diff --git a/extracters/ods2/ODS2.vcxproj.filters b/extracters/ods2/ODS2.vcxproj.filters index 046e7f0..dc87ef1 100644 --- a/extracters/ods2/ODS2.vcxproj.filters +++ b/extracters/ods2/ODS2.vcxproj.filters @@ -65,9 +65,6 @@ Header Files - - Header Files - Header Files diff --git a/extracters/ods2/access.c b/extracters/ods2/access.c index 67adf08..3e35a16 100644 --- a/extracters/ods2/access.c +++ b/extracters/ods2/access.c @@ -17,6 +17,7 @@ 'RMS' routines. */ +#include #include #include #include @@ -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; } diff --git a/extracters/ods2/access.h b/extracters/ods2/access.h index edc023a..604867a 100644 --- a/extracters/ods2/access.h +++ b/extracters/ods2/access.h @@ -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 diff --git a/extracters/ods2/descrip.mms b/extracters/ods2/descrip.mms index 47b5f96..eb2b249 100644 --- a/extracters/ods2/descrip.mms +++ b/extracters/ods2/descrip.mms @@ -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 diff --git a/extracters/ods2/diskio.c b/extracters/ods2/diskio.c index 6705f19..905b22a 100644 --- a/extracters/ods2/diskio.c +++ b/extracters/ods2/diskio.c @@ -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; } diff --git a/extracters/ods2/header.h b/extracters/ods2/header.h deleted file mode 100644 index 9b0c5bd..0000000 --- a/extracters/ods2/header.h +++ /dev/null @@ -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; -}; diff --git a/extracters/ods2/makefile.generic b/extracters/ods2/makefile.generic index da02a23..26f0767 100644 --- a/extracters/ods2/makefile.generic +++ b/extracters/ods2/makefile.generic @@ -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 diff --git a/extracters/ods2/ods2.c b/extracters/ods2/ods2.c index 3f56090..d13e27a 100644 --- a/extracters/ods2/ods2.c +++ b/extracters/ods2/ods2.c @@ -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 #include -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 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 %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 diff --git a/extracters/ods2/sysmsg.c b/extracters/ods2/sysmsg.c index c5eb90c..b5c5605 100644 --- a/extracters/ods2/sysmsg.c +++ b/extracters/ods2/sysmsg.c @@ -4,6 +4,7 @@ #include #include +#include /* 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; } /* diff --git a/extracters/ods2/sysmsg.h b/extracters/ods2/sysmsg.h index 2e8d828..1e52012 100644 --- a/extracters/ods2/sysmsg.h +++ b/extracters/ods2/sysmsg.h @@ -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