Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 6461 → Rev 6462

/kernel/trunk/fs/ext2/blocks.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Revision
\ No newline at end of property
/kernel/trunk/fs/ext2/inode.inc
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Revision
\ No newline at end of property
/kernel/trunk/fs/ext2/ext2.inc
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Revision
\ No newline at end of property
/kernel/trunk/fs/ext2/resource.inc
File deleted
\ No newline at end of file
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Revision
\ No newline at end of property
/kernel/trunk/fs/ext2/ext2.asm
File deleted
Property changes:
Deleted: svn:eol-style
-native
\ No newline at end of property
Deleted: svn:keywords
-Revision
\ No newline at end of property
/kernel/trunk/fs/ext.inc
0,0 → 1,2508
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
; EXT external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> EXTFS structure
; [esi]+[[esp+4]] = name
; out:
; eax, ebx = return values for sysfunc 70
iglobal
align 4
ext_user_functions:
dd ext_free
dd (ext_user_functions_end - ext_user_functions - 4) / 4
dd ext_ReadFile
dd ext_ReadFolder
dd ext_CreateFile
dd ext_WriteFile
dd ext_SetFileEnd
dd ext_GetFileInfo
dd ext_SetFileInfo
dd 0
dd ext_Delete
dd ext_CreateFolder
ext_user_functions_end:
endg
 
struct DIRENTRY
inodeNumber dd ?
entryLength dw ?
nameLength db ?
fileType db ?
name db ? ; rb [nameLength]
ends
 
struct INODE
accessMode dw ?
UID dw ?
fileSize dd ?
accessedTime dd ?
inodeModified dd ?
dataModified dd ?
deletedTime dd ?
GID dw ?
linksCount dw ?
sectorsUsed dd ?
featureFlags dd ?
reserved dd ?
blockNumbers rd 12
addressBlock dd ?
doubleAddress dd ?
tripleAddress dd ?
generation dd ?
ACL dd ?
fileSizeHigh dd ?
ends
 
struct BGDESCR ; block group descriptor
blockBitmap dd ?
inodeBitmap dd ?
inodeTable dd ?
blocksFree dw ?
inodesFree dw ?
directoriesCount dw ?
reserved rb 14
ends
 
struct SUPERBLOCK
inodesTotal dd ?
blocksTotal dd ?
blocksReserved dd ?
blocksFree dd ?
inodesFree dd ?
firstGroupBlock dd ?
sectorsPerBlockLog dd ? ; shift for 1024
fragmentSizeLog dd ?
blocksPerGroup dd ?
fragmentsPerGroup dd ?
inodesPerGroup dd ?
lastMountTime dd ?
lastWriteTime dd ?
mountCount dw ?
mountMax dw ?
magic dw ?
state dw ?
errorHandling dw ?
additionalVersion dw ?
lastCheck dd ?
checkInterval dd ?
creatorOS dd ?
dynamicVersionFlag dd ?
reservedUID dw ?
reservedGID dw ?
firstInode dd ?
inodeSize dw ?
thisBlockGroup dw ?
compatibleFlags dd ?
incompatibleFlags dd ?
RO_compatibleFlags dd ?
ends
 
; ext4 extent tree
struct NODEHEADER ; tree node header
magic dw ? ; 0xF30A
entriesFolow dw ?
entriesMax dw ?
currentDepth dw ?
generation dd ?
ends
 
struct INDEX ; root/branch
fileBlock dd ?
nodeBlock dd ?
nodeBlockHigh dw ?
reserved dw ?
ends
 
struct EXTENT ; leaf
fileBlock dd ?
blocksCount dw ?
fsBlockHigh dw ?
fsBlock dd ?
ends
 
ROOT_INODE = 2
PERMISSIONS = 110110110b
EXTENTS_USED = 80000h
TYPE_MASK = 0F000h
FLAG_FILE = 8000h
DIRECTORY = 4000h
DIR_FLAG_FILE = 1
DIR_DIRECTORY = 2
KOS_HIDDEN = 2
KOS_DIRECTORY = 10h
READ_ONLY = 1
 
; Implemented "incompatible" features:
; 2 = have file type in directory entry
; 40h = extents
; 200h = flexible block groups
INCOMPATIBLE_SUPPORT = 242h
; Read only support for "incompatible" features:
INCOMPATIBLE_READ_SUPPORT = 240h
 
; Implemented "read-only" features:
; 1 = sparse superblock
; 2 = 64-bit file size
READ_ONLY_SUPPORT = 3
 
struct EXTFS PARTITION
Lock MUTEX
mountType dd ?
sectorsPerBlockLog dd ? ; shift for 512
bytesPerBlock dd ?
sectorsPerBlock dd ?
dwordsPerBlock dd ?
dwordsPerBranch dd ? ; dwordsPerBlock ^ 2
mainBlockBuffer dd ?
tempBlockBuffer dd ?
align 512
superblock SUPERBLOCK
align 1024
rootInodeBuffer INODE
align 1024
mainInodeBuffer INODE
align 1024
tempInodeBuffer INODE
ends
 
; mount if it's a valid EXT partition
ext2_create_partition:
; in:
; ebp -> PARTITION structure
; ebx -> boot sector
; ebx+512 -> buffer
; out:
; eax -> EXTFS structure, 0 = not EXT
push ebx
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .fail
mov eax, 2
add ebx, 512
call fs_read32_sys
test eax, eax
jnz .fail
cmp [ebx+SUPERBLOCK.magic], 0xEF53
jne .fail
cmp [ebx+SUPERBLOCK.state], 1
jne .fail
test [ebx+SUPERBLOCK.incompatibleFlags], not INCOMPATIBLE_SUPPORT
jnz .fail
cmp [ebx+SUPERBLOCK.sectorsPerBlockLog], 6 ; 64KB
ja .fail
cmp [ebx+SUPERBLOCK.inodeSize], 1024
ja .fail
cmp [ebx+SUPERBLOCK.blocksPerGroup], 0
je .fail
cmp [ebx+SUPERBLOCK.inodesPerGroup], 0
je .fail
stdcall kernel_alloc, 1000h
test eax, eax
jz .fail
mov ecx, dword [ebp+PARTITION.FirstSector]
mov dword [eax+EXTFS.FirstSector], ecx
mov ecx, dword [ebp+PARTITION.FirstSector+4]
mov dword [eax+EXTFS.FirstSector+4], ecx
mov ecx, dword [ebp+PARTITION.Length]
mov dword [eax+EXTFS.Length], ecx
mov ecx, dword [ebp+PARTITION.Length+4]
mov dword [eax+EXTFS.Length+4], ecx
mov ecx, [ebp+PARTITION.Disk]
mov [eax+EXTFS.Disk], ecx
mov [eax+EXTFS.FSUserFunctions], ext_user_functions
 
push ebp esi edi
mov ebp, eax
lea ecx, [eax+EXTFS.Lock]
call mutex_init
mov esi, ebx
lea edi, [ebp+EXTFS.superblock]
mov ecx, 512/4
rep movsd ; copy superblock
mov ecx, [ebx+SUPERBLOCK.sectorsPerBlockLog]
inc ecx
mov [ebp+EXTFS.sectorsPerBlockLog], ecx
mov eax, 1
shl eax, cl
mov [ebp+EXTFS.sectorsPerBlock], eax
shl eax, 9
mov [ebp+EXTFS.bytesPerBlock], eax
shl eax, 1
push eax
shr eax, 3
mov [ebp+EXTFS.dwordsPerBlock], eax
mul eax
mov [ebp+EXTFS.dwordsPerBranch], eax
call kernel_alloc
test eax, eax
jz .error
mov [ebp+EXTFS.mainBlockBuffer], eax
add eax, [ebp+EXTFS.bytesPerBlock]
mov [ebp+EXTFS.tempBlockBuffer], eax
mov [ebp+EXTFS.mountType], 0
test [ebx+SUPERBLOCK.RO_compatibleFlags], not READ_ONLY_SUPPORT
jnz .read_only
test [ebx+SUPERBLOCK.incompatibleFlags], INCOMPATIBLE_READ_SUPPORT
jz @f
.read_only:
or [ebp+EXTFS.mountType], READ_ONLY
@@: ; read root inode
lea ebx, [ebp+EXTFS.rootInodeBuffer]
mov eax, ROOT_INODE
call readInode
test eax, eax
jnz @f
mov eax, ebp
pop edi esi ebp ebx
ret
 
@@:
stdcall kernel_free, [ebp+EXTFS.mainBlockBuffer]
.error:
stdcall kernel_free, ebp
pop edi esi ebp
.fail:
pop ebx
xor eax, eax
ret
 
; unmount EXT partition
ext_free:
; in: eax -> EXTFS structure
push eax
stdcall kernel_free, [eax+EXTFS.mainBlockBuffer]
call kernel_free
ret
 
extfsWriteBlock:
push fs_write64_sys
jmp @f
; in:
; eax = block number
; ebx -> buffer
extfsReadBlock:
push fs_read64_sys
@@:
push ecx edx
mov ecx, [ebp+EXTFS.sectorsPerBlock]
mul ecx
call dword[esp+8]
pop edx ecx
add esp, 4
test eax, eax
jz @f
movi eax, ERROR_DEVICE
stc
@@:
ret
 
extfsReadDescriptor:
; in: eax = block group number
; out:
; [ebp+EXTFS.tempBlockBuffer] -> relevant block
; eax -> block group descriptor, 0 = error
push edx ebx
shl eax, 5
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
add eax, [ebp+EXTFS.superblock.firstGroupBlock]
inc eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .fail
mov eax, ebx
add eax, edx
@@:
pop ebx edx
ret
 
.fail:
xor eax, eax
stc
jmp @b
 
extfsWriteDescriptor:
; in:
; eax = block group number
; [ebp+EXTFS.tempBlockBuffer] -> relevant block
push edx ebx
shl eax, 5
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
add eax, [ebp+EXTFS.superblock.firstGroupBlock]
inc eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsWriteBlock
pop ebx edx
ret
 
extfsResourceFree:
; in:
; ecx=0 -> block, ecx=1 -> inode
; eax = block/inode number
push ebx edx
sub eax, [ebp+EXTFS.superblock.firstGroupBlock]
xor edx, edx
div [ebp+EXTFS.superblock.blocksPerGroup]
push eax edx
call extfsReadDescriptor
jc .fail
inc [eax+BGDESCR.blocksFree+ecx*2]
mov eax, [eax+BGDESCR.blockBitmap+ecx*4]
mov ebx, [ebp+EXTFS.mainBlockBuffer]
mov edx, eax
call extfsReadBlock
jc .fail
pop eax
push edx
mov edx, eax
and edx, 31
shr eax, 5
shl eax, 2
add eax, [ebp+EXTFS.mainBlockBuffer]
btr [eax], edx
pop eax
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsWriteBlock
jc @f
inc [ebp+EXTFS.superblock.blocksFree+ecx*4]
pop eax
call extfsWriteDescriptor
.ret:
pop edx ebx
ret
 
