;Copyright (C) 2002 by Joshua Hudson ; ;$Id: du.asm,v 1.2 2004/01/20 05:25:31 konst Exp $ ; ; hackers du - JH ; ; This guy can just about use that 8k stack ; ; Usage: du [-taskd] directory ; -t total all and display only total ; -a all files ; -s summary: no depth display ; -k display in kb blocks ; -ss turns off recursion all together ; -d Use 512 block size & fill holes (transfer est.) %include 'system.inc' direntbufsize equ 8192 ;S_IFMT equ 0170000q ;S_IFDIR equ 0040000q CODESEG START: ;*********** Process each option ***************** pop esi pop esi opt: pop esi or esi, esi jz bye lodsb cmp al, '-' jne doneopt .nopt lodsb cmp al, 'a' je .all cmp al, 's' je .sum cmp al, 't' je .tot cmp al, 'k' je .kb cmp al, 'd' je .kd cmp al, '-' je nextarg cmp al, 0 je opt jmps .nopt ; Skip unknown options .all inc byte [optall] jmps .nopt .sum inc byte [optsummary] jmps .nopt .tot inc byte [opttotal] jmps .nopt .kb inc byte [optkb] jmps .nopt .kd inc byte [optd] jmps .nopt ;******************* Display total and exit ************** bye: cmp [opttotal], byte 0 je .exit call itoa mov edx, itoabuf + 10 xchg eax, ebp push edx call itoa pop edx mov [edx], byte 10 sub edx, ecx inc edx sys_write 1 .exit sys_exit_true ;***************** Process each directory ****************** doneopt: dec esi push esi xor ebp, ebp nextarg: pop esi ; next argument or esi, esi jz bye mov edi, pathbuf .copy lodsb stosb or al, al jnz .copy dec edi call du js nextarg add ebp, eax cmp [opttotal], byte 0 jne nextarg call itoa call outline jmps nextarg ;**************** Calc usage of each directory ************* du: ; Stat it sys_lstat pathbuf, sts or eax, eax js near .duret ; cant stat this guy test [optd], byte 1 jz .dev mov eax, [sts.st_size] add eax, 511 xor edx, edx mov ebx, 512 div ebx jz .gotbk .dev mov eax, [sts.st_blocks] mov ebx, 512 ; Want # of device blocks used mul ebx ; not 512 byte blocks mov ebx, [sts.st_blksize] shr ebx, 2 ; Why? div ebx .gotbk cmp [optkb], byte 0 je .no2k or eax, eax ; If used no blocks, will use none jz .no2k mov ebx, 512 * 4 test [optd], byte 1 jnz .nodv2 mov ebx, [sts.st_blksize] .nodv2 mul ebx mov ebx, 1024 * 4 ; Why not 1024? div ebx or edx, edx jz .no2k inc eax ; Round up! .no2k cmp [optsummary], byte 2 jnb near .dubye ; No recursion at all! mov ebx, [sts.st_mode] and ebx, S_IFMT cmp ebx, S_IFDIR jne near .dubye ;******************* Du recursion ***************************** push ebx ; Save mode for later push ebp ; Be nice mov ebp, eax ; Our total to sum sys_open pathbuf, 0 xchg eax, ebx mov eax, ebp ; Prevent large return on ENOPERM or ebx, ebx js near .norec push edi mov [edi], byte '/' inc edi xor edx, edx mov dh, direntbufsize >> 8 call allocdirentsbuf push ecx ; Loop through all the directory entries in the directory in pathbuf ; (we opened it) .loop: pop ecx xor edx, edx mov dh, direntbufsize >> 8 push ecx %ifdef __BSD__ mov esi, direntoffs sys_getdirentries %else sys_getdents %endif or eax, eax js .donerc jz .donerc .next: push eax ; Cant pusha/popa here push ebx push ecx push edi %ifdef __BSD__ cdq cmp [ecx + dirent.d_fileno], edx ; Fix bum name for bum BSD jz .isnxt %endif lea esi, [ecx + dirent.d_name] cmp [esi], byte 0 je .isnxt cmp [esi], word 0x002E je .isnxt ; skip . (current directory) cmp [esi], word 0x2E2E jne .copy ; not .. cmp [esi + 2], byte 0 je .isnxt ; skip .. (parent directory) .copy lodsb stosb or al, al jnz .copy dec edi call du ; We are recursive anyway js .isnxt add ebp, eax ; Total it up cmp [opttotal], byte 0 jne .isnxt cmp [optall], byte 0 jne .disply or eax, eax js .isnxt cmp ebx, S_IFDIR ; ebx saved file type from call jne .isnxt .disply call itoa call outline .isnxt pop edi pop ecx pop ebx pop eax movzx edx, word [ecx + dirent.d_reclen] or edx, edx jz .nonext add ecx, edx sub eax, edx jnc .next .nonext: jmp .loop .donerc sys_close pop ecx call freedirentsbuf pop edi mov [edi], byte 0 add eax, ebp ; Return total .norec pop ebp pop ebx .dubye sub ecx, ecx ; clear sign flag .duret ret ;****************** Alloc/free functions ******************* allocdirentsbuf: ; works well enough mov ecx, [direntsbuf] ; Assuming stack like add ecx, edx cmp ecx, [highwater] jna .nosbrk push ebx sys_brk ecx or eax, eax js error pop ebx mov [highwater], ecx .nosbrk mov [direntsbuf], ecx mov [ecx - 4], ecx sub ecx, edx mov [ecx], ecx ret error: sys_exit_false freedirentsbuf: mov [direntsbuf], ecx ; Stack like: quick ret ;***************** Generic Subroutines ********************* itoa: push edi mov edi, itoabuf + 10 std _mov ebx, 10 push eax mov al, __t stosb pop eax .div xor edx, edx div ebx xchg eax, edx add al, '0' stosb xchg eax, edx or eax, eax jnz .div cld inc edi mov ecx, edi ; Odd? it makes sense (read below) pop edi ret outline: push edi mov edi, ecx xor edx, edx mov eax, edx .scan inc edx scasb jnz .scan dec edi mov [edi], byte 10 sys_write 1 mov [edi], byte 0 pop edi ret DATASEG direntsbuf dd buf highwater dd buf UDATASEG opttotal resb 1 optall resb 1 optsummary resb 1 optkb resb 1 optd resb 1 resb 3 sts: %ifdef __BSD__ B_STRUC Stat,.st_mode,.st_size,.st_blocks,.st_blksize %else B_STRUC Stat,.st_mode,.st_size,.st_blksize,.st_blocks %endif gtotal resd 1 itoabuf resb 11 pathbuf resb 1024 * 2 + 4 ; Real maximum %ifdef __BSD__ direntoffs resd 1 %endif buf resb 0 ; Grown with sys_brk END