home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 700-799 / ff701.lha / du / Du.a < prev    next >
Text File  |  1992-08-03  |  12KB  |  515 lines

  1. ;**************************************************************************
  2. ;
  3. ; NAME        : Du v2.5
  4. ;
  5. ; TEMPLATE    : Du <dir/filename>,... [FILES] [DIRS] [NOHEAD] [NOTOTAL]
  6. ;
  7. ; DESCRIPTION    : print disk usage for a given set of directories/files.
  8. ;          If no directory specified then use current dir.
  9. ;
  10. ; AUTHOR    : Stuart Mitchell
  11. ;          (email: stuart@minster.york.ac.uk)
  12. ;
  13. ; DATE        : 12-Jul-92
  14. ;
  15. ; NOTES     : v1.0 - Initial coding
  16. ;          v2.0 - Accepts wildcards and files/dirs switches
  17. ;          v2.1 - Code tidied up
  18. ;          v2.2 - New tabular output
  19. ;          v2.3 - Can now be made resident (uses the LINK
  20. ;               instruction to grab workspace).
  21. ;             Prints totals if more than 1 arg or
  22. ;               an argument contains a wildcard.
  23. ;          v2.4 - If Lock on current dir is NULL then
  24. ;               uses "sys:"
  25. ;                 v2.5 - Now uses DOS 2.0 functions instead of ARP
  26. ;                        Added NOHEAD and NOTOTAL switches
  27. ;             Added WB2.0 version string
  28. ;
  29. ;**************************************************************************
  30.  
  31.  
  32.         section du,code
  33.  
  34.         include "dos/dos.i"
  35.         include "dos/dosextens.i"
  36.         include "dos/dosasl.i"
  37.         include "exec/memory.i"
  38.         include "exec/execbase.i"
  39.  
  40. _LVOOpenLibrary     equ    -$228
  41. _LVOCloseLibrary    equ    -$19e
  42. _LVOFreeMem        equ    -$d2
  43. _LVOAllocMem        equ    -$c6
  44.  
  45. _LVOAllocDosObject    equ    -$e4
  46. _LVOReadArgs        equ    -$31e
  47. _LVOFreeArgs        equ    -$35a
  48. _LVOPutStr        equ    -$3b4
  49. _LVOMatchFirst        equ    -$336
  50. _LVOMatchNext        equ    -$33c
  51. _LVOMatchEnd        equ    -$342
  52. _LVOVPrintf        equ    -$3ba
  53. _LVOPrintFault        equ    -$1da
  54. _LVOGetCurrentDirName    equ    -$234
  55.  
  56. CALL        macro    (name)
  57.         jsr    _LVO\1(a6)
  58.         endm
  59.  
  60. r_current_arg    equr    a2
  61. r_anchor    equr    a3
  62. r_dosbase    equr    a4
  63. r_var_base    equr    a5
  64.  
  65. r_files        equr    d2
  66. r_dirs        equr    d3    ; note multiple use
  67. r_options    equr    d3    ; this IS OK
  68. r_bytes        equr    d4
  69. r_blocks    equr    d5
  70. r_total_flag    equr    d6
  71. r_rdaargs       equr    d7
  72.  
  73. ;; bitdefs for dir scan - should really be picked up from dosasl.i ...
  74.  
  75. DIDDIR        equ    3
  76. DODIR        equ    2
  77. ITSWILD        equ    1
  78.  
  79. ;; define offsets into space reserved on the stack by link instruction
  80.  
  81. LINK_SIZE    equ    56            ; size of reserved area
  82.  
  83. ;; running totals
  84.  
  85. TFILES        equ    -56            ; must be in this order!
  86. TDIRS        equ    -52
  87. TBYTES        equ    -48
  88. TBLOCKS        equ    -44
  89.  
  90. ;; arguments for VPrintf()
  91.  
  92. P_ARG0        equ    -40            ; must be in this order
  93. P_ARG1        equ    -36            ;
  94. P_ARG2        equ    -32            ;
  95. P_ARG3        equ    -28            ;
  96. P_ARG4        equ    -24            ;
  97.  
  98. ;; vars returned by call to ReadArgs()
  99.  
  100. ARGS        equ    -20            ; char *args[]
  101. DIR_FLAG    equ    -16
  102. FILE_FLAG    equ    -12
  103. HEADER_FLAG    equ    -8
  104. TOTAL_FLAG    equ    -4
  105.  
  106. ;; *********************************************************************
  107.  
  108. start:        link    r_var_base,#-LINK_SIZE    ; reserve 56 bytes on stack
  109.  
  110. ;; open DOS library
  111.  
  112. open_lib:    move.l    (4).w,a6
  113.         lea    doslib(pc),a1
  114.         moveq.l    #37,d0            ; 2.04 +
  115.         CALL    OpenLibrary
  116.         tst.l    d0
  117.         beq    exit
  118.         move.l    d0,a6
  119.         move.l    d0,r_dosbase
  120.  
  121. ;; clear argument array and global vars
  122.  
  123.                 moveq.l    #(LINK_SIZE-4)/4,d0    ; loop count
  124.         moveq.l #0,d3
  125.         lea    -LINK_SIZE(r_var_base),a0
  126. clr_loop:       move.l  d3,(a0)+
  127.                 dbra    d0,clr_loop
  128.  
  129. ;; parse command line
  130. ;;   (d3 already set to NULL)
  131.  
  132. parse_args:     lea    ARGS(r_var_base),a0    ; pointer to arg array
  133.         move.l    a0,d2
  134.         lea    tplate(pc),a0
  135.         move.l    a0,d1
  136.         CALL    ReadArgs
  137.  
  138.         move.l    d0,r_rdaargs
  139.         beq    closedos
  140.  
  141. ;; output header line
  142.  
  143.         tst.l    HEADER_FLAG(r_var_base)
  144.         bne.s   1$            ; skip if flag specified
  145.  
  146.         lea    header_bar(pc),a0
  147.         move.l    a0,d1
  148.         CALL    PutStr
  149.  
  150. ;; total flag is incremented for each arg, thus if more than one arg
  151. ;; is present then total flag will end up non-zero...
  152.  
  153. 1$        moveq.l    #-1,r_total_flag
  154.  
  155.         moveq.l    #0,r_options
  156. set_file_flag:    move.l    FILE_FLAG(r_var_base),d0
  157.         beq.s    set_dir_flag        ; if zero then option not specified
  158.         moveq.l    #-1,r_options
  159. set_dir_flag:    move.l    DIR_FLAG(r_var_base),d0
  160.         beq.s   test_num_args
  161.         moveq.l    #1,r_options
  162.  
  163. ;; test if any directories/files specified on the command line - if none
  164. ;; then do current directory
  165.  
  166. test_num_args:    tst.l    ARGS(r_var_base)
  167.         beq    do_curr_dir
  168.  
  169. ;; allocate memory for AnchorPath structure
  170.  
  171.         bsr    alloc_anchor
  172.  
  173. ;; main loop -
  174. ;;   for each arg:
  175. ;;   while (matching entry found)
  176. ;;     if (file)
  177. ;;       print info;
  178. ;;     else
  179. ;;       scan dir & print info;
  180.  
  181.         move.l  ARGS(r_var_base),r_current_arg
  182. main_loop:    move.l    (r_current_arg)+,d1
  183.         beq    print_total        ; no args left (last arg NULL)
  184.  
  185.         addq.l    #1,r_total_flag        ; increment totals count
  186.  
  187. findfirst:    move.l    r_anchor,d2
  188.         CALL    MatchFirst
  189.         tst.l    d0
  190.         bne    does_not_exist
  191.  
  192. ;; if arg is wildcard then force totals at the end
  193. ;; ( ITSWILD bit is set by the call to MatchFirst )
  194.  
  195.         move.b    ap_Flags(r_anchor),d0
  196.         btst    #ITSWILD,d0        ; bit's status --> Z flag
  197.         beq.s    inner_loop        ; if bit clear then continue
  198.  
  199.                 moveq.l    #1,r_total_flag     ; make sure totals are printed
  200.  
  201. inner_loop:    move.l    fib_DirEntryType+ap_Info(r_anchor),d0
  202.         blt.s    do_file
  203.  
  204. do_dir:         cmp.l    #ST_LINKDIR,d0        ; if this a (hard) link
  205.         beq.s    skip            ; if so ignore it
  206.         cmp.l    #ST_SOFTLINK,d0        ; soft link (file OR dir)
  207.         beq.s    skip
  208.  
  209.         tst.l    r_options        ; if r_options is negative
  210.         blt.s    skip            ;   then files only required
  211.  
  212.         lea    ap_Buf(r_anchor),a0
  213.         bsr    du
  214.         tst.l    d0
  215.         bne.s    break_pressed        ; error - break pressed
  216.  
  217.         bra.s    skip
  218.  
  219. do_file:        cmp.l   #ST_LINKFILE,d0        ; file link?
  220.         beq.s    skip
  221.  
  222.         tst.l    r_options        ; if r_options is positive
  223.         bgt.s    skip            ;   then only dirs to be shown
  224.  
  225.         move.l    fib_Size+ap_Info(r_anchor),d0
  226.         move.l    d0,P_ARG0(r_var_base)
  227.         add.l    d0,TBYTES(r_var_base)
  228.  
  229.         move.l    fib_NumBlocks+ap_Info(r_anchor),d0
  230.         addq.l    #1,d0            ; correct block count to
  231.         move.l    d0,P_ARG1(r_var_base)    ;   include file header block
  232.         add.l    d0,TBLOCKS(r_var_base)
  233.  
  234.         lea    fib_FileName+ap_Info(r_anchor),a0
  235.         move.l    a0,P_ARG2(r_var_base)
  236.  
  237.         lea    P_ARG0(r_var_base),a0
  238.         move.l    a0,d2
  239.         lea    file_fmt(pc),a0
  240.         move.l    a0,d1
  241.         CALL    VPrintf
  242.  
  243. skip:        move.l    r_anchor,d1
  244.         CALL    MatchNext
  245.         cmpi.l    #ERROR_BREAK,d0
  246.         beq.s    break_pressed
  247.         tst.l    d0
  248.         beq.s    inner_loop
  249.  
  250.         bra    main_loop
  251.  
  252. print_total:    tst.l    r_total_flag        ; only print totals if
  253.         ble.s    free_rda        ;   flag is >0
  254.         tst.l   TOTAL_FLAG(r_var_base)    ; skip totals if NOTOTAL flag
  255.         bne.s    free_rda        ;   specified on command line
  256.  
  257.         lea    total_fmt(pc),a0
  258.         move.l    a0,d1
  259.         lea     TFILES(r_var_base),a0
  260.         move.l    a0,d2
  261.         CALL    VPrintf
  262.         bra.s   free_rda
  263.  
  264. ;; ********************************************************************
  265. ;; Output "**BREAK" - Called if CNTL-C detected
  266. ;;     Note: drop through to end of program
  267.  
  268. break_pressed:  move.l    #break_str,d1
  269.         CALL    PutStr
  270.  
  271. ;; ********************************************************************
  272.  
  273. free_rda:       move.l    r_rdaargs,d1
  274.         CALL    FreeArgs
  275.  
  276.         bsr    free_asl
  277.  
  278. closedos:    move.l    r_dosbase,a1
  279.         move.l    (4).w,a6
  280.         CALL    CloseLibrary
  281.  
  282. exit:        unlk    r_var_base
  283.         moveq.l    #0,d0
  284.         rts
  285.  
  286. ;; **********************************************************************
  287. ;; Print error message if object does not exist
  288. ;;
  289. ;; IN:    d0 - error code from MatchFirst() call (i.e. IoErr() code)
  290. ;;     a6 - DosBase
  291. ;; OUT:    <none>
  292.  
  293. does_not_exist:    move.l    d0,d1
  294.         move.l    -4(r_current_arg),d2    ; r_current_arg has been advanced already
  295.         CALL    PrintFault
  296.         bra    main_loop        ; try next arg...
  297.  
  298. ;; **********************************************************************
  299. ;; Scan directory and print info on directory
  300. ;;
  301. ;; IN:    a0 - full pathname of required directory
  302. ;;     r_var_base - pointer to top of allocated workspace
  303. ;;    a6 - DosBase
  304. ;; OUT:    d0 - 0 on success, 1 if interrupted by ^C
  305.  
  306. du:        movem.l    d2-d7/a2-a4,-(sp)
  307.         move.l    a0,a2
  308.         move.l    a0,P_ARG4(r_var_base)    ; save name to print later
  309.  
  310.         bsr    alloc_anchor
  311.         move.l    r_anchor,d2
  312.         beq     exit_du            ; no memory
  313.  
  314. ;; main loop
  315.  
  316. ;; find first file/directory
  317.  
  318.         move.l    a2,d1            ; move pathname
  319.         CALL    MatchFirst
  320.         tst.l    d0
  321.         bne.s   finished        ; should never happen...
  322.  
  323. init_regs:    moveq.l    #0,r_files        ; zero results
  324.         moveq.l    #0,r_dirs
  325.         moveq.l    #0,r_bytes
  326.         moveq.l    #0,r_blocks
  327.  
  328. ;; loop around in directory until all subdirectories/files exhausted
  329.  
  330. du_loop:    move.b    ap_Flags(r_anchor),d1
  331.  
  332. ;; if DirEntryType <0 then we have a file
  333.  
  334.         move.l    fib_DirEntryType+ap_Info(r_anchor),d0
  335.         blt.s    du_do_file
  336.  
  337. du_do_dir:    btst    #DIDDIR,d1        ; DIDDIR bit set
  338.         beq.s    du_enter_dir        ; no ... enter dir
  339.  
  340. ;; have just popped out of a directory, mark as finished & increment count
  341.  
  342. du_exit_dir:    bclr    #DIDDIR,d1
  343.  
  344.         addq.l    #1,r_dirs        ; bump dir count
  345.         bra.s    du_find_next
  346.  
  347. ;; found a new directory, so enter it at next FindNext
  348.  
  349. du_enter_dir:    bset    #DODIR,d1
  350.         bra.s    du_find_next
  351.  
  352. ;; this ones a file, so increment count & bytes
  353.  
  354. du_do_file:    addq.l    #1,r_files
  355.         add.l    fib_Size+ap_Info(r_anchor),r_bytes
  356.         add.l    fib_NumBlocks+ap_Info(r_anchor),r_blocks
  357.         addq.l    #1,r_blocks        ; take account of file header block
  358.  
  359. ;; find next file/dir
  360.  
  361. du_find_next:    move.b    d1,ap_Flags(r_anchor)    ; set directory handling
  362.  
  363.         move.l    r_anchor,d1
  364.         CALL    MatchNext
  365.         cmpi.l    #ERROR_BREAK,d0        ; ^C pressed ?
  366.         beq.s    du_break
  367.         tst.l    d0              ; if zero then got something
  368.         beq.s    du_loop
  369.  
  370. ;; print out results (dirname already put in place at start of subroutine)
  371.  
  372. print_dir:    movem.l r_files/r_dirs/r_bytes/r_blocks,P_ARG0(r_var_base)     ; flush results
  373.  
  374.         add.l    r_bytes,TBYTES(r_var_base)
  375.         add.l    r_files,TFILES(r_var_base)
  376.         add.l    r_blocks,TBLOCKS(r_var_base)
  377.         add.l    r_dirs,TDIRS(r_var_base)
  378.  
  379.         lea    dir_fmt(pc),a0        ; format string
  380.         move.l    a0,d1
  381.         lea    P_ARG0(r_var_base),a0    ; address of ptrs to args
  382.         move.l    a0,d2
  383.         CALL    VPrintf            ; print results
  384.  
  385. finished:    bsr.s    free_asl
  386.         moveq.l    #0,d0            ; set error code
  387. exit_du:    movem.l    (sp)+,d2-d7/a2-a4
  388.         rts
  389.  
  390. du_break:    bsr.s    free_asl
  391.         moveq.l    #1,d0            ; error return code
  392.         bra.s    exit_du
  393.  
  394. ;; **********************************************************************
  395. ;; Allocate an ASL AnchorPath structure & extra string storage space
  396. ;;
  397. ;; IN:    <none>
  398. ;; OUT:    d0 - pointer to anchorpath structure, or NULL on failiure
  399.  
  400. alloc_anchor:    move.l    a6,-(sp)
  401.  
  402.         move.l    #ap_SIZEOF+256,d0       ; allow room for full pathname
  403.         moveq.l    #MEMF_PUBLIC,d1
  404.         move.l    (4).w,a6
  405.         CALL    AllocMem                ;
  406.         move.l    d0,r_anchor        ; save it
  407.  
  408. ;; set up required fields in structure
  409.  
  410.         move.b    #%00100001,ap_Flags(r_anchor)   ; DOWILD|DODOT
  411.         move.w    #256,ap_Strlen(r_anchor)    ; for full path
  412.  
  413. ;; set bits we can break on (^C only)
  414.  
  415.                 move.l    #$00001000,ap_BreakBits(r_anchor)
  416.  
  417.                 move.l    (sp)+,a6
  418.         rts
  419.  
  420. ;; **********************************************************************
  421. ;; Free ASL Anchor Chain
  422. ;;
  423. ;; IN:    a6 - DosBase
  424. ;; OUT:    <none>
  425.  
  426. free_asl:    move.l    r_anchor,d1        ; free any memory allocated
  427.         beq.s   null_anchor        ; by dos routines
  428.  
  429.         CALL    MatchEnd
  430.  
  431.         move.l    a6,-(sp)        ; save DosBase
  432.         move.l    r_anchor,a1
  433.                 move.l    #ap_SIZEOF+256,d0
  434.         move.l    (4).w,a6
  435.         CALL    FreeMem            ; free AnchorPath struct
  436.  
  437.         sub.l    r_anchor,r_anchor       ; clear register
  438.  
  439.         move.l    (sp)+,a6
  440. null_anchor:    rts
  441.  
  442. ;; **********************************************************************
  443. ;; find name of current directory and use that
  444. ;;
  445. ;; IN:     a6 - DosBase
  446. ;; OUT:    <none>
  447.  
  448. do_curr_dir:    move.l    r_rdaargs,d1        ; finished with args
  449.         CALL    FreeArgs
  450.  
  451.         move.l    (4).w,a6
  452.         moveq.l    #MEMF_PUBLIC,d1
  453.         move.l    #1024,d0        ; get memory to store
  454.         CALL    AllocMem        ; full path of current dir
  455.         tst.l    d0
  456.         beq    closedos
  457.         move.l    d0,a2            ; store address
  458.  
  459.         move.l    r_dosbase,a6
  460.         move.l    d0,d1
  461.         move.l    #1024,d2
  462.                 CALL    GetCurrentDirName
  463.         beq.s    use_sys            ; failed...
  464.  
  465.                 tst.b    (a2)            ; empty buffer?
  466.         beq.s    use_sys            ; use "sys:"
  467.  
  468.         move.l    a2,a0            ; get ptr path name
  469.  
  470.                 bra.s    do_cd            ; and do it
  471.  
  472. use_sys:    lea    sys(pc),a0
  473.  
  474. do_cd:        bsr    du
  475.  
  476. free_buffer:    move.l    a2,a1            ; move buffer address
  477.                 move.l  d2,d0            ; buffer length
  478.                 move.l    (4).w,a6        ; get ExecBase
  479.  
  480.         CALL     FreeMem
  481.  
  482.         bra     closedos        ; exit program
  483.  
  484. ;; ************************************************************************
  485.  
  486.         even
  487. ver_str:    dc.b    0,"$VER: Du 2.5 (12.7.92)",0
  488.  
  489.         even
  490. doslib:        dc.b    "dos.library",0
  491.  
  492.         even
  493. tplate:        dc.b    "NAME/M,DIRS/S,FILES/S,NOHEAD/S,NOTOTAL/S",0
  494.  
  495.         even
  496. sys:        dc.b    "sys:",0
  497.  
  498.         even
  499. break_str    dc.b    "***Break",$a,0
  500.  
  501.         even
  502. total_fmt    dc.b    "----- ----- -------- ------",$a
  503.         dc.b    "%5ld%6ld%9ld%7ld",$a,0
  504.  
  505.         even
  506. header_bar    dc.b    "Files  Dirs    Bytes Blocks",$a,0
  507.  
  508.         even
  509. file_fmt    dc.b    "%20ld%7ld %s",$0a,$0 ; uses %20ld for extra space
  510.  
  511.         even
  512. dir_fmt        dc.b    "%5ld%6ld%9ld%7ld ",$1b,"[33m","%s",$1b,"[31m",$0a,0
  513.  
  514.         end
  515.