.fail:
pop eax
@@:
pop eax
movi eax, ERROR_DEVICE
jmp .ret
 
freeDoublyIndirectBlock:
; in: eax = doubly-indirect block number
; out: eax=1 -> finished
test eax, eax
jz .complete
push eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
pop eax
jc .ret
xor ecx, ecx
call extfsResourceFree
mov edx, ebx
add edx, [ebp+EXTFS.bytesPerBlock]
@@:
mov eax, [ebx]
test eax, eax
jz .complete
call extfsResourceFree
add ebx, 4
cmp ebx, edx
jb @b
.ret:
xor eax, eax
ret
 
.complete:
inc eax
ret
 
inodeBlockAlloc:
; in: esi -> inode
; out: ebx = block number
; TODO: fix to have correct preference.
mov eax, ROOT_INODE
call extfsBlockAlloc
jc @f
mov eax, [ebp+EXTFS.sectorsPerBlock]
add [esi+INODE.sectorsUsed], eax
xor eax, eax
@@:
ret
 
extfsBlockAlloc: ; also erases
; in: eax = inode number
; out: ebx = block number
xor ebx, ebx
call extfsResourceAlloc
jc @f
push ebx ecx edi
mov ecx, [ebp+EXTFS.dwordsPerBlock]
mov edi, [ebp+EXTFS.tempBlockBuffer]
mov ebx, edi
xor eax, eax
rep stosd
pop edi ecx
mov eax, [esp]
call extfsWriteBlock
pop ebx
@@:
ret
 
extfsResourceAlloc:
; in:
; eax = inode number
; ebx=0 -> block, ebx=1 -> inode
; out:
; ebx = block/inode number
push ecx edx esi edi
dec eax
xor edx, edx
div [ebp+EXTFS.superblock.inodesPerGroup]
push eax eax
mov esi, .forward ; search forward, then backward
.test_block_group:
call extfsReadDescriptor
jc .fail
dec [eax+BGDESCR.blocksFree+ebx*2]
mov eax, [eax+BGDESCR.blockBitmap+ebx*4]
push ebx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
mov edx, eax
mov edi, ebx
call extfsReadBlock
pop ebx
jc .fail
mov ecx, [ebp+EXTFS.superblock.blocksPerGroup+ebx*8]
or eax, -1
shr ecx, 5
jz .next
repz scasd
jz .next
sub edi, 4
mov eax, [edi]
not eax
bsf eax, eax
bts [edi], eax
sub edi, [ebp+EXTFS.mainBlockBuffer]
shl edi, 3
add eax, edi
mov ecx, eax
mov eax, edx
push ebx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsWriteBlock
pop ebx
jc .fail
mov eax, [esp]
mul [ebp+EXTFS.superblock.blocksPerGroup+ebx*8]
add eax, ecx
dec [ebp+EXTFS.superblock.blocksFree+ebx*4]
mov ebx, eax
pop eax
add esp, 4
call extfsWriteDescriptor
@@:
pop edi esi edx ecx
ret
 
.fail:
pop eax eax
movi eax, ERROR_DEVICE
jmp @b
 
.next:
jmp esi
 
.forward:
inc dword[esp]
mov eax, [esp]
mul [ebp+EXTFS.superblock.blocksPerGroup+ebx*8]
neg ebx
cmp eax, [ebp+EXTFS.superblock.blocksTotal+ebx*4]
ja @f
neg ebx
mov eax, [esp]
jmp .test_block_group
 
@@:
neg ebx
mov eax, [esp+4]
mov [esp], eax
mov esi, .backward
.backward:
sub dword[esp], 1
jc .fail
mov eax, [esp]
jmp .test_block_group
 
extfsGetFileBlock:
; in:
; ecx = file block number
; esi -> inode
; out:
; ecx = block number
test [esi+INODE.featureFlags], EXTENTS_USED
jz .listTreeSearch
pushad
add esi, INODE.blockNumbers
.extentTreeSearch:
cmp word [esi+NODEHEADER.magic], 0xF30A
jne .fail
movzx ebx, [esi+NODEHEADER.entriesFolow]
add esi, sizeof.NODEHEADER
cmp word [esi-sizeof.NODEHEADER+NODEHEADER.currentDepth], 0
je .leaf_block
test ebx, ebx
jz .fail ; empty
@@:
cmp ebx, 1
je .end_search_index
cmp ecx, [esi+INDEX.fileBlock]
jb .fail
cmp ecx, [esi+sizeof.INDEX+INDEX.fileBlock]
jb .end_search_index
add esi, sizeof.INDEX
dec ebx
jmp @b
 
.end_search_index:
mov ebx, [ebp+EXTFS.tempBlockBuffer]
mov eax, [esi+INDEX.nodeBlock]
call extfsReadBlock
jc .fail
mov esi, ebx
jmp .extentTreeSearch
 
.leaf_block:
test ebx, ebx
jz .fail
mov edx, [esi+EXTENT.fileBlock]
cmp ecx, edx
jb .fail
movzx edi, [esi+EXTENT.blocksCount]
add edx, edi
cmp ecx, edx
jb .end_search_extent
add esi, sizeof.EXTENT
dec ebx
jmp .leaf_block
 
.end_search_extent:
sub ecx, [esi+EXTENT.fileBlock]
add ecx, [esi+EXTENT.fsBlock]
mov PUSHAD_ECX, ecx
popad
xor eax, eax
ret
 
.fail:
popad
movi eax, ERROR_FS_FAIL
stc
ret
 
.get_indirect_block:
push edx ebx
mov eax, [esi+INODE.addressBlock]
test eax, eax
jz .fail3
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc @f
mov ecx, [ebx+ecx*4]
@@:
pop ebx edx
ret
 
.get_direct_block:
mov ecx, [esi+INODE.blockNumbers+ecx*4]
xor eax, eax
ret
 
.listTreeSearch:
cmp ecx, 12
jb .get_direct_block
sub ecx, 12
cmp ecx, [ebp+EXTFS.dwordsPerBlock]
jb .get_indirect_block
sub ecx, [ebp+EXTFS.dwordsPerBlock]
cmp ecx, [ebp+EXTFS.dwordsPerBranch]
jb .get_double_indirect_block
; triply-indirect blocks
sub ecx, [ebp+EXTFS.dwordsPerBranch]
push edx ebx
mov eax, [esi+INODE.tripleAddress]
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .fail2
xor edx, edx
mov eax, ecx
div [ebp+EXTFS.dwordsPerBranch]
; eax = number in triply-indirect block, edx = number in branch
mov eax, [ebx+eax*4]
test eax, eax
jz .fail3
call extfsReadBlock
jc .fail2
mov eax, edx
jmp @f
 
.fail3:
pop ebx edx
movi eax, ERROR_FS_FAIL
stc
ret
 
.get_double_indirect_block:
push edx ebx
mov eax, [esi+INODE.doubleAddress]
test eax, eax
jz .fail3
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .fail2
mov eax, ecx
@@:
xor edx, edx
div [ebp+EXTFS.dwordsPerBlock]
; eax = number in doubly-indirect block, edx = number in indirect block
mov eax, [ebx+eax*4]
test eax, eax
jz .fail3
call extfsReadBlock
jc .fail2
mov ecx, [ebx+edx*4]
.fail2:
pop ebx edx
ret
 
extfsSetFileBlock:
; in:
; ecx = file block number
; edi = block number
; esi -> inode
push ebx ecx edx
cmp ecx, 12
jb .direct_block
sub ecx, 12
cmp ecx, [ebp+EXTFS.dwordsPerBlock]
jb .indirect_block
sub ecx, [ebp+EXTFS.dwordsPerBlock]
cmp ecx, [ebp+EXTFS.dwordsPerBranch]
jb .double_indirect_block
; triple indirect blocks
sub ecx, [ebp+EXTFS.dwordsPerBranch]
mov eax, [esi+INODE.tripleAddress]
test eax, eax
jnz @f
call inodeBlockAlloc
jc .ret
mov [esi+INODE.tripleAddress], ebx
mov eax, ebx
@@:
push eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .fail_alloc_4
xor edx, edx
mov eax, ecx
div [ebp+EXTFS.dwordsPerBranch]
; eax = number in triply-indirect block, edx = number in branch
lea ecx, [ebx+eax*4]
mov eax, [ebx+eax*4]
test eax, eax
jnz @f
call inodeBlockAlloc
jc .fail_alloc_4
mov [ecx], ebx
mov eax, [esp]
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsWriteBlock
jc .fail_alloc_4
mov eax, [ecx]
@@:
mov [esp], eax
call extfsReadBlock
jc .fail_alloc_4
mov eax, edx
jmp @f
 
.double_indirect_block:
mov eax, [esi+INODE.doubleAddress]
test eax, eax
jnz .double_indirect_present
call inodeBlockAlloc
jc .ret
mov [esi+INODE.doubleAddress], ebx
mov eax, ebx
.double_indirect_present:
push eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .fail_alloc_4
mov eax, ecx
@@:
xor edx, edx
div [ebp+EXTFS.dwordsPerBlock]
; eax = number in doubly-indirect block, edx = number in indirect block
lea ecx, [ebx+edx*4]
push ecx
lea ecx, [ebx+eax*4]
cmp dword[ecx], 0
jne @f
call inodeBlockAlloc
jc .fail_alloc_8
mov [ecx], ebx
mov eax, [esp+4]
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsWriteBlock
jc .fail_alloc_8
@@:
mov eax, [ecx]
push eax
call extfsReadBlock
jc .fail_alloc_12
pop eax ecx edx
mov [ecx], edi
call extfsWriteBlock
jmp .ret
 
.indirect_block:
mov eax, [esi+INODE.addressBlock]
test eax, eax
jnz @f
call inodeBlockAlloc
jc .ret
mov [esi+INODE.addressBlock], ebx
mov eax, ebx
@@:
push eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .fail_alloc_4
mov [ebx+ecx*4], edi
pop eax
call extfsWriteBlock
jmp .ret
 
.direct_block:
mov [esi+INODE.blockNumbers+ecx*4], edi
xor eax, eax
.ret:
pop edx ecx ebx
ret
 
