home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / dirutl / du_pv.arc / DU.A86 next >
Text File  |  1989-08-05  |  11KB  |  577 lines

  1. ;    DU    Print disk usage for a directory and all subtrees.
  2. ;
  3. ;    Usage:    du [-h] [-nnn] [drive:][path]
  4. ;
  5. ;        -h   include hidden directories in list (not just in statistics)
  6. ;        -0   use actual cluster size (default)
  7. ;        -1   use cluster size for single sided diskette
  8. ;        -2   use cluster size for double sided diskette
  9. ;        -nnn, -nnnK  use cluster size of nnn or nnnK.
  10. ;
  11. ;    This is a disassembled and modified version of
  12. ;    CompuServe\ibmsw_forum\kegelu.arc\du.com
  13.  
  14. ;    Assemble with A86.
  15.  
  16. stdout    equ    1
  17. stderr    equ    2
  18. CR    equ    13
  19. LF    equ    10
  20. TAB    equ    9
  21. BEL    equ    7
  22.  
  23. area43:
  24. f_attr    equ    area43+21
  25. f_size    equ    area43+26
  26. f_name    equ    area43+30
  27.  
  28.     cld
  29.     mov    ah,1ah        ;set disk transfer address
  30.     mov    dx,offset area43
  31.     int    21h
  32.  
  33. ;    Handle switchar.
  34.  
  35.     mov    ax,3700h    ;get switch character
  36.     int    21h
  37.     cmp    dl,'/'
  38.     jne    wh2
  39.     mov    byte slash,'\'
  40.  
  41. ;    Handle switches.
  42.  
  43. wh2:    mov    di,81h
  44.     mov    ch,0
  45.     mov    cl,[di-1]
  46.  
  47. wh3:    jcxz    wh7        ;if end of string
  48.     mov    al,dl        ;switch character
  49.     repnz    scasb
  50.     jne    wh7        ;if done
  51.     cmp    al,'/'
  52.     je    wh4        ;if slash, don't require preceding white space
  53.     mov    al,[di-2]
  54.     cmp    al,' '
  55.     je    wh4        ;if space
  56.     cmp    al,TAB
  57.     jne    wh3        ;if not tab
  58.  
  59. wh4:    mov    ax,'  '        ;white out the switch
  60.     xchg    ax,[di-1]
  61.     xchg    al,ah
  62.     cmp    al,'h'
  63.     je    wh6
  64.     sub    al,'0'
  65.     cmp    al,9
  66.     ja    wh5        ;if not digit
  67.     call    nswit        ;process numeric switch
  68.     jmp    wh6a        ;go for more switches
  69.  
  70. wh5:    mov    si,offset msg1    ;illegal switch
  71.  
  72. errend:    mov    bx,stderr
  73.     mov    di,offset lyne
  74.     call    strprt
  75.     mov    ax,4c01h    ;error quit
  76.     int    21h
  77.     
  78. wh6:    mov    byte hidmask,0    ;set 'hidden' mask to zero
  79. wh6a:    mov    al,[di+1]
  80.     cmp    al,' '
  81.     je    wh3        ;if end of switches
  82.     cmp    al,TAB
  83.     je    wh3
  84.     inc    di
  85.     loop    wh4        ;loop back for more
  86.  
  87. ;    Get drive letter
  88.  
  89. wh7:    mov    si,81h
  90. wh8:    lodsb            ;skip separators
  91.     cmp    al,' '
  92.     je    wh8
  93.     cmp    al,TAB
  94.     je    wh8
  95.     dec    si
  96.     mov    ax,[si]
  97.     sub    ax,':A'
  98.     and    al,-1-20h
  99.     cmp    ax,31
  100.     jbe    wh9        ;if drive letter given
  101.     mov    ah,19h        ;get current disk
  102.     int    21h
  103.     add    al,'a'        ;prepend drive letter
  104.     mov    ah,':'
  105.     dec    si
  106.     dec    si
  107.     mov    [si],ax
  108. wh9:    mov    di,prmaddr
  109.     lodsb
  110.  
  111. ;    Copy until separator, converting to lower case.
  112.  
  113. wh10:    cmp    al,' '        ;check for separator
  114.     je    wh12
  115.     cmp    al,TAB
  116.     je    wh12
  117.     cmp    al,CR
  118.     je    wh13        ;if end of line
  119.     cmp    al,'A'
  120.     jb    wh11        ;if not upper case
  121.     cmp    al,'Z'
  122.     ja    wh11
  123.     add    al,20h
  124. wh11:    stosb
  125.     lodsb
  126.     jmp    wh10
  127.  
  128. ;    Too many parameters?
  129.  
  130. wh12:    lodsb
  131.     cmp    al,' '
  132.     je    wh12
  133.     cmp    al,TAB
  134.     je    wh12
  135.     cmp    al,CR
  136.     je    wh13
  137.     mov    si,offset msg2    ;too many parameters
  138.     jmp    errend
  139.  
  140. ;    If current directory:  find it.
  141.  
  142. wh13:    mov    byte [di],0    ;null terminate it
  143.     mov    ax,[prmaddr+2]
  144.     cmp    ax,'.'
  145.     je    wh14        ;if '.'
  146.     cmp    al,0
  147.     jne    wh15        ;if not empty
  148.  
  149. wh14:    mov    ah,47h        ;get current directory
  150.     mov    dl,[prmaddr]
  151.     sub    dl,'a'-1    ;drive
  152.     mov    si,prmaddr+3
  153.     int    21h
  154.     mov    al,slash
  155.     mov    [prmaddr+2],al
  156.     cmp    byte [prmaddr+3],0
  157.     jnz    wh17        ;if we are not in the root
  158.     mov    byte [prmaddr+2],0
  159.     jmp    short wh17
  160.  
  161. wh15:    dec    di
  162.     mov    al,byte [di]    ;remove trailing slash, if any
  163.     cmp    al,'/'
  164.     je    wh16
  165.     cmp    al,'\'
  166.     jne    wh17
  167.  
  168. wh16:    mov    byte [di],0    ;remove it
  169.  
  170. ;    Compute bytes to clusters shift.
  171.  
  172. wh17:    cmp    word shcount,0
  173.     jnz    wh20        ;if explicitly given
  174.     mov    ah,32h        ;get DOS disk block
  175.     mov    dl,[prmaddr]
  176.     sub    dl,'a'-1    ;drive no. (1=A, etc.)
  177.     int    21h
  178.     mov    ax,[bx+2]    ;bytes per sector
  179.     xor    cx,cx
  180.     or    ax,ax
  181.     jz    wh19        ;if zero:  something's wrong
  182. wh18:    shr    ax,1        ;compute log base two
  183.     inc    cx
  184.     cmp    ax,1
  185.     jne    wh18        ;if not done yet
  186. wh19:    add    cl,[bx+5]    ;cluster to sector shift
  187.     push    cs        ;restore DS
  188.     pop    ds
  189.     mov    shcount,cx    ;save it
  190.  
  191. wh20:    call    doit        ;do recursion
  192.     mov    si,prmaddr
  193.     cmp    byte [si+2],0    ;convert 'drive:' to 'drive:/'
  194.     jne    wh21
  195.     push    ax
  196.     mov    al,slash
  197.     mov    ah,0
  198.     mov    [si+2],ax
  199.     pop    ax
  200. wh21:    call    prntlin        ;print the first line
  201.     call    bsort        ;sort the first level
  202.     call    prnt        ;print the rest
  203.     ret            ;normal exit
  204.  
  205. ;    NSWIT    Handle numeric switch.
  206.  
  207. nswit:    push    dx
  208.     cbw
  209.     xchg    ax,bx        ;form number in bx
  210.     mov    si,10
  211.  
  212. ns1:    mov    al,[di+1]    ;begin loop over digits
  213.     sub    al,'0'
  214.     cmp    al,9
  215.     ja    ns2        ;if not digit
  216.     inc    di
  217.     dec    cx
  218.     mov    byte [di],' '    ;zero it out
  219.     cbw
  220.     xchg    ax,bx
  221.     mul    si
  222.     add    bx,ax
  223.     jmp    ns1        ;get next digit
  224.  
  225. ns2:    or    bx,bx
  226.     jz    ns7        ;if zero:  use actual
  227.     cmp    al,'K'-'0'
  228.     je    ns3
  229.     cmp    al,'k'-'0'
  230.     jne    ns4
  231.  
  232. ns3:    inc    di        ;'K' given:  remove the character
  233.     dec    cx
  234.     mov    byte [di],' '
  235.     mov    ax,10        ;initial shift count:  count kilobytes
  236.     jmp    ns5        ;compute kilobytes
  237.  
  238. ns4:    xor    ax,ax        ;no 'K' given:  initialize shift count
  239.     cmp    bx,2
  240.     ja    ns5        ;if byte count
  241.     add    bx,8        ;1 or 2:  use 9 or 10 for SS or DS
  242.     jmp    ns7
  243.  
  244. ns5:    xchg    ax,bx        ;shift count in bx, number being shifted in ax
  245. ns6:    shr    ax,1
  246.     jz    ns7        ;if done shifting
  247.     inc    bx
  248.     cmp    ax,3
  249.     jne    ns6        ;if not 3
  250.     inc    bx,2        ;add two more and quit
  251.  
  252. ns7:    mov    shcount,bx    ;save shift count
  253.     pop    dx
  254.     ret
  255.  
  256. ;    DOIT    Do the recursive part, adding up file lengths.
  257. ;        Exit    dx:ax    Cumulative file lengths
  258. ;            bx    Pointer to start of chain
  259. ;            cx    Cluster count
  260.  
  261. doit:    push    bp
  262.     sub    sp,10
  263.     mov    bp,sp
  264.     mov    word [bp+2],0    ;[bp+2] = (dword) cumulative length
  265.     mov    word [bp+4],0
  266.     mov    word [bp+6],0    ;[bp+6] = cumulative cluster count
  267.     mov    word [bp+8],0    ;[bp+8] = pointer to chain of items
  268.     mov    di,prmaddr    ;skip to end of string
  269.     mov    al,0
  270.     mov    cx,-1
  271.     repne    scasb
  272.     mov    [bp],di        ;[bp] = end of string
  273.     dec    di
  274.     mov    al,slash    ;add '/*.*'
  275.     stosb
  276.     mov    ax,'.*'
  277.     stosw
  278.     mov    ah,0
  279.     stosw
  280.     mov    ah,4eh        ;find first file
  281.     mov    cx,17h
  282.     mov    dx,prmaddr
  283.     int    21h
  284.     jc    do3        ;if none
  285.  
  286. ;    Begin loop over files.
  287.  
  288. do1:    mov    ax,word f_size    ;add file length to dword at [bp+2]
  289.     mov    dx,word f_size+2
  290.     add    [bp+2],ax
  291.     adc    [bp+4],dx
  292.     sub    ax,1        ;convert bytes to clusters
  293.     sbb    dx,0
  294.     jb    do1b        ;if zero
  295.     mov    cx,shcount
  296. do1a:    shr    dx,1        ;double shift
  297.     rcr    ax,1
  298.     loop    do1a
  299. do1b:    inc    ax
  300.     add    [bp+6],ax    ;add cluster count
  301.     test    byte f_attr,10h
  302.     jz    do2        ;if this is not a directory
  303.     cmp    byte f_name,'.'
  304.     jz    do2        ;if '.' or '..'
  305.     call    savname        ;make a heap entry
  306.     mov    [bp+8],bx    ;save its location
  307. do2:    mov    ah,4fh        ;get next file
  308.     int    21h
  309.     jnc    do1
  310.     mov    ah,0bh        ;check ctrl-break
  311.     int    21h
  312.  
  313. ;    Sort the directories found.
  314.  
  315. do3:    mov    bx,[bp+8]    ;address of this chain
  316.     call    bsort        ;sort the chain
  317.     push    bx
  318.  
  319. ;    Traverse the subdirectories.
  320.  
  321. do4:    or    bx,bx
  322.     jz    do5        ;if end of list
  323.     lea    si,[bx+11]    ;address of file name
  324.     mov    di,[bp]
  325.     mov    cx,13        ;copy new filename
  326.     rep    movsb
  327.     push    bx
  328.     call    doit        ;do recursion
  329.     pop    si
  330.     mov    [si+8],bx    ;link to subchain
  331.     add    [si],ax        ;adjust length
  332.     adc    [si+2],dx
  333.     add    [si+4],cx
  334.     add    [bp+2],ax
  335.     adc    [bp+4],dx
  336.     add    [bp+6],cx
  337.     mov    bx,[si+6]
  338.     jmp    do4        ;go back for more
  339.  
  340. do5:    mov    si,[bp]        ;restore string
  341.     mov    byte [si-1],0
  342.     pop    bx        ;bx = link to chain
  343.     mov    ax,[bp+2]    ;return the length and cluster info., too
  344.     mov    dx,[bp+4]
  345.     mov    cx,[bp+6]
  346.     add    sp,10
  347.     pop    bp
  348.     ret    
  349.  
  350. ;    SAVNAME    Save name in heap.
  351.  
  352. savname:mov    cx,1ch        ;allocate space for new entry
  353.     call    new
  354.     mov    di,bx
  355.     mov    ax,word f_size
  356.     stosw            ;[bx] = (dword) file size
  357.     mov    ax,word f_size+2
  358.     stosw
  359.     xor    ax,ax
  360.     stosw            ;[bx+4] = clusters used    (none by directory)
  361.     mov    ax,[bp+8]
  362.     stosw            ;[bx+6] = link to next in list
  363.     stosw            ;[bx+8] = link to subdirectory chain (later)
  364.     mov    al,byte f_attr
  365.     stosb            ;[bx+10] = attribute
  366.  
  367.     mov    si,offset f_name;[bx+11] = file name
  368.  
  369. sv1:    lodsb            ;copy the file name
  370.     cmp    al,'A'        ;convert to lower case
  371.     jb    sv2
  372.     cmp    al,'Z'
  373.     ja    sv2
  374.     add    al,'a'-'A'
  375. sv2:    stosb    
  376.     cmp    al,0
  377.     jnz    sv1
  378.     ret    
  379.  
  380. ;    BSORT    Bubble sort the chain at [bx].
  381.  
  382. bsort:    push    bp
  383.     sub    sp,4
  384.     mov    bp,sp
  385.     mov    [bp],bx
  386.     or    bx,bx
  387.     jz    bs5
  388. bs1:    mov    byte [bp+2],0
  389.     lea    bx,[bp]
  390.     mov    di,[bx]
  391.     mov    si,[di+6]
  392. bs2:    or    si,si
  393.     jz    bs4
  394.     push    si        ;compare the entries
  395.     push    di
  396.     mov    cx,15
  397.     add    si,11
  398.     add    di,11
  399.     repz    cmpsb    
  400.     pop    di
  401.     pop    si
  402.     jae    bs3
  403.     mov    ax,[si+6]    ;switch the two and set flag
  404.     mov    [di+6],ax
  405.     mov    [si+6],di
  406.     mov    [bx],si
  407.     xchg    si,di
  408.     mov    byte [bp+2],0ffh
  409. bs3:    lea    bx,[di+6]
  410.     mov    di,si
  411.     mov    si,[si+6]
  412.     jmp    bs2
  413.  
  414. bs4:    test    byte [bp+2],0ffh
  415.     jnz    bs1
  416. bs5:    mov    bx,[bp]
  417.     add    sp,4
  418.     pop    bp
  419.     ret    
  420.  
  421. ;    PRNT    Recursive subroutine to print the line.
  422.  
  423. prnt:    inc    word level
  424. pr1:    or    bx,bx
  425.     jz    pr3
  426.     push    [bx+6]        ;address of next entry
  427.     mov    al,[bx+10]    ;attribute
  428.     test    al,hidmask
  429.     jnz    pr2        ;if hidden
  430.     mov    ax,[bx]        ;length of file(s)
  431.     mov    dx,[bx+2]
  432.     mov    cx,[bx+4]
  433.     lea    si,[bx+11]    ;string
  434.     call    prntlin        ;print the line
  435.     mov    bx,[bx+8]
  436.     or    bx,bx
  437.     jz    pr2
  438.     call    prnt
  439. pr2:    pop    bx
  440.     jmp    pr1
  441.  
  442. pr3:    dec    level
  443.     ret    
  444.  
  445. ;    PRNTLIN    Print a line of the file.
  446. ;    Entry    dx:ax    Length
  447. ;        cx    Clusters used
  448. ;        level    Indicates number of spaces to skip
  449. ;        si    Beginning of string to put at end
  450.  
  451. prntlin:push    bx
  452.     xchg    ax,bx        ;ax:bx := length
  453.     xchg    ax,dx
  454.     mov    di,offset lyne
  455.     push    si
  456.     push    cx
  457.     mov    cx,9        ;print 9 character length
  458.     call    dprint
  459.     pop    bx        ;recover cluster count
  460.     xor    ax,ax
  461.     mov    cx,shcount
  462.     sub    cx,10
  463.     jle    prl2        ;if shift right
  464. prl1:    shl    bx,1        ;convert clusters to Kbytes
  465.     rcl    ax,1
  466.     loop    prl1
  467.     jmp    short prl3
  468. prl2:    neg    cx        ;shift right
  469.     clc
  470.     shr    bx,cl
  471.     jnc    prl3        ;if no rounding
  472.     inc    bx
  473. prl3:    mov    cx,6        ;print 6 character Kcount
  474.     call    dprint
  475.     mov    al,'K'
  476.     stosb
  477.     pop    si
  478.     mov    ax,'  '        ;add padding spaces
  479.     stosw
  480.     mov    cx,level
  481.     rep    stosw
  482.     add    cx,level
  483.     rep    stosb
  484.     mov    bx,stdout
  485.  
  486. ;    STRPRT    Print just a string.
  487. ;    Entry    bx    File handle
  488. ;        si    String
  489. ;        di    offset lyne
  490.  
  491. strprt:    lodsb            ;copy string at end
  492.     stosb
  493.     cmp    al,0
  494.     jne    strprt        ;if not end
  495.     mov    word [di-1],LF*256+CR
  496.     mov    ah,40h        ;write to file
  497.     mov    cx,di
  498.     mov    dx,offset lyne
  499.     sub    cx,dx
  500.     inc    cx
  501.     int    21h
  502.     pop    bx
  503.     ret    
  504.  
  505. ;    DPRINT    Print (CX)-digit number in AX:BX.
  506.  
  507. dprint:    push    bp
  508.     mov    bp,sp
  509.     mov    si,10
  510. dp1:    xor    dx,dx
  511.     div    si
  512.     xchg    ax,bx
  513.     div    si
  514.     add    dl,'0'
  515.     push    dx
  516.     dec    cx
  517.     xchg    ax,bx
  518.     or    bx,bx
  519.     jnz    dp1
  520.     or    ax,ax
  521.     jnz    dp1
  522.     or    cx,cx
  523.     js    dp2
  524.     mov    al,' '
  525.     rep    stosb
  526. dp2:    pop    ax
  527.     stosb
  528.     cmp    sp,bp
  529.     jne    dp2
  530.     pop    bp
  531.     ret
  532.     
  533. ;----- New - Allocate space on heap.
  534. ; Given length in CX, returns pointer in BX.
  535. ; Does not affect CX.
  536.  
  537. new:    push    cx
  538.     mov    bx, word heappos
  539.     add    cx, word heappos
  540.     mov    word heappos, cx
  541.     add    cx,100h
  542.     jc    newerror
  543.     cmp    sp, cx
  544.     pop    cx
  545.  
  546.     jbe    newerror
  547.     ret
  548.  
  549. stackmsg:    db    '?New: heap overflow', BEL, CR, LF
  550. sml    equ    22    ; newerror - stackmsg
  551.  
  552. newerror:
  553.     mov    dx, offset stackmsg
  554.     mov    cx, sml
  555.     mov    bx, stderr
  556.     mov    ah, 40h
  557.     int    21h
  558.     mov    ax, 4c02h        ; terminate--error code 2
  559.     int    21h
  560.     ret
  561.  
  562. heappos    dw    heap        ;heap variable
  563.  
  564. msg1    db    'Illegal switch',0
  565. msg2    db    'Too many parameters',0
  566. level    dw    0
  567. shcount    dw    0        ;byte to cluster shift count
  568. hidmask    db    6        ;value of -h switch
  569. slash    db    '/'
  570.  
  571. prmaddr equ    5ch        ;temp. storage for parameter
  572.  
  573. end1:                ;end of code
  574. lyne    equ    end1        ;where to form output line
  575. heap    equ    end1+80h    ;available for heap
  576.     end
  577.