.title DISKSPACE - Get free space data .ident /V4.01/ .sbttl Documentation ;+ ; ; For every mounted FILES-11 disk on the system, provide the calling ; program with the logical name, number of free blocks, and maximum ; number of blocks on the disk. ; ; Calling sequence (from FORTRAN): ; ; status = DISKSPACE (maxnum, number, bufflen, namelen, ; %ref(diskname), maxblks, freeblks) ; ; Inputs: ; maxnum - maximum number of disk units to be handled ; bufflen - length of character array elements to hold log name ; ; Outputs: (arrays) ; status - return status code ; number - number of mounted disks found ; namelen - lengths of names of disks ; diskname - logical names of disks ; maxblks - total number of blocks on disk ; freeblks - number of free blocks on the disk ; ; Side-effects: ; none ; ; ; Heavily based on the DISKSPACE.MAR routine from ZEUS ; ; Eric F. Richards ; 23-Sep-85 ; Gould OSD VAX/VMS V4.2 ;- .sbttl Equated Symbols .enable suppression .disable traceback, debug .link /sys$system:sys.stb/ ; use system symbol table .library /sys$library:lib/ ; use version-sensitive library $mtldef ; Mount list offsets $ucbdef ; Unit control block offsets $vcbdef ; Volume control block offsets $devdef ; device characteristic codes $lnmstrdef ; logical name table offsets $ssdef ; Status code def'ns $dcdef ; device class def'ns $prdef ; priv'd reg def'ns .global ioc$gq_mountlst ; ptr to system mount list que .global sch$gl_curpcb ; pointer to current PCB .global sch$iolockr ; entry point to read-lock I/O database .global sch$iounlock ; entry point to unlock I/O database maxnum = 4 ; # of elements in return ary number = 8 ; number of disks actually returned bufflen = 12 ; size of char ary element namelen = 16 ; length of name returned diskname = 20 ; pointer to char ary space maxblks = 24 ; total usable space on disk freeblks = 28 ; total space free .page .sbttl Main routine .psect $$$diskspace_code, page, nowrt, exe, pic, shr .entry diskspace, 0 ; Get into kernel mode so we $cmkrnl_s routin=scan_data, - ; can do something useful arglst=(ap) ; give it the args it needs ret ; all done .align quad scan_data: .word ^m ; ; Lock I/O data base for read. IPL goes to 2 when this is done. ; movl g^sch$gl_curpcb, r4 ; Get our PCB address jsb g^sch$iolockr ; Lock down the I/O data base assume mtl$l_mtlfl eq 0 ; end-of-list chk counts on this clrl r10 ; Init disk unit count moval g^ioc$gq_mountlst-mtl$l_mtlfl, r8 ; Get adr of 1st mntd vol descr movl r8, r7 ; Get modifiable copy of address ; ; Walk mounted volume list for our information. End of list ; is indicated by the address of the pointer to the first ; mounted volume. ; 10$: movl mtl$l_mtlfl(r7), r7 ; Get address of next one cmpl r7, r8 ; is this the end of the list? bneq 15$ ; If NEQL, continue brw 30$ ; otherwise, stop here 15$: movl mtl$l_ucb(r7), r6 ; Get address of first UCB beql 10$ ; Skip if no UCB's ; ; Check to make sure volume is a R/W Files-11 system volume ; cmpb ucb$b_devclass(r6), #dc$_disk ; Is device a disk? bneq 10$ ; If NEQ no movl ucb$l_devchar(r6), r0 ; get device char's, skip if: bbc #dev$v_mnt, r0, 10$ ; Device not mounted bbs #dev$v_for, r0, 10$ ; Mounted foreign bbs #dev$v_swl, r0, 10$ ; or Write Locked ; ; Get the total block count from UCB ; moval @maxblks(ap)[r10], r2 ; Get addr of max blocks storage ifnowrt #4, (r2), 50$ ; Check for writability movl ucb$l_maxblock(r6),(r2) ; write out max block count ; ; Get the number of free blocks from the VCB ; movl ucb$l_vcb(r6), r5 ; Get address of VCB beql 10$ ; If EQL none, dismounted moval @freeblks(ap)[r10], r2 ; Get adr of free block storage ifnowrt #4, (r2), 50$ ; Check for writability movl vcb$l_free(r5), (r2) ; Get free block count ; ; Get the logical dev name from the logical name block ; moval @bufflen(ap), r1 ; get address of buffer length dsc ifnord #4, (r1), 50$ ; error if i can't read this movl (r1), r1 ; get buffer length mull3 r1, r10, r2 ; r2 has offset factor of string buffer movab @diskname(ap)[r2], r2 ; r2 now has the address of the buffer ifnowrt r1, (r2), 50$ ; bomb if i can't write to the buffer movl mtl$l_logname(r7), r6 ; get logical name block for this vol. beql 40$ ; If none, dismounted movzbl lnmb$t_name(r6), r0 ; get length of name beql 40$ ; again, if none, no such volume moval @namelen(ap)[r10], r3 ; get length of return buffer for len ifnowrt #4, (r3), 50$ ; check for correct access movl r0, (r3) ; if good, save that value movc5 r0,1+lnmb$t_name(r6), - ; move the logical name assoc. with #^a/ /, r1, (r2) ; the device into the user buffer ; ; Check and see if we have filled the array. If we have, then ; don't continue through loop. Note that this routine assumes ; that the value of MAXNUM is at least 1. ; moval @maxnum(ap), r2 ; Get address of max unit count ifnord #4, (r2), 50$ ; Check for readability aoblss (r2), r10, 40$ ; Bump number of disks found 30$: moval @number(ap), r2 ; Get address of disk count ifnowrt #4, (r2), 50$ ; Check for writability movl r10, (r2) ; Save count of disks found pushl #ss$_normal ; Set success, save on stack brb 60$ ; do final cleanup ; ; IFRD, IFNORD, IFWRT, IFNOWRT failed -- access violation, ; return error condition - go back to user mode ; 50$: pushl #ss$_accvio ; save error status on stack ; ; Unlock database, pop return status and go back to user mode ; 60$: movl g^sch$gl_curpcb, r4 ; Get our PCB address jsb g^sch$iounlock ; Unlock the I/O data base setipl #0 ; Drop IPL popl r0 ; Restore status code ret ; ...all done! 40$: brw 10$ ; common jump to top of loop end_scan_data: assume le 512 .end