.fail_alloc_12:
pop ebx
.fail_alloc_8:
pop ebx
.fail_alloc_4:
pop ebx
jmp .ret
 
extfsEraseFileBlock: ; also allocates
; in:
; edx = inode number
; eax = file block number
; [ebp+EXTFS.tempInodeBuffer] = inode
push ebx ecx edx edi esi
mov edi, eax
mov ecx, eax
lea esi, [ebp+EXTFS.tempInodeBuffer]
call extfsGetFileBlock
jc @f
test ecx, ecx
jz .allocate
mov edx, ecx
mov ecx, [ebp+EXTFS.bytesPerBlock]
mov edi, [ebp+EXTFS.tempBlockBuffer]
xor eax, eax
rep stosb
mov eax, edx
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsWriteBlock
jmp @f
 
.allocate:
mov eax, edx
call extfsBlockAlloc
jc @f
mov ecx, edi
mov edi, ebx
lea esi, [ebp+EXTFS.tempInodeBuffer]
call extfsSetFileBlock
jc @f
mov eax, [ebp+EXTFS.sectorsPerBlock]
add [esi+INODE.sectorsUsed], eax
xor eax, eax
@@:
pop esi edi edx ecx ebx
ret
 
extfsFreeFileBlock:
; in:
; eax = file block number
; [ebp+EXTFS.tempInodeBuffer] = inode
push ebx ecx edi esi
mov edi, eax
mov ecx, eax
lea esi, [ebp+EXTFS.tempInodeBuffer]
call extfsGetFileBlock
jc @f
test ecx, ecx
jz @f
mov eax, ecx
xor ecx, ecx
call extfsResourceFree
mov ecx, edi
xor edi, edi
lea esi, [ebp+EXTFS.tempInodeBuffer]
call extfsSetFileBlock
mov eax, [ebp+EXTFS.sectorsPerBlock]
sub [esi+INODE.sectorsUsed], eax
xor eax, eax
@@:
pop esi edi ecx ebx
ret
 
extfsReadFileBlock:
; in:
; eax = file block number
; [ebp+EXTFS.tempInodeBuffer] = inode
; out:
; [ebp+EXTFS.mainBlockBuffer] -> block
push ebx ecx edx esi
mov ecx, eax
lea esi, [ebp+EXTFS.tempInodeBuffer]
call extfsGetFileBlock
jc .ret
test ecx, ecx
jz @f
mov eax, ecx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsReadBlock
.ret:
pop esi edx ecx ebx
ret
 
@@:
movi eax, ERROR_FS_FAIL
stc
jmp .ret
 
extfsWriteFileBlock:
; in:
; eax = file block number
; [ebp+EXTFS.tempInodeBuffer] = inode
; [ebp+EXTFS.mainBlockBuffer] -> block to write
push ebx ecx edx esi
mov ecx, eax
lea esi, [ebp+EXTFS.tempInodeBuffer]
call extfsGetFileBlock
jc @f
test ecx, ecx
jz @b
mov eax, ecx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsWriteBlock
@@:
pop esi edx ecx ebx
ret
 
getInodeLocation:
; in: eax = inode number
; out:
; ebx = inode sector
; edx = offset in sector
dec eax
xor edx, edx
div [ebp+EXTFS.superblock.inodesPerGroup]
mov ecx, edx
shl eax, 5
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
add eax, [ebp+EXTFS.superblock.firstGroupBlock]
inc eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc @f
add ebx, edx
mov ebx, [ebx+BGDESCR.inodeTable]
mov eax, ecx
mov ecx, [ebp+EXTFS.sectorsPerBlockLog]
shl ebx, cl
mul [ebp+EXTFS.superblock.inodeSize]
mov edx, eax
shr eax, 9
and edx, 511
add ebx, eax
xor eax, eax
@@:
ret
 
writeInode:
; in:
; eax = inode number
; ebx -> inode data
push edx edi esi ecx ebx eax
mov edi, ebx
call fsGetTime
add eax, 978307200
mov [edi+INODE.inodeModified], eax
pop eax
call getInodeLocation
jc .ret
mov eax, ebx
mov ebx, [ebp+EXTFS.tempBlockBuffer]
mov ecx, eax
call fs_read32_sys
test eax, eax
jnz @f
mov eax, ecx
mov esi, edi
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
mov edi, edx
add edi, ebx
rep movsb
call fs_write32_sys
.ret:
pop ebx ecx esi edi edx
ret
 
@@:
movi eax, ERROR_DEVICE
stc
jmp .ret
 
readInode:
; in:
; eax = inode number
; ebx -> inode buffer
push edx edi esi ecx ebx
mov edi, ebx
call getInodeLocation
jc @f
mov eax, ebx
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call fs_read32_sys
test eax, eax
jnz @b
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
mov esi, edx
add esi, ebx
rep movsb
xor eax, eax
@@:
pop ebx ecx esi edi edx
ret
 
extfsExtendFile:
; in:
; eax = inode number
; ecx = new size
push ebx ecx edx esi edi eax
lea ebx, [ebp+EXTFS.tempInodeBuffer]
call readInode
jc .ret
cmp [ebx+INODE.fileSize], ecx
jnc .ret
mov eax, [ebx+INODE.fileSize]
push eax
sub ecx, eax
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
test edx, edx
jz .start_aligned
mov esi, [ebp+EXTFS.bytesPerBlock]
sub esi, edx
cmp esi, ecx
jbe @f
mov esi, ecx
@@: ; clear esi trailing bytes in block number eax
push eax
call extfsReadFileBlock
pop edi
jc .error_inode_size
push edi ecx
xor eax, eax
mov ecx, esi
mov edi, ebx
add edi, edx
rep stosb
pop ecx eax
call extfsWriteFileBlock
jc .error_inode_size
add [esp], esi
sub ecx, esi
jz .write_inode
.start_aligned:
cmp ecx, [ebp+EXTFS.bytesPerBlock]
jb @f
mov eax, [esp]
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
mov edx, [esp+4]
call extfsEraseFileBlock
jc .error_inode_size
mov eax, [ebp+EXTFS.bytesPerBlock]
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.bytesPerBlock]
mov edx, [esp+4]
call extfsEraseFileBlock
jc .error_inode_size
add [esp], ecx
.write_inode:
xor eax, eax
.error_inode_size:
lea ebx, [ebp+EXTFS.tempInodeBuffer]
pop [ebx+INODE.fileSize]
push eax
mov eax, [esp+4]
call writeInode
pop ebx
jc .ret
xchg eax, ebx
cmp ebx, eax ; set CF
.ret:
pop edi edi esi edx ecx ebx
ret
 
extfsTruncateFile:
; in:
; eax = inode number
; ecx = new size
push ebx ecx edx esi edi eax
lea ebx, [ebp+EXTFS.tempInodeBuffer]
call readInode
jc .ret
cmp ecx, [ebx+INODE.fileSize]
jnc .ret
mov eax, [ebx+INODE.fileSize]
push eax
sub ecx, eax
not ecx
inc ecx
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
test edx, edx
jz .start_aligned
mov esi, edx
cmp esi, ecx
jbe @f
; if the size to truncate is smaller than the unaligned bytes
; we're going to clear neccessary bytes from the EOF
push eax
call extfsReadFileBlock
pop edi
jc .error_inode_size
push edi ecx
mov edi, [ebp+EXTFS.mainBlockBuffer]
sub edx, ecx
add edi, edx
xor eax, eax
rep stosb
pop ecx eax
call extfsWriteFileBlock
jc .error_inode_size
sub [esp], ecx
jmp .write_inode
 
@@:
call extfsFreeFileBlock
sub [esp], esi
sub ecx, esi
jz .write_inode
.start_aligned:
cmp ecx, [ebp+EXTFS.bytesPerBlock]
jb @f
mov eax, [esp]
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
dec eax
call extfsFreeFileBlock
mov eax, [ebp+EXTFS.bytesPerBlock]
sub ecx, eax
sub [esp], eax
jmp .start_aligned
 
@@: ; handle the remaining bytes
test ecx, ecx
jz .write_inode
mov eax, [esp]
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
dec eax
push eax
call extfsReadFileBlock
pop edi
jc .error_inode_size
push edi ecx
mov edi, [ebp+EXTFS.mainBlockBuffer]
mov edx, [ebp+EXTFS.bytesPerBlock]
sub edx, ecx
add edi, edx
xor eax, eax
rep stosb
pop ecx eax
call extfsWriteFileBlock
jc .error_inode_size
sub [esp], ecx
.write_inode:
xor eax, eax
.error_inode_size:
lea ebx, [ebp+EXTFS.tempInodeBuffer]
pop [ebx+INODE.fileSize]
push eax
mov eax, [esp+4]
call writeInode
pop ebx
jc .ret
xchg eax, ebx
cmp ebx, eax ; set CF
.ret:
pop edi edi esi edx ecx ebx
ret
 
linkInode:
; in:
; eax = inode on which to link
; ebx = inode to link
; esi -> name
; dl = file type
push esi edi ebx ecx eax edx
call strlen
add ecx, 8 ; directory entry size
push esi ebx ecx
xor ecx, ecx
lea esi, [ebp+EXTFS.tempInodeBuffer]
mov ebx, esi
call readInode
jc .error_inode_read
mov ecx, [ebp+EXTFS.sectorsPerBlockLog]
mov eax, [esi+INODE.sectorsUsed]
shr eax, cl
xor ecx, ecx
push eax ; maximum file block number
push ecx ; current file block number
.searchBlock:
call extfsGetFileBlock
jc .error_get_inode_block
test ecx, ecx
jz .alloc_block
push ecx
mov eax, ecx
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .error_block_read
mov ecx, [esp+8]
mov edi, [ebp+EXTFS.tempBlockBuffer]
mov edx, edi
add edx, [ebp+EXTFS.bytesPerBlock]
.searchSpace:
movzx eax, [edi+DIRENTRY.entryLength]
test eax, eax
jz .zeroLength
cmp [edi+DIRENTRY.inodeNumber], 0
je .unusedEntry
movzx ebx, [edi+DIRENTRY.nameLength]
add ebx, 8+3
and ebx, -4
sub eax, ebx
add edi, ebx
cmp eax, ecx
jb .nextEntry
sub edi, ebx
mov [edi+DIRENTRY.entryLength], bx
add edi, ebx
mov [edi+DIRENTRY.entryLength], ax
jmp .found
 
.unusedEntry:
cmp eax, ecx
jge .found
.nextEntry:
add edi, eax
cmp edi, edx
jb .searchSpace
jmp .nextBlock
 
