kolibrios-gitea/kernel/trunk/fs/fs_lfn.inc

645 lines
15 KiB
PHP
Raw Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; 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
ERROR_OUT_OF_MEMORY = 12
maxPathLength = 1000h
image_of_eax EQU esp+32
image_of_ebx EQU esp+20
; 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
file_system_lfn:
; in: ebx -> parameter structure
; operation codes:
; 0 = read file
; 1 = read folder
; 2 = create/rewrite file
; 3 = write/append to file
; 4 = set file end
; 5 = get file info
; 6 = set file info
; start application
; 8 = delete file/folder
; 9 = create folder
lea ebp, [ebx+20]
cmp byte [ebp], 0
jnz @f
mov ebp, [ebx+21]
@@:
cmp dword[ebx], 7 ; start application
jne @f
mov edx, [ebx+4]
mov ebx, [ebx+8]
call fs_execute ; ebp, ebx, edx
mov [image_of_eax], eax
ret
@@:
cmp word [ebp], '/'
jz .rootdir
cmp byte [ebp], 2
jnz @f
cmp dword[ebp+1], '/'
jz .rootdir
@@:
stdcall kernel_alloc, maxPathLength
push ebx
mov ebx, ebp
mov ebp, eax
push maxPathLength
push eax
call get_full_file_name
pop ebx
test eax, eax
jz .notfound
mov esi, ebp
mov ax, [ebp]
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
call dword[fs_CdServices + eax*4]
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
stc
jnz @f ; no more partitions
mov al, 1 ; /cdX/1
clc
@@:
ret
.maindir: ; list partitions
mov esi, .nextCD
.maindir_noesi: ; backjump from dyndisk_handler
push ebp
mov ebp, ecx
call kernel_free
cmp dword[ebx], 1
jnz .access_denied ; read folder?
push ebp
pushd [ebx+4] ; first block
mov ebp, [ebx+12] ; the number of blocks to read
mov edx, [ebx+16] ; buffer
mov ebx, [ebx+8] ; flags
mov ecx, 32/4
mov edi, edx
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, 1
jz .uni
@@:
pop eax
add eax, '0'
stosb
test eax, eax
jnz @b
pop edi edx eax
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
.rootdir: ; / - virtual root folder
cmp dword[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, 1
jz .uni2
@@:
lodsb
stosb
test eax, eax
jnz @b
pop edi eax
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
or al, 20h
scasb
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]
dec ebx
jz .set
dec ebx
jz .get
dec ebx
jz .mount_additional_directory
dec ebx
jz .get16
@@:
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, 63
rep movsb ; copying fake directory name
inc esi
xor eax, eax
stosb ; terminator of name, in case if we get the inlet trash
mov cl, 63
cmp word [esi], 2
jz .utf16
call cp866toUTF8_string
@@:
mov byte [edi], 0
mov [full_file_name_table.size], 2
ret
.utf16:
add esi, 2
call UTF16to8_string
jmp @b
.get: ; in: ecx -> buffer, edx = length
mov esi, edi
mov edi, ecx
cmp edx, maxPathLength
jc @f
mov edx, maxPathLength
@@:
mov al, '/'
stosb
mov ecx, edx
dec ecx
@@:
dec ecx
js @f
call utf8to16
call uni2ansi_char
stosb
test al, al
jnz @b
sub edx, ecx
mov ecx, edx
@@:
mov [esp+32], ecx
ret
.get16:
mov esi, edi
mov edi, ecx
cmp edx, maxPathLength
jc @f
mov edx, maxPathLength
@@:
shr edx, 1
mov ax, '/'
stosw
mov ecx, edx
dec ecx
@@:
dec ecx
js @f
call utf8to16
stosw
test ax, ax
jnz @b
sub edx, ecx
mov ecx, edx
@@:
mov [esp+32], ecx
ret
.set:
pop eax
push maxPathLength
push edi
push eax
mov ebx, ecx
get_full_file_name:
; in: ebx -> file name, [esp+4] -> destination, [esp+8] = max length
; out: eax=0 -> out of length
push ebp ebx
mov esi, ebx
cmp byte [ebx], 2
jnz @f
inc esi
@@:
cmp byte [esi], '/'
jnz .set_relative
inc esi
cmp byte [ebx], 2
jnz @f
inc esi
@@:
call process_replace_file_name
mov edi, [esp+12]
mov ecx, [esp+16]
test ebp, ebp
jz .absolute
@@:
lodsb
stosb
dec ecx
test al, al
jnz @b
mov esi, ebp
dec edi
.absolute:
cmp byte [ebx], 2
jz @f
call cp866toUTF8_string
jns .ret
jmp .fail
@@:
call UTF16to8_string
jns .ret
.fail:
mov byte [edi], 0
xor eax, eax
pop ebx ebp
ret 8
.set_relative:
mov edi, [current_slot]
mov edi, [edi+APPDATA.cur_dir]
mov edx, edi
mov ecx, [esp+16]
xor eax, eax
repnz scasb
mov esi, edi
dec esi
mov edi, [esp+12]
jecxz .fail
cmp byte [ebx], 2
jz .relative16
.relative:
cmp byte [ebx], 0
jz .set_ok
cmp word [ebx], '.'
jz .set_ok
cmp word [ebx], './'
jz .next
cmp word [ebx], '..'
jnz .doset_relative
cmp byte [ebx+2], 0
jz @f
cmp byte [ebx+2], '/'
jnz .doset_relative
inc ebx
@@:
dec esi
cmp byte [esi], '/'
jnz @b
.next:
add ebx, 2
jmp .relative
.set_ok:
cmp edx, edi ; is destination equal to cur_dir?
jz @f
mov ecx, esi
sub ecx, edx
mov esi, edx
rep movsb
mov byte [edi], 0
.ret:
mov al, 1
pop ebx ebp
ret 8
@@:
mov byte [esi], 0
jmp .ret
.doset_relative:
cmp edx, edi ; is destination equal to cur_dir?
mov edi, esi
jz @f
mov edi, [esp+12]
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, [esp+16]
sub ecx, edi
mov ebx, [esp]
jmp .absolute
.relative16:
cmp word [ebx], 0
jz .set_ok
cmp word [ebx], '.'
jnz .doset_relative
cmp word [ebx+2], 0
jz .set_ok
cmp word [ebx+2], '/'
jz .next16
cmp word [ebx+2], '.'
jnz .doset_relative
cmp word [ebx+4], 0
jz @f
cmp word [ebx+4], '/'
jnz .doset_relative
add ebx, 2
@@:
dec esi
cmp byte [esi], '/'
jnz @b
.next16:
add ebx, 4
jmp .relative16
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"