; RT11DIR -- List directory on an RT-11 diskette (DZ1:) ; Copyright (C) by Nicholas Zymaris 24-DEC-1985 19:55:04 ; 12 Woody Lane ; Northport, NY 11768 ; Updated for Year 2000 compatibility 9-FEB-1998 ; More specific error messages and multisegment directories: ; 11-MAR-1998 (like RT-11 DIR2 V2.0) ; Total blocks listed as in RT-11 DIR2 V2.1 18-MAR-1998 ; Author may be reached at: nickz@idt.net ; Linking instructions -- LIBR=POSSUM:RO, STACK=0 (optional). ; Link with R50ASC.OBJ. ; No privilege required. .mcall qiow$s, qiow$, dir$, alun$s, exit$s tab=9. ; tab character ; ; PROVOL argument list for file 1 (DZ1:) ; problk: .byte 4,0 .word status,req,dev,devl status: .blkw 8. req: .blkw 1 dev: .ascii /DZ1:/ devl: .word .-dev ; ; R50ASC argument list ; r50arg: .byte 3,0 ; Three arguments for PDP-11 calling sequence .word count ; No. of chars. to convert .word 0 ; Addr. of Radix 50 string .word 0 ; Addr. of ASCII string (output) count: .word 0 ascout: .blkb 6 ; Filename .ascii /./ ; (Dot) ascext: .blkb 3 ; Extension .byte tab ; Tab for neatness asclen=.-ascout .even ; ; QIO buffers, prompts, etc. ; iostat: .blkw 2 filbuf: .blkb 512.*2 ; 1 directory segment = 2 blocks dirloc: .blkw 1 ; LBN of RT-11 directory dsize: .blkw 1 ; Number of blocks, including directory fsize: .blkw 1 ; Number of file blocks, not incl. dir [V2.0] numfil: .blkw 1 ; Number of files frsiz: .blkw 1 ; Number of free (del.+tent.) blocks [V2.1] curseg: .blkw 1 ; Current dir segment nxtsg: .blkw 1 ; Next segment read from dir hiseg: .blkw 1 ; Highest segment in use exwrd: .blkw 1 ; Extra bytes in each dir entry, if any errmsg: .ascii |An I/O error has occurred.| errlen=.-errmsg oddmsg: .ascii /Odd number of extra bytes in RT-11 directory: exiting./ oddlen=.-oddmsg p: .asciz /P/ d: .ascii / Del/ ; Deleted file flag dlen=.-d t: .ascii / T / ; Tentative file flag tlen=.-t .even outdpb: qiow$ io.wvb,5,2,,,,<,,40> dmsg: .asciz /%VA%D%A%VA//%Y/ donmsg: .asciz /%N%N%D Files, %D Blocks, %D Total Used Blocks, %D Free Blocks./ outbuf: .blkb 64. ; For $EDMSG .even edblk: .blkw 12. ; " (doubled in size for V2.0 so code <> buff!) ; ; Code ; start: mov #problk,r5 mov #2,32(r5) ; 2=dismount jsr pc,provol mov #problk,r5 mov #1,32(r5) ; 1=mount foreign jsr pc,provol alun$s #3,#"DZ,#1 ; Assign LUN 3 to DZ1: qiow$s #io.rlb,#3,#1,,#iostat,,<#filbuf,#1000,,#0,#1> ; Read LBN 1 tstb iostat bpl 3$ jmp error 3$: mov filbuf+724,dirloc ; Get location of directory qiow$s #io.rlb,#3,#1,,#iostat,,<#filbuf,#2000,,#0,dirloc> ; Read it tstb iostat bpl 4$ jmp error 4$: mov filbuf+10,dsize ; Get size of directory mov #1,curseg ; Initialize current segment [V2.0]... mov filbuf+2,nxtsg ; Next segment or zero if last mov filbuf+4,hiseg ; Highest seg in use (only on 1st seg) mov filbuf+6,exwrd ; Extra bytes per entry clr fsize ; Zero file blocks so far [V2.0] clr frsiz ; Zero free blocks so far [V2.1] mov exwrd,r3 ; Use R3 as scratch reg before use as ptr ror r3 bcc exval ; Make sure extra bytes are even amt! [V2.0] jmp oddb ; Give error and exit if not [V2.0] ; ; Read directory ; exval: mov #filbuf+12,r3 ; Start of first directory entry clr numfil ; Zero files so far chkfil: cmp #4000,(r3) ; End of directory? bne 5$ ; No, read this entry. jmp nxtseg ; Yes, go to next segment or done. 5$: mov #6,count ; Number of charcters to convert mov r3,r50arg+4 ; Store address of filename add #2,r50arg+4 ; (Offset of filename in dir. entry is 2) mov #ascout,r50arg+6; Address of output buffer mov #r50arg,r5 call r50asc ; Convert filename to ASCII mov #3,count ; Number of charcters to convert mov r3,r50arg+4 ; Store address of file extension add #6,r50arg+4 ; (Offset of extension in dir. entry is 6) mov #ascext,r50arg+6; Address of output buffer mov #r50arg,r5 call r50asc ; Convert file extension to ASCII ; ; Set up buffers for $EDMSG ; mov #outbuf,r0 ; Output buffer for $EDMSG mov #dmsg,r1 ; Address of format chars. for $EDMSG mov #edblk,r2 ; List of data: mov #asclen,(r2)+ ; Length of FILE.EXT mov #ascout,(r2)+ ; Address of the above mov 10(r3),(r2)+ ; Size of file ; ; Test status of file ; bit #100000,(r3) ; Test protection bit beq 1$ ; Not protected mov #P,(r2)+ ; Protected -- push address of "P" onto list br 10$ ; Skip next instruction 1$: mov #40,(r2)+ ; Not protected -- push a space instead 10$: bit #1000,(r3) ; Test deleted-file bit beq 11$ ; Not deleted mov #dlen,(r2)+ ; Deleted -- push length of "Deleted" msg. mov #d,(r2)+ ; Push address of above msg. add 10(r3),frsiz ; Add to cumulative free blocks [V2.1] br next ; Don't add in size 11$: bit #400,(r3) ; [V2.1]... Tentative file? beq 2$ ; No, consider it a present file mov #tlen,(r2)+ ; Tentative -- push length of tentative msg. mov #t,(r2)+ ; Push address of above msg. add 10(r3),frsiz ; Add to cumulative free blocks [V2.1] br next ; Don't add in size 2$: add 10(r3),dsize ; Add in this file's size to total blocks add 10(r3),fsize ; And total file blocks inc numfil ; Indicate one more file clr (r2)+ ; Clear length of "Deleted" msg. since it's not clr (r2)+ ; Fill space where address would go ; (needed only if more entries follow) ; ; Get date from directory entry, unpack, and give to $EDMSG ; next: mov 14(r3),r5 ; Get date, using R5 as scratch register mov r5,r4 ; Duplicate it [9-FEB-1998] bic #^C37,r5 ; Mask out all but low bits of year bic #^C140000,r4 ; Mask out all but epoch bits swab r4 ; (Note: R4 not otherwise used in this program) ror r4 ; Shift them over 9 bits add r4,r5 ; Add to low year bits add #72.,r5 ; Year is modulo 1972 A.D. cmp r5,#99. ; What century are we in? blos 21$ ; Still in 20th century sub #100.,r5 ; Happy New Year! 21$: mov r5,(r2)+ ; Save it for $EDMSG (2-digit year) mov 14(r3),r5 ; Get date again bic #^C36000,r5 ; Mask out all but month clc ash #-10.,r5 ; Right-justify the month mov r5,(r2)+ ; Save it mov 14(r3),r5 ; Get date yet again bic #^C1740,r5 ; Mask out all but day (date) of month clc ash #-5,r5 ; Right-justify it mov r5,(r2)+ ; Save date mov #edblk,r2 ; Restore ptr to beginning of list call $edmsg ; Edit output msg. (R0-R2 destroyed) call month ; Make last two letters of month lower case mov #outdpb,r2 ; DPB for output QIO mov #outbuf,q.iopl(r2) ; Load address... mov r1,q.iopl+2(r2) ; and length of output buffer msg into DPB dir$ r2 ; Print the directory entry add #16,r3 ; Point to next filename add exwrd,r3 ; Add any extra words (bytes) in entry [V2.0] jmp chkfil .sbttl Get next directory segment, if any nxtseg: dec hiseg ; One more segment down... [V2.0]... beq done ; none to go? try: add #2,dirloc ; Try next segment inc curseg ; Make it current segment try2: cmp curseg,nxtsg ; Are we at next seg acc to prev seg? blo try ; No, try again beq nread ; Yes, read it sub #4,dirloc ; No, backtrack (if segs linked out of order) sub #2,curseg br try2 nread: qiow$s #io.rlb,#3,#1,,#iostat,,<#filbuf,#2000,,#0,dirloc> ; Read 1 seg bcs error mov filbuf+2,nxtsg ; Read in number of next segment mov #filbuf+12,r3 ; Point to first dir entry in segment jmp chkfil ; And process the segment ; Use $EDMSG to print summary done: mov #outbuf,r0 ; $EDMSG's output buffer mov #donmsg,r1 ; Format string mov #edblk,r2 ; List of data for $EDMSG: mov numfil,(r2)+ ; Total no. of files mov fsize,(r2)+ ; Total no. of file blocks [V2.0] mov dsize,(r2)+ ; Total no. of blocks mov frsiz,(r2)+ ; Total free blocks on volume (del+tent) [V2.1] mov #edblk,r2 ; Restore it jsr pc,$edmsg ; Do it mov #outdpb,r2 ; Load address of output QIO DPB mov #outbuf,q.iopl(r2) mov r1,q.iopl+2(r2) ; Length of msg. dir$ r2 br dismt oddb: mov #outdpb,r5 ; [V2.0]... mov #oddmsg,q.iopl(r5) mov #oddlen,q.iopl+2(r5) dir$ r5 br dismt ; ...[V2.0] error: mov #outdpb,r5 mov #errmsg,q.iopl(r5) mov #errlen,q.iopl+2(r5) dir$ r5 dismt: mov #problk,r5 ; Dismount DZ1: mov #2,32(r5) jsr pc,provol exit: exit$s ; Task exit. ; ; MONTH: This subroutine changes a month in the $EDMSG output buffer from ; dd-MMM-yy format to dd-Mmm-yy format, as in the RT-11 directory listings. ; ; Input: OUTBUF=start of $EDMSG output buffer ; that contains no dashes ("-") before the occurence of the date. ; ; Result: All registers preserved; month changed as: 14-MAR-85 --> 14-Mar-85 ; month: mov r0,-(sp) ; Save working registers mov r1,-(sp) ; " mov r2,-(sp) ; " mov #outbuf,r0 ; Load addr. of output string 1$: cmpb #'-,(r0)+ ; A dash means I found the date (DD-MMM-YY) bne 1$ ; Loop till found inc r0 ; Skip first letter of month mov #2,r2 ; Do this to next two characters: 2$: clr r1 ; Make sure high order byte is clear movb (r0),r1 ; Load letter of month add #40,r1 ; Make letter of month lowercase movb r1,(r0)+ ; Store it sob r2,2$ ; Loop R2 times mov (sp)+,r2 ; Restore working registers mov (sp)+,r1 ; " mov (sp)+,r0 ; " rts pc ; Return .end start ; End of source code.