.zeroLength:
mov [edi+DIRENTRY.entryLength], cx
mov eax, edx
sub eax, edi
cmp eax, ecx
jge .found
mov [edi+DIRENTRY.inodeNumber], 0
mov [edi+DIRENTRY.entryLength], ax
; this block wasn't linking to the next one, so write it, and use the next block
pop eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsWriteBlock
jc .error_get_inode_block
inc dword[esp]
mov ecx, [esp]
call extfsGetFileBlock
jc .error_get_inode_block
test ecx, ecx
jz .alloc_block
push ecx
jmp .prepare_block
 
.nextBlock:
add esp, 4
inc dword[esp]
mov ecx, [esp]
cmp ecx, [esp+4]
jbe .searchBlock
.alloc_block:
mov eax, [esp+12]
call extfsBlockAlloc
jc .error_get_inode_block
mov ecx, [esp]
mov edi, ebx
call extfsSetFileBlock
jc .error_get_inode_block
mov eax, [ebp+EXTFS.bytesPerBlock]
add [esi+INODE.fileSize], eax
mov eax, [ebp+EXTFS.sectorsPerBlock]
add [esi+INODE.sectorsUsed], eax
mov eax, [esp+24]
mov ebx, esi
call writeInode
jc .error_get_inode_block
push edi ; save the block we just allocated
.prepare_block:
mov eax, [esp]
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .error_block_read
mov edi, ebx
mov eax, [ebp+EXTFS.bytesPerBlock]
mov [edi+DIRENTRY.entryLength], ax
.found:
pop edx ecx ecx ecx ebx esi
push ebx
mov [edi], ebx ; save inode
mov eax, [esp+4]
cmp [ebp+EXTFS.superblock.dynamicVersionFlag], 0
je .name
mov [edi+DIRENTRY.fileType], al
.name:
sub ecx, 8
mov [edi+DIRENTRY.nameLength], cl
add edi, 8
rep movsb
mov eax, edx
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsWriteBlock
jc .error_block_write
mov eax, [esp]
lea ebx, [ebp+EXTFS.tempInodeBuffer]
call readInode
jc .error_block_write
pop eax
inc [ebx+INODE.linksCount]
call writeInode
jc @f
xor eax, eax
@@:
pop edx ecx ecx ebx edi esi
ret
 
.error_block_read:
pop ebx
.error_get_inode_block:
pop ebx ebx
.error_inode_read:
pop ebx ebx
.error_block_write:
pop ebx
jmp @b
 
unlinkInode:
; in:
; eax = inode from which to unlink
; ebx = inode to unlink
; out:
; eax = current number of links to inode, -1 = error
push edx esi edi ebx
lea ebx, [ebp+EXTFS.tempInodeBuffer]
call readInode
jc .fail
push eax
lea esi, [ebp+EXTFS.tempInodeBuffer]
.loop:
mov ecx, [esp]
call extfsGetFileBlock
jc .fail_loop
test ecx, ecx
jz .fail_loop
mov eax, ecx
mov edi, ecx
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .fail_loop
.first_dir_entry: ; edi -> block
mov eax, [esp+4]
cmp [ebx+DIRENTRY.inodeNumber], eax
jne @f
mov [ebx+DIRENTRY.inodeNumber], 0
mov word [ebx+DIRENTRY.nameLength], 0 ; fileType = 0
jmp .write_block
 
@@:
mov edx, ebx
add edx, [ebp+EXTFS.bytesPerBlock]
push edx
mov edx, ebx
movzx ecx, [ebx+DIRENTRY.entryLength]
add ebx, ecx
.dir_entry:
cmp [ebx+DIRENTRY.inodeNumber], eax
jne @f
mov cx, [ebx+DIRENTRY.entryLength]
add [edx+DIRENTRY.entryLength], cx
pop eax
jmp .write_block
 
@@:
mov edx, ebx
movzx ecx, [ebx+DIRENTRY.entryLength]
test ecx, ecx
jz .fail_inode
add ebx, ecx
cmp ebx, [esp]
jb .dir_entry
pop ecx
inc dword[esp]
jmp .loop
 
.fail_inode:
pop eax
.fail_loop:
pop eax
.fail:
or eax, -1
jmp @f
 
.write_block:
pop eax
mov eax, edi
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsWriteBlock
jc .fail
mov eax, [esp]
lea ebx, [ebp+EXTFS.tempInodeBuffer]
call readInode
jc .fail
dec word [ebx+INODE.linksCount]
mov eax, [esp]
call writeInode
jc .fail
movzx eax, word [ebx+INODE.linksCount]
@@:
pop ebx edi esi edx
ret
 
findInode_parent:
; in: esi -> path
; out:
; edi -> file name
; esi = inode
push esi
xor edi, edi
.loop:
cmp byte [esi], '/'
jne @f
mov edi, esi
inc esi
jmp .loop
 
@@:
inc esi
cmp byte [esi-1], 0
jne .loop
cmp edi, 0
jne @f
; parent is root
pop edi
dec esi
jmp .get_inode
 
@@: ; parent is folder
mov byte [edi], 0
inc edi
pop esi
.get_inode:
push ebx edx
stdcall findInode, 0
pop edx ebx
ret
 
findInode:
; in: [esi]+[[esp+4]] = name
; out:
; [ebp+EXTFS.mainInodeBuffer] = inode
; esi = inode number
; dl = first byte of file/folder name
lea edx, [ebp+EXTFS.rootInodeBuffer]
cmp [edx+INODE.sectorsUsed], 0
je .not_found
cmp byte [esi], 0
jne .next_path_part
; root
push edi ecx
lea esi, [ebp+EXTFS.rootInodeBuffer]
lea edi, [ebp+EXTFS.mainInodeBuffer]
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
rep movsb
pop ecx edi
xor eax, eax
xor dl, dl
mov esi, ROOT_INODE
ret 4
 
.next_path_part:
push [edx+INODE.sectorsUsed]
xor ecx, ecx
.folder_block_cycle:
push ecx
xchg esi, edx
call extfsGetFileBlock
jc .error_get_block
xchg esi, edx
mov eax, ecx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsReadBlock
jc .error_get_block
push esi edx
sub esp, 256
mov edx, ebx
add edx, [ebp+EXTFS.bytesPerBlock]
.start_rec:
cmp [ebx+DIRENTRY.inodeNumber], 0
jz .next_rec
mov edi, esp
push esi
movzx ecx, [ebx+DIRENTRY.nameLength]
lea esi, [ebx+DIRENTRY.name]
call utf8_to_cp866
mov ecx, edi
lea edi, [esp+4]
sub ecx, edi ; number of bytes in resulting string
mov esi, [esp]
@@: ; edi -> converted string in stack, ecx = size, esi -> original file path
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
@@: ; doesn't match
pop esi
.next_rec:
movzx eax, [ebx+DIRENTRY.entryLength]
add ebx, eax
cmp ebx, edx
jb .start_rec
push eax
jmp @f
 
.test_find:
cmp byte [esi], 0
je @f
cmp byte [esi], '/'
jne @b
inc esi
@@:
add esp, 256+4
pop edx edi ecx
; ebx -> matched directory entry, esi -> name without parent, or not changed
cmp edi, esi
je .next_folder_block
cmp byte [esi], 0
jnz @f
cmp dword[esp+8], 0
je .get_inode_ret
mov esi, [esp+8]
mov dword[esp+8], 0
@@:
mov eax, [ebx+DIRENTRY.inodeNumber]
lea ebx, [ebp+EXTFS.mainInodeBuffer]
call readInode
jc .error_get_inode
movzx eax, [ebx+INODE.accessMode]
and eax, TYPE_MASK
cmp eax, DIRECTORY
jne .not_found ; path folder is a file
pop ecx
mov edx, ebx
jmp .next_path_part
 
.next_folder_block:
pop eax
sub eax, [ebp+EXTFS.sectorsPerBlock]
jle .not_found
push eax
inc ecx
jmp .folder_block_cycle
 
.get_inode_ret:
pop eax
mov dl, [ebx+DIRENTRY.name]
mov eax, [ebx+DIRENTRY.inodeNumber]
lea ebx, [ebp+EXTFS.mainInodeBuffer]
mov esi, eax
call readInode
ret 4
 
.not_found:
movi eax, ERROR_FILE_NOT_FOUND
stc
ret 4
 
.error_get_block:
pop ebx
.error_get_inode:
pop ebx
ret 4
 
writeSuperblock:
push ebx
mov eax, 2
lea ebx, [ebp+EXTFS.superblock]
call fs_write32_sys
pop ebx
ret
 
extfsWritingInit:
movi eax, ERROR_ACCESS_DENIED
cmp byte [esi], 0
jz @f
movi eax, ERROR_UNSUPPORTED_FS
test [ebp+EXTFS.mountType], READ_ONLY
jnz @f
ext_lock:
lea ecx, [ebp+EXTFS.Lock]
jmp mutex_lock
 
@@:
pop ebx
xor ebx, ebx
ret
 
ext_unlock:
lea ecx, [ebp+EXTFS.Lock]
jmp mutex_unlock
 
;----------------------------------------------------------------
ext_ReadFolder:
call ext_lock
cmp byte [esi], 0
jz .root_folder
push ebx
stdcall findInode, [esp+4+4]
pop ebx
jc .error_ret
lea esi, [ebp+EXTFS.mainInodeBuffer]
test [esi+INODE.accessMode], DIRECTORY
jz .error_not_found
jmp @f
 
.root_folder:
lea esi, [ebp+EXTFS.rootInodeBuffer]
lea edi, [ebp+EXTFS.mainInodeBuffer]
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
shr ecx, 2
push edi
rep movsd
pop esi
@@:
cmp [esi+INODE.fileSize], 0
je .error_empty_dir
mov edx, [ebx+16]
push edx ; [edi+28] result buffer
push 0 ; [edi+24] end of the current block in folder
pushd [ebx+12] ; [edi+20] files to read
pushd [ebx+4] ; [edi+16] first wanted file
pushd [ebx+8] ; [edi+12] flags
push 0 ; [edi+8] read files
push 0 ; [edi+4] files in folder
push 0 ; [edi] current block index
mov edi, esp ; edi -> local variables
add edx, 32
xor ecx, ecx
call extfsGetFileBlock
jc .error_get_block
mov eax, ecx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsReadBlock
jc .error_get_block
mov eax, ebx
add eax, [ebp+EXTFS.bytesPerBlock]
mov [edi+24], eax
mov ecx, [edi+16]
.find_wanted_start:
jecxz .find_wanted_end
.find_wanted_cycle:
cmp [ebx+DIRENTRY.inodeNumber], 0
jz @f
inc dword [edi+4]
dec ecx
@@:
movzx eax, [ebx+DIRENTRY.entryLength]
cmp eax, 12 ; minimum entry length
jb .error_bad_len
test eax, 3 ; length must be aligned
jnz .error_bad_len
sub [esi+INODE.fileSize], eax
add ebx, eax
cmp ebx, [edi+24]
jb .find_wanted_start
push .find_wanted_start
.end_block: ; read next block
cmp [esi+INODE.fileSize], 0
jle .end_dir
inc dword [edi]
push ecx
mov ecx, [edi]
call extfsGetFileBlock
jc .error_get_block
mov eax, ecx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsReadBlock
jc .error_get_block
pop ecx
mov eax, ebx
add eax, [ebp+EXTFS.bytesPerBlock]
mov [edi+24], eax
ret
 
