home *** CD-ROM | disk | FTP | other *** search
- ;**************************************************************************
- ;
- ; NAME : Du v2.5
- ;
- ; TEMPLATE : Du <dir/filename>,... [FILES] [DIRS] [NOHEAD] [NOTOTAL]
- ;
- ; DESCRIPTION : print disk usage for a given set of directories/files.
- ; If no directory specified then use current dir.
- ;
- ; AUTHOR : Stuart Mitchell
- ; (email: stuart@minster.york.ac.uk)
- ;
- ; DATE : 6-Jul-92
- ;
- ; NOTES : v1.0 - Initial coding
- ; v2.0 - Accepts wildcards and files/dirs switches
- ; v2.1 - Code tidied up
- ; v2.2 - New tabular output
- ; v2.3 - Can now be made resident (uses the LINK
- ; instruction to grab workspace).
- ; Prints totals if more than 1 arg or
- ; an argument contains a wildcard.
- ; v2.4 - If Lock on current dir is NULL then
- ; uses "sys:"
- ; v2.5 - Now uses DOS 2.0 functions instead of ARP
- ; Added NOHEAD and NOTOTAL flags
- ; Added WB2.0 version string
- ;
- ;**************************************************************************
-
-
- section du,code
-
- include "dos/dos.i"
- include "dos/dosextens.i"
- include "dos/dosasl.i"
- include "exec/memory.i"
- include "exec/execbase.i"
-
- _LVOOpenLibrary equ -$228
- _LVOCloseLibrary equ -$19e
- _LVOFreeMem equ -$d2
- _LVOAllocMem equ -$c6
-
- _LVOAllocDosObject equ -$e4
- _LVOReadArgs equ -$31e
- _LVOFreeArgs equ -$35a
- _LVOPutStr equ -$3b4
- _LVOMatchFirst equ -$336
- _LVOMatchNext equ -$33c
- _LVOMatchEnd equ -$342
- _LVOVPrintf equ -$3ba
- _LVOPrintFault equ -$1da
- _LVOGetCurrentDirName equ -$234
-
- CALL macro (name)
- jsr _LVO\1(a6)
- endm
-
- r_current_arg equr a2
- r_anchor equr a3
- r_dosbase equr a4
- r_var_base equr a5
-
- r_files equr d2
- r_dirs equr d3 ; note multiple use
- r_options equr d3 ; this IS OK
- r_bytes equr d4
- r_blocks equr d5
- r_total_flag equr d6
- r_rdaargs equr d7
-
- ;; bitdefs for dir scan - should really be picked up from dosasl.i ...
-
- DIDDIR equ 3
- DODIR equ 2
- ITSWILD equ 1
-
- ;; define offsets into space reserved on the stack by link instruction
-
- LINK_SIZE equ 56 ; size of reserved area
-
- ;; running totals
-
- TFILES equ -56 ; must be in this order!
- TDIRS equ -52
- TBYTES equ -48
- TBLOCKS equ -44
-
- ;; arguments for VPrintf()
-
- P_ARG0 equ -40 ; must be in this order
- P_ARG1 equ -36 ;
- P_ARG2 equ -32 ;
- P_ARG3 equ -28 ;
- P_ARG4 equ -24 ;
-
- ;; vars returned by call to ReadArgs()
-
- ARGS equ -20 ; char *args[]
- DIR_FLAG equ -16
- FILE_FLAG equ -12
- HEADER_FLAG equ -8
- TOTAL_FLAG equ -4
-
- ;; *********************************************************************
-
- start: link r_var_base,#-LINK_SIZE ; reserve 56 bytes on stack
-
- ;; open DOS library
-
- open_lib: move.l (4).w,a6
- lea doslib(pc),a1
- moveq.l #37,d0 ; 2.04 +
- CALL OpenLibrary
- tst.l d0
- beq exit
- move.l d0,a6
- move.l d0,r_dosbase
-
- ;; clear argument array and global vars
-
- moveq.l #(LINK_SIZE-4)/4,d0 ; loop count
- moveq.l #0,d3
- lea -LINK_SIZE(r_var_base),a0
- clr_loop: move.l d3,(a0)+
- dbra d0,clr_loop
-
- ;; parse command line
- ;; (d3 already set to NULL)
-
- parse_args: lea ARGS(r_var_base),a0 ; pointer to arg array
- move.l a0,d2
- lea tplate(pc),a0
- move.l a0,d1
- CALL ReadArgs
-
- move.l d0,r_rdaargs
- beq closedos
-
- ;; output header line
-
- tst.l HEADER_FLAG(r_var_base)
- bne.s 1$ ; skip if flag specified
-
- lea header_bar(pc),a0
- move.l a0,d1
- CALL PutStr
-
- ;; total flag is incremented for each arg, thus if more than one arg
- ;; is present then total flag will end up non-zero...
-
- 1$ moveq.l #-1,r_total_flag ; set if wildcard
-
- moveq.l #0,r_options
- set_file_flag: move.l FILE_FLAG(r_var_base),d0
- beq.s set_dir_flag ; if zero then option not specified
- moveq.l #-1,r_options
- set_dir_flag: move.l DIR_FLAG(r_var_base),d0
- beq.s test_num_args
- moveq.l #1,r_options
-
- ;; test if any directories/files specified on the command line - if none
- ;; then do current directory
-
- test_num_args: tst.l ARGS(r_var_base)
- beq do_curr_dir
-
- ;; allocate memory for AnchorPath structure
-
- bsr alloc_anchor
-
- ;; main loop -
- ;; for each arg:
- ;; while (matching entry found)
- ;; if (file)
- ;; print info;
- ;; else
- ;; scan dir & print info;
-
- move.l ARGS(r_var_base),r_current_arg
- main_loop: move.l (r_current_arg)+,d1
- beq print_total ; no args left (last arg NULL)
-
- addq.l #1,r_total_flag ; increment totals count
-
- findfirst: move.l r_anchor,d2
- CALL MatchFirst
- tst.l d0
- bne does_not_exist
-
- ;; if arg is wildcard then force totals at the end
- ;; ( ITSWILD bit is set by the call to MatchFirst )
-
- move.b ap_Flags(r_anchor),d0
- btst #ITSWILD,d0 ; bit's status --> Z flag
- beq.s inner_loop ; if bit clear then continue
-
- moveq.l #1,r_total_flag ; make sure totals are printed
-
- inner_loop: move.l fib_DirEntryType+ap_Info(r_anchor),d0
- blt.s do_file
-
- do_dir: cmp.l #ST_LINKDIR,d0 ; if this a (hard) link
- beq.s skip ; if so ignore it
- cmp.l #ST_SOFTLINK,d0 ; soft link (file OR dir)
- beq.s skip
-
- tst.l r_options ; if r_options is negative
- blt.s skip ; then files only required
-
- lea ap_Buf(r_anchor),a0
- bsr du
- tst.l d0
- bne.s break_pressed ; error - break pressed
-
- bra.s skip
-
- do_file: cmp.l #ST_LINKFILE,d0 ; file link?
- beq.s skip
-
- tst.l r_options ; if r_options is positive
- bgt.s skip ; then only dirs to be shown
-
- move.l fib_Size+ap_Info(r_anchor),d0
- move.l d0,P_ARG0(r_var_base)
- add.l d0,TBYTES(r_var_base)
-
- move.l fib_NumBlocks+ap_Info(r_anchor),d0
- addq.l #1,d0 ; correct block count to
- move.l d0,P_ARG1(r_var_base) ; include file header block
- add.l d0,TBLOCKS(r_var_base)
-
- lea fib_FileName+ap_Info(r_anchor),a0
- move.l a0,P_ARG2(r_var_base)
-
- lea P_ARG0(r_var_base),a0
- move.l a0,d2
- lea file_fmt(pc),a0
- move.l a0,d1
- CALL VPrintf
-
- skip: move.l r_anchor,d1
- CALL MatchNext
- cmpi.l #ERROR_BREAK,d0
- beq.s break_pressed
- tst.l d0
- beq.s inner_loop
-
- bra main_loop
-
- print_total: tst.l r_total_flag ; only print totals if
- ble.s free_rda ; flag is >0
- tst.l TOTAL_FLAG(r_var_base) ; skip totals if NOTOTAL flag
- bne.s free_rda ; specified on command line
-
- lea total_fmt(pc),a0
- move.l a0,d1
- lea TFILES(r_var_base),a0
- move.l a0,d2
- CALL VPrintf
- bra.s free_rda
-
- ;; ********************************************************************
- ;; Output "**BREAK" - Called if CNTL-C detected
- ;; Note: drop through to end of program
-
- break_pressed: move.l #break_str,d1
- CALL PutStr
-
- ;; ********************************************************************
-
- free_rda: move.l r_rdaargs,d1
- CALL FreeArgs
-
- bsr free_asl
-
- closedos: move.l r_dosbase,a1
- move.l (4).w,a6
- CALL CloseLibrary
-
- exit: unlk r_var_base
- moveq.l #0,d0
- rts
-
- ;; **********************************************************************
- ;; Print error message if object does not exist
- ;;
- ;; IN: d0 - error code from MatchFirst() call (i.e. IoErr() code)
- ;; a6 - DosBase
- ;; OUT: <none>
-
- does_not_exist: move.l d0,d1
- move.l -4(r_current_arg),d2 ; r_current_arg has been advanced already
- CALL PrintFault
- bra main_loop ; try next arg...
-
- ;; **********************************************************************
- ;; Scan directory and print info on directory
- ;;
- ;; IN: a0 - full pathname of required directory
- ;; r_var_base - pointer to top of allocated workspace
- ;; a6 - DosBase
- ;; OUT: d0 - 0 on success, 1 if interrupted by ^C
-
- du: movem.l d2-d7/a2-a4,-(sp)
- move.l a0,a2
- move.l a0,P_ARG4(r_var_base) ; save name to print later
-
- bsr alloc_anchor
- move.l r_anchor,d2
- beq exit_du ; no memory
-
- ;; main loop
-
- ;; find first file/directory
-
- move.l a2,d1 ; move pathname
- CALL MatchFirst
- tst.l d0
- bne.s finished ; should never happen...
-
- init_regs: moveq.l #0,r_files ; zero results
- moveq.l #0,r_dirs
- moveq.l #0,r_bytes
- moveq.l #0,r_blocks
-
- ;; loop around in directory until all subdirectories/files exhausted
-
- du_loop: move.b ap_Flags(r_anchor),d1
-
- ;; if DirEntryType <0 then we have a file
-
- move.l fib_DirEntryType+ap_Info(r_anchor),d0
- blt.s du_do_file
-
- du_do_dir: btst #DIDDIR,d1 ; DIDDIR bit set
- beq.s du_enter_dir ; no ... enter dir
-
- ;; have just popped out of a directory, mark as finished & increment count
-
- du_exit_dir: bclr #DIDDIR,d1
-
- addq.l #1,r_dirs ; bump dir count
- bra.s du_find_next
-
- ;; found a new directory, so enter it at next FindNext
-
- du_enter_dir: bset #DODIR,d1
- bra.s du_find_next
-
- ;; this ones a file, so increment count & bytes
-
- du_do_file: addq.l #1,r_files
- add.l fib_Size+ap_Info(r_anchor),r_bytes
- add.l fib_NumBlocks+ap_Info(r_anchor),r_blocks
- addq.l #1,r_blocks ; take account of file header block
-
- ;; find next file/dir
-
- du_find_next: move.b d1,ap_Flags(r_anchor) ; set directory handling
-
- move.l r_anchor,d1
- CALL MatchNext
- cmpi.l #ERROR_BREAK,d0 ; ^C pressed ?
- beq.s du_break
- tst.l d0 ; if zero then got something
- beq.s du_loop
-
- ;; print out results (dirname already put in place at start of subroutine)
-
- print_dir: movem.l r_files/r_dirs/r_bytes/r_blocks,P_ARG0(r_var_base) ; flush results
-
- add.l r_bytes,TBYTES(r_var_base)
- add.l r_files,TFILES(r_var_base)
- add.l r_blocks,TBLOCKS(r_var_base)
- add.l r_dirs,TDIRS(r_var_base)
-
- lea dir_fmt(pc),a0 ; format string
- move.l a0,d1
- lea P_ARG0(r_var_base),a0 ; address of ptrs to args
- move.l a0,d2
- CALL VPrintf ; print results
-
- finished: bsr.s free_asl
- moveq.l #0,d0 ; set error code
- exit_du: movem.l (sp)+,d2-d7/a2-a4
- rts
-
- du_break: bsr.s free_asl
- moveq.l #1,d0 ; error return code
- bra.s exit_du
-
- ;; **********************************************************************
- ;; Allocate an ASL AnchorPath structure & extra string storage space
- ;;
- ;; IN: <none>
- ;; OUT: d0 - pointer to anchorpath structure, or NULL on failiure
-
- alloc_anchor: move.l a6,-(sp)
-
- move.l #ap_SIZEOF+256,d0 ; allow room for full pathname
- moveq.l #MEMF_PUBLIC,d1
- move.l (4).w,a6
- CALL AllocMem ;
- move.l d0,r_anchor ; save it
-
- ;; set up required fields in structure
-
- move.b #%00100001,ap_Flags(r_anchor) ; DOWILD|DODOT
- move.w #256,ap_Strlen(r_anchor) ; for full path
-
- ;; set bits we can break on (^C only)
-
- move.l #$00001000,ap_BreakBits(r_anchor)
-
- move.l (sp)+,a6
- rts
-
- ;; **********************************************************************
- ;; Free ASL Anchor Chain
- ;;
- ;; IN: a6 - DosBase
- ;; OUT: <none>
-
- free_asl: move.l r_anchor,d1 ; free any memory allocated
- beq.s null_anchor ; by dos routines
-
- CALL MatchEnd
-
- move.l a6,-(sp) ; save DosBase
- move.l r_anchor,a1
- move.l #ap_SIZEOF+256,d0
- move.l (4).w,a6
- CALL FreeMem ; free AnchorPath struct
-
- sub.l r_anchor,r_anchor ; clear register
-
- move.l (sp)+,a6
- null_anchor: rts
-
- ;; **********************************************************************
- ;; find name of current directory and use that
- ;;
- ;; IN: a6 - DosBase
- ;; OUT: <none>
-
- do_curr_dir: move.l r_rdaargs,d1 ; finished with args
- CALL FreeArgs
-
- move.l (4).w,a6
- moveq.l #MEMF_PUBLIC,d1
- move.l #1024,d0 ; get memory to store
- CALL AllocMem ; full path of current dir
- tst.l d0
- beq closedos
- move.l d0,a2 ; store address
-
- move.l r_dosbase,a6
- move.l d0,d1
- move.l #1024,d2
- CALL GetCurrentDirName
- beq.s use_sys ; failed...
-
- tst.b (a2) ; empty buffer?
- beq.s use_sys ; use "sys:"
-
- move.l a2,a0 ; get ptr path name
-
- bra.s do_cd ; and do it
-
- use_sys: lea sys(pc),a0
-
- do_cd: bsr du
-
- free_buffer: move.l a2,a1 ; move buffer address
- move.l d2,d0 ; buffer length
- move.l (4).w,a6 ; get ExecBase
-
- CALL FreeMem
-
- bra closedos ; exit program
-
- ;; ************************************************************************
-
- even
- ver_str: dc.b 0,"$VER: Du 2.5 (6/7/92)",0
-
- even
- doslib: dc.b "dos.library",0
-
- even
- tplate: dc.b "NAME/M,DIRS/S,FILES/S,NOHEAD/S,NOTOTAL/S",0
-
- even
- sys: dc.b "sys:",0
-
- even
- break_str dc.b "***Break",$a,0
-
- even
- total_fmt dc.b "----- ----- -------- ------",$a
- dc.b "%5ld%6ld%9ld%7ld",$a,0
-
- even
- header_bar dc.b "Files Dirs Bytes Blocks",$a,0
-
- even
- file_fmt dc.b "%20ld%7ld %s",$0a,$0 ; uses %20ld for extra space
-
- even
- dir_fmt dc.b "%5ld%6ld%9ld%7ld ",$1b,"[33m","%s",$1b,"[31m",$0a,0
-
- end
-