home *** CD-ROM | disk | FTP | other *** search
- ; 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
-