.wanted_end:
loop .find_wanted_cycle
.find_wanted_end:
mov ecx, [edi+20]
.wanted_start:
jecxz .wanted_end
cmp [ebx+DIRENTRY.inodeNumber], 0
jz .empty_rec
inc dword [edi+8]
inc dword [edi+4]
push ebx edi ecx esi edx
mov edi, edx
xor eax, eax
mov ecx, 40 / 4
rep stosd
mov eax, [ebx+DIRENTRY.inodeNumber]
lea ebx, [ebp+EXTFS.tempInodeBuffer]
call readInode
jc .error_read_subinode
mov esi, ebx
lea edi, [edx+8]
mov eax, [ebx+INODE.inodeModified]
sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
call fsTime2bdfe
 
mov eax, [esi+INODE.accessedTime]
sub eax, 978307200
call fsTime2bdfe
 
mov eax, [esi+INODE.dataModified]
sub eax, 978307200
call fsTime2bdfe
pop edx
or dword [edx], KOS_DIRECTORY
test [esi+INODE.accessMode], DIRECTORY
jnz @f
xor dword [edx], KOS_DIRECTORY ; mark as file
mov eax, [esi+INODE.fileSize]
stosd
mov eax, [esi+INODE.fileSizeHigh]
stosd
@@:
mov esi, [esp+12]
movzx ecx, [esi+DIRENTRY.nameLength]
lea edi, [edx+40]
lea esi, [esi+DIRENTRY.name]
call utf8_to_cp866
and byte [edi], 0
pop esi ecx edi ebx
cmp byte [edx+40], '.'
jne @f
or dword [edx], KOS_HIDDEN
@@:
add edx, 40+264 ; go to the next record
dec ecx
.empty_rec:
movzx eax, [ebx+DIRENTRY.entryLength]
cmp eax, 12
jb .error_bad_len
test eax, 3
jnz .error_bad_len
sub [esi+INODE.fileSize], eax
add ebx, eax
cmp ebx, [edi+24]
jb .wanted_start
push .wanted_start
jmp .end_block
 
.end_dir:
call ext_unlock
mov edx, [edi+28]
mov ebx, [edi+8]
mov ecx, [edi+4]
mov dword [edx], 1 ; version
mov [edx+4], ebx
mov [edx+8], ecx
lea esp, [edi+32]
mov ecx, 20/4
lea edi, [edx+12]
xor eax, eax
rep stosd
ret
 
.error_bad_len:
movi eax, ERROR_FS_FAIL
.error_read_subinode:
.error_get_block:
lea esp, [edi+32]
.error_ret:
or ebx, -1
push eax
call ext_unlock
pop eax
ret
 
.error_empty_dir:
movi eax, ERROR_FS_FAIL
jmp .error_ret
 
.error_not_found:
movi eax, ERROR_FILE_NOT_FOUND
jmp .error_ret
 
;----------------------------------------------------------------
ext_ReadFile:
call ext_lock
push ERROR_ACCESS_DENIED
cmp byte [esi], 0
jz .error ; root
mov [esp], ebx
stdcall findInode, [esp+4+4]
pop ebx
jc .error_eax
push ERROR_ACCESS_DENIED
lea esi, [ebp+EXTFS.mainInodeBuffer]
mov ax, [esi+INODE.accessMode]
and ax, TYPE_MASK
cmp ax, FLAG_FILE
jnz .error ; not a file
pop eax
mov edi, [ebx+16]
mov ecx, [ebx+12]
mov eax, [ebx+4]
mov edx, [ebx+8]
push ERROR_END_OF_FILE
cmp [esi+INODE.fileSizeHigh], edx
ja @f
jb .error
cmp [esi+INODE.fileSize], eax
jna .error
@@:
add esp, 4
add eax, ecx
adc edx, 0
cmp [esi+INODE.fileSizeHigh], edx
ja .read_till_requested
jb .read_whole_file
cmp [esi+INODE.fileSize], eax
jae .read_till_requested
.read_whole_file:
push 1 ; read till the end of file
mov ecx, [esi+INODE.fileSize]
sub ecx, [ebx+4]
jmp @f
 
.read_till_requested:
push 0 ; read as much as requested
@@: ; ecx = bytes to read, edi -> buffer
push ecx
; read part of the first block
mov edx, [ebx+8]
mov eax, [ebx+4]
div [ebp+EXTFS.bytesPerBlock]
push eax
push ecx
mov ecx, eax
call extfsGetFileBlock
jc .error_at_first_block
mov ebx, [ebp+EXTFS.mainBlockBuffer]
mov eax, ecx
call extfsReadBlock
jc .error_at_first_block
pop ecx
add ebx, edx
neg edx
add edx, [ebp+EXTFS.bytesPerBlock]
cmp ecx, edx
jbe .only_one_block
mov eax, ecx
sub eax, edx ; bytes to read
mov ecx, edx
push esi
mov esi, ebx
rep movsb
pop esi
mov ebx, edi
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
mov edi, eax
@@:
test edi, edi
jz .finish_block
inc dword [esp]
mov ecx, [esp]
call extfsGetFileBlock
jc .error_at_read_cycle
mov eax, ecx
call extfsReadBlock
jc .error_at_read_cycle
add ebx, [ebp+EXTFS.bytesPerBlock]
dec edi
jmp @b
 
.finish_block: ; edx = number of bytes in the last block
test edx, edx
jz .end_read
pop ecx ; block counter
inc ecx
call extfsGetFileBlock
jc .error_at_finish_block
mov edi, ebx
mov eax, ecx
mov ebx, [ebp+EXTFS.mainBlockBuffer]
call extfsReadBlock
jc .error_at_finish_block
push eax
mov ecx, edx
.only_one_block:
mov esi, ebx
rep movsb
.end_read:
call ext_unlock
pop eax ebx eax
test eax, eax
jz @f
movi eax, ERROR_END_OF_FILE
@@:
ret
 
.error_at_first_block:
pop ebx
.error_at_read_cycle:
pop ebx
.error_at_finish_block:
pop ebx ebx
.error_eax:
push eax
.error:
call ext_unlock
xor ebx, ebx
pop eax
ret
 
;----------------------------------------------------------------
ext_GetFileInfo:
call ext_lock
mov edx, [ebx+16]
cmp byte [esi], 0
jz .is_root
push edx
stdcall findInode, [esp+4+4]
mov ebx, edx
pop edx
lea esi, [ebp+EXTFS.mainInodeBuffer]
jnc @f
push eax
call ext_unlock
pop eax
ret
 
.is_root:
xor ebx, ebx
lea esi, [ebp+EXTFS.rootInodeBuffer]
@@:
xor eax, eax
mov edi, edx
mov ecx, 40/4
rep stosd
cmp bl, '.'
jne @f
or dword [edx], KOS_HIDDEN
@@:
or dword [edx], KOS_DIRECTORY
test [esi+INODE.accessMode], DIRECTORY
jnz @f
xor dword [edx], KOS_DIRECTORY ; mark as file
mov eax, [esi+INODE.fileSize]
mov ebx, [esi+INODE.fileSizeHigh]
mov dword [edx+32], eax
mov dword [edx+36], ebx
@@:
lea edi, [edx+8]
mov eax, [esi+INODE.inodeModified]
sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
call fsTime2bdfe
 
mov eax, [esi+INODE.accessedTime]
sub eax, 978307200
call fsTime2bdfe
 
mov eax, [esi+INODE.dataModified]
sub eax, 978307200
call fsTime2bdfe
call ext_unlock
xor eax, eax
ret
 
;----------------------------------------------------------------
ext_SetFileInfo:
call extfsWritingInit
pushd [ebx+16]
stdcall findInode, [esp+4+4]
pop edx
jc @f
push esi ; inode number
lea esi, [edx+16]
lea edi, [ebp+EXTFS.mainInodeBuffer]
call fsCalculateTime
add eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
mov [edi+INODE.accessedTime], eax
 
add esi, 8
call fsCalculateTime
add eax, 978307200
mov [edi+INODE.dataModified], eax
mov ebx, edi
pop eax
call writeInode
@@:
push eax
jc @f
call writeSuperblock
mov esi, [ebp+PARTITION.Disk]
call disk_sync
@@:
call ext_unlock
pop eax
ret
 
;----------------------------------------------------------------
ext_Delete:
call extfsWritingInit
push esi
stdcall findInode, [esp+4+4]
mov ebx, esi
pop esi
push eax
jc .ret
pop eax
lea edx, [ebp+EXTFS.mainInodeBuffer]
movzx edx, [edx+INODE.accessMode]
and edx, TYPE_MASK
cmp edx, DIRECTORY
jne .file
push esi ebx edx 0
lea esi, [ebp+EXTFS.mainInodeBuffer]
.checkDirectory:
mov ecx, [esp]
call extfsGetFileBlock
jc .not_empty_eax
test ecx, ecx
jz .empty
mov eax, ecx
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
jc .not_empty_eax
mov edx, ebx
add edx, [ebp+EXTFS.bytesPerBlock]
movzx ecx, [ebx+DIRENTRY.entryLength]
add ebx, ecx
.dir_entry:
cmp byte [ebx+DIRENTRY.nameLength], 1
jne @f
cmp byte [ebx+DIRENTRY.name], '.'
jne .not_empty
@@:
cmp byte [ebx+DIRENTRY.nameLength], 2
jne .not_empty
cmp word [ebx+DIRENTRY.name], '..'
jne .not_empty
movzx ecx, [ebx+DIRENTRY.entryLength]
add ebx, ecx
cmp ebx, edx
jb .dir_entry
inc dword[esp]
jmp .checkDirectory
 
