forked from KolibriOS/kolibrios
906756cda2
git-svn-id: svn://kolibrios.org@3743 a494cfbc-eb01-0410-851d-a64ba20cac60
1344 lines
50 KiB
PHP
1344 lines
50 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
;; ;;
|
||
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||
;; Distributed under terms of the GNU General Public License ;;
|
||
;; 02.02.2010 turbanoff - support 70.5 ;;
|
||
;; 23.01.2010 turbanoff - support 70.0 70.1 ;;
|
||
;; 21.06.2013 yogev_ezra - Translate Russian comments ;;
|
||
;; ;;
|
||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
$Revision$
|
||
|
||
EXT2_BAD_INO = 1
|
||
EXT2_ROOT_INO = 2
|
||
EXT2_ACL_IDX_INO = 3
|
||
EXT2_ACL_DATA_INO = 4
|
||
EXT2_BOOT_LOADER_INO = 5
|
||
EXT2_UNDEL_DIR_INO = 6
|
||
|
||
;RUS: флаги, указываемые в inode файла ;ENG: flags specified in file inode
|
||
EXT2_S_IFREG = 0x8000
|
||
EXT2_S_IFDIR = 0x4000
|
||
EXT2_S_IFMT = 0xF000 ;RUS: маска для типа файла ;ENG: mask for file type
|
||
|
||
;RUS: флаги, указываемые в linked list родительской папки
|
||
;ENG: flags specified in linked list of parent folder
|
||
EXT2_FT_REG_FILE = 1 ;RUS: это файл, запись в родительском каталоге
|
||
;ENG: this is a file, record in parent catalog
|
||
EXT2_FT_DIR = 2 ;RUS: это папка ;ENG: this is a folder
|
||
|
||
;RUS: флаги используемые KolibriOS ;ENG: flags used by KolibriOS
|
||
FS_FT_HIDDEN = 2
|
||
FS_FT_DIR = 0x10 ;RUS: это папка ;ENG: this is a folder
|
||
FS_FT_ASCII = 0 ;RUS: имя в ascii ;ENG: name in ASCII
|
||
FS_FT_UNICODE = 1 ;RUS: имя в unicode ;ENG: name in UNICODE
|
||
|
||
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ;RUS: тип файла должен указываться в директории
|
||
;ENG: file type must be specified in the folder
|
||
EXT4_FEATURE_INCOMPAT_EXTENTS = 0x0040 ;RUS: экстенты ;ENG: extents
|
||
EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x0200 ;RUS: гибкие группы блоков ;ENG: flexible block groups
|
||
|
||
;RUS: реализованные ext[234] features ;ENG: implemented ext[234] features
|
||
EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \
|
||
or EXT4_FEATURE_INCOMPAT_EXTENTS \
|
||
or EXT4_FEATURE_INCOMPAT_FLEX_BG
|
||
|
||
;RUS: флаги, указываемые для inode в i_flags ;ENG: flags specified for inode in i_flags
|
||
EXT2_EXTENTS_FL = 0x00080000
|
||
|
||
struct EXT2_INODE_STRUC
|
||
i_mode dw ?
|
||
i_uid dw ?
|
||
i_size dd ?
|
||
i_atime dd ?
|
||
i_ctime dd ?
|
||
i_mtime dd ?
|
||
i_dtime dd ?
|
||
i_gid dw ?
|
||
i_links_count dw ?
|
||
i_blocks dd ?
|
||
i_flags dd ?
|
||
i_osd1 dd ?
|
||
i_block rd 15
|
||
i_generation dd ?
|
||
i_file_acl dd ?
|
||
i_dir_acl dd ?
|
||
i_faddr dd ?
|
||
i_osd2 dd ? ; 1..12
|
||
ends
|
||
|
||
struct EXT2_DIR_STRUC
|
||
inode dd ?
|
||
rec_len dw ?
|
||
name_len db ?
|
||
file_type db ?
|
||
name db ? ; 0..255
|
||
ends
|
||
|
||
struct EXT2_BLOCK_GROUP_DESC
|
||
block_bitmap dd ? ;+0
|
||
inode_bitmap dd ? ;+4
|
||
inode_table dd ? ;+8
|
||
free_blocks_count dw ? ;+12
|
||
free_inodes_count dw ? ;+14
|
||
used_dirs_count dw ? ;+16
|
||
pad dw ? ;+18
|
||
reserved rb 12;+20
|
||
ends
|
||
|
||
struct EXT2_SB_STRUC
|
||
inodes_count dd ? ;+0
|
||
blocks_count dd ? ;+4
|
||
r_block_count dd ? ;+8
|
||
free_block_count dd ? ;+12
|
||
free_inodes_count dd ? ;+16
|
||
first_data_block dd ? ;+20
|
||
log_block_size dd ? ;+24
|
||
log_frag_size dd ? ;+28
|
||
blocks_per_group dd ? ;+32
|
||
frags_per_group dd ? ;+36
|
||
inodes_per_group dd ? ;+40
|
||
mtime dd ? ;+44
|
||
wtime dd ? ;+48
|
||
mnt_count dw ? ;+52
|
||
max_mnt_count dw ? ;+54
|
||
magic dw ? ;+56
|
||
state dw ? ;+58
|
||
errors dw ? ;+60
|
||
minor_rev_level dw ? ;+62
|
||
lastcheck dd ? ;+64
|
||
check_intervals dd ? ;+68
|
||
creator_os dd ? ;+72
|
||
rev_level dd ? ;+76
|
||
def_resuid dw ? ;+80
|
||
def_resgid dw ? ;+82
|
||
first_ino dd ? ;+84
|
||
inode_size dw ? ;+88
|
||
block_group_nr dw ? ;+90
|
||
feature_compat dd ? ;+92
|
||
feature_incompat dd ? ;+96
|
||
feature_ro_compat dd ? ;+100
|
||
uuid rb 16 ;+104
|
||
volume_name rb 16 ;+120
|
||
last_mounted rb 64 ;+136
|
||
algo_bitmap dd ? ;+200
|
||
prealloc_blocks db ? ;+204
|
||
preallock_dir_blocks db ? ;+205
|
||
reserved_gdt_blocks dw ? ;+206
|
||
journal_uuid rb 16 ;+208
|
||
journal_inum dd ? ;+224
|
||
journal_dev dd ? ;+228
|
||
last_orphan dd ? ;+232
|
||
hash_seed rd 4 ;+236
|
||
def_hash_version db ? ;+252
|
||
rb 3 ;+253 reserved
|
||
default_mount_options dd ? ;+256
|
||
first_meta_bg dd ? ;+260
|
||
mkfs_time dd ? ;+264
|
||
jnl_blocks rd 17 ;+268
|
||
blocks_count_hi dd ? ;+336
|
||
r_blocks_count_hi dd ? ;+340
|
||
free_blocks_count_hi dd ? ;+344
|
||
min_extra_isize dw ? ;+348
|
||
want_extra_isize dw ? ;+350
|
||
flags dd ? ;+352
|
||
raid_stride dw ? ;+356
|
||
mmp_interval dw ? ;+358
|
||
mmp_block dq ? ;+360
|
||
raid_stripe_width dd ? ;+368
|
||
log_groups_per_flex db ? ;+372
|
||
ends
|
||
|
||
struct EXT4_EXTENT_HEADER ;RUS: заголовок блока экстентов/индексов
|
||
eh_magic dw ? ;RUS: в текущей реализации ext4 должно быть 0xF30A
|
||
eh_entries dw ? ;RUS: количество экстентов/индексов в блоке
|
||
eh_max dw ? ;RUS: max количество (используется при записи)
|
||
eh_depth dw ? ;RUS: глубина дерева (0, если это блок экстентов)
|
||
eh_generation dd ? ;???
|
||
ends
|
||
|
||
struct EXT4_EXTENT ;RUS: экстент ;ENG: extent
|
||
ee_block dd ? ;RUS: номер ext4 блока ;ENG: number of ext4 block
|
||
ee_len dw ? ;RUS: длина экстента ;ENG: extent length
|
||
ee_start_hi dw ? ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS)
|
||
;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet)
|
||
ee_start_lo dd ? ;RUS: младшие 32 бита 48-битного адреса
|
||
;ENG: lower 32 bits of the 48-bit address
|
||
ends
|
||
|
||
struct EXT4_EXTENT_IDX ;RUS: индекс - указатель на блок с экстентами/индексами
|
||
;ENG: index - pointer to block of extents/indexes
|
||
ei_block dd ? ;RUS: номер ext4 блока ;ENG: number of ext4 block
|
||
ei_leaf_lo dd ? ;RUS: младшие 32 бит 48-битного адреса
|
||
;ENG: lower 32 bits of the 48-bit address
|
||
ei_leaf_hi dw ? ;RUS: старшие 16 бит 48-битного адреса (пока не используются в KOS)
|
||
;ENG: upper 16 bits of the 48-bit address (not used in KolibriOS yet)
|
||
ei_unused dw ? ;RUS: зарезервировано ;ENG: reserved
|
||
ends
|
||
|
||
struct EXTFS PARTITION
|
||
Lock MUTEX
|
||
log_block_size dd ?
|
||
block_size dd ?
|
||
count_block_in_block dd ?
|
||
blocks_per_group dd ?
|
||
global_desc_table dd ?
|
||
root_inode dd ? ; pointer to root inode in memory
|
||
inode_size dd ?
|
||
count_pointer_in_block dd ? ; block_size / 4
|
||
count_pointer_in_block_square dd ? ; (block_size / 4)**2
|
||
ext2_save_block dd ? ;RUS: блок на глобальную 1 процедуру ;ENG: block for 1 global procedure
|
||
ext2_temp_block dd ? ;RUS: блок для мелких процедур ;ENG: block for small procedures
|
||
ext2_save_inode dd ? ;RUS: inode на глобальную процедуру ;ENG: inode for global procedure
|
||
ext2_temp_inode dd ? ;RUS: inode для мелких процедур ;ENG: inode for small procedures
|
||
groups_count dd ?
|
||
superblock rd 512/4
|
||
ends
|
||
|
||
iglobal
|
||
align 4
|
||
ext2_user_functions:
|
||
dd ext2_free
|
||
dd (ext2_user_functions_end - ext2_user_functions - 4) / 4
|
||
dd ext2_Read
|
||
dd ext2_ReadFolder
|
||
dd ext2_Rewrite
|
||
dd ext2_Write
|
||
dd ext2_SetFileEnd
|
||
dd ext2_GetFileInfo
|
||
dd ext2_SetFileInfo
|
||
dd 0
|
||
dd ext2_Delete
|
||
dd ext2_CreateFolder
|
||
ext2_user_functions_end:
|
||
endg
|
||
|
||
proc ext2_create_partition
|
||
push ebx
|
||
|
||
mov eax, 2 ;superblock start at 1024b
|
||
add ebx, 512 ; get pointer to fs-specific buffer
|
||
call fs_read32_sys
|
||
|
||
cmp [ebx + EXT2_SB_STRUC.log_block_size], 3 ;0,1,2,3
|
||
ja .no
|
||
cmp [ebx + EXT2_SB_STRUC.magic], 0xEF53
|
||
jne .no
|
||
cmp [ebx + EXT2_SB_STRUC.state], 1 ;EXT_VALID_FS=1
|
||
jne .no
|
||
cmp [ebx + EXT2_SB_STRUC.inodes_per_group], 0
|
||
je .no
|
||
|
||
mov eax, [ebx + EXT2_SB_STRUC.feature_incompat]
|
||
test eax, EXT2_FEATURE_INCOMPAT_FILETYPE
|
||
jz .no
|
||
test eax, not EXT4_FEATURE_INCOMPAT_SUPP
|
||
jz ext2_setup
|
||
|
||
.no:
|
||
; No, this superblock isn't EXT2
|
||
pop ebx
|
||
xor eax, eax
|
||
ret
|
||
|
||
; OK, this is correct EXT2 superblock
|
||
ext2_setup:
|
||
movi eax, sizeof.EXTFS
|
||
call malloc
|
||
test eax, eax
|
||
jz ext2_create_partition.no
|
||
|
||
mov ecx, dword [ebp+PARTITION.FirstSector]
|
||
mov dword [eax+EXTFS.FirstSector], ecx
|
||
mov ecx, dword [ebp+PARTITION.FirstSector+4]
|
||
mov dword [eax+EXTFS.FirstSector+4], ecx
|
||
mov ecx, dword [ebp+PARTITION.Length]
|
||
mov dword [eax+EXTFS.Length], ecx
|
||
mov ecx, dword [ebp+PARTITION.Length+4]
|
||
mov dword [eax+EXTFS.Length+4], ecx
|
||
mov ecx, [ebp+PARTITION.Disk]
|
||
mov [eax+EXTFS.Disk], ecx
|
||
mov [eax+EXTFS.FSUserFunctions], ext2_user_functions
|
||
push ebp esi edi
|
||
mov ebp, eax
|
||
lea ecx, [eax+EXTFS.Lock]
|
||
call mutex_init
|
||
|
||
mov esi, ebx
|
||
lea edi, [ebp+EXTFS.superblock]
|
||
mov ecx, 512/4
|
||
rep movsd ; copy sb to reserved mem
|
||
|
||
mov eax, [ebx + EXT2_SB_STRUC.blocks_count]
|
||
sub eax, [ebx + EXT2_SB_STRUC.first_data_block]
|
||
dec eax
|
||
xor edx, edx
|
||
div [ebx + EXT2_SB_STRUC.blocks_per_group]
|
||
inc eax
|
||
mov [ebp+EXTFS.groups_count], eax
|
||
|
||
mov ecx, [ebx + EXT2_SB_STRUC.log_block_size]
|
||
inc ecx
|
||
mov [ebp+EXTFS.log_block_size], ecx ; 1, 2, 3, 4 equ 1kb, 2kb, 4kb, 8kb
|
||
|
||
mov eax, 1
|
||
shl eax, cl
|
||
mov [ebp+EXTFS.count_block_in_block], eax
|
||
|
||
shl eax, 7
|
||
mov [ebp+EXTFS.count_pointer_in_block], eax
|
||
mov edx, eax ;RUS: потом еще квадрат найдем ;ENG: we'll find a square later
|
||
|
||
shl eax, 2
|
||
mov [ebp+EXTFS.block_size], eax
|
||
|
||
push eax eax ; 2 kernel_alloc
|
||
|
||
mov eax, edx
|
||
mul edx
|
||
mov [ebp+EXTFS.count_pointer_in_block_square], eax
|
||
|
||
call kernel_alloc
|
||
mov [ebp+EXTFS.ext2_save_block], eax ; and for temp block
|
||
call kernel_alloc
|
||
mov [ebp+EXTFS.ext2_temp_block], eax ; and for get_inode proc
|
||
|
||
movzx eax, word [ebx + EXT2_SB_STRUC.inode_size]
|
||
mov ecx, [ebx + EXT2_SB_STRUC.blocks_per_group]
|
||
|
||
mov [ebp+EXTFS.inode_size], eax
|
||
mov [ebp+EXTFS.blocks_per_group], ecx
|
||
|
||
push eax eax eax ;3 kernel_alloc
|
||
call kernel_alloc
|
||
mov [ebp+EXTFS.ext2_save_inode], eax
|
||
call kernel_alloc
|
||
mov [ebp+EXTFS.ext2_temp_inode], eax
|
||
call kernel_alloc
|
||
mov [ebp+EXTFS.root_inode], eax
|
||
|
||
mov ebx, eax
|
||
mov eax, EXT2_ROOT_INO
|
||
call ext2_get_inode ; read root inode
|
||
|
||
mov eax, ebp ; return pointer to EXTFS
|
||
pop edi esi ebp ebx
|
||
ret
|
||
endp
|
||
|
||
proc ext2_free
|
||
push ebp
|
||
xchg ebp, eax
|
||
stdcall kernel_free, [ebp+EXTFS.ext2_save_block]
|
||
stdcall kernel_free, [ebp+EXTFS.ext2_temp_block]
|
||
stdcall kernel_free, [ebp+EXTFS.ext2_save_inode]
|
||
stdcall kernel_free, [ebp+EXTFS.ext2_temp_inode]
|
||
stdcall kernel_free, [ebp+EXTFS.root_inode]
|
||
xchg ebp, eax
|
||
call free
|
||
pop ebp
|
||
ret
|
||
endp
|
||
|
||
proc ext2_lock
|
||
lea ecx, [ebp+EXTFS.Lock]
|
||
jmp mutex_lock
|
||
endp
|
||
|
||
proc ext2_unlock
|
||
lea ecx, [ebp+EXTFS.Lock]
|
||
jmp mutex_unlock
|
||
endp
|
||
|
||
;==================================================================
|
||
;read ext2 block form FS to memory
|
||
;in: eax = i_block (address of block in ext2 terms)
|
||
; ebx = pointer to return memory
|
||
; ebp = pointer to EXTFS
|
||
;out: eax - error code (0 = no_error)
|
||
ext2_get_block:
|
||
push ebx ecx
|
||
mov ecx, [ebp+EXTFS.log_block_size]
|
||
shl eax, cl
|
||
mov ecx, eax
|
||
push [ebp+EXTFS.count_block_in_block]
|
||
@@:
|
||
mov eax, ecx
|
||
call fs_read32_sys
|
||
test eax, eax
|
||
jnz .fail
|
||
inc ecx
|
||
add ebx, 512
|
||
dec dword [esp]
|
||
jnz @B
|
||
pop ecx
|
||
xor eax, eax
|
||
@@:
|
||
pop ecx ebx
|
||
ret
|
||
.fail:
|
||
mov eax, ERROR_DEVICE
|
||
jmp @B
|
||
|
||
|
||
;===================================================================
|
||
;RUS: получает номер блока из extent inode ;ENG: receives block number from extent inode
|
||
;RUS: in: ecx = номер блока по порядку ;ENG: in: ecx = consecutive block number
|
||
;RUS: esi = адрес extent header`а ;ENG: esi = address of extent header
|
||
;RUS: ebp = указатель на структуру EXTFS ;ENG: ebp = pointer to EXTFS
|
||
;RUS: out: ecx - адрес очередного блока в случае успеха ;ENG: out: ecx - address of next block, if successful
|
||
;RUS: eax - номер ошибки (если равно 0, то ошибки нет) ;ENG: eax - error number (0 - no error)
|
||
ext4_block_recursive_search:
|
||
cmp word [esi + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC
|
||
jne .fail
|
||
|
||
movzx ebx, [esi + EXT4_EXTENT_HEADER.eh_entries]
|
||
add esi, sizeof.EXT4_EXTENT_HEADER
|
||
cmp word [esi - sizeof.EXT4_EXTENT_HEADER + EXT4_EXTENT_HEADER.eh_depth], 0
|
||
je .leaf_block ;листовой ли это блок?
|
||
|
||
;не листовой блок, а индексный ; eax - ext4_extent_idx
|
||
test ebx, ebx
|
||
jz .fail ;пустой индексный блок -> ошибка
|
||
|
||
;цикл по индексам экстентов
|
||
@@:
|
||
cmp ebx, 1 ;у индексов не хранится длина,
|
||
je .end_search_index ;поэтому, если остался последний - то это нужный
|
||
|
||
cmp ecx, [esi + EXT4_EXTENT_IDX.ei_block]
|
||
jb .fail
|
||
|
||
cmp ecx, [esi + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса
|
||
jb .end_search_index ;следующий дальше - значит текущий, то что нам нужен
|
||
|
||
add esi, sizeof.EXT4_EXTENT_IDX
|
||
dec ebx
|
||
jmp @B
|
||
|
||
.end_search_index:
|
||
;ebp указывает на нужный extent_idx, считываем следующий блок
|
||
mov ebx, [ebp+EXTFS.ext2_temp_block]
|
||
mov eax, [esi + EXT4_EXTENT_IDX.ei_leaf_lo]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .fail
|
||
mov esi, ebx
|
||
jmp ext4_block_recursive_search ;рекурсивно прыгаем в начало
|
||
|
||
.leaf_block: ;листовой блок esi - ext4_extent
|
||
;цикл по экстентам
|
||
@@:
|
||
test ebx, ebx
|
||
jz .fail ;ни один узел не подошел - ошибка
|
||
|
||
mov edx, [esi + EXT4_EXTENT.ee_block]
|
||
cmp ecx, edx
|
||
jb .fail ;если меньше, значит он был в предыдущих блоках -> ошибка
|
||
|
||
movzx edi, [esi + EXT4_EXTENT.ee_len]
|
||
add edx, edi
|
||
cmp ecx, edx
|
||
jb .end_search_extent ;нашли нужный блок
|
||
|
||
add esi, sizeof.EXT4_EXTENT
|
||
dec ebx
|
||
jmp @B
|
||
|
||
.end_search_extent:
|
||
mov edx, [esi + EXT4_EXTENT.ee_start_lo]
|
||
sub ecx, [esi + EXT4_EXTENT.ee_block] ;разница в ext4 блоках
|
||
add ecx, edx
|
||
xor eax, eax
|
||
ret
|
||
|
||
.fail:
|
||
mov eax, ERROR_FS_FAIL
|
||
ret
|
||
|
||
;===================================================================
|
||
;получает адрес ext2 блока из inode с определнным номером
|
||
;RUS: in: ecx = номер блока в inode (0..) ;ENG: in: ecx = number of block in inode (0..)
|
||
;RUS: esi = адрес inode ;ENG: esi = inode address
|
||
;RUS: ebp = указатель на структуру EXTFS;ENG: ebp = pointer to EXTFS
|
||
;RUS: out: ecx = адрес очередного блока ;ENG: out: ecx = next block address
|
||
;RUS: eax - error code ;ENG: eax - error code
|
||
ext2_get_inode_block:
|
||
test [esi + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL
|
||
jz @F
|
||
|
||
pushad
|
||
add esi, EXT2_INODE_STRUC.i_block ;esi - extent_header
|
||
call ext4_block_recursive_search
|
||
mov PUSHAD_ECX, ecx
|
||
mov PUSHAD_EAX, eax
|
||
popad
|
||
ret
|
||
|
||
@@:
|
||
cmp ecx, 12 ; 0..11 - direct block address
|
||
jb .get_direct_block
|
||
|
||
sub ecx, 12
|
||
cmp ecx, [ebp+EXTFS.count_pointer_in_block] ; 12.. - indirect blocks
|
||
jb .get_indirect_block
|
||
|
||
sub ecx, [ebp+EXTFS.count_pointer_in_block]
|
||
cmp ecx, [ebp+EXTFS.count_pointer_in_block_square]
|
||
jb .get_double_indirect_block
|
||
|
||
sub ecx, [ebp+EXTFS.count_pointer_in_block_square]
|
||
;triple indirect block
|
||
push edx ebx
|
||
|
||
mov eax, [esi + EXT2_INODE_STRUC.i_block + 14*4]
|
||
mov ebx, [ebp+EXTFS.ext2_temp_block]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .fail
|
||
|
||
xor edx, edx
|
||
mov eax, ecx
|
||
div [ebp+EXTFS.count_pointer_in_block_square]
|
||
|
||
;RUS: eax - номер в полученном блоке edx - номер дальше
|
||
;ENG: eax - current block number, edx - next block number
|
||
mov eax, [ebx + eax*4]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .fail
|
||
|
||
mov eax, edx
|
||
jmp @F
|
||
|
||
.get_double_indirect_block:
|
||
push edx ebx
|
||
|
||
mov eax, [esi + EXT2_INODE_STRUC.i_block + 13*4]
|
||
mov ebx, [ebp+EXTFS.ext2_temp_block]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .fail
|
||
|
||
mov eax, ecx
|
||
@@:
|
||
xor edx, edx
|
||
div [ebp+EXTFS.count_pointer_in_block]
|
||
|
||
mov eax, [ebx + eax*4]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .fail
|
||
|
||
mov ecx, [ebx + edx*4]
|
||
.fail:
|
||
pop ebx edx
|
||
ret
|
||
|
||
.get_indirect_block:
|
||
push ebx
|
||
mov eax, [esi + EXT2_INODE_STRUC.i_block + 12*4]
|
||
mov ebx, [ebp+EXTFS.ext2_temp_block]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz @F ;RUS: если не было ошибки ;ENG: if there was no error
|
||
|
||
mov ecx, [ebx + ecx*4] ;RUS: заносим результат ;ENG: ???
|
||
@@:
|
||
pop ebx
|
||
ret
|
||
|
||
.get_direct_block:
|
||
mov ecx, [esi + EXT2_INODE_STRUC.i_block + ecx*4]
|
||
xor eax, eax
|
||
ret
|
||
|
||
;===================================================================
|
||
;get content inode by num
|
||
;in: eax = inode_num
|
||
; ebx = address of inode content
|
||
; ebp = pointer to EXTFS
|
||
;out: eax - error code
|
||
ext2_get_inode:
|
||
pushad
|
||
mov edi, ebx ;сохраним адрес inode
|
||
dec eax
|
||
xor edx, edx
|
||
|
||
div [ebp + EXT2_SB_STRUC.inodes_per_group + EXTFS.superblock]
|
||
|
||
push edx ;locale num in group
|
||
|
||
mov edx, 32
|
||
mul edx ; address block_group in global_desc_table
|
||
|
||
;RUS: в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы
|
||
;RUS: найдем блок в котором он находится
|
||
;ENG: in eax - inode group offset relative to global descriptor table start
|
||
;ENG: let's find the block this inode is in
|
||
div [ebp+EXTFS.block_size]
|
||
add eax, [ebp + EXT2_SB_STRUC.first_data_block + EXTFS.superblock]
|
||
inc eax
|
||
mov ebx, [ebp+EXTFS.ext2_temp_block]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .fail
|
||
|
||
add ebx, edx ;RUS: локальный номер в блоке ;ENG: local number inside block
|
||
mov eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table] ;RUS: номер блока - в терминах ext2
|
||
;ENG: block number - in ext2 terms
|
||
mov ecx, [ebp+EXTFS.log_block_size]
|
||
shl eax, cl
|
||
;RUS: eax - указывает на таблицу inode-ов на hdd ;ENG: eax - points to inode table on HDD
|
||
mov esi, eax ;RUS: сохраним его пока в esi ;ENG: let's save it in esi for now
|
||
|
||
;RUS: прибавим локальный адрес inode-а ;ENG: add local address of inode
|
||
pop eax ; index
|
||
mov ecx, [ebp+EXTFS.inode_size]
|
||
mul ecx ; (index * inode_size)
|
||
;RUS: поделим на размер блока ;ENG: divide by block size
|
||
mov ecx, eax
|
||
and ecx, 512 - 1
|
||
shrd eax, edx, 9
|
||
|
||
add eax, esi ;RUS: нашли адрес блока для чтения ;ENG: found block address to read
|
||
mov ebx, [ebp+EXTFS.ext2_temp_block]
|
||
call fs_read32_sys
|
||
test eax, eax
|
||
jnz .fail
|
||
|
||
mov esi, ecx ;RUS: добавим "остаток" ;ENG: add the "remainder"
|
||
mov ecx, [ebp+EXTFS.inode_size]
|
||
add esi, ebx ;RUS: к адресу ;ENG: to the address
|
||
rep movsb ;RUS: копируем inode ;ENG: copy inode
|
||
xor eax, eax
|
||
.fail:
|
||
mov PUSHAD_EAX, eax
|
||
popad
|
||
ret
|
||
|
||
;----------------------------------------------------------------
|
||
; ext2_ReadFolder - EXT2FS implementation of reading a folder
|
||
; in: ebp = pointer to EXTFS structure
|
||
; in: esi+[esp+4] = name
|
||
; in: ebx = pointer to parameters from sysfunc 70
|
||
; out: eax, ebx = return values for sysfunc 70
|
||
;----------------------------------------------------------------
|
||
ext2_ReadFolder:
|
||
call ext2_lock
|
||
cmp byte [esi], 0
|
||
jz .root_folder
|
||
|
||
push ebx
|
||
stdcall ext2_find_lfn, [esp+4+4] ;вернет в esi адрес inode
|
||
pop ebx
|
||
test eax, eax
|
||
jnz .error_ret
|
||
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
|
||
jz .error_not_found
|
||
jmp @F
|
||
|
||
.root_folder:
|
||
mov esi, [ebp+EXTFS.root_inode]
|
||
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
|
||
jz .error_root
|
||
;придется копировать inode
|
||
mov edi, [ebp+EXTFS.ext2_save_inode]
|
||
mov ecx, [ebp+EXTFS.inode_size]
|
||
shr ecx, 2
|
||
push edi
|
||
rep movsd
|
||
pop esi
|
||
@@:
|
||
cmp [esi + EXT2_INODE_STRUC.i_size], 0 ;папка пуста
|
||
je .error_empty_dir
|
||
|
||
mov edx, [ebx + 16]
|
||
push edx ;адрес результата [edi + 28]
|
||
push 0 ;конец очередного блока папки [edi + 24]
|
||
push dword [ebx +12];сколько файлов нужно прочитать [edi + 20]
|
||
push dword [ebx + 4];первый "нужный" файл [edi + 16]
|
||
push dword [ebx + 8];флаги [edi + 12]
|
||
push 0 ;[EXT2_read_in_folder] [edi + 8]
|
||
push 0 ;[EXT2_files_in_folder] [edi + 4]
|
||
push 0 ;номер блока по порядку [edi]
|
||
|
||
mov edi, edx
|
||
mov ecx, 32/4
|
||
rep stosd ; fill header zero
|
||
|
||
mov edi, esp ; edi - указатель на локальные переменные
|
||
add edx, 32 ; edx = current mem for return
|
||
|
||
xor ecx, ecx ; получим номер первого блока
|
||
call ext2_get_inode_block
|
||
test eax, eax
|
||
jnz .error_get_block
|
||
|
||
mov eax, ecx
|
||
mov ebx, [ebp+EXTFS.ext2_save_block]
|
||
call ext2_get_block ; и считываем блок с hdd
|
||
test eax, eax
|
||
jnz .error_get_block
|
||
|
||
mov eax, ebx ; ebx = current dir record
|
||
add eax, [ebp+EXTFS.block_size]
|
||
mov [edi + 24], eax ; запомним конец очередного блока
|
||
|
||
mov ecx, [edi + 16] ; ecx = first wanted (flags ommited)
|
||
|
||
.find_wanted_start:
|
||
jecxz .find_wanted_end
|
||
.find_wanted_cycle:
|
||
cmp [ebx + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
|
||
jz @F
|
||
inc dword [edi + 4] ; EXT2_files_in_folder
|
||
dec ecx
|
||
@@:
|
||
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
|
||
|
||
cmp eax, 12 ; минимальная длина записи
|
||
jb .error_bad_len
|
||
test eax, 0x3 ; длина записи должна делиться на 4
|
||
jnz .error_bad_len
|
||
|
||
sub [esi + EXT2_INODE_STRUC.i_size], eax ;вычитаем напрямую из структуры inode
|
||
add ebx, eax ; к следующей записи
|
||
cmp ebx, [edi + 24] ; сравниваем с концом блока
|
||
jb .find_wanted_start
|
||
|
||
push .find_wanted_start
|
||
.end_block: ;вылетели из цикла
|
||
cmp [esi + EXT2_INODE_STRUC.i_size], 0
|
||
jle .end_dir
|
||
|
||
inc dword [edi] ;получаем новый блок
|
||
push ecx
|
||
mov ecx, [edi]
|
||
call ext2_get_inode_block
|
||
test eax, eax
|
||
jnz .error_get_block
|
||
|
||
mov eax, ecx
|
||
mov ebx, [ebp+EXTFS.ext2_save_block]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .error_get_block
|
||
|
||
pop ecx
|
||
mov eax, ebx
|
||
add eax, [ebp+EXTFS.block_size]
|
||
mov [edi + 24], eax ;запомним конец блока
|
||
ret ; опять в цикл
|
||
|
||
.wanted_end:
|
||
loop .find_wanted_cycle ; ecx 0 => -1 нужно посчитать сколько файлов
|
||
|
||
;дошли до первого "нужного" файла
|
||
.find_wanted_end:
|
||
mov ecx, [edi + 20]
|
||
.wanted_start: ; ищем first_wanted+count
|
||
jecxz .wanted_end
|
||
cmp [ebx + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used
|
||
jz .empty_rec
|
||
inc dword [edi + 8]
|
||
inc dword [edi + 4]
|
||
|
||
push edi ecx
|
||
mov edi, edx ;обнуляем место под очереное имя файла/папки
|
||
xor eax, eax
|
||
mov ecx, 40 / 4
|
||
rep stosd
|
||
pop ecx edi
|
||
|
||
push ebx edi edx
|
||
mov eax, [ebx + EXT2_DIR_STRUC.inode] ;получим дочерний inode
|
||
mov ebx, [ebp+EXTFS.ext2_temp_inode]
|
||
call ext2_get_inode
|
||
test eax, eax
|
||
jnz .error_read_subinode
|
||
|
||
lea edi, [edx + 8]
|
||
|
||
mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; переведем время в ntfs формат
|
||
xor edx, edx
|
||
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600
|
||
adc edx, 2
|
||
call ntfs_datetime_to_bdfe.sec
|
||
|
||
mov eax, [ebx + EXT2_INODE_STRUC.i_atime]
|
||
xor edx, edx
|
||
add eax, 3054539008
|
||
adc edx, 2
|
||
call ntfs_datetime_to_bdfe.sec
|
||
|
||
mov eax, [ebx + EXT2_INODE_STRUC.i_mtime]
|
||
xor edx, edx
|
||
add eax, 3054539008
|
||
adc edx, 2
|
||
call ntfs_datetime_to_bdfe.sec
|
||
|
||
pop edx ; пока достаем только буфер
|
||
test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; для папки размер
|
||
jnz @F ; не возвращаем
|
||
|
||
mov eax, [ebx + EXT2_INODE_STRUC.i_size] ;low size
|
||
stosd
|
||
mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size
|
||
stosd
|
||
xor dword [edx], FS_FT_DIR ;помечаем, что это файл(2 раза xor)
|
||
@@:
|
||
xor dword [edx], FS_FT_DIR ;помечаем, что это файл
|
||
|
||
;теперь скопируем имя, сконвертировав из UTF-8 в CP866
|
||
push ecx esi ;edi уже сохранен в стеке
|
||
mov esi, [esp+12]
|
||
movzx ecx, [esi + EXT2_DIR_STRUC.name_len]
|
||
lea edi, [edx + 40]
|
||
lea esi, [esi + EXT2_DIR_STRUC.name]
|
||
call utf8_to_cp866
|
||
and byte [edi], 0
|
||
pop esi ecx edi ebx
|
||
|
||
cmp byte [edx + 40], '.' ; в linux файл, начинающийся с точки - скрытый
|
||
jne @F
|
||
or dword [edx], FS_FT_HIDDEN
|
||
@@:
|
||
|
||
add edx, 40 + 264 ; go to next record
|
||
dec ecx ; если запись пустая ecx не надо уменьшать
|
||
.empty_rec:
|
||
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
|
||
cmp eax, 12 ; минимальная длина записи
|
||
jb .error_bad_len
|
||
test eax, 0x3 ; длина записи должна делиться на 4
|
||
jnz .error_bad_len
|
||
|
||
sub [esi + EXT2_INODE_STRUC.i_size], eax ;вычитаем напрямую из структуры inode
|
||
add ebx, eax
|
||
cmp ebx, [edi + 24] ;дошли ли до конца блока?
|
||
jb .wanted_start
|
||
|
||
push .wanted_start ; дошли
|
||
jmp .end_block
|
||
|
||
.end_dir: ;конец папки, когда еще не дошли до нужного файла
|
||
call ext2_unlock
|
||
mov edx, [edi + 28] ;адрес структуры результата
|
||
mov ebx, [edi + 8] ;EXT2_read_in_folder
|
||
mov ecx, [edi + 4] ;EXT2_files_in_folder
|
||
mov dword [edx], 1 ;version
|
||
mov [edx + 4], ebx
|
||
mov [edx + 8], ecx
|
||
|
||
lea esp, [edi + 32]
|
||
|
||
xor eax, eax ;RUS: зарезервировано: нули в текущей реализации
|
||
;ENG: reserved: zeros in current implementation
|
||
lea edi, [edx + 12]
|
||
mov ecx, 20 / 4
|
||
rep stosd
|
||
ret
|
||
|
||
.error_bad_len:
|
||
mov eax, ERROR_FS_FAIL
|
||
.error_read_subinode:
|
||
.error_get_block:
|
||
lea esp, [edi + 32]
|
||
.error_ret:
|
||
or ebx, -1
|
||
push eax
|
||
call ext2_unlock
|
||
pop eax
|
||
ret
|
||
|
||
.error_empty_dir: ;RUS: inode папки без блоков ;ENG: inode of folder without blocks
|
||
.error_root: ;RUS: root - не папка ;ENG: root is not a folder
|
||
mov eax, ERROR_FS_FAIL
|
||
jmp .error_ret
|
||
|
||
.error_not_found: ;RUS: файл не найден ;ENG: file not found
|
||
mov eax, ERROR_FILE_NOT_FOUND
|
||
jmp .error_ret
|
||
|
||
;============================================
|
||
;convert UTF-8 string to ASCII-string (codepage 866)
|
||
;in: ecx = length source
|
||
; esi = source
|
||
; edi = buffer
|
||
; destroys: eax,esi,edi
|
||
utf8_to_cp866:
|
||
jecxz .ret
|
||
.start:
|
||
lodsw
|
||
cmp al, 0x80
|
||
jb .ascii
|
||
|
||
xchg al, ah ; big-endian
|
||
cmp ax, 0xd080
|
||
jz .yo1
|
||
cmp ax, 0xd191
|
||
jz .yo2
|
||
cmp ax, 0xd090
|
||
jb .unk
|
||
cmp ax, 0xd180
|
||
jb .rus1
|
||
cmp ax, 0xd190
|
||
jb .rus2
|
||
.unk:
|
||
mov al, '_'
|
||
jmp .doit
|
||
.yo1:
|
||
mov al, 0xf0 ; Ё capital
|
||
jmp .doit
|
||
.yo2:
|
||
mov al, 0xf1 ; ё small
|
||
jmp .doit
|
||
.rus1:
|
||
sub ax, 0xd090 - 0x80
|
||
jmp .doit
|
||
.rus2:
|
||
sub ax, 0xd18f - 0xEF
|
||
.doit:
|
||
stosb
|
||
sub ecx, 2
|
||
ja .start
|
||
ret
|
||
|
||
.ascii:
|
||
stosb
|
||
dec esi
|
||
dec ecx
|
||
jnz .start
|
||
.ret:
|
||
ret
|
||
|
||
;----------------------------------------------------------------
|
||
; ext2_Read - EXT2FS implementation of reading a file
|
||
; in: ebp = pointer to FAT structure
|
||
; in: esi+[esp+4] = name
|
||
; in: ebx = pointer to parameters from sysfunc 70
|
||
; out: eax, ebx = return values for sysfunc 70
|
||
;----------------------------------------------------------------
|
||
ext2_Read:
|
||
call ext2_lock
|
||
cmp byte [esi], 0
|
||
jnz @F
|
||
|
||
.this_is_nofile:
|
||
call ext2_unlock
|
||
or ebx, -1
|
||
mov eax, ERROR_ACCESS_DENIED
|
||
ret
|
||
|
||
@@:
|
||
push ebx
|
||
stdcall ext2_find_lfn, [esp+4+4]
|
||
pop ebx
|
||
test eax, eax
|
||
jz @F
|
||
|
||
call ext2_unlock
|
||
or ebx, -1
|
||
mov eax, ERROR_FILE_NOT_FOUND
|
||
ret
|
||
|
||
@@:
|
||
mov ax, [esi + EXT2_INODE_STRUC.i_mode]
|
||
and ax, EXT2_S_IFMT ;оставляем только тип inode в ax
|
||
cmp ax, EXT2_S_IFREG
|
||
jne .this_is_nofile
|
||
|
||
mov edi, [ebx+16] ; edi = pointer to return mem
|
||
mov ecx, [ebx+12]
|
||
|
||
mov eax, [ebx+4]
|
||
mov edx, [ebx+8] ;RUS: edx : eax - стартовый номер байта ;ENG: edx : eax - start byte number
|
||
|
||
;RUS: ///// сравним хватит ли нам файла или нет ;ENG: ///// check if file is big enough for us
|
||
cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx
|
||
ja .size_great
|
||
jb .size_less
|
||
|
||
cmp [esi + EXT2_INODE_STRUC.i_size], eax
|
||
ja .size_great
|
||
|
||
.size_less:
|
||
call ext2_unlock
|
||
xor ebx, ebx
|
||
mov eax, ERROR_END_OF_FILE
|
||
ret
|
||
|
||
.size_great:
|
||
add eax, ecx ;RUS: add to first_wanted кол-во байт для чтения
|
||
;ENG: add to first_wanted number of bytes to read
|
||
adc edx, 0
|
||
|
||
cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx
|
||
ja .size_great_great
|
||
jb .size_great_less
|
||
cmp [esi + EXT2_INODE_STRUC.i_size], eax
|
||
jae .size_great_great ; and if it's equal, no matter where we jump
|
||
|
||
.size_great_less:
|
||
push 1 ;RUS: читаем по границе размера ;ENG: reading till the end of file
|
||
mov ecx, [esi + EXT2_INODE_STRUC.i_size]
|
||
sub ecx, [ebx+4] ;RUS: (размер - старт) = сколько читать ;ENG: to read = (size - start)
|
||
jmp @F
|
||
|
||
.size_great_great:
|
||
push 0 ;RUS: читаем столько, сколько запросили ;ENG: reading as much as requested
|
||
|
||
@@:
|
||
;здесь мы точно знаем сколько байт читать - ecx
|
||
;edi - return memory
|
||
;esi -> first wanted
|
||
|
||
push ecx ;количество считанных байт
|
||
|
||
;получим кусок из первого блока
|
||
mov edx, [ebx+8]
|
||
mov eax, [ebx+4]
|
||
div [ebp+EXTFS.block_size]
|
||
|
||
push eax ;счетчик блоков ложим в стек
|
||
|
||
push ecx
|
||
mov ecx, eax
|
||
call ext2_get_inode_block
|
||
test eax, eax
|
||
jnz .error_at_first_block
|
||
mov ebx, [ebp+EXTFS.ext2_save_block]
|
||
mov eax, ecx
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .error_at_first_block
|
||
pop ecx
|
||
add ebx, edx
|
||
|
||
neg edx
|
||
add edx, [ebp+EXTFS.block_size] ;RUS: block_size - стартовый байт = сколько байт 1-го блока
|
||
;ENG: block_size - start byte = number of bytes in 1st block
|
||
cmp ecx, edx
|
||
jbe .only_one_block
|
||
|
||
mov eax, ecx
|
||
sub eax, edx
|
||
mov ecx, edx
|
||
|
||
push esi
|
||
mov esi, ebx
|
||
rep movsb ;RUS: кусок 1-го блока ;ENG: part of 1st block
|
||
pop esi
|
||
|
||
;теперь в eax кол-во оставшихся байт для чтения
|
||
.calc_blocks_count:
|
||
mov ebx, edi ;чтение блока прям в ->ebx
|
||
xor edx, edx
|
||
div [ebp+EXTFS.block_size] ;кол-во байт в последнем блоке (остаток) в edx
|
||
mov edi, eax ;кол-во целых блоков в edi
|
||
@@:
|
||
test edi, edi
|
||
jz .finish_block
|
||
inc dword [esp]
|
||
mov ecx, [esp]
|
||
call ext2_get_inode_block
|
||
test eax, eax
|
||
jnz .error_at_read_cycle
|
||
|
||
mov eax, ecx ;а ebx уже забит нужным значением
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .error_at_read_cycle
|
||
add ebx, [ebp+EXTFS.block_size]
|
||
|
||
dec edi
|
||
jmp @B
|
||
|
||
.finish_block: ;в edx - кол-во байт в последнем блоке
|
||
test edx, edx
|
||
jz .end_read
|
||
|
||
pop ecx ;счетчик блоков -> ecx
|
||
inc ecx
|
||
call ext2_get_inode_block
|
||
test eax, eax
|
||
jnz .error_at_finish_block
|
||
|
||
mov edi, ebx
|
||
mov eax, ecx
|
||
mov ebx, [ebp+EXTFS.ext2_save_block]
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .error_at_finish_block
|
||
|
||
mov ecx, edx
|
||
mov esi, ebx
|
||
rep movsb ;кусок last блока
|
||
jmp @F
|
||
|
||
.end_read:
|
||
pop ecx ;счетчик блоков, который хранился в стеке
|
||
@@:
|
||
pop ebx ;количество считанных байт
|
||
call ext2_unlock
|
||
pop eax ; 1 или 0 - достигли ли конца файла
|
||
test eax, eax
|
||
jz @F
|
||
|
||
mov eax, ERROR_END_OF_FILE
|
||
ret
|
||
@@:
|
||
xor eax, eax
|
||
ret
|
||
|
||
.only_one_block:
|
||
mov esi, ebx
|
||
rep movsb ;кусок last блока
|
||
jmp .end_read
|
||
|
||
.error_at_first_block:
|
||
pop edx
|
||
.error_at_read_cycle:
|
||
pop ebx
|
||
.error_at_finish_block:
|
||
pop ecx edx
|
||
or ebx, -1
|
||
push eax
|
||
call ext2_unlock
|
||
pop eax
|
||
ret
|
||
|
||
;----------------------------------------------------------------
|
||
; in: esi = file path
|
||
; ebx = pointer to dir block
|
||
; ebp = pointer to EXTFS structure
|
||
; out: esi - name without parent or not_changed
|
||
; ebx - dir_rec of inode children
|
||
ext2_test_block_by_name:
|
||
sub esp, 256 ;EXT2_filename
|
||
mov edx, ebx
|
||
add edx, [ebp+EXTFS.block_size] ;RUS: запомним конец блока ;ENG: save block end
|
||
|
||
.start_rec:
|
||
cmp [ebx + EXT2_DIR_STRUC.inode], 0
|
||
jz .next_rec
|
||
|
||
mov edi, esp
|
||
push esi
|
||
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len]
|
||
lea esi, [ebx + EXT2_DIR_STRUC.name]
|
||
call utf8_to_cp866
|
||
|
||
mov ecx, edi
|
||
lea edi, [esp + 4]
|
||
sub ecx, edi ;RUS: кол-во байт в получившейся строке ;ENG: number of bytes in resulting string
|
||
|
||
mov esi, [esp]
|
||
@@:
|
||
jecxz .test_find
|
||
dec ecx
|
||
|
||
lodsb
|
||
call char_toupper
|
||
|
||
mov ah, [edi]
|
||
inc edi
|
||
xchg al, ah
|
||
call char_toupper
|
||
cmp al, ah
|
||
je @B
|
||
@@: ;RUS: не подошло ;ENG: didn't fit
|
||
pop esi
|
||
.next_rec:
|
||
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
|
||
add ebx, eax ;RUS: к след. записи ;ENG: go to next record
|
||
cmp ebx, edx ;RUS: проверим конец ли ;ENG: check if this is the end
|
||
jb .start_rec
|
||
add esp, 256
|
||
ret
|
||
|
||
.test_find:
|
||
cmp byte [esi], 0
|
||
je .ret ;RUS: нашли конец ;ENG: the end reached
|
||
cmp byte [esi], '/'
|
||
jne @B
|
||
inc esi
|
||
.ret:
|
||
add esp, 256 + 4
|
||
ret
|
||
|
||
;========================
|
||
;Ищет inode по строке пути
|
||
;in: esi+[esp+4] = name
|
||
; ebp = pointer to EXTFS
|
||
;out: eax - error code
|
||
; esi = inode
|
||
; dl - первый байт из имени файла/папки
|
||
ext2_find_lfn:
|
||
mov edx, [ebp+EXTFS.root_inode]
|
||
cmp [edx + EXT2_INODE_STRUC.i_blocks], 0
|
||
je .error_empty_root
|
||
|
||
.next_path_part:
|
||
push [edx + EXT2_INODE_STRUC.i_blocks]
|
||
xor ecx, ecx
|
||
.folder_block_cycle:
|
||
push ecx
|
||
xchg esi, edx
|
||
call ext2_get_inode_block
|
||
xchg esi, edx
|
||
test eax, eax
|
||
jnz .error_get_inode_block
|
||
|
||
mov eax, ecx
|
||
mov ebx, [ebp+EXTFS.ext2_save_block] ;ebx = cur dir record
|
||
call ext2_get_block
|
||
test eax, eax
|
||
jnz .error_get_block
|
||
|
||
push esi
|
||
push edx
|
||
call ext2_test_block_by_name
|
||
pop edx
|
||
pop edi ecx
|
||
|
||
cmp edi, esi ;RUS: нашли имя? ;ENG: did we find a name?
|
||
je .next_folder_block ;RUS: не нашли -> к след. блоку ;ENG: we didn't -> moving to next block
|
||
|
||
cmp byte [esi], 0 ;RUS: дошли до "конца" пути -> возваращаемся
|
||
;ENG: reached the "end" of path -> returning
|
||
jnz @f
|
||
cmp dword [esp+8], 0
|
||
jz .get_inode_ret
|
||
mov esi, [esp+8]
|
||
mov dword [esp+8], 0
|
||
@@:
|
||
|
||
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR ;RUS: нашли, но это не папка
|
||
jne .not_found ;ENG: found, but it's not a folder
|
||
|
||
mov eax, [ebx + EXT2_DIR_STRUC.inode]
|
||
mov ebx, [ebp+EXTFS.ext2_save_inode] ;RUS: все же папка. ;ENG: it's a folder afterall
|
||
call ext2_get_inode
|
||
test eax, eax
|
||
jnz .error_get_inode
|
||
pop ecx ;RUS: в стеке лежит кол-во блоков ;ENG: stack top contains number of blocks
|
||
mov edx, ebx
|
||
jmp .next_path_part
|
||
|
||
.next_folder_block:
|
||
;к следующему блоку в текущей папке
|
||
pop eax ;RUS: счетчик блоков ;ENG: blocks counter
|
||
sub eax, [ebp+EXTFS.count_block_in_block]
|
||
jle .not_found
|
||
|
||
push eax
|
||
inc ecx
|
||
jmp .folder_block_cycle
|
||
|
||
.not_found:
|
||
mov eax, ERROR_FILE_NOT_FOUND
|
||
ret 4
|
||
|
||
.get_inode_ret:
|
||
pop ecx ;RUS: в стеке лежит кол-во блоков ;ENG: stack top contains number of blocks
|
||
mov dl, [ebx + EXT2_DIR_STRUC.name] ;RUS: в dl - первый символ () ;ENG: ???
|
||
mov eax, [ebx + EXT2_DIR_STRUC.inode]
|
||
mov ebx, [ebp+EXTFS.ext2_save_inode]
|
||
call ext2_get_inode
|
||
mov esi, ebx
|
||
xor eax, eax
|
||
ret 4
|
||
|
||
.error_get_inode_block:
|
||
.error_get_block:
|
||
pop ecx
|
||
.error_get_inode:
|
||
pop ebx
|
||
.error_empty_root:
|
||
mov eax, ERROR_FS_FAIL
|
||
ret 4
|
||
|
||
;----------------------------------------------------------------
|
||
; ext2_GetFileInfo - EXT2 implementation of getting file info
|
||
; in: ebp = pointer to EXTFS structure
|
||
; in: esi+[esp+4] = name
|
||
; in: ebx = pointer to parameters from sysfunc 70
|
||
; out: eax, ebx = return values for sysfunc 70
|
||
;----------------------------------------------------------------
|
||
ext2_GetFileInfo:
|
||
call ext2_lock
|
||
mov edx, [ebx+16]
|
||
cmp byte [esi], 0
|
||
jz .is_root
|
||
|
||
push edx
|
||
stdcall ext2_find_lfn, [esp+4+4]
|
||
mov ebx, edx
|
||
pop edx
|
||
test eax, eax
|
||
jz @F
|
||
push eax
|
||
call ext2_unlock
|
||
pop eax
|
||
ret
|
||
|
||
.is_root:
|
||
xor ebx, ebx ;RUS: root не может быть скрытым ;ENG: root cannot be hidden
|
||
mov esi, [ebp+EXTFS.root_inode]
|
||
@@:
|
||
xor eax, eax
|
||
mov edi, edx
|
||
mov ecx, 40/4
|
||
rep stosd ; fill zero
|
||
|
||
cmp bl, '.'
|
||
jne @F
|
||
or dword [edx], FS_FT_HIDDEN
|
||
@@:
|
||
|
||
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR
|
||
jnz @F
|
||
mov eax, [esi + EXT2_INODE_STRUC.i_size] ;low size
|
||
mov ebx, [esi + EXT2_INODE_STRUC.i_dir_acl] ;high size
|
||
mov dword [edx+32], eax
|
||
mov dword [edx+36], ebx
|
||
xor dword [edx], FS_FT_DIR
|
||
@@:
|
||
xor dword [edx], FS_FT_DIR
|
||
|
||
lea edi, [edx + 8]
|
||
mov eax, [esi + EXT2_INODE_STRUC.i_ctime]
|
||
xor edx, edx
|
||
add eax, 3054539008
|
||
adc edx, 2
|
||
call ntfs_datetime_to_bdfe.sec
|
||
|
||
mov eax, [esi + EXT2_INODE_STRUC.i_atime]
|
||
xor edx, edx
|
||
add eax, 3054539008
|
||
adc edx, 2
|
||
call ntfs_datetime_to_bdfe.sec
|
||
|
||
mov eax, [esi + EXT2_INODE_STRUC.i_mtime]
|
||
xor edx, edx
|
||
add eax, 3054539008
|
||
adc edx, 2
|
||
call ntfs_datetime_to_bdfe.sec
|
||
|
||
call ext2_unlock
|
||
xor eax, eax
|
||
ret
|
||
|
||
ext2_Rewrite:
|
||
ext2_Write:
|
||
ext2_SetFileEnd:
|
||
ext2_SetFileInfo:
|
||
ext2_Delete:
|
||
ext2_CreateFolder:
|
||
xor ebx, ebx
|
||
mov eax, ERROR_UNSUPPORTED_FS
|
||
ret
|