/kernel/trunk/fs/part_set.inc |
---|
File deleted |
Property changes: |
Deleted: svn:eol-style |
-native |
\ No newline at end of property |
Deleted: svn:keywords |
-Rev |
\ No newline at end of property |
/kernel/trunk/fs/ext2.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;; |
;; 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 ;; |
177,14 → 177,50 |
ei_unused dw ? ;RUS: зарезервировано ;ENG: reserved |
ends |
ext2_test_superblock: |
cmp [fs_type], 0x83 |
jne .no |
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 |
mov eax, [PARTITION_START] |
add eax, 2 ;superblock start at 1024b |
call hd_read |
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 |
198,27 → 234,41 |
test eax, EXT2_FEATURE_INCOMPAT_FILETYPE |
jz .no |
test eax, not EXT4_FEATURE_INCOMPAT_SUPP |
jnz .no |
jz ext2_setup |
; OK, this is correct EXT2 superblock |
clc |
ret |
.no: |
; No, this superblock isn't EXT2 |
stc |
pop ebx |
xor eax, eax |
ret |
; OK, this is correct EXT2 superblock |
ext2_setup: |
mov [fs_type], 2 |
movi eax, sizeof.EXTFS |
call malloc |
test eax, eax |
jz ext2_create_partition.no |
push 512 |
call kernel_alloc ; mem for superblock |
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 |
mov ebp, eax |
lea ecx, [eax+EXTFS.Lock] |
call mutex_init |
mov esi, ebx |
mov edi, eax |
lea edi, [ebp+EXTFS.superblock] |
mov ecx, 512/4 |
rep movsd ; copy sb to reserved mem |
mov ebx, eax |
mov [ext2_data.sb], eax |
mov eax, [ebx + EXT2_SB_STRUC.blocks_count] |
sub eax, [ebx + EXT2_SB_STRUC.first_data_block] |
226,72 → 276,103 |
xor edx, edx |
div [ebx + EXT2_SB_STRUC.blocks_per_group] |
inc eax |
mov [ext2_data.groups_count], eax |
mov [ebp+EXTFS.groups_count], eax |
mov ecx, [ebx + EXT2_SB_STRUC.log_block_size] |
inc ecx |
mov [ext2_data.log_block_size], ecx ; 1, 2, 3, 4 equ 1kb, 2kb, 4kb, 8kb |
mov [ebp+EXTFS.log_block_size], ecx ; 1, 2, 3, 4 equ 1kb, 2kb, 4kb, 8kb |
mov eax, 1 |
shl eax, cl |
mov [ext2_data.count_block_in_block], eax |
mov [ebp+EXTFS.count_block_in_block], eax |
shl eax, 7 |
mov [ext2_data.count_pointer_in_block], eax |
mov [ebp+EXTFS.count_pointer_in_block], eax |
mov edx, eax ;RUS: потом еще квадрат найдем ;ENG: we'll find a square later |
shl eax, 2 |
mov [ext2_data.block_size], eax |
mov [ebp+EXTFS.block_size], eax |
push eax eax ; 2 kernel_alloc |
mov eax, edx |
mul edx |
mov [ext2_data.count_pointer_in_block_square], eax |
mov [ebp+EXTFS.count_pointer_in_block_square], eax |
call kernel_alloc |
mov [ext2_data.ext2_save_block], eax ; and for temp block |
mov [ebp+EXTFS.ext2_save_block], eax ; and for temp block |
call kernel_alloc |
mov [ext2_data.ext2_temp_block], eax ; and for get_inode proc |
mov [ebp+EXTFS.ext2_temp_block], eax ; and for get_inode proc |
movzx ebp, word [ebx + EXT2_SB_STRUC.inode_size] |
movzx eax, word [ebx + EXT2_SB_STRUC.inode_size] |
mov ecx, [ebx + EXT2_SB_STRUC.blocks_per_group] |
mov [ext2_data.inode_size], ebp |
mov [ext2_data.blocks_per_group], ecx |
mov [ebp+EXTFS.inode_size], eax |
mov [ebp+EXTFS.blocks_per_group], ecx |
push ebp ebp ebp ;3 kernel_alloc |
push eax eax eax ;3 kernel_alloc |
call kernel_alloc |
mov [ext2_data.ext2_save_inode], eax |
mov [ebp+EXTFS.ext2_save_inode], eax |
call kernel_alloc |
mov [ext2_data.ext2_temp_inode], eax |
mov [ebp+EXTFS.ext2_temp_inode], eax |
call kernel_alloc |
mov [ext2_data.root_inode], eax |
mov [ebp+EXTFS.root_inode], eax |
mov ebx, eax |
mov eax, EXT2_ROOT_INO |
call ext2_get_inode ; read root inode |
jmp return_from_part_set |
mov eax, ebp ; return pointer to EXTFS |
pop 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, [ext2_data.log_block_size] |
mov ecx, [ebp+EXTFS.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] |
mov ecx, [ext2_data.count_block_in_block] |
mov ecx, eax |
push [ebp+EXTFS.count_block_in_block] |
@@: |
call hd_read |
cmp [hd_error], 0 |
mov eax, ecx |
call fs_read32_sys |
test eax, eax |
jnz .fail |
inc eax |
inc ecx |
add ebx, 512 |
loop @B |
dec dword [esp] |
jnz @B |
pop ecx |
xor eax, eax |
@@: |
pop ecx ebx |
304,16 → 385,17 |
;=================================================================== |
;RUS: получает номер блока из extent inode ;ENG: receives block number from extent inode |
;RUS: in: ecx = номер блока по порядку ;ENG: in: ecx = consecutive block number |
;RUS: ebp = адрес extent header`а ;ENG: ebp = address of extent header |
;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 [ebp + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC |
cmp word [esi + EXT4_EXTENT_HEADER.eh_magic], 0xF30A ;EXT4_EXT_MAGIC |
jne .fail |
movzx ebx, [ebp + EXT4_EXTENT_HEADER.eh_entries] |
add ebp, sizeof.EXT4_EXTENT_HEADER |
cmp word [ebp - sizeof.EXT4_EXTENT_HEADER + EXT4_EXTENT_HEADER.eh_depth], 0 |
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 |
325,48 → 407,48 |
cmp ebx, 1 ;у индексов не хранится длина, |
je .end_search_index ;поэтому, если остался последний - то это нужный |
cmp ecx, [ebp + EXT4_EXTENT_IDX.ei_block] |
cmp ecx, [esi + EXT4_EXTENT_IDX.ei_block] |
jb .fail |
cmp ecx, [ebp + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса |
cmp ecx, [esi + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса |
jb .end_search_index ;следующий дальше - значит текущий, то что нам нужен |
add ebp, sizeof.EXT4_EXTENT_IDX |
add esi, sizeof.EXT4_EXTENT_IDX |
dec ebx |
jmp @B |
.end_search_index: |
;ebp указывает на нужный extent_idx, считываем следующий блок |
mov ebx, [ext2_data.ext2_temp_block] |
mov eax, [ebp + EXT4_EXTENT_IDX.ei_leaf_lo] |
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 ebp, ebx |
mov esi, ebx |
jmp ext4_block_recursive_search ;рекурсивно прыгаем в начало |
.leaf_block: ;листовой блок ebp - ext4_extent |
.leaf_block: ;листовой блок esi - ext4_extent |
;цикл по экстентам |
@@: |
test ebx, ebx |
jz .fail ;ни один узел не подошел - ошибка |
mov edx, [ebp + EXT4_EXTENT.ee_block] |
mov edx, [esi + EXT4_EXTENT.ee_block] |
cmp ecx, edx |
jb .fail ;если меньше, значит он был в предыдущих блоках -> ошибка |
movzx edi, [ebp + EXT4_EXTENT.ee_len] |
movzx edi, [esi + EXT4_EXTENT.ee_len] |
add edx, edi |
cmp ecx, edx |
jb .end_search_extent ;нашли нужный блок |
add ebp, sizeof.EXT4_EXTENT |
add esi, sizeof.EXT4_EXTENT |
dec ebx |
jmp @B |
.end_search_extent: |
mov edx, [ebp + EXT4_EXTENT.ee_start_lo] |
sub ecx, [ebp + EXT4_EXTENT.ee_block] ;разница в ext4 блоках |
mov edx, [esi + EXT4_EXTENT.ee_start_lo] |
sub ecx, [esi + EXT4_EXTENT.ee_block] ;разница в ext4 блоках |
add ecx, edx |
xor eax, eax |
ret |
378,15 → 460,16 |
;=================================================================== |
;получает адрес ext2 блока из inode с определнным номером |
;RUS: in: ecx = номер блока в inode (0..) ;ENG: in: ecx = number of block in inode (0..) |
;RUS: ebp = адрес inode ;ENG: ebp = inode address |
;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 [ebp + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL |
test [esi + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL |
jz @F |
pushad |
add ebp, EXT2_INODE_STRUC.i_block ;ebp - extent_header |
add esi, EXT2_INODE_STRUC.i_block ;esi - extent_header |
call ext4_block_recursive_search |
mov PUSHAD_ECX, ecx |
mov PUSHAD_EAX, eax |
398,19 → 481,19 |
jb .get_direct_block |
sub ecx, 12 |
cmp ecx, [ext2_data.count_pointer_in_block] ; 12.. - indirect blocks |
cmp ecx, [ebp+EXTFS.count_pointer_in_block] ; 12.. - indirect blocks |
jb .get_indirect_block |
sub ecx, [ext2_data.count_pointer_in_block] |
cmp ecx, [ext2_data.count_pointer_in_block_square] |
sub ecx, [ebp+EXTFS.count_pointer_in_block] |
cmp ecx, [ebp+EXTFS.count_pointer_in_block_square] |
jb .get_double_indirect_block |
sub ecx, [ext2_data.count_pointer_in_block_square] |
sub ecx, [ebp+EXTFS.count_pointer_in_block_square] |
;triple indirect block |
push edx ebx |
mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4] |
mov ebx, [ext2_data.ext2_temp_block] |
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 |
417,7 → 500,7 |
xor edx, edx |
mov eax, ecx |
div [ext2_data.count_pointer_in_block_square] |
div [ebp+EXTFS.count_pointer_in_block_square] |
;RUS: eax - номер в полученном блоке edx - номер дальше |
;ENG: eax - current block number, edx - next block number |
432,8 → 515,8 |
.get_double_indirect_block: |
push edx ebx |
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 13*4] |
mov ebx, [ext2_data.ext2_temp_block] |
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 |
441,7 → 524,7 |
mov eax, ecx |
@@: |
xor edx, edx |
div [ext2_data.count_pointer_in_block] |
div [ebp+EXTFS.count_pointer_in_block] |
mov eax, [ebx + eax*4] |
call ext2_get_block |
455,8 → 538,8 |
.get_indirect_block: |
push ebx |
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 12*4] |
mov ebx, [ext2_data.ext2_temp_block] |
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 |
467,7 → 550,7 |
ret |
.get_direct_block: |
mov ecx, [ebp + EXT2_INODE_STRUC.i_block + ecx*4] |
mov ecx, [esi + EXT2_INODE_STRUC.i_block + ecx*4] |
xor eax, eax |
ret |
475,6 → 558,7 |
;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 |
482,8 → 566,7 |
dec eax |
xor edx, edx |
mov ecx, [ext2_data.sb] |
div [ecx + EXT2_SB_STRUC.inodes_per_group] |
div [ebp + EXT2_SB_STRUC.inodes_per_group + EXTFS.superblock] |
push edx ;locale num in group |
494,10 → 577,10 |
;RUS: найдем блок в котором он находится |
;ENG: in eax - inode group offset relative to global descriptor table start |
;ENG: let's find the block this inode is in |
div [ext2_data.block_size] |
add eax, [ecx + EXT2_SB_STRUC.first_data_block] |
div [ebp+EXTFS.block_size] |
add eax, [ebp + EXT2_SB_STRUC.first_data_block + EXTFS.superblock] |
inc eax |
mov ebx, [ext2_data.ext2_temp_block] |
mov ebx, [ebp+EXTFS.ext2_temp_block] |
call ext2_get_block |
test eax, eax |
jnz .fail |
505,27 → 588,28 |
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, [ext2_data.log_block_size] |
mov ecx, [ebp+EXTFS.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] ;RUS: а старт раздела - в терминах hdd (512) |
;ENG: partition start - in HDD terms (512) |
;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, [ext2_data.inode_size] |
mov ecx, [ebp+EXTFS.inode_size] |
mul ecx ; (index * inode_size) |
mov ebp, 512 |
div ebp ;RUS: поделим на размер блока ;ENG: divide by block 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, [ext2_data.ext2_temp_block] |
call hd_read |
cmp [hd_error], 0 |
mov ebx, [ebp+EXTFS.ext2_temp_block] |
call fs_read32_sys |
test eax, eax |
jnz .fail |
mov esi, edx ;RUS: добавим "остаток" ;ENG: add the "remainder" |
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 |
535,55 → 619,47 |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdReadFolder - read disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ext2_HdReadFolder: |
; 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 ecx edx |
call ext2_find_lfn ;вернет в ebp адрес inode |
pop edx ecx ebx |
push ebx |
stdcall ext2_find_lfn, [esp+4+4] ;вернет в esi адрес inode |
pop ebx |
test eax, eax |
jnz .error_ret |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jz .error_not_found |
jmp @F |
.root_folder: |
mov ebp, [ext2_data.root_inode] |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
mov esi, [ebp+EXTFS.root_inode] |
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jz .error_root |
;придется копировать inode |
push ecx |
mov esi, ebp |
mov edi, [ext2_data.ext2_save_inode] |
mov ecx, [ext2_data.inode_size] |
mov edi, [ebp+EXTFS.ext2_save_inode] |
mov ecx, [ebp+EXTFS.inode_size] |
shr ecx, 2 |
mov ebp, edi |
push edi |
rep movsd |
pop ecx |
pop esi |
@@: |
cmp [ebp + EXT2_INODE_STRUC.i_size], 0 ;папка пуста |
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 ecx ;сколько файлов нужно прочитать [edi + 20] |
push dword [ebx] ;первый "нужный" файл [edi + 16] |
push dword [ebx + 4];флаги [edi + 12] |
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] |
601,14 → 677,14 |
jnz .error_get_block |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
mov ebx, [ebp+EXTFS.ext2_save_block] |
call ext2_get_block ; и считываем блок с hdd |
test eax, eax |
jnz .error_get_block |
mov esi, ebx ; esi = current dir record |
add ebx, [ext2_data.block_size] |
mov [edi + 24], ebx ; запомним конец очередного блока |
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) |
615,26 → 691,26 |
.find_wanted_start: |
jecxz .find_wanted_end |
.find_wanted_cycle: |
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
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 ebx, [esi + EXT2_DIR_STRUC.rec_len] |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
cmp eax, 12 ; минимальная длина записи |
jb .error_bad_len |
test ebx, 0x3 ; длина записи должна делиться на 4 |
test eax, 0x3 ; длина записи должна делиться на 4 |
jnz .error_bad_len |
sub [ebp + EXT2_INODE_STRUC.i_size], ebx ;вычитаем напрямую из структуры inode |
add esi, ebx ; к следующей записи |
cmp esi, [edi + 24] ; сравниваем с концом блока |
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 [ebp + EXT2_INODE_STRUC.i_size], 0 |
cmp [esi + EXT2_INODE_STRUC.i_size], 0 |
jle .end_dir |
inc dword [edi] ;получаем новый блок |
645,15 → 721,15 |
jnz .error_get_block |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
mov ebx, [ebp+EXTFS.ext2_save_block] |
call ext2_get_block |
test eax, eax |
jnz .error_get_block |
pop ecx |
mov esi, ebx |
add ebx, [ext2_data.block_size] |
mov [edi + 24], ebx ;запомним конец блока |
mov eax, ebx |
add eax, [ebp+EXTFS.block_size] |
mov [edi + 24], eax ;запомним конец блока |
ret ; опять в цикл |
.wanted_end: |
664,7 → 740,7 |
mov ecx, [edi + 20] |
.wanted_start: ; ищем first_wanted+count |
jecxz .wanted_end |
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz .empty_rec |
inc dword [edi + 8] |
inc dword [edi + 4] |
676,9 → 752,9 |
rep stosd |
pop ecx edi |
push esi edi edx |
mov eax, [esi + EXT2_DIR_STRUC.inode] ;получим дочерний inode |
mov ebx, [ext2_data.ext2_temp_inode] |
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 |
716,13 → 792,14 |
xor dword [edx], FS_FT_DIR ;помечаем, что это файл |
;теперь скопируем имя, сконвертировав из UTF-8 в CP866 |
push ecx ;edi и esi уже сохранены в стеке |
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 ecx edi esi |
pop esi ecx edi ebx |
cmp byte [edx + 40], '.' ; в linux файл, начинающийся с точки - скрытый |
jne @F |
732,15 → 809,15 |
add edx, 40 + 264 ; go to next record |
dec ecx ; если запись пустая ecx не надо уменьшать |
.empty_rec: |
movzx ebx, [esi + EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
cmp eax, 12 ; минимальная длина записи |
jb .error_bad_len |
test ebx, 0x3 ; длина записи должна делиться на 4 |
test eax, 0x3 ; длина записи должна делиться на 4 |
jnz .error_bad_len |
sub [ebp + EXT2_INODE_STRUC.i_size], ebx ;вычитаем напрямую из структуры inode |
add esi, ebx |
cmp esi, [edi + 24] ;дошли ли до конца блока? |
sub [esi + EXT2_INODE_STRUC.i_size], eax ;вычитаем напрямую из структуры inode |
add ebx, eax |
cmp ebx, [edi + 24] ;дошли ли до конца блока? |
jb .wanted_start |
push .wanted_start ; дошли |
747,6 → 824,7 |
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 |
770,6 → 848,9 |
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 |
834,84 → 915,76 |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdRead - read hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
;-------------------------------------------------------------- |
ext2_HdRead: |
; 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 ecx ebx edx |
call ext2_find_lfn |
pop edx ebx ecx |
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, [ebp + EXT2_INODE_STRUC.i_mode] |
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, edx ; edi = pointer to return mem |
mov edi, [ebx+16] ; edi = pointer to return mem |
mov ecx, [ebx+12] |
test ebx, ebx |
jz @F |
mov esi, ebx ; esi = pointer to first_wanted |
mov ebx, [esi+4] |
mov eax, [esi] ;RUS: ebx : eax - стартовый номер байта ;ENG: ebx : eax - start byte number |
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 [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx |
cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx |
ja .size_great |
jb .size_less |
cmp [ebp + EXT2_INODE_STRUC.i_size], eax |
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 |
@@: |
xor ebx, ebx |
xor eax, eax |
.size_great: |
add eax, ecx ;RUS: add to first_wanted кол-во байт для чтения |
;ENG: add to first_wanted number of bytes to read |
adc ebx, 0 |
adc edx, 0 |
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx |
cmp [esi + EXT2_INODE_STRUC.i_dir_acl], edx |
ja .size_great_great |
jb .size_great_less |
cmp [ebp + EXT2_INODE_STRUC.i_size], eax |
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, [ebp + EXT2_INODE_STRUC.i_size] |
sub ecx, [esi] ;RUS: (размер - старт) = сколько читать ;ENG: to read = (size - start) |
mov ecx, [esi + EXT2_INODE_STRUC.i_size] |
sub ecx, [ebx+4] ;RUS: (размер - старт) = сколько читать ;ENG: to read = (size - start) |
jmp @F |
.size_great_great: |
923,13 → 996,11 |
;esi -> first wanted |
push ecx ;количество считанных байт |
test esi, esi |
jz .zero_start |
;получим кусок из первого блока |
mov edx, [esi+4] |
mov eax, [esi] |
div [ext2_data.block_size] |
mov edx, [ebx+8] |
mov eax, [ebx+4] |
div [ebp+EXTFS.block_size] |
push eax ;счетчик блоков ложим в стек |
938,7 → 1009,7 |
call ext2_get_inode_block |
test eax, eax |
jnz .error_at_first_block |
mov ebx, [ext2_data.ext2_save_block] |
mov ebx, [ebp+EXTFS.ext2_save_block] |
mov eax, ecx |
call ext2_get_block |
test eax, eax |
947,7 → 1018,7 |
add ebx, edx |
neg edx |
add edx, [ext2_data.block_size] ;RUS: block_size - стартовый байт = сколько байт 1-го блока |
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 |
956,18 → 1027,16 |
sub eax, edx |
mov ecx, edx |
push esi |
mov esi, ebx |
rep movsb ;RUS: кусок 1-го блока ;ENG: part of 1st block |
jmp .calc_blocks_count |
pop esi |
.zero_start: |
mov eax, ecx |
push 0 ;счетчик блоков ложим в стек |
;теперь в eax кол-во оставшихся байт для чтения |
.calc_blocks_count: |
mov ebx, edi ;чтение блока прям в ->ebx |
xor edx, edx |
div [ext2_data.block_size] ;кол-во байт в последнем блоке (остаток) в edx |
div [ebp+EXTFS.block_size] ;кол-во байт в последнем блоке (остаток) в edx |
mov edi, eax ;кол-во целых блоков в edi |
@@: |
test edi, edi |
982,7 → 1051,7 |
call ext2_get_block |
test eax, eax |
jnz .error_at_read_cycle |
add ebx, [ext2_data.block_size] |
add ebx, [ebp+EXTFS.block_size] |
dec edi |
jmp @B |
999,7 → 1068,7 |
mov edi, ebx |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
mov ebx, [ebp+EXTFS.ext2_save_block] |
call ext2_get_block |
test eax, eax |
jnz .error_at_finish_block |
1013,6 → 1082,7 |
pop ecx ;счетчик блоков, который хранился в стеке |
@@: |
pop ebx ;количество считанных байт |
call ext2_unlock |
pop eax ; 1 или 0 - достигли ли конца файла |
test eax, eax |
jz @F |
1035,17 → 1105,21 |
.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, [ext2_data.block_size] ;RUS: запомним конец блока ;ENG: save block end |
add edx, [ebp+EXTFS.block_size] ;RUS: запомним конец блока ;ENG: save block end |
.start_rec: |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 |
1097,32 → 1171,37 |
;======================== |
;Ищет inode по строке пути |
;in: esi = name |
;in: esi+[esp+4] = name |
; ebp = pointer to EXTFS |
;out: eax - error code |
; ebp = inode |
; esi = inode |
; dl - первый байт из имени файла/папки |
ext2_find_lfn: |
mov ebp, [ext2_data.root_inode] |
cmp [ebp + EXT2_INODE_STRUC.i_blocks], 0 |
mov edx, [ebp+EXTFS.root_inode] |
cmp [edx + EXT2_INODE_STRUC.i_blocks], 0 |
je .error_empty_root |
.next_path_part: |
push [ebp + EXT2_INODE_STRUC.i_blocks] |
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, [ext2_data.ext2_save_block] ;ebx = cur dir record |
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? |
1130,24 → 1209,29 |
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, [ext2_data.ext2_save_inode] ;RUS: все же папка. ;ENG: it's a folder afterall |
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 ebp, ebx |
mov edx, ebx |
jmp .next_path_part |
.next_folder_block: |
;к следующему блоку в текущей папке |
pop eax ;RUS: счетчик блоков ;ENG: blocks counter |
sub eax, [ext2_data.count_block_in_block] |
sub eax, [ebp+EXTFS.count_block_in_block] |
jle .not_found |
push eax |
1156,17 → 1240,17 |
.not_found: |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
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, [ext2_data.ext2_save_inode] |
mov ebx, [ebp+EXTFS.ext2_save_inode] |
call ext2_get_inode |
mov ebp, ebx |
mov esi, ebx |
xor eax, eax |
ret |
ret 4 |
.error_get_inode_block: |
.error_get_block: |
1175,30 → 1259,35 |
pop ebx |
.error_empty_root: |
mov eax, ERROR_FS_FAIL |
ret |
ret 4 |
;---------------------------------------------------------------- |
;ext2_HdGetFileInfo - read file info from block device |
; |
;in: esi points to filename |
; edx mem location to return data |
;-------------------------------------------------------------- |
ext2_HdGetFileInfo: |
xchg bx, bx |
; 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 |
call ext2_find_lfn |
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 ebp, [ext2_data.root_inode] |
mov esi, [ebp+EXTFS.root_inode] |
@@: |
xor eax, eax |
mov edi, edx |
1210,10 → 1299,10 |
or dword [edx], FS_FT_HIDDEN |
@@: |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
test [esi + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jnz @F |
mov eax, [ebp + EXT2_INODE_STRUC.i_size] ;low size |
mov ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl] ;high size |
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 |
1221,33 → 1310,34 |
xor dword [edx], FS_FT_DIR |
lea edi, [edx + 8] |
mov eax, [ebp + EXT2_INODE_STRUC.i_ctime] |
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, [ebp + EXT2_INODE_STRUC.i_atime] |
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, [ebp + EXT2_INODE_STRUC.i_mtime] |
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_HdRewrite: |
ext2_HdWrite: |
ext2_HdSetFileEnd: |
ext2_HdSetFileInfo: |
ext2_HdDelete: |
ext2_HdCreateFolder: |
ext2_Rewrite: |
ext2_Write: |
ext2_SetFileEnd: |
ext2_SetFileInfo: |
ext2_Delete: |
ext2_CreateFolder: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
/kernel/trunk/fs/fat32.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; FAT32.INC ;; |
58,8 → 58,7 |
PUSHAD_EDI equ [esp+0] |
; Internal data for every FAT partition. |
struct FAT |
p PARTITION ; must be the first item |
struct FAT PARTITION |
fs_type db ? |
fat16_root db 0 ; flag for fat16 rootdir |
fat_change db 0 ; 1=fat has changed |
121,6 → 120,7 |
iglobal |
align 4 |
fat_user_functions: |
dd free |
dd (fat_user_functions_end - fat_user_functions - 4) / 4 |
dd fat_Read |
dd fat_ReadFolder |
138,10 → 138,8 |
; these labels are located before the main function to make |
; most of jumps to these be short |
fat_create_partition.free_return0: |
push ebx |
mov eax, ebp |
call free |
pop ebx |
pop ebp |
fat_create_partition.return0: |
xor eax, eax |
148,7 → 146,7 |
ret |
fat_create_partition: |
; bootsector must have been successfully read |
cmp dword [esp+4], 1 |
cmp dword [esp+4], 0 |
jnz .return0 |
; bootsector signature must be correct |
cmp word [ebx+0x1fe], 0xaa55 |
170,16 → 168,17 |
call malloc |
test eax, eax |
jz .return0 |
mov ecx, [ebp+8] |
mov dword [eax+FAT.p.FirstSector], ecx |
mov ecx, [ebp+12] |
mov dword [eax+FAT.p.FirstSector+4], ecx |
mov ecx, [ebp+16] |
mov dword [eax+FAT.p.Length], ecx |
mov ecx, [ebp+20] |
mov dword [eax+FAT.p.Length+4], ecx |
mov [eax+FAT.p.Disk], esi |
mov [eax+FAT.p.FSUserFunctions], fat_user_functions |
mov ecx, dword [ebp+PARTITION.FirstSector] |
mov dword [eax+FAT.FirstSector], ecx |
mov ecx, dword [ebp+PARTITION.FirstSector+4] |
mov dword [eax+FAT.FirstSector+4], ecx |
mov ecx, dword [ebp+PARTITION.Length] |
mov dword [eax+FAT.Length], ecx |
mov ecx, dword [ebp+PARTITION.Length+4] |
mov dword [eax+FAT.Length+4], ecx |
mov ecx, [ebp+PARTITION.Disk] |
mov [eax+FAT.Disk], ecx |
mov [eax+FAT.FSUserFunctions], fat_user_functions |
or [eax+FAT.fat_in_cache], -1 |
mov [eax+FAT.fat_change], 0 |
push ebp |
226,8 → 225,8 |
jnz @f |
mov eax, [ebx+0x20] ; total sector count |
@@: |
mov dword [ebp+FAT.p.Length], eax |
and dword [ebp+FAT.p.Length+4], 0 |
mov dword [ebp+FAT.Length], eax |
and dword [ebp+FAT.Length+4], 0 |
sub eax, [ebp+FAT.DATA_START] ; eax = count of data sectors |
xor edx, edx |
div [ebp+FAT.SECTORS_PER_CLUSTER] |
262,7 → 261,6 |
mov [ebp+FAT.fatEND], 0x0FFFFFF8 |
mov [ebp+FAT.fatMASK], 0x0FFFFFFF |
mov al, 32 |
mov [fs_type], al |
mov [ebp+FAT.fs_type], al |
mov eax, ebp |
pop ebp |
274,7 → 272,6 |
mov [ebp+FAT.fatEND], 0x0000FFF8 |
mov [ebp+FAT.fatMASK], 0x0000FFFF |
mov al, 16 |
mov [fs_type], al |
mov [ebp+FAT.fs_type], al |
mov eax, ebp |
pop ebp |
769,42 → 766,6 |
ret 4 |
;---------------------------------------------------------------- |
; |
; fs_HdRead - LFN variant for reading hard disk |
; |
; Obsolete, will be replaced with filesystem-specific functions. |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdRead: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdRead |
cmp [fs_type], 2 |
jz ext2_HdRead |
or ebx, -1 |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
call fat_Read |
pop ebp |
ret |
;---------------------------------------------------------------- |
; fat_Read - FAT16/32 implementation of reading a file |
; in: ebp = pointer to FAT structure |
; in: esi+[esp+4] = name |
944,43 → 905,6 |
jmp .reteof |
;---------------------------------------------------------------- |
; |
; fs_HdReadFolder - LFN variant for reading hard disk folder |
; |
; Obsolete, will be replaced with filesystem-specific functions. |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdReadFolder: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdReadFolder |
cmp [fs_type], 2 |
jz ext2_HdReadFolder |
movi eax, ERROR_UNSUPPORTED_FS |
or ebx, -1 |
ret |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
call fat_ReadFolder |
pop ebp |
ret |
;---------------------------------------------------------------- |
; fat_ReadFolder - FAT16/32 implementation of reading a folder |
; in: ebp = pointer to FAT structure |
; in: esi+[esp+4] = name |
1377,52 → 1301,6 |
pop ecx |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdRewrite - LFN variant for writing hard disk |
; |
; Obsolete, will be replaced with filesystem-specific functions. |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdCreateFolder: |
mov al, 1 |
jmp fs_HdRewrite.common |
fs_HdRewrite: |
xor eax, eax |
.common: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdRewrite |
cmp [fs_type], 2 |
jz ext2_HdRewrite |
mov eax, ERROR_UNKNOWN_FS |
xor ebx, ebx |
ret |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
test eax, eax |
mov eax, fat_CreateFolder |
jnz @f |
mov eax, fat_Rewrite |
@@: |
call eax |
pop ebp |
ret |
fshrad: |
call fat_unlock |
mov eax, ERROR_ACCESS_DENIED |
1441,7 → 1319,7 |
jmp fat_Rewrite.common |
;---------------------------------------------------------------- |
; fat_HdRewrite - FAT16/32 implementation of creating a new file |
; fat_Rewrite - FAT16/32 implementation of creating a new file |
; in: ebp = pointer to FAT structure |
; in: esi+[esp+4] = name |
; in: ebx = pointer to parameters from sysfunc 70 |
1988,52 → 1866,17 |
mov [edi-32+20], cx |
jmp .writedircont |
;---------------------------------------------------------------- |
; |
; fs_HdWrite - LFN variant for writing to hard disk |
; |
; Obsolete, will be replaced with filesystem-specific functions. |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
fat_Write.access_denied: |
push ERROR_ACCESS_DENIED |
fs_HdWrite.ret0: |
fat_Write.ret0: |
pop eax |
xor ebx, ebx |
ret |
fs_HdWrite.ret11: |
fat_Write.ret11: |
push ERROR_DEVICE |
jmp fs_HdWrite.ret0 |
jmp fat_Write.ret0 |
fs_HdWrite: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdWrite |
cmp [fs_type], 2 |
jz ext2_HdWrite |
push ERROR_UNKNOWN_FS |
jmp .ret0 |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
call fat_Write |
pop ebp |
ret |
;---------------------------------------------------------------- |
; fat_Write - FAT16/32 implementation of writing to file |
; in: ebp = pointer to FAT structure |
2051,7 → 1894,7 |
pop edi |
push eax |
call fat_unlock |
jmp fs_HdWrite.ret0 |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
cmp dword [ebx+8], 0 |
2060,7 → 1903,7 |
pop edi |
push ERROR_END_OF_FILE |
call fat_unlock |
jmp fs_HdWrite.ret0 |
jmp .ret0 |
@@: |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
2362,39 → 2205,6 |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdSetFileEnd - set end of file on hard disk |
; |
; Obsolete, will be replaced with filesystem-specific functions. |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdSetFileEnd: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdSetFileEnd |
cmp [fs_type], 2 |
jz ext2_HdSetFileEnd |
movi eax, ERROR_UNKNOWN_FS |
ret |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
call fat_SetFileEnd |
pop ebp |
ret |
;---------------------------------------------------------------- |
; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file |
; in: ebp = pointer to FAT structure |
; in: esi+[esp+4] = name |
2634,25 → 2444,6 |
movi eax, ERROR_FAT_TABLE |
ret |
fs_HdGetFileInfo: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdGetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdGetFileInfo |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
call fat_GetFileInfo |
pop ebp |
ret |
;---------------------------------------------------------------- |
; fat_GetFileInfo - FAT16/32 implementation of getting file info |
; in: ebp = pointer to FAT structure |
2687,25 → 2478,6 |
pop edi |
ret |
fs_HdSetFileInfo: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdSetFileInfo |
cmp [fs_type], 2 |
jz ext2_HdSetFileInfo |
mov eax, ERROR_UNKNOWN_FS |
ret |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
call fat_SetFileInfo |
pop ebp |
ret |
;---------------------------------------------------------------- |
; fat_SetFileInfo - FAT16/32 implementation of setting file info |
; in: ebp = pointer to FAT structure |
2742,36 → 2514,6 |
ret |
;---------------------------------------------------------------- |
; |
; fs_HdDelete - delete file or empty folder from hard disk |
; |
; Obsolete, will be replaced with filesystem-specific functions. |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdDelete: |
cmp [fs_type], 16 |
jz @f |
cmp [fs_type], 32 |
jz @f |
cmp [fs_type], 1 |
jz ntfs_HdDelete |
cmp [fs_type], 2 |
jz ext2_HdDelete |
movi eax, ERROR_UNKNOWN_FS |
ret |
@@: |
sub ebx, 4 |
push ebp |
mov ebp, [fs_dependent_data_start.partition] |
call fat_Delete |
pop ebp |
ret |
;---------------------------------------------------------------- |
; fat_Delete - FAT16/32 implementation of deleting a file/folder |
; in: ebp = pointer to FAT structure |
; in: esi+[esp+4] = name |
/kernel/trunk/fs/fs.inc |
---|
318,86 → 318,6 |
fs_noflpdisk: |
;***************************************************************** |
mov eax, [edi+1] |
cmp eax, 'HD0 ' |
je fs_yesharddisk_IDE0 |
cmp eax, 'HD1 ' |
je fs_yesharddisk_IDE1 |
cmp eax, 'HD2 ' |
je fs_yesharddisk_IDE2 |
cmp eax, 'HD3 ' |
je fs_yesharddisk_IDE3 |
jmp old_path_harddisk |
fs_yesharddisk_IDE0: |
call reserve_hd1 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x0 |
mov [hdpos], 1 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE1: |
call reserve_hd1 |
mov [hdbase], 0x1f0 |
mov [hdid], 0x10 |
mov [hdpos], 2 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE2: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0x0 |
mov [hdpos], 3 |
jmp fs_yesharddisk_partition |
fs_yesharddisk_IDE3: |
call reserve_hd1 |
mov [hdbase], 0x170 |
mov [hdid], 0x10 |
mov [hdpos], 4 |
fs_yesharddisk_partition: |
call reserve_hd_channel |
; call choice_necessity_partition |
; jmp fs_yesharddisk_all |
jmp fs_for_new_semantic |
choice_necessity_partition: |
mov eax, [edi+1+12] |
call StringToNumber |
mov [fat32part], eax |
choice_necessity_partition_1: |
mov ecx, [hdpos] |
xor eax, eax |
mov [hd_entries], eax; entries in hd cache |
mov edx, DRIVE_DATA+2 |
cmp ecx, 0x80 |
jb search_partition_array |
mov ecx, 4 |
search_partition_array: |
mov bl, [edx] |
movzx ebx, bl |
add eax, ebx |
inc edx |
loop search_partition_array |
mov ecx, [hdpos] |
mov edx, BiosDiskPartitions |
sub ecx, 0x80 |
jb .s |
je .f |
@@: |
mov ebx, [edx] |
add edx, 4 |
add eax, ebx |
loop @b |
jmp .f |
.s: |
sub eax, ebx |
.f: |
add eax, [known_part]; add eax,[fat32part] |
dec eax |
xor edx, edx |
imul eax, 100 |
add eax, DRIVE_DATA+0xa |
mov [transfer_adress], eax |
call partition_data_transfer_1 |
ret |
old_path_harddisk: |
mov eax, [edi+1] |
cmp eax, 'HD ' |
416,28 → 336,8 |
fs_no_LBA_read: |
cmp byte [edi+1+11], 0; directory read |
je fs_give_dir1 |
call reserve_hd1 |
fs_for_new_semantic: |
call choice_necessity_partition |
fs_yesharddisk_all: |
mov eax, 1 |
mov ebx, [esp+24+24] |
cmp [hdpos], 0 ; is hd base set? |
jz hd_err_return |
cmp [fat32part], 0 ; is partition set? |
jnz @f |
hd_err_return: |
call free_hd_channel |
and [hd1_status], 0 |
jmp file_system_return |
@@: |
call free_hd_channel |
and [hd1_status], 0 |
fs_noharddisk: |
; \begin{diamond}[18.03.2006] |
mov eax, 5 ; file not found |
542,7 → 442,10 |
lbarl1: |
call reserve_hd1 |
pushad |
mov ecx, ide_mutex |
call mutex_lock |
popad |
push eax |
push ecx |
633,6 → 536,10 |
mov [hd_error], 0 |
mov [hd1_status], 0 |
add esp, 2*4 |
pushad |
mov ecx, ide_mutex |
call mutex_unlock |
popad |
ret |
/kernel/trunk/fs/fs_lfn.inc |
---|
42,18 → 42,6 |
db 10,'floppydisk' |
dd fs_OnFloppy |
dd fs_NextFloppy |
db 3,'hd0' |
dd fs_OnHd0 |
dd fs_NextHd0 |
db 3,'hd1' |
dd fs_OnHd1 |
dd fs_NextHd1 |
db 3,'hd2' |
dd fs_OnHd2 |
dd fs_NextHd2 |
db 3,'hd3' |
dd fs_OnHd3 |
dd fs_NextHd3 |
;********************************************** |
db 3,'cd0' |
dd fs_OnCd0 |
76,14 → 64,6 |
db 'rd',0 |
dd fs_HasFloppy |
db 'fd',0 |
dd fs_HasHd0 |
db 'hd0',0 |
dd fs_HasHd1 |
db 'hd1',0 |
dd fs_HasHd2 |
db 'hd2',0 |
dd fs_HasHd3 |
db 'hd3',0 |
;********************************************** |
dd fs_HasCd0 |
db 'cd0',0 |
97,7 → 77,6 |
dd 0 |
fs_additional_handlers: |
dd biosdisk_handler, biosdisk_enum_root |
dd dyndisk_handler, dyndisk_enum_root |
; add new handlers here |
dd 0 |
523,84 → 502,6 |
dd fs_FloppyCreateFolder |
fs_NumFloppyServices = ($ - fs_FloppyServices)/4 |
fs_OnHd0: |
call reserve_hd1 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1F0 |
mov [hdid], 0 |
push 1 |
jmp fs_OnHd |
fs_OnHd1: |
call reserve_hd1 |
mov eax, [hd_address_table] |
mov [hdbase], eax ;0x1F0 |
mov [hdid], 0x10 |
push 2 |
jmp fs_OnHd |
fs_OnHd2: |
call reserve_hd1 |
mov eax, [hd_address_table+16] |
mov [hdbase], eax ;0x170 |
mov [hdid], 0 |
push 3 |
jmp fs_OnHd |
fs_OnHd3: |
call reserve_hd1 |
mov eax, [hd_address_table+16] |
mov [hdbase], eax ;0x170 |
mov [hdid], 0x10 |
push 4 |
fs_OnHd: |
call reserve_hd_channel |
pop eax |
mov [hdpos], eax |
cmp ecx, 0x100 |
jae fs_OnHdAndBd.nf |
cmp cl, [DRIVE_DATA+1+eax] |
fs_OnHdAndBd: |
jbe @f |
.nf: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 5 ; not found |
ret |
@@: |
mov [known_part], ecx ; mov [fat32part], ecx |
push ebx esi |
call choice_necessity_partition_1 |
pop esi ebx |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
; add edx, std_application_base_address |
mov eax, [ebx] |
cmp eax, fs_NumHdServices |
jae .not_impl |
add ebx, 4 |
call dword [fs_HdServices + eax*4] |
call free_hd_channel |
and [hd1_status], 0 |
mov [image_of_eax], eax |
mov [image_of_ebx], ebx |
ret |
.not_impl: |
call free_hd_channel |
and [hd1_status], 0 |
mov dword [image_of_eax], 2 ; not implemented |
ret |
fs_HdServices: |
dd fs_HdRead |
dd fs_HdReadFolder |
dd fs_HdRewrite |
dd fs_HdWrite |
dd fs_HdSetFileEnd |
dd fs_HdGetFileInfo |
dd fs_HdSetFileInfo |
dd 0 |
dd fs_HdDelete |
dd fs_HdCreateFolder |
fs_NumHdServices = ($ - fs_HdServices)/4 |
;******************************************************* |
fs_OnCd0: |
call reserve_cd |
691,22 → 592,6 |
cmp byte [DRIVE_DATA], 0 |
setnz al |
ret |
fs_HasHd0: |
test byte [DRIVE_DATA+1], 01000000b |
setnz al |
ret |
fs_HasHd1: |
test byte [DRIVE_DATA+1], 00010000b |
setnz al |
ret |
fs_HasHd2: |
test byte [DRIVE_DATA+1], 00000100b |
setnz al |
ret |
fs_HasHd3: |
test byte [DRIVE_DATA+1], 00000001b |
setnz al |
ret |
;******************************************************* |
fs_HasCd0: |
762,27 → 647,6 |
stc |
ret |
; on hdx, we have partitions from 1 to [0x40002+x] |
fs_NextHd0: |
push 0 |
jmp fs_NextHd |
fs_NextHd1: |
push 1 |
jmp fs_NextHd |
fs_NextHd2: |
push 2 |
jmp fs_NextHd |
fs_NextHd3: |
push 3 |
fs_NextHd: |
pop ecx |
movzx ecx, byte [DRIVE_DATA+2+ecx] |
cmp eax, ecx |
jae fs_NextFloppy.no2 |
inc eax |
clc |
ret |
;******************************************************* |
fs_NextCd: |
; we always have /cdX/1 |
795,147 → 659,6 |
ret |
;******************************************************* |
; Additional FS handlers. |
; This handler gets the control each time when fn 70 is called |
; with unknown item of root subdirectory. |
; in: esi -> name |
; ebp = 0 or rest of name relative to esi |
; out: if the handler processes path, he must not return in file_system_lfn, |
; but instead pop return address and return directly to the caller |
; otherwise simply return |
; here we test for /bd<N>/... - BIOS disks |
biosdisk_handler: |
cmp [NumBiosDisks], 0 |
jz .ret |
mov al, [esi] |
or al, 20h |
cmp al, 'b' |
jnz .ret |
mov al, [esi+1] |
or al, 20h |
cmp al, 'd' |
jnz .ret |
push esi |
inc esi |
inc esi |
cmp byte [esi], '0' |
jb .ret2 |
cmp byte [esi], '9' |
ja .ret2 |
xor edx, edx |
@@: |
lodsb |
test al, al |
jz .ok |
cmp al, '/' |
jz .ok |
sub al, '0' |
cmp al, 9 |
ja .ret2 |
lea edx, [edx*5] |
lea edx, [edx*2+eax] |
jmp @b |
.ret2: |
pop esi |
.ret: |
ret |
.ok: |
cmp al, '/' |
jz @f |
dec esi |
@@: |
add dl, 80h |
xor ecx, ecx |
@@: |
cmp dl, [BiosDisksData+ecx*4] |
jz .ok2 |
inc ecx |
cmp ecx, [NumBiosDisks] |
jb @b |
jmp .ret2 |
.ok2: |
add esp, 8 |
test al, al |
jnz @f |
mov esi, fs_BdNext |
jmp file_system_lfn.maindir_noesi |
@@: |
push ecx |
push ecx |
push biosdisk_cleanup |
push fs_OnBd |
mov edi, esp |
jmp file_system_lfn.found2 |
fs_BdNext: |
cmp eax, [BiosDiskPartitions+ecx*4] |
inc eax |
cmc |
biosdisk_cleanup: |
ret |
fs_OnBd: |
pop edx edx edx edx |
; edx = disk number, ecx = partition number |
; esi+ebp = name |
call reserve_hd1 |
add edx, 0x80 |
mov [hdpos], edx |
cmp ecx, [BiosDiskPartitions+(edx-0x80)*4] |
jmp fs_OnHdAndBd |
; This handler is called when virtual root is enumerated |
; and must return all items which can be handled by this. |
; It is called several times, first time with eax=0 |
; in: eax = 0 for first call, previously returned value for subsequent calls |
; out: eax = 0 => no more items |
; eax != 0 => buffer pointed to by edi contains name of item |
; here we enumerate existing BIOS disks /bd<N> |
biosdisk_enum_root: |
cmp eax, [NumBiosDisks] |
jae .end |
push eax |
movzx eax, byte [BiosDisksData+eax*4] |
sub al, 80h |
push eax |
mov al, 'b' |
stosb |
mov al, 'd' |
stosb |
pop eax |
cmp al, 10 |
jae .big |
add al, '0' |
stosb |
mov byte [edi], 0 |
pop eax |
inc eax |
ret |
.end: |
xor eax, eax |
ret |
.big: |
push ecx edx |
push -'0' |
mov ecx, 10 |
@@: |
xor edx, edx |
div ecx |
push edx |
test eax, eax |
jnz @b |
xchg eax, edx |
@@: |
pop eax |
add al, '0' |
stosb |
jnz @b |
pop edx ecx |
pop eax |
inc eax |
ret |
;----------------------------------------------------------------------------- |
process_replace_file_name: |
; in |
/kernel/trunk/fs/iso9660.inc |
---|
42,26 → 42,18 |
cmp [ChannelNumber], 1 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
cli |
cmp [IDE_Channel_1], 0 |
je .reserve_ok_1 |
sti |
call change_task |
jmp .IDE_Channel_1 |
.IDE_Channel_2: |
cli |
cmp [IDE_Channel_2], 0 |
je .reserve_ok_2 |
sti |
call change_task |
jmp .IDE_Channel_2 |
.reserve_ok_1: |
pushad |
mov ecx, ide_channel1_mutex |
call mutex_lock |
mov [IDE_Channel_1], 1 |
sti |
popad |
ret |
.reserve_ok_2: |
.IDE_Channel_2: |
pushad |
mov ecx, ide_channel2_mutex |
call mutex_lock |
mov [IDE_Channel_2], 1 |
sti |
popad |
ret |
free_cd_channel: |
69,11 → 61,17 |
jne .IDE_Channel_2 |
.IDE_Channel_1: |
mov [IDE_Channel_1], 0 |
sti |
pushad |
mov ecx, ide_channel1_mutex |
call mutex_unlock |
popad |
ret |
.IDE_Channel_2: |
mov [IDE_Channel_2], 0 |
sti |
pushad |
mov ecx, ide_channel2_mutex |
call mutex_unlock |
popad |
ret |
uglobal |
/kernel/trunk/fs/ntfs.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
7,7 → 7,65 |
$Revision$ |
struct NTFS PARTITION |
Lock MUTEX ? ; currently operations with one partition |
; can not be executed in parallel since the |
; legacy code is not ready; this mutex guards |
; all operations |
sectors_per_cluster dd ? |
mft_cluster dd ? |
mftmirr_cluster dd ? |
frs_size dd ? ; FRS size in bytes |
iab_size dd ? ; IndexAllocationBuffer size in bytes |
frs_buffer dd ? |
iab_buffer dd ? |
mft_retrieval dd ? |
mft_retrieval_size dd ? |
mft_retrieval_alloc dd ? |
mft_retrieval_end dd ? |
cur_index_size dd ? |
cur_index_buf dd ? |
ntfs_cur_attr dd ? |
ntfs_cur_iRecord dd ? |
ntfs_cur_offs dd ? ; in sectors |
ntfs_cur_size dd ? ; in sectors |
ntfs_cur_buf dd ? |
ntfs_cur_read dd ? ; [output] |
ntfs_bCanContinue db ? |
rb 3 |
cur_subnode_size dd ? |
ntfs_attr_iRecord dd ? |
ntfs_attr_iBaseRecord dd ? |
ntfs_attr_offs dd ? |
ntfs_attr_list dd ? |
ntfs_attr_size dq ? |
ntfs_cur_tail dd ? |
ntfs_attrlist_buf rb 0x400 |
ntfs_attrlist_mft_buf rb 0x400 |
ntfs_bitmap_buf rb 0x400 |
ends |
iglobal |
align 4 |
ntfs_user_functions: |
dd ntfs_free |
dd (ntfs_user_functions_end - ntfs_user_functions - 4) / 4 |
dd ntfs_Read |
dd ntfs_ReadFolder |
dd ntfs_Rewrite |
dd ntfs_Write |
dd ntfs_SetFileEnd |
dd ntfs_GetFileInfo |
dd ntfs_SetFileInfo |
dd 0 |
dd ntfs_Delete |
dd ntfs_CreateFolder |
ntfs_user_functions_end: |
endg |
ntfs_test_bootsec: |
; in: ebx->buffer, edx=size of partition |
; out: CF set <=> invalid |
93,25 → 151,66 |
stc |
ret |
ntfs_setup: ; CODE XREF: part_set.inc |
proc ntfs_create_partition |
mov edx, dword [ebp+PARTITION.Length] |
cmp dword [esp+4], 0 |
jz .boot_read_ok |
add ebx, 512 |
lea eax, [edx-1] |
call fs_read32_sys |
test eax, eax |
jnz @f |
call ntfs_test_bootsec |
jnc .ntfs_setup |
@@: |
mov eax, edx |
shr eax, 1 |
call fs_read32_sys |
test eax, eax |
jnz .nope ; no chance... |
.boot_read_ok: |
call ntfs_test_bootsec |
jnc .ntfs_setup |
.nope: |
xor eax, eax |
jmp .exit |
.ntfs_setup: |
; By given bootsector, initialize some NTFS variables |
; call ntfs_test_bootsec ; checking boot sector was already |
; jc problem_fat_dec_count |
movi eax, sizeof.NTFS |
call malloc |
test eax, eax |
jz .exit |
mov ecx, dword [ebp+PARTITION.FirstSector] |
mov dword [eax+NTFS.FirstSector], ecx |
mov ecx, dword [ebp+PARTITION.FirstSector+4] |
mov dword [eax+NTFS.FirstSector+4], ecx |
mov ecx, dword [ebp+PARTITION.Length] |
mov dword [eax+NTFS.Length], ecx |
mov ecx, dword [ebp+PARTITION.Length+4] |
mov dword [eax+NTFS.Length+4], ecx |
mov ecx, [ebp+PARTITION.Disk] |
mov [eax+NTFS.Disk], ecx |
mov [eax+NTFS.FSUserFunctions], ntfs_user_functions |
push ebx ebp esi |
mov ebp, eax |
lea ecx, [ebp+NTFS.Lock] |
call mutex_init |
movzx eax, byte [ebx+13] |
mov [ntfs_data.sectors_per_cluster], eax |
mov [ebp+NTFS.sectors_per_cluster], eax |
mov eax, [ebx+0x28] |
add eax, [PARTITION_START] |
dec eax |
mov [PARTITION_END], eax |
mov [fs_type], 1 |
mov dword [ebp+NTFS.Length], eax |
and dword [ebp+NTFS.Length+4], 0 |
mov eax, [ebx+0x30] |
mov [ntfs_data.mft_cluster], eax |
mov [ebp+NTFS.mft_cluster], eax |
mov eax, [ebx+0x38] |
mov [ntfs_data.mftmirr_cluster], eax |
mov [ebp+NTFS.mftmirr_cluster], eax |
movsx eax, byte [ebx+0x40] |
test eax, eax |
js .1 |
mul [ntfs_data.sectors_per_cluster] |
mul [ebp+NTFS.sectors_per_cluster] |
shl eax, 9 |
jmp .2 |
.1: |
120,11 → 219,11 |
mov eax, 1 |
shl eax, cl |
.2: |
mov [ntfs_data.frs_size], eax |
mov [ebp+NTFS.frs_size], eax |
movsx eax, byte [ebx+0x44] |
test eax, eax |
js .3 |
mul [ntfs_data.sectors_per_cluster] |
mul [ebp+NTFS.sectors_per_cluster] |
shl eax, 9 |
jmp .4 |
.3: |
133,21 → 232,21 |
mov eax, 1 |
shl eax, cl |
.4: |
mov [ntfs_data.iab_size], eax |
mov [ebp+NTFS.iab_size], eax |
; allocate space for buffers |
add eax, [ntfs_data.frs_size] |
add eax, [ebp+NTFS.frs_size] |
push eax |
call kernel_alloc |
test eax, eax |
jz problem_fat_dec_count |
mov [ntfs_data.frs_buffer], eax |
add eax, [ntfs_data.frs_size] |
mov [ntfs_data.iab_buffer], eax |
jz .fail_free |
mov [ebp+NTFS.frs_buffer], eax |
add eax, [ebp+NTFS.frs_size] |
mov [ebp+NTFS.iab_buffer], eax |
; read $MFT disposition |
mov eax, [ntfs_data.mft_cluster] |
mul [ntfs_data.sectors_per_cluster] |
mov eax, [ebp+NTFS.mft_cluster] |
mul [ebp+NTFS.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
test eax, eax |
jnz .usemirr |
cmp dword [ebx], 'FILE' |
jnz .usemirr |
154,11 → 253,10 |
call ntfs_restore_usa_frs |
jnc .mftok |
.usemirr: |
and [hd_error], 0 |
mov eax, [ntfs_data.mftmirr_cluster] |
mul [ntfs_data.sectors_per_cluster] |
mov eax, [ebp+NTFS.mftmirr_cluster] |
mul [ebp+NTFS.sectors_per_cluster] |
call ntfs_read_frs_sector |
cmp [hd_error], 0 |
test eax, eax |
jnz @f |
cmp dword [ebx], 'FILE' |
jnz @f |
167,11 → 265,22 |
@@: |
; $MFT and $MFTMirr invalid! |
.fail_free_frs: |
push [ntfs_data.frs_buffer] |
push [ebp+NTFS.frs_buffer] |
call kernel_free |
jmp problem_fat_dec_count |
.fail_free: |
mov eax, ebp |
call free |
xor eax, eax |
.pop_exit: |
pop esi ebp ebx |
.exit: |
cmp dword [esp+4], 0 |
jz @f |
sub ebx, 512 |
@@: |
ret |
.fail_free_mft: |
push [ntfs_data.mft_retrieval] |
push [ebp+NTFS.mft_retrieval] |
call kernel_free |
jmp .fail_free_frs |
.mftok: |
183,9 → 292,9 |
pop ebx |
test eax, eax |
jz .fail_free_frs |
mov [ntfs_data.mft_retrieval], eax |
and [ntfs_data.mft_retrieval_size], 0 |
mov [ntfs_data.mft_retrieval_alloc], 0x1000/8 |
mov [ebp+NTFS.mft_retrieval], eax |
and [ebp+NTFS.mft_retrieval_size], 0 |
mov [ebp+NTFS.mft_retrieval_alloc], 0x1000/8 |
; $MFT base record must contain unnamed non-resident $DATA attribute |
movzx eax, word [ebx+14h] |
add eax, ebx |
204,7 → 313,7 |
jz .fail_free_mft |
; load first portion of $DATA attribute retrieval information |
mov edx, [eax+0x18] |
mov [ntfs_data.mft_retrieval_end], edx |
mov [ebp+NTFS.mft_retrieval_end], edx |
mov esi, eax |
movzx eax, word [eax+0x20] |
add esi, eax |
217,7 → 326,7 |
mov [eax], edx |
mov edx, [esp+8] ; block addr (relative) |
mov [eax+4], edx |
inc [ntfs_data.mft_retrieval_size] |
inc [ebp+NTFS.mft_retrieval_size] |
jmp .scanmcb |
.scanmcbend: |
add esp, 10h |
224,25 → 333,24 |
; there may be other portions of $DATA attribute in auxiliary records; |
; if they will be needed, they will be loaded later |
mov [ntfs_data.cur_index_size], 0x1000/0x200 |
mov [ebp+NTFS.cur_index_size], 0x1000/0x200 |
push 0x1000 |
call kernel_alloc |
test eax, eax |
jz .fail_free_mft |
mov [ntfs_data.cur_index_buf], eax |
mov [ebp+NTFS.cur_index_buf], eax |
popad |
call free_hd_channel |
and [hd1_status], 0 |
ret |
mov eax, ebp |
jmp .pop_exit |
endp |
.get_mft_retrieval_ptr: |
pushad |
mov eax, [ntfs_data.mft_retrieval_size] |
cmp eax, [ntfs_data.mft_retrieval_alloc] |
mov eax, [ebp+NTFS.mft_retrieval_size] |
cmp eax, [ebp+NTFS.mft_retrieval_alloc] |
jnz .ok |
add eax, 0x1000/8 |
mov [ntfs_data.mft_retrieval_alloc], eax |
mov [ebp+NTFS.mft_retrieval_alloc], eax |
shl eax, 3 |
push eax |
call kernel_alloc |
252,83 → 360,88 |
add esp, 14h |
jmp .fail_free_mft |
@@: |
mov esi, [ntfs_data.mft_retrieval] |
mov esi, [ebp+NTFS.mft_retrieval] |
mov edi, eax |
mov ecx, [ntfs_data.mft_retrieval_size] |
mov ecx, [ebp+NTFS.mft_retrieval_size] |
add ecx, ecx |
rep movsd |
push [ntfs_data.mft_retrieval] |
mov [ntfs_data.mft_retrieval], eax |
push [ebp+NTFS.mft_retrieval] |
mov [ebp+NTFS.mft_retrieval], eax |
call kernel_free |
mov eax, [ntfs_data.mft_retrieval_size] |
mov eax, [ebp+NTFS.mft_retrieval_size] |
.ok: |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
add eax, [ebp+NTFS.mft_retrieval] |
mov [esp+28], eax |
popad |
ret |
proc ntfs_free |
push ebx |
xchg ebx, eax |
stdcall kernel_free, [ebx+NTFS.frs_buffer] |
stdcall kernel_free, [ebx+NTFS.mft_retrieval] |
stdcall kernel_free, [ebx+NTFS.cur_index_buf] |
xchg ebx, eax |
call free |
pop ebx |
ret |
endp |
proc ntfs_lock |
lea ecx, [ebp+NTFS.Lock] |
jmp mutex_lock |
endp |
proc ntfs_unlock |
lea ecx, [ebp+NTFS.Lock] |
jmp mutex_unlock |
endp |
ntfs_read_frs_sector: |
push eax ecx |
add eax, [PARTITION_START] |
mov ecx, [ntfs_data.frs_size] |
push ecx |
mov ebx, [ebp+NTFS.frs_buffer] |
push ebx |
mov ecx, [ebp+NTFS.frs_size] |
shr ecx, 9 |
mov ebx, [ntfs_data.frs_buffer] |
push ebx |
push ecx |
mov ecx, eax |
@@: |
call hd_read |
cmp [hd_error], 0 |
mov eax, ecx |
call fs_read32_sys |
test eax, eax |
jnz .fail |
add ebx, 0x200 |
inc eax |
loop @b |
inc ecx |
dec dword [esp] |
jnz @b |
pop eax |
.fail: |
pop ebx |
pop ecx eax |
pop ecx |
ret |
uglobal |
align 4 |
ntfs_cur_attr dd ? |
ntfs_cur_iRecord dd ? |
ntfs_cur_offs dd ? ; in sectors |
ntfs_cur_size dd ? ; in sectors |
ntfs_cur_buf dd ? |
ntfs_cur_read dd ? ; [output] |
ntfs_bCanContinue db ? |
rb 3 |
ntfs_attrlist_buf rb 0x400 |
ntfs_attrlist_mft_buf rb 0x400 |
ntfs_bitmap_buf rb 0x400 |
ntfs_attr_iRecord dd ? |
ntfs_attr_iBaseRecord dd ? |
ntfs_attr_offs dd ? |
ntfs_attr_list dd ? |
ntfs_attr_size dq ? |
ntfs_cur_tail dd ? |
endg |
ntfs_read_attr: |
; in: global variables |
; out: [ntfs_cur_read] |
; in: variables in ebp+NTFS.* |
; out: [ebp+NTFS.ntfs_cur_read] |
; out: CF=1 => notfound, in this case eax=0 => disk ok, otherwise eax=disk error code |
xor eax, eax |
pushad |
and [ntfs_cur_read], 0 |
cmp [ntfs_cur_iRecord], 0 |
and [ebp+NTFS.ntfs_cur_read], 0 |
cmp [ebp+NTFS.ntfs_cur_iRecord], 0 |
jnz .nomft |
cmp [ntfs_cur_attr], 0x80 |
cmp [ebp+NTFS.ntfs_cur_attr], 0x80 |
jnz .nomft |
mov eax, [ntfs_data.mft_retrieval_end] |
mov eax, [ebp+NTFS.mft_retrieval_end] |
inc eax |
mul [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
mul [ebp+NTFS.sectors_per_cluster] |
cmp eax, [ebp+NTFS.ntfs_cur_offs] |
jbe .nomft |
; precalculated part of $Mft $DATA |
mov esi, [ntfs_data.mft_retrieval] |
mov eax, [ntfs_cur_offs] |
mov esi, [ebp+NTFS.mft_retrieval] |
mov eax, [ebp+NTFS.ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
div [ebp+NTFS.sectors_per_cluster] |
; eax = VCN, edx = offset in sectors from beginning of cluster |
xor ecx, ecx ; ecx will contain LCN |
.mftscan: |
337,9 → 450,9 |
jb @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
mov eax, [ebp+NTFS.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
add eax, [ebp+NTFS.mft_retrieval] |
cmp eax, esi |
pop eax |
jnz .mftscan |
350,42 → 463,43 |
add ecx, [esi] |
push eax |
push edx |
mov eax, [ntfs_data.sectors_per_cluster] |
mov eax, [ebp+NTFS.sectors_per_cluster] |
mul ecx |
; eax = sector on partition |
add eax, [PARTITION_START] |
pop edx |
add eax, edx |
mov ebx, [ntfs_cur_buf] |
mov ebx, [ebp+NTFS.ntfs_cur_buf] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
imul ecx, [ebp+NTFS.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
cmp ecx, [ebp+NTFS.ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
mov ecx, [ebp+NTFS.ntfs_cur_size] |
@@: |
; ecx = number of sequential sectors to read |
call hd_read |
cmp [hd_error], 0 |
push eax |
call fs_read32_sys |
pop edx |
test eax, eax |
jnz .errread |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
add [ebp+NTFS.ntfs_cur_read], 0x200 |
dec [ebp+NTFS.ntfs_cur_size] |
inc [ebp+NTFS.ntfs_cur_offs] |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
mov [ebp+NTFS.ntfs_cur_buf], ebx |
lea eax, [edx+1] |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], eax |
cmp [ebp+NTFS.ntfs_cur_size], eax |
jz @f |
add esi, 8 |
push eax |
mov eax, [ntfs_data.mft_retrieval_end] |
mov eax, [ebp+NTFS.mft_retrieval_end] |
shl eax, 3 |
add eax, [ntfs_data.mft_retrieval] |
add eax, [ebp+NTFS.mft_retrieval] |
cmp eax, esi |
pop eax |
jz .nomft |
396,6 → 510,7 |
.errread: |
pop ecx |
.errret: |
mov [esp+28], eax |
stc |
popad |
ret |
402,17 → 517,16 |
.nomft: |
; 1. Read file record. |
; N.B. This will do recursive call of read_attr for $MFT::$Data. |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iRecord], eax |
and [ntfs_attr_list], 0 |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
or [ntfs_attr_iBaseRecord], -1 |
mov eax, [ebp+NTFS.ntfs_cur_iRecord] |
mov [ebp+NTFS.ntfs_attr_iRecord], eax |
and [ebp+NTFS.ntfs_attr_list], 0 |
or dword [ebp+NTFS.ntfs_attr_size], -1 |
or dword [ebp+NTFS.ntfs_attr_size+4], -1 |
or [ebp+NTFS.ntfs_attr_iBaseRecord], -1 |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
jc .errret |
; 2. Find required attribute. |
mov eax, [ntfs_data.frs_buffer] |
mov eax, [ebp+NTFS.frs_buffer] |
; a) For auxiliary records, read base record |
; N.B. If base record is present, |
; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero |
422,27 → 536,26 |
; test eax, eax |
; jz @f |
.beginfindattr: |
mov [ntfs_attr_iRecord], eax |
mov [ebp+NTFS.ntfs_attr_iRecord], eax |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
jc .errret |
@@: |
; b) Scan for required attribute and for $ATTR_LIST |
mov eax, [ntfs_data.frs_buffer] |
mov eax, [ebp+NTFS.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
and [ntfs_attr_offs], 0 |
mov ecx, [ebp+NTFS.ntfs_cur_attr] |
and [ebp+NTFS.ntfs_attr_offs], 0 |
.scanattr: |
cmp dword [eax], -1 |
jz .scandone |
cmp dword [eax], ecx |
jz .okattr |
cmp [ntfs_attr_iBaseRecord], -1 |
cmp [ebp+NTFS.ntfs_attr_iBaseRecord], -1 |
jnz .scancont |
cmp dword [eax], 0x20 ; $ATTR_LIST |
jnz .scancont |
mov [ntfs_attr_list], eax |
mov [ebp+NTFS.ntfs_attr_list], eax |
jmp .scancont |
.okattr: |
; ignore named $DATA attributes (aka NTFS streams) |
451,30 → 564,30 |
cmp byte [eax+9], 0 |
jnz .scancont |
@@: |
mov [ntfs_attr_offs], eax |
mov [ebp+NTFS.ntfs_attr_offs], eax |
.scancont: |
add eax, [eax+4] |
jmp .scanattr |
.continue: |
pushad |
and [ntfs_cur_read], 0 |
and [ebp+NTFS.ntfs_cur_read], 0 |
.scandone: |
; c) Check for required offset and length |
mov ecx, [ntfs_attr_offs] |
mov ecx, [ebp+NTFS.ntfs_attr_offs] |
jecxz .noattr |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ebp+NTFS.ntfs_cur_size] |
push [ebp+NTFS.ntfs_cur_read] |
call .doreadattr |
pop edx |
pop eax |
pop ecx |
jc @f |
cmp [ntfs_bCanContinue], 0 |
cmp [ebp+NTFS.ntfs_bCanContinue], 0 |
jz @f |
sub edx, [ntfs_cur_read] |
sub edx, [ebp+NTFS.ntfs_cur_read] |
neg edx |
shr edx, 9 |
sub eax, edx |
mov [ntfs_cur_size], eax |
sub ecx, edx |
mov [ebp+NTFS.ntfs_cur_size], ecx |
jnz .not_in_cur |
@@: |
popad |
481,13 → 594,14 |
ret |
.noattr: |
.not_in_cur: |
cmp [ntfs_cur_attr], 0x20 |
cmp [ebp+NTFS.ntfs_cur_attr], 0x20 |
jz @f |
mov ecx, [ntfs_attr_list] |
mov ecx, [ebp+NTFS.ntfs_attr_list] |
test ecx, ecx |
jnz .lookattr |
.ret_is_attr: |
cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0 |
and dword [esp+28], 0 |
cmp [ebp+NTFS.ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0 |
popad |
ret |
.lookattr: |
494,49 → 608,49 |
; required attribute or required offset was not found in base record; |
; it may be present in auxiliary records; |
; scan $ATTR_LIST |
mov eax, [ntfs_attr_iBaseRecord] |
mov eax, [ebp+NTFS.ntfs_attr_iBaseRecord] |
cmp eax, -1 |
jz @f |
call ntfs_read_file_record |
test eax, eax |
jz .errret |
or [ntfs_attr_iBaseRecord], -1 |
jc .errret |
or [ebp+NTFS.ntfs_attr_iBaseRecord], -1 |
@@: |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
and [ntfs_cur_read], 0 |
mov eax, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
push [ebp+NTFS.ntfs_cur_offs] |
push [ebp+NTFS.ntfs_cur_size] |
push [ebp+NTFS.ntfs_cur_read] |
push [ebp+NTFS.ntfs_cur_buf] |
push dword [ebp+NTFS.ntfs_attr_size] |
push dword [ebp+NTFS.ntfs_attr_size+4] |
or dword [ebp+NTFS.ntfs_attr_size], -1 |
or dword [ebp+NTFS.ntfs_attr_size+4], -1 |
and [ebp+NTFS.ntfs_cur_offs], 0 |
mov [ebp+NTFS.ntfs_cur_size], 2 |
and [ebp+NTFS.ntfs_cur_read], 0 |
lea eax, [ebp+NTFS.ntfs_attrlist_buf] |
cmp [ebp+NTFS.ntfs_cur_iRecord], 0 |
jnz @f |
mov eax, ntfs_attrlist_mft_buf |
lea eax, [ebp+NTFS.ntfs_attrlist_mft_buf] |
@@: |
mov [ntfs_cur_buf], eax |
mov [ebp+NTFS.ntfs_cur_buf], eax |
push eax |
call .doreadattr |
pop esi |
mov edx, 1 |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
mov ebp, [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
pop dword [ebp+NTFS.ntfs_attr_size+4] |
pop dword [ebp+NTFS.ntfs_attr_size] |
mov ecx, [ebp+NTFS.ntfs_cur_read] |
pop [ebp+NTFS.ntfs_cur_buf] |
pop [ebp+NTFS.ntfs_cur_read] |
pop [ebp+NTFS.ntfs_cur_size] |
pop [ebp+NTFS.ntfs_cur_offs] |
jc .errret |
or edi, -1 |
lea ebp, [ebp+esi-1Ah] |
lea ecx, [ecx+esi-1Ah] |
.scanliststart: |
mov eax, [ntfs_cur_attr] |
push ecx |
mov eax, [ebp+NTFS.ntfs_cur_attr] |
.scanlist: |
cmp esi, ebp |
cmp esi, [esp] |
jae .scanlistdone |
cmp eax, [esi] |
jz @f |
555,26 → 669,28 |
mov eax, [esi+8] |
test eax, eax |
jnz .testf |
mov eax, dword [ntfs_attr_size] |
and eax, dword [ntfs_attr_size+4] |
mov eax, dword [ebp+NTFS.ntfs_attr_size] |
and eax, dword [ebp+NTFS.ntfs_attr_size+4] |
cmp eax, -1 |
jnz .testfz |
; if attribute is in auxiliary records, its size is defined only in first |
mov eax, [esi+10h] |
call ntfs_read_file_record |
test eax, eax |
jnz @f |
jnc @f |
.errret_pop: |
pop eax |
pop ecx ecx |
jmp .errret |
.errret2_pop: |
xor eax, eax |
jmp .errret_pop |
@@: |
mov eax, [ntfs_data.frs_buffer] |
mov eax, [ebp+NTFS.frs_buffer] |
movzx ecx, word [eax+14h] |
add eax, ecx |
mov ecx, [ntfs_cur_attr] |
mov ecx, [ebp+NTFS.ntfs_cur_attr] |
@@: |
cmp dword [eax], -1 |
jz .errret_pop |
jz .errret2_pop |
cmp dword [eax], ecx |
jz @f |
.l1: |
589,24 → 705,25 |
cmp byte [eax+8], 0 |
jnz .sdnores |
mov eax, [eax+10h] |
mov dword [ntfs_attr_size], eax |
and dword [ntfs_attr_size+4], 0 |
mov dword [ebp+NTFS.ntfs_attr_size], eax |
and dword [ebp+NTFS.ntfs_attr_size+4], 0 |
jmp .testfz |
.sdnores: |
mov ecx, [eax+30h] |
mov dword [ntfs_attr_size], ecx |
mov dword [ebp+NTFS.ntfs_attr_size], ecx |
mov ecx, [eax+34h] |
mov dword [ntfs_attr_size+4], ecx |
mov dword [ebp+NTFS.ntfs_attr_size+4], ecx |
.testfz: |
xor eax, eax |
.testf: |
imul eax, [ntfs_data.sectors_per_cluster] |
cmp eax, [ntfs_cur_offs] |
imul eax, [ebp+NTFS.sectors_per_cluster] |
cmp eax, [ebp+NTFS.ntfs_cur_offs] |
pop eax |
ja @f |
mov edi, [esi+10h] ; keep previous iRecord |
jmp .scanlistcont |
@@: |
pop ecx |
.scanlistfound: |
cmp edi, -1 |
jnz @f |
613,30 → 730,28 |
popad |
ret |
@@: |
mov eax, [ntfs_cur_iRecord] |
mov [ntfs_attr_iBaseRecord], eax |
mov eax, [ebp+NTFS.ntfs_cur_iRecord] |
mov [ebp+NTFS.ntfs_attr_iBaseRecord], eax |
mov eax, edi |
jmp .beginfindattr |
.sde: |
popad |
stc |
ret |
.scanlistdone: |
sub ebp, ntfs_attrlist_buf-1Ah |
cmp [ntfs_cur_iRecord], 0 |
pop ecx |
sub ecx, ebp |
sub ecx, NTFS.ntfs_attrlist_buf-1Ah |
cmp [ebp+NTFS.ntfs_cur_iRecord], 0 |
jnz @f |
sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
sub ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf |
@@: |
cmp ebp, 0x400 |
cmp ecx, 0x400 |
jnz .scanlistfound |
inc edx |
push esi edi |
mov esi, ntfs_attrlist_buf+0x200 |
mov edi, ntfs_attrlist_buf |
cmp [ntfs_cur_iRecord], 0 |
lea esi, [ebp+NTFS.ntfs_attrlist_buf+0x200] |
lea edi, [ebp+NTFS.ntfs_attrlist_buf] |
cmp [ebp+NTFS.ntfs_cur_iRecord], 0 |
jnz @f |
mov esi, ntfs_attrlist_mft_buf+0x200 |
mov edi, ntfs_attrlist_mft_buf |
lea esi, [ebp+NTFS.ntfs_attrlist_mft_buf+0x200] |
lea edi, [ebp+NTFS.ntfs_attrlist_mft_buf] |
@@: |
mov ecx, 0x200/4 |
rep movsd |
643,43 → 758,43 |
mov eax, edi |
pop edi esi |
sub esi, 0x200 |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_read] |
push [ntfs_cur_buf] |
push dword [ntfs_attr_size] |
push dword [ntfs_attr_size+4] |
or dword [ntfs_attr_size], -1 |
or dword [ntfs_attr_size+4], -1 |
mov [ntfs_cur_offs], edx |
mov [ntfs_cur_size], 1 |
and [ntfs_cur_read], 0 |
mov [ntfs_cur_buf], eax |
mov ecx, [ntfs_attr_list] |
push esi edx |
push [ebp+NTFS.ntfs_cur_offs] |
push [ebp+NTFS.ntfs_cur_size] |
push [ebp+NTFS.ntfs_cur_read] |
push [ebp+NTFS.ntfs_cur_buf] |
push dword [ebp+NTFS.ntfs_attr_size] |
push dword [ebp+NTFS.ntfs_attr_size+4] |
or dword [ebp+NTFS.ntfs_attr_size], -1 |
or dword [ebp+NTFS.ntfs_attr_size+4], -1 |
mov [ebp+NTFS.ntfs_cur_offs], edx |
mov [ebp+NTFS.ntfs_cur_size], 1 |
and [ebp+NTFS.ntfs_cur_read], 0 |
mov [ebp+NTFS.ntfs_cur_buf], eax |
mov ecx, [ebp+NTFS.ntfs_attr_list] |
push esi edx edi |
call .doreadattr |
pop edx esi |
mov ebp, [ntfs_cur_read] |
pop dword [ntfs_attr_size+4] |
pop dword [ntfs_attr_size] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_read] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
pop edi edx esi |
mov ecx, [ebp+NTFS.ntfs_cur_read] |
pop dword [ebp+NTFS.ntfs_attr_size+4] |
pop dword [ebp+NTFS.ntfs_attr_size] |
pop [ebp+NTFS.ntfs_cur_buf] |
pop [ebp+NTFS.ntfs_cur_read] |
pop [ebp+NTFS.ntfs_cur_size] |
pop [ebp+NTFS.ntfs_cur_offs] |
jc .errret |
add ebp, ntfs_attrlist_buf+0x200-0x1A |
cmp [ntfs_cur_iRecord], 0 |
lea ecx, [ecx+ebp+NTFS.ntfs_attrlist_buf+0x200-0x1A] |
cmp [ebp+NTFS.ntfs_cur_iRecord], 0 |
jnz .scanliststart |
add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf |
add ecx, NTFS.ntfs_attrlist_mft_buf-NTFS.ntfs_attrlist_buf |
jmp .scanliststart |
.doreadattr: |
mov [ntfs_bCanContinue], 0 |
mov [ebp+NTFS.ntfs_bCanContinue], 0 |
cmp byte [ecx+8], 0 |
jnz .nonresident |
mov eax, [ecx+10h] ; length |
mov esi, eax |
mov edx, [ntfs_cur_offs] |
mov edx, [ebp+NTFS.ntfs_cur_offs] |
shr eax, 9 |
cmp eax, edx |
jb .okret |
688,7 → 803,7 |
movzx eax, word [ecx+14h] |
add edx, eax |
add edx, ecx ; edx -> data |
mov eax, [ntfs_cur_size] |
mov eax, [ebp+NTFS.ntfs_cur_size] |
cmp eax, (0xFFFFFFFF shr 9)+1 |
jbe @f |
mov eax, (0xFFFFFFFF shr 9)+1 |
699,17 → 814,17 |
mov eax, esi |
@@: |
; eax = length, edx -> data |
mov [ntfs_cur_read], eax |
mov [ebp+NTFS.ntfs_cur_read], eax |
mov ecx, eax |
mov eax, edx |
mov ebx, [ntfs_cur_buf] |
mov ebx, [ebp+NTFS.ntfs_cur_buf] |
call memmove |
and [ntfs_cur_size], 0 ; CF=0 |
and [ebp+NTFS.ntfs_cur_size], 0 ; CF=0 |
ret |
.nonresident: |
; Not all auxiliary records contain correct FileSize info |
mov eax, dword [ntfs_attr_size] |
mov edx, dword [ntfs_attr_size+4] |
mov eax, dword [ebp+NTFS.ntfs_attr_size] |
mov edx, dword [ebp+NTFS.ntfs_attr_size+4] |
push eax |
and eax, edx |
cmp eax, -1 |
717,34 → 832,34 |
jnz @f |
mov eax, [ecx+30h] ; FileSize |
mov edx, [ecx+34h] |
mov dword [ntfs_attr_size], eax |
mov dword [ntfs_attr_size+4], edx |
mov dword [ebp+NTFS.ntfs_attr_size], eax |
mov dword [ebp+NTFS.ntfs_attr_size+4], edx |
@@: |
add eax, 0x1FF |
adc edx, 0 |
shrd eax, edx, 9 |
sub eax, [ntfs_cur_offs] |
sub eax, [ebp+NTFS.ntfs_cur_offs] |
ja @f |
; return with nothing read |
and [ntfs_cur_size], 0 |
and [ebp+NTFS.ntfs_cur_size], 0 |
.okret: |
clc |
ret |
@@: |
; reduce read length |
and [ntfs_cur_tail], 0 |
cmp [ntfs_cur_size], eax |
and [ebp+NTFS.ntfs_cur_tail], 0 |
cmp [ebp+NTFS.ntfs_cur_size], eax |
jb @f |
mov [ntfs_cur_size], eax |
mov eax, dword [ntfs_attr_size] |
mov [ebp+NTFS.ntfs_cur_size], eax |
mov eax, dword [ebp+NTFS.ntfs_attr_size] |
and eax, 0x1FF |
mov [ntfs_cur_tail], eax |
mov [ebp+NTFS.ntfs_cur_tail], eax |
@@: |
cmp [ntfs_cur_size], 0 |
cmp [ebp+NTFS.ntfs_cur_size], 0 |
jz .okret |
mov eax, [ntfs_cur_offs] |
mov eax, [ebp+NTFS.ntfs_cur_offs] |
xor edx, edx |
div [ntfs_data.sectors_per_cluster] |
div [ebp+NTFS.sectors_per_cluster] |
sub eax, [ecx+10h] ; first_vbo |
jb .okret |
; eax = cluster, edx = starting sector |
751,51 → 866,60 |
sub esp, 10h |
movzx esi, word [ecx+20h] ; mcb_info_ofs |
add esi, ecx |
xor ebp, ebp |
xor edi, edi |
.readloop: |
call ntfs_decode_mcb_entry |
jnc .break |
add ebp, [esp+8] |
add edi, [esp+8] |
sub eax, [esp] |
jae .readloop |
push ecx |
push eax |
add eax, [esp+8] |
add eax, ebp |
imul eax, [ntfs_data.sectors_per_cluster] |
add eax, edi |
imul eax, [ebp+NTFS.sectors_per_cluster] |
add eax, edx |
add eax, [PARTITION_START] |
pop ecx |
neg ecx |
imul ecx, [ntfs_data.sectors_per_cluster] |
imul ecx, [ebp+NTFS.sectors_per_cluster] |
sub ecx, edx |
cmp ecx, [ntfs_cur_size] |
cmp ecx, [ebp+NTFS.ntfs_cur_size] |
jb @f |
mov ecx, [ntfs_cur_size] |
mov ecx, [ebp+NTFS.ntfs_cur_size] |
@@: |
mov ebx, [ntfs_cur_buf] |
mov ebx, [ebp+NTFS.ntfs_cur_buf] |
@@: |
call hd_read |
cmp [hd_error], 0 |
push eax |
cmp [ebp+NTFS.ntfs_cur_attr], 0x80 |
jnz .sys |
cmp [ebp+NTFS.ntfs_cur_iRecord], 0 |
jz .sys |
call fs_read32_app |
jmp .appsys |
.sys: |
call fs_read32_sys |
.appsys: |
pop edx |
test eax, eax |
jnz .errread2 |
add ebx, 0x200 |
mov [ntfs_cur_buf], ebx |
inc eax |
add [ntfs_cur_read], 0x200 |
dec [ntfs_cur_size] |
inc [ntfs_cur_offs] |
mov [ebp+NTFS.ntfs_cur_buf], ebx |
lea eax, [edx+1] |
add [ebp+NTFS.ntfs_cur_read], 0x200 |
dec [ebp+NTFS.ntfs_cur_size] |
inc [ebp+NTFS.ntfs_cur_offs] |
loop @b |
pop ecx |
xor eax, eax |
xor edx, edx |
cmp [ntfs_cur_size], 0 |
cmp [ebp+NTFS.ntfs_cur_size], 0 |
jnz .readloop |
add esp, 10h |
mov eax, [ntfs_cur_tail] |
mov eax, [ebp+NTFS.ntfs_cur_tail] |
test eax, eax |
jz @f |
sub eax, 0x200 |
add [ntfs_cur_read], eax |
add [ebp+NTFS.ntfs_cur_read], eax |
@@: |
clc |
ret |
806,58 → 930,57 |
ret |
.break: |
add esp, 10h ; CF=0 |
mov [ntfs_bCanContinue], 1 |
mov [ebp+NTFS.ntfs_bCanContinue], 1 |
ret |
ntfs_read_file_record: |
; in: eax=iRecord |
; out: [ntfs_data.frs_buffer] contains information |
; eax=0 - failed, eax=1 - success |
; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size] |
; out: [ebp+NTFS.frs_buffer] contains information |
; CF=1 - failed, in this case eax=0 => something with FS, eax nonzero => disk error |
; Read attr $DATA of $Mft, starting from eax*[ebp+NTFS.frs_size] |
push ecx edx |
mov ecx, [ntfs_data.frs_size] |
mov ecx, [ebp+NTFS.frs_size] |
mul ecx |
shrd eax, edx, 9 |
shr edx, 9 |
jnz .err |
push [ntfs_attr_iRecord] |
push [ntfs_attr_iBaseRecord] |
push [ntfs_attr_offs] |
push [ntfs_attr_list] |
push dword [ntfs_attr_size+4] |
push dword [ntfs_attr_size] |
push [ntfs_cur_iRecord] |
push [ntfs_cur_attr] |
push [ntfs_cur_offs] |
push [ntfs_cur_size] |
push [ntfs_cur_buf] |
push [ntfs_cur_read] |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_iRecord], 0 ; $Mft |
mov [ntfs_cur_offs], eax |
jnz .errret |
push [ebp+NTFS.ntfs_attr_iRecord] |
push [ebp+NTFS.ntfs_attr_iBaseRecord] |
push [ebp+NTFS.ntfs_attr_offs] |
push [ebp+NTFS.ntfs_attr_list] |
push dword [ebp+NTFS.ntfs_attr_size+4] |
push dword [ebp+NTFS.ntfs_attr_size] |
push [ebp+NTFS.ntfs_cur_iRecord] |
push [ebp+NTFS.ntfs_cur_attr] |
push [ebp+NTFS.ntfs_cur_offs] |
push [ebp+NTFS.ntfs_cur_size] |
push [ebp+NTFS.ntfs_cur_buf] |
push [ebp+NTFS.ntfs_cur_read] |
mov [ebp+NTFS.ntfs_cur_attr], 0x80 ; $DATA |
and [ebp+NTFS.ntfs_cur_iRecord], 0 ; $Mft |
mov [ebp+NTFS.ntfs_cur_offs], eax |
shr ecx, 9 |
mov [ntfs_cur_size], ecx |
mov eax, [ntfs_data.frs_buffer] |
mov [ntfs_cur_buf], eax |
mov [ebp+NTFS.ntfs_cur_size], ecx |
mov eax, [ebp+NTFS.frs_buffer] |
mov [ebp+NTFS.ntfs_cur_buf], eax |
call ntfs_read_attr |
mov eax, [ntfs_cur_read] |
pop [ntfs_cur_read] |
pop [ntfs_cur_buf] |
pop [ntfs_cur_size] |
pop [ntfs_cur_offs] |
pop [ntfs_cur_attr] |
pop [ntfs_cur_iRecord] |
pop dword [ntfs_attr_size] |
pop dword [ntfs_attr_size+4] |
pop [ntfs_attr_list] |
pop [ntfs_attr_offs] |
pop [ntfs_attr_iBaseRecord] |
pop [ntfs_attr_iRecord] |
pop edx ecx |
jc .errret |
cmp eax, [ntfs_data.frs_size] |
mov edx, [ebp+NTFS.ntfs_cur_read] |
pop [ebp+NTFS.ntfs_cur_read] |
pop [ebp+NTFS.ntfs_cur_buf] |
pop [ebp+NTFS.ntfs_cur_size] |
pop [ebp+NTFS.ntfs_cur_offs] |
pop [ebp+NTFS.ntfs_cur_attr] |
pop [ebp+NTFS.ntfs_cur_iRecord] |
pop dword [ebp+NTFS.ntfs_attr_size] |
pop dword [ebp+NTFS.ntfs_attr_size+4] |
pop [ebp+NTFS.ntfs_attr_list] |
pop [ebp+NTFS.ntfs_attr_offs] |
pop [ebp+NTFS.ntfs_attr_iBaseRecord] |
pop [ebp+NTFS.ntfs_attr_iRecord] |
jc .ret |
cmp edx, [ebp+NTFS.frs_size] |
jnz .errret |
mov eax, [ntfs_data.frs_buffer] |
mov eax, [ebp+NTFS.frs_buffer] |
cmp dword [eax], 'FILE' |
jnz .errret |
push ebx |
864,18 → 987,18 |
mov ebx, eax |
call ntfs_restore_usa_frs |
pop ebx |
setnc al |
movzx eax, al |
jc .errret |
.ret: |
pop edx ecx |
ret |
.err: |
.errret: |
pop edx ecx |
.errret: |
xor eax, eax |
stc |
ret |
ntfs_restore_usa_frs: |
mov eax, [ntfs_data.frs_size] |
mov eax, [ebp+NTFS.frs_size] |
ntfs_restore_usa: |
pushad |
shr eax, 9 |
955,82 → 1078,83 |
ret |
ntfs_find_lfn: |
; in: esi+ebp -> name |
; in: esi+[esp+4] -> name |
; out: CF=1 - file not found |
; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory |
mov [ntfs_cur_iRecord], 5 ; start parse from root cluster |
; else CF=0, [ebp+NTFS.ntfs_cur_iRecord] valid, eax->record in parent directory |
mov [ebp+NTFS.ntfs_cur_iRecord], 5 ; start parse from root cluster |
.doit2: |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
mov [ebp+NTFS.ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ebp+NTFS.ntfs_cur_offs], 0 |
mov eax, [ebp+NTFS.cur_index_size] |
mov [ebp+NTFS.ntfs_cur_size], eax |
mov eax, [ebp+NTFS.cur_index_buf] |
mov [ebp+NTFS.ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc @f |
.ret: |
ret |
ret 4 |
@@: |
cmp [ntfs_cur_read], 0x20 |
xor eax, eax |
cmp [ebp+NTFS.ntfs_cur_read], 0x20 |
jc .ret |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov esi, [ebp+NTFS.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
cmp [ebp+NTFS.ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
cmp eax, [ebp+NTFS.cur_index_size] |
ja @f |
.stc_ret: |
popad |
stc |
ret |
ret 4 |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
push [ebp+NTFS.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
mov [ebp+NTFS.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
and [ebp+NTFS.cur_index_size], 0 |
and [ebp+NTFS.cur_index_buf], 0 |
jmp .stc_ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
mov [ebp+NTFS.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
mov edx, [esi+8] ; subnode_size |
shr edx, 9 |
cmp edx, [ebp+NTFS.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
push esi edx |
push edx |
call kernel_alloc |
pop ebp esi |
pop edx esi |
test eax, eax |
jz .stc_ret |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
mov ecx, [ebp+NTFS.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
mov [ebp+NTFS.cur_index_size], edx |
push esi edx |
push [ebp+NTFS.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
pop edx esi |
mov [ebp+NTFS.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov edi, [esp+4] |
; edi -> name, esi -> current index data, ebp = subnode size |
; edi -> name, esi -> current index data, edx = subnode size |
.scanloop: |
add esi, [esi] |
.scanloopint: |
1070,17 → 1194,19 |
jz .notfound |
movzx eax, word [esi+8] |
mov eax, [esi+eax-8] |
mul [ntfs_data.sectors_per_cluster] |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
imul eax, [ebp+NTFS.sectors_per_cluster] |
mov [ebp+NTFS.ntfs_cur_offs], eax |
mov [ebp+NTFS.ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION |
mov [ebp+NTFS.ntfs_cur_size], edx |
mov eax, [ebp+NTFS.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
mov [ebp+NTFS.ntfs_cur_buf], eax |
push edx |
call ntfs_read_attr |
mov eax, ebp |
pop edx |
mov eax, edx |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
cmp [ebp+NTFS.ntfs_cur_read], eax |
jnz .notfound |
cmp dword [esi], 'INDX' |
jnz .notfound |
1092,7 → 1218,7 |
.notfound: |
popad |
stc |
ret |
ret 4 |
.found: |
cmp byte [edi], 0 |
jz .done |
1106,7 → 1232,7 |
pop esi |
pop esi |
mov eax, [esi] |
mov [ntfs_cur_iRecord], eax |
mov [ebp+NTFS.ntfs_cur_iRecord], eax |
mov [esp+1Ch], esi |
mov [esp+4], edi |
popad |
1113,29 → 1239,22 |
inc esi |
cmp byte [esi-1], 0 |
jnz .doit2 |
test ebp, ebp |
cmp dword [esp+4], 0 |
jz @f |
mov esi, ebp |
xor ebp, ebp |
mov esi, [esp+4] |
mov dword [esp+4], 0 |
jmp .doit2 |
@@: |
ret |
ret 4 |
;---------------------------------------------------------------- |
; |
; ntfs_HdRead - read NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRead: |
; ntfs_Read - NTFS implementation of reading a file |
; in: ebp = pointer to NTFS structure |
; in: esi+[esp+4] = name |
; in: ebx = pointer to parameters from sysfunc 70 |
; out: eax, ebx = return values for sysfunc 70 |
;---------------------------------------------------------------- |
ntfs_Read: |
cmp byte [esi], 0 |
jnz @f |
or ebx, -1 |
1142,17 → 1261,20 |
movi eax, ERROR_ACCESS_DENIED |
ret |
@@: |
call ntfs_find_lfn |
call ntfs_lock |
stdcall ntfs_find_lfn, [esp+4] |
jnc .found |
call ntfs_unlock |
or ebx, -1 |
movi eax, ERROR_FILE_NOT_FOUND |
ret |
.found: |
mov [ntfs_cur_attr], 0x80 ; $DATA |
and [ntfs_cur_offs], 0 |
and [ntfs_cur_size], 0 |
mov [ebp+NTFS.ntfs_cur_attr], 0x80 ; $DATA |
and [ebp+NTFS.ntfs_cur_offs], 0 |
and [ebp+NTFS.ntfs_cur_size], 0 |
call ntfs_read_attr |
jnc @f |
call ntfs_unlock |
or ebx, -1 |
movi eax, ERROR_ACCESS_DENIED |
ret |
1160,9 → 1282,7 |
pushad |
and dword [esp+10h], 0 |
xor eax, eax |
test ebx, ebx |
jz .zero1 |
cmp dword [ebx+4], 0x200 |
cmp dword [ebx+8], 0x200 |
jb @f |
.eof0: |
popad |
1169,23 → 1289,29 |
xor ebx, ebx |
.eof: |
movi eax, ERROR_END_OF_FILE |
push eax |
call ntfs_unlock |
pop eax |
ret |
@@: |
mov eax, [ebx] |
mov ecx, [ebx+12] |
mov edx, [ebx+16] |
mov eax, [ebx+4] |
test eax, 0x1FF |
jz .alignedstart |
push edx |
mov edx, [ebx+4] |
mov edx, [ebx+8] |
shrd eax, edx, 9 |
pop edx |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
mov [ebp+NTFS.ntfs_cur_offs], eax |
mov [ebp+NTFS.ntfs_cur_size], 1 |
lea eax, [ebp+NTFS.ntfs_bitmap_buf] |
mov [ebp+NTFS.ntfs_cur_buf], eax |
call ntfs_read_attr.continue |
mov eax, [ebx] |
mov eax, [ebx+4] |
and eax, 0x1FF |
lea esi, [ntfs_bitmap_buf+eax] |
sub eax, [ntfs_cur_read] |
lea esi, [ebp+NTFS.ntfs_bitmap_buf+eax] |
sub eax, [ebp+NTFS.ntfs_cur_read] |
jae .eof0 |
neg eax |
push ecx |
1202,115 → 1328,113 |
jnz @f |
.retok: |
popad |
call ntfs_unlock |
xor eax, eax |
ret |
@@: |
cmp [ntfs_cur_read], 0x200 |
cmp [ebp+NTFS.ntfs_cur_read], 0x200 |
jz .alignedstart |
.eof_ebx: |
popad |
jmp .eof |
.alignedstart: |
mov eax, [ebx] |
mov eax, [ebx+4] |
push edx |
mov edx, [ebx+4] |
mov edx, [ebx+8] |
add eax, 511 |
adc edx, 0 |
shrd eax, edx, 9 |
pop edx |
.zero1: |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_buf], edx |
mov [ebp+NTFS.ntfs_cur_offs], eax |
mov [ebp+NTFS.ntfs_cur_buf], edx |
mov eax, ecx |
shr eax, 9 |
mov [ntfs_cur_size], eax |
add eax, [ntfs_cur_offs] |
mov [ebp+NTFS.ntfs_cur_size], eax |
add eax, [ebp+NTFS.ntfs_cur_offs] |
push eax |
call ntfs_read_attr.continue |
pop [ntfs_cur_offs] |
mov eax, [ntfs_cur_read] |
pop [ebp+NTFS.ntfs_cur_offs] |
mov eax, [ebp+NTFS.ntfs_cur_read] |
add [esp+10h], eax |
mov eax, ecx |
and eax, not 0x1FF |
cmp [ntfs_cur_read], eax |
cmp [ebp+NTFS.ntfs_cur_read], eax |
jnz .eof_ebx |
and ecx, 0x1FF |
jz .retok |
add edx, [ntfs_cur_read] |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
add edx, [ebp+NTFS.ntfs_cur_read] |
mov [ebp+NTFS.ntfs_cur_size], 1 |
lea eax, [ebp+NTFS.ntfs_bitmap_buf] |
mov [ebp+NTFS.ntfs_cur_buf], eax |
call ntfs_read_attr.continue |
cmp [ntfs_cur_read], ecx |
cmp [ebp+NTFS.ntfs_cur_read], ecx |
jb @f |
mov [ntfs_cur_read], ecx |
mov [ebp+NTFS.ntfs_cur_read], ecx |
@@: |
xchg ecx, [ntfs_cur_read] |
xchg ecx, [ebp+NTFS.ntfs_cur_read] |
push ecx |
mov edi, edx |
mov esi, ntfs_bitmap_buf |
lea esi, [ebp+NTFS.ntfs_bitmap_buf] |
add [esp+10h+4], ecx |
rep movsb |
pop ecx |
xor eax, eax |
cmp ecx, [ntfs_cur_read] |
cmp ecx, [ebp+NTFS.ntfs_cur_read] |
jz @f |
mov al, ERROR_END_OF_FILE |
@@: |
mov [esp+1Ch], eax |
call ntfs_unlock |
popad |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdReadFolder - read NTFS hard disk folder |
; |
; esi points to filename |
; ebx pointer to structure 32-bit number = first wanted block, 0+ |
; & flags (bitfields) |
; flags: bit 0: 0=ANSI names, 1=UNICODE names |
; ecx number of blocks to read, 0+ |
; edx mem location to return data |
; |
; ret ebx = blocks read or 0xffffffff folder not found |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdReadFolder: |
; ntfs_ReadFolder - NTFS implementation of reading a folder |
; in: ebp = pointer to NTFS structure |
; in: esi+[esp+4] = name |
; in: ebx = pointer to parameters from sysfunc 70 |
; out: eax, ebx = return values for sysfunc 70 |
;---------------------------------------------------------------- |
ntfs_ReadFolder: |
call ntfs_lock |
mov eax, 5 ; root cluster |
cmp byte [esi], 0 |
jz .doit |
call ntfs_find_lfn |
stdcall ntfs_find_lfn, [esp+4] |
jnc .doit2 |
.notfound: |
or ebx, -1 |
push ERROR_FILE_NOT_FOUND |
.pop_ret: |
call ntfs_unlock |
pop eax |
ret |
.doit: |
mov [ntfs_cur_iRecord], eax |
mov [ebp+NTFS.ntfs_cur_iRecord], eax |
.doit2: |
mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 1 |
mov [ntfs_cur_buf], ntfs_bitmap_buf |
mov [ebp+NTFS.ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION |
and [ebp+NTFS.ntfs_cur_offs], 0 |
mov [ebp+NTFS.ntfs_cur_size], 1 |
lea eax, [ebp+NTFS.ntfs_bitmap_buf] |
mov [ebp+NTFS.ntfs_cur_buf], eax |
call ntfs_read_attr |
jc .notfound |
mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ntfs_cur_offs], 0 |
mov eax, [ntfs_data.cur_index_size] |
mov [ntfs_cur_size], eax |
mov eax, [ntfs_data.cur_index_buf] |
mov [ntfs_cur_buf], eax |
mov [ebp+NTFS.ntfs_cur_attr], 0x90 ; $INDEX_ROOT |
and [ebp+NTFS.ntfs_cur_offs], 0 |
mov eax, [ebp+NTFS.cur_index_size] |
mov [ebp+NTFS.ntfs_cur_size], eax |
mov eax, [ebp+NTFS.cur_index_buf] |
mov [ebp+NTFS.ntfs_cur_buf], eax |
call ntfs_read_attr |
jnc .ok |
cmp [hd_error], 0 |
test eax, eax |
jz .notfound |
or ebx, -1 |
push 11 |
jmp .pop_ret |
.ok: |
cmp [ntfs_cur_read], 0x20 |
cmp [ebp+NTFS.ntfs_cur_read], 0x20 |
jae @f |
or ebx, -1 |
.fserr: |
1318,14 → 1442,14 |
jmp .pop_ret |
@@: |
pushad |
mov esi, [ntfs_data.cur_index_buf] |
mov esi, [ebp+NTFS.cur_index_buf] |
mov eax, [esi+14h] |
add eax, 10h |
cmp [ntfs_cur_read], eax |
cmp [ebp+NTFS.ntfs_cur_read], eax |
jae .readok1 |
add eax, 1FFh |
shr eax, 9 |
cmp eax, [ntfs_data.cur_index_size] |
cmp eax, [ebp+NTFS.cur_index_size] |
ja @f |
popad |
jmp .fserr |
1332,53 → 1456,51 |
@@: |
; reallocate |
push eax |
push [ntfs_data.cur_index_buf] |
push [ebp+NTFS.cur_index_buf] |
call kernel_free |
pop eax |
mov [ntfs_data.cur_index_size], eax |
mov [ebp+NTFS.cur_index_size], eax |
push eax |
call kernel_alloc |
test eax, eax |
jnz @f |
and [ntfs_data.cur_index_size], 0 |
and [ntfs_data.cur_index_buf], 0 |
and [ebp+NTFS.cur_index_size], 0 |
and [ebp+NTFS.cur_index_buf], 0 |
.nomem: |
call ntfs_unlock |
popad |
or ebx, -1 |
movi eax, 12 |
ret |
@@: |
mov [ntfs_data.cur_index_buf], eax |
mov [ebp+NTFS.cur_index_buf], eax |
popad |
jmp .doit2 |
.readok1: |
mov ebp, [esi+8] ; subnode_size |
shr ebp, 9 |
cmp ebp, [ntfs_data.cur_index_size] |
mov edx, [esi+8] ; subnode_size |
shr edx, 9 |
mov [ebp+NTFS.cur_subnode_size], edx |
cmp edx, [ebp+NTFS.cur_index_size] |
jbe .ok2 |
push esi ebp |
push ebp |
push esi edx |
push edx |
call kernel_alloc |
pop ebp esi |
pop edx esi |
test eax, eax |
jz .nomem |
mov edi, eax |
mov ecx, [ntfs_data.cur_index_size] |
mov ecx, [ebp+NTFS.cur_index_size] |
shl ecx, 9-2 |
rep movsd |
mov esi, eax |
mov [ntfs_data.cur_index_size], ebp |
push esi ebp |
push [ntfs_data.cur_index_buf] |
mov [ebp+NTFS.cur_index_size], edx |
push [ebp+NTFS.cur_index_buf] |
call kernel_free |
pop ebp esi |
mov [ntfs_data.cur_index_buf], esi |
mov [ebp+NTFS.cur_index_buf], esi |
.ok2: |
add esi, 10h |
mov ebx, [esp+10h] |
mov edx, [esp+14h] |
push dword [ebx+4] ; read ANSI/UNICODE name |
mov ebx, [ebx] |
mov edx, [ebx+16] |
push dword [ebx+8] ; read ANSI/UNICODE name |
; init header |
mov edi, edx |
mov ecx, 32/4 |
1385,13 → 1507,14 |
xor eax, eax |
rep stosd |
mov byte [edx], 1 ; version |
mov ecx, [esp+4+18h] |
mov ecx, [ebx+12] |
mov ebx, [ebx+4] |
push edx |
mov edx, esp |
; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block, |
; edi -> BDFE, esi -> current index data, ebx = first wanted block, |
; ecx = number of blocks to read |
; edx -> parameters block: dd <output>, dd <flags> |
cmp [ntfs_cur_iRecord], 5 |
cmp [ebp+NTFS.ntfs_cur_iRecord], 5 |
jz .skip_specials |
; dot and dotdot entries |
push esi |
1413,38 → 1536,39 |
.dump_root_done: |
; now dump all subnodes |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
lea edi, [ebp+NTFS.ntfs_bitmap_buf] |
mov [ebp+NTFS.ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
mov [ntfs_cur_attr], 0xB0 ; $BITMAP |
and [ntfs_cur_offs], 0 |
mov [ntfs_cur_size], 2 |
mov [ebp+NTFS.ntfs_cur_attr], 0xB0 ; $BITMAP |
and [ebp+NTFS.ntfs_cur_offs], 0 |
mov [ebp+NTFS.ntfs_cur_size], 2 |
call ntfs_read_attr |
pop edi ecx |
push 0 ; save offset in $BITMAP attribute |
and [ntfs_cur_offs], 0 |
and [ebp+NTFS.ntfs_cur_offs], 0 |
.dumploop: |
mov [ntfs_cur_attr], 0xA0 |
mov [ntfs_cur_size], ebp |
mov eax, [ntfs_data.cur_index_buf] |
mov [ebp+NTFS.ntfs_cur_attr], 0xA0 |
mov eax, [ebp+NTFS.cur_subnode_size] |
mov [ebp+NTFS.ntfs_cur_size], eax |
mov eax, [ebp+NTFS.cur_index_buf] |
mov esi, eax |
mov [ntfs_cur_buf], eax |
push [ntfs_cur_offs] |
mov eax, [ntfs_cur_offs] |
imul eax, ebp |
mov [ntfs_cur_offs], eax |
mov [ebp+NTFS.ntfs_cur_buf], eax |
push [ebp+NTFS.ntfs_cur_offs] |
mov eax, [ebp+NTFS.ntfs_cur_offs] |
imul eax, [ebp+NTFS.cur_subnode_size] |
mov [ebp+NTFS.ntfs_cur_offs], eax |
call ntfs_read_attr |
pop [ntfs_cur_offs] |
mov eax, ebp |
pop [ebp+NTFS.ntfs_cur_offs] |
mov eax, [ebp+NTFS.cur_subnode_size] |
shl eax, 9 |
cmp [ntfs_cur_read], eax |
cmp [ebp+NTFS.ntfs_cur_read], eax |
jnz .done |
push eax |
mov eax, [ntfs_cur_offs] |
mov eax, [ebp+NTFS.ntfs_cur_offs] |
and eax, 0x400*8-1 |
bt dword [ntfs_bitmap_buf], eax |
bt dword [ebp+NTFS.ntfs_bitmap_buf], eax |
pop eax |
jnc .dump_subnode_done |
cmp dword [esi], 'INDX' |
1464,26 → 1588,26 |
add esi, eax |
jmp .dump_subnode |
.dump_subnode_done: |
inc [ntfs_cur_offs] |
test [ntfs_cur_offs], 0x400*8-1 |
inc [ebp+NTFS.ntfs_cur_offs] |
test [ebp+NTFS.ntfs_cur_offs], 0x400*8-1 |
jnz .dumploop |
mov [ntfs_cur_attr], 0xB0 |
mov [ebp+NTFS.ntfs_cur_attr], 0xB0 |
push ecx edi |
mov edi, ntfs_bitmap_buf |
mov [ntfs_cur_buf], edi |
lea edi, [ebp+NTFS.ntfs_bitmap_buf] |
mov [ebp+NTFS.ntfs_cur_buf], edi |
mov ecx, 0x400/4 |
xor eax, eax |
rep stosd |
pop edi ecx |
pop eax |
push [ntfs_cur_offs] |
push [ebp+NTFS.ntfs_cur_offs] |
inc eax |
mov [ntfs_cur_offs], eax |
mov [ntfs_cur_size], 2 |
mov [ebp+NTFS.ntfs_cur_offs], eax |
mov [ebp+NTFS.ntfs_cur_size], 2 |
push eax |
call ntfs_read_attr |
pop eax |
pop [ntfs_cur_offs] |
pop [ebp+NTFS.ntfs_cur_offs] |
push eax |
jmp .dumploop |
.done: |
1498,6 → 1622,7 |
@@: |
mov [esp+1Ch], eax |
mov [esp+10h], ebx |
call ntfs_unlock |
popad |
ret |
1517,14 → 1642,14 |
stosd |
scasd |
push edx |
mov eax, dword [ntfs_bitmap_buf] |
mov edx, dword [ntfs_bitmap_buf+4] |
mov eax, dword [ebp+NTFS.ntfs_bitmap_buf] |
mov edx, dword [ebp+NTFS.ntfs_bitmap_buf+4] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+0x18] |
mov edx, dword [ntfs_bitmap_buf+0x1C] |
mov eax, dword [ebp+NTFS.ntfs_bitmap_buf+0x18] |
mov edx, dword [ebp+NTFS.ntfs_bitmap_buf+0x1C] |
call ntfs_datetime_to_bdfe |
mov eax, dword [ntfs_bitmap_buf+8] |
mov edx, dword [ntfs_bitmap_buf+0xC] |
mov eax, dword [ebp+NTFS.ntfs_bitmap_buf+8] |
mov edx, dword [ebp+NTFS.ntfs_bitmap_buf+0xC] |
call ntfs_datetime_to_bdfe |
pop edx |
xor eax, eax |
1733,90 → 1858,69 |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdRewrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx ignored (reserved) |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = number of written bytes |
; eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdRewrite: |
; ntfs_Rewrite - NTFS implementation of creating a new file |
; in: ebp = pointer to NTFS structure |
; in: esi+[esp+4] = name |
; in: ebx = pointer to parameters from sysfunc 70 |
; out: eax, ebx = return values for sysfunc 70 |
;---------------------------------------------------------------- |
ntfs_Rewrite: |
ntfs_CreateFolder: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdWrite - write to NTFS hard disk |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdWrite: |
; ntfs_Write - NTFS implementation of writing to file |
; in: ebp = pointer to NTFS structure |
; in: esi+[esp+4] = name |
; in: ebx = pointer to parameters from sysfunc 70 |
; out: eax, ebx = return values for sysfunc 70 |
;---------------------------------------------------------------- |
ntfs_Write: |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ntfs_HdSetFileEnd - set end of file on NTFS hard disk |
; |
; esi points to filename |
; ebx points to 64-bit number = new file size |
; ecx ignored (reserved) |
; edx ignored (reserved) |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdSetFileEnd: |
ntfs_HdSetFileInfo: |
;---------------------------------------------------------------- |
; |
; ntfs_HdDelete - delete file or empty folder from NTFS hard disk |
; |
; esi points to filename |
; |
; ret eax = 0 ok or other = errormsg |
; |
;-------------------------------------------------------------- |
ntfs_HdDelete: |
ntfs_SetFileEnd: |
ntfs_SetFileInfo: |
ntfs_Delete: |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
ntfs_HdGetFileInfo: |
;---------------------------------------------------------------- |
; ntfs_GetFileInfo - NTFS implementation of getting file info |
; in: ebp = pointer to NTFS structure |
; in: esi+[esp+4] = name |
; in: ebx = pointer to parameters from sysfunc 70 |
; out: eax, ebx = return values for sysfunc 70 |
;---------------------------------------------------------------- |
ntfs_GetFileInfo: |
cmp byte [esi], 0 |
jnz @f |
movi eax, 2 |
ret |
@@: |
call ntfs_find_lfn |
call ntfs_lock |
stdcall ntfs_find_lfn, [esp+4] |
jnc .doit |
test eax, eax |
movi eax, ERROR_FILE_NOT_FOUND |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: |
push eax |
call ntfs_unlock |
pop eax |
ret |
.doit: |
push esi edi |
mov esi, eax |
mov edi, edx |
mov edi, [ebx+16] |
xor eax, eax |
call ntfs_direntry_to_bdfe |
pop edi esi |
call ntfs_unlock |
xor eax, eax |
ret |