.empty:
pop edx edx ebx esi
.file:
call findInode_parent
jc .error
mov eax, esi
; save file/folder's and parent's inode
push ebx eax
cmp edx, DIRECTORY
jne @f
; Unlink '.'
mov eax, [esp+4]
call unlinkInode
cmp eax, -1
je .error_stack8
; Unlink '..'
mov eax, [esp+4]
mov ebx, [esp]
call unlinkInode
cmp eax, -1
je .error_stack8
@@:
pop eax
mov ebx, [esp]
call unlinkInode
cmp eax, -1
je .error_stack4
test eax, eax
jz @f
; has hardlinks
xor eax, eax
mov [esp], eax
jmp .disk_sync
 
@@:
mov eax, [esp]
lea ebx, [ebp+EXTFS.mainInodeBuffer]
call readInode
jc .error_stack4_eax
; free file's data
lea esi, [ebp+EXTFS.mainInodeBuffer]
xor ecx, ecx
@@:
push ecx
call extfsGetFileBlock
jc .error_stack8_eax
mov eax, ecx
test eax, eax
jz @f
xor ecx, ecx
call extfsResourceFree
pop ecx
inc ecx
jmp @b
 
@@: ; free indirect blocks
pop ecx
push edx
lea edi, [ebp+EXTFS.mainInodeBuffer]
mov eax, [edi+INODE.addressBlock]
test eax, eax
jz .success
xor ecx, ecx
call extfsResourceFree
mov eax, [edi+INODE.doubleAddress]
call freeDoublyIndirectBlock
cmp eax, 1
je .success
mov eax, [edi+INODE.tripleAddress]
test eax, eax
jz .success
push eax
mov ebx, [ebp+EXTFS.tempBlockBuffer]
call extfsReadBlock
pop ecx
jc .error_stack8_eax
mov eax, ecx
xor ecx, ecx
call extfsResourceFree
mov edx, ebx
add edx, [ebp+EXTFS.bytesPerBlock]
@@:
mov eax, [ebx]
test eax, eax
jz .success
push ebx edx
call freeDoublyIndirectBlock
pop edx ebx
cmp eax, 1
je .success
add ebx, 4
cmp ebx, edx
jb @b
.success: ; clear the inode, and add deletion time
xor eax, eax
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
rep stosb
lea edi, [ebp+EXTFS.mainInodeBuffer]
call fsGetTime
pop edx
add eax, 978307200
mov [edi+INODE.deletedTime], eax
mov eax, [esp]
mov ebx, edi
call writeInode
jc .error_stack4_eax
cmp edx, DIRECTORY
jne @f
mov eax, [esp]
dec eax
xor edx, edx
div [ebp+EXTFS.superblock.inodesPerGroup]
push eax
call extfsReadDescriptor
jc .error_stack8
dec [eax+BGDESCR.directoriesCount]
pop eax
call extfsWriteDescriptor
@@: ; free inode
pop eax
dec eax
xor ecx, ecx
inc ecx
call extfsResourceFree
push eax
.disk_sync:
call writeSuperblock
mov esi, [ebp+PARTITION.Disk]
call disk_sync
.ret:
call ext_unlock
xor ebx, ebx
pop eax
ret
 
.not_empty:
pop eax
.error_stack8:
pop eax
.error_stack4:
pop eax
push ERROR_ACCESS_DENIED
jmp .disk_sync
 
.not_empty_eax:
pop ebx
.error_stack8_eax:
pop ebx
.error_stack4_eax:
pop ebx
.error:
push eax
jmp .disk_sync
 
;----------------------------------------------------------------
ext_CreateFolder:
call extfsWritingInit
push esi
stdcall findInode, [esp+4+4]
pop esi
jnc .success ; exist
call findInode_parent
jc .error
mov eax, esi
xor ebx, ebx
inc ebx
call extfsResourceAlloc
jc .error
inc ebx
push ebx esi edi
xor al, al
lea edi, [ebp+EXTFS.tempInodeBuffer]
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
rep stosb
lea edi, [ebp+EXTFS.tempInodeBuffer]
call fsGetTime
add eax, 978307200
mov [edi+INODE.accessedTime], eax
mov [edi+INODE.dataModified], eax
mov ebx, edi
pop edi esi edx
; edx = allocated inode number, edi -> filename, esi = parent inode number
mov [ebx+INODE.accessMode], DIRECTORY or PERMISSIONS
mov eax, edx
call writeInode
jc .error
; link to self
push edx esi
mov eax, edx
mov ebx, eax
mov dl, DIR_DIRECTORY
mov esi, self_link
call linkInode
pop esi edx
jc .error
; link to parent
push edx esi
mov eax, ebx
mov ebx, esi
mov dl, DIR_DIRECTORY
mov esi, parent_link
call linkInode
pop esi edx
jc .error
; link parent to child
mov eax, esi
mov ebx, edx
mov esi, edi
mov dl, DIR_DIRECTORY
call linkInode
jc .error
mov eax, ebx
dec eax
xor edx, edx
div [ebp+EXTFS.superblock.inodesPerGroup]
mov edx, eax
call extfsReadDescriptor
jc @f
inc [eax+BGDESCR.directoriesCount]
mov eax, edx
call extfsWriteDescriptor
.success:
.error:
push eax
call writeSuperblock
mov esi, [ebp+PARTITION.Disk]
call disk_sync
call ext_unlock
pop eax
ret
 
@@:
movi eax, ERROR_DEVICE
jmp .error
 
self_link db ".", 0
parent_link db "..", 0
 
;----------------------------------------------------------------
ext_CreateFile:
call extfsWritingInit
push ebx esi
stdcall findInode, [esp+8+4]
mov esi, [esp]
jc @f
call ext_unlock
stdcall ext_Delete, [esp+8+4]
mov [esp], eax
call ext_lock
pop eax
test eax, eax
jnz .error
mov esi, [esp]
@@:
call findInode_parent
jc .error
mov eax, esi
xor ebx, ebx
inc ebx
call extfsResourceAlloc
jc .error
inc ebx
push ebx esi edi
xor al, al
lea edi, [ebp+EXTFS.tempInodeBuffer]
movzx ecx, [ebp+EXTFS.superblock.inodeSize]
rep stosb
lea edi, [ebp+EXTFS.tempInodeBuffer]
call fsGetTime
add eax, 978307200
mov [edi+INODE.accessedTime], eax
mov [edi+INODE.dataModified], eax
mov ebx, edi
pop edi esi edx
; edx = allocated inode number, edi -> filename, esi = parent inode number
mov [ebx+INODE.accessMode], FLAG_FILE or PERMISSIONS
mov eax, edx
call writeInode
jc .error
; link parent to child
mov eax, esi
mov ebx, edx
mov esi, edi
mov dl, DIR_FLAG_FILE
call linkInode
jc .error
pop esi ebx
call ext_unlock
jmp ext_WriteFile
 
.error:
push eax
call ext_unlock
pop eax ebx ebx
xor ebx, ebx
ret
 
;----------------------------------------------------------------
ext_WriteFile:
call extfsWritingInit
push 0 ebx
stdcall findInode, [esp+8+4]
jc .error
lea edx, [ebp+EXTFS.mainInodeBuffer]
movi eax, ERROR_ACCESS_DENIED
test [edx+INODE.accessMode], FLAG_FILE
jz .error ; not a file
mov ebx, [esp]
push esi ; inode number
mov eax, esi
mov ecx, [ebx+4]
call extfsExtendFile
jc .error2
mov ecx, [ebx+12]
mov esi, [ebx+16]
mov eax, [edx+INODE.fileSize]
push eax
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
test edx, edx
jz .start_aligned
mov ebx, [ebp+EXTFS.bytesPerBlock]
sub ebx, edx
cmp ebx, ecx
jbe @f
mov ebx, ecx
@@:
push eax
call extfsReadFileBlock
pop edi
jc .error_inode_size
mov eax, edi
push ecx
mov ecx, ebx
mov edi, ebx
add edi, edx
rep movsb
pop ecx
call extfsWriteFileBlock
jc .error_inode_size
add [esp], ebx
sub ecx, ebx
jz .write_inode
.start_aligned:
cmp ecx, [ebp+EXTFS.bytesPerBlock]
jb @f
mov eax, [esp]
xor edx, edx
div [ebp+EXTFS.bytesPerBlock]
mov edx, [esp+4]
push eax
call extfsEraseFileBlock
pop edi
jc .error_inode_size
mov eax, edi
push ecx
mov ecx, [ebp+EXTFS.bytesPerBlock]
mov edi, [ebp+EXTFS.mainBlockBuffer]
rep movsb
pop ecx
call extfsWriteFileBlock
jc .error_inode_size
mov eax, [ebp+EXTFS.bytesPerBlock]
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.bytesPerBlock]
push eax
call extfsReadFileBlock
pop eax
jnc @f
mov edx, [esp+4]
push eax
call extfsEraseFileBlock
pop edi
jc .error_inode_size
mov eax, edi
@@:
push ecx
mov edi, [ebp+EXTFS.mainBlockBuffer]
rep movsb
pop ecx
call extfsWriteFileBlock
jc .error_inode_size
add [esp], ecx
xor ecx, ecx
.error_inode_size:
mov [esp+12], eax
.write_inode:
lea ebx, [ebp+EXTFS.tempInodeBuffer]
pop [ebx+INODE.fileSize]
pop eax
call writeInode
pop ebx
mov ebx, [ebx+12]
sub ebx, ecx
test eax, eax
jz @f
mov [esp], eax
@@:
call writeSuperblock
mov esi, [ebp+PARTITION.Disk]
call disk_sync
@@:
call ext_unlock
pop eax
ret
 
.error2:
pop ebx
.error:
pop ebx ebx
push eax
jmp @b
 
;----------------------------------------------------------------
ext_SetFileEnd:
call extfsWritingInit
pushd [ebx+4]
stdcall findInode, [esp+4+4]
pop ecx
jc @f
lea edx, [ebp+EXTFS.mainInodeBuffer]
movi eax, ERROR_ACCESS_DENIED
cmp [edx+INODE.accessMode], FLAG_FILE
jnz @f ; not a file
mov eax, esi
call extfsExtendFile
jc @f
mov eax, esi
call extfsTruncateFile
jc @f
mov eax, esi
lea ebx, [ebp+EXTFS.tempInodeBuffer]
call writeInode
@@:
push eax
call writeSuperblock
mov esi, [ebp+PARTITION.Disk]
call disk_sync
call ext_unlock
pop eax
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/trunk/fs/fs_common.inc
0,0 → 1,142
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
fsReadCMOS:
out 70h, al
in al, 71h
xor ah, ah
shl ax, 4
shr al, 4
aad
ret
 
