.TITLE DSKUPD -- DISK BLOCK ACCOUNTING SUBROUTINES .IDENT/V02XA/ ;+ ; THIS SUBROUTINE PACKAGE IS DESIGNED TO BE CALLED FROM A FORTRAN MAINLINE. ; WHILE UPDATE.MAC IS WELL SUITED FOR KEEPING TRACK OF USERS WHO HAVE ONLY ; ONE [UIC] PER ACCOUNT ENTRY IN RSX11.SYS, THE PROBLEM STILL EXISTS OF HOW ; TO KEEP TRACK OF USERS WHO ARE PRIVILEGED AND HAVE UIC'S ALL OVER A WIDE ; VARIETY OF DISKS. NOW SINCE THE GOALS FOR MANAGING DISK USAGE WILL VARY ; WIDELY FROM ONE SYSTEM TO ANOTHER, THIS SUBROUTINE IS PROVIDED TO RETURN ; THE NUMBER OF FILES USED AND THE BLOCKS ALLOCATED TO A MAINLINE PROGRAM. ; IT IS THE FUNCTION OF THE CALLING PROGRAM TO, UPDATE FILES, SEND OFF DATA ; TO THE SYSTEM ACCOUNT LOGGING TASK(LOG...), WARN USERS, PRINT OUT LISTS, ; ETC. ; ; THESE SUBROUTINES REQUIRE THE USE OF LUNS 1 AND 2. ; 11/21/79 ; ; ; BY : JAMES G. DOWNWARD ; KMS FUSION, INC. ; ANN ARBOR, MICH 48104 ; 313-769-8500 ; ; ; .MCALL OPEN$W,OPNS$R,READ$,CLOSE$,WAIT$,HMBOF$ .MCALL FSRSZ$,FDBDF$,FDAT$A,FDRC$A,FDBK$A .MCALL FDOP$A,FDBF$A,NMBLK$,FHDOF$,DEF$L .MCALL PUT$,ALUN$,GTSK$ .MCALL QIO$,WTSE$S,MRKT$,DIR$ ; ; LUN1=1 EFN1=1 LUN2=2 EFN2=2 ;LUN3=3 ;EFN3=3 ; ; ERROR MESSAGES ; DEV: .ASCII /LB00/ ; DEVICE UIC: .ASCII /[GGG,MMM]/ ; UIC .EVEN DEVCNT:.WORD 0 ; NUMBER OF BYTES IN DEVICE STRING UICCNT:.WORD 0 ; NUMBER OF BYTES IN UIC STRING ; ; ;+ ; THIS SECTION CONTAINS THE FILE DESCRIPTOR BLOCKS AND ; ASSOCIATED INFORMATION. ;- ; FSRSZ$ 1 ;ONE RECORD CONTROLLED FILE FHDOF$ DEF$L ;DEFINE INDEX FILE OFFSETS HMBOF$ DEF$L ;DEFINE HOME BLOCK OFFSETS ; ; ; FDB FOR DIRECTORY FILE (*.DIR) ; FDB1: FDBDF$ FDAT$A R.FIX,,1000 FDRC$A FD.RWM!FD.RAN!FD.PLC FDBK$A WORKBU,1000,,EFN1,BKST1 FDOP$A LUN1,DSPT1,FNB1 FDBF$A EFN1 ; FNB1: NMBLK$ ,DIR,0,SY,0 ; ; FDB FOR INDEX FILE (INDEX.SYS) ; FDB2: FDBDF$ FDAT$A R.FIX,,1000 FDRC$A FD.RWM!FD.RAN!FD.PLC FDBK$A WORKBU,1000,,EFN2,BKST2 FDOP$A LUN2,DSPT2,FNB2 FDBF$A EFN2 ; FNB2: NMBLK$ INDEXF,SYS,0,SY,0 ; DATA SET BLOCK FOR DIRECTORY FILE ; DSPT1: .WORD DNSZE .WORD DNSTR .WORD DSTRSZ .WORD DSTR1 .WORD SSZE1 .WORD STR1 ;+ ; DATA SET BLOCK FOR INDEX FILE ;- DSPT2: .WORD DNSZE .WORD DNSTR .WORD DSTRSZ .WORD DSTR1 .WORD SSZE2 .WORD STR2 ; BKST1: .BLKW 2 BKST2: .BLKW 2 ; .NLIST BIN DSTR1: .ASCII %[0,0]% DSTRSZ=.-DSTR1 .EVEN ; STR1: .ASCII %000000% SSZE1=.-STR1 .EVEN ; STR2: .ASCII %INDEXF% SSZE2=.-STR2 .EVEN ; STR3: .BLKB 9. SSZE3=.-STR3 .EVEN ; ; DNSTR: .ASCII %SY0:% DNSZE=.-DNSTR .EVEN .LIST BIN ;+ ; THIS SECTION CONTAINS THE BLOCK BUFFERS AND WORK BUFFERS ;- ; WORKBU: .BLKW 256. WRKBU: .BLKW 256. ; ; ; ; .EVEN ; NENTRY: .BLKW 1 TMP: .BLKW 2 NBLOCK:.BLKW 1 SAVR5: .BLKW 1 BUF: .BLKW 18. INXFHD:.WORD 0 ; POINTER TO START OF FILE HEADERS ; RJDK ;+ ; FORTRAN CALLABLE SUBROUTINE TO PROVIDE A TALLY OF THE FILES AND BLOCKS USED ; ON A GIVEN DEV:[UIC] ; ; CALL UPDATE(LDIRSTR,IFILES,IBLOCKS,IER) ; WHERE ; LDIRSTR = DIRECTORY STRING OF FORM DEV:[UIC. LDIRSTR IS A LOGICAL*1 ASCII ARRAY TERMINATED WITH ; A NULL(MARK END OF STRING), EITHER AN ARRAY OR A LITTERAL ; IFILES = NUMBER OF FILES ON DIRECTORY ; IBLOCKS = NUMBER OF BLOCKS USED ; IER = ERROR CODE ; 1 SUCCESS ; -1 SYNTAX ERROR IN DIRECTORY STRING( DEV STRING TOO LONG) ; -2 SYNTAX ERROR("[" NOT FOUND) ; -3 SYNTAX ERROR("]" NOT FOUND) ; -4 SYNTAX ERROR(DIRECTORY STRING TOO LONG) ; -5 DV:[0,0]GGGMMM.DIR CAN NOT BE OPENED ; -6 DV:[0,0]INDEXF.SYS CAN NOT BE OPENED ; -7 READ ERROR - INDEXF.SYS (ERROR IN FINDING MFD) ; -8 READ ERROR - GGGMMM.DIR ; -9 READ ERROR - ERROR READING FILE HEADER IN INDEXF.SYS ; UPDATE:: CMP (R5),#4 ; SHOULD BE 4 PARAMETERS PASSED BNE 100$ ; IF NOT, EXIT POST HASTE MOV #1,@10(R5) ; ASSUME SUCCESS MOV 2(R5),R0 ; GET ADDRESS OF STRING MOV #DEV,R1 ; ASCII DEVICE STRING WILL GO HERE CLR DEVCNT ; INITIALLY 0 BYTES IN DEVICE STRING CLR UICCNT ; AND 0 BYTES IN UIC STRING 10$: MOVB (R0)+,(R1)+ ; MOVE IN FIRST BYTE INC DEVCNT ; COUNT IT CMP DEVCNT,#4 ; IF MORE THAN 4 CHARACTERS BEFOR : FOUND, ERROR BGT 200$ ; EXIT WITH ERROR CMPB (R0),#': ; IS IT A ':' BNE 10$ ; NOPE, GET ANOTHER CHARACTER INC R0 ; YES, BUMP PAST ':' CMPB (R0),#'[ ; IS IT A "[" BNE 250$ ; IF NOT EQ, ERROR MOV #UIC,R1 ; ADDRESS OF WHERE TO STUFF UIC STRING 20$: MOVB (R0)+,(R1)+ ; MOVE IN A BYTE INC UICCNT ; AND COUNT IT TSTB (R0) ; ARE WE AT END OF STRING BEQ 300$ ; END OF STRING FOUND BEFORE LAST "]" CMP UICCNT,#8. ; IS STRING TOO LONG BGT 350$ ; IF GT, ERROR CMPB (R0),#'] ; END OF STRING BNE 20$ ; IF NE, LOOP SOME MORE MOVB (R0),(R1) ; MOVE IN "]" INC UICCNT ; AND COUNT IT MOV R5,SAVR5 ; SAVE R5 FOR LATER CALL SETUP CALL BLOCK ; FIND THE NUMBER OF BLOCKS AND FILES ON THE DIRECTORY BCS 400$ ; IF CS, ERROR CALCULATING BLOCKS MOV SAVR5,R5 ; GET IT BACK MOV NENTRY,@4(R5) ; RETURN NUMBER OF FILES MOV NBLOCK,@6(R5) ; RETURN NUMBER OF BLOCKS 100$: RETURN 200$: MOV #-1,@10(R5) ; SYNTAX ERROR, TOO MANY BYTES IN DEVICE STRING RETURN ; 250$: MOV #-2,@10(R5) ; SYNTAX ERROR, "[" NOT FOUND RETURN ; 300$: MOV #-3,@10(R5) ; SYNTAX ERROR, "]" NOT FOUND RETURN ; 350$: MOV #-4,@10(R5) ; SYNTAX ERROR, UIC STRING TOO LONG RETURN ; 400$: MOV SAVR5,R5 ; RESTORE R5 MOV R0,@10(R5) ; ERROR IN CALCULATING BLOCKS RETURN SETUP: MOV #DEV, ; SET UP CORRECT DEVICE FOR DIRECTORY FILE ; GGGMMM.DIR;1 MOV DEVCNT,DSPT1 ; AND SET THE CORRECT BYTE COUNT MOV #DEV, ; SET UP CORRECT DEVICE FOR INDEX FILE(INDEXF.SYS) MOV DEVCNT,DSPT2 ; AND SET THE CORRECT BYTE COUNT MOV #UIC,R0 ; SET ADDRESS OF UIC ENTRY ADD UICCNT,R0 ; OFFSET TO POINT TO LAST NUMERIC ENTRY DEC R0 ; BY POINTING TO "]" AND BACKING UP ONE CHARACTER MOV #STR1,R1 ; GET ADDRESS OF DIRECTORY STRING ADD #6,R1 ; POINT TO LAST POSSIBLE NUMERIC ENTRY 17$: CMPB #',,-(R0) ; IS IT A ","? BEQ 20$ ; YES, GO GET GROUP CODE MOVB (R0),-(R1) ; NO, MOVE IN MEMBER CODE ONE BYTE AT A TIME BR 17$ ; AND LOOP TILL COMMA FOUND 20$: MOV #STR1,R1 ; RESET POINTER TO GROUP CODE IN DIRECTORY STRING ADD #3,R1 ; AND POINT TO THE LAST NUMBER (GROUP) 25$: CMPB #'[,-(R0) ; IS IT A "["? BEQ 30$ ; YES, ALL DONE MOVB (R0),-(R1) ; NO, SO MOVE IN GROUP CODE-(IN REVERSE) BR 25$ ; AND LOOP TILL DONE 30$: RETURN ; ALL DONE ;+ ; ENTER HERE AFTER COMMAND STRING HAS BEEN INTERPRETED ; READ DIRECTORY FILE BLOCK-BY-BLOCK AND LOAD EACH EIGHT WORD ; ENTRY INTO THE BUFFER, RETAINING THE LAST 5 WORDS OF ; EACH ENTRY. ;- BLOCK: OPNS$R #FDB1,,,#FD.RWM ;OPEN DIRECTORY FILE(NNNMMM.DIR;1) BCC 17$ ;ERROR? MOV #-5,R0 ; SHOW WHERE ERROR OCCURED RETURN ; CARY SET, RETURN WITH ERROR 17$: MOV #1, ;NO--SET TO 1ST VBN OPNS$R #FDB2,,,#FD.RWM ;OPEN INDEX FILE BCC 18$ ;ERROR? MOV #-6,R0 ; RETURN ; CARY SET, RETURN WITH ERROR 18$: MOV #3, ;SET UP TO READ HOME BLOCK(SET EOF BLOCK #=30) MOV #2, ;SET VBN=2 READ$ #FDB2,#WORKBU ;READ HOME BLOCK(INDEXF.SYS) BCC 19$ ;ERROR? MOV #-7,R0 ; RETURN ; CARRY SET, RETURN ERROR 19$: WAIT$ #FDB2 ;NO--CONTINUE MOV ,R0 ;GET INDEX BIT MAP SIZE ADD #3,R0 ;AND FIND VBN FOR INDEX FILE MOV R0,INXFHD ; SAVE START OF FILES FOR LATER MOV R0, INC R0 MOV R0, ;SET UP VBN POINTER FOR GETBLOCK CALL GETBLK ;FIND # BLOCKS IN INDEX FILE INC R2 MOV R2, CLR NBLOCK ;ZERO BLOCK COUNTER CLR NENTRY ;ZERO NUMBER OF ENTRIES 20$: READ$ #FDB1,#WORKBU ;READ A BLOCK BCC 21$ ;ERROR? CMPB #IE.EOF,FDB1+F.ERR ;MAYBE--END OF FILE? BEQ 22$ ;YES SEC ; SET CARRY MOV #-8.,R0 ; RETURN ; SHOW ERROR JMP 29$ 21$: WAIT$ #FDB1 CALL LOAD ;LOAD THE ENTRIES IN TO THE BUFFER BR 20$ ;READ NEXT BLOCK 22$: MOV NENTRY,R1 29$: MOV NBLOCK,R1 CLOSE$ #FDB1 CLOSE$ #FDB2 RETURN ; RETURN TO MAIN LINE CODE ; ; ; ;+ ; THIS SUBROUTINE WILL DETERMINE THE NUMBER OF BLOCKS ALLOCATED ; BY A SPECIFIC FILE. UPON ENTRY THE VBN MUST BE SET (FDB2+F.BKVB+2) ; FOR THE FILE HEADER BLOCK WITHIN THE INDEX FILE. ; VBN = 1ST WORD OF FILE ID + N ;- GETBLK: MOV R0,-(SP) CLR R2 ;ZERO BLOCK COUNTER 100$: ; REF LABEL FOR MULTIHEADER SUPPORT READ$ #FDB2,#WRKBU ;READ FILE HEADER BCC 1$ ;ERROR? MOV #-9.,R0 ; RETURN ; CARRY SET, TO SHOW ERROR BR 20$ ;AND EXIT 1$: WAIT$ #FDB2 ;NO--CONTINUE MOV #WRKBU,R0 MOVB 1(R0),R1 ;GET MAP AREA OFFSET ASL R1 ;AND CONVERT TO A BYTE OFFSET ADD R1,R0 ;ADJUST POINTER TO MAP AREA CLR R1 ; BISB M.USE(R0),R1 ; GET #WORDS OF RETRIEVAL PTRS ASR R1 ;EACH PTR CONSISTS OF 2 WORDS BLE 20$ ;0 BLOCKS ALLOCATED--EXIT!! ADD #M.RTRV,R0 ;MOVE TO START OF RETRIEVAL PTRS 2$: MOVB 1(R0),R3 ;GET BLOCK COUNT-1 BIC #177400,R3 ;CLEAR UPPER BYTE (SBE) INC R3 ADD R3,R2 ;ADD # BLKS TO TOTAL CMP (R0)+,(R0)+ ;MOVE TO NEXT RETRIEVAL PTR SOB R1,2$ ;MORE POINTERS? MOV #WRKBU,R0 ; TEDIOUSLY GET WORD WHICH MAY CONTAIN ; RJDK MOVB 1(R0),R1 ; FID FOR CONTINUATION HEADER ; RJDK ASL R1 ; ; RJDK ADD R1,R0 ; ; RJDK MOV M.EFNU(R0),R1 ; AT LAST ; RJDK BEQ 20$ ; ZERO AT END SO DONE ; RJDK DEC R1 ; COMPENSATE FOR POINTER BEING TO 1:1 ; RJDK ADD INXFHD,R1 ; AND MAKE CORRECT BLOCK # ; RJDK MOV R1, ; ; RJDK BR 100$ ; AND DO NEXT HEADER ; RJDK 20$: MOV (SP)+,R0 RETURN ;+ ; THIS SUBROUTINE WILL SEARCH THROUGH EACH 8 WORD ENTRY CONTAINED ; IN THE INDEX FILE, DETERMINE IF THE FILE IS STILL EXISTANT (THE ; FIRST WORD IS NON-ZERO). ; THE LAST 5 WORDS OF EACH ENTRY (FILE NAME, EXTENTION, AND VERSION ; NUMBER) ARE RETAINED IN THE BUFFER (BLKBUF). ; ALSO, AN ADDITIONAL WORD CONTAINING THE VBN OF THE FILE HEADER IS ; STORED AS THE 6TH WORD. ;- LOAD: MOV #32.,R4 ;# ENTRIES/BLOCK IN DIRECTORY FILE MOV #WORKBU,R0 ;SET PTR TO 1ST ENTRY 1$: TST (R0) ;ENTRY STILL ACTIVE? BEQ 11$ ;NO--MOVE TO NEXT ENTRY MOV (R0),R2 ;COMPUTE VBN ; ADD #3,R2 ; BUF FIRST OFFSET IT BY 3(WHY I DON'T K; RJDK ADD INXFHD,R2 ; ; RJDK DEC R2 ; POINT TO FILE HEADER OFFSET FROM FID1:; RJDK MOV R2, ;LOAD THE VBN INTO THE FDB ;**-1 CALL GETBLK ;GET THE NUMBER OF BLOCKS ADD R2,NBLOCK ;ADD TO RUNNING TOTAL INC NENTRY ;INCREMENT # ENTRIES 11$: ADD #20,R0 ;MOVE TO NEXT INDEX FILE ENTRY DEC R4 ;MORE ENTRIES? BLE 12$ ;NO JMP 1$ ;YES 12$: RETURN ;+ ; *** - QIO - ISSUE QIO ; ; INPUT: ; R4 - DPB ADDRESS ;- QIO: DIR$ R4 ; ISSUE QIO BCS 10$ ; ERROR MOVB Q.IOEF(R4),R5 ; GET EVENT FLAG TO WAIT ON WTSE$S R5 ; AND WAIT 10$: RETURN ; .END