17,45 → 17,32 |
EXT2_BOOT_LOADER_INO= 5 |
EXT2_UNDEL_DIR_INO = 6 |
|
;type inode |
;флаги, указываемый в inode файла |
EXT2_S_IFREG = 0x8000 |
EXT2_S_IFDIR = 0x4000 |
;user inode right's |
EXT2_S_IRUSR = 0x0100 |
EXT2_S_IWUSR = 0x0080 |
EXT2_S_IXUSR = 0x0040 |
;group inode right's |
EXT2_S_IRGRP = 0x0020 |
EXT2_S_IWGRP = 0x0010 |
EXT2_S_IXGRP = 0x0008 |
;other inode right's |
EXT2_S_IROTH = 0x0004 |
EXT2_S_IWOTH = 0x0002 |
EXT2_S_IXOTH = 0x0001 |
EXT2_777_MODE = EXT2_S_IROTH or EXT2_S_IWOTH or EXT2_S_IXOTH or \ |
EXT2_S_IRGRP or EXT2_S_IWGRP or EXT2_S_IXGRP or \ |
EXT2_S_IRUSR or EXT2_S_IWUSR or EXT2_S_IXUSR |
|
;флаги, указываемые в linked list родительской папки |
EXT2_FT_REG_FILE = 1 ;это файл, запись в родительском каталоге |
EXT2_FT_DIR = 2 ;это папка |
|
;флаги используемые KolibriOS |
FS_FT_HIDDEN = 2 |
FS_FT_DIR = 0x10 ;это папка |
FS_FT_ASCII = 0 ;имя в ascii |
FS_FT_UNICODE = 1 ;имя в unicode |
|
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 |
EXT2_FEATURE_INCOMPAT_FILETYPE = 0x0002 ;тип файла должен указываться в директории |
EXT4_FEATURE_INCOMPAT_EXTENTS = 0x0040 ;экстенты |
EXT4_FEATURE_INCOMPAT_FLEX_BG = 0x0200 ;гибкие группы блоков |
;реализованные ext[234] features |
EXT4_FEATURE_INCOMPAT_SUPP = EXT2_FEATURE_INCOMPAT_FILETYPE \ |
or EXT4_FEATURE_INCOMPAT_EXTENTS \ |
or EXT4_FEATURE_INCOMPAT_FLEX_BG |
|
uglobal |
EXT2_files_in_folder dd ? ;всего файлов в папке |
EXT2_read_in_folder dd ? ;сколько файлов "считали" |
EXT2_end_block dd ? ;конец очередного блока папки |
EXT2_counter_blocks dd ? |
EXT2_filename rb 256 |
EXT2_parent_name rb 256 |
EXT2_name_len dd ? |
endg |
|
;флаги, указываемые для inode в i_flags |
EXT2_EXTENTS_FL = 0x00080000 |
|
struct EXT2_INODE_STRUC |
i_mode dw ? |
i_uid dw ? |
86,12 → 73,14 |
ends |
|
struct EXT2_BLOCK_GROUP_DESC |
block_bitmap dd ? |
inode_bitmap dd ? |
inode_table dd ? |
free_blocks_count dw ? |
free_inodes_count dw ? |
used_dirs_count dw ? |
block_bitmap dd ? ;+0 |
inode_bitmap dd ? ;+4 |
inode_table dd ? ;+8 |
free_blocks_count dw ? ;+12 |
free_inodes_count dw ? ;+14 |
used_dirs_count dw ? ;+16 |
pad dw ? ;+18 |
reserved rb 12;+20 |
ends |
|
struct EXT2_SB_STRUC |
132,7 → 121,7 |
algo_bitmap dd ? ;+200 |
prealloc_blocks db ? ;+204 |
preallock_dir_blocks db ? ;+205 |
dw ? ;+206 alignment |
reserved_gdt_blocks dw ? ;+206 |
journal_uuid rb 16 ;+208 |
journal_inum dd ? ;+224 |
journal_dev dd ? ;+228 |
142,8 → 131,43 |
rb 3 ;+253 reserved |
default_mount_options dd ? ;+256 |
first_meta_bg dd ? ;+260 |
mkfs_time dd ? ;+264 |
jnl_blocks rd 17 ;+268 |
blocks_count_hi dd ? ;+336 |
r_blocks_count_hi dd ? ;+340 |
free_blocks_count_hi dd ? ;+344 |
min_extra_isize dw ? ;+348 |
want_extra_isize dw ? ;+350 |
flags dd ? ;+352 |
raid_stride dw ? ;+356 |
mmp_interval dw ? ;+358 |
mmp_block dq ? ;+360 |
raid_stripe_width dd ? ;+368 |
log_groups_per_flex db ? ;+372 |
ends |
|
struct EXT4_EXTENT_HEADER ;заголовок блока экстентов/индексов |
eh_magic dw ? ;в текущей реализации ext4 должно быть 0xF30A |
eh_entries dw ? ;количество экстентов/индексов в блоке |
eh_max dw ? ;max количество (используется при записи) |
eh_depth dw ? ;глубина дерева (0, если это блок экстентов) |
eh_generation dd ? ;??? |
ends |
|
struct EXT4_EXTENT ;экстент |
ee_block dd ? ;номер ext4 блока |
ee_len dw ? ;длина экстента |
ee_start_hi dw ? ;старшие 16 бит 48-битного адреса (пока не используются в KOS) |
ee_start_lo dd ? ;младшие 32 бита 48-битного адреса |
ends |
|
struct EXT4_EXTENT_IDX ;индес - указатель на блок с экстентами/индексами |
ei_block dd ? ;номер ext4 блока |
ei_leaf_lo dd ? ;младшие 32 бит 48-битного адреса |
ei_leaf_hi dw ? ;старшие 16 бит 48-битного адреса (пока не используются в KOS) |
ei_unused dw ? ;зарезервировано |
ends |
|
ext2_test_superblock: |
cmp [fs_type], 0x83 |
jne .no |
152,16 → 176,19 |
add eax, 2 ;superblock start at 1024b |
call hd_read |
|
cmp dword [ebx+24], 3 ;s_block_size 0,1,2,3 |
cmp [ebx + EXT2_SB_STRUC.log_block_size], 3 ;0,1,2,3 |
ja .no |
cmp word [ebx+56], 0xEF53 ;s_magic |
cmp [ebx + EXT2_SB_STRUC.magic], 0xEF53 |
jne .no |
cmp word [ebx+58], 1 ;s_state (EXT_VALID_FS=1) |
cmp [ebx + EXT2_SB_STRUC.state], 1 ;EXT_VALID_FS=1 |
jne .no |
mov eax, [ebx+96] |
cmp [ebx + EXT2_SB_STRUC.inodes_per_group], 0 |
je .no |
|
mov eax, [ebx + EXT2_SB_STRUC.feature_incompat] |
test eax, EXT2_FEATURE_INCOMPAT_FILETYPE |
jz .no |
test eax, not EXT2_FEATURE_INCOMPAT_FILETYPE |
test eax, not EXT4_FEATURE_INCOMPAT_SUPP |
jnz .no |
|
; OK, this is correct EXT2 superblock |
192,7 → 219,7 |
inc eax |
mov [ext2_data.groups_count], eax |
|
mov ecx, [ebx+24] |
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 |
|
218,13 → 245,11 |
call kernel_alloc |
mov [ext2_data.ext2_temp_block], eax ; and for get_inode proc |
|
movzx ebp, word [ebx+88] |
mov ecx, [ebx+32] |
mov edx, [ebx+40] |
movzx ebp, 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 [ext2_data.inodes_per_group], edx |
|
push ebp ebp ebp ;3 kernel_alloc |
call kernel_alloc |
241,10 → 266,12 |
jmp return_from_part_set |
|
;================================================================== |
;in: eax = i_block |
;read ext2 block form FS to memory |
;in: eax = i_block (address of block in ext2 terms) |
; ebx = pointer to return memory |
;out: eax - error code (0 = no_error) |
ext2_get_block: |
push eax ebx ecx |
push ebx ecx |
mov ecx, [ext2_data.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] |
251,21 → 278,118 |
mov ecx, [ext2_data.count_block_in_block] |
@@: |
call hd_read |
cmp [hd_error], 0 |
jnz .fail |
inc eax |
add ebx, 512 |
loop @B |
pop ecx ebx eax |
xor eax, eax |
@@: |
pop ecx ebx |
ret |
.fail: |
mov eax, ERROR_DEVICE |
jmp @B |
|
|
;=================================================================== |
;получает номер блока из extent inode |
;in: ecx = номер блока по порядку |
; ebp = адрес extent header`а |
;out: ecx - адрес очередного блока в случае успеха |
; eax - номер ошибки (если равно 0, то ошибки нет) |
ext4_block_recursive_search: |
cmp word [ebp + 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 |
je .leaf_block ;листовой ли это блок? |
|
;не листовой блок, а индексный ; eax - ext4_extent_idx |
test ebx, ebx |
jz .fail ;пустой индексный блок -> ошибка |
|
;цикл по индексам экстентов |
@@: |
cmp ebx, 1 ;у индексов не хранится длина, |
je .end_search_index ;поэтому, если остался последний - то это нужный |
|
cmp ecx, [ebp + EXT4_EXTENT_IDX.ei_block] |
jb .fail |
|
cmp ecx, [ebp + sizeof.EXT4_EXTENT_IDX + EXT4_EXTENT_IDX.ei_block] ;блок слeдующего индекса |
jb .end_search_index ;следующий дальше - значит текущий, то что нам нужен |
|
add ebp, 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] |
call ext2_get_block |
test eax, eax |
jnz .fail |
mov ebp, ebx |
jmp ext4_block_recursive_search ;рекурсивно прыгаем в начало |
|
.leaf_block: ;листовой блок ebp - ext4_extent |
;цикл по экстентам |
@@: |
test ebx, ebx |
jz .fail ;ни один узел не подошел - ошибка |
|
mov edx, [ebp + EXT4_EXTENT.ee_block] |
cmp ecx, edx |
jb .fail ;если меньше, значит он был в предыдущих блоках -> ошибка |
|
movzx edi, [ebp + EXT4_EXTENT.ee_len] |
add edx, edi |
cmp ecx, edx |
jb .end_search_extent ;нашли нужный блок |
|
add ebp, 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 блоках |
add ecx, edx |
xor eax, eax |
ret |
|
.fail: |
mov eax, ERROR_FS_FAIL |
ret |
|
;=================================================================== |
;получает адрес ext2 блока из inode с определнным номером |
; in: ecx = номер блока в inode (0..) |
; ebp = адрес inode |
; out: ecx = адрес очередного блока |
; eax - error code |
ext2_get_inode_block: |
test [ebp + EXT2_INODE_STRUC.i_flags], EXT2_EXTENTS_FL |
jz @F |
|
pushad |
add ebp, EXT2_INODE_STRUC.i_block ;ebp - extent_header |
call ext4_block_recursive_search |
mov PUSHAD_ECX, ecx |
mov PUSHAD_EAX, eax |
popad |
ret |
|
@@: |
cmp ecx, 12 ; 0..11 - direct block address |
jb .get_direct_block |
|
sub ecx, 12 |
cmp ecx, [ext2_data.count_pointer_in_block] ; 12.. - indirect block |
cmp ecx, [ext2_data.count_pointer_in_block] ; 12.. - indirect blocks |
jb .get_indirect_block |
|
sub ecx, [ext2_data.count_pointer_in_block] |
273,12 → 397,14 |
jb .get_double_indirect_block |
|
sub ecx, [ext2_data.count_pointer_in_block_square] |
;.get_triple_indirect_block: |
push eax edx ebx |
;triple indirect block |
push edx ebx |
|
mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4] |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
test eax, eax |
jnz .fail |
|
xor edx, edx |
mov eax, ecx |
287,16 → 413,20 |
;eax - номер в полученном блоке edx - номер дальше |
mov eax, [ebx + eax*4] |
call ext2_get_block |
test eax, eax |
jnz .fail |
|
mov eax, edx |
jmp @F |
|
.get_double_indirect_block: |
push eax edx ebx |
push edx ebx |
|
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 13*4] |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
test eax, eax |
jnz .fail |
|
mov eax, ecx |
@@: |
305,23 → 435,30 |
|
mov eax, [ebx + eax*4] |
call ext2_get_block |
test eax, eax |
jnz .fail |
|
mov ecx, [ebx + edx*4] |
|
pop ebx edx eax |
.fail: |
pop ebx edx |
ret |
|
.get_indirect_block: |
push eax ebx |
push ebx |
mov eax, [ebp + EXT2_INODE_STRUC.i_block + 12*4] |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
test eax, eax |
jz @F ;если не было ошибки |
|
mov ecx, [ebx + ecx*4] |
pop ebx eax |
mov ecx, [ebx + ecx*4] ;заносим результат |
@@: |
pop ebx |
ret |
|
.get_direct_block: |
mov ecx, dword [ebp + EXT2_INODE_STRUC.i_block + ecx*4] |
mov ecx, [ebp + EXT2_INODE_STRUC.i_block + ecx*4] |
xor eax, eax |
ret |
|
;=================================================================== |
328,14 → 465,16 |
;get content inode by num |
;in: eax = inode_num |
; ebx = address of inode content |
;out: eax - error code |
ext2_get_inode: |
|
pushad |
mov edi, ebx ;сохраним адрес inode |
dec eax |
xor edx, edx |
div [ext2_data.inodes_per_group] |
|
mov ecx, [ext2_data.sb] |
div [ecx + EXT2_SB_STRUC.inodes_per_group] |
|
push edx ;locale num in group |
|
mov edx, 32 |
343,16 → 482,16 |
|
; в eax - смещение группы с inode-ом относительно начала глобальной дескрипторной таблицы |
; найдем блок в котором он находится |
|
div [ext2_data.block_size] |
mov ecx, [ext2_data.sb] |
add eax, [ecx + EXT2_SB_STRUC.first_data_block] |
inc eax |
mov ebx, [ext2_data.ext2_temp_block] |
call ext2_get_block |
test eax, eax |
jnz .fail |
|
add ebx, edx ; локальный номер в блоке |
mov eax, [ebx+8] ; номер блока - в терминах ext2 |
mov eax, [ebx + EXT2_BLOCK_GROUP_DESC.inode_table]; номер блока - в терминах ext2 |
|
mov ecx, [ext2_data.log_block_size] |
shl eax, cl |
371,75 → 510,19 |
add eax, esi ;нашли адрес блока для чтения |
mov ebx, [ext2_data.ext2_temp_block] |
call hd_read |
cmp [hd_error], 0 |
jnz .fail |
|
mov esi, edx ;добавим "остаток" |
add esi, ebx ;к адресу |
; mov ecx, [ext2_data.inode_size] |
rep movsb ;копируем inode |
xor eax, eax |
.fail: |
mov PUSHAD_EAX, eax |
popad |
ret |
|
;---------------------------------------------------------------- |
; in: esi -> children |
; ebx -> pointer to dir block |
; out: esi -> name without parent or not_changed |
; ebx -> dir_rec of inode children or trash |
ext2_test_block_by_name: |
push eax ecx edx edi |
|
mov edx, ebx |
add edx, [ext2_data.block_size] ;запомним конец блока |
|
.start_rec: |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 |
jz .next_rec |
|
push esi |
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] |
mov edi, EXT2_filename |
lea esi, [ebx + EXT2_DIR_STRUC.name] |
|
call utf8toansi_str |
mov ecx, edi |
sub ecx, EXT2_filename ;кол-во байт в получившейся строке |
|
mov edi, EXT2_filename |
mov esi, [esp] |
@@: |
jecxz .test_find |
dec ecx |
|
lodsb |
call char_toupper |
|
mov ah, [edi] |
inc edi |
xchg al, ah |
call char_toupper |
cmp al, ah |
je @B |
@@: ;не подошло |
pop esi |
.next_rec: |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
add ebx, eax ;к след. записи |
cmp ebx, edx ;проверим конец ли |
jb .start_rec |
jmp .ret |
|
.test_find: |
cmp byte [esi], 0 |
je .find ;нашли конец |
cmp byte [esi], '/' |
jne @B |
inc esi |
.find: |
pop eax ;удаляем из стека сохраненое значение |
.ret: |
pop edi edx ecx eax |
ret |
|
;---------------------------------------------------------------- |
; |
; ext2_HdReadFolder - read disk folder |
; |
456,120 → 539,137 |
;-------------------------------------------------------------- |
ext2_HdReadFolder: |
cmp byte [esi], 0 |
jz .doit |
jz .root_folder |
|
push ecx ebx |
call ext2_find_lfn |
jnc .doit2 |
pop ebx |
.not_found: |
pop ecx |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
push ebx ecx edx |
call ext2_find_lfn ;вернет в ebp адрес inode |
pop edx ecx ebx |
test eax, eax |
jnz .error_ret |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jz .error_not_found |
jmp @F |
|
.doit: |
.root_folder: |
mov ebp, [ext2_data.root_inode] |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jz .error_root |
;придется копировать inode |
push ecx |
jmp @F |
.doit2: |
pop ebx |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR |
jz .not_found |
mov esi, ebp |
mov edi, [ext2_data.ext2_save_inode] |
mov ecx, [ext2_data.inode_size] |
shr ecx, 2 |
mov ebp, edi |
rep movsd |
pop ecx |
@@: |
xor eax, eax |
cmp [ebp + EXT2_INODE_STRUC.i_blocks], 0 ;папка пуста |
je .error_empty_dir |
|
push edx ;адрес результата [edi + 28] |
push 0 ;конец очередного блока папки [edi + 24] |
push ecx ;сколько файлов нужно прочитать [edi + 20] |
push dword [ebx] ;первый "нужный" файл [edi + 16] |
push dword [ebx + 4];флаги [edi + 12] |
push 0 ;[EXT2_read_in_folder] [edi + 8] |
push 0 ;[EXT2_files_in_folder] [edi + 4] |
push 0 ;номер блока по порядку [edi] |
|
mov edi, edx |
mov ecx, 32/4 |
rep stosd ; fill header zero |
pop edi ; edi = число блоков для чтения |
push edx ebx |
|
;--------------------------------------------- final step |
and [EXT2_read_in_folder], 0 |
and [EXT2_files_in_folder], 0 |
mov edi, esp ; edi - указатель на локальные переменные |
add edx, 32 ; edx = current mem for return |
|
mov eax, [ebp + EXT2_INODE_STRUC.i_blocks] |
mov [EXT2_counter_blocks], eax |
|
add edx, 32 ; (header pointer in stack) edx = current mem for return |
xor esi, esi ; esi = номер блока по порядку |
|
.new_block_folder: ;reserved label |
mov ecx, esi ; получим номер блока |
xor ecx, ecx ; получим номер первого блока |
call ext2_get_inode_block |
test eax, eax |
jnz .error_get_block |
|
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block ; и считываем блок с hdd |
test eax, eax |
jnz .error_get_block |
|
mov eax, ebx ; eax = current dir record |
mov esi, ebx ; esi = current dir record |
add ebx, [ext2_data.block_size] |
mov [EXT2_end_block], ebx ; запомним конец очередного блока |
mov [edi + 24], ebx ; запомним конец очередного блока |
|
pop ecx |
mov ecx, [ecx] ; ecx = first wanted (flags ommited) |
mov ecx, [edi + 16] ; ecx = first wanted (flags ommited) |
|
.find_wanted_start: |
jecxz .find_wanted_end |
.find_wanted_cycle: |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz @F |
inc [EXT2_files_in_folder] |
inc dword [edi + 4] ; EXT2_files_in_folder |
dec ecx |
@@: |
movzx ebx, [eax+EXT2_DIR_STRUC.rec_len] |
movzx ebx, [esi + EXT2_DIR_STRUC.rec_len] |
|
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
jb .error_bad_len |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
jnz .error_bad_len |
|
add eax, ebx ; к следующей записи |
cmp eax, [EXT2_end_block] ; проверяем "конец" |
add esi, ebx ; к следующей записи |
cmp esi, [edi + 24] ; сравниваем с концом блока |
jb .find_wanted_start |
|
push .find_wanted_start |
.end_block: ;вылетили из цикла |
.end_block: ;вылетели из цикла |
mov ebx, [ext2_data.count_block_in_block] |
sub [EXT2_counter_blocks], ebx |
jbe .end_dir |
sub [ebp + EXT2_INODE_STRUC.i_blocks], ebx ;вычитаем напрямую из структуры inode |
jle .end_dir |
|
inc esi ;получаем новый блок |
inc dword [edi] ;получаем новый блок |
push ecx |
mov ecx, esi |
mov ecx, [edi] |
call ext2_get_inode_block |
test eax, eax |
jnz .error_get_block |
|
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
test eax, eax |
jnz .error_get_block |
|
pop ecx |
mov eax, ebx |
mov esi, ebx |
add ebx, [ext2_data.block_size] |
mov [EXT2_end_block], ebx |
mov [edi + 24], ebx ;запомним конец блока |
ret ; опять в цикл |
|
.wanted_end: |
loop .find_wanted_cycle ; ecx = -1 |
loop .find_wanted_cycle ; ecx 0 => -1 нужно посчитать сколько файлов |
|
;дошли до первого "нужного" файла |
.find_wanted_end: |
mov ecx, edi |
mov ecx, [edi + 20] |
.wanted_start: ; ищем first_wanted+count |
jecxz .wanted_end |
cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
cmp [esi + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used |
jz .empty_rec |
inc [EXT2_files_in_folder] |
inc [EXT2_read_in_folder] |
inc dword [edi + 8] |
inc dword [edi + 4] |
|
mov edi, edx |
push eax ecx |
push edi ecx |
mov edi, edx ;обнуляем место под очереное имя файла/папки |
xor eax, eax |
mov ecx, 40 / 4 |
rep stosd |
pop ecx eax |
pop ecx edi |
|
push eax esi edx ;получим inode |
mov eax, [eax + EXT2_DIR_STRUC.inode] |
push esi edi edx |
mov eax, [esi + EXT2_DIR_STRUC.inode] ;получим дочерний inode |
mov ebx, [ext2_data.ext2_temp_inode] |
call ext2_get_inode |
test eax, eax |
jnz .error_read_subinode |
|
lea edi, [edx + 8] |
|
599,23 → 699,20 |
stosd |
mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size |
stosd |
xor dword [edx], FS_FT_DIR |
xor dword [edx], FS_FT_DIR ;помечаем, что это файл(2 раза xor) |
@@: |
xor dword [edx], FS_FT_DIR |
pop esi eax |
xor dword [edx], FS_FT_DIR ;помечаем, что это файл |
|
or dword [edx+4], FS_FT_ASCII ; symbol type in name |
|
;теперь скопируем имя, сконвертировав из UTF-8 в CP866 |
push eax ecx esi |
movzx ecx, [eax + EXT2_DIR_STRUC.name_len] |
push ecx ;edi и esi уже сохранены в стеке |
movzx ecx, [esi + EXT2_DIR_STRUC.name_len] |
lea edi, [edx + 40] |
lea esi, [eax + EXT2_DIR_STRUC.name] |
call utf8toansi_str |
pop esi ecx eax |
lea esi, [esi + EXT2_DIR_STRUC.name] |
call utf8_to_cp866 |
and byte [edi], 0 |
pop ecx edi esi |
|
cmp byte [edx + 40], '.' |
cmp byte [edx + 40], '.' ; в linux файл, начинающийся с точки - скрытый |
jne @F |
or dword [edx], FS_FT_HIDDEN |
@@: |
623,38 → 720,60 |
add edx, 40 + 264 ; go to next record |
dec ecx ; если запись пустая ecx не надо уменьшать |
.empty_rec: |
movzx ebx, [eax + EXT2_DIR_STRUC.rec_len] |
movzx ebx, [esi + EXT2_DIR_STRUC.rec_len] |
cmp ebx, 12 ; минимальная длина записи |
jb .end_error |
jb .error_bad_len |
test ebx, 0x3 ; длина записи должна делиться на 4 |
jnz .end_error |
jnz .error_bad_len |
|
add eax, ebx |
cmp eax, [EXT2_end_block] |
add esi, ebx |
cmp esi, [edi + 24] ;дошли ли до конца блока? |
jb .wanted_start |
|
push .wanted_start ; дошли до конца очередного блока |
push .wanted_start ; дошли |
jmp .end_block |
|
.end_dir: |
pop eax ; мусор (адрес возврата в цикл) |
.end_error: |
pop edx |
mov ebx, [EXT2_read_in_folder] |
mov ecx, [EXT2_files_in_folder] |
.end_dir: ;конец папки, когда еще не дошли до нужного файла |
mov edx, [edi + 28] ;адрес структуры результата |
mov ebx, [edi + 8] ;EXT2_read_in_folder |
mov ecx, [edi + 4] ;EXT2_files_in_folder |
mov dword [edx], 1 ;version |
xor eax, eax |
mov [edx+4], ebx |
mov [edx+8], ecx |
|
lea esp, [edi + 32] |
|
xor eax, eax ;зарезервировано: нули в текущей реализации |
lea edi, [edx + 12] |
mov ecx, 20 / 4 |
rep stosd |
ret |
;====================== end ext2_HdReadFolder |
utf8toansi_str: |
|
.error_bad_len: |
mov eax, ERROR_FS_FAIL |
.error_read_subinode: |
.error_get_block: |
lea esp, [edi + 32] |
.error_ret: |
or ebx, -1 |
ret |
|
.error_empty_dir: ;inode папки без блоков |
.error_root: ;root - не папка |
mov eax, ERROR_FS_FAIL |
jmp .error_ret |
|
.error_not_found: ;файл не найден |
mov eax, ERROR_FILE_NOT_FOUND |
jmp .error_ret |
|
;============================================ |
; convert UTF-8 string to ASCII-string (codepage 866) |
; in: ecx=length source, esi->source, edi->buffer |
;in: ecx = length source |
; esi = source |
; edi = buffer |
; destroys: eax,esi,edi |
utf8_to_cp866: |
jecxz .ret |
.start: |
lodsw |
712,7 → 831,7 |
; |
; ret ebx = bytes read or 0xffffffff file not found |
; eax = 0 ok read or other = errormsg |
; |
|
;-------------------------------------------------------------- |
ext2_HdRead: |
cmp byte [esi], 0 |
724,27 → 843,29 |
ret |
|
@@: |
push ecx ebx |
push ecx ebx edx |
call ext2_find_lfn |
pop ebx ecx |
jnc .doit |
;.not_found: |
pop edx ebx ecx |
test eax, eax |
jz @F |
|
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
|
.doit: |
@@: |
test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG |
jz .this_is_nofile |
|
;-----------------------------------------------------------------------------final step |
mov edi, edx ; edi = pointer to return mem |
|
test ebx, ebx |
jz @F |
mov esi, ebx ; esi = pointer to first_wanted |
|
;///// сравним хватит ли нам файла или нет |
mov ebx, [esi+4] |
mov eax, [esi] ; ebx : eax - стартовый номер байта |
|
;///// сравним хватит ли нам файла или нет |
cmp [ebp + EXT2_INODE_STRUC.i_dir_acl], ebx |
ja .size_great |
jb .size_less |
756,6 → 877,10 |
xor ebx, ebx |
mov eax, ERROR_END_OF_FILE |
ret |
|
@@: |
xor ebx, ebx |
xor eax, eax |
.size_great: |
add eax, ecx ;add to first_wanted кол-во байт для чтения |
adc ebx, 0 |
764,35 → 889,45 |
ja .size_great_great |
jb .size_great_less |
cmp [ebp + EXT2_INODE_STRUC.i_size], eax |
jae .size_great_great ; а если равно, то не важно куда |
jae .size_great_great |
|
.size_great_less: |
or [EXT2_files_in_folder], 1 ;читаем по границе размера |
push 1 |
; or [EXT2_files_in_folder], 1 ;читаем по границе размера |
mov ecx, [ebp + EXT2_INODE_STRUC.i_size] |
sub ecx, [esi] ;(размер - старт) |
sub ecx, [esi] ;(размер - старт) = сколько читать |
jmp @F |
|
.size_great_great: |
and [EXT2_files_in_folder], 0 ;читаем столько сколько запросили |
push 0 |
; and [EXT2_files_in_folder], 0 ;читаем столько сколько запросили |
|
@@: |
push ecx ;save for return |
;здесь мы точно знаем сколько байт читать - ecx |
;edi - return memory |
;esi -> first wanted |
|
push ecx ;количество считанных байт |
test esi, esi |
jz .zero_start |
|
;пока делаем п..ц криво =) |
;получим кусок из первого блока |
mov edx, [esi+4] |
mov eax, [esi] |
div [ext2_data.block_size] |
|
mov [EXT2_counter_blocks], eax ;номер блока запоминаем |
push eax ;номер блока запоминаем |
|
push ecx |
mov ecx, eax |
call ext2_get_inode_block |
test eax, eax |
jnz .error_at_first_block |
mov ebx, [ext2_data.ext2_save_block] |
mov eax, ecx |
call ext2_get_block |
test eax, eax |
jnz .error_at_first_block |
pop ecx |
add ebx, edx |
|
807,12 → 942,13 |
|
mov esi, ebx |
rep movsb ;кусок 1-го блока |
jmp @F |
jmp .calc_blocks_count |
|
.zero_start: |
mov eax, ecx |
push 0 ;счетчик блоков |
;теперь в eax кол-во оставшихся байт для чтения |
@@: |
.calc_blocks_count: |
mov ebx, edi ;чтение блока прям в ->ebx |
xor edx, edx |
div [ext2_data.block_size] ;кол-во байт в последнем блоке (остаток) в edx |
820,12 → 956,16 |
@@: |
test edi, edi |
jz .finish_block |
inc [EXT2_counter_blocks] |
mov ecx, [EXT2_counter_blocks] |
inc dword [esp] |
mov ecx, [esp] |
call ext2_get_inode_block |
test eax, eax |
jnz .error_at_read_cycle |
|
mov eax, ecx ;а ebx уже забит нужным значением |
call ext2_get_block |
test eax, eax |
jnz .error_at_read_cycle |
add ebx, [ext2_data.block_size] |
|
dec edi |
835,23 → 975,26 |
test edx, edx |
jz .end_read |
|
mov ecx, [EXT2_counter_blocks] |
pop ecx ;счетчик блоков -> ecx |
inc ecx |
call ext2_get_inode_block |
test eax, eax |
jz .error_at_finish_block |
|
mov edi, ebx |
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
test eax, eax |
jnz .error_at_finish_block |
|
mov ecx, edx |
|
.only_one_block: |
mov esi, ebx |
rep movsb ;кусок last блока |
.end_read: |
pop ebx |
cmp [EXT2_files_in_folder], 0 |
pop eax |
test eax, eax |
jz @F |
|
mov eax, ERROR_END_OF_FILE |
859,77 → 1002,181 |
@@: |
xor eax, eax |
ret |
|
.only_one_block: |
mov esi, ebx |
rep movsb ;кусок last блока |
pop eax |
jmp .end_read |
|
.error_at_first_block: |
pop edx |
.error_at_read_cycle: |
pop ebx |
.error_at_finish_block: |
pop ecx edx |
or ebx, -1 |
ret |
|
;---------------------------------------------------------------- |
; in: esi = file path |
; ebx = pointer to dir block |
; 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] ;запомним конец блока |
|
.start_rec: |
cmp [ebx + EXT2_DIR_STRUC.inode], 0 |
jz .next_rec |
|
mov edi, esp |
push esi |
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] |
lea esi, [ebx + EXT2_DIR_STRUC.name] |
call utf8_to_cp866 |
|
mov ecx, edi |
lea edi, [esp + 4] |
sub ecx, edi ;кол-во байт в получившейся строке |
|
mov esi, [esp] |
@@: |
jecxz .test_find |
dec ecx |
|
lodsb |
call char_toupper |
|
mov ah, [edi] |
inc edi |
xchg al, ah |
call char_toupper |
cmp al, ah |
je @B |
@@: ;не подошло |
pop esi |
.next_rec: |
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] |
add ebx, eax ;к след. записи |
cmp ebx, edx ;проверим конец ли |
jb .start_rec |
add esp, 256 |
ret |
|
.test_find: |
cmp byte [esi], 0 |
je .ret ;нашли конец |
cmp byte [esi], '/' |
jne @B |
inc esi |
.ret: |
add esp, 256 + 4 |
ret |
|
;======================== |
;in : esi -> name not save: eax ebx ecx |
;out: ebp -> inode cf=0 |
; ebp -> trash cf=1 |
;Ищет inode по строке пути |
;in: esi = name |
;out: eax - error code |
; ebp = inode |
; dl - первый байт из имени файла/папки |
ext2_find_lfn: |
mov ebp, [ext2_data.root_inode] |
.next_folder: |
or [EXT2_counter_blocks], -1 ;счетчик блоков папки cur block of inode |
mov eax, [ebp + EXT2_INODE_STRUC.i_blocks] ;убывающий счетчик блоков |
add eax, [ext2_data.count_block_in_block] |
mov [EXT2_end_block], eax |
.next_block_folder: |
mov eax, [ext2_data.count_block_in_block] |
sub [EXT2_end_block], eax |
jz .not_found |
inc [EXT2_counter_blocks] |
mov ecx, [EXT2_counter_blocks] |
cmp [ebp + EXT2_INODE_STRUC.i_blocks], 0 |
je .error_empty_root |
|
.next_path_part: |
push [ebp + EXT2_INODE_STRUC.i_blocks] |
xor ecx, ecx |
.folder_block_cycle: |
call ext2_get_inode_block |
test eax, eax |
jnz .error_get_inode_block |
|
mov eax, ecx |
mov ebx, [ext2_data.ext2_save_block] ;ebx = cur dir record |
call ext2_get_block |
test eax, eax |
jnz .error_get_block |
|
mov eax, esi |
push esi |
call ext2_test_block_by_name |
cmp eax, esi ;нашли имя? |
jz .next_block_folder |
pop edi |
|
cmp byte [esi], 0 |
cmp edi, esi ;нашли имя? |
je .next_folder_block ;не нашли -> к след. блоку |
|
cmp byte [esi], 0 ;дошли до "конца" пути -> возваращаемся |
jz .get_inode_ret |
|
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR |
jne .not_found ;нашли, но это не папка |
cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR ;нашли, но это не папка |
jne .not_found |
|
mov eax, [ebx + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_save_inode] ;все же папка. |
call ext2_get_inode |
test eax, eax |
jnz .error_get_inode |
pop ecx ;в стеке лежит кол-во блоков |
mov ebp, ebx |
jmp .next_folder |
jmp .next_path_part |
|
.next_folder_block: |
;к следующему блоку в текущей папке |
pop eax ;счетчик блоков |
sub eax, [ext2_data.count_block_in_block] |
jle .not_found |
|
inc ecx |
jmp .folder_block_cycle |
|
.not_found: |
stc |
pop ebx |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
|
.get_inode_ret: |
mov [EXT2_end_block], ebx ; сохраняем указатеть на dir_rec |
pop ecx ;в стеке лежит кол-во блоков |
mov dl, [ebx + EXT2_DIR_STRUC.name] ;в dl - первый символ () |
mov eax, [ebx + EXT2_DIR_STRUC.inode] |
mov ebx, [ext2_data.ext2_save_inode] |
call ext2_get_inode |
mov ebp, ebx |
clc |
xor eax, eax |
ret |
|
.error_get_inode_block: |
.error_get_block: |
.error_get_inode: |
pop ebx |
.error_empty_root: |
mov eax, ERROR_FS_FAIL |
ret |
|
;======================== |
|
;---------------------------------------------------------------- |
;ext2_HdGetFileInfo - read file info from block device |
; |
;in: esi points to filename |
; edx mem location to return data |
;-------------------------------------------------------------- |
ext2_HdGetFileInfo: |
xchg bx, bx |
cmp byte [esi], 0 |
jz .doit |
jz .is_root |
|
push edx |
call ext2_find_lfn |
jnc .doit2 |
;.not_found: |
mov eax, ERROR_FILE_NOT_FOUND |
mov ebx, edx |
pop edx |
test eax, eax |
jz @F |
ret |
|
.doit: |
.is_root: |
xor ebx, ebx ;root не может быть скрытым |
mov ebp, [ext2_data.root_inode] |
mov ebx, .doit ;неважно что лишь бы этому адресу не '.' |
jmp @F |
.doit2: |
mov ebx, [EXT2_end_block] |
add ebx, EXT2_DIR_STRUC.name |
@@: |
xor eax, eax |
mov edi, edx |
936,8 → 1183,8 |
mov ecx, 40/4 |
rep stosd ; fill zero |
|
cmp byte [ebx], '.' |
jnz @F |
cmp bl, '.' |
jne @F |
or dword [edx], FS_FT_HIDDEN |
@@: |
|
952,19 → 1199,19 |
xor dword [edx], FS_FT_DIR |
|
lea edi, [edx + 8] |
mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] |
mov eax, [ebp + EXT2_INODE_STRUC.i_ctime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
|
mov eax, [ebx + EXT2_INODE_STRUC.i_atime] |
mov eax, [ebp + EXT2_INODE_STRUC.i_atime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
call ntfs_datetime_to_bdfe.sec |
|
mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] |
mov eax, [ebp + EXT2_INODE_STRUC.i_mtime] |
xor edx, edx |
add eax, 3054539008 |
adc edx, 2 |
982,337 → 1229,3 |
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
;---------------------------------------------------------------- |
; |
; ext2_HdCreateFolder - create new folder |
; |
; esi points to filename |
; |
; ret eax = 0 ok read or other = errormsg |
; |
;-------------------------------------------------------------- |
cmp byte [esi], 0 |
jz .not_found |
cmp byte [esi], '/' |
jz .not_found |
|
mov ebx, esi ; save source pointer |
xor edi, edi ; slah pointer |
@@: |
lodsb |
cmp al, 0 |
jz .zero |
cmp al, '/' |
jz .slash |
jmp @B |
|
.slash: |
lodsb |
cmp al, 0 |
jz .zero ; уберем слеш из имени |
cmp al, '/' |
jz .not_found |
mov edi, esi ; edi -> next symbol after '/' |
dec edi |
jmp @B |
|
.zero: |
dec esi |
test edi, edi |
jz .doit |
|
;слеш был |
mov eax, esi |
sub eax, edi |
mov [EXT2_name_len], eax |
|
mov ecx, edi |
sub ecx, ebx |
dec ecx ;выкинули '/' из имени ролителя |
mov esi, ebx |
mov edi, EXT2_parent_name |
rep movsb |
; esi - pointer to last slash |
|
mov edx, esi |
mov esi, EXT2_parent_name |
call ext2_find_lfn |
jnc .doit2 |
.not_found: |
or ebx, -1 |
mov eax, ERROR_FILE_NOT_FOUND |
ret |
|
.doit: |
mov ebp, [ext2_data.root_inode] |
mov edx, ebx ; имя создаваемой папки |
sub esi, ebx |
mov [EXT2_name_len], esi |
.doit2: |
;ebp -> parent_inode ebx->name_new_folder [EXT2_name_len]=length of name |
; стратегия выбора группы для нового inode: (так делает линукс) |
; 1) Ищем группу в которой меньше всего папок и в есть свободное место |
; 2) Если такая группа не нашлась, то берем группу в которой больше свободного места |
|
|
|
|
call ext2_balloc |
jmp ext2_HdDelete |
|
push ebx |
push ebp |
|
mov ecx, [ext2_data.sb] |
cmp [ecx + EXT2_SB_STRUC.free_inodes_count], 0 ; есть ли место для inode |
jz .no_space |
mov eax, [ecx + EXT2_SB_STRUC.free_block_count] |
sub eax, [ecx + EXT2_SB_STRUC.r_block_count] |
cmp eax, 2 ; и как минимум на 2 блока |
jb .no_space |
|
mov ecx, [ext2_data.groups_count] |
mov esi, [ext2_data.global_desc_table] |
mov edi, -1 ;указатель на лучшую группу |
mov edx, 0 |
.find_group_dir: |
jecxz .end_find_group_dir |
movzx eax, [esi + EXT2_BLOCK_GROUP_DESC.free_inodes_count] |
cmp eax, edx |
jbe @F |
cmp [esi + EXT2_BLOCK_GROUP_DESC.free_blocks_count], 0 |
jz @F |
mov edi, esi |
movzx edx, [esi + EXT2_BLOCK_GROUP_DESC.free_inodes_count] |
@@: |
dec ecx |
add esi, 32 ;размер структуры |
jmp .find_group_dir |
.end_find_group_dir: |
cmp edx, 0 |
jz .no_space |
|
;нашли группу, получим битовую карту inode-ов (найдем locale number) |
mov eax, [edi + EXT2_BLOCK_GROUP_DESC.inode_bitmap] |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
|
;теперь цикл по всем битам |
mov esi, ebx |
mov ecx, [ext2_data.inodes_per_group] |
shr ecx, 5 ;делим на 32 |
mov ebp, ecx ; всего сохраним в ebp |
or eax, -1 ; ищем первый свободный inode (!= -1) |
repne scasd |
jnz .test_last_dword ;нашли или нет |
mov eax, [esi-4] |
|
sub ebp, ecx |
dec ebp |
shl ebp, 5 ; глобальный номер локального номера |
|
mov ecx, 32 |
@@: |
test eax, 1 |
jz @F |
shr eax, 1 |
loop @B |
@@: |
mov eax, 32 |
sub eax, ecx |
|
add ebp, eax ; locale num of inode |
|
mov eax, [esi-4] |
;устанавливаем в eax крайний справа нулевой бит в 1 |
mov ecx, eax |
inc ecx |
or eax, ecx ; x | (x+1) |
mov [esi-4], eax |
mov ebx, [ext2_data.ext2_save_block] |
mov eax, [edi + EXT2_BLOCK_GROUP_DESC.inode_bitmap] |
call ext2_set_block |
;считаем таблицу inode |
sub edi, [ext2_data.global_desc_table] |
shr edi, 5 |
|
mov eax, edi |
mul [ext2_data.inodes_per_group] |
add eax, ebp |
inc eax ; теперь в eax (ebp) номер inode-а |
mov ebp, eax |
;call ext2_get_inode_address |
|
mov ebx, [ext2_data.ext2_save_block] |
call hd_read |
add edx, ebx ; в edx адрес нужного inode |
|
;забьем 0 для начала |
mov edi, edx |
mov ecx, [ext2_data.inode_size] |
shr ecx, 2 |
xor eax, eax |
rep stosd |
|
mov edi, edx |
mov eax, EXT2_S_IFDIR or EXT2_777_MODE |
stosd ; i_mode |
xor eax, eax |
stosd ; i_uid |
mov eax, [ext2_data.block_size] |
stosd ; i_size |
xor eax, eax |
stosd ; i_atime |
stosd ; i_ctime |
stosd ; i_mtime |
stosd ; i_dtime |
stosd ; i_gid |
inc eax |
stosd ; i_links_count |
mov eax, [ext2_data.count_block_in_block] |
stosd ; i_blocks |
|
|
|
|
.test_last_dword: |
|
xor ebx, ebx |
mov eax, ERROR_UNSUPPORTED_FS |
ret |
|
|
|
.no_space: |
or ebx, -1 |
mov eax, ERROR_DISK_FULL |
ret |
|
;выделяет новый блок, если это можно |
;иначе возвращает eax=0 |
ext2_balloc: |
mov ecx, [ext2_data.sb] |
mov eax, [ecx + EXT2_SB_STRUC.free_block_count] |
sub eax, [ecx + EXT2_SB_STRUC.r_block_count] |
jbe .no_space |
|
mov ecx, [ext2_data.groups_count] |
mov edi, [ext2_data.global_desc_table] |
;mov esi, -1 ;указатель на лучшую группу |
mov edx, 0 |
.find_group: |
jecxz .end_find_group |
movzx eax, [edi + EXT2_BLOCK_GROUP_DESC.free_blocks_count] |
cmp eax, edx |
jbe @F |
mov esi, edi |
mov edx, eax |
@@: |
dec ecx |
add edi, 32 ;размер структуры |
jmp .find_group |
.end_find_group: |
cmp edx, 0 |
jz .no_space |
|
;нашли группу, получим битовую карту block-ов |
mov eax, [esi + EXT2_BLOCK_GROUP_DESC.block_bitmap] |
mov ebx, [ext2_data.ext2_save_block] |
call ext2_get_block |
|
;теперь цикл по всем битам |
mov edi, ebx |
mov ecx, [ext2_data.blocks_per_group] |
shr ecx, 5 ;делим на 32 |
mov ebp, ecx ;всего сохраним в ebp |
or eax, -1 ;ищем первый свободный inode (!= -1) |
repe scasd |
jz .test_last_dword ;нашли или нет |
|
mov eax, [edi-4] |
sub ebp, ecx |
dec ebp |
shl ebp, 5 ; ebp = 32*(номер div 32). Теперь найдем (номер mod 32) |
|
mov ecx, 32 |
@@: |
test eax, 1 |
jz @F |
shr eax, 1 |
loop @B |
@@: |
mov eax, 32 |
sub eax, ecx |
|
add ebp, eax ; ebp = номер блока в группе |
|
mov eax, [edi-4] |
mov ecx, eax |
inc ecx |
or eax, ecx ; x | (x+1) - устанавливает в 1 крайний справа нулевой бит (block used) |
mov [edi-4], eax |
|
mov ebx, [ext2_data.ext2_save_block] |
mov eax, [esi + EXT2_BLOCK_GROUP_DESC.inode_bitmap] |
; call ext2_set_block ; и пишем на hdd новую битовую маску |
|
;============== тут получаем номер блока |
mov eax, [ext2_data.blocks_per_group] |
sub esi, [ext2_data.global_desc_table] |
shr esi, 5 ;esi - номер группы |
mul esi |
add ebp, eax ;(номер_группы) * (blocks_per_group) + локальный номер в группе |
mov eax, [ext2_data.sb] |
add ebp, [eax + EXT2_SB_STRUC.first_data_block] |
|
;теперь поправим глобальную дескрипторную таблицу и суперблок |
mov ebx, [ext2_data.sb] |
dec [ebx + EXT2_SB_STRUC.free_block_count] |
mov eax, 2 |
add eax, [PARTITION_START] |
call hd_write |
mov eax, [ebx + EXT2_SB_STRUC.first_data_block] |
inc eax |
dec [esi + EXT2_BLOCK_GROUP_DESC.free_blocks_count];edi все еще указывает на группу в которой мы выделил блок |
call ext2_set_block |
|
mov eax, ebx |
ret |
|
.test_last_dword: |
lodsd |
mov ecx, [ext2_data.blocks_per_group] |
and ecx, not (32-1) ;обнуляем все кроме последних 5 бит |
mov edx, ecx |
mov ebx, 1 |
@@: |
jecxz .no_space |
mov edx, ebx |
or edx, eax ; тестируем очередной бит |
shl ebx, 1 |
jmp @B |
@@: |
sub edx, ecx |
dec edx ;номер в последнем блоке |
|
|
.no_space: |
xor eax, eax |
ret |
|
;in: eax = i_block |
; ebx = pointer to memory |
ext2_set_block: |
push eax ebx ecx |
mov ecx, [ext2_data.log_block_size] |
shl eax, cl |
add eax, [PARTITION_START] |
mov ecx, [ext2_data.count_block_in_block] |
@@: |
call hd_write |
inc eax |
add ebx, 512 |
loop @B |
pop ecx ebx eax |
ret |
|