fsGetTime:
mov al, 7
call fsReadCMOS
ror eax, 8
mov al, 8
call fsReadCMOS
ror eax, 8
mov al, 9
call fsReadCMOS
add eax, 2000
ror eax, 16
push eax
xor eax, eax
call fsReadCMOS
ror eax, 8
mov al, 2
call fsReadCMOS
ror eax, 8
mov al, 4
call fsReadCMOS
ror eax, 16
push eax
mov esi, esp
add esp, 8
fsCalculateTime:
; in: esi -> data block
; out: eax = seconds since 01.01.2001
movzx eax, word [esi+6]
sub eax, 2001
jnc @f
xor eax, eax
@@:
mov edx, months
mov ebx, eax
inc eax
test eax, 3
jnz @f
add edx, 12
@@:
movzx eax, byte [esi+5]
dec eax
xor ecx, ecx
@@:
dec eax
js @f
add cl, [edx+eax]
adc ch, 0
jmp @b
@@:
mov eax, ebx ; years
mov edx, 365
mul edx
shr ebx, 2
add eax, ebx
add eax, ecx
mov bl, [esi+4]
dec eax
add eax, ebx ; days
mov dl, 24
mul edx
mov bl, [esi+2]
add eax, ebx ; hours
mov ecx, 60
mul ecx
mov bl, [esi+1]
add eax, ebx ; minutes
mul ecx
mov bl, [esi]
add eax, ebx
ret
 
iglobal
months db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
months2 db 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
endg
 
fsTime2bdfe:
; in: eax = seconds since 01.01.2001
; edi -> data block
; out: edi = edi+8
xor edx, edx
mov ecx, 60
div ecx
mov [edi], dl
xor edx, edx
div ecx
mov [edi+1], dl
xor edx, edx
mov cl, 24
div ecx
mov [edi+2], dx
xor edx, edx
mov cx, 365
div ecx
mov ebx, eax
add ebx, 2001
shr eax, 2
sub edx, eax
jns @f
dec ebx
add edx, 365
test ebx, 3
jnz @f
inc edx
@@:
xor eax, eax
mov ecx, months-1
test ebx, 3
jnz @f
add ecx, 12
@@:
inc ecx
inc eax
sub dl, [ecx]
jnc @b
dec dh
jns @b
add dl, [ecx]
inc edx
mov [edi+4], dl
mov [edi+5], al
mov [edi+6], bx
add edi, 8
ret
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Rev
\ No newline at end of property
/kernel/trunk/fs/fs_lfn.inc
1,7 → 1,7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
965,3 → 965,11
jz .ret.ok
mov byte [edi-1], '/'
jmp .set_copy_cont
 
