.TITLE DISKUSE .IDENT /V7.03/ ;********************************************************************** ; ; DISKUSE.TSK ; ; PRINTS A SUMMARY ON TI: OF THE CURRENT DISK USAGES FOR THE ; CURRENT ACCOUNT AND ITS MEMBERS (OR MASTER AND ITS MEMBERS). ; ; FOR USE WITH ACCOUNTING SYSTEM VERSION 7 ONLY. ; ; VERSION: V7 JUNE 1982 ; ; STEVE THOMPSON ; SCHOOL OF CHEMICAL ENGINEERING ; OLIN HALL ; CORNELL UNIVERSITY ; ITHACA NY 14853 ; ; REVISION HISTORY ; ---------------- ; ; SMT846 5-MAY-83 ADDED DISK BLOCK ALLOCATION PRINTOUT ; ; SMT851 22-JUL-83 ADDED RSX-11M V4.1 SUPPORT ; ;*********************************************************************** .MCALL GTSK$S,GTIM$S,DIR$,QIOW$,MRKT$S,STSE$S,EXIT$S .MCALL ALUN$,GLUN$ .MCALL FINIT$,FDBDF$,FDAT$A,FDRC$A,FDBK$A,FDOP$A .MCALL FDBF$A,FDAT$R .MCALL READ$,WAIT$,OPNS$R .MCALL FHDOF$,HMBOF$ .MCALL CLOSE$,EXST$S ACTDF$ <:>,<=> ; DEFINE ADDITIONAL ACCOUNT FILE OFFSETS FHDOF$ DEF$L ; DEFINE INDEX FILE OFFSETS HMBOF$ DEF$L ; DEFINE HOME BLOCK OFFSETS ; ; CONSTANTS ; EFN1 = 1 ; EVENT FLAG FOR TI: I/O EFN2 = 2 ; EVENT FLAG FOR A/C FILE I/O EFN3 = 3 ; EFN4 = 4 ; EVENT FLAG FOR DIRECTORY FILE I/O EFN5 = 5 ; EVENT FLAG FOR INDEX FILE I/O LUN1 = 1 ; TI: LUN ; LUN2 (GLOBALLY DEFINED IN ACTFIL.MAC) IS FOR ; ACCOUNT FILE I/O LUN4 = 4 ; USED TO FIND TRUE DEVICE NAMES FOR DIRECTORY ENTRIES LUN5 = 5 ; LUN FOR DIRECTORY FILES LUN6 = 6 ; LUN FOR INDEX FILES SPA = 40 ; SPACE COLON = ': ; COLON DPT = '. ; DECIMAL POINT CR = 15 ; CARRIAGE RETURN LF = 12 ; LINEFEED HT = 11 ; HORIZONTAL TAB ; ; MACROS ; .MACRO DKUDF$,L,B .ASECT .=0 D.UIC:'L' .BLKW 3 ; ASCII USER IDENTIFICATION CODE D.SYDV:'L' .BLKW 2 ; ASCII SYSTEM DEVICE FROM A/C FILE D.DEVN:'L' .BLKW 1 ; ASCII TRUE SYSTEM DEVICE NAME D.DEVU:'L' .BLKW 1 ; BINARY TRUE DEVICE NUMBER D.PREV:'L' .BLKW 2 ; # BLOCKS FOUND LAST TIME ; (FOUND FROM ACCOUNT FILE) D.BLOK:'L' .BLKW 2 ; TOTAL BLOCKS ALLOCATED D.NFIL:'L' .BLKW 1 ; NUMBER OF FILES D.ABLK:'L' .BLKW 2 ; AVERAGE BLOCKS THIS PERIOD .IF DF AA$BLK D.BALL:'L' .BLKW 2 ; BLOCK ALLOCATION .ENDC ; DF AA$BLK D.FLAG:'L' .BLKW 1 ; INTERNAL PROCESSING FLAGS D.LGTH='B'. ; LENGTH OF DATA PACKET DD.ERR='B'1 ; ERROR DURING ACCOUNT PROCESSING DD.ACN='B'2 ; THIS ENTRY PROCESSED .PSECT .MACRO DKUDF$,X,Y .ENDM .ENDM .MACRO PRINT MSG,MSGSZ MOV MSG,TIDPB+Q.IOPL .IF B MSGSZ MOV MSG'SZ,TIDPB+Q.IOPL+2 .IFF MOV MSGSZ,TIDPB+Q.IOPL+2 .ENDC DIR$ #TIDPB .ENDM ; ; DEFINE CONTROL BLOCK OFFSETS AND BITMASK DEFINITIONS ; DKUDF$ ; ; LOCAL STORAGE ; TASKSZ: .LIMIT ; TKB DEFINES ADDRESS LIMITS LUNBUF: ; BUFFER FOR GLUN$ INFORMATION TASKBF: .BLKW 16. ; TASK PARAMETERS BUFFER NUSER: .WORD 0 ; NUMBER OF USERS IN BUFFER BUFADR: .WORD 0 ; CONTAINS START ADDRESS OF USER BUFFER BUFNUM: .WORD 0 ; CONTAINS MAX. NUMBER OF USERS IN BUFFER FSIZE: .WORD 0,0 ; FILE SIZE FOR FILSIZ ROUTINE UFDADR: .BLKW 1 ; SAVED BUFFER ADDRESS IN UFD SCAN UFDAD2: .BLKW 1 ; COPY OF UFDADR FOR USE IN FILSIZ ROUTINE FDBADR: .BLKW 1 ; FDB ADDRESS FOR FCS ERROR PROCESSOR DEVN: .ASCII / / ; DEVICE NAME FOR NEXT INDEX FILE DEVU: .WORD 0 ; DEVICE UNIT FOR NEXT INDEX FILE IDXFHD: .WORD 0 ; VIRTUAL BLOCK NUMBER OF INDEX FILE HEADER ; WITHIN THE INDEX FILE IDXMAP: .WORD 0 ; "EFFECTIVE" SIZE OF INDEX FILE BITMAP OUTBUF: .BLKB 80. ; OUTPUT BUFFER (MUST BE EVEN LENGTH) IDXBUF: .WORD $ACTBF ; BLOCK BUFFER ADDRESS FOR INDEX FILE DIRBUF: .WORD $ACTBF+512. ; BLOCK BUFFER ADDRESS FOR DIRECTORY FILE ; THE INDEX FILE AND DIRECTORY FILE BUFFERS ; OVERLAY THE ACCOUNT FILE BUFFER ALLOCATED ; IN MODULE "ACTFIL". THE DIRECTORY FILE ; BUFFER IS 3 BLOCKS (1536. BYTES) LONG ; SINCE THE ACCOUNT FILE BUFFER IS 4 BLOCKS ; (2048. BYTES) LONG. ; ; ALLOCATE BUFFER FOR INDEX FILE BITMAP I/O ; .PSECT BITMP0 ; BITMAP I/O BUFFER (ALLOCATED BY TKB) $BMAP0: .PSECT BITMP1 $BMAP1: .WORD <<$BMAP1-$BMAP0>/512.> ; SIZE OF BUFFER IN DISK BLOCKS $BMAP2: .BLKW 1 ; HIGHEST FILE I.D. IN BUFFERED BITMAP .PSECT BITMSK: .WORD 1 ; BITMASK TABLE FOR INDEX FILE BITMAP CHECK .WORD 2 ; .WORD 4 ; .WORD 10 ; .WORD 20 ; .WORD 40 ; .WORD 100 ; .WORD 200 ; .WORD 400 ; .WORD 1000 ; .WORD 2000 ; .WORD 4000 ; .WORD 10000 ; .WORD 20000 ; .WORD 40000 ; .WORD 100000 ; ; ; TEXT MESSAGES ; .NLIST BEX .ENABL LC TOT1: .ASCIZ /Total of / TOT2: .ASCIZ / blocks in / TOT3: .ASCIZ / files./ HEAD: .BYTE LF,CR HEAD1: .ASCII /Device/ OUFD=.-HEAD1 .ASCII / UFD / OFIL=.-HEAD1 .ASCII /Files / OBLK=.-HEAD1 .ASCII /Blocks / HEADSZ=.-HEAD FCS: .ASCIZ / FCS / DIR: .ASCIZ / DIR / .IF DF AA$BLK ALLOC1: .ASCIZ /(Allocation = / ALLOC2: .ASCIZ / Blocks)/ .ENDC ; DF AA$BLK ; ; ERROR MESSAGES ; .IIF NDF AA$V40 & AA$V41, .DSABL LC ERR0: .ASCIZ /** Error Detected **/ ERR1: .ASCII /DISKUSE -- *FATAL* No buffer space/ ERR1SZ=.-ERR1 ERR2: .ASCII /DISKUSE -- *FATAL* Account not found/ ERR2SZ=.-ERR2 ERR3: .ASCII /DISKUSE -- *FATAL* Master account not found/ ERR3SZ=.-ERR3 ERR4: .ASCII /DISKUSE -- *FATAL* Account file open failure/ ERR4SZ=.-ERR4 ERR5: .ASCII /DISKUSE -- *WARNING* Insufficient buffer space/ ERR5SZ=.-ERR5 ERR6: .ASCII /DISKUSE -- Index file open failure on / ERR6A: .ASCII /XX000: FCS -000./ ERR7: .ASCII /DISKUSE -- Directory file open failure: / ERR7A: .ASCII /XX00:[000,000] FCS -000./ ERR8: .ASCII /DISKUSE -- Home block read error on / ERR8A: .ASCII /XX000: FCS -000./ ERR9: .ASCII /DISKUSE -- Read error on index file on / ERR9A: .ASCII /XX000: FCS -000./ ERR10: .ASCII /DISKUSE -- Read error on directory file / ERR10A: .ASCII /XX00:[000,000] FCS -000./ ERR11: .ASCII /DISKUSE -- Assign LUN4 failed: / ERR11A: .ASCII /XX00:[000,000]/ ERR12: .ASCII /DISKUSE -- Get LUN4 information failed: / ERR12A: .ASCII /XX00:[000,000]/ ERR13: .ASCII "DISKUSE -- File ID/Sequence number check - " ERR13A: .ASCII /DDNN:[GGG,MMM]FILENAME.TYPE;VERS/ ERR14: .ASCII "DISKUSE -- Skipping file synonym - " ERR14A: .ASCII /DDNN:[GGG,MMM]FILENAME.TYPE;VERS/ ERR15: .ASCII /DISKUSE -- *WARNING* Index file bitmap truncated on / ERR15A: .ASCII /XX000:/ ERR16: .ASCII /DISKUSE -- *WARNING* Read error on index file bitmap on / ERR16A: .ASCII /XX000: FCS -000./ .ENABL LC ; ; FILE RELATED STORAGE ; .EVEN DIRFDB: FDBDF$ ; FILE DESCRIPTOR BLOCK FOR UFD FDAT$A R.FIX,,512. ; ([0,0]XXXXXX.DIR) FDRC$A FD.RWM!FD.RAN!FD.PLC FDBK$A <$ACTBF+512.>,<3*512.>,,EFN4,DFSTAT FDOP$A LUN5,DIRDSP FDBF$A EFN4 IDXFDB: FDBDF$ ; FILE DESCRIPTOR BLOCK FOR INDEX FILE FDAT$A R.FIX,,512. ; FDRC$A FD.RWM!FD.RAN!FD.PLC FDBK$A $ACTBF,512.,,EFN5,IFSTAT FDOP$A LUN6,IDXDSP FDBF$A EFN5 IFSTAT: .BLKW 2 ; I/O STATUS BLOCK: INDEX FILE DFSTAT: .BLKW 2 ; I/O STATUS BLOCK: DIRECTORY FILE IDXDSP: .WORD IDXDSZ,IDXDEV ; DATASET DESCRIPTOR FOR INDEX FILE .WORD DIRSIZ,DIR00 ; .WORD DXFSIZ,INDEXF ; DIRDSP: .WORD IDXDSZ,IDXDEV ; DATASET DESCRIPTOR FOR DIRECTORY FILE .WORD DIRSIZ,DIR00 ; .WORD DIRECS,DIRECF ; DEVNAM: .ASCII /LB0:/ DEVSIZ=.-DEVNAM .EVEN ; DON'T REMOVE IDXDEV: .ASCII /SY000:/ ; FOR INDEX AND DIRECTORY FILES ; (MUST BE 3 CHARACTERS IN UNIT NUMBER) IDXDSZ=.-IDXDEV DIR00: .ASCII /[0,0]/ ; DIRECTORY STRING DIRSIZ=.-DIR00 INDEXF: .ASCII /INDEXF.SYS/ ; INDEX FILE NAME DXFSIZ=.-INDEXF ; "DIRECF" MUST START ON A WORD BOUNDARY .EVEN DIRECF: .ASCII /000000.DIR/ ; DIRECTORY FILE NAME DIRECS=.-DIRECF ; ; OTHER LOCAL STORAGE ; .BLKB 4 ; WORKSPACE, MUST BE BEFORE "UIC" UIC: .BLKB 6 ; FOR ASCII UIC .EVEN ACNO: .BLKW 1 ; ACCOUNT NUMBER TOTBLK: .WORD 0,0 ; TOTAL BLOCKS TOTFIL: .WORD 0,0 ; TOTAL FILES ; ; DIRECTIVE PARAMETER BLOCKS ; .EVEN ALUN: ALUN$ LUN4,SY,0 ; ASSIGN LUN DPB GLUN: GLUN$ LUN4,LUNBUF ; GET LUN INFORMATION DPB TIDPB: QIOW$ IO.WVB,LUN1,EFN1,,,,<0,0,40> TIATT: QIOW$ IO.ATT,LUN1,EFN1 TIDET: QIOW$ IO.DET,LUN1,EFN1 .PAGE .SBTTL MAIN PROGRAM $DSKEP: ; ENTRY POINT FINIT$ ; INITIALISE FSR ; ; DETERMINE SIZE OF USER BUFFER REGION. SPACE USED IS FROM THE END OF ; CODE UP TO THE END OF THE PARTITION. THE BUFFER IS ZEROED TO ; INITIALISE ALL CONTROL BLOCKS. ; GTSK$S #TASKBF ; GET TASK PARAMETERS MOV TASKSZ+2,R1 ; GET END OF CODE ADDRESS ADD #2,R1 ; BUMP UP BY TWO MOV R1,BUFADR ; SAVE START OF USER BUFFERS MOV TASKBF+G.TSTS,R0 ; GET SIZE OF TASK (END OF PARTITION ADDR.) SUB #<5*2>,R0 ; ALLOCATE A 5 WORD SAFETY ZONE SUB R1,R0 ; CALCULATE USER BUFFER SIZE BLE 10$ ; LE IS ERROR MOV R0,R3 ; SAVE SIZE INC R3 ; DON'T FORGET A BYTE ASR R3 ; CONVERT TO WORDS MOV #D.LGTH,R1 ; GET LENGTH OF ONE CONTROL BLOCK CALL $DIV ; CALCULATE MAX. NO OF CONTROL BLOCKS MOV R0,BUFNUM ; SAVE RESULT BGT 30$ ; POSITIVE IS OK 10$: PRINT #ERR1,#ERR1SZ ; NO BUFFER SPACE 20$: JMP EXSEV ; EXIT WITH SEVERE ERROR 30$: MOV BUFADR,R0 ; GET START ADDR. OF USER BUFFER 40$: CLR (R0)+ ; ZERO A WORD DEC R3 ; DONE YET? BNE 40$ ; IF NE NO, LOOP ; ; DETERMINE WHO THE USER IS. ; MOVB TASKBF+G.TSPC,R1 ; GET MEMBER CODE BIC #177400,R1 ; ZERO THE RUBBISH BYTE MOV #UIC,R0 ; GET BUFFER ADDRESS FOR ASCII UIC MOV PC,R2 ; INCLUDE LEADING ZEROES CALL $CBOMG ; CONVERT TO ASCII MOVB TASKBF+G.TSGC,R1 ; GET GROUP CODE BIC #177400,R1 ; ZERO THE HIGH BYTE MOV #UIC-3,R0 ; SET BUFFER ADDRESS CALL $CBOMG ; CONVERT TO ASCII OCTAL ; ; OPEN ACCOUNT FILE AND SEARCH FOR ACCOUNT ENTRY ; ALSO WE FILL IN THE TRUE DEVICE NAMES AND NUMBERS AS REPRESENTED IN ; THE ACCOUNT FILE ENTRIES. ; CLR $ACTFL+F.FNB+N.FID ; DON'T OPEN BY FILE ID CALL OPENAF ; OPEN THE ACCOUNT FILE ; (THIS ROUTINE DOES NOT RETURN CONTROL ; IF ANY ERRORS ARE DETECTED) MOV #ACCPT1,$ASUBR ; SET ACCEPTANCE ROUTINE ADDRESS CALL $ASCAN ; SEARCH FOR IT BCC 81$ ; GOOD CALL $AFCLS ; CLOSE ACCOUNT FILE PRINT #ERR2,#ERR2SZ ; ACCOUNT NOT FOUND JMP EXSEV ; EXIT WITH SEVERE ERROR 81$: MOV A.CHWD(R0),ACNO ; ACCOUNT CHAINED? BEQ 83$ ; IF EQ NO 82$: MOV #ACCPT2,$ASUBR ; SET ACCEPTANCE ROUTINE FOR MASTER SEARCH CALL $ASCAN ; LOOK FOR MASTER ACCOUNT BCC 83$ ; FOUND IT CALL $AFCLS ; CLOSE ACCOUNT FILE PRINT #ERR3,#ERR3SZ ; MASTER ACCOUNT NOT FOUND JMP EXSEV ; EXIT WITH SEVERE ERROR 83$: MOV A.ACNO(R0),ACNO ; SAVE ACCOUNT NUMBER 85$: BIC #100000,ACNO ; CLEAR MASTER FLAG ; ; COPY ALL RELEVANT ACCOUNTS FROM ACCOUNT FILE TO INTERNAL BUFFERS ; MOV BUFADR,R5 ; GET USER BUFFERS ADDRESS MOV BUFNUM,R4 ; AND NUMBER OF CONTROL BLOCKS 100$: CALL $AFGET ; READ DATA FROM THE ACCOUNT FILE BNE 110$ ; IF NE WE GOT SOME DATA JMP 130$ ; NO WORDS READ 110$: TST A.GRP(R0) ; ENTRY IN USE? BNE 1101$ ; IF NE YES JMP 120$ ; TRY NEXT ACCOUNT 1101$: TST A.ACNO(R0) ; ENTRY ENABLED FOR ACCOUNTING? BNE 1102$ ; IF NE YES TST A.CHWD(R0) ; ACCOUNT CHAINED? 1102$: BEQ 1103$ ; IF EQ NO CMP ACNO,A.CHWD(R0) ; YES, ARE WE THE MASTER? BEQ 1105$ ; IF EQ YES, INCLUDE US 1103$: MOV A.ACNO(R0),-(SP) ; PUSH ACCOUNT NUMBER BIC #100000,(SP) ; CLEAR MASTER FLAG CMP (SP)+,ACNO ; IS THIS OUR ACCOUNT? BEQ 1105$ ; IF EQ YES JMP 120$ ; TRY NEXT ACCOUNT 1105$: INC NUSER ; SHOW ONE MORE USER IN BUFFER MOV A.GRP(R0),D.UIC(R5) ; SAVE UIC IN USER BUFFER MOV A.GRP+2(R0),D.UIC+2(R5) ; MOV A.GRP+4(R0),D.UIC+4(R5) ; MOV A.SYDV(R0),D.SYDV(R5) ; SAVE SYSTEM DEVICE (ASCII) MOV A.SYDV+2(R0),D.SYDV+2(R5) ; .IF DF AA$BLK TST A.CHWD(R0) ; ACCOUNT CHAINED? BNE 1106$ ; IF NE YES, NO BLOCK ALLOCATION MOV A.BALL(R0),D.BALL(R5) ; SAVE BLOCK ALLOCATION MOV A.BALL+2(R0),D.BALL+2(R5) ; 1106$: ; REF. LABEL .ENDC ; DF AA$BLK MOV A.ABLK(R0),D.ABLK(R5) ; SAVE AVERAGE BLOCKS MOV A.ABLK+2(R0),D.ABLK+2(R5) ; MOV A.PREV(R0),D.PREV(R5) ; SAVE BLOCKS FOUND LAST TIME MOV A.PREV+2(R0),D.PREV+2(R5) ; MOV D.SYDV(R5),ALUN+A.LUNA ; SET UP DEVICE NAME IN DPB CALL UNITNM ; CONVERT UNIT NUMBER TO BINARY MOV R1,ALUN+A.LUNU ; STORE IT IN THE ALUN$ DPB BIS #DD.ERR,D.FLAG(R5) ; ASSUME THERE WILL BE AN ERROR DIR$ #ALUN ; ASSIGN THE LUN BCC 114$ ; OK MOV R0,-(SP) ; SAVE R0 MOV #ERR11A,R0 ; SET UP ERROR MESSAGE POINTERS MOV #ERR11,R1 ; 112$: MOVB D.SYDV(R5),(R0)+ ; MOVE IN DEVICE SPEC. MOVB D.SYDV+1(R5),(R0)+ ; MOVB D.SYDV+2(R5),(R0)+ ; MOVB D.SYDV+3(R5),(R0)+ ; MOVB #COLON,(R0)+ ; DEVICE/UFD SEPARATOR CALL FMTUIC ; FILL IN UFD AS [GGG,MMM] SUB R1,R0 ; CALCULATE MESSAGE SIZE PRINT R1,R0 ; PRINT IT OUT MOV (SP)+,R0 ; RESTORE R0 BR 115$ ; CONTINUE WITH NEXT USER 114$: DIR$ #GLUN ; GET LUN INFO. BCC 116$ ; OK MOV R0,-(SP) ; SAVE R0 MOV #ERR12A,R0 ; SET UP ERROR MESSAGE PARAMETERS MOV #ERR12,R1 ; BR 112$ ; SEND ERROR MESSAGE 116$: BIC #DD.ERR,D.FLAG(R5) ; OK, CLEAR ERROR FLAG MOV LUNBUF+G.LUNA,D.DEVN(R5) ; STORE DEVICE NAME BISB LUNBUF+G.LUNU,D.DEVU(R5) ; AND UNIT NUMBER 115$: ADD #D.LGTH,R5 ; POINT TO NEXT CONTROL BLOCK DEC R4 ; ANY LEFT? BNE 120$ ; IF NE YES PRINT #ERR5,#ERR5SZ ; NO, SAY OVERFLOW BR 140$ ; THAT'S IT 120$: ADD #A.LEN,R0 ; POINT TO NEXT ACCOUNT ENTRY SUB #A.LEN,R2 ; ANY DATA LEFT IN BUFFER? BLOS 130$ ; IF LOS NO, DON'T LOOP JMP 110$ ; GIVE THE NEXT USER THE TREATMENT 130$: CMPB #IE.EOF,$AFIOS ; END OF FILE? BEQ 140$ ; IF EQ YES TSTB $AFIOS ; NO, ANY ERRORS? BMI 140$ ; IF MI YES CALL $AFNXB ; POINT TO NEXT BLOCK IN A/C FILE JMP 100$ ; GO DO IT 140$: CALL $AFCLS ; CLOSE THE ACCOUNT FILE TST NUSER ; DID WE GET ANYTHING? BNE 145$ ; IF NE YES JMP EXIT ; NO, JUST EXIT ; ; NOW WE SCAN THE INTERNAL BUFFER ENTRY BY ENTRY. THE SCAN IS SUCH THAT WE ; DO IT DEVICE BY DEVICE SO THAT THE INDEX FILE FOR EACH VOLUME HAS TO BE ; OPENED ONLY ONCE. FOR EACH VOLUME, THE BLOCKS IN USE BY EACH USER REPRESENTED ; IN THE ACCOUNT FILE IS DETERMINED. ANY UFDS THAT ARE ON THE VOLUME BUT DO ; NOT HAVE A CORRESPONDING ACCOUNT IN THE ACCOUNT FILE WILL BE IGNORED. ; 145$: DIR$ #TIATT ; ATTACH TO TI: PRINT #HEAD,#HEADSZ ; TYPE OUT TABLE HEADING 150$: CALL NXTDEV ; GET THE NEXT DEVICE TO EXAMINE BCS 170$ ; IF CS NO MORE DEVICES CALL INDEXV ; OPEN THE INDEX FILE ON THIS VOLUME AND ; SET IT UP FOR FCS I/O BCS 150$ ; OPEN FAILURE ON INDEX FILE, GET NEXT DEVICE 160$: CALL NXTUSR ; GET THE NEXT USER ON THIS VOLUME BCS 150$ ; IF CS THERE AREN'T ANY MORE CALL UFDSIZ ; FIND USAGE PARAMETERS FOR THIS USER CALL LIST ; PRINT TOTALS FOR THIS USER BR 160$ ; REPEAT FOR NEXT USER 170$: DIR$ #TIDET ; DETACH TI: CALL SHWTTL ; SHOW TOTALS BR EXIT ; AND EXIT EXSEV: EXST$S #EX$SEV ; EXIT WITH SEVERE ERROR EXIT: EXIT$S ; NORMAL EXIT .PAGE .SBTTL ROUTINE TO OPEN ACCOUNT FILE ;+ ; *** OPENAF ; ; THIS ROUTINE OPENS THE RSX11 SYSTEM ACCOUNT FILE. IF THERE ; ARE ERRORS, AN ERROR MESSAGE IS PRINTED AND A JUMP IS MADE ; TO EXSEV TO GENERATE A SEVERE ERROR. ; ;- OPENAF: CALL $AFOPN ; CALL A/C FILE OPEN ROUTINE BCC 10$ ; GOOD PRINT #ERR4 ; ERROR, PRINT MESSAGE JMP EXSEV ; AND GENERATE A SEVERE ERROR EXIT 10$: RETURN ; RETURN TO CALLER .PAGE .SBTTL ROUTINE TO CONVERT DISK UNIT NUMBER ;+ ; *** UNITNM ; ; THIS ROUTINE CONVERTS A TWO-DIGIT ASCII DISK UNIT NUMBER TO ; BINARY. ; ; INPUTS: ; R5 ADDRESS OF DISK CONTROL BLOCK ; ; OUTPUTS: ; R1 BINARY UNIT NUMBER ; ALL OTHER REGISTERS ARE (MUST BE) PRESERVED ; ;- UNITNM: CLR -(SP) ; CLEAR LOCATION READY FOR UNIT NUMBER BISB D.SYDV+2(R5),(SP) ; GET FIRST DIGIT OF UNIT NUMBER SUB #'0,(SP) ; SUBTRACT BIAS TO GET A NUMBER ASL (SP) ; MULTIPLY BY EIGHT ASL (SP) ; ASL (SP) ; CLR R1 ; ZERO R1 FOR SECOND DIGIT BISB D.SYDV+3(R5),R1 ; GET SECOND DIGIT OF UNIT NUMBER SUB #'0,R1 ; SUBTRACT CHARACTER BIAS ADD (SP)+,R1 ; GET FINAL UNIT NUMBER RETURN ; AND RETURN TO CALLER .PAGE .SBTTL ROUTINE TO GET NEXT DEVICE FOR ACCOUNTING ;+ ; *** NXTDEV ; ; THIS ROUTINE SCANS THE INTERNAL BUFFER AND OBTAINS THE NEXT ; DEVICE TO BE ACCOUNTED. THIS IS OBTAINED FROM THE D.DEVN AND ; D.DEVU FIELDS OF THE FIRST CONTROL BLOCK FOUND THAT HAS ; D.FLAG EQUAL TO ZERO. ; ; OUTPUT: ; CARRY SET -- ALL DEVICES HAVE BEEN ACCOUNTED ; CARRY CLEAR DEVN AND DEVU HAVE BEEN SET UP WITH THE NAME ; AND NUMBER OF THE NEXT DEVICE TO ACCOUNT. ;- NXTDEV: CLOSE$ #IDXFDB ; MAKE SURE INDEX FILE IS CLOSED AFTER ; PREVIOUS OPERATION MOV BUFADR,R5 ; GET INTERNAL BUFFER ADDRESS MOV BUFNUM,R4 ; AND SIZE OF IT (# CONTROL BLOCKS) 10$: TST D.UIC(R5) ; THIS ENTRY IN USE? BEQ 20$ ; IF EQ NO, SKIP IT TST D.FLAG(R5) ; ALREADY ACCOUNTED? BNE 20$ ; IF NE YES, SKIP IT MOV D.DEVN(R5),DEVN ; SAVE DEVICE NAME MOV D.DEVU(R5),DEVU ; AND ITS UNIT NUMBER BR 30$ ; RETURN WITH SUCCESS 20$: ADD #D.LGTH,R5 ; POINT TO NEXT CONTROL BLOCK DEC R4 ; ARE THERE ANY MORE? BNE 10$ ; IF NE YES, TRY THEM SEC ; NO, SET NO MORE DEVICES TO ACCOUNT BR 40$ ; AND RETURN 30$: CLC ; SET SUCCESS 40$: RETURN ; AND RETURN TO CALLER .PAGE .SBTTL INDEX FILE OPEN ROUTINE ;+ ; *** INDEXV ; ; ; THIS ROUTINE OPENS THE INDEX FILE ON THE VOLUME SEPCIFIED BY ; "DEVN" AND "DEVU". THE INDEX FILE IS SIZED TO PERMIT FCS I/O. ; AN ERROR MESSAGE IS DISPLAYED IF THERE IS AN OPEN ERROR - THE ; VOLUME WILL NOT BE ACCOUNTED. ALL USERS ON THIS VOLUME MUST BE ; SCANNED (TO PREVENT A LOOP LOOKING FOR THE NEXT DEVICE TO ; ACCOUNT) AND MARKED WITH AN ERROR FLAG. ; ;- INDEXV: MOV #IDXDEV,R0 ; GET ADDRESS OF DEVICE STRING FOR OPEN MOV DEVN,(R0)+ ; INSERT THE DEVICE NAME MOV DEVU,R1 ; GET DEVICE PHYSICAL UNIT NUMBER MOV PC,R2 ; FIELD WIDTH OF 3 CHARACTERS CALL $CBTMG ; CONVERT TO OCTAL MOV #IDXFDB,FDBADR ; SET FDB ADDRESS FOR ERROR PROCESSOR OPNS$R #IDXFDB ; OPEN THE INDEX FILE BCC 20$ ; GOOD, WE DID IT MOV #ERR6A,R0 ; GET PLACE FOR DEVICE NAME MESSAGE MOV #ERR6,R3 ; SET ERROR MESSAGE ADDRESS 10$: CALL FMTDEV ; FORMAT DEVICE NAME CALL FCSERR ; INSERT FCS ERROR INFORMATION SUB R3,R0 ; CALCULATE ERROR MESSAGE SIZE PRINT R3,R0 ; SEND IT OUT CALL IDXERR ; SET ERROR MARKERS FOR THIS VOLUME SEC ; SET CARRY TO INDICATE FAILURE JMP 40$ ; AND RETURN TO CALLER 20$: MOV #3,IDXFDB+F.EFBK+2 ; SET EOF BLOCK TO READ HOME BLOCK MOV #2,IDXFDB+F.BKVB+2 ; SET VIRTUAL BLOCK NUMBER TO 2 READ$ #IDXFDB ; READ HOME BLOCK BCC 30$ ; GOOD CLOSE$ #IDXFDB ; CLOSE INDEX FILE MOV #ERR8A,R0 ; BUFFER ADDRESS FOR DEVICE STRING MOV #ERR8,R3 ; ERROR TEXT ADDRESS BR 10$ ; SEND OUT ERROR 30$: WAIT$ #IDXFDB ; WAIT FOR HOME BLOCK I/O TO COMPLETE MOV IDXBUF,R0 ; GET BUFFER ADDRESS MOV H.IBSZ(R0),R0 ; GET INDEX BIT MAP SIZE MOV R0,IDXMAP ; SAVE IT ADD #3,R0 ; FIND VIRTUAL BLOCK FOR INDEX FILE HEADER MOV R0,IDXFHD ; AND SAVE IT FOR DIRECTORY SCAN MOV R0,IDXFDB+F.BKVB+2 ; SET UP TO READ INDEX FILE HEADER INC R0 ; GET EOF BLOCK MOV R0,IDXFDB+F.EFBK+2 ; SET IT UP IN THE FDB CLR UFDADR ; DISABLE ID/SEQUENCE NUMBER CHECK CALL FILSIZ ; FIND SIZE OF INDEX FILE ADD #1,FSIZE+2 ; POINT PAST EOF ADC FSIZE ; MOV FSIZE,IDXFDB+F.EFBK ; SET THIS UP IN THE FDB MOV FSIZE+2,IDXFDB+F.EFBK+2 ; CALL BITMAP ; READ INDEX FILE BITMAP 40$: RETURN ; RETURN TO CALLER .PAGE .SBTTL ERROR MARKER ROUTINE ;+ ; *** IDXERR ; ; THIS ROUTINE IS CALLED WHEN THERE HAS BEEN AN INDEX FILE OPEN ; ERROR (EG VOLUME NOT MOUNTED). ALL USERS ON THIS VOLUME HAVE ; THEIR ERROR FLAGS SET TO AVOID A LOOP IN THE NEXT VOLUME ; ROUTINE. ; ;- IDXERR: CLOSE$ #IDXFDB ; MAKE SURE FILE IS CLOSED MOV BUFADR,R5 ; GET ADDRESS OF USER DATA REGION MOV BUFNUM,R4 ; AND NUMBER OF CONTROL BLOCKS 10$: TST D.UIC(R5) ; THIS ENTRY IN USE? BEQ 20$ ; IF EQ, NO CMP D.DEVN(R5),DEVN ; YES, ON THE RIGHT VOLUME? BNE 20$ ; IF NE NO CMP D.DEVU(R5),DEVU ; MAYBE BNE 20$ ; IF NE NO BIS #DD.ERR,D.FLAG(R5) ; OK, SET ERROR FLAG 20$: ADD #D.LGTH,R5 ; POINT TO NEXT CONTROL BLOCK DEC R4 ; AND MORE LEFT? BNE 10$ ; IF NE YES, SO LOOP RETURN ; ELSE RETURN TO CALLER .PAGE .SBTTL INDEX FILE BIT MAP READ ROUTINE ;+ ; *** BITMAP ; ; THIS ROUTINE IS CALLED DURING THE INDEX FILE OPEN PHASE. IT ; BUFFERS THE INDEX FILE BIT MAP IN THE ACCOUNT FILE BUFFER. ; THIS MAP IS USED SUBSEQUENTLY TO DETERMINE IF WE HAVE ALREADY ; LOOKED AT A PARTICULAR FILE HEADER (IE FOR PROPER SYNONYM ; EXCLUSION). IF THE BITMAP IS TOO LARGE (>BUFFER SIZE), WE READ ; WHAT WE CAN AND FUDGE THE REST. IF WE CAN'T READ THE BITMAP ; FOR ANY REASON, WE SKIP IT AND HOPE THAT EVERYONE IS NOT ; MADLY RENAMING THEIR FILES. IF THERE IS NO BITMAP BUFFER ; ALLOCATION, WE FUDGE EVRYTHING. ; ;- BITMAP: TST $BMAP1 ; ANY BITMAP BUFFER ALLOCATION? BNE 10$ ; IF NE YES CLR IDXMAP ; NO, CLEAR SIZE WORD BR 50$ ; AND RETURN 10$: CMP IDXMAP,$BMAP1 ; BIT MAP TOO LARGE? BLE 20$ ; IF LE NO MOV $BMAP1,IDXMAP ; YES, USE ONLY THE FIRST BLOCKS MOV #ERR15A,R0 ; GET ERROR MESSAGE ADDRESS FOR DEVICE CALL FMTDEV ; FORMAT DEVICE NAME SUB #ERR15,R0 ; CALCULATE MESSAGE LENGTH PRINT #ERR15,R0 ; AND PRINT IT, THEN CONTINUE 20$: MOV #$BMAP0,IDXFDB+F.BKDS+2 ; SET NEW BUFFER ADDRESS MOV IDXMAP,R0 ; GET REQUIRED SIZE IN BLOCKS SWAB R0 ; MULTIPLY BY 512. TO GET SIZE... ASL R0 ; ...IN BYTES MOV R0,IDXFDB+F.BKDS ; AND PUT IT IN THE FDB MOV #3,IDXFDB+F.BKVB+2 ; SET UP TO READ 1ST BLOCK OF BITMAP READ$ #IDXFDB ; READ INDEX FILE BITMAP BCC 30$ ; IF CC GOOD CLR IDXMAP ; SHOW NO BITMAP AVAILABLE MOV #ERR16A,R0 ; GET ERROR MESSAGE ADDRESS FOR DEVICE CALL FMTDEV ; FORMAT DEVICE NAME CALL FCSERR ; INSERT FCS ERROR INFORMATION SUB #ERR16,R0 ; CALCULATE MESSAGE LENGTH PRINT #ERR16,R0 ; AND PRINT IT BR 40$ ; RESET BUFFER PARAMETERS AND RETURN 30$: WAIT$ #IDXFDB ; WAIT FOR BITMAP I/O MOV IFSTAT+2,R0 ; GET COUNT OF BYTES READ ASL R0 ; COMPUTE HIGHEST FILE I.D. AVAILABLE ASL R0 ; ASL R0 ; MOV R0,$BMAP2 ; SAVE FOR CHKBIT ROUTINE 40$: MOV #512.,IDXFDB+F.BKDS ; RESET BUFFER SIZE MOV IDXBUF,IDXFDB+F.BKDS+2 ; RESET BUFFER ADDRESS 50$: RETURN ; AND RETURN TO INDEX FILE ROUTINE .PAGE .SBTTL ROUTINE TO FIND NEXT USER FOR ACCOUNTING ;+ ; *** NXTUSR ; ; THIS ROUTINE SCANS THE USER BUFFER TO FIND THE NEXT USER TO BE ; ACCOUNTED ON THE CURRENT VOLUME. THIS IS THE USER WITH D.FLAG=0 ; AND WITH A TRUE SYSTEM DEVICE THAT MATCHES THAT OF THE CURRENT ; VOLUME, AS IN DEVN AND DEVU. ; ; OUTPUT: ; R5 USER'S CONTROL BLOCK ADDRESS ; ;- NXTUSR: MOV BUFADR,R5 ; GET BUFFER ADDRESS MOV BUFNUM,R4 ; AND NUMBER OF USERS 10$: TST D.UIC(R5) ; THIS ENTRY IN USE? BEQ 20$ ; IF EQ NO TST D.FLAG(R5) ; THIS ENTRY BEEN DONE YET? BNE 20$ ; IF NE YES, SKIP IT CMP D.DEVN(R5),DEVN ; DO DEVICE NAMES MATCH? BNE 20$ ; IF NE NO, SKIP THIS USER CMP D.DEVU(R5),DEVU ; YES, DO UNIT NUMBERS MATCH? BEQ 30$ ; IF EQ YES, THIS IS THE ONE WE WANT 20$: ADD #D.LGTH,R5 ; POINT TO NEXT CONTROL BLOCK DEC R4 ; ARE THERE ANY LEFT? BNE 10$ ; IF NE YES, LOOP SEC ; NO, SET CARRY TO INDICATE WE'RE OUT OF USERS BR 40$ ; AND RETURN 30$: CLC ; CLEAR CARRY TO INDICATE SUCCESS 40$: RETURN ; RETURN TO CALLER .PAGE .SBTTL USER FILE DIRECTORY SCANNING ROUTINE ;+ ; *** UFDSIZ ; ; THIS ROUTINE SCANS A USER FILE DIRECTORY ON THE CURRENT VOLUME ; AND ADDS UP THE TOTAL NUMBER OF FILES AND BLOCKS ALLOCATED TO ; THE USER. THE VOLUME SPECIFICATION IS ALREADY SET UP IN THE ; DATASET DESCRIPTOR, BUT THE UFD NAME NEEDS TO BE INITIALISED. ; THE DIRECTORY FILE IS READ IN 3 BLOCKS AT A TIME. ; ; INPUT: ; R5 USER CONTROL BLOCK ADDRESS ; ; OUTPUT: ; THE RELEVANT AREAS IN THE CONTROL BLOCK ARE ; INCREMENTED. ; ;- UFDSIZ: MOV #DIRECF,R0 ; GET ADDRESS OF DIRECTORY FILE NAME STRING MOV D.UIC(R5),(R0)+ ; SET UP UFD NAME IN DATASET DESCRIPTOR MOV D.UIC+2(R5),(R0)+ ; MOV D.UIC+4(R5),(R0)+ ; BIS #DD.ACN,D.FLAG(R5) ; SHOW THIS ENTRY DONE MOV #DIRFDB,FDBADR ; SET FDB ADDRESS FOR ERROR PROCESSOR OPNS$R #DIRFDB ; OPEN THE DIRECTORY FILE BCC 20$ ; OK BIS #DD.ERR,D.FLAG(R5) ; SHOW AN ERROR IN THE CONTROL BLOCK MOV #ERR7A,R0 ; GET UFD FIELD ADDRESS IN ERROR MESSAGE MOV #ERR7,R3 ; AND ERROR TEXT ADDRESS 10$: CALL FMTDEV ; INSERT DEVICE SPECIFICATION CALL FMTUIC ; AND THE UFD IN [GGG,MMM] FORM CALL FCSERR ; INSERT FCS ERROR INFORMATION SUB R3,R0 ; CALCULATE MESSAGE LENGTH PRINT R3,R0 ; TYPE IT OUT BR 60$ ; AND RETURN 20$: MOV #DIRFDB,FDBADR ; SET FDB ADDRESS FOR ERROR PROCESSOR READ$ #DIRFDB ; READ A BLOCK OF THE DIRECTORY FILE BCC 30$ ; GOOD CMPB #IE.EOF,DIRFDB+F.ERR ; END OF FILE? BEQ 60$ ; IF EQ YES, THAT'S IT 22$: MOV #ERR10A,R0 ; SET UP ERROR MESSAGE PARAMETERS MOV #ERR10,R3 ; BR 10$ ; SEND IT 30$: WAIT$ #DIRFDB ; WAIT FOR I/O MOV DFSTAT+2,R3 ; GET COUNT OF BYTES READ ASR R3 ; DIVIDE BY SIXTEEN... ASR R3 ; ...TO GET NUMBER OF... ASR R3 ; ...DIRECTORY ENTRIES... ASR R3 ; ...(EACH IS 16. BYTES LONG) BEQ 22$ ; IF EQ, SOMETHING IS UP MOV DIRBUF,R0 ; GET BUFFER ADDRESS (FIRST ENTRY ADDRESS) 40$: MOV R0,UFDADR ; NOTE CURRENT POSITION IN UFD MOV (R0),R1 ; GET FILE ID BEQ 50$ ; IF EQ NO FILE IS IN THIS SLOT ADD IDXFHD,R1 ; CALCULATE VBN FOR FILE HEADER IN INDEX FILE DEC R1 ; MOV R1,IDXFDB+F.BKVB+2 ; SET UP VBN FOR FILSIZ ROUTINE CALL FILSIZ ; FIND THE SIZE OF THIS FILE ADD FSIZE+2,D.BLOK+2(R5) ; ADD FILE SIZE TO UFD SIZE ADC D.BLOK(R5) ; ADD FSIZE,D.BLOK(R5) ; ADD FSIZE+2,TOTBLK+2 ; ADC TOTBLK ; ADD FSIZE,TOTBLK ; INC D.NFIL(R5) ; AND NUMBER OF FILES ADD #1,TOTFIL+2 ; ADC TOTFIL ; MOV UFDADR,R0 ; RESTORE CURRENT UFD POSITION 50$: ADD #<8.*2>,R0 ; POINT TO NEXT ENTRY DEC R3 ; ARE THERE ANY MORE? BNE 40$ ; IF NE YES, DO IT BR 20$ ; TRY NEXT BLOCK OF DIRECTORY FILE 60$: CLOSE$ #DIRFDB ; CLOSE THE DIRECTORY FILE 70$: RETURN ; AND RETURN TO CALLER .PAGE .SBTTL ROUTINE TO FIND THE SIZE OF A FILE ;+ ; *** FILSIZ ; ; THIS ROUTINE FINDS THE SIZE OF A FILE. ; ON ENTRY INTO THIS ROUTINE, THE FILE DESCRIPTOR BLOCK FOR ; THE INDEX FILE (IDXFDB) MUST BE SET UP WITH THE VIRTUAL BLOCK ; NUMBER OF THE FILE HEADER WITHIN THE INDEX FILE. ; A FILE ID/SEQUENCE NUMBER CHECK IS PERFORMED IF "UFDADR" IS ; NON-ZERO AND CONTAINS THE ADDRESS OF THE BUFFERED DIRECTORY ; ENTRY. WE CHECK TO SEE IF WE HAVE ALREADY EXAMINED THIS FILE ; BY CHECKING THE STATE OF THE RELEVANT BIT IN THE BUFFERED ; INDEX FILE BITMAP. IF NO BITMAP IS AVAILABLE, WE REQUIRE THE ; FILESPEC IN THE DIRECTORY ENTRY TO MATCH THAT IN THE FILE ; HEADER (NOT VALID IF FILES ARE RENAMED). ; ; OUTPUT: ; FSIZE SIZE OF FILE IN BLOCKS (2 WORDS) ; R0-R2 USED ; R3-R5 PRESERVED ;- FILSIZ: JSR R5,$SAVRG ; SAVE R3-R5 CLR FSIZE ; SET ZERO SIZE INITIALLY CLR FSIZE+2 ; MOV UFDADR,UFDAD2 ; MAKE COPY OF DIRECTORY POSITION MOV #IDXFDB,FDBADR ; SET FDB ADDRESS FOR ERROR PROCESSOR 10$: READ$ #IDXFDB ; READ FILE HEADER BCC 15$ ; IT WORKED MOV #ERR9A,R0 ; GET ADDRESS FOR DEVICE SPEC CALL FMTDEV ; STICK IN DEVICE NAME AND NUMBER CALL FCSERR ; INSERT FCS ERROR INFORMATION SUB #ERR9,R0 ; CALCULATE MESSAGE SIZE PRINT #ERR9,R0 ; AND PRINT IT BR 25$ ; AND FORGET ANY MORE EXTENSIONS 15$: WAIT$ #IDXFDB ; WAIT FOR I/O TO COMPLETE MOV IDXBUF,R0 ; GET INDEX FILE I/O BUFFER ADDRESS MOV UFDAD2,R2 ; GET ADDRESS OF DIRECTORY ENTRY BUFFER BEQ 19$ ; IF EQ, ID/SEQ CHECK DISABLED CMP H.FNUM(R0),(R2)+ ; FILE ID MATCH? BNE 16$ ; IF NE NO, SOMETHING IS UP CMP H.FSEQ(R0),(R2)+ ; YES, SEQUENCE NUMBER MATCH? BEQ 17$ ; IF EQ YES, OK 16$: MOV #ERR13A,R0 ; SET ADDRESS FOR ERROR MESSAGE CONSTRUCTION MOV #ERR13,R4 ; AND START OF ERROR MESSAGE 161$: CALL FMTDEV ; FORMAT DEVICE NAME MOV #DIRECF,R5 ; SET DIRECTORY NAME CALL FMTUIC ; FORMAT DIRECORY NAME MOV UFDAD2,R5 ; POINT R5 TO FILESPEC ADD #6,R5 ; CALL R50.TA ; CONVERT FILENAME TO ASCII CALL R50.TA ; CALL R50.TA ; MOVB #DPT,(R0)+ ; INSERT NAME/TYPE SEPARATOR CALL R50.TA ; CONVERT FILETYPE TO ASCII MOVB #';,(R0)+ ; INSERT TYPE/VERSION SEPARATOR MOV (R5),R1 ; GET BINARY VERSION NUMBER CALL OC.TAL ; AND CONVERT TO ASCII SUB R4,R0 ; CALCULATE MESSAGE LENGTH PRINT R4,R0 ; PRINT IT BR 25$ ; AND RETURN TO CALLER 17$: TST IDXMAP ; BITMAP AVAILABLE? BEQ 172$ ; IF EQ NO CMP H.FNUM(R0),$BMAP2 ; FILE ID BEYOND BUFFERED BITMAP? BGT 172$ ; IF GT YES, SKIP IT CALL CHKBIT ; YES, PERFORM CHECK BCS 18$ ; IF CS, WE ALREADY LOOKED AT THIS HEADER BR 19$ ; HEADER CHECKS OUT 172$: TST (R2)+ ; POSITION DIRECTORY ENTRY TO FILENAME MOVB (R0),R1 ; GET IDENTIFICATION AREA OFFSET ASL R1 ; CONVERT TO BYTE OFFSET ADD R0,R1 ; GET ADDRESS OF IDENTIFICATION AREA CMP (R2)+,(R1)+ ; COMPARE FILENAMES BNE 18$ ; IF NE, THEY DON'T MATCH CMP (R2)+,(R1)+ ; BNE 18$ ; CMP (R2)+,(R1)+ ; BNE 18$ ; CMP (R2)+,(R1)+ ; COMPARE FILETYPES BNE 18$ ; CMP (R2)+,(R1)+ ; COMPARE VERSION NUMBERS BEQ 19$ ; IF EQ, FILESPEC MATCHES DIRECTORY ENTRY 18$: 19$: MOVB 1(R0),R1 ; GET OFFSET TO MAP AREA ASL R1 ; CONVERT TO BYTE OFFSET ADD R1,R0 ; R0 NOW POINTS TO MAP AREA MOV M.EFNU(R0),R4 ; GET EXTENSION FILE NUMBER FOR LATER IN CASE ; THERE ARE ANY EXTENSIONS CLR R1 ; ZERO R1 TO GET NUMBER OF WORDS OF ; RETRIEVAL POINTERS BISB M.USE(R0),R1 ; GET IT ASR R1 ; EACH POINTER IS TWO WORDS LONG, SO DIVIDE ; BY TWO TO GET NUMBER OF POINTERS BLE 25$ ; IF LE THEN ZERO BLOCKS ALLOCATED ADD #M.RTRV,R0 ; POINT TO START OF RETRIEVAL POINTERS 20$: CLR R3 ; ZERO R3 READY TO GET BLOCK COUNT BISB 1(R0),R3 ; GET BLOCK COUNT INC R3 ; COUNT WAS #BLOCKS-1 ADD R3,FSIZE+2 ; ADD TO RUNNING TOTAL ADC FSIZE ; DON'T FORGET THE CARRY ADD #<2*2>,R0 ; UPDATE R0 TO NEXT POINTER DEC R1 ; ARE THERE ANY MORE? BNE 20$ ; IF NE YES, DO IT TST R4 ; ANY EXTENSIONS? BEQ 25$ ; IF EQ NO, RETURN WITH SIZE OF FILE DEC R4 ; ADJUST POINTER ADD IDXFHD,R4 ; POINT TO VBN OF EXTENSION HEADER MOV R4,IDXFDB+F.BKVB+2 ; SET UP IN FDB CLR UFDAD2 ; DISABLE CONSISTENCY CHECKING JMP 10$ ; AND DO SOME MORE WORK 25$: RETURN ; RETURN TO CALLER .PAGE .SBTTL BITMAP CHECK ROUTINE ;+ ; *** CHKBIT ; ; THIS ROUTINE IS CALLED DURING FILE SIZING TO CHECK IF WE HAVE ; ALREADY LOOKED AT THE FILE HEADER THAT IS CURRENTLY BEING ; EXAMINED, AS A CHECK ON SKIPPING FILE SYNONYMS. WE LOOK IN THE ; BUFFERED COPY OF THE INDEX FILE BIT MAP. IF THE BIT CORRESPONDING ; TO THE FILE ID UNDER EXAMINATION IS CLEAR, WE HAVE ALREADY ; LOOKED AT THIS HEADER. IF IT IS SET, WE HAVE NOT. THE BIT IS ; ALWAYS CLEARED BY THIS ROUTINE, PROVIDING THAT IT IS WITHIN ; THE COPY OF THE BITMAP WE ARE USING. ; ; INPUTS: ; R0 ADDRESS OF BUFFERD FILE HEADER ; ; OUTPUTS: ; CC OK, BIT IN BITMAP WAS SET ; CS HEADER ALREADY CHECKED, BIT WAS CLEAR ; ;- CHKBIT: JSR R2,$SAVVR ; SAVE R0-R2 MOV H.FNUM(R0),R0 ; GET FILE ID DEC R0 ; COMPUTE WORD AND BIT OFFSET MOV #16.,R1 ; CALL $DIV ; ASL R0 ; CONVERT WORD OFFSET TO BYTE OFFSET ASL R1 ; GET INDEX INTO BIT DEFS. TABLE BIT BITMSK(R1),$BMAP0(R0) ; WAS THE BIT CLEAR? BEQ 20$ ; IF EQ YES, BAD NEWS BIC BITMSK(R1),$BMAP0(R0) ; NO, CLEAR THE BIT 10$: CLC ; THIS HEADER IS OK BR 30$ ; 20$: SEC ; THIS HEADER ALREADY SEEN 30$: RETURN ; .SBTTL SINGLE ACCOUNT LISTING ROUTINE ;+ ; *** LIST ; ; THIS ROUTINE TYPES OUT ON THE TERMINAL THE NUMBER OF FILES AND ; BLOCKS ALLOCATED TO A SINGLE USER AFTER IT HAS BEEN ; DETERMINED. ; ; INPUTS: ; R5 CONTROL BLOCK ADDRESS ; ;- LIST: MOV #<80./2>,R1 ; GET SIZE OF OUTPUT BUFFER (WORDS) MOV #OUTBUF,R0 ; AND ITS ADDRESS 20$: MOV #20040,(R0)+ ; BLANK OUT TWO BYTES DEC R1 ; DONE? BNE 20$ ; IF NE NO, LOOP MOV #OUTBUF,R0 ; RESET BUFFER ADDRESS MOV D.DEVN(R5),(R0)+ ; STICK IN THE DEVICE NAME MOV D.DEVU(R5),R1 ; GET DEVICE NUMBER CALL OC.TAL ; CONVERT TO OCTAL MOVB #COLON,(R0)+ ; INSERT A COLON MOV #OUTBUF+OUFD,R0 ; SET POINTER TO UFD FIELD CALL FMTUIC ; PUT IN UFD NAME [GGG,MMM] MOV #OUTBUF+OFIL,R0 ; SET BUFFER POSITION FOR # FILES BIT #DD.ERR,D.FLAG(R5) ; ERROR DETECTED FOR THIS ACCOUNT? BEQ 40$ ; IF EQ NO MOVSTR #ERR0 ; YES, MOVE IN MESSAGE TEXT BR 60$ ; AND PRINT IT OUT 40$: MOV D.NFIL(R5),R1 ; GET NUMBER OF FILES CALL DE.CML ; CONVERT TO DECIMAL MOV #OUTBUF+OBLK,R0 ; SET BUFFER FOR # BLOCKS MOV R5,R1 ; POINT R1 TO NUMBER OF BLOCKS ADD #D.BLOK,R1 ; CALL FM.QIO ; FORMAT AS D.P. DECIMAL .IF DF AA$BLK TST D.BALL+2(R5) ; ANY BLOCK ALLOCATION? BEQ 60$ ; IF EQ NO MOVSTR #ALLOC1 ; YES, INSERT "ALLOCATION=" MOV R5,R1 ; POINT R1 TO BLOCK ALLOCATION ADD #D.BALL,R1 ; CALL FM.QIO ; FORMAT AS D.P. DECIMAL MOVSTR #ALLOC2 ; INSERT "BLOCKS" TEXT .ENDC ; DF AA$BLK 60$: SUB #OUTBUF,R0 ; CALCULATE STRING LENGTH PRINT #OUTBUF,R0 ; TYPE IT OUT RETURN ; RETURN TO CALLER .PAGE .SBTTL SHOW TOTALS ROUTINE ;+ ; *** SHWTTL ; ; THIS ROUTINE PRINTS THE TOTAL NUMBER OF FILES AND BLOCKS ; AFTER WE HAVE SCANNED ALL RELEVANT ACCOUNTS. ; ;- SHWTTL: MOV #OUTBUF,R0 ; GET OUTPUT BUFFER ADDRESS MOVSTR #TOT1 ; "TOTAL OF" MOV #TOTBLK,R1 ; ADDRESS OF TOTAL BLOCKS FIELD CALL FM.QIO ; FORMAT IT MOVSTR #TOT2 ; "BLOCKS IN" MOV #TOTFIL,R1 ; ADDRESS OF TOTAL FILES FIELD CALL FM.QIO ; MOVSTR #TOT3 ; "FILES" SUB #OUTBUF,R0 ; PRINT #OUTBUF,R0 ; PRINT IT RETURN ; RETURN TO CALLER .PAGE .SBTTL FCS ERROR PROCESSOR ;+ ; *** FCSERR ; ; THIS ROUTINE IS CALLED TO FORMAT AN FCS OR DIRECTIVE ERROR CODE. ; ; INPUTS: ; R0 MESSAGE BUFFER ADDRESS ; FDBADR FILE FDB ADDRESS ; ; OUTPUTS: ; R0 UPDATED ; R1,R2 USED ; ;- FCSERR: MOV FDBADR,R2 ; GET FDB ADDRESS MOV #FCS,R1 ; ASSUME AN FCS ERROR TSTB F.ERR+1(R2) ; FCS ERROR? BEQ 10$ ; IF EQ YES MOV #DIR,R1 ; NO, DIRECTIVE ERROR 10$: CALL MV.STR ; INSERT "FCS" OR "DIR" TEXT MOVB F.ERR(R2),R1 ; GET FCS ERROR CODE CALL DC.SGN ; CONVERT TO SIGNED DECIMAL RETURN ; .PAGE .SBTTL DEVICE SPECIFICATION FORMATTER ;+ ; *** FMTDEV ; ; THIS ROUTINE FILLS IN THE DEVICE SPECIFICATION (DDNN:) IN THE ; OUTPUT BUFFER FOR THE CURRENT VOLUME. ; ; INPUTS: ; R0 BUFFER POINTER ; ; OUTPUTS: ; R0 UPDATED ; R1,R2 USED ; ;- FMTDEV: MOVB DEVN,(R0)+ ; PUT IN DEVICE NAME MOVB DEVN+1,(R0)+ ; MOV DEVU,R1 ; GET UNIT NUMBER CALL OC.TAL ; CONVERT TO OCTAL MOVB #COLON,(R0)+ ; FINISH WITH A COLON RETURN ; AND RETURN .PAGE .SBTTL UFD FORMATTER ROUTINE ;+ ; *** FMTUIC ; ; THIS ROUTINE STICKS THE UFD NAME IN THE FORM [GGG,MMM] INTO ; THE OUTPUT BUFFER. ; ; INPUT: ; R0 BUFFER POINTER ; R5 CONTROL BLOCK ADDRESS ; ; OUTPUT: ; R0 UPDATED ; ALL OTHER REGISTERS PRESERVED ; ;- FMTUIC: MOVB #'[,(R0)+ ; INSERT LEADING SEPARATOR MOVB (R5)+,(R0)+ ; INSERT GROUP CODE MOVB (R5)+,(R0)+ ; MOVB (R5)+,(R0)+ ; MOVB #',,(R0)+ ; INSERT A COMMA MOVB (R5)+,(R0)+ ; INSERT MEMBER CODE MOVB (R5)+,(R0)+ ; MOVB (R5)+,(R0)+ ; MOVB #'],(R0)+ ; INSERT FINAL SEPARATOR SUB #6,R5 ; ADJUST R5 BACK TO ENTRY VALUE RETURN ; AND RETURN .PAGE .SBTTL ACCEPTANCE ROUTINES ;+ ; *** ACCPT1 ; *** ACCPT2 ; ; THESE ARE THE ACCOUNT ACCEPTANCE ROUTINES CALLED BY $ASCAN ; FOR INITIALLY FINDING TH ACCOUNT (ACCPT1) OR THE CORRESPONDING ; MASTER ACCOUNT (ACCPT2). ; ;- ACCPT1: CMP UIC,A.GRP(R0) ; UIC MATCHES? BNE 10$ ; IF NE NO CMP UIC+2,A.GRP+2(R0) ; MAYBE BNE 10$ ; IF NE NO CMP UIC+4,A.GRP+4(R0) ; MAYBE BEQ 20$ ; IF EQ YES 10$: SEC ; 20$: RETURN ; ACCPT2: MOV A.ACNO(R0),R1 ; GET ACCOUNT NUMBER BIC #100000,R1 ; CLEAR MASTER FLAG CMP ACNO,R1 ; ACCOUNT NUMBER MATCH? BEQ 10$ ; IF EQ YES SEC ; 10$: RETURN ; .END $DSKEP