;Copyright (C) 2000 Dmitry Bakhvalov
;
;$Id: rm.asm,v 1.5 2003/05/13 16:03:17 konst Exp $
;
;hackers' rm
;
;syntax: rm [-r] file...
;
;If someone really feels like he needs more of the original GNU rm's
;options - just ask me or better yet add 'em yourself :)
;
;Send me any feedback,suggestions,additional code, etc.
%include "system.inc"
CODESEG
START:
pop ecx ; get argc
cmp ecx,byte 2 ; must have at least 2 args
jl near invalid_args
pop eax ; skip argv[0]
dec ecx ; dont count argv[0]
xor ebp,ebp ; -r flag
pop ebx ; let's test for "-r" option
cmp word [ebx],"-r"
jnz not_recursive
inc ebp ; set recursive flag
jmp args_loop
not_recursive:
push ebx ; put the arg back
args_loop:
pop edi
test edi,edi
jz no_more_args
call is_dir
jnz rm_file
test ebp,ebp ; it's a dir and no -r flag
jz args_loop ; set. so we skip this arg
push edi ; dir to rm
call rm ; rm files
pop ebx ;
sys_rmdir ; rm the dir itself
jmp args_loop
rm_file:
sys_unlink edi ; rm the file
jmp args_loop
no_more_args:
invalid_args:
sys_exit_true ; exit
;
;
%define CALL_FRAME 8
%define SRC_DIR (CALL_FRAME+0)
%define HANDLE_SIZE 4
%define HANDLE_OFFS (HANDLE_SIZE+0)
%define DENTS_BUF_SIZE 266
%define DENTS_BUF_OFFS (DENTS_BUF_SIZE+HANDLE_OFFS)
%define BUF_SIZE 4096
%define BUF_OFFS (DENTS_BUF_OFFS+BUF_SIZE)
%define LOCAL_BUFSIZE (HANDLE_SIZE+DENTS_BUF_SIZE+BUF_SIZE)
rm:
push ebp
mov ebp,esp
sub esp,LOCAL_BUFSIZE
mov edi,[ebp+SRC_DIR] ; src must be a dir
call is_dir
jnz near .error
sys_open [ebp+SRC_DIR],O_RDONLY ; opendir(src)
test eax,eax
js near .error
mov [ebp-HANDLE_OFFS],eax
.next_dentry:
lea ecx,[ebp-DENTS_BUF_OFFS]
sys_getdents [ebp-HANDLE_OFFS],EMPTY,DENTS_BUF_SIZE
test eax,eax
js near .error
jz near .done
mov edi,ecx ; edi = buf
mov ecx,eax ; ecx = rc
.main_loop:
lea edx,[edi+10] ; edx = filename
mov ax,0x002E
cmp byte [edx],al ; starts with "." ?
jnz .without_dots ; nope
cmp byte [edx+1],ah ; null?
jz .skip ; skip "." dir
cmp word [edx+1],ax ; ".." dir
jz .skip ; skip it
.without_dots:
push edi ; save buf ptr
lea edi,[ebp-BUF_OFFS] ; tmp buffer
mov esi,[ebp+SRC_DIR] ; dst dir
; edx hold filename
call full_name ; create fullname
; edi holds tmp buffer
call is_dir
jnz .its_a_file
pushad ; call ourself
push edi ; fullname
call rm
pop ebx ; remove the dir itself
sys_rmdir
popad
jmp .next
.its_a_file:
; rm the damn file
sys_unlink edi
.next:
pop edi ; restore buf ptr
.skip:
xor eax,eax
mov ax,[edi+8] ; eax=rec_len
add edi,eax
sub ecx,eax
jnz .main_loop
jmp .next_dentry
.done:
mov ebx,[ebp-HANDLE_OFFS]
sys_close
.error:
add esp,LOCAL_BUFSIZE
pop ebp
ret
;
; ----------------------------- procedures ------------------------------------
;
; edi - tmp buf, esi - dir, edx - file
;
full_name:
pushad
call strcpy
call fix_slash
mov esi,edx
call strcat
popad
ret
; edi=file name
; -
fix_slash:
push edx
push esi
mov esi,edi
call strlen
dec edx
mov ax,0x002F
cmp byte [edi+edx],al
jz .ok
inc edx
mov word [edi+edx],ax
.ok:
pop esi
pop edx
ret
; edi = file name
; zero flag = 1 if dir; carry flag=1 if file doesnt exists
is_dir:
pushad
sys_lstat edi,stat_buf
test eax,eax
js .error
movzx eax,word [stat_buf.st_mode]
mov ebx,40000q
and eax,ebx
cmp eax,ebx
clc ; file exists
jmp .popit
.error:
stc ; if file doesnt exist set
; carry flag
.popit:
popad
ret
; esi=string
; edx=strlen
strlen:
push eax
push esi
xor eax,eax
mov edx,eax
dec edx
.do_strlen:
inc edx
lodsb
test al,al
jnz .do_strlen
pop esi
pop eax
ret
; esi=source edi=dest
; -
strcpy:
pushad
call strlen
inc edx ; copy NULL too
mov ecx,edx
rep movsb
popad
ret
; esi=source edi=dest
; -
strcat:
pushad
xchg esi,edi
call strlen
xchg esi,edi
add edi,edx
call strlen
inc edx ; copy NULL byte too
mov ecx,edx
rep movsb ; copy
popad
ret
UDATASEG
stat_buf B_STRUC Stat,.st_mode
buf: resb 4096
buf_size equ $-buf
END