;Copyright (C) 2000 Dmitry Bakhvalov
;
;$Id: mv.asm,v 1.4 2002/02/02 08:49:25 konst Exp $
;
;hackers' mv
;
;syntax: mv source dest, or
; mv source... directory
;
;No options are supported by now
;
;If someone really feels like he needs more of the original GNU mv'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 3 ; must have at least 3 args
jl near invalid_args
pop eax ; skip argv[0]
dec ecx ; dont count argv[0]
dec ecx ; last argument's index
xor edi,edi ; eax=NULL
xchg edi,[esp+ecx*4] ; argv[last_arg]=NULL
jmp short args_loop
move_file:
call mv
args_loop:
pop esi ; get nex arg
test esi,esi ; no more?
jnz move_file
no_more_args:
invalid_args:
sys_exit_true ; exit
; mv files
; esi - source file; edi - dest file/dir
; carry = 1 if error
mv:
pushad
call is_dir ; is our dest a dir
jnz .just_move ; it's a file. move now
push edi ; save target
call strlen ; get src len
mov ax,0x002f ; al='/',ah=0
mov ecx,edx ; save strlen
dec edx ; last char
mov edi,esi ; edi=src
add edi,edx ; edi points to the lats char
cmp byte [edi],al ; is it a '/'
jnz .no_slash ; nope
mov byte [edi],ah ; remove '/'
.no_slash:
std ; backward scanning
repne scasb ; look for first '/'
cld ; forward scanning
jnz .slash_not_found ;
inc edi ; correct edi
.slash_not_found:
inc edi ; correct edi
mov ebp,esi ; save esi
mov esi,edi ; esi=corrected scasb result
pop edi ; restore original dest
mov edx,esi ; edx=src filename
mov esi,edi ; esi=dst dir name
mov edi,buf ; edi=tmp buf
call full_name ; make full name: "dst_dir/filename"
mov esi,ebp ; restore original src
.just_move:
sys_rename esi, edi
popad
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_stat 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
cld
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