program directories !++ ! ! DIRECTORIES.BAS - List disk space by user ! ! Author: Don Stokes (don@gp.govt.nz) ! ! This program parses an ANALYZE/DISK/USAGE disk accounting file and ! displays the amount of disk space used within given directory trees. ! ! Three to four questions are asked: ! ANALYZE/DISK/USAGE output file [USAGE.DAT] : ! The disk accounting file to use. ! ! Output file [SYS$OUTPUT] : ! The output file to write the listing to (default is the terminal) ! ! Depth [1] : ! How many directories down to summarize by. Specifying 1 (the default) ! will give the total space used below each directory in the root. ! ! Directory to search [[000000]] : ! Only asked if depth > 1. Specifies the root directory to search. ! !-- option type = explicit external long function SOR$BEGIN_SORT, & SOR$RELEASE_REC, & SOR$SORT_MERGE, & SOR$RETURN_REC, & SOR$END_SORT external sub LIB$STOP( long by value ) %include "$SSDEF" %from %library %include "$USGDEF" %from %library %include "$DSCDEF" %from %library map (USAGEFIL) USGDEF usg.i map (USAGEFIL) USGDEF1 usg.f map (USAGEFIL) string usg.str = USG$S_USGDEF1 map (KEYBUF) word kbf.keys, & kbf.type, & kbf.direction, & kbf.offset, & kbf.size declare long constant TRUE = -1, & FALSE = 0 declare long sts, & allocated, & used, & files, & first, & depth, & allocated_t, & used_t, & files_t, & n,z,x,y declare string usage_file, & output_file, & searchdir, & lastkey, & thiskey, & header, & s ! ! Ask for and open disk accounting files ! set no prompt linput "ANALYZE/DISK/USAGE output file [USAGE.DAT] : "; usage_file open usage_file for input as file #1, map USAGEFIL, & defaultname "USAGE.DAT" ! ! Ask for and open output file (default = terminal) ! linput "Output file [SYS$OUTPUT] : "; output_file output_file = "SYS$OUTPUT" if output_file = "" open output_file for output as file #2, recordsize 132, & defaultname "USAGE.LIS" ! ! Ask for depth of directories to summarize by ! input "Depth [1] : "; depth depth = 1 if depth < 1 searchdir = "" ! ! If depth is more than 1 then ask for the directory ! to search ! if depth > 1% then linput "Directory to search [[000000]] : "; searchdir searchdir = edit$(searchdir, 1%+2%+4%+32%) searchdir = "" if searchdir = "[000000]" if searchdir <> "" then searchdir = left(searchdir, len(searchdir) - 1%) & if right(searchdir, len(searchdir)) = "]" searchdir = searchdir + "." end if end if ! ! Get header record ! get #1 header = usg.str ! ! Set up for SORT ! kbf.keys = 1% kbf.type = DSC$K_DTYPE_T kbf.direction = 0% kbf.offset = loc(usg.f::USG$T_FILESPEC) - loc(usg.str) kbf.size = len(usg.f::USG$T_FILESPEC) sts = SOR$BEGIN_SORT( kbf.keys, USG$S_USGDEF1) call LIB$STOP(sts) unless sts and SS$_NORMAL ! ! Feed remains of file into SORT, but only if they ! match the directory specified. ! while -1% when error in get #1 use exit handler if err <> 11% continue end_of_file end when if searchdir <> "" then s = usg.f::USG$T_FILESPEC s = left(s, instr(0%, s, "]") - 1%) + "." iterate if left(s, len(searchdir)) <> searchdir end if sts = SOR$RELEASE_REC( usg.str) call LIB$STOP(sts) unless sts and SS$_NORMAL next end_of_file: ! ! Do SORT ! sts = SOR$SORT_MERGE call LIB$STOP(sts) unless sts and SS$_NORMAL ! ! Print header record and column headings ! usg.str = header print #2, "Volume " + usg.i::USG$T_VOLNAME & + " Owner " + usg.i::USG$T_OWNERNAME & + " Format " + usg.i::USG$T_FORMAT print #2 print #2, "Directory________________________________________" & + "__Allocated______Used_____Files" ! ! Loop through sorted records... ! first = TRUE allocated_t, used_t, files_t = 0% until SOR$RETURN_REC( usg.str ) = SS$_ENDOFFILE call LIB$STOP(sts) unless sts and SS$_NORMAL ! ! Get break key (based on directory) ! x = instr(0%, usg.f::USG$T_FILESPEC, "]") y = 0% y = instr(y + 1%, usg.f::USG$T_FILESPEC, ".") for n = 1 to depth y = x if y > x or y = 0% thiskey = left(usg.f::USG$T_FILESPEC, y - 1%) ! ! If break key doesn't match last times, or this is the ! first time through: ! Output stuff for the old key (if there is one) ! Clear totals for the new key ! if thiskey <> lastkey or first then gosub output_record unless first allocated, used, files = 0% lastkey = thiskey first = FALSE end if ! ! Count totals for this key, and the whole lot ! allocated = allocated + usg.f::USG$L_ALLOCATED - 1% used = used + usg.f::USG$L_USED files = files + 1% allocated_t = allocated_t + usg.f::USG$L_ALLOCATED - 1% used_t = used_t + usg.f::USG$L_USED files_t = files_t + 1% next ! ! Finish SORT ! sts = SOR$END_SORT call LIB$STOP(sts) unless sts and SS$_NORMAL ! ! Output the last key's data and print totals ! gosub output_record unless first print #2, "Total"; tab(50); format$( allocated_t, "##########") & + format$( used_t, "##########") & + format$( files_t, "##########") ! ! Close files and exit ! close #1 close #2 exit program ! ! Subroutine to print a key's totals ! output_record: z = 0 z = z + 1 if mid(lastkey, n, 1%) = "." for n = 1% to len(lastkey) s = lastkey + "...]" s = lastkey + "]" if z < depth - 1% s = "[000000]" if lastkey = "[000000" print #2, s; tab(50); format$( allocated, "##########") & + format$( used, "##########") & + format$( files, "##########") return end