include "parse_fn.inc"
include "fs_common.inc"
include "iso9660.inc" ; read for CD filesystem
include "fat.inc"
include "ntfs.inc"
include "ext.inc"
include "xfs.asm"
/kernel/trunk/fs/ntfs.inc
1,13 → 1,36
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
; NTFS driver
; NTFS external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> NTFS structure
; [esi]+[[esp+4]] = name
; out:
; eax, ebx = return values for sysfunc 70
iglobal
align 4
ntfs_user_functions:
dd ntfs_free
dd (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
dd ntfs_ReadFile
dd ntfs_ReadFolder
dd ntfs_CreateFile
dd ntfs_WriteFile
dd ntfs_SetFileEnd
dd ntfs_GetFileInfo
dd ntfs_SetFileInfo
dd 0
dd ntfs_Delete
dd ntfs_CreateFolder
ntfs_user_functions_end:
endg
 
; Basic concepts:
; File is a FileRecord in the $MFT.
95,7 → 118,7
fileName = 52h
 
struct NTFS PARTITION
Lock MUTEX ? ; Currently operations with one partition
Lock MUTEX ; Currently operations with one partition
; can not be executed in parallel since the legacy code is not ready.
sectors_per_cluster dd ?
mft_cluster dd ? ; location
151,31 → 174,6
bitmap_buf rb 1024
ends
 
; NTFS external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> NTFS structure
; [esi]+[esp+4] = name
; out:
; eax, ebx = return values for sysfunc 70
iglobal
align 4
ntfs_user_functions:
dd ntfs_free
dd (ntfs_user_functions_end - ntfs_user_functions - 4) / 4
dd ntfs_ReadFile
dd ntfs_ReadFolder
dd ntfs_CreateFile
dd ntfs_WriteFile
dd ntfs_SetFileEnd
dd ntfs_GetFileInfo
dd ntfs_SetFileInfo
dd 0
dd ntfs_Delete
dd ntfs_CreateFolder
ntfs_user_functions_end:
endg
 
ntfs_test_bootsec:
; in: ebx -> buffer, edx = size of partition
; out: CF=1 -> invalid
258,7 → 256,14
stc
ret
 
; Mount if it's a valid NTFS partition.
ntfs_create_partition:
; in:
; ebp -> PARTITION structure
; ebx -> boot sector
; ebx+512 -> buffer
; out:
; eax -> NTFS structure, 0 = not NTFS
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .nope
mov edx, dword [ebp+PARTITION.Length]
1684,7 → 1689,7
mov eax, 0x10
stosd
scasd
push edx
push ebx ecx edx
mov eax, dword [ebp+NTFS.bitmap_buf]
mov edx, dword [ebp+NTFS.bitmap_buf+4]
call ntfs_datetime_to_bdfe
1694,7 → 1699,7
mov eax, dword [ebp+NTFS.bitmap_buf+8]
mov edx, dword [ebp+NTFS.bitmap_buf+0xC]
call ntfs_datetime_to_bdfe
pop edx
pop edx ecx ebx
xor eax, eax
stosd
stosd
1778,7 → 1783,7
@@:
stosd
scasd
push edx
push ebx ecx edx
mov eax, [esi+fileCreated]
mov edx, [esi+fileCreated+4]
call ntfs_datetime_to_bdfe
1788,7 → 1793,7
mov eax, [esi+fileModified]
mov edx, [esi+fileModified+4]
call ntfs_datetime_to_bdfe
pop edx
pop edx ecx ebx
mov eax, [esi+fileRealSize]
stosd
mov eax, [esi+fileRealSize+4]
1795,85 → 1800,20
stosd
ret
 
iglobal
months db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
months2 db 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
endg
 
ntfs_datetime_to_bdfe:
; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC
push ebx ecx
mov ebx, eax
mov eax, edx
xor edx, edx
; in: edx:eax = seconds since 01.01.1601 x10000000
; edi -> data block
; out: edi = edi+8
sub eax, 3365781504
sbb edx, 29389701
mov ecx, 10000000
div ecx
xchg eax, ebx
div ecx
.forEXT:
xchg eax, ebx
cmp edx, ecx
jc @f
xor edx, edx
mov ecx, 60
@@:
div ecx
xchg eax, ebx
div ecx
mov [edi], dl
mov edx, ebx
; edx:eax = number of minutes
div ecx
mov [edi+1], dl
; eax = number of hours
xor edx, edx
mov cl, 24
div ecx
mov [edi+2], dx
; eax = number of days since January 1, 1601
xor edx, edx
mov cx, 365
div ecx
mov ebx, eax
add ebx, 1601
shr eax, 2
sub edx, eax
mov cl, 25
div cl
xor ah, ah
add edx, eax
shr eax, 2
sub edx, eax
jns @f
dec ebx
add edx, 365
test bl, 3
jnz @f
inc edx
@@:
xor eax, eax
mov ecx, months-1
test bl, 3
jnz @f
add ecx, 12
@@:
inc ecx
inc eax
sub dl, [ecx]
jnc @b
dec dh
jns @b
add dl, [ecx]
inc edx
mov [edi+4], dl
mov [edi+5], al
mov [edi+6], bx
add edi, 8
pop ecx ebx
ret
jmp fsTime2bdfe
 
.sec:
push ebx ecx
mov ebx, edx
jmp .forEXT
 
;----------------------------------------------------------------
ntfs_GetFileInfo:
call ntfs_lock
4179,90 → 4119,19
call ntfsSpaceClean
jmp ntfsDone
 
ntfsReadCMOS:
out 70h, al
in al, 71h
xor ah, ah
shl ax, 4
shr al, 4
aad
ret
ntfsGetTime:
call fsGetTime
jmp @f
 
ntfsGetTime:
mov al, 7
call ntfsReadCMOS
ror eax, 8
mov al, 8
call ntfsReadCMOS
ror eax, 8
mov al, 9
call ntfsReadCMOS
add eax, 2000
ror eax, 16
push eax
xor eax, eax
call ntfsReadCMOS
ror eax, 8
mov al, 2
call ntfsReadCMOS
ror eax, 8
mov al, 4
call ntfsReadCMOS
ror eax, 16
push eax
mov esi, esp
add esp, 8
ntfsCalculateTime:
; in: esi -> data block
; out: edx:eax = time
movzx eax, word [esi+6]
sub eax, 2001
jnc @f
xor eax, eax
; out: edx:eax = seconds since 01.01.1601 x10000000
call fsCalculateTime
@@:
mov edx, months
mov ebx, eax
inc eax
test eax, 3
jnz @f
add edx, 12
@@:
movzx eax, byte [esi+5]
dec eax
xor ecx, ecx
@@:
dec eax
js @f
add cl, [edx+eax]
adc ch, 0
jmp @b
@@:
mov eax, ebx
mov edx, 365
mov edx, 10000000
mul edx
shr ebx, 2
add eax, ebx
add eax, ecx
mov bl, [esi+4]
add eax, ebx
add eax, 400*365+100-4
mov dl, 24
mul edx
mov bl, [esi+2]
add eax, ebx
mov ecx, 60
mul ecx
mov bl, [esi+1]
add eax, ebx
mul ecx
mov bl, [esi]
add ebx, eax
mov eax, edx
mov ecx, 10000000
mul ecx
xchg eax, ebx
mul ecx
add edx, ebx
add eax, 3365781504
adc edx, 29389701
ret
 
;----------------------------------------------------------------
/kernel/trunk/fs/parse_fn.inc
1,7 → 1,7
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
391,3 → 391,72
.unk:
mov al, '_'
ret
 
utf8_to_cp866:
; in: esi, edi, ecx
; destroys esi, edi, ecx, eax
call utf8to16
js utf8to16.ret
call uni2ansi_char
stosb
jmp utf8_to_cp866
 
utf8to16:
; in:
; esi -> string
; ecx = byte counter
; out:
; SF=1 -> end
; ax = UTF-16 char
; changes esi, ecx
dec ecx
js .ret
lodsb
test al, al
jns .got
shl al, 2
jnc utf8to16
@@:
shl ax, 8
dec ecx
js .ret
lodsb
test al, al
jns .got
shl al, 2
jc @b
shr ah, 2
shl ax, 3
jnc @f
shl eax, 3
dec ecx
js .ret
lodsb
test al, al
jns .got
shl al, 2
jc @b
shr eax, 2
ret
 
@@:
shr ax, 5
ret
 
.got:
xor ah, ah
.ret:
ret
 
strlen:
; in: esi -> source
; out: ecx = length
push edi eax
or ecx, -1
mov edi, esi
xor eax, eax
repnz scasb
inc ecx
not ecx
pop eax edi
ret
/kernel/trunk/fs/xfs.asm
1,29 → 1,46
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Copyright (C) KolibriOS team 2013-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
; XFS external functions
; in:
; ebx -> parameter structure of sysfunc 70
; ebp -> XFS structure
; [esi]+[[esp+4]] = name
; out:
; eax, ebx = return values for sysfunc 70
iglobal
align 4
xfs_user_functions:
dd xfs_free
dd (xfs_user_functions_end - xfs_user_functions - 4) / 4
dd xfs_ReadFile
dd xfs_ReadFolder
dd 0;xfs_CreateFile
dd 0;xfs_WriteFile
dd 0;xfs_SetFileEnd
dd xfs_GetFileInfo
dd 0;xfs_SetFileInfo
dd 0
dd 0;xfs_Delete
dd 0;xfs_CreateFolder
xfs_user_functions_end:
endg
 
include 'xfs.inc'
 
;
; This file contains XFS related code.
; For more information on XFS check sources below.
;
; 1. XFS Filesystem Structure, 2nd Edition, Revision 1. Silicon Graphics Inc. 2006
; 2. Linux source http://kernel.org
;
 
 
; test partition type (valid XFS one?)
; alloc and fill XFS (see xfs.inc) structure
; this function is called for each partition
; returns 0 (not XFS or invalid) / pointer to partition structure
; Mount if it's a valid XFS partition.
xfs_create_partition:
; in:
; ebp -> PARTITION structure
; ebx -> boot sector
; out:
; eax -> XFS structure, 0 = not XFS
push ebx ecx edx esi edi
cmp dword [esi+DISK.MediaInfo.SectorSize], 512
jnz .error
211,25 → 228,6
ret
 
 
iglobal
align 4
xfs_user_functions:
dd xfs_free
dd (xfs_user_functions_end - xfs_user_functions - 4) / 4
dd xfs_Read
dd xfs_ReadFolder
dd 0;xfs_Rewrite
dd 0;xfs_Write
dd 0;xfs_SetFileEnd
dd xfs_GetFileInfo
dd 0;xfs_SetFileInfo
dd 0
dd 0;xfs_Delete
dd 0;xfs_CreateFolder
xfs_user_functions_end:
endg
 
 
; lock partition access mutex
proc xfs_lock
;DEBUGF 1,"xfs_lock\n"
1739,28 → 1737,22
mov eax, [edx + xfs_inode.di_core.di_ctime.t_sec]
bswap eax
push edx
xor edx, edx
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600
adc edx, 2
call ntfs_datetime_to_bdfe.sec
sub eax, 978307200 ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
call fsTime2bdfe
pop edx
 
mov eax, [edx + xfs_inode.di_core.di_atime.t_sec]
bswap eax
push edx
xor edx, edx
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600
adc edx, 2
call ntfs_datetime_to_bdfe.sec
sub eax, 978307200
call fsTime2bdfe
pop edx
 
mov eax, [edx + xfs_inode.di_core.di_mtime.t_sec]
bswap eax
push edx
xor edx, edx
add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600
adc edx, 2
call ntfs_datetime_to_bdfe.sec
sub eax, 978307200
call fsTime2bdfe
pop edx
 
.quit:
1947,18 → 1939,16
 
 
;----------------------------------------------------------------
; xfs_Read - XFS implementation of reading a file
; xfs_ReadFile - XFS implementation of reading a file
; in: ebp = pointer to XFS structure
; in: esi+[esp+4] = name
; in: ebx = pointer to parameters from sysfunc 70
; out: eax, ebx = return values for sysfunc 70
;----------------------------------------------------------------
xfs_Read:
xfs_ReadFile:
push ebx ecx edx esi edi
call xfs_lock
 
add esi, [esp + 24]
;DEBUGF 1,"xfs_Read: %d %d |%s|\n",[ebx+4],[ebx+12],esi
stdcall xfs_get_inode, esi
mov ecx, edx
or ecx, eax
/kernel/trunk/gui/font.inc
141,40 → 141,18
.drawUTF8:
dec dword [esp]
js .done
@@:
movzx ebx, byte [esi]
inc esi
test bl, bl
mov ecx, 256
xor eax, eax
call utf8to16
test ax, ax
jz .done
jns .valid
shl bx, 10
jnc @b
mov bl, [esi]
test bl, bl
jns @b
shl bl, 2
jc @b
shr bh, 2
shr bx, 2
inc esi
cmp bx, 1419
jc .valid
shl bh, 4
jns @f
.tail:
mov bl, [esi]
shl bl, 1
jnc @b
js @b
inc esi
shl bh, 1
js .tail
cmp eax, 1419
jc @f
xor eax, eax
@@:
xor ebx, ebx
.valid:
shl eax, 4
lea ebx, [eax+fontUni]
pushd esi edi 16
shl ebx, 4
add ebx, fontUni
mov esi, [esp+12+fontMultiplier]
call drawChar
imul esi, 8*4
/kernel/trunk/kernel32.inc
1,132 → 1,70
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License. ;;
;; ;;
;; KERNEL32.INC ;;
;; ;;
;; Included 32 bit kernel files for MenuetOS ;;
;; ;;
;; This file is kept separate as it will be easier to ;;
;; maintain and compile with an automated SETUP program ;;
;; in the future. ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
 
; Core functions
include "core/sync.inc" ; macros for synhronization objects
include "core/sys32.inc" ; process management
include "core/sched.inc" ; process scheduling
include "core/syscall.inc" ; system call
include "core/syscall.inc"
include "core/fpu.inc" ; all fpu/sse support
include "core/memory.inc"
include "core/mtrr.inc"
include "core/heap.inc" ; kernel and app heap
include "core/heap.inc"
include "core/malloc.inc" ; small kernel heap
include "core/taskman.inc"
include "core/dll.inc"
include "core/peload.inc" ;
include "core/peload.inc"
include "core/exports.inc"
include "core/string.inc"
include "core/v86.inc" ; virtual-8086 manager
include "core/irq.inc" ; irq handling functions
include "core/apic.inc" ; Interrupt Controller functions
include "core/v86.inc" ; 16-bit mode machine
include "core/irq.inc" ; interrupt handling functions
include "core/apic.inc"
include "core/timers.inc"
include "core/clipboard.inc" ; custom clipboard
include "core/clipboard.inc"
include "core/conf_lib.inc"
include "core/ext_lib.inc" ; load external library
 
; GUI stuff
include "gui/window.inc"
include "gui/event.inc"
include "gui/font.inc"
include "gui/button.inc"
 
include "boot/shutdown.inc" ; kernel shutdown
 
; file system
 
include "blkdev/disk.inc" ; support for plug-n-play disks
include "blkdev/disk_cache.inc" ; caching for plug-n-play disks
include "blkdev/rd.inc" ; ramdisk read /write
include "fs/fat.inc" ; read / write for fat filesystem
include "fs/ntfs.inc" ; read / write for ntfs filesystem
include "fs/fs_lfn.inc" ; syscall, version 2
include "fs/iso9660.inc" ; read for iso9660 filesystem CD
include "fs/ext2/ext2.asm" ; read / write for ext2 filesystem
include "fs/xfs.asm" ; read / write for xfs filesystem
 
; sound
 
include "sound/playnote.inc" ; player Note for Speaker PC
 
; display
 
;include "video/vesa12.inc" ; Vesa 1.2 functions
include "video/vesa20.inc" ; Vesa 2.0 functions
include "video/vesa20.inc"
include "video/blitter.inc"
include "video/vga.inc" ; VGA 16 color functions
include "video/cursors.inc" ; cursors functions
include "video/framebuffer.inc" ; framebuffer functions
include "video/cursors.inc"
include "video/framebuffer.inc"
 
; Network Interface & TCPIP Stack
include "gui/window.inc"
include "gui/event.inc"
include "gui/font.inc"
include "gui/button.inc"
include "gui/mouse.inc" ; cursor
include "gui/skincode.inc" ; windows' skin
 
include "network/stack.inc"
include "hid/keyboard.inc"
include "hid/mousedrv.inc"
include "hid/set_dtc.inc" ; setting date,time,clock and alarm-clock
 
;include "drivers/uart.inc"
include "sound/playnote.inc" ; player Note for PC Speaker
 
 
; Mouse pointer
 
include "gui/mouse.inc"
 
; Window skinning
 
include "gui/skincode.inc"
 
; Pci functions
 
include "bus/pci/pci32.inc"
 
; USB functions
include "bus/usb/init.inc"
 
; Floppy drive controller
 
include "blkdev/flp_drv.inc" ; floppy driver
include "blkdev/fdc.inc"
include "blkdev/flp_drv.inc"
include "blkdev/cd_drv.inc" ; CD driver
include "blkdev/ide_cache.inc" ; CD cache
include "blkdev/hd_drv.inc" ; HDD driver
include "blkdev/bd_drv.inc" ; BIOS disks driver
include "blkdev/rd.inc" ; ramdisk driver
include "blkdev/disk.inc" ; support for plug-n-play disks
include "blkdev/disk_cache.inc" ; caching for plug-n-play disks
 
; IDE cache
include "blkdev/ide_cache.inc"
include "fs/fs_lfn.inc" ; sysfunction 70
 
; HD drive controller
include "blkdev/hd_drv.inc"
; Access through BIOS
include "blkdev/bd_drv.inc"
include "network/stack.inc"
 
; CD drive controller
 
include "blkdev/cd_drv.inc"
 
; Character devices
 
include "hid/keyboard.inc"
include "hid/mousedrv.inc"
 
; setting date,time,clock and alarm-clock
 
include "hid/set_dtc.inc"
 
;% -include
 
;parser file names
include "fs/parse_fn.inc"
 
; work with conf lib
include "core/conf_lib.inc"
 
; load external lib
include "core/ext_lib.inc"
 
; list of external functions
include "imports.inc"
include "imports.inc" ; list of external functions