360e379fc7
git-svn-id: svn://kolibrios.org@9047 a494cfbc-eb01-0410-851d-a64ba20cac60
795 lines
19 KiB
PHP
795 lines
19 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License. ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
$Revision$
|
|
|
|
ERROR_SUCCESS = 0
|
|
ERROR_DISK_BASE = 1
|
|
ERROR_UNSUPPORTED_FS = 2
|
|
ERROR_UNKNOWN_FS = 3
|
|
ERROR_PARTITION = 4
|
|
ERROR_FILE_NOT_FOUND = 5
|
|
ERROR_END_OF_FILE = 6
|
|
ERROR_MEMORY_POINTER = 7
|
|
ERROR_DISK_FULL = 8
|
|
ERROR_FS_FAIL = 9
|
|
ERROR_ACCESS_DENIED = 10
|
|
ERROR_DEVICE = 11
|
|
|
|
maxPathLength = 1000h
|
|
|
|
image_of_eax EQU esp+32
|
|
image_of_ebx EQU esp+20
|
|
|
|
; ; System function 70 security check
|
|
; align 4
|
|
; proc file_system_is_operation_safe stdcall, inf_struct_ptr: dword
|
|
; ; in:
|
|
; ; inf_struct_ptr = pointer to information structure was given to sysfn70
|
|
; ; out: ZF = 1 if operation is safe
|
|
; ; ZF = 0 if operation can cause kernel crash
|
|
; push ebx ecx edx
|
|
; xor ecx, ecx ; ecx - length of target buffer
|
|
|
|
; mov ebx, [inf_struct_ptr]
|
|
; mov edx, [ebx + 16] ; base of target buffer
|
|
|
|
; cmp dword [ebx], 0 ; if 70.0
|
|
; jnz .case1
|
|
; mov ecx, dword [ebx + 12]
|
|
; jmp .end_switch
|
|
|
|
; .case1:
|
|
; cmp dword [ebx], 1 ; if 70.1
|
|
; jnz .case2_3
|
|
; ;mov ecx, 32
|
|
; cmp dword [ebx + 8], 1 ; check encoding
|
|
; jbe .case1_304 ; if encdoing <= 1 i.e cpp866
|
|
; mov ecx, 560 ; if unicode then bdvk block len is 560 bytes
|
|
; jmp .case1_end
|
|
; .case1_304:
|
|
; mov ecx, 304 ; if cp866 then bdvk block len is 304 bytes
|
|
; .case1_end:
|
|
; imul ecx, dword [ebx + 12] ; multiply bdvk length by their count
|
|
; add ecx, 32 ; add result header len
|
|
; jmp .end_switch
|
|
|
|
; .case2_3:
|
|
; cmp dword [ebx], 3
|
|
; ja .case5 ; if subfn > 3
|
|
; mov ecx, dword [ebx + 12]
|
|
; jmp .end_switch
|
|
|
|
; .case5:
|
|
; cmp dword [ebx], 5
|
|
; jnz .case6
|
|
; mov ecx, 40
|
|
; jmp .end_switch
|
|
|
|
; .case6:
|
|
; cmp dword [ebx], 6
|
|
; jnz .switch_none
|
|
; mov ecx, 32
|
|
; jmp .end_switch
|
|
|
|
; .switch_none:
|
|
; mov ecx, 1
|
|
; test ecx, ecx
|
|
; jmp .ret
|
|
|
|
; .end_switch:
|
|
; ;;
|
|
; stdcall is_region_userspace, edx, ecx
|
|
; .ret:
|
|
; pop edx ecx ebx
|
|
; ret
|
|
; endp
|
|
|
|
; syscall_fileSystemUnicode: ; with user pointer correctness checking
|
|
; ; in: ebx -> f.80 parameter structure
|
|
; stdcall file_system_is_operation_safe, ebx
|
|
; jz @f
|
|
|
|
; DEBUGF 1, "sysfn80 addr error\n"
|
|
; mov dword [image_of_eax], ERROR_MEMORY_POINTER
|
|
; ret
|
|
; @@:
|
|
; jmp fileSystemUnicode
|
|
|
|
; temporarily commented out cause acpi driver (drivers/devman) uses sysfn70 via 0x40
|
|
; so because drivers it kernel space, pointer checking fails
|
|
; TODO solution: add filesystem functions without pointer checking to kernel exports
|
|
; and make the driver use them, not int 0x40
|
|
; syscall_fileSystemUnicode commented out for the same reason
|
|
; syscall_file_system_lfn: ; with user pointer correctness checking
|
|
; ; in: ebx -> f.70 parameter structure
|
|
; stdcall file_system_is_operation_safe, ebx
|
|
; jz @f
|
|
|
|
; DEBUGF 1, "sysfn70 addr error\n"
|
|
; mov dword [image_of_eax], ERROR_MEMORY_POINTER
|
|
; ret
|
|
; @@:
|
|
; jmp file_system_lfn
|
|
|
|
|
|
; System function 70
|
|
|
|
file_system_lfn_protected:
|
|
pushad
|
|
call protect_from_terminate
|
|
call file_system_lfn
|
|
call unprotect_from_terminate
|
|
popad
|
|
mov [image_of_eax], eax
|
|
mov [image_of_ebx], ebx
|
|
ret
|
|
|
|
fileSystemUnicode:
|
|
; in: ebx -> f.80 parameter structure
|
|
mov edi, [ebx+20]
|
|
mov esi, [ebx+24]
|
|
jmp @f
|
|
|
|
file_system_lfn:
|
|
; in: ebx -> f.70 parameter structure
|
|
xor edi, edi
|
|
lea esi, [ebx+20]
|
|
cmp byte [esi], 0
|
|
jnz @f
|
|
mov esi, [ebx+21]
|
|
@@:
|
|
cmp word [esi], '/'
|
|
jnz @f
|
|
cmp edi, 2
|
|
jnz .rootdir
|
|
cmp dword[esi], '/'
|
|
jz .rootdir
|
|
@@:
|
|
stdcall kernel_alloc, maxPathLength
|
|
push eax ebx
|
|
xchg eax, edi
|
|
call getFullPath
|
|
pop ebx ebp
|
|
test eax, eax
|
|
jz .notfound
|
|
cmp dword[ebx], 7 ; start application
|
|
jnz @f
|
|
mov edx, [ebx+4]
|
|
mov ecx, [ebx+8]
|
|
mov ebx, ebp
|
|
call fs_execute
|
|
mov [image_of_eax], eax
|
|
ret
|
|
|
|
@@:
|
|
lea esi, [ebp+2]
|
|
mov ax, [esi]
|
|
or ax, 2020h
|
|
cmp ax, 'cd'
|
|
jz .CD
|
|
call dyndisk_handler ; not returns if success
|
|
.notfound:
|
|
stdcall kernel_free, ebp
|
|
mov dword[image_of_eax], ERROR_FILE_NOT_FOUND
|
|
ret
|
|
|
|
.CD:
|
|
add esi, 2
|
|
xor eax, eax
|
|
lodsb ; disk number
|
|
sub eax, '0'
|
|
cmp eax, 10
|
|
jnc .notfound
|
|
mov edi, eax
|
|
lodsb
|
|
test eax, eax
|
|
jz .maindir
|
|
cmp al, '/'
|
|
jnz .notfound
|
|
lodsb ; partition number
|
|
test eax, eax
|
|
jz .maindir
|
|
cmp al, '1'
|
|
jnz .notfound
|
|
cmp byte [esi], '/'
|
|
jnz @f
|
|
inc esi
|
|
@@:
|
|
call reserve_cd
|
|
mov eax, edi
|
|
bt eax, 0
|
|
setc [DiskNumber]
|
|
bt eax, 1
|
|
setc [ChannelNumber]
|
|
inc [ChannelNumber]
|
|
inc eax
|
|
mov [cdpos], eax
|
|
call reserve_cd_channel
|
|
mov eax, edi
|
|
not eax
|
|
and eax, 3
|
|
shl eax, 1
|
|
inc eax
|
|
shr edi, 2
|
|
mov dword[image_of_eax], ERROR_FILE_NOT_FOUND
|
|
bt [edi*5+DRIVE_DATA+1], ax
|
|
jnc @f
|
|
mov ecx, [ebx+12]
|
|
mov edx, [ebx+16]
|
|
mov eax, [ebx]
|
|
mov dword[image_of_eax], ERROR_UNSUPPORTED_FS
|
|
cmp eax, fs_NumCdServices
|
|
jae @f
|
|
add ebx, 4
|
|
push ebp
|
|
call dword[fs_CdServices + eax*4]
|
|
pop ebp
|
|
mov [image_of_eax], eax
|
|
mov [image_of_ebx], ebx
|
|
@@:
|
|
call free_cd_channel
|
|
and [cd_status], 0
|
|
stdcall kernel_free, ebp
|
|
ret
|
|
|
|
.nextCD:
|
|
test eax, eax ; partition number
|
|
jnz @f
|
|
inc eax ; /cdX/1
|
|
ret
|
|
|
|
@@:
|
|
stc
|
|
ret
|
|
|
|
.maindir: ; list partitions
|
|
mov esi, .nextCD
|
|
xor ecx, ecx
|
|
.maindir_noesi: ; backjump from dyndisk_handler
|
|
push ebp
|
|
mov ebp, ecx
|
|
call kernel_free
|
|
mov edi, [ebx+16] ; buffer
|
|
cmp byte [ebx], 5
|
|
jz .deviceInfo
|
|
cmp byte [ebx], 1 ; read folder?
|
|
jnz .access_denied
|
|
push ebp
|
|
pushd [ebx+4] ; first block
|
|
mov ebp, [ebx+12] ; the number of blocks to read
|
|
mov ebx, [ebx+8] ; flags
|
|
mov ecx, 32/4
|
|
mov edx, edi
|
|
xor eax, eax
|
|
rep stosd
|
|
mov byte [edx], 1 ; version
|
|
.maindir_loop:
|
|
call esi
|
|
jc .maindir_done
|
|
inc dword[edx+8]
|
|
dec dword[esp]
|
|
jns .maindir_loop
|
|
dec ebp
|
|
js .maindir_loop
|
|
inc dword[edx+4]
|
|
mov dword[edi], 16 ; attributes: folder
|
|
mov dword[edi+4], ebx ; name encoding
|
|
push eax
|
|
mov ecx, 32/4
|
|
add edi, 8
|
|
xor eax, eax
|
|
rep stosd
|
|
pop eax
|
|
push eax edx edi
|
|
; convert number in eax to decimal string
|
|
push -'0'
|
|
mov ecx, 10
|
|
@@:
|
|
xor edx, edx
|
|
div ecx
|
|
push edx
|
|
test eax, eax
|
|
jnz @b
|
|
cmp ebx, 2
|
|
jz .uni
|
|
@@:
|
|
pop eax
|
|
add eax, '0'
|
|
stosb
|
|
test eax, eax
|
|
jnz @b
|
|
pop edi edx eax
|
|
cmp ebx, 3
|
|
jz @f
|
|
add edi, 264
|
|
jmp .maindir_loop
|
|
|
|
.uni:
|
|
pop eax
|
|
add eax, '0'
|
|
stosw
|
|
test eax, eax
|
|
jnz .uni
|
|
pop edi edx eax
|
|
@@:
|
|
add edi, 520
|
|
jmp .maindir_loop
|
|
|
|
.maindir_done:
|
|
pop eax eax
|
|
mov ebx, [edx+4]
|
|
xor eax, eax
|
|
dec ebp
|
|
js @f
|
|
mov al, ERROR_END_OF_FILE
|
|
@@:
|
|
mov [image_of_eax], eax
|
|
mov [image_of_ebx], ebx
|
|
ret
|
|
|
|
.access_denied:
|
|
mov dword[image_of_eax], ERROR_ACCESS_DENIED
|
|
ret
|
|
|
|
.deviceInfo:
|
|
test ebp, ebp
|
|
jz @f
|
|
mov eax, dword[ebp+DISK.MediaInfo.Capacity]
|
|
mov edx, dword[ebp+DISK.MediaInfo.Capacity+4]
|
|
shld edx, eax, 9
|
|
shl eax, 9
|
|
mov [edi+36], edx
|
|
mov [edi+32], eax
|
|
@@:
|
|
and dword[image_of_eax], 0
|
|
ret
|
|
|
|
.rootdir: ; / - virtual root folder
|
|
cmp byte [ebx], 5
|
|
jz @b
|
|
cmp byte [ebx], 1 ; read folder?
|
|
jnz .access_denied
|
|
mov ebp, [ebx+12] ; number of blocks
|
|
mov edx, [ebx+16] ; return area
|
|
push dword[ebx+4] ; first block
|
|
mov ebx, [ebx+8] ; flags
|
|
mov ecx, 32/4
|
|
mov edi, edx
|
|
xor eax, eax
|
|
rep stosd
|
|
mov byte [edx], 1 ; version
|
|
sub esp, 16
|
|
.rootdir_loop:
|
|
push edi
|
|
lea edi, [esp+4]
|
|
call dyndisk_enum_root
|
|
pop edi
|
|
test eax, eax
|
|
jz .rootdirCD
|
|
inc dword[edx+8]
|
|
dec dword[esp+16]
|
|
jns .rootdir_loop
|
|
dec ebp
|
|
js .rootdir_loop
|
|
inc dword[edx+4]
|
|
mov dword[edi], 16 ; attributes: folder
|
|
mov dword[edi+4], ebx ; name encoding
|
|
push eax
|
|
mov ecx, 32/4
|
|
add edi, 8
|
|
xor eax, eax
|
|
rep stosd
|
|
push edi
|
|
lea esi, [esp+8]
|
|
cmp ebx, 2
|
|
jz .uni2
|
|
@@:
|
|
lodsb
|
|
stosb
|
|
test eax, eax
|
|
jnz @b
|
|
pop edi eax
|
|
cmp ebx, 3
|
|
jz @f
|
|
add edi, 264
|
|
jmp .rootdir_loop
|
|
|
|
.uni2:
|
|
lodsb
|
|
stosw
|
|
test eax, eax
|
|
jnz .uni2
|
|
pop edi eax
|
|
@@:
|
|
add edi, 520
|
|
jmp .rootdir_loop
|
|
|
|
.rootdirCD:
|
|
add esp, 16
|
|
or esi, -1
|
|
.rootdirCD_loop:
|
|
inc esi
|
|
cmp esi, 10
|
|
jnc .rootdir_done
|
|
mov eax, esi
|
|
not eax
|
|
and eax, 3
|
|
shl eax, 1
|
|
inc eax
|
|
mov ecx, esi
|
|
shr ecx, 2
|
|
bt [ecx*5+DRIVE_DATA+1], ax
|
|
jnc .rootdirCD_loop
|
|
inc dword[edx+8]
|
|
dec dword[esp]
|
|
jns .rootdirCD_loop
|
|
dec ebp
|
|
js .rootdirCD_loop
|
|
inc dword[edx+4]
|
|
mov dword[edi], 16 ; attributes: folder
|
|
mov dword[edi+4], ebx ; name encoding
|
|
mov ecx, 32/4
|
|
add edi, 8
|
|
xor eax, eax
|
|
rep stosd
|
|
mov eax, esi
|
|
add eax, '0'
|
|
cmp ebx, 1
|
|
jz @f
|
|
mov word [edi], 'cd'
|
|
mov [edi+2], ax
|
|
add edi, 264
|
|
jmp .rootdirCD_loop
|
|
|
|
@@:
|
|
mov dword[edi], 640063h
|
|
mov [edi+4], eax
|
|
add edi, 520
|
|
jmp .rootdirCD_loop
|
|
|
|
.rootdir_done:
|
|
pop eax
|
|
mov ebx, [edx+4]
|
|
xor eax, eax
|
|
dec ebp
|
|
js @f
|
|
mov al, ERROR_END_OF_FILE
|
|
@@:
|
|
mov [image_of_eax], eax
|
|
mov [image_of_ebx], ebx
|
|
ret
|
|
|
|
;-----------------------------------------------------------------------------
|
|
process_replace_file_name:
|
|
; in: [esi] = virtual path
|
|
; out: [esi]+[ebp] = physical path
|
|
xor edi, edi
|
|
xor ebp, ebp
|
|
.loop:
|
|
cmp edi, [full_file_name_table.size]
|
|
jae .notfound
|
|
push esi edi
|
|
shl edi, 7
|
|
add edi, [full_file_name_table]
|
|
@@:
|
|
cmp byte [edi], 0
|
|
jz .dest_done
|
|
lodsb
|
|
test al, al
|
|
jz .cont
|
|
scasb
|
|
jz @b
|
|
or al, 20h
|
|
cmp [edi-1], al
|
|
jz @b
|
|
.cont:
|
|
pop edi esi
|
|
inc edi
|
|
jmp .loop
|
|
|
|
.dest_done:
|
|
cmp byte [esi], 0
|
|
jz .found
|
|
cmp byte [esi], '/'
|
|
jnz .cont
|
|
.found:
|
|
pop edi eax
|
|
shl edi, 7
|
|
add edi, [full_file_name_table]
|
|
mov ebp, esi
|
|
lea esi, [edi+64]
|
|
.notfound:
|
|
ret
|
|
|
|
;-----------------------------------------------------------------------------
|
|
uglobal
|
|
addDirSeal db ?
|
|
endg
|
|
|
|
sys_current_directory: ; sysfunction 30
|
|
mov eax, [current_slot]
|
|
mov edi, [eax+APPDATA.cur_dir]
|
|
xor eax, eax
|
|
dec ebx
|
|
jz .set
|
|
dec ebx
|
|
jz .get
|
|
dec ebx
|
|
jz .mount_additional_directory
|
|
mov eax, edx
|
|
dec ebx
|
|
jz .set
|
|
mov eax, esi
|
|
dec ebx
|
|
jz .get
|
|
@@:
|
|
ret
|
|
|
|
.mount_additional_directory:
|
|
; in: ecx -> dir name+dir path (128)
|
|
mov al, 1
|
|
xchg [addDirSeal], al
|
|
test al, al
|
|
jnz @b
|
|
mov esi, ecx
|
|
mov edi, sysdir_name1
|
|
mov ecx, 64
|
|
rep movsb ; copying fake directory name
|
|
mov byte [edi-1], 0
|
|
mov cl, 63
|
|
call cp866toUTF8_string
|
|
mov byte [edi], 0
|
|
mov [full_file_name_table.size], 2
|
|
ret
|
|
|
|
.get:
|
|
; in: ecx -> buffer, edx = length, eax = encoding
|
|
stdcall is_region_userspace, ecx, edx
|
|
jz @f
|
|
|
|
; if illegal buffer given
|
|
xor edx, edx
|
|
jmp .ret
|
|
@@:
|
|
|
|
mov esi, edi
|
|
inc esi
|
|
mov edi, ecx
|
|
cmp edx, maxPathLength
|
|
jc @f
|
|
mov edx, maxPathLength
|
|
@@:
|
|
mov ecx, edx
|
|
jecxz .ret
|
|
cmp eax, 2
|
|
jz .get16
|
|
cmp eax, 3
|
|
jz .get8
|
|
@@:
|
|
dec ecx
|
|
js @f
|
|
call utf8to16
|
|
call uni2ansi_char
|
|
stosb
|
|
test al, al
|
|
jnz @b
|
|
sub edx, ecx
|
|
@@:
|
|
mov byte [edi-1], 0
|
|
.ret:
|
|
mov [esp+32], edx
|
|
ret
|
|
|
|
.get8:
|
|
push edi
|
|
mov edi, esi
|
|
xor eax, eax
|
|
repnz scasb
|
|
sub edx, ecx
|
|
mov ecx, edx
|
|
pop edi
|
|
rep movsb
|
|
jmp @b
|
|
|
|
.get16:
|
|
shr ecx, 1
|
|
shr edx, 1
|
|
@@:
|
|
dec ecx
|
|
js @f
|
|
call utf8to16
|
|
stosw
|
|
test ax, ax
|
|
jnz @b
|
|
sub edx, ecx
|
|
@@:
|
|
shl edx, 1
|
|
mov word [edi-2], 0
|
|
jmp .ret
|
|
|
|
.set:
|
|
mov esi, ecx
|
|
getFullPath:
|
|
; in: esi -> file path, eax = string encoding, edi -> destination
|
|
; out: UTF-8 string (with marker), eax = length, 0 -> error
|
|
test eax, eax
|
|
jnz @f
|
|
cmp byte [esi], 4
|
|
jnc @f
|
|
cmp byte [esi], 0
|
|
jz @f
|
|
lodsb
|
|
@@:
|
|
cmp byte [esi], '/'
|
|
jnz .relative
|
|
cmp eax, 2
|
|
jnz @f
|
|
cmp word [esi], '/'
|
|
jnz .relative
|
|
inc esi
|
|
inc esi
|
|
jmp .start
|
|
|
|
@@:
|
|
inc esi
|
|
cmp byte [esi], 4
|
|
jnc .start
|
|
lodsb
|
|
cmp byte [esi], '/'
|
|
jnz .start
|
|
inc esi
|
|
.start:
|
|
push eax edi
|
|
call process_replace_file_name
|
|
mov edi, [esp]
|
|
mov ecx, maxPathLength
|
|
mov al, 3
|
|
mov ah, '/'
|
|
stosw
|
|
sub ecx, 2
|
|
test ebp, ebp
|
|
jz .absolute
|
|
@@:
|
|
lodsb
|
|
stosb
|
|
dec ecx
|
|
test al, al
|
|
jnz @b
|
|
mov esi, ebp
|
|
dec edi
|
|
.absolute:
|
|
cmp byte [esp+4], 2
|
|
jz .utf16
|
|
cmp byte [esp+4], 3
|
|
jz .utf8
|
|
call cp866toUTF8_string
|
|
jns .end
|
|
jmp .fail
|
|
|
|
.utf8:
|
|
dec ecx
|
|
js .fail
|
|
lodsb
|
|
stosb
|
|
test al, al
|
|
jz .end
|
|
jmp .utf8
|
|
|
|
.utf16:
|
|
call UTF16to8_string
|
|
jns .end
|
|
.fail:
|
|
mov byte [edi], 0
|
|
pop eax eax
|
|
xor eax, eax
|
|
ret
|
|
|
|
.relative:
|
|
push eax edi
|
|
mov ebx, esi
|
|
mov edi, [current_slot]
|
|
mov edi, [edi+APPDATA.cur_dir]
|
|
mov edx, edi
|
|
mov ecx, maxPathLength
|
|
xor eax, eax
|
|
repnz scasb
|
|
mov esi, edi
|
|
mov edi, [esp]
|
|
jecxz .fail
|
|
cmp byte [ebx], 0
|
|
jz .set_ok
|
|
dec esi
|
|
cmp edx, edi ; is destination equal to cur_dir?
|
|
mov edi, esi
|
|
jz @f
|
|
mov edi, [esp]
|
|
mov ecx, esi
|
|
sub ecx, edx
|
|
mov esi, edx
|
|
mov edx, edi
|
|
rep movsb
|
|
@@:
|
|
mov byte [edi], '/'
|
|
inc edi
|
|
mov esi, ebx
|
|
mov ecx, edx
|
|
add ecx, maxPathLength
|
|
sub ecx, edi
|
|
jmp .absolute
|
|
|
|
.set_ok:
|
|
cmp edx, edi ; is destination equal to cur_dir?
|
|
jz @f
|
|
mov ecx, esi
|
|
sub ecx, edx
|
|
mov esi, edx
|
|
rep movsb
|
|
@@:
|
|
pop eax
|
|
sub edi, eax
|
|
pop eax
|
|
mov eax, edi
|
|
ret
|
|
|
|
.end:
|
|
or ecx, -1
|
|
mov edi, [esp]
|
|
xor eax, eax
|
|
push edi
|
|
repnz scasb
|
|
not ecx
|
|
pop edi
|
|
.parse:
|
|
mov al, '/'
|
|
repnz scasb
|
|
jecxz @b
|
|
cmp byte [edi], '.'
|
|
jnz .parse
|
|
mov esi, edi
|
|
@@:
|
|
lodsw
|
|
sub ecx, 2
|
|
cmp ax, './'
|
|
jz @b
|
|
cmp ax, '..'
|
|
jnz @f
|
|
cmp byte [esi], '/'
|
|
jnz @f
|
|
mov edx, ecx
|
|
mov ecx, edi
|
|
sub ecx, [esp]
|
|
sub ecx, 2
|
|
jc .fail
|
|
sub edi, 2
|
|
lodsb
|
|
dec edx
|
|
std
|
|
repnz scasb
|
|
cld
|
|
add edi, 2
|
|
mov ecx, edx
|
|
jmp @b
|
|
|
|
@@:
|
|
sub esi, 2
|
|
add ecx, 2
|
|
cmp esi, edi
|
|
jz .parse
|
|
push edi ecx
|
|
rep movsb
|
|
pop ecx edi
|
|
jmp .parse
|
|
|
|
include "parse_fn.inc"
|
|
include "fs_common.inc"
|
|
include "iso9660.inc" ; read for CD filesystem
|
|
include "fat.inc"
|
|
include "ntfs.inc"
|
|
include "ext.inc"
|
|
include "xfs.asm"
|