home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programming
/
powerprogramming1994.iso
/
progtool
/
dirutl
/
du_pv.arc
/
DU.A86
next >
Wrap
Text File
|
1989-08-05
|
11KB
|
577 lines
; DU Print disk usage for a directory and all subtrees.
;
; Usage: du [-h] [-nnn] [drive:][path]
;
; -h include hidden directories in list (not just in statistics)
; -0 use actual cluster size (default)
; -1 use cluster size for single sided diskette
; -2 use cluster size for double sided diskette
; -nnn, -nnnK use cluster size of nnn or nnnK.
;
; This is a disassembled and modified version of
; CompuServe\ibmsw_forum\kegelu.arc\du.com
; Assemble with A86.
stdout equ 1
stderr equ 2
CR equ 13
LF equ 10
TAB equ 9
BEL equ 7
area43:
f_attr equ area43+21
f_size equ area43+26
f_name equ area43+30
cld
mov ah,1ah ;set disk transfer address
mov dx,offset area43
int 21h
; Handle switchar.
mov ax,3700h ;get switch character
int 21h
cmp dl,'/'
jne wh2
mov byte slash,'\'
; Handle switches.
wh2: mov di,81h
mov ch,0
mov cl,[di-1]
wh3: jcxz wh7 ;if end of string
mov al,dl ;switch character
repnz scasb
jne wh7 ;if done
cmp al,'/'
je wh4 ;if slash, don't require preceding white space
mov al,[di-2]
cmp al,' '
je wh4 ;if space
cmp al,TAB
jne wh3 ;if not tab
wh4: mov ax,' ' ;white out the switch
xchg ax,[di-1]
xchg al,ah
cmp al,'h'
je wh6
sub al,'0'
cmp al,9
ja wh5 ;if not digit
call nswit ;process numeric switch
jmp wh6a ;go for more switches
wh5: mov si,offset msg1 ;illegal switch
errend: mov bx,stderr
mov di,offset lyne
call strprt
mov ax,4c01h ;error quit
int 21h
wh6: mov byte hidmask,0 ;set 'hidden' mask to zero
wh6a: mov al,[di+1]
cmp al,' '
je wh3 ;if end of switches
cmp al,TAB
je wh3
inc di
loop wh4 ;loop back for more
; Get drive letter
wh7: mov si,81h
wh8: lodsb ;skip separators
cmp al,' '
je wh8
cmp al,TAB
je wh8
dec si
mov ax,[si]
sub ax,':A'
and al,-1-20h
cmp ax,31
jbe wh9 ;if drive letter given
mov ah,19h ;get current disk
int 21h
add al,'a' ;prepend drive letter
mov ah,':'
dec si
dec si
mov [si],ax
wh9: mov di,prmaddr
lodsb
; Copy until separator, converting to lower case.
wh10: cmp al,' ' ;check for separator
je wh12
cmp al,TAB
je wh12
cmp al,CR
je wh13 ;if end of line
cmp al,'A'
jb wh11 ;if not upper case
cmp al,'Z'
ja wh11
add al,20h
wh11: stosb
lodsb
jmp wh10
; Too many parameters?
wh12: lodsb
cmp al,' '
je wh12
cmp al,TAB
je wh12
cmp al,CR
je wh13
mov si,offset msg2 ;too many parameters
jmp errend
; If current directory: find it.
wh13: mov byte [di],0 ;null terminate it
mov ax,[prmaddr+2]
cmp ax,'.'
je wh14 ;if '.'
cmp al,0
jne wh15 ;if not empty
wh14: mov ah,47h ;get current directory
mov dl,[prmaddr]
sub dl,'a'-1 ;drive
mov si,prmaddr+3
int 21h
mov al,slash
mov [prmaddr+2],al
cmp byte [prmaddr+3],0
jnz wh17 ;if we are not in the root
mov byte [prmaddr+2],0
jmp short wh17
wh15: dec di
mov al,byte [di] ;remove trailing slash, if any
cmp al,'/'
je wh16
cmp al,'\'
jne wh17
wh16: mov byte [di],0 ;remove it
; Compute bytes to clusters shift.
wh17: cmp word shcount,0
jnz wh20 ;if explicitly given
mov ah,32h ;get DOS disk block
mov dl,[prmaddr]
sub dl,'a'-1 ;drive no. (1=A, etc.)
int 21h
mov ax,[bx+2] ;bytes per sector
xor cx,cx
or ax,ax
jz wh19 ;if zero: something's wrong
wh18: shr ax,1 ;compute log base two
inc cx
cmp ax,1
jne wh18 ;if not done yet
wh19: add cl,[bx+5] ;cluster to sector shift
push cs ;restore DS
pop ds
mov shcount,cx ;save it
wh20: call doit ;do recursion
mov si,prmaddr
cmp byte [si+2],0 ;convert 'drive:' to 'drive:/'
jne wh21
push ax
mov al,slash
mov ah,0
mov [si+2],ax
pop ax
wh21: call prntlin ;print the first line
call bsort ;sort the first level
call prnt ;print the rest
ret ;normal exit
; NSWIT Handle numeric switch.
nswit: push dx
cbw
xchg ax,bx ;form number in bx
mov si,10
ns1: mov al,[di+1] ;begin loop over digits
sub al,'0'
cmp al,9
ja ns2 ;if not digit
inc di
dec cx
mov byte [di],' ' ;zero it out
cbw
xchg ax,bx
mul si
add bx,ax
jmp ns1 ;get next digit
ns2: or bx,bx
jz ns7 ;if zero: use actual
cmp al,'K'-'0'
je ns3
cmp al,'k'-'0'
jne ns4
ns3: inc di ;'K' given: remove the character
dec cx
mov byte [di],' '
mov ax,10 ;initial shift count: count kilobytes
jmp ns5 ;compute kilobytes
ns4: xor ax,ax ;no 'K' given: initialize shift count
cmp bx,2
ja ns5 ;if byte count
add bx,8 ;1 or 2: use 9 or 10 for SS or DS
jmp ns7
ns5: xchg ax,bx ;shift count in bx, number being shifted in ax
ns6: shr ax,1
jz ns7 ;if done shifting
inc bx
cmp ax,3
jne ns6 ;if not 3
inc bx,2 ;add two more and quit
ns7: mov shcount,bx ;save shift count
pop dx
ret
; DOIT Do the recursive part, adding up file lengths.
; Exit dx:ax Cumulative file lengths
; bx Pointer to start of chain
; cx Cluster count
doit: push bp
sub sp,10
mov bp,sp
mov word [bp+2],0 ;[bp+2] = (dword) cumulative length
mov word [bp+4],0
mov word [bp+6],0 ;[bp+6] = cumulative cluster count
mov word [bp+8],0 ;[bp+8] = pointer to chain of items
mov di,prmaddr ;skip to end of string
mov al,0
mov cx,-1
repne scasb
mov [bp],di ;[bp] = end of string
dec di
mov al,slash ;add '/*.*'
stosb
mov ax,'.*'
stosw
mov ah,0
stosw
mov ah,4eh ;find first file
mov cx,17h
mov dx,prmaddr
int 21h
jc do3 ;if none
; Begin loop over files.
do1: mov ax,word f_size ;add file length to dword at [bp+2]
mov dx,word f_size+2
add [bp+2],ax
adc [bp+4],dx
sub ax,1 ;convert bytes to clusters
sbb dx,0
jb do1b ;if zero
mov cx,shcount
do1a: shr dx,1 ;double shift
rcr ax,1
loop do1a
do1b: inc ax
add [bp+6],ax ;add cluster count
test byte f_attr,10h
jz do2 ;if this is not a directory
cmp byte f_name,'.'
jz do2 ;if '.' or '..'
call savname ;make a heap entry
mov [bp+8],bx ;save its location
do2: mov ah,4fh ;get next file
int 21h
jnc do1
mov ah,0bh ;check ctrl-break
int 21h
; Sort the directories found.
do3: mov bx,[bp+8] ;address of this chain
call bsort ;sort the chain
push bx
; Traverse the subdirectories.
do4: or bx,bx
jz do5 ;if end of list
lea si,[bx+11] ;address of file name
mov di,[bp]
mov cx,13 ;copy new filename
rep movsb
push bx
call doit ;do recursion
pop si
mov [si+8],bx ;link to subchain
add [si],ax ;adjust length
adc [si+2],dx
add [si+4],cx
add [bp+2],ax
adc [bp+4],dx
add [bp+6],cx
mov bx,[si+6]
jmp do4 ;go back for more
do5: mov si,[bp] ;restore string
mov byte [si-1],0
pop bx ;bx = link to chain
mov ax,[bp+2] ;return the length and cluster info., too
mov dx,[bp+4]
mov cx,[bp+6]
add sp,10
pop bp
ret
; SAVNAME Save name in heap.
savname:mov cx,1ch ;allocate space for new entry
call new
mov di,bx
mov ax,word f_size
stosw ;[bx] = (dword) file size
mov ax,word f_size+2
stosw
xor ax,ax
stosw ;[bx+4] = clusters used (none by directory)
mov ax,[bp+8]
stosw ;[bx+6] = link to next in list
stosw ;[bx+8] = link to subdirectory chain (later)
mov al,byte f_attr
stosb ;[bx+10] = attribute
mov si,offset f_name;[bx+11] = file name
sv1: lodsb ;copy the file name
cmp al,'A' ;convert to lower case
jb sv2
cmp al,'Z'
ja sv2
add al,'a'-'A'
sv2: stosb
cmp al,0
jnz sv1
ret
; BSORT Bubble sort the chain at [bx].
bsort: push bp
sub sp,4
mov bp,sp
mov [bp],bx
or bx,bx
jz bs5
bs1: mov byte [bp+2],0
lea bx,[bp]
mov di,[bx]
mov si,[di+6]
bs2: or si,si
jz bs4
push si ;compare the entries
push di
mov cx,15
add si,11
add di,11
repz cmpsb
pop di
pop si
jae bs3
mov ax,[si+6] ;switch the two and set flag
mov [di+6],ax
mov [si+6],di
mov [bx],si
xchg si,di
mov byte [bp+2],0ffh
bs3: lea bx,[di+6]
mov di,si
mov si,[si+6]
jmp bs2
bs4: test byte [bp+2],0ffh
jnz bs1
bs5: mov bx,[bp]
add sp,4
pop bp
ret
; PRNT Recursive subroutine to print the line.
prnt: inc word level
pr1: or bx,bx
jz pr3
push [bx+6] ;address of next entry
mov al,[bx+10] ;attribute
test al,hidmask
jnz pr2 ;if hidden
mov ax,[bx] ;length of file(s)
mov dx,[bx+2]
mov cx,[bx+4]
lea si,[bx+11] ;string
call prntlin ;print the line
mov bx,[bx+8]
or bx,bx
jz pr2
call prnt
pr2: pop bx
jmp pr1
pr3: dec level
ret
; PRNTLIN Print a line of the file.
; Entry dx:ax Length
; cx Clusters used
; level Indicates number of spaces to skip
; si Beginning of string to put at end
prntlin:push bx
xchg ax,bx ;ax:bx := length
xchg ax,dx
mov di,offset lyne
push si
push cx
mov cx,9 ;print 9 character length
call dprint
pop bx ;recover cluster count
xor ax,ax
mov cx,shcount
sub cx,10
jle prl2 ;if shift right
prl1: shl bx,1 ;convert clusters to Kbytes
rcl ax,1
loop prl1
jmp short prl3
prl2: neg cx ;shift right
clc
shr bx,cl
jnc prl3 ;if no rounding
inc bx
prl3: mov cx,6 ;print 6 character Kcount
call dprint
mov al,'K'
stosb
pop si
mov ax,' ' ;add padding spaces
stosw
mov cx,level
rep stosw
add cx,level
rep stosb
mov bx,stdout
; STRPRT Print just a string.
; Entry bx File handle
; si String
; di offset lyne
strprt: lodsb ;copy string at end
stosb
cmp al,0
jne strprt ;if not end
mov word [di-1],LF*256+CR
mov ah,40h ;write to file
mov cx,di
mov dx,offset lyne
sub cx,dx
inc cx
int 21h
pop bx
ret
; DPRINT Print (CX)-digit number in AX:BX.
dprint: push bp
mov bp,sp
mov si,10
dp1: xor dx,dx
div si
xchg ax,bx
div si
add dl,'0'
push dx
dec cx
xchg ax,bx
or bx,bx
jnz dp1
or ax,ax
jnz dp1
or cx,cx
js dp2
mov al,' '
rep stosb
dp2: pop ax
stosb
cmp sp,bp
jne dp2
pop bp
ret
;----- New - Allocate space on heap.
; Given length in CX, returns pointer in BX.
; Does not affect CX.
new: push cx
mov bx, word heappos
add cx, word heappos
mov word heappos, cx
add cx,100h
jc newerror
cmp sp, cx
pop cx
jbe newerror
ret
stackmsg: db '?New: heap overflow', BEL, CR, LF
sml equ 22 ; newerror - stackmsg
newerror:
mov dx, offset stackmsg
mov cx, sml
mov bx, stderr
mov ah, 40h
int 21h
mov ax, 4c02h ; terminate--error code 2
int 21h
ret
heappos dw heap ;heap variable
msg1 db 'Illegal switch',0
msg2 db 'Too many parameters',0
level dw 0
shcount dw 0 ;byte to cluster shift count
hidmask db 6 ;value of -h switch
slash db '/'
prmaddr equ 5ch ;temp. storage for parameter
end1: ;end of code
lyne equ end1 ;where to form output line
heap equ end1+80h ;available for heap
end