Finished ext2 write support, under KSoC.

git-svn-id: svn://kolibrios.org@4066 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
shikhin 2013-10-21 09:30:07 +00:00
parent e3f61693b7
commit 7365b0cf3f
6 changed files with 3025 additions and 37 deletions

View File

@ -1566,26 +1566,26 @@ Returned value:
Remarks: Remarks:
* The function is supported only for ATAPI devices (CD and DVD). * The function is supported only for ATAPI devices (CD and DVD).
* An example of usage of the function is the application CD_tray. * An example of usage of the function is the application CD_tray.
====================================================================== ======================================================================
======= Function 25 - put image area on the background layer. ======== ======= Function 25 - put image area on the background layer. ========
====================================================================== ======================================================================
Paramters: Paramters:
* eax = 25 - function number * eax = 25 - function number
* ebx = pointer to the previously allocated memory area, * ebx = pointer to the previously allocated memory area,
where placed the source images in a format BBGGRRTTBBGGRRTT... where placed the source images in a format BBGGRRTTBBGGRRTT...
* ecx = [size on axis x]*65536 + [size on axis y] * ecx = [size on axis x]*65536 + [size on axis y]
* edx = [coordinate on axis x]*65536 + [coordinate on axis y] * edx = [coordinate on axis x]*65536 + [coordinate on axis y]
Returned value: Returned value:
* function does not return value * function does not return value
Remarks: Remarks:
* Coordinates of the image are coordinates of the upper left corner * Coordinates of the image are coordinates of the upper left corner
of the image relative to the screen. of the image relative to the screen.
* Size of the image in bytes is 4*xsize*ysize * Size of the image in bytes is 4*xsize*ysize
* TT - byte pointer of transparency, at current version: * TT - byte pointer of transparency, at current version:
1 to FF - opaque, 0 - transparent. 1 to FF - opaque, 0 - transparent.
* The function places the image directly to LFB. It is not for * The function places the image directly to LFB. It is not for
background image f.15. Options f.15 to f.25 does not make sense. background image f.15. Options f.15 to f.25 does not make sense.
====================================================================== ======================================================================
======== Function 26, subfunction 1 - get MPU MIDI base port. ======== ======== Function 26, subfunction 1 - get MPU MIDI base port. ========
@ -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

View 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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View 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