forked from KolibriOS/kolibrios
Finished ext2 write support, under KSoC.
git-svn-id: svn://kolibrios.org@4066 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
e3f61693b7
commit
7365b0cf3f
@ -3953,7 +3953,7 @@ Format of the information structure:
|
|||||||
* +0: dword: 2 = subfunction number
|
* +0: dword: 2 = subfunction number
|
||||||
* +4: dword: 0 (reserved)
|
* +4: dword: 0 (reserved)
|
||||||
* +8: dword: 0 (reserved)
|
* +8: dword: 0 (reserved)
|
||||||
* +12 = +0xC: dword: number of bytes to read
|
* +12 = +0xC: dword: number of bytes to write
|
||||||
* +16 = +0x10: dword: pointer to data
|
* +16 = +0x10: dword: pointer to data
|
||||||
* +20 = +0x14: ASCIIZ-name of file, the rules of names forming are
|
* +20 = +0x14: ASCIIZ-name of file, the rules of names forming are
|
||||||
given in the general description
|
given in the general description
|
||||||
|
409
kernel/trunk/fs/ext2/blocks.inc
Normal file
409
kernel/trunk/fs/ext2/blocks.inc
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Contains ext2 block handling code. ;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||||
|
;; Distributed under the terms of the new BSD license. ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Write ext2 block from memory to disk.
|
||||||
|
; Input: eax = i_block (block number in ext2 terms);
|
||||||
|
; ebx = buffer address
|
||||||
|
; ebp = pointer to EXTFS
|
||||||
|
; Output: eax = error code (0 implies no error)
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_write:
|
||||||
|
push edx ebx ecx
|
||||||
|
|
||||||
|
mov edx, fs_write32_sys
|
||||||
|
jmp ext2_block_modify
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Read ext2 block from disk to memory.
|
||||||
|
; Input: eax = i_block (block number in ext2 terms);
|
||||||
|
; ebx = address of where to read block
|
||||||
|
; ebp = pointer to EXTFS
|
||||||
|
; Output: eax = error code (0 implies no error)
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_read:
|
||||||
|
push edx ebx ecx
|
||||||
|
|
||||||
|
mov edx, fs_read32_sys
|
||||||
|
jmp ext2_block_modify
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Modify ext2 block.
|
||||||
|
; Input: eax = i_block (block number in ext2 terms);
|
||||||
|
; ebx = I/O buffer address;
|
||||||
|
; edx = fs_read/write32_sys
|
||||||
|
; ebp = pointer to EXTFS
|
||||||
|
; edx, ebx, ecx on stack.
|
||||||
|
; Output: eax = error code (0 implies no error)
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_modify:
|
||||||
|
; Get block number in hard-disk terms in eax.
|
||||||
|
mov ecx, [ebp + EXTFS.log_block_size]
|
||||||
|
shl eax, cl
|
||||||
|
mov ecx, eax
|
||||||
|
push [ebp + EXTFS.count_block_in_block]
|
||||||
|
|
||||||
|
@@:
|
||||||
|
mov eax, ecx
|
||||||
|
call edx
|
||||||
|
test eax, eax
|
||||||
|
jnz .fail
|
||||||
|
|
||||||
|
inc ecx
|
||||||
|
add ebx, 512
|
||||||
|
dec dword[esp]
|
||||||
|
jnz @B
|
||||||
|
|
||||||
|
xor eax, eax
|
||||||
|
@@:
|
||||||
|
pop ecx
|
||||||
|
pop ecx ebx edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.fail:
|
||||||
|
mov eax, ERROR_DEVICE
|
||||||
|
jmp @B
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Zeroes a block.
|
||||||
|
; Input: ebx = block ID.
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
; Output: eax = error code.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_zero:
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
mov eax, ebx
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_temp_block]
|
||||||
|
|
||||||
|
call ext2_block_read
|
||||||
|
test eax, eax
|
||||||
|
jnz .return
|
||||||
|
|
||||||
|
push edi ecx
|
||||||
|
xor eax, eax
|
||||||
|
mov ecx, [ebp + EXTFS.block_size]
|
||||||
|
mov edi, [ebp + EXTFS.ext2_temp_block]
|
||||||
|
rep stosb
|
||||||
|
pop ecx edi
|
||||||
|
|
||||||
|
mov eax, [esp]
|
||||||
|
call ext2_block_write
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Allocates a block.
|
||||||
|
; Input: eax = inode ID for "preference".
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
; Output: Block marked as set in block group.
|
||||||
|
; eax = error code.
|
||||||
|
; ebx = block ID.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_alloc:
|
||||||
|
push [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_count]
|
||||||
|
push EXT2_BLOCK_GROUP_DESC.free_blocks_count
|
||||||
|
push [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group]
|
||||||
|
|
||||||
|
lea ebx, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count]
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
push ext2_bg_read_blk_bitmap
|
||||||
|
|
||||||
|
call ext2_resource_alloc
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Zero-allocates a block.
|
||||||
|
; Input: eax = inode ID for "preference".
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
; Output: Block marked as set in block group.
|
||||||
|
; eax = error code.
|
||||||
|
; ebx = block ID.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_calloc:
|
||||||
|
call ext2_block_alloc
|
||||||
|
test eax, eax
|
||||||
|
jnz @F
|
||||||
|
|
||||||
|
call ext2_block_zero
|
||||||
|
@@:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Frees a block.
|
||||||
|
; Input: eax = block ID.
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
; Output: Block marked as free in block group.
|
||||||
|
; eax = error code.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_free:
|
||||||
|
push edi ecx
|
||||||
|
|
||||||
|
mov edi, ext2_bg_read_blk_bitmap
|
||||||
|
xor ecx, ecx
|
||||||
|
call ext2_resource_free
|
||||||
|
|
||||||
|
pop ecx edi
|
||||||
|
ret
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Find parent from file path in block.
|
||||||
|
; Input: esi = file path.
|
||||||
|
; ebx = pointer to directory block.
|
||||||
|
; ebp = pointer to EXTFS structure.
|
||||||
|
; Output: esi = name without parent, or not changed.
|
||||||
|
; ebx = directory record matched.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_find_parent:
|
||||||
|
sub esp, 256 ; Space for EXT2 filename.
|
||||||
|
mov edx, ebx
|
||||||
|
add edx, [ebp + EXTFS.block_size] ; Save block end.
|
||||||
|
|
||||||
|
.start_rec:
|
||||||
|
cmp [ebx + EXT2_DIR_STRUC.inode], 0
|
||||||
|
jz .next_rec
|
||||||
|
|
||||||
|
mov edi, esp
|
||||||
|
push esi
|
||||||
|
movzx ecx, [ebx + EXT2_DIR_STRUC.name_len]
|
||||||
|
lea esi, [ebx + EXT2_DIR_STRUC.name]
|
||||||
|
call utf8_to_cp866
|
||||||
|
|
||||||
|
mov ecx, edi
|
||||||
|
lea edi, [esp + 4]
|
||||||
|
sub ecx, edi ; Number of bytes in resulting string.
|
||||||
|
|
||||||
|
mov esi, [esp]
|
||||||
|
|
||||||
|
; esi: original file path.
|
||||||
|
; edi: converted string stored on stack.
|
||||||
|
; ecx: size of converted string.
|
||||||
|
@@:
|
||||||
|
; If no bytes left in resulting string, test it.
|
||||||
|
jecxz .test_find
|
||||||
|
dec ecx
|
||||||
|
|
||||||
|
lodsb
|
||||||
|
call char_toupper
|
||||||
|
|
||||||
|
mov ah, [edi]
|
||||||
|
inc edi
|
||||||
|
xchg al, ah
|
||||||
|
call char_toupper
|
||||||
|
|
||||||
|
; If both are same, check next byte.
|
||||||
|
cmp al, ah
|
||||||
|
je @B
|
||||||
|
@@: ; Doesn't match.
|
||||||
|
pop esi
|
||||||
|
|
||||||
|
.next_rec:
|
||||||
|
movzx eax, [ebx + EXT2_DIR_STRUC.rec_len]
|
||||||
|
add ebx, eax ; Go to next record.
|
||||||
|
cmp ebx, edx ; Check if this is the end.
|
||||||
|
jb .start_rec
|
||||||
|
|
||||||
|
add esp, 256
|
||||||
|
ret
|
||||||
|
|
||||||
|
.test_find:
|
||||||
|
cmp byte [esi], 0
|
||||||
|
je .ret ; The end reached.
|
||||||
|
cmp byte [esi], '/' ; If not end of directory name, not matched.
|
||||||
|
jne @B
|
||||||
|
inc esi
|
||||||
|
|
||||||
|
.ret:
|
||||||
|
add esp, 256 + 4
|
||||||
|
ret
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Finds free space in a directory block, modifying last entry appropriately.
|
||||||
|
; Input: ebp = pointer to EXTFS.
|
||||||
|
; ecx = size of free space required.
|
||||||
|
; [EXTFS.ext2_temp_block] contains the block relevant.
|
||||||
|
; Output: edi = free entry.
|
||||||
|
; rec_len of free entry is set.
|
||||||
|
; eax = error code; if the block doesn't link to the next one, this is 0x00000001 on failure.
|
||||||
|
; ; else, 0xFFFFFFFF.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_block_find_fspace:
|
||||||
|
push ebx edx
|
||||||
|
|
||||||
|
mov edi, [ebp + EXTFS.ext2_temp_block]
|
||||||
|
mov edx, edi
|
||||||
|
add edx, [ebp + EXTFS.block_size]
|
||||||
|
|
||||||
|
@@:
|
||||||
|
movzx eax, [edi + EXT2_DIR_STRUC.rec_len]
|
||||||
|
test eax, eax
|
||||||
|
jz .zero_len
|
||||||
|
|
||||||
|
cmp [edi + EXT2_DIR_STRUC.inode], 0
|
||||||
|
je .unused_entry
|
||||||
|
|
||||||
|
; It's a used entry, so see if we can fit it between current one and next.
|
||||||
|
; Subtract the size used by the name and the structure from rec_len.
|
||||||
|
movzx ebx, [edi + EXT2_DIR_STRUC.name_len]
|
||||||
|
add ebx, 8 + 3
|
||||||
|
and ebx, 0xfffffffc ; Align it on the next 4-byte boundary.
|
||||||
|
|
||||||
|
sub eax, ebx
|
||||||
|
add edi, ebx
|
||||||
|
cmp eax, ecx
|
||||||
|
jb .next_iter
|
||||||
|
|
||||||
|
sub edi, ebx
|
||||||
|
mov [edi + EXT2_DIR_STRUC.rec_len], bx ; Make previous entry point to us.
|
||||||
|
add edi, ebx
|
||||||
|
|
||||||
|
mov [edi + EXT2_DIR_STRUC.rec_len], ax ; Make current entry point to next one.
|
||||||
|
jmp .found
|
||||||
|
|
||||||
|
.unused_entry:
|
||||||
|
; It's an unused inode.
|
||||||
|
cmp eax, ecx
|
||||||
|
jge .found
|
||||||
|
|
||||||
|
.next_iter:
|
||||||
|
add edi, eax
|
||||||
|
cmp edi, edx
|
||||||
|
jb @B
|
||||||
|
|
||||||
|
.not_found:
|
||||||
|
xor eax, eax
|
||||||
|
not eax
|
||||||
|
jmp .ret
|
||||||
|
|
||||||
|
; Zero length entry means we have the rest of the block for us.
|
||||||
|
.zero_len:
|
||||||
|
mov eax, edx
|
||||||
|
sub eax, edi
|
||||||
|
|
||||||
|
; Point to next block.
|
||||||
|
mov [edi + EXT2_DIR_STRUC.rec_len], ax
|
||||||
|
|
||||||
|
cmp eax, ecx
|
||||||
|
jge .fits
|
||||||
|
|
||||||
|
mov [edi + EXT2_DIR_STRUC.inode], 0
|
||||||
|
|
||||||
|
; It doesn't fit, but the block doesn't link to the next block.
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
jmp .ret
|
||||||
|
|
||||||
|
.fits:
|
||||||
|
mov [edi + EXT2_DIR_STRUC.rec_len], cx
|
||||||
|
|
||||||
|
.found:
|
||||||
|
xor eax, eax
|
||||||
|
|
||||||
|
.ret:
|
||||||
|
pop edx ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Gets the block group's descriptor.
|
||||||
|
; Input: eax = block group.
|
||||||
|
; Output: eax = if zero, error; else, points to block group descriptor.
|
||||||
|
; [EXTFS.ext2_temp_block] contains relevant block.
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_bg_read_desc:
|
||||||
|
push edx ebx
|
||||||
|
mov edx, 32
|
||||||
|
mul edx ; Get index of descriptor in global_desc_table.
|
||||||
|
|
||||||
|
; eax: block group descriptor offset relative to global descriptor table start
|
||||||
|
; Find the block this block descriptor is in.
|
||||||
|
div [ebp + EXTFS.block_size]
|
||||||
|
add eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
|
||||||
|
inc eax
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_temp_block]
|
||||||
|
call ext2_block_read
|
||||||
|
test eax, eax
|
||||||
|
jnz .fail
|
||||||
|
|
||||||
|
add ebx, edx ; edx: local index of descriptor inside block
|
||||||
|
mov eax, ebx
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop ebx edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.fail:
|
||||||
|
xor eax, eax
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Writes a block group's descriptor.
|
||||||
|
; Input: eax = block group.
|
||||||
|
; [EXTFS.ext2_temp_data] contains the block relevant.
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
; Output: eax = error code.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_bg_write_desc:
|
||||||
|
push edx ebx
|
||||||
|
mov edx, 32
|
||||||
|
mul edx ; Get index of descriptor in global_desc_table.
|
||||||
|
|
||||||
|
; eax: block group descriptor offset relative to global descriptor table start
|
||||||
|
; Find the block this block descriptor is in.
|
||||||
|
div [ebp + EXTFS.block_size]
|
||||||
|
add eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
|
||||||
|
inc eax
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_temp_block]
|
||||||
|
call ext2_block_write
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop ebx edx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Gets the block group's block bitmap.
|
||||||
|
; Input: eax = block group.
|
||||||
|
; Output: eax = if zero, error; else, points to block group descriptor.
|
||||||
|
; ebx = block bitmap's block (hard disk).
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_bg_read_blk_bitmap:
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
call ext2_bg_read_desc
|
||||||
|
test eax, eax
|
||||||
|
jz .fail
|
||||||
|
|
||||||
|
mov ebx, [eax + EXT2_BLOCK_GROUP_DESC.block_bitmap] ; Block number of block group bitmap - in ext2 terms.
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.fail:
|
||||||
|
xor eax, eax
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Updates superblock, plus backups.
|
||||||
|
; Input: ebp = pointer to EXTFS.
|
||||||
|
; Output: eax = error code.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_sb_update:
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
mov eax, 2
|
||||||
|
lea ebx, [ebp + EXTFS.superblock]
|
||||||
|
call fs_write32_sys
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
ret
|
@ -8,9 +8,9 @@
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
include 'ext2.inc'
|
include 'ext2.inc'
|
||||||
include 'blocks.asm'
|
include 'blocks.inc'
|
||||||
include 'inode.asm'
|
include 'inode.inc'
|
||||||
include 'resource.asm'
|
include 'resource.inc'
|
||||||
|
|
||||||
iglobal
|
iglobal
|
||||||
align 4
|
align 4
|
||||||
@ -197,6 +197,11 @@ proc ext2_create_partition
|
|||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error
|
jnz .error
|
||||||
|
|
||||||
|
;call ext2_sb_update
|
||||||
|
; Sync the disk.
|
||||||
|
;mov esi, [ebp + PARTITION.Disk]
|
||||||
|
;call disk_sync ; eax contains error code, if any.
|
||||||
|
|
||||||
mov eax, ebp ; Return pointer to EXTFS.
|
mov eax, ebp ; Return pointer to EXTFS.
|
||||||
pop edi esi ebp ebx
|
pop edi esi ebp ebx
|
||||||
ret
|
ret
|
||||||
@ -252,6 +257,7 @@ endp
|
|||||||
; eax = error code (0 implies no error)
|
; eax = error code (0 implies no error)
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
ext2_ReadFolder:
|
ext2_ReadFolder:
|
||||||
|
;DEBUGF 1, "Reading folder.\n"
|
||||||
call ext2_lock
|
call ext2_lock
|
||||||
cmp byte [esi], 0
|
cmp byte [esi], 0
|
||||||
jz .root_folder
|
jz .root_folder
|
||||||
@ -306,7 +312,7 @@ ext2_ReadFolder:
|
|||||||
add edx, 32 ; edx = mem to return.
|
add edx, 32 ; edx = mem to return.
|
||||||
|
|
||||||
xor ecx, ecx ; Get number of first block.
|
xor ecx, ecx ; Get number of first block.
|
||||||
call ext2_get_inode_block
|
call ext2_inode_get_block
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error_get_block
|
jnz .error_get_block
|
||||||
|
|
||||||
@ -355,7 +361,7 @@ ext2_ReadFolder:
|
|||||||
; Read the next block.
|
; Read the next block.
|
||||||
push ecx
|
push ecx
|
||||||
mov ecx, [edi]
|
mov ecx, [edi]
|
||||||
call ext2_get_inode_block
|
call ext2_inode_get_block
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error_get_block
|
jnz .error_get_block
|
||||||
|
|
||||||
@ -482,6 +488,8 @@ ext2_ReadFolder:
|
|||||||
lea edi, [edx + 12]
|
lea edi, [edx + 12]
|
||||||
mov ecx, 20 / 4
|
mov ecx, 20 / 4
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
|
;DEBUGF 1, "Returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.error_bad_len:
|
.error_bad_len:
|
||||||
@ -497,7 +505,7 @@ ext2_ReadFolder:
|
|||||||
push eax
|
push eax
|
||||||
call ext2_unlock
|
call ext2_unlock
|
||||||
pop eax
|
pop eax
|
||||||
|
;DEBUGF 1, "Returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.error_empty_dir: ; inode of folder without blocks.
|
.error_empty_dir: ; inode of folder without blocks.
|
||||||
@ -518,6 +526,7 @@ ext2_ReadFolder:
|
|||||||
; eax = error code (0 implies no error)
|
; eax = error code (0 implies no error)
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
ext2_Read:
|
ext2_Read:
|
||||||
|
;DEBUGF 1, "Attempting read.\n"
|
||||||
call ext2_lock
|
call ext2_lock
|
||||||
cmp byte [esi], 0
|
cmp byte [esi], 0
|
||||||
jnz @F
|
jnz @F
|
||||||
@ -607,7 +616,7 @@ ext2_Read:
|
|||||||
|
|
||||||
push ecx
|
push ecx
|
||||||
mov ecx, eax
|
mov ecx, eax
|
||||||
call ext2_get_inode_block
|
call ext2_inode_get_block
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error_at_first_block
|
jnz .error_at_first_block
|
||||||
|
|
||||||
@ -651,7 +660,7 @@ ext2_Read:
|
|||||||
|
|
||||||
inc dword [esp]
|
inc dword [esp]
|
||||||
mov ecx, [esp]
|
mov ecx, [esp]
|
||||||
call ext2_get_inode_block
|
call ext2_inode_get_block
|
||||||
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error_at_read_cycle
|
jnz .error_at_read_cycle
|
||||||
@ -674,7 +683,7 @@ ext2_Read:
|
|||||||
|
|
||||||
pop ecx ; Pop block counter in ECX.
|
pop ecx ; Pop block counter in ECX.
|
||||||
inc ecx
|
inc ecx
|
||||||
call ext2_get_inode_block
|
call ext2_inode_get_block
|
||||||
|
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error_at_finish_block
|
jnz .error_at_finish_block
|
||||||
@ -705,6 +714,7 @@ ext2_Read:
|
|||||||
ret
|
ret
|
||||||
@@:
|
@@:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
;DEBUGF 1, "Returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.only_one_block:
|
.only_one_block:
|
||||||
@ -722,6 +732,8 @@ ext2_Read:
|
|||||||
push eax
|
push eax
|
||||||
call ext2_unlock
|
call ext2_unlock
|
||||||
pop eax
|
pop eax
|
||||||
|
|
||||||
|
;DEBUGF 1, "Returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
@ -732,6 +744,7 @@ ext2_Read:
|
|||||||
; Output: eax = error code.
|
; Output: eax = error code.
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
ext2_GetFileInfo:
|
ext2_GetFileInfo:
|
||||||
|
;DEBUGF 1, "Calling for file info.\n"
|
||||||
call ext2_lock
|
call ext2_lock
|
||||||
mov edx, [ebx + 16]
|
mov edx, [ebx + 16]
|
||||||
cmp byte [esi], 0
|
cmp byte [esi], 0
|
||||||
@ -749,6 +762,8 @@ ext2_GetFileInfo:
|
|||||||
push eax
|
push eax
|
||||||
call ext2_unlock
|
call ext2_unlock
|
||||||
pop eax
|
pop eax
|
||||||
|
|
||||||
|
;DEBUGF 1, "Returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.is_root:
|
.is_root:
|
||||||
@ -801,6 +816,7 @@ ext2_GetFileInfo:
|
|||||||
|
|
||||||
call ext2_unlock
|
call ext2_unlock
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
;DEBUGF 1, "Returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
@ -811,6 +827,13 @@ ext2_GetFileInfo:
|
|||||||
; Output: eax = error code.
|
; Output: eax = error code.
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
ext2_SetFileInfo:
|
ext2_SetFileInfo:
|
||||||
|
test [ebp + EXTFS.partition_flags], EXT2_RO
|
||||||
|
jz @F
|
||||||
|
|
||||||
|
mov eax, ERROR_UNSUPPORTED_FS
|
||||||
|
ret
|
||||||
|
|
||||||
|
@@:
|
||||||
push edx esi edi ebx
|
push edx esi edi ebx
|
||||||
call ext2_lock
|
call ext2_lock
|
||||||
mov edx, [ebx + 16]
|
mov edx, [ebx + 16]
|
||||||
@ -888,6 +911,14 @@ ext2_SetFileInfo:
|
|||||||
; Output: eax = error code.
|
; Output: eax = error code.
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
ext2_Delete:
|
ext2_Delete:
|
||||||
|
;DEBUGF 1, "Attempting Delete.\n"
|
||||||
|
test [ebp + EXTFS.partition_flags], EXT2_RO
|
||||||
|
jz @F
|
||||||
|
|
||||||
|
mov eax, ERROR_UNSUPPORTED_FS
|
||||||
|
ret
|
||||||
|
|
||||||
|
@@:
|
||||||
push ebx ecx edx esi edi
|
push ebx ecx edx esi edi
|
||||||
call ext2_lock
|
call ext2_lock
|
||||||
|
|
||||||
@ -971,7 +1002,7 @@ ext2_Delete:
|
|||||||
|
|
||||||
@@:
|
@@:
|
||||||
push ecx
|
push ecx
|
||||||
call ext2_get_inode_block
|
call ext2_inode_get_block
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz .error_stack8
|
jnz .error_stack8
|
||||||
mov eax, ecx
|
mov eax, ecx
|
||||||
@ -989,6 +1020,11 @@ ext2_Delete:
|
|||||||
jmp @B
|
jmp @B
|
||||||
|
|
||||||
@@:
|
@@:
|
||||||
|
; Free indirect blocks.
|
||||||
|
call ext2_inode_free_indirect_blocks
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_stack4
|
||||||
|
|
||||||
; Clear the inode, and add deletion time.
|
; Clear the inode, and add deletion time.
|
||||||
mov edi, [ebp + EXTFS.ext2_save_inode]
|
mov edi, [ebp + EXTFS.ext2_save_inode]
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
@ -1047,6 +1083,7 @@ ext2_Delete:
|
|||||||
pop eax
|
pop eax
|
||||||
|
|
||||||
pop edi esi edx ecx ebx
|
pop edi esi edx ecx ebx
|
||||||
|
;DEBUGF 1, "And returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.error_stack8:
|
.error_stack8:
|
||||||
@ -1071,12 +1108,20 @@ ext2_Delete:
|
|||||||
; Output: eax = error code.
|
; Output: eax = error code.
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
ext2_CreateFolder:
|
ext2_CreateFolder:
|
||||||
|
;DEBUGF 1, "Attempting to create folder.\n"
|
||||||
|
test [ebp + EXTFS.partition_flags], EXT2_RO
|
||||||
|
jz @F
|
||||||
|
|
||||||
|
mov eax, ERROR_UNSUPPORTED_FS
|
||||||
|
ret
|
||||||
|
|
||||||
|
@@:
|
||||||
push ebx ecx edx esi edi
|
push ebx ecx edx esi edi
|
||||||
call ext2_lock
|
call ext2_lock
|
||||||
|
|
||||||
add esi, [esp + 20 + 4]
|
add esi, [esp + 20 + 4]
|
||||||
|
|
||||||
; Can't create root, but for CreateFile already existing directory is success.
|
; Can't create root, but for CreateFolder already existing directory is success.
|
||||||
cmp byte [esi], 0
|
cmp byte [esi], 0
|
||||||
jz .success
|
jz .success
|
||||||
|
|
||||||
@ -1194,6 +1239,7 @@ ext2_CreateFolder:
|
|||||||
pop eax
|
pop eax
|
||||||
|
|
||||||
pop edi esi edx ecx ebx
|
pop edi esi edx ecx ebx
|
||||||
|
;DEBUGF 1, "Returning with: %x.\n", eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.error:
|
.error:
|
||||||
@ -1210,12 +1256,464 @@ ext2_CreateFolder:
|
|||||||
mov eax, ERROR_DISK_FULL
|
mov eax, ERROR_DISK_FULL
|
||||||
jmp .return
|
jmp .return
|
||||||
|
|
||||||
self_link: db ".", 0
|
self_link db ".", 0
|
||||||
parent_link: db "..", 0
|
parent_link db "..", 0
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Rewrite a file.
|
||||||
|
; Input: esi + [esp + 4] = file name.
|
||||||
|
; ebx = pointer to paramteres from sysfunc 70.
|
||||||
|
; ebp = pointer to EXTFS structure.
|
||||||
|
; Output: eax = error code.
|
||||||
|
; ebx = bytes written.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
ext2_Rewrite:
|
ext2_Rewrite:
|
||||||
ext2_Write:
|
;DEBUGF 1, "Attempting Rewrite.\n"
|
||||||
ext2_SetFileEnd:
|
test [ebp + EXTFS.partition_flags], EXT2_RO
|
||||||
xor ebx, ebx
|
jz @F
|
||||||
|
|
||||||
mov eax, ERROR_UNSUPPORTED_FS
|
mov eax, ERROR_UNSUPPORTED_FS
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@@:
|
||||||
|
push ecx edx esi edi
|
||||||
|
pushad
|
||||||
|
|
||||||
|
call ext2_lock
|
||||||
|
|
||||||
|
add esi, [esp + 16 + 32 + 4]
|
||||||
|
; Can't create root.
|
||||||
|
cmp byte [esi], 0
|
||||||
|
jz .error_access_denied
|
||||||
|
|
||||||
|
push esi
|
||||||
|
stdcall ext2_inode_find, 0
|
||||||
|
pop esi
|
||||||
|
|
||||||
|
; If the file is there, delete it.
|
||||||
|
test eax, eax
|
||||||
|
jnz @F
|
||||||
|
|
||||||
|
pushad
|
||||||
|
|
||||||
|
push eax
|
||||||
|
call ext2_unlock
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
push dword 0x00000000
|
||||||
|
call ext2_Delete
|
||||||
|
add esp, 4
|
||||||
|
|
||||||
|
push eax
|
||||||
|
call ext2_lock
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_access_denied_delete
|
||||||
|
|
||||||
|
popad
|
||||||
|
@@:
|
||||||
|
; Find parent.
|
||||||
|
call ext2_inode_find_parent
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_access_denied
|
||||||
|
|
||||||
|
; Inode ID for preference.
|
||||||
|
mov eax, esi
|
||||||
|
call ext2_inode_alloc
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_full
|
||||||
|
|
||||||
|
; Save allocated inode in EDX; filename is in EDI; parent ID in ESI.
|
||||||
|
mov edx, ebx
|
||||||
|
|
||||||
|
push edi
|
||||||
|
|
||||||
|
xor al, al
|
||||||
|
mov edi, [ebp + EXTFS.ext2_temp_inode]
|
||||||
|
mov ecx, [ebp + EXTFS.inode_size]
|
||||||
|
rep stosb
|
||||||
|
|
||||||
|
mov edi, [ebp + EXTFS.ext2_temp_inode]
|
||||||
|
add edi, EXT2_INODE_STRUC.i_atime
|
||||||
|
call current_unix_time
|
||||||
|
|
||||||
|
add edi, 8
|
||||||
|
call current_unix_time
|
||||||
|
|
||||||
|
pop edi
|
||||||
|
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_temp_inode]
|
||||||
|
mov [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG
|
||||||
|
mov eax, edx
|
||||||
|
call ext2_inode_write
|
||||||
|
test eax, eax
|
||||||
|
jnz .error
|
||||||
|
|
||||||
|
; Link parent to child.
|
||||||
|
mov eax, esi
|
||||||
|
mov ebx, edx
|
||||||
|
mov esi, edi
|
||||||
|
mov dl, EXT2_FT_REG_FILE
|
||||||
|
call ext2_inode_link
|
||||||
|
test eax, eax
|
||||||
|
jnz .error
|
||||||
|
|
||||||
|
popad
|
||||||
|
push eax
|
||||||
|
call ext2_unlock
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
push dword 0x00000000
|
||||||
|
call ext2_Write
|
||||||
|
add esp, 4
|
||||||
|
|
||||||
|
push eax
|
||||||
|
call ext2_lock
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
.success:
|
||||||
|
push eax
|
||||||
|
call ext2_sb_update
|
||||||
|
|
||||||
|
; Sync the disk.
|
||||||
|
mov esi, [ebp + PARTITION.Disk]
|
||||||
|
call disk_sync ; eax contains error code, if any.
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
.return:
|
||||||
|
push eax
|
||||||
|
call ext2_unlock
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
pop edi esi edx ecx
|
||||||
|
|
||||||
|
;DEBUGF 1, "And returning with: %x.\n", eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.error:
|
||||||
|
mov eax, ERROR_ACCESS_DENIED
|
||||||
|
jmp .success
|
||||||
|
|
||||||
|
.error_access_denied_delete:
|
||||||
|
popad
|
||||||
|
|
||||||
|
.error_access_denied:
|
||||||
|
popad
|
||||||
|
xor ebx, ebx
|
||||||
|
|
||||||
|
mov eax, ERROR_ACCESS_DENIED
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
.error_full:
|
||||||
|
popad
|
||||||
|
xor ebx, ebx
|
||||||
|
|
||||||
|
mov eax, ERROR_DISK_FULL
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Write to a file.
|
||||||
|
; Input: esi + [esp + 4] = file name.
|
||||||
|
; ebx = pointer to paramteres from sysfunc 70.
|
||||||
|
; ebp = pointer to EXTFS structure.
|
||||||
|
; Output: eax = error code.
|
||||||
|
; ebx = number of bytes written.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_Write:
|
||||||
|
;DEBUGF 1, "Attempting write, "
|
||||||
|
test [ebp + EXTFS.partition_flags], EXT2_RO
|
||||||
|
jz @F
|
||||||
|
|
||||||
|
mov eax, ERROR_UNSUPPORTED_FS
|
||||||
|
ret
|
||||||
|
|
||||||
|
@@:
|
||||||
|
push ecx edx esi edi
|
||||||
|
call ext2_lock
|
||||||
|
|
||||||
|
add esi, [esp + 16 + 4]
|
||||||
|
|
||||||
|
; Can't write to root.
|
||||||
|
cmp byte [esi], 0
|
||||||
|
jz .error
|
||||||
|
|
||||||
|
push ebx ecx edx
|
||||||
|
stdcall ext2_inode_find, 0
|
||||||
|
pop edx ecx ebx
|
||||||
|
; If file not there, error.
|
||||||
|
xor ecx, ecx
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_file_not_found
|
||||||
|
|
||||||
|
; Save the inode.
|
||||||
|
push esi
|
||||||
|
|
||||||
|
; Check if it's a file.
|
||||||
|
mov edx, [ebp + EXTFS.ext2_save_inode]
|
||||||
|
cmp [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG
|
||||||
|
jne .error
|
||||||
|
|
||||||
|
mov eax, esi
|
||||||
|
mov ecx, [ebx + 4]
|
||||||
|
|
||||||
|
call ext2_inode_extend
|
||||||
|
xor ecx, ecx
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_device
|
||||||
|
|
||||||
|
; ECX contains the size to write, and ESI points to it.
|
||||||
|
mov ecx, [ebx + 0x0C]
|
||||||
|
mov esi, [ebx + 0x10]
|
||||||
|
|
||||||
|
; Save the size of the inode.
|
||||||
|
mov eax, [edx + EXT2_INODE_STRUC.i_size]
|
||||||
|
push eax
|
||||||
|
|
||||||
|
xor edx, edx
|
||||||
|
div [ebp + EXTFS.block_size]
|
||||||
|
|
||||||
|
test edx, edx
|
||||||
|
jz .start_aligned
|
||||||
|
|
||||||
|
; Start isn't aligned, so deal with the non-aligned bytes.
|
||||||
|
mov ebx, [ebp + EXTFS.block_size]
|
||||||
|
sub ebx, edx
|
||||||
|
|
||||||
|
cmp ebx, ecx
|
||||||
|
jbe @F
|
||||||
|
|
||||||
|
; If the size to copy fits in current block, limit to that, instead of the entire block.
|
||||||
|
mov ebx, ecx
|
||||||
|
|
||||||
|
@@:
|
||||||
|
; Copy EBX bytes, in EAX indexed block.
|
||||||
|
push eax
|
||||||
|
call ext2_inode_read_entry
|
||||||
|
test eax, eax
|
||||||
|
pop eax
|
||||||
|
jnz .error_inode_size
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov ecx, ebx
|
||||||
|
mov edi, ebx
|
||||||
|
add edi, edx
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
; Write the block.
|
||||||
|
call ext2_inode_write_entry
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_inode_size
|
||||||
|
|
||||||
|
add [esp], ebx
|
||||||
|
sub ecx, ebx
|
||||||
|
jz .write_inode
|
||||||
|
|
||||||
|
.start_aligned:
|
||||||
|
cmp ecx, [ebp + EXTFS.block_size]
|
||||||
|
jb @F
|
||||||
|
|
||||||
|
mov eax, [esp]
|
||||||
|
xor edx, edx
|
||||||
|
div [ebp + EXTFS.block_size]
|
||||||
|
|
||||||
|
push eax
|
||||||
|
mov edx, [esp + 8]
|
||||||
|
call ext2_inode_blank_entry
|
||||||
|
test eax, eax
|
||||||
|
pop eax
|
||||||
|
jnz .error_inode_size
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
|
||||||
|
mov ecx, [ebp + EXTFS.block_size]
|
||||||
|
mov edi, [ebp + EXTFS.ext2_save_block]
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
call ext2_inode_write_entry
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_inode_size
|
||||||
|
|
||||||
|
mov eax, [ebp + EXTFS.block_size]
|
||||||
|
sub ecx, eax
|
||||||
|
add [esp], eax
|
||||||
|
jmp .start_aligned
|
||||||
|
|
||||||
|
; Handle the remaining bytes.
|
||||||
|
@@:
|
||||||
|
test ecx, ecx
|
||||||
|
jz .write_inode
|
||||||
|
|
||||||
|
mov eax, [esp]
|
||||||
|
xor edx, edx
|
||||||
|
div [ebp + EXTFS.block_size]
|
||||||
|
|
||||||
|
push eax
|
||||||
|
call ext2_inode_read_entry
|
||||||
|
test eax, eax
|
||||||
|
pop eax
|
||||||
|
jz @F
|
||||||
|
|
||||||
|
push eax
|
||||||
|
mov edx, [esp + 8]
|
||||||
|
|
||||||
|
call ext2_inode_blank_entry
|
||||||
|
test eax, eax
|
||||||
|
pop eax
|
||||||
|
jnz .error_inode_size
|
||||||
|
|
||||||
|
@@:
|
||||||
|
push ecx
|
||||||
|
mov edi, [ebp + EXTFS.ext2_save_block]
|
||||||
|
rep movsb
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
call ext2_inode_write_entry
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_inode_size
|
||||||
|
|
||||||
|
add [esp], ecx
|
||||||
|
xor ecx, ecx
|
||||||
|
|
||||||
|
.write_inode:
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_temp_inode]
|
||||||
|
pop eax
|
||||||
|
mov [ebx + EXT2_INODE_STRUC.i_size], eax
|
||||||
|
mov eax, [esp]
|
||||||
|
|
||||||
|
call ext2_inode_write
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_device
|
||||||
|
|
||||||
|
.success:
|
||||||
|
call ext2_sb_update
|
||||||
|
|
||||||
|
; Sync the disk.
|
||||||
|
mov esi, [ebp + PARTITION.Disk]
|
||||||
|
call disk_sync ; eax contains error code, if any.
|
||||||
|
|
||||||
|
.return:
|
||||||
|
push eax
|
||||||
|
call ext2_unlock
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
add esp, 4
|
||||||
|
|
||||||
|
mov ebx, [esp + 12]
|
||||||
|
sub ebx, ecx
|
||||||
|
pop edi esi edx ecx
|
||||||
|
|
||||||
|
;DEBUGF 1, "and returning with: %x.\n", eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.error:
|
||||||
|
mov eax, ERROR_ACCESS_DENIED
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
.error_file_not_found:
|
||||||
|
mov eax, ERROR_FILE_NOT_FOUND
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
.error_inode_size:
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_temp_inode]
|
||||||
|
pop eax
|
||||||
|
mov [ebx + EXT2_INODE_STRUC.i_size], eax
|
||||||
|
mov eax, [esp]
|
||||||
|
|
||||||
|
call ext2_inode_write
|
||||||
|
|
||||||
|
.error_device:
|
||||||
|
call ext2_sb_update
|
||||||
|
|
||||||
|
; Sync the disk.
|
||||||
|
mov esi, [ebp + PARTITION.Disk]
|
||||||
|
call disk_sync ; eax contains error code, if any.
|
||||||
|
|
||||||
|
mov eax, ERROR_DEVICE
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Set the end of a file.
|
||||||
|
; Input: esi + [esp + 4] = file name.
|
||||||
|
; ebx = pointer to paramteres from sysfunc 70.
|
||||||
|
; ebp = pointer to EXTFS structure.
|
||||||
|
; Output: eax = error code.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_SetFileEnd:
|
||||||
|
test [ebp + EXTFS.partition_flags], EXT2_RO
|
||||||
|
jz @F
|
||||||
|
|
||||||
|
mov eax, ERROR_UNSUPPORTED_FS
|
||||||
|
ret
|
||||||
|
|
||||||
|
@@:
|
||||||
|
push ebx ecx edx esi edi
|
||||||
|
call ext2_lock
|
||||||
|
|
||||||
|
add esi, [esp + 20 + 4]
|
||||||
|
|
||||||
|
; Can't write to root.
|
||||||
|
cmp byte [esi], 0
|
||||||
|
jz .error
|
||||||
|
|
||||||
|
stdcall ext2_inode_find, 0
|
||||||
|
; If file not there, error.
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_file_not_found
|
||||||
|
|
||||||
|
; Check if it's a file.
|
||||||
|
mov edx, [ebp + EXTFS.ext2_save_inode]
|
||||||
|
cmp [edx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFREG
|
||||||
|
jne .error
|
||||||
|
|
||||||
|
mov eax, esi
|
||||||
|
mov ecx, [ebx + 4]
|
||||||
|
call ext2_inode_extend
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_disk_full
|
||||||
|
|
||||||
|
mov eax, esi
|
||||||
|
call ext2_inode_truncate
|
||||||
|
test eax, eax
|
||||||
|
jnz .error_disk_full
|
||||||
|
|
||||||
|
mov eax, esi
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_temp_inode]
|
||||||
|
call ext2_inode_write
|
||||||
|
|
||||||
|
call ext2_sb_update
|
||||||
|
|
||||||
|
; Sync the disk.
|
||||||
|
mov esi, [ebp + PARTITION.Disk]
|
||||||
|
call disk_sync ; eax contains error code, if any.
|
||||||
|
|
||||||
|
.return:
|
||||||
|
push eax
|
||||||
|
call ext2_unlock
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
pop edi esi edx ecx ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.error:
|
||||||
|
mov eax, ERROR_ACCESS_DENIED
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
.error_file_not_found:
|
||||||
|
mov eax, ERROR_FILE_NOT_FOUND
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
.error_disk_full:
|
||||||
|
call ext2_sb_update
|
||||||
|
|
||||||
|
; Sync the disk.
|
||||||
|
mov esi, [ebp + PARTITION.Disk]
|
||||||
|
call disk_sync ; eax contains error code, if any.
|
||||||
|
|
||||||
|
mov eax, ERROR_DISK_FULL
|
||||||
|
jmp .return
|
||||||
|
@ -7,6 +7,13 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
; Future jobs for driver, in order of preference:
|
||||||
|
; * clean up existing extents support.
|
||||||
|
; * add b-tree directories support.
|
||||||
|
; * add long file support.
|
||||||
|
; * add journal support.
|
||||||
|
; * add minor features that come with ext3/4.
|
||||||
|
|
||||||
; Recommended move to some kernel-wide bitmap handling code (with a bit of abstraction, of course).
|
; Recommended move to some kernel-wide bitmap handling code (with a bit of abstraction, of course).
|
||||||
|
|
||||||
;---------------------------------------------------------------------
|
;---------------------------------------------------------------------
|
||||||
@ -86,6 +93,7 @@ bitmap_find_free_bit:
|
|||||||
|
|
||||||
; We found the value. Let's return with it.
|
; We found the value. Let's return with it.
|
||||||
add esp, 4
|
add esp, 4
|
||||||
|
|
||||||
add eax, edx
|
add eax, edx
|
||||||
jmp .return
|
jmp .return
|
||||||
|
|
||||||
|
1850
kernel/trunk/fs/ext2/inode.inc
Normal file
1850
kernel/trunk/fs/ext2/inode.inc
Normal file
File diff suppressed because it is too large
Load Diff
223
kernel/trunk/fs/ext2/resource.inc
Normal file
223
kernel/trunk/fs/ext2/resource.inc
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; ;;
|
||||||
|
;; Contains common resource allocation + freeing code. ;;
|
||||||
|
;; ;;
|
||||||
|
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
|
||||||
|
;; Distributed under the terms of the new BSD license. ;;
|
||||||
|
;; ;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Frees a resource (block/inode).
|
||||||
|
; Input: eax = resource ID.
|
||||||
|
; edi = function pointer of ext2_bg_*_bitmap form, to
|
||||||
|
; get bitmap of resource.
|
||||||
|
; ecx = 0, block; 1, inode.
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
; Output: Block marked as free in block group.
|
||||||
|
; eax = error code.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_resource_free:
|
||||||
|
push ebx edx esi
|
||||||
|
|
||||||
|
; Get block group.
|
||||||
|
sub eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.first_data_block]
|
||||||
|
xor edx, edx
|
||||||
|
div [ebp + EXTFS.superblock + EXT2_SB_STRUC.blocks_per_group]
|
||||||
|
push eax edx
|
||||||
|
|
||||||
|
call edi
|
||||||
|
test eax, eax
|
||||||
|
jz .fail
|
||||||
|
mov esi, eax
|
||||||
|
|
||||||
|
; Read the bitmap.
|
||||||
|
mov eax, ebx
|
||||||
|
mov edx, eax
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||||||
|
call ext2_block_read
|
||||||
|
test eax, eax
|
||||||
|
jnz .fail
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
; Mark bit free.
|
||||||
|
call bitmap_clear_bit
|
||||||
|
test eax, eax
|
||||||
|
jz @F
|
||||||
|
|
||||||
|
; No need to save anything.
|
||||||
|
xor eax, eax
|
||||||
|
|
||||||
|
add esp, 4
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
@@:
|
||||||
|
mov eax, edx
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||||||
|
call ext2_block_write
|
||||||
|
test eax, eax
|
||||||
|
jnz .fail
|
||||||
|
|
||||||
|
; Read the descriptor.
|
||||||
|
mov eax, [esp]
|
||||||
|
call ext2_bg_read_desc
|
||||||
|
test eax, eax
|
||||||
|
jz .fail_bg_desc_read
|
||||||
|
|
||||||
|
lea eax, [eax + EXT2_BLOCK_GROUP_DESC.free_blocks_count]
|
||||||
|
shl ecx, 1
|
||||||
|
add eax, ecx
|
||||||
|
inc word[eax]
|
||||||
|
|
||||||
|
lea eax, [ebp + EXTFS.superblock + EXT2_SB_STRUC.free_block_count]
|
||||||
|
shl ecx, 1
|
||||||
|
add eax, ecx
|
||||||
|
inc dword[eax]
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
call ext2_bg_write_desc
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop esi edx ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.fail:
|
||||||
|
add esp, 4
|
||||||
|
.fail_bg_desc_read:
|
||||||
|
add esp, 4
|
||||||
|
xor eax, eax
|
||||||
|
not eax
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
; Allocates a resource.
|
||||||
|
; Input: eax = inode ID for "preference".
|
||||||
|
; ebp = pointer to EXTFS.
|
||||||
|
; [esp + 4], func pointer to ext2_bg_*_bitmap
|
||||||
|
; [esp + 8], pointer to free_*_count in SB.
|
||||||
|
; [esp + 12], *_per_group
|
||||||
|
; [esp + 16], offset to free_*_count in bg descriptor.
|
||||||
|
; [esp + 20], *_count
|
||||||
|
; Output: Resource marked as set in block group.
|
||||||
|
; eax = error code.
|
||||||
|
; ebx = resource ID.
|
||||||
|
;---------------------------------------------------------------------
|
||||||
|
ext2_resource_alloc:
|
||||||
|
; Block allocation is a pretty serious area, since bad allocation
|
||||||
|
; can lead to fragmentation. Thus, the best way to allocate that
|
||||||
|
; comes to mind is to allocate around an inode as much as possible.
|
||||||
|
; On the other hand, this isn't about a single inode/file/directory,
|
||||||
|
; and focusing just around the preferred inode would lead to
|
||||||
|
; congestion. Thus, after much thought, the chosen allocation algorithm
|
||||||
|
; is to search forward, then backward.
|
||||||
|
push ecx edx esi edi
|
||||||
|
|
||||||
|
cmp dword[esp + 16 + 8], 0
|
||||||
|
jnz @F
|
||||||
|
|
||||||
|
; No free blocks.
|
||||||
|
xor eax, eax
|
||||||
|
not eax
|
||||||
|
pop edi esi edx ecx
|
||||||
|
ret 20
|
||||||
|
|
||||||
|
@@:
|
||||||
|
; Calculate which block group the preferred inode belongs to.
|
||||||
|
dec eax
|
||||||
|
xor edx, edx
|
||||||
|
|
||||||
|
; EAX = block group.
|
||||||
|
div [ebp + EXTFS.superblock + EXT2_SB_STRUC.inodes_per_group]
|
||||||
|
push eax
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov edi, .forward
|
||||||
|
|
||||||
|
.test_block_group:
|
||||||
|
call dword[esp + 16 + 8 + 4]
|
||||||
|
test eax, eax
|
||||||
|
jz .fail
|
||||||
|
mov esi, eax
|
||||||
|
|
||||||
|
mov eax, ebx
|
||||||
|
mov edx, eax
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||||||
|
call ext2_block_read
|
||||||
|
test eax, eax
|
||||||
|
jnz .fail
|
||||||
|
|
||||||
|
mov ecx, [esp + 16 + 8 + 12]
|
||||||
|
call ext2_find_free_bit
|
||||||
|
cmp eax, 0xFFFFFFFF
|
||||||
|
jne @F
|
||||||
|
|
||||||
|
mov eax, edi
|
||||||
|
jmp eax
|
||||||
|
|
||||||
|
@@:
|
||||||
|
mov ecx, eax
|
||||||
|
|
||||||
|
mov eax, edx
|
||||||
|
mov ebx, [ebp + EXTFS.ext2_save_block]
|
||||||
|
call ext2_block_write
|
||||||
|
test eax, eax
|
||||||
|
jnz .fail
|
||||||
|
|
||||||
|
; ecx: the index of the matched entry.
|
||||||
|
; [esp]: block group where we found.
|
||||||
|
; [esp + 4]: starting block group.
|
||||||
|
; esi: block group descriptor.
|
||||||
|
mov eax, [esp] ; Index of block group in which we found.
|
||||||
|
mul dword[esp + 16 + 8 + 12]
|
||||||
|
add eax, ecx
|
||||||
|
mov ebx, eax
|
||||||
|
|
||||||
|
mov eax, [esp + 16 + 8 + 8]
|
||||||
|
dec dword[eax]
|
||||||
|
|
||||||
|
mov eax, esi
|
||||||
|
add eax, [esp + 16 + 8 + 16]
|
||||||
|
dec word[eax]
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
call ext2_bg_write_desc
|
||||||
|
|
||||||
|
add esp, 4
|
||||||
|
jmp .return
|
||||||
|
|
||||||
|
; Continue forward.
|
||||||
|
.forward:
|
||||||
|
inc dword[esp]
|
||||||
|
mov eax, [esp]
|
||||||
|
mul dword[esp + 16 + 8 + 12]
|
||||||
|
cmp eax, [esp + 16 + 8 + 20]
|
||||||
|
jbe @F
|
||||||
|
|
||||||
|
; We need to go backward.
|
||||||
|
mov eax, [esp + 4]
|
||||||
|
mov [esp], eax
|
||||||
|
mov edi, .backward
|
||||||
|
jmp .backward
|
||||||
|
|
||||||
|
@@:
|
||||||
|
mov eax, [esp]
|
||||||
|
jmp .test_block_group
|
||||||
|
|
||||||
|
; Continue backward.
|
||||||
|
.backward:
|
||||||
|
cmp dword[esp], 0
|
||||||
|
je .fail
|
||||||
|
|
||||||
|
dec dword[esp]
|
||||||
|
mov eax, [esp]
|
||||||
|
jmp .test_block_group
|
||||||
|
|
||||||
|
.return:
|
||||||
|
pop edi esi edx ecx
|
||||||
|
ret 20
|
||||||
|
|
||||||
|
.fail:
|
||||||
|
add esp, 8
|
||||||
|
xor eax, eax
|
||||||
|
not eax
|
||||||
|
jmp .return
|
Loading…
Reference in New Issue
Block a user