!*************************** AMUS Program Label ****************************** ! Filename: UFDSAV.RUN (d/basic) Date: 06/12/89 ! Category: DISK Hash Code: 146-144-030-164 Version: 1.0(105) ! Initials: AMI Name: AMI BAR-YADIN ! Company: UNITED FASHIONS OF TEXAS Telephone #: 5126312277 ! Related Files: SBR'S: DISKIO,DEVCHR,WRTREC,HASH,DATES ! Min. Op. Sys.: na Expertise Level: NOV ! Special: requires d/basic (but could be converted :-) ! Description: Writes the system structure (label,mfd,ufd) of a disk to a file ! ! !***************************************************************************** !* Updated on 12-Jun-89 at 8:08 PM by Ami Bar-Yadin; edit time: 3:55:07 *! PROGRAM UFDSAV,1.0(105) ! save disk system structure (label,mfd,ufd) ! ! (c) 1989 by Ami Bar-Yadin ! ! usage: ! .run ufdsav file=disk {/O} {/S} !ie .run ufdsav dsk0.ufd=dsk0 ! ! The 2nd backup fields in the disk label block are updated ! (after the label is saved) with today's date and the output ! file name. ! ! UFD save file format: ! The save file is mostly in binary format, however it may have ! an ASCII header, so long as each line has a ";" in column 1. ! ! There are four sections: ID, Label, MFD and UFD. ! ! The ID is a binary image as follows: MAP1 ID MAP2 ID'DEVNAM,S,8 ! null padded ASCII device name MAP2 ID'BLKSIZ,B,4 ! size of each disk block MAP2 ID'MFDBLKS,B,4 ! number of MFD blocks MAP2 ID'UFDBLKS,B,4 ! number of UFD blocks MAP2 ID'SAVDATE,B,4 ! system internal format ! The ID is followed by a 32-bit hash code for the ID data. ! ! Following the ID is a stream of disk blocks each preceeded by ! a block ID header and followed by a 32-bit hash code which ! includes the block ID data. MAP1 BLOCK'ID ! (all zeros for disk label block) MAP2 BID'BLKNUM,B,4 ! original disk block number MAP2 BID'PPN,B,2 ! =0,0 for MFD blocks MAP2 BID'RELBLK,B,2 ! relative to MFD/UFD (1st=1) MAP2 BID'BUF,X,512 ! (buffer for IO and hash code) ! ! The Label is always one block long. ! The MFD blocks are saved one after the other and then ! the UFD blocks are saved, one PPN at a time, block after block. ! ! disk block formats MAP1 LABEL,X,512 MAP1 LABELX,@LABEL MAP2 LBL'OKFLAG,B,4 MAP2 LBL'VOLNAM,S,40 MAP2 LBL'VOLID,S,10 MAP2 LBL'CREATOR,S,30 MAP2 LBL'INSTALATION,S,30 MAP2 LBL'SYSNAM,S,30 MAP2 LBL'CREATED,B,4 ! D,M,W,Y separated,word swapped MAP2 LBL'ACCESSED,B,4 MAP2 LBL'BACKUP1,B,4 MAP2 LBL'BACKVOL1,S,10 MAP2 LBL'BACKUP2,B,4 MAP2 LBL'BACKVOL2,S,10 MAP1 MB,F MAP1 MFD,X,512 MAP1 MFDX,@MFD DEF MFD'ENTRIES=63 MAP2 MFD'ENTRY(MFD'ENTRIES) MAP3 MFD'PPN,B,2 MAP3 MFD'UFDLINK,B,2 MAP3 MFD'PASSWORD,B,4 MAP2 MFD'ZERO,B,2 MAP2 MFD'NEXT,B,2 MAP2 MFD'PREV,B,2 MAP2 MFD'FLAG,B,2 MAP1 UB,F MAP1 UFD,X,512 MAP1 UFDX,@UFD MAP2 UFD'NEXT,B,2 MAP2 UFD'ENTRY(42) MAP3 UFD'FILNAM,B,4 MAP3 UFD'FILEXT,B,2 MAP3 UFD'FILBLKS,B,2 MAP3 UFD'FILBYTS,B,2 MAP3 UFD'FILLINK,B,2 ! bit swapping maps MAP1 PPN,B,2 MAP1 PPNX,@PPN ! byte swapped MAP2 PPN'PROG,B,1 MAP2 PPN'PROJ,B,1 MAP1 LBLDATE,B,4 MAP1 LBLDATEX,X,4,@LBLDATE ! work variables ++INCLUDE DEVCHR MAP1 STAMP,S,60 function STAMP$() STAMP="--" STAMP[ 3; 6]=.jobname STAMP[10; 6]=.terminal STAMP[17; 6]=.pgmname STAMP[24;10]=.pgmversion STAMP[35; 3]=.day STAMP[39; 8]=merge("##/##/##",.date using "#ZZZZZ") STAMP[48; 8]=merge("##:##:##",.time using "#ZZZZZ") RETURN STAMP+" "+.username endfunc MAP1 DDB,X,104 ! ddb for disk io MAP1 DDBX,@DDB MAP2 DERR,B,1 MAP2 DFLG,B,1 DEF DFERC=1 DEF DFBYP=2 MAP2 DDEV,B,2 MAP2 DDRV,B,2 MAP2 DFIL,B,4 MAP2 DEXT,B,2 MAP2 DPPN,B,2 MAP2 DREC,B,4 MAP2 DBUF,B,4 MAP2 DSIZ,B,4 MAP2 DIDX,B,4 MAP2 DOPN,B,1 ! save file ID debug info format MAP1 FH$,S,80, & "Save file ID: \2345\ block=### MFDs=\-\ UFDs=\---\ \234567\ hash=\234567\" ! block ID debug info format MAP1 BH$,S,80, & "Block ID: block=###### PPN=\23456\ relative=#### hash=\234567\" MAP1 SILENT'FLAG,F MAP1 OUTFIL,S,30 MAP1 HASHCODE,B,4 MAP1 I,F MAP1 J,F MAP1 A$,S,15 ! !======= ! UFDSAV: ++INCLUDE USMAC:MTMCSN GOSUB SETUP GOSUB SHOW'LABEL ! read label and display some fields GOSUB WRITE'ID GOSUB SAVE'LABEL GOSUB SAVE'MFD GOSUB SAVE'UFD GOSUB UPDATE'LABEL EXIT: IF OUTFIL<>SPACE CLOSE #1 END SETUP: PRINT .pgmname;" v";.pgmversion IF INSTR(1,.options,"/S") SILENT'FLAG=-1 I=INSTR(1,.options,"=") WHEN I=0 ! PRINT "?Command line error" : END PRINT "%No file output; DEBUG ONLY run." OUTFIL=SPACE ELSE OUTFIL=.options[1,I-1] WEND ID'DEVNAM=parse(.options[I+1,-1]) XCALL DEVCHR,ID'DEVNAM,DEVCHR'MAP,ID'DEVNAM IF (DEVCHR'FLAGS AND DCF'NODEVICE) & PRINT "?No such device" : END IF (DEVCHR'FLAGS AND DCF'FILSTRUC)=0 & PRINT "?Device not file structured" : END IF (DEVCHR'FLAGS AND DCF'MOUNTED)=0 & PRINT "?Device not mounted." : END XCALL DISKIO,0,DDB,BID'BUF,ID'DEVNAM DFLG=DFLG AND (NOT (DFERC OR DFBYP)) ! enable systm error trapping WHEN OUTFIL<>SPACE LOOKUP OUTFIL,I WHEN I<>0 IF INSTR(1,.options,"/O")=0 & PRINT "?Output file exists." : END KILL OUTFIL WEND OPEN #1,OUTFIL,OUTPUT PRINT #1 ";";STAMP$() WEND RETURN WRITE'ID: ID'BLKSIZ=DEVCHR'BLKSIZE ! set block size XCALL DATES,1,0,0,ID'SAVDATE ! set save date GOSUB COUNT'MFD'BLOCKS GOSUB COUNT'UFD'BLOCKS XCALL HASH,ID,HASHCODE,0,1 ! one pass, all of id WHEN OUTFIL<>SPACE XCALL WRTREC,1,ID ! write ID XCALL WRTREC,1,HASHCODE ! write ID hash code ELSE XCALL DATES,1,0,ID'SAVDATE,A$ PRINT USING FH$;ID'DEVNAM,ID'BLKSIZ,STR(ID'MFDBLKS), & STR(ID'UFDBLKS),A$,HEX(HASHCODE) WEND RETURN SAVE'LABEL: BID'BLKNUM=0 BID'PPN=0 BID'RELBLK=0 BID'BUF=LABEL GOSUB SAVE'BLOCK RETURN SAVE'MFD: MFD'NEXT=1 ! start with MFD root block IF OUTFIL<>SPACE AND SILENT'FLAG=0 PRINT "Saving MFD block "; BID'RELBLK=0 WHILE MFD'NEXT IF OUTFIL<>SPACE AND SILENT'FLAG=0 PRINT HEX(MFD'NEXT);" "; MB=MFD'NEXT XCALL DISKIO,1,DDB,MB,MFD BID'BLKNUM=MB BID'PPN=0 BID'RELBLK+=1 BID'BUF=MFD GOSUB SAVE'BLOCK WEND IF SILENT'FLAG=0 PRINT RETURN SAVE'UFD: IF OUTFIL<>SPACE AND SILENT'FLAG=0 PRINT "Saving UFD blocks: " MFD'NEXT=1 ! start with MFD root block WHILE MFD'NEXT IF OUTFIL<>SPACE AND SILENT'FLAG=0 & PRINT " MFD block ";HEX(MFD'NEXT) MB=MFD'NEXT XCALL DISKIO,1,DDB,MB,MFD ! read MFD block FOR I=1 TO MFD'ENTRIES WHEN MFD'PPN(I) PPN=MFD'PPN(I) A$=OCT(PPN'PROJ)+","+OCT(PPN'PROG) UFD'NEXT=MFD'UFDLINK(I) IF UFD'NEXT GOSUB SAVE'UFDS WEND NEXT WEND RETURN SAVE'UFDS: IF OUTFIL<>SPACE AND SILENT'FLAG=0 PRINT " ";A$;": "; BID'RELBLK=0 WHILE UFD'NEXT IF OUTFIL<>SPACE AND SILENT'FLAG=0 PRINT HEX(UFD'NEXT);" "; UB=UFD'NEXT XCALL DISKIO,1,DDB,UB,UFD BID'BLKNUM=UB BID'PPN=PPN BID'RELBLK+=1 BID'BUF=UFD GOSUB SAVE'BLOCK WEND IF SILENT'FLAG=0 PRINT RETURN SHOW'LABEL: XCALL DISKIO,1,DDB,0,LABEL ! read label block PRINT LBL'VOLID;" ";LBL'VOLNAM;" of ";LBL'SYSNAM;" at ";LBL'INSTALATION LBLDATE=LBL'CREATED XCALL DATES,1,0,LBLDATEX,A$ PRINT "Created ";A$;" by ";LBL'CREATOR;", "; LBLDATE=LBL'ACCESSED XCALL DATES,1,0,LBLDATEX,A$ PRINT "last accessed ";A$ LBLDATE=LBL'BACKUP1 XCALL DATES,1,0,LBLDATEX,A$ PRINT "Last backed up ";A$;" on ";LBL'BACKVOL1 LBLDATE=LBL'BACKUP2 XCALL DATES,1,0,LBLDATEX,A$ PRINT "Last UFD save ";A$;" on ";LBL'BACKVOL2 RETURN UPDATE'LABEL: WHEN OUTFIL=SPACE PRINT "%Disk label not updated." ELSE XCALL DATES,1,0,ID'SAVDATE,LBLDATEX LBL'BACKUP2=LBLDATE LBL'BACKVOL2=OUTFIL XCALL DATES,1,0,LBLDATEX,A$ PRINT "UFD saved ";A$;" on ";LBL'BACKVOL2 DOPN=0 !enable write XCALL DISKIO,2,DDB,0,LABEL ! update disk label DOPN=1 !disable write WEND RETURN COUNT'MFD'BLOCKS: IF SILENT'FLAG=0 PRINT "Counting MFD blocks: "; ID'MFDBLKS=0 MFD'NEXT=1 ! start with MFD root block WHILE MFD'NEXT IF SILENT'FLAG=0 PRINT HEX(MFD'NEXT);" "; ID'MFDBLKS+=1 ! count MFD block MB=MFD'NEXT XCALL DISKIO,1,DDB,MB,MFD ! read MFD block WHEN MFD'NEXT>DEVCHR'BLOCKS ! check link to next block PRINT & "?Invalid next block link in MFD block ";HEX(MB) BREAK WEND WEND IF SILENT'FLAG=0 PRINT RETURN COUNT'UFD'BLOCKS: ID'UFDBLKS=0 IF SILENT'FLAG=0 PRINT "Counting UFD blocks: " MFD'NEXT=1 ! start with MFD root block WHILE MFD'NEXT IF SILENT'FLAG=0 PRINT " MFD block ";HEX(MFD'NEXT) MB=MFD'NEXT XCALL DISKIO,1,DDB,MB,MFD ! read MFD block FOR I=1 TO MFD'ENTRIES WHEN MFD'PPN(I) PPN=MFD'PPN(I) A$=OCT(PPN'PROJ)+","+OCT(PPN'PROG) UFD'NEXT=MFD'UFDLINK(I) WHEN UFD'NEXT WHEN UFD'NEXT>DEVCHR'BLOCKS PRINT & "%Invalid UFD block link in entry";I;"of MFD block ";HEX(MB);" for ";A$ ELSE GOSUB COUNT'UFDS WEND WEND ELSE IF MFD'UFDLINK(I) PRINT & "%Non-zero block link for zero PPN in entry";I;"of MFD block ";HEX(MB) WEND NEXT WEND RETURN COUNT'UFDS: IF SILENT'FLAG=0 PRINT " ";A$;": "; J=0 WHILE UFD'NEXT IF SILENT'FLAG=0 PRINT HEX(UFD'NEXT);" "; ID'UFDBLKS+=1 J+=1 UB=UFD'NEXT XCALL DISKIO,1,DDB,UB,UFD ! read MFD block WHEN UFD'NEXT>DEVCHR'BLOCKS PRINT & "?Invalid next block link in UFD block ";HEX(UB);", block";J;" of ";A$ BREAK WEND WEND IF SILENT'FLAG=0 PRINT RETURN SAVE'BLOCK: XCALL HASH,BLOCK'ID,HASHCODE,0,1 WHEN OUTFIL<>SPACE XCALL WRTREC,1,BLOCK'ID XCALL WRTREC,1,HASHCODE ELSE PPN=BID'PPN A$=OCT(PPN'PROJ)+","+OCT(PPN'PROG) PRINT USING BH$;BID'BLKNUM,A$,BID'RELBLK,HEX(HASHCODE) WEND RETURN