diff --git a/xfs.asm b/xfs.asm deleted file mode 100644 index 731aba7..0000000 --- a/xfs.asm +++ /dev/null @@ -1,2771 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2013-2016. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License. ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision: 6462 $ - -; 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' - -; 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 - cmp dword[ebx + xfs_sb.sb_magicnum], XFS_SB_MAGIC ; signature - jne .error - - ; TODO: check XFS.versionnum and XFS.features2 - ; print superblock params for debugging (waiting for bug reports) - - movi eax, sizeof.XFS - call malloc - test eax, eax - jz .error - - ; standard partition initialization, common for all file systems - - mov edi, eax - mov eax, dword[ebp + PARTITION.FirstSector] - mov dword[edi + XFS.FirstSector], eax - mov eax, dword[ebp + PARTITION.FirstSector + 4] - mov dword[edi + XFS.FirstSector + 4], eax - mov eax, dword[ebp + PARTITION.Length] - mov dword[edi + XFS.Length], eax - mov eax, dword[ebp + PARTITION.Length + 4] - mov dword[edi + XFS.Length + 4], eax - mov eax, [ebp + PARTITION.Disk] - mov [edi + XFS.Disk], eax - mov [edi + XFS.FSUserFunctions], xfs_user_functions - - ; here we initialize only one mutex so far (for the entire partition) - ; XFS potentially allows parallel r/w access to several AGs, keep it in mind for SMP times - - lea ecx, [edi + XFS.Lock] - call mutex_init - - ; read superblock and fill just allocated XFS partition structure - - mov eax, [ebx + xfs_sb.sb_blocksize] - bswap eax ; XFS is big endian - mov [edi + XFS.blocksize], eax - movzx eax, word[ebx + xfs_sb.sb_sectsize] - xchg al, ah - mov [edi + XFS.sectsize], eax - movzx eax, word[ebx + xfs_sb.sb_versionnum] - xchg al, ah - mov [edi + XFS.versionnum], eax - mov eax, [ebx + xfs_sb.sb_features2] - bswap eax - mov [edi + XFS.features2], eax - movzx eax, word[ebx + xfs_sb.sb_inodesize] - xchg al, ah - mov [edi + XFS.inodesize], eax - movzx eax, word[ebx + xfs_sb.sb_inopblock] ; inodes per block - xchg al, ah - mov [edi + XFS.inopblock], eax - movzx eax, byte[ebx + xfs_sb.sb_blocklog] ; log2 of block size, in bytes - mov [edi + XFS.blocklog], eax - movzx eax, byte[ebx + xfs_sb.sb_sectlog] - mov [edi + XFS.sectlog], eax - movzx eax, byte[ebx + xfs_sb.sb_inodelog] - mov [edi + XFS.inodelog], eax - movzx eax, byte[ebx + xfs_sb.sb_inopblog] - mov [edi + XFS.inopblog], eax - movzx eax, byte[ebx + xfs_sb.sb_dirblklog] - mov [edi + XFS.dirblklog], eax - mov eax, dword[ebx + xfs_sb.sb_rootino + 4] ; - bswap eax ; big - mov dword[edi + XFS.rootino + 0], eax ; endian - mov eax, dword[ebx + xfs_sb.sb_rootino + 0] ; 64bit - bswap eax ; number - mov dword[edi + XFS.rootino + 4], eax ; - - mov eax, [edi + XFS.blocksize] - mov ecx, [edi + XFS.dirblklog] - shl eax, cl - mov [edi + XFS.dirblocksize], eax ; blocks for files, dirblocks for directories - - ; sector is always smaller than block - ; so precalculate shift order to allow faster sector_num->block_num conversion - - mov ecx, [edi + XFS.blocklog] - sub ecx, [edi + XFS.sectlog] - mov [edi + XFS.blockmsectlog], ecx - - mov eax, 1 - shl eax, cl - mov [edi + XFS.sectpblock], eax - - ; shift order for inode_num->block_num conversion - - mov eax, [edi + XFS.blocklog] - sub eax, [edi + XFS.inodelog] - mov [edi + XFS.inodetoblocklog], eax - - mov eax, [ebx + xfs_sb.sb_agblocks] - bswap eax - mov [edi + XFS.agblocks], eax - movzx ecx, byte[ebx + xfs_sb.sb_agblklog] - mov [edi + XFS.agblklog], ecx - - ; get the mask for block numbers - ; block numbers are AG relative! - ; bitfield length may vary between partitions - - mov eax, 1 - shl eax, cl - dec eax - mov dword[edi + XFS.agblockmask + 0], eax - mov eax, 1 - sub ecx, 32 - jc @f - shl eax, cl - @@: - dec eax - mov dword[edi + XFS.agblockmask + 4], eax - - ; calculate magic offsets for directories - - mov ecx, [edi + XFS.blocklog] - mov eax, XFS_DIR2_LEAF_OFFSET AND 0xffffffff ; lo - mov edx, XFS_DIR2_LEAF_OFFSET SHR 32 ; hi - shrd eax, edx, cl - mov [edi + XFS.dir2_leaf_offset_blocks], eax - - mov ecx, [edi + XFS.blocklog] - mov eax, XFS_DIR2_FREE_OFFSET AND 0xffffffff ; lo - mov edx, XFS_DIR2_FREE_OFFSET SHR 32 ; hi - shrd eax, edx, cl - mov [edi + XFS.dir2_free_offset_blocks], eax - -; mov ecx, [edi + XFS.dirblklog] -; mov eax, [edi + XFS.blocksize] -; shl eax, cl -; mov [edi + XFS.dirblocksize], eax - - mov eax, [edi + XFS.blocksize] - call malloc - test eax, eax - jz .error - mov [edi + XFS.cur_block], eax - - ; we do need XFS.blocksize bytes for single inode - ; minimal file system structure is block, inodes are packed in blocks - - mov eax, [edi + XFS.blocksize] - call malloc - test eax, eax - jz .error - mov [edi + XFS.cur_inode], eax - - ; temporary inode - ; used for browsing directories - - mov eax, [edi + XFS.blocksize] - call malloc - test eax, eax - jz .error - mov [edi + XFS.tmp_inode], eax - - ; current sector - ; only for sector size structures like AGI - ; inodes has usually the same size, but never store them here - - mov eax, [edi + XFS.sectsize] - call malloc - test eax, eax - jz .error - mov [edi + XFS.cur_sect], eax - - ; current directory block - - mov eax, [edi + XFS.dirblocksize] - call malloc - test eax, eax - jz .error - mov [edi + XFS.cur_dirblock], eax - - .quit: - mov eax, edi ; return pointer to allocated XFS partition structure - pop edi esi edx ecx ebx - ret - .error: - xor eax, eax - pop edi esi edx ecx ebx - ret - - -; lock partition access mutex -proc xfs_lock -;DEBUGF 1,"xfs_lock\n" - lea ecx, [ebp + XFS.Lock] - jmp mutex_lock -endp - - -; unlock partition access mutex -proc xfs_unlock -;DEBUGF 1,"xfs_unlock\n" - lea ecx, [ebp + XFS.Lock] - jmp mutex_unlock -endp - - -; free all the allocated memory -; called on partition destroy -proc xfs_free - push ebp - xchg ebp, eax - stdcall kernel_free, [ebp + XFS.cur_block] - stdcall kernel_free, [ebp + XFS.cur_inode] - stdcall kernel_free, [ebp + XFS.cur_sect] - stdcall kernel_free, [ebp + XFS.cur_dirblock] - stdcall kernel_free, [ebp + XFS.tmp_inode] - xchg ebp, eax - call free - pop ebp - ret -endp - - -;--------------------------------------------------------------- -; block number (AG relative) -; eax -- inode_lo -; edx -- inode_hi -; ebx -- buffer -;--------------------------------------------------------------- -xfs_read_block: - push ebx esi - - push edx - push eax - - ; XFS block numbers are AG relative - ; they come in bitfield form of concatenated AG and block numbers - ; to get absolute block number for fs_read32_sys we should - ; 1. extract AG number (using precalculated mask) - ; 2. multiply it by the AG size in blocks - ; 3. add AG relative block number - - ; 1. - mov ecx, [ebp + XFS.agblklog] - shrd eax, edx, cl - shr edx, cl - ; 2. - mul dword[ebp + XFS.agblocks] - pop ecx - pop esi - and ecx, dword[ebp + XFS.agblockmask + 0] - and esi, dword[ebp + XFS.agblockmask + 4] - ; 3. - add eax, ecx - adc edx, esi - -;DEBUGF 1,"read block: 0x%x%x\n",edx,eax - ; there is no way to read file system block at once, therefore we - ; 1. calculate the number of sectors first - ; 2. and then read them in series - - ; 1. - mov ecx, [ebp + XFS.blockmsectlog] - shld edx, eax, cl - shl eax, cl - mov esi, [ebp + XFS.sectpblock] - - ; 2. - .next_sector: - push eax edx - call fs_read32_sys - mov ecx, eax - pop edx eax - test ecx, ecx - jnz .error - add eax, 1 ; be ready to fs_read64_sys - adc edx, 0 - add ebx, [ebp + XFS.sectsize] ; update buffer offset - dec esi - jnz .next_sector - - .quit: - xor eax, eax - pop esi ebx - ret - .error: - mov eax, ecx - pop esi ebx - ret - - -;--------------------------------------------------------------- -; push buffer -; push startblock_hi -; push startblock_lo -; call xfs_read_dirblock -; test eax, eax -;--------------------------------------------------------------- -xfs_read_dirblock: -;mov eax, [esp + 4] -;mov edx, [esp + 8] -;DEBUGF 1,"read dirblock at: %d %d\n",edx,eax -;DEBUGF 1,"dirblklog: %d\n",[ebp + XFS.dirblklog] - push ebx esi - - mov eax, [esp + 12] ; startblock_lo - mov edx, [esp + 16] ; startblock_hi - mov ebx, [esp + 20] ; buffer - - ; dirblock >= block - ; read dirblocks by blocks - - mov ecx, [ebp + XFS.dirblklog] - mov esi, 1 - shl esi, cl - .next_block: - push eax edx - call xfs_read_block - mov ecx, eax - pop edx eax - test ecx, ecx - jnz .error - add eax, 1 ; be ready to fs_read64_sys - adc edx, 0 - add ebx, [ebp + XFS.blocksize] - dec esi - jnz .next_block - - .quit: - xor eax, eax - pop esi ebx - ret 12 - .error: - mov eax, ecx - pop esi ebx - ret 12 - - -;--------------------------------------------------------------- -; push buffer -; push inode_hi -; push inode_lo -; call xfs_read_inode -; test eax, eax -;--------------------------------------------------------------- -xfs_read_inode: -;DEBUGF 1,"reading inode: 0x%x%x\n",[esp+8],[esp+4] - push ebx - mov eax, [esp + 8] ; inode_lo - mov edx, [esp + 12] ; inode_hi - mov ebx, [esp + 16] ; buffer - - ; inodes are packed into blocks - ; 1. calculate block number - ; 2. read the block - ; 3. add inode offset to block base address - - ; 1. - mov ecx, [ebp + XFS.inodetoblocklog] - shrd eax, edx, cl - shr edx, cl - ; 2. - call xfs_read_block - test eax, eax - jnz .error - - ; note that inode numbers should be first extracted from bitfields using mask - - mov eax, [esp + 8] - mov edx, 1 - mov ecx, [ebp + XFS.inopblog] - shl edx, cl - dec edx ; get inode number mask - and eax, edx ; apply mask - mov ecx, [ebp + XFS.inodelog] - shl eax, cl - add ebx, eax - - cmp word[ebx], XFS_DINODE_MAGIC ; test signature - jne .error - .quit: - xor eax, eax - mov edx, ebx - pop ebx - ret 12 - .error: - movi eax, ERROR_FS_FAIL - mov edx, ebx - pop ebx - ret 12 - - -;---------------------------------------------------------------- -; push encoding ; ASCII / UNICODE -; push src ; inode -; push dst ; bdfe -; push entries_to_read -; push start_number ; from 0 -;---------------------------------------------------------------- -xfs_dir_get_bdfes: -DEBUGF 1,"xfs_dir_get_bdfes: %d entries from %d\n",[esp+8],[esp+4] - sub esp, 4 ; local vars - push ecx edx esi edi - - mov ebx, [esp + 36] ; src - mov edx, [esp + 32] ; dst - mov ecx, [esp + 24] ; start_number - - ; define directory ondisk format and jump to corresponding label - - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_LOCAL - jne .not_shortdir - jmp .shortdir - .not_shortdir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS - jne .not_blockdir - mov eax, [ebx + xfs_inode.di_core.di_nextents] - bswap eax - cmp eax, 1 - jne .not_blockdir - jmp .blockdir - .not_blockdir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS - jne .not_leafdir - mov eax, [ebx + xfs_inode.di_core.di_nextents] - bswap eax - cmp eax, 4 - ja .not_leafdir - jmp .leafdir - .not_leafdir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS - jne .not_nodedir - jmp .nodedir - .not_nodedir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE - jne .not_btreedir - jmp .btreedir - .not_btreedir: - movi eax, ERROR_FS_FAIL - jmp .error - - ; short form directory (all the data fits into inode) - .shortdir: -;DEBUGF 1,"shortdir\n", - movzx eax, word[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count] - test al, al ; is count zero? - jnz @f ; if not, use it (i8count must be zero then) - shr eax, 8 ; use i8count - @@: - add eax, 1 ; '..' and '.' are implicit - mov dword[edx + 0], 1 ; version - mov [edx + 8], eax ; total entries - sub eax, [esp + 24] ; start number - cmp eax, [esp + 28] ; entries to read - jbe @f - mov eax, [esp + 28] - @@: - mov [esp + 28], eax - mov [edx + 4], eax ; number of actually read entries - mov [ebp + XFS.entries_read], eax - - ; inode numbers are often saved as 4 bytes (iff they fit) - ; compute the length of inode numbers - - mov eax, 4 ; 4 by default - cmp byte[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.i8count], 0 - je @f - add eax, eax ; 4+4=8, iff i8count != 0 - @@: - mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; - add edx, 32 - lea esi, [ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent + eax] - dec ecx - js .shortdir.fill - - ; skip some entries if the first entry to read is not 0 - - .shortdir.skip: - test ecx, ecx - jz .shortdir.skipped - movzx edi, byte[esi + xfs_dir2_sf_entry.namelen] - lea esi, [esi + xfs_dir2_sf_entry.name + edi] - add esi, eax - dec ecx - jnz .shortdir.skip - mov ecx, [esp + 28] ; entries to read - jmp .shortdir.skipped - .shortdir.fill: - mov ecx, [esp + 28] ; total number - test ecx, ecx - jz .quit - push ecx -;DEBUGF 1,"ecx: %d\n",ecx - lea edi, [edx + 40] ; get file name offset -;DEBUGF 1,"filename: ..\n" - mov dword[edi], '..' - mov edi, edx - push eax ebx edx esi - stdcall xfs_get_inode_number_sf, dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count], dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent + 4], dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent] - stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode] -; test eax, eax -; jnz .error - stdcall xfs_get_inode_info, edx, edi - test eax, eax - pop esi edx ebx eax - jnz .error - mov ecx, [esp + 44] ; file name encding - mov [edx + 4], ecx - add edx, 304 ; ASCII only for now - pop ecx - dec ecx - jz .quit - -; push ecx -; lea edi, [edx + 40] -;DEBUGF 1,"filename: .\n" -; mov dword[edi], '.' -; mov edi, edx -; push eax edx -; stdcall xfs_get_inode_info, [ebp + XFS.cur_inode], edi -; test eax, eax -; pop edx eax -; jnz .error -; mov ecx, [esp + 44] -; mov [edx + 4], ecx -; add edx, 304 ; ASCII only for now -; pop ecx -; dec ecx -; jz .quit - - ; we skipped some entries - ; now we fill min(required, present) number of bdfe's - - .shortdir.skipped: -;DEBUGF 1,"ecx: %d\n",ecx - push ecx - movzx ecx, byte[esi + xfs_dir2_sf_entry.namelen] - add esi, xfs_dir2_sf_entry.name - lea edi, [edx + 40] ; bdfe offset of file name -;DEBUGF 1,"filename: |%s|\n",esi - rep movsb - mov word[edi], 0 ; terminator (ASCIIZ) - - push eax ebx ecx edx esi -; push edx ; for xfs_get_inode_info - mov edi, edx - stdcall xfs_get_inode_number_sf, dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count], [esi + 4], [esi] - stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode] -; test eax, eax -; jnz .error - stdcall xfs_get_inode_info, edx, edi - test eax, eax - pop esi edx ecx ebx eax - jnz .error - mov ecx, [esp + 44] ; file name encoding - mov [edx + 4], ecx - - add edx, 304 ; ASCII only for now - add esi, eax - pop ecx - dec ecx - jnz .shortdir.skipped - jmp .quit - - .blockdir: -;DEBUGF 1,"blockdir\n" - push edx - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - stdcall xfs_extent_unpack, eax -;DEBUGF 1,"extent.br_startoff : 0x%x%x\n",[ebp+XFS.extent.br_startoff+4],[ebp+XFS.extent.br_startoff+0] -;DEBUGF 1,"extent.br_startblock: 0x%x%x\n",[ebp+XFS.extent.br_startblock+4],[ebp+XFS.extent.br_startblock+0] -;DEBUGF 1,"extent.br_blockcount: %d\n",[ebp+XFS.extent.br_blockcount] -;DEBUGF 1,"extent.br_state : %d\n",[ebp+XFS.extent.br_state] - stdcall xfs_read_dirblock, dword[ebp + XFS.extent.br_startblock + 0], dword[ebp + XFS.extent.br_startblock + 4], [ebp + XFS.cur_dirblock] - test eax, eax - pop edx - jnz .error -;DEBUGF 1,"dirblock signature: %s\n",[ebp+XFS.cur_dirblock] - mov ebx, [ebp + XFS.cur_dirblock] - mov dword[edx + 0], 1 ; version - mov eax, [ebp + XFS.dirblocksize] - mov ecx, [ebx + eax - sizeof.xfs_dir2_block_tail + xfs_dir2_block_tail.stale] - mov eax, [ebx + eax - sizeof.xfs_dir2_block_tail + xfs_dir2_block_tail.count] - bswap ecx - bswap eax - sub eax, ecx ; actual number of entries = count - stale - mov [edx + 8], eax ; total entries -;DEBUGF 1,"total entries: %d\n",eax - sub eax, [esp + 24] ; start number - cmp eax, [esp + 28] ; entries to read - jbe @f - mov eax, [esp + 28] - @@: - mov [esp + 28], eax - mov [edx + 4], eax ; number of actually read entries - mov [ebp + XFS.entries_read], eax -;DEBUGF 1,"actually read entries: %d\n",eax - mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; - add ebx, xfs_dir2_block.u - - mov ecx, [esp + 24] ; start entry number - ; also means how many to skip - test ecx, ecx - jz .blockdir.skipped - .blockdir.skip: - cmp word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG - jne @f - movzx eax, word[ebx + xfs_dir2_data_union.unused.length] - xchg al, ah - add ebx, eax - jmp .blockdir.skip - @@: - movzx eax, [ebx + xfs_dir2_data_union.xentry.namelen] - lea ebx, [ebx + xfs_dir2_data_union.xentry.name + eax + 2] ; 2 bytes for 'tag' - add ebx, 7 ; align on 8 bytes - and ebx, not 7 - dec ecx - jnz .blockdir.skip - .blockdir.skipped: - mov ecx, [edx + 4] ; actually read entries - test ecx, ecx - jz .quit - add edx, 32 ; set edx to the first bdfe - .blockdir.next_entry: - cmp word[ebx + xfs_dir2_data_union.unused.freetag], XFS_NULL - jne @f - movzx eax, word[ebx + xfs_dir2_data_union.unused.length] - xchg al, ah - add ebx, eax - jmp .blockdir.next_entry - @@: - push ecx - push eax ebx ecx edx esi - mov edi, edx - mov edx, dword[ebx + xfs_dir2_data_union.xentry.inumber + 0] - mov eax, dword[ebx + xfs_dir2_data_union.xentry.inumber + 4] - bswap edx - bswap eax - stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode] - stdcall xfs_get_inode_info, edx, edi - test eax, eax - pop esi edx ecx ebx eax - jnz .error - mov ecx, [esp + 44] - mov [edx + 4], ecx - lea edi, [edx + 40] - movzx ecx, byte[ebx + xfs_dir2_data_union.xentry.namelen] - lea esi, [ebx + xfs_dir2_data_union.xentry.name] -;DEBUGF 1,"filename: |%s|\n",esi - rep movsb -; call utf8_to_cp866 - mov word[edi], 0 ; terminator - lea ebx, [esi + 2] ; skip 'tag' - add ebx, 7 ; xfs_dir2_data_entries are aligned to 8 bytes - and ebx, not 7 - add edx, 304 - pop ecx - dec ecx - jnz .blockdir.next_entry - jmp .quit - - .leafdir: -;DEBUGF 1,"readdir: leaf\n" - mov [ebp + XFS.cur_inode_save], ebx - push ebx ecx edx - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_extent_list_read_dirblock, eax, [ebp + XFS.dir2_leaf_offset_blocks], 0, edx, 0xffffffff, 0xffffffff - mov ecx, eax - and ecx, edx - inc ecx - pop edx ecx ebx - jz .error - - mov eax, [ebp + XFS.cur_dirblock] - movzx ecx, word[eax + xfs_dir2_leaf.hdr.stale] - movzx eax, word[eax + xfs_dir2_leaf.hdr.count] - xchg cl, ch - xchg al, ah - sub eax, ecx -;DEBUGF 1,"total count: %d\n",eax - - mov dword[edx + 0], 1 ; version - mov [edx + 8], eax ; total entries - sub eax, [esp + 24] ; start number - cmp eax, [esp + 28] ; entries to read - jbe @f - mov eax, [esp + 28] - @@: - mov [esp + 28], eax - mov [edx + 4], eax ; number of actually read entries - - mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; - - mov eax, [ebp + XFS.cur_dirblock] - add eax, [ebp + XFS.dirblocksize] - mov [ebp + XFS.max_dirblockaddr], eax - mov dword[ebp + XFS.next_block_num + 0], 0 - mov dword[ebp + XFS.next_block_num + 4], 0 - - mov ebx, [ebp + XFS.max_dirblockaddr] ; to read dirblock immediately - mov ecx, [esp + 24] ; start number - test ecx, ecx - jz .leafdir.skipped - .leafdir.skip: - cmp ebx, [ebp + XFS.max_dirblockaddr] - jne @f - push ecx edx - mov ebx, [ebp + XFS.cur_inode_save] - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0 - mov ecx, eax - and ecx, edx - inc ecx - jz .error - add eax, 1 - adc edx, 0 - mov dword[ebp + XFS.next_block_num + 0], eax - mov dword[ebp + XFS.next_block_num + 4], edx - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, sizeof.xfs_dir2_data_hdr - pop edx ecx - @@: - cmp word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG - jne @f - movzx eax, word[ebx + xfs_dir2_data_union.unused.length] - xchg al, ah - add ebx, eax - jmp .leafdir.skip - @@: - movzx eax, [ebx + xfs_dir2_data_union.xentry.namelen] - lea ebx, [ebx + xfs_dir2_data_union.xentry.name + eax + 2] ; 2 for 'tag' - add ebx, 7 - and ebx, not 7 - dec ecx - jnz .leafdir.skip - .leafdir.skipped: - mov [ebp + XFS.entries_read], 0 - mov ecx, [edx + 4] ; actually read entries - test ecx, ecx - jz .quit - add edx, 32 ; first bdfe entry - .leafdir.next_entry: -;DEBUGF 1,"next_extry\n" - cmp ebx, [ebp + XFS.max_dirblockaddr] - jne .leafdir.process_current_block - push ecx edx - mov ebx, [ebp + XFS.cur_inode_save] - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0 -;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax - mov ecx, eax - and ecx, edx - inc ecx - jnz @f - pop edx ecx - jmp .quit - @@: - add eax, 1 - adc edx, 0 - mov dword[ebp + XFS.next_block_num + 0], eax - mov dword[ebp + XFS.next_block_num + 4], edx - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, sizeof.xfs_dir2_data_hdr - pop edx ecx - .leafdir.process_current_block: - cmp word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG - jne @f - movzx eax, word[ebx + xfs_dir2_data_union.unused.length] - xchg al, ah - add ebx, eax - jmp .leafdir.next_entry - @@: - push eax ebx ecx edx esi - mov edi, edx - mov edx, dword[ebx + xfs_dir2_data_union.xentry.inumber + 0] - mov eax, dword[ebx + xfs_dir2_data_union.xentry.inumber + 4] - bswap edx - bswap eax - stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode] - stdcall xfs_get_inode_info, edx, edi - test eax, eax - pop esi edx ecx ebx eax - jnz .error - push ecx - mov ecx, [esp + 44] - mov [edx + 4], ecx - lea edi, [edx + 40] - movzx ecx, byte[ebx + xfs_dir2_data_union.xentry.namelen] - lea esi, [ebx + xfs_dir2_data_union.xentry.name] -;DEBUGF 1,"filename: |%s|\n",esi - rep movsb - pop ecx - mov word[edi], 0 - lea ebx, [esi + 2] ; skip 'tag' - add ebx, 7 ; xfs_dir2_data_entries are aligned to 8 bytes - and ebx, not 7 - add edx, 304 ; ASCII only for now - inc [ebp + XFS.entries_read] - dec ecx - jnz .leafdir.next_entry - jmp .quit - - .nodedir: -;DEBUGF 1,"readdir: node\n" - push edx - mov [ebp + XFS.cur_inode_save], ebx - mov [ebp + XFS.entries_read], 0 - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_dir2_node_get_numfiles, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks] - pop edx - test eax, eax - jnz .error - mov eax, [ebp + XFS.entries_read] - mov [ebp + XFS.entries_read], 0 -;DEBUGF 1,"numfiles: %d\n",eax - mov dword[edx + 0], 1 ; version - mov [edx + 8], eax ; total entries - sub eax, [esp + 24] ; start number - cmp eax, [esp + 28] ; entries to read - jbe @f - mov eax, [esp + 28] - @@: - mov [esp + 28], eax - mov [edx + 4], eax ; number of actually read entries - - mov dword[edx + 12], 0 ; reserved - mov dword[edx + 16], 0 ; - mov dword[edx + 20], 0 ; - mov dword[edx + 24], 0 ; - mov dword[edx + 28], 0 ; - - mov eax, [ebp + XFS.cur_dirblock] - add eax, [ebp + XFS.dirblocksize] - mov [ebp + XFS.max_dirblockaddr], eax - mov dword[ebp + XFS.next_block_num + 0], 0 - mov dword[ebp + XFS.next_block_num + 4], 0 - - mov ebx, [ebp + XFS.max_dirblockaddr] ; to read dirblock immediately - mov ecx, [esp + 24] ; start number - test ecx, ecx - jz .leafdir.skipped - jmp .leafdir.skip - - .btreedir: -;DEBUGF 1,"readdir: btree\n" - mov [ebp + XFS.cur_inode_save], ebx - push ebx edx - mov eax, [ebx + xfs_inode.di_core.di_nextents] - bswap eax - mov [ebp + XFS.ro_nextents], eax - mov eax, [ebp + XFS.inodesize] - sub eax, xfs_inode.di_u - sub eax, sizeof.xfs_bmdr_block - shr eax, 4 -;DEBUGF 1,"maxnumresc: %d\n",eax - mov edx, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 0] - mov eax, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 4] - bswap eax - bswap edx - mov ebx, [ebp + XFS.cur_block] -;DEBUGF 1,"read_block: %x %x ",edx,eax - stdcall xfs_read_block - pop edx ebx - test eax, eax - jnz .error -;DEBUGF 1,"ok\n" - - mov ebx, [ebp + XFS.cur_block] - push edx - mov [ebp + XFS.entries_read], 0 - lea eax, [ebx + sizeof.xfs_bmbt_block] - mov edx, [ebp + XFS.ro_nextents] - stdcall xfs_dir2_node_get_numfiles, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks] - pop edx - test eax, eax - jnz .error - mov eax, [ebp + XFS.entries_read] - mov [ebp + XFS.entries_read], 0 -;DEBUGF 1,"numfiles: %d\n",eax - - mov dword[edx + 0], 1 ; version - mov [edx + 8], eax ; total entries - sub eax, [esp + 24] ; start number - cmp eax, [esp + 28] ; entries to read - jbe @f - mov eax, [esp + 28] - @@: - mov [esp + 28], eax - mov [edx + 4], eax ; number of actually read entries - - mov dword[edx + 12], 0 - mov dword[edx + 16], 0 - mov dword[edx + 20], 0 - mov dword[edx + 24], 0 - mov dword[edx + 28], 0 - - mov eax, [ebp + XFS.cur_dirblock] ; fsblock? - add eax, [ebp + XFS.dirblocksize] - mov [ebp + XFS.max_dirblockaddr], eax - mov dword[ebp + XFS.next_block_num + 0], 0 - mov dword[ebp + XFS.next_block_num + 4], 0 - - mov ebx, [ebp + XFS.max_dirblockaddr] ; to read dirblock immediately - mov ecx, [esp + 24] ; start number - test ecx, ecx - jz .btreedir.skipped -; jmp .btreedir.skip - .btreedir.skip: - cmp ebx, [ebp + XFS.max_dirblockaddr] - jne @f - push ecx edx - mov ebx, [ebp + XFS.cur_block] - lea eax, [ebx + sizeof.xfs_bmbt_block] - mov edx, [ebp + XFS.ro_nextents] - stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0 -;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax - mov ecx, eax - and ecx, edx - inc ecx - jz .error - add eax, 1 - adc edx, 0 - mov dword[ebp + XFS.next_block_num + 0], eax - mov dword[ebp + XFS.next_block_num + 4], edx - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, sizeof.xfs_dir2_data_hdr - pop edx ecx - @@: - cmp word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG - jne @f - movzx eax, word[ebx + xfs_dir2_data_union.unused.length] - xchg al, ah - add ebx, eax - jmp .btreedir.skip - @@: - movzx eax, [ebx + xfs_dir2_data_union.xentry.namelen] - lea ebx, [ebx + xfs_dir2_data_union.xentry.name + eax + 2] ; 2 for 'tag' - add ebx, 7 - and ebx, not 7 - dec ecx - jnz .btreedir.skip - .btreedir.skipped: - mov [ebp + XFS.entries_read], 0 - mov ecx, [edx + 4] ; actually read entries - test ecx, ecx - jz .quit - add edx, 32 - .btreedir.next_entry: -;mov eax, [ebp + XFS.entries_read] -;DEBUGF 1,"next_extry: %d\n",eax - cmp ebx, [ebp + XFS.max_dirblockaddr] - jne .btreedir.process_current_block - push ecx edx - mov ebx, [ebp + XFS.cur_block] - lea eax, [ebx + sizeof.xfs_bmbt_block] - mov edx, [ebp + XFS.ro_nextents] - stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0 -;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax - mov ecx, eax - and ecx, edx - inc ecx - jnz @f - pop edx ecx - jmp .quit - @@: - add eax, 1 - adc edx, 0 - mov dword[ebp + XFS.next_block_num + 0], eax - mov dword[ebp + XFS.next_block_num + 4], edx - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, sizeof.xfs_dir2_data_hdr - pop edx ecx - .btreedir.process_current_block: - cmp word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG - jne @f - movzx eax, word[ebx + xfs_dir2_data_union.unused.length] - xchg al, ah - add ebx, eax - jmp .btreedir.next_entry - @@: - push eax ebx ecx edx esi - mov edi, edx - mov edx, dword[ebx + xfs_dir2_data_union.xentry.inumber + 0] - mov eax, dword[ebx + xfs_dir2_data_union.xentry.inumber + 4] - bswap edx - bswap eax - stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode] - stdcall xfs_get_inode_info, edx, edi - test eax, eax - pop esi edx ecx ebx eax - jnz .error - push ecx - mov ecx, [esp + 44] - mov [edx + 4], ecx - lea edi, [edx + 40] - movzx ecx, byte[ebx + xfs_dir2_data_union.xentry.namelen] - lea esi, [ebx + xfs_dir2_data_union.xentry.name] -;DEBUGF 1,"filename: |%s|\n",esi - rep movsb - pop ecx - mov word[edi], 0 - lea ebx, [esi + 2] ; skip 'tag' - add ebx, 7 ; xfs_dir2_data_entries are aligned to 8 bytes - and ebx, not 7 - add edx, 304 - inc [ebp + XFS.entries_read] - dec ecx - jnz .btreedir.next_entry - jmp .quit - - - .quit: - pop edi esi edx ecx - add esp, 4 ; pop vars - xor eax, eax -; mov ebx, [esp + 8] - mov ebx, [ebp + XFS.entries_read] -DEBUGF 1,"xfs_dir_get_bdfes done: %d\n",ebx - ret 20 - .error: - pop edi esi edx ecx - add esp, 4 ; pop vars - mov eax, ERROR_FS_FAIL - movi ebx, -1 - ret 20 - - -;---------------------------------------------------------------- -; push inode_hi -; push inode_lo -; push name -;---------------------------------------------------------------- -xfs_get_inode_short: - ; this function searches for the file in _current_ dir - ; it is called recursively for all the subdirs /path/to/my/file - -;DEBUGF 1,"xfs_get_inode_short: %s\n",[esp+4] - mov esi, [esp + 4] ; name - movzx eax, word[esi] - cmp eax, '.' ; current dir; it is already read, just return - je .quit - cmp eax, './' ; same thing - je .quit - - ; read inode - - mov eax, [esp + 8] ; inode_lo - mov edx, [esp + 12] ; inode_hi - stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode] - test eax, eax - movi eax, ERROR_FS_FAIL - jnz .error - - ; find file name in directory - ; switch directory ondisk format - - mov ebx, edx - mov [ebp + XFS.cur_inode_save], ebx - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_LOCAL - jne .not_shortdir -;DEBUGF 1,"dir: shortdir\n" - jmp .shortdir - .not_shortdir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS - jne .not_blockdir - mov eax, [ebx + xfs_inode.di_core.di_nextents] - bswap eax - cmp eax, 1 - jne .not_blockdir - jmp .blockdir - .not_blockdir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS - jne .not_leafdir - mov eax, [ebx + xfs_inode.di_core.di_nextents] - bswap eax - cmp eax, 4 - ja .not_leafdir - jmp .leafdir - .not_leafdir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS - jne .not_nodedir - jmp .nodedir - .not_nodedir: - cmp byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE - jne .not_btreedir - jmp .btreedir - .not_btreedir: -DEBUGF 1,"NOT IMPLEMENTED: DIR FORMAT\n" - jmp .error - - .shortdir: - .shortdir.check_parent: - ; parent inode number in shortform directories is always implicit, check this case - mov eax, [esi] - and eax, 0x00ffffff - cmp eax, '..' - je .shortdir.parent2 - cmp eax, '../' - je .shortdir.parent3 - jmp .shortdir.common - .shortdir.parent3: - inc esi - .shortdir.parent2: - add esi, 2 - add ebx, xfs_inode.di_u - stdcall xfs_get_inode_number_sf, dword[ebx + xfs_dir2_sf_hdr.count], dword[ebx + xfs_dir2_sf_hdr.parent + 4], dword[ebx + xfs_dir2_sf_hdr.parent] -;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax - jmp .quit - - ; not a parent inode? - ; search in the list, all the other files are stored uniformly - - .shortdir.common: - mov eax, 4 - movzx edx, word[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count] ; read count (byte) and i8count (byte) at once - test dl, dl ; is count zero? - jnz @f - shr edx, 8 ; use i8count - add eax, eax ; inode_num size - @@: - lea edi, [ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent + eax] - - .next_name: - movzx ecx, byte[edi + xfs_dir2_sf_entry.namelen] - add edi, xfs_dir2_sf_entry.name - mov esi, [esp + 4] -;DEBUGF 1,"esi: %s\n",esi -;DEBUGF 1,"edi: %s\n",edi - repe cmpsb - jne @f - cmp byte[esi], 0 ; HINT: use adc here? - je .found - cmp byte[esi], '/' - je .found_inc - @@: - add edi, ecx - add edi, eax - dec edx - jnz .next_name - movi eax, ERROR_FILE_NOT_FOUND - jmp .error - .found_inc: ; increment esi to skip '/' symbol - ; this means esi always points to valid file name or zero terminator byte - inc esi - .found: - stdcall xfs_get_inode_number_sf, dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count], [edi + 4], [edi] -;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax - jmp .quit - - .blockdir: - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - stdcall xfs_extent_unpack, eax - stdcall xfs_read_dirblock, dword[ebp + XFS.extent.br_startblock + 0], dword[ebp + XFS.extent.br_startblock + 4], [ebp + XFS.cur_dirblock] - test eax, eax - jnz .error -;DEBUGF 1,"dirblock signature: %s\n",[ebp+XFS.cur_dirblock] - mov ebx, [ebp + XFS.cur_dirblock] - mov eax, [ebp + XFS.dirblocksize] - mov eax, [ebx + eax - sizeof.xfs_dir2_block_tail + xfs_dir2_block_tail.count] - ; note that we don't subtract xfs_dir2_block_tail.stale here, - ; since we need the number of leaf entries rather than file number - bswap eax - add ebx, [ebp + XFS.dirblocksize] -; mov ecx, sizeof.xfs_dir2_leaf_entry - imul ecx, eax, sizeof.xfs_dir2_leaf_entry - sub ebx, sizeof.xfs_dir2_block_tail - sub ebx, ecx - shr ecx, 3 - push ecx ; for xfs_get_inode_by_hash - push ebx ; for xfs_get_inode_by_hash - - mov edi, esi - xor eax, eax - mov ecx, 4096 ; MAX_PATH_LEN - repne scasb - movi eax, ERROR_FS_FAIL - jne .error - neg ecx - add ecx, 4096 ; MAX_PATH_LEN - dec ecx - mov edx, ecx -;DEBUGF 1,"strlen total : %d\n",edx - mov edi, esi - mov eax, '/' - mov ecx, edx - repne scasb - jne @f - inc ecx - @@: - neg ecx - add ecx, edx -;DEBUGF 1,"strlen current: %d\n",ecx - stdcall xfs_hashname, esi, ecx - add esi, ecx - cmp byte[esi], '/' - jne @f - inc esi - @@: -;DEBUGF 1,"hashed: 0x%x\n",eax -; bswap eax - stdcall xfs_get_addr_by_hash - bswap eax -;DEBUGF 1,"got address: 0x%x\n",eax - cmp eax, -1 - jne @f - movi eax, ERROR_FILE_NOT_FOUND - mov ebx, -1 - jmp .error - @@: - shl eax, 3 - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, eax - mov edx, [ebx + 0] - mov eax, [ebx + 4] - bswap edx - bswap eax -;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax - jmp .quit - - .leafdir: -;DEBUGF 1,"dirblock signature: %s\n",[ebp+XFS.cur_dirblock] - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_extent_list_read_dirblock, eax, [ebp + XFS.dir2_leaf_offset_blocks], 0, edx, -1, -1 -;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax - mov ecx, eax - and ecx, edx - inc ecx - jz .error - - mov ebx, [ebp + XFS.cur_dirblock] - movzx eax, [ebx + xfs_dir2_leaf.hdr.count] - ; note that we don't subtract xfs_dir2_leaf.hdr.stale here, - ; since we need the number of leaf entries rather than file number - xchg al, ah - add ebx, xfs_dir2_leaf.ents -; imul ecx, eax, sizeof.xfs_dir2_leaf_entry -; shr ecx, 3 - push eax ; for xfs_get_addr_by_hash: len - push ebx ; for xfs_get_addr_by_hash: base - - mov edi, esi - xor eax, eax - mov ecx, 4096 ; MAX_PATH_LEN - repne scasb - movi eax, ERROR_FS_FAIL - jne .error - neg ecx - add ecx, 4096 - dec ecx - mov edx, ecx -;DEBUGF 1,"strlen total : %d\n",edx - mov edi, esi - mov eax, '/' - mov ecx, edx - repne scasb - jne @f - inc ecx - @@: - neg ecx - add ecx, edx -;DEBUGF 1,"strlen current: %d\n",ecx - stdcall xfs_hashname, esi, ecx - add esi, ecx - cmp byte[esi], '/' - jne @f - inc esi - @@: -;DEBUGF 1,"hashed: 0x%x\n",eax - stdcall xfs_get_addr_by_hash - bswap eax -;DEBUGF 1,"got address: 0x%x\n",eax - cmp eax, -1 - jne @f - movi eax, ERROR_FILE_NOT_FOUND - mov ebx, -1 - jmp .error - @@: - - mov ebx, [ebp + XFS.cur_inode_save] - push esi edi - xor edi, edi - mov esi, eax - shld edi, esi, 3 ; get offset - shl esi, 3 ; 2^3 = 8 byte align - mov edx, esi - mov ecx, [ebp + XFS.dirblklog] - add ecx, [ebp + XFS.blocklog] - mov eax, 1 - shl eax, cl - dec eax - and edx, eax - push edx - shrd esi, edi, cl - shr edi, cl - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_extent_list_read_dirblock, eax, esi, edi, edx, [ebp + XFS.dir2_leaf_offset_blocks], 0 -;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax - pop edx - pop edi esi - mov ecx, eax - and ecx, edx - inc ecx - jz .error - - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, edx - mov edx, [ebx + 0] - mov eax, [ebx + 4] - bswap edx - bswap eax -;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax - jmp .quit - - .nodedir: -;DEBUGF 1,"lookupdir: node\n" - mov [ebp + XFS.cur_inode_save], ebx - - mov edi, esi - xor eax, eax - mov ecx, 4096 ; MAX_PATH_LEN - repne scasb - movi eax, ERROR_FS_FAIL - jne .error - neg ecx - add ecx, 4096 ; MAX_PATH_LEN - dec ecx - mov edx, ecx -;DEBUGF 1,"strlen total : %d\n",edx - mov edi, esi - mov eax, '/' - mov ecx, edx - repne scasb - jne @f - inc ecx - @@: - neg ecx - add ecx, edx -;DEBUGF 1,"strlen current: %d\n",ecx - stdcall xfs_hashname, esi, ecx - add esi, ecx - cmp byte[esi], '/' - jne @f - inc esi - @@: -;DEBUGF 1,"hashed: 0x%x\n",eax - push edi edx - mov edi, eax - mov [ebp + XFS.entries_read], 0 - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_dir2_lookupdir_node, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks], edi - pop edx edi - test eax, eax - jnz .error - bswap ecx -;DEBUGF 1,"got address: 0x%x\n",ecx - - mov ebx, [ebp + XFS.cur_inode_save] - push esi edi - xor edi, edi - mov esi, ecx - shld edi, esi, 3 ; get offset - shl esi, 3 ; 8 byte align - mov edx, esi - mov ecx, [ebp + XFS.dirblklog] - add ecx, [ebp + XFS.blocklog] - mov eax, 1 - shl eax, cl - dec eax - and edx, eax - push edx - shrd esi, edi, cl - shr edi, cl - lea eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0] - mov edx, [ebx + xfs_inode.di_core.di_nextents] - bswap edx - stdcall xfs_extent_list_read_dirblock, eax, esi, edi, edx, [ebp + XFS.dir2_leaf_offset_blocks], 0 -;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax - pop edx - pop edi esi - mov ecx, eax - and ecx, edx - inc ecx - jz .error - - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, edx - mov edx, [ebx + 0] - mov eax, [ebx + 4] - bswap edx - bswap eax -;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax - jmp .quit - - .btreedir: -DEBUGF 1,"lookupdir: btree\n" - mov [ebp + XFS.cur_inode_save], ebx - - push ebx edx - mov eax, [ebx + xfs_inode.di_core.di_nextents] - bswap eax - mov [ebp + XFS.ro_nextents], eax - mov eax, [ebp + XFS.inodesize] - sub eax, xfs_inode.di_u - sub eax, sizeof.xfs_bmdr_block - shr eax, 4 ; FIXME forkoff -;DEBUGF 1,"maxnumresc: %d\n",eax - mov edx, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 0] - mov eax, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 4] - bswap eax - bswap edx - mov ebx, [ebp + XFS.cur_block] -;DEBUGF 1,"read_block: %x %x ",edx,eax - stdcall xfs_read_block - pop edx ebx - test eax, eax - jnz .error -;DEBUGF 1,"ok\n" - mov ebx, [ebp + XFS.cur_block] - - mov edi, esi - xor eax, eax - mov ecx, 4096 ; MAX_PATH_LEN - repne scasb - movi eax, ERROR_FS_FAIL - jne .error - neg ecx - add ecx, 4096 - dec ecx - mov edx, ecx -DEBUGF 1,"strlen total : %d\n",edx - mov edi, esi - mov eax, '/' - mov ecx, edx - repne scasb - jne @f - inc ecx - @@: - neg ecx - add ecx, edx -DEBUGF 1,"strlen current: %d\n",ecx - stdcall xfs_hashname, esi, ecx - add esi, ecx - cmp byte[esi], '/' - jne @f - inc esi - @@: -DEBUGF 1,"hashed: 0x%x\n",eax - push edi edx - mov edi, eax - mov [ebp + XFS.entries_read], 0 - lea eax, [ebx + sizeof.xfs_bmbt_block] - mov edx, [ebp + XFS.ro_nextents] -;push eax -;mov eax, [ebp + XFS.dir2_leaf_offset_blocks] -;DEBUGF 1,": 0x%x %d\n",eax,eax -;pop eax - stdcall xfs_dir2_lookupdir_node, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks], edi - pop edx edi - test eax, eax - jnz .error - bswap ecx -DEBUGF 1,"got address: 0x%x\n",ecx - - mov ebx, [ebp + XFS.cur_block] - push esi edi - xor edi, edi - mov esi, ecx - shld edi, esi, 3 ; get offset - shl esi, 3 - mov edx, esi - mov ecx, [ebp + XFS.dirblklog] - add ecx, [ebp + XFS.blocklog] - mov eax, 1 - shl eax, cl - dec eax - and edx, eax - push edx - shrd esi, edi, cl - shr edi, cl - lea eax, [ebx + sizeof.xfs_bmbt_block] - mov edx, [ebp + XFS.ro_nextents] - stdcall xfs_extent_list_read_dirblock, eax, esi, edi, edx, [ebp + XFS.dir2_leaf_offset_blocks], 0 -;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax - pop edx - pop edi esi - mov ecx, eax - and ecx, edx - inc ecx - jz .error - - mov ebx, [ebp + XFS.cur_dirblock] - add ebx, edx - mov edx, [ebx + 0] - mov eax, [ebx + 4] - bswap edx - bswap eax -DEBUGF 1,"found inode: 0x%x%x\n",edx,eax - jmp .quit - - .quit: - ret 12 - .error: - xor eax, eax - mov edx, eax - ret 12 - - -;---------------------------------------------------------------- -; push name -; call xfs_get_inode -; test eax, eax -;---------------------------------------------------------------- -xfs_get_inode: - ; call xfs_get_inode_short until file is found / error returned - -;DEBUGF 1,"getting inode of: %s\n",[esp+4] - push ebx esi edi - - ; start from the root inode - - mov edx, dword[ebp + XFS.rootino + 4] ; hi - mov eax, dword[ebp + XFS.rootino + 0] ; lo - mov esi, [esp + 16] ; name - - .next_dir: - cmp byte[esi], 0 - je .found - -;DEBUGF 1,"next_level: |%s|\n",esi - stdcall xfs_get_inode_short, esi, eax, edx - test edx, edx - jnz @f - test eax, eax - jz .error - @@: - jmp .next_dir ; file name found, go to next directory level - - .found: - - .quit: - pop edi esi ebx - ret 4 - .error: - pop edi esi ebx - xor eax, eax - mov edx, eax - ret 4 - - -;---------------------------------------------------------------- -; xfs_ReadFolder - XFS implementation of reading a folder -; 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_ReadFolder: - - ; to read folder - ; 1. lock partition - ; 2. find inode number - ; 3. read this inode - ; 4. get bdfe's - ; 5. unlock partition - - ; 1. - call xfs_lock - push ecx edx esi edi - - ; 2. - push ebx esi edi - add esi, [esp + 32] ; directory name -;DEBUGF 1,"xfs_ReadFolder: |%s|\n",esi - stdcall xfs_get_inode, esi - pop edi esi ebx - mov ecx, edx - or ecx, eax - jnz @f - movi eax, ERROR_FILE_NOT_FOUND - @@: - - ; 3. - stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode] - test eax, eax - movi eax, ERROR_FS_FAIL - jnz .error - - ; 4. - mov eax, [ebx + 8] ; encoding - and eax, 1 - stdcall xfs_dir_get_bdfes, [ebx + 4], [ebx + 12], [ebx + 16], edx, eax - test eax, eax - jnz .error - - .quit: -;DEBUGF 1,"\n\n" - pop edi esi edx ecx - ; 5. - call xfs_unlock - xor eax, eax - ret - .error: -;DEBUGF 1,"\n\n" - pop edi esi edx ecx - push eax - call xfs_unlock - pop eax - ret - - -;---------------------------------------------------------------- -; push inode_num_hi -; push inode_num_lo -; push [count] -; call xfs_get_inode_number_sf -;---------------------------------------------------------------- -xfs_get_inode_number_sf: - - ; inode numbers in short form directories may be 4 or 8 bytes long - ; determine the length in run time and read inode number at given address - - cmp byte[esp + 4 + xfs_dir2_sf_hdr.i8count], 0 ; i8count == 0 means 4 byte per inode number - je .i4bytes - .i8bytes: - mov edx, [esp + 12] ; hi - mov eax, [esp + 8] ; lo - bswap edx ; big endian - bswap eax - ret 12 - .i4bytes: - xor edx, edx ; no hi - mov eax, [esp + 12] ; hi = lo - bswap eax ; big endian - ret 12 - - -;---------------------------------------------------------------- -; push dest -; push src -; call xfs_get_inode_info -;---------------------------------------------------------------- -xfs_get_inode_info: - - ; get access time and other file properties - ; useful for browsing directories - ; called for each dir entry - -;DEBUGF 1,"get_inode_info\n" - xor eax, eax - mov edx, [esp + 4] - movzx ecx, word[edx + xfs_inode.di_core.di_mode] - xchg cl, ch -;DEBUGF 1,"di_mode: %x\n",ecx - test ecx, S_IFDIR ; directory? - jz @f - mov eax, 0x10 ; set directory flag - @@: - - mov edi, [esp + 8] - mov [edi + 0], eax - mov eax, dword[edx + xfs_inode.di_core.di_size + 0] ; hi - bswap eax - mov dword[edi + 36], eax ; file size hi -;DEBUGF 1,"file_size hi: %d\n",eax - mov eax, dword[edx + xfs_inode.di_core.di_size + 4] ; lo - bswap eax - mov dword[edi + 32], eax ; file size lo -;DEBUGF 1,"file_size lo: %d\n",eax - - add edi, 8 - mov eax, [edx + xfs_inode.di_core.di_ctime.t_sec] - bswap eax - push edx - 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 - sub eax, 978307200 - call fsTime2bdfe - pop edx - - mov eax, [edx + xfs_inode.di_core.di_mtime.t_sec] - bswap eax - push edx - sub eax, 978307200 - call fsTime2bdfe - pop edx - - .quit: - xor eax, eax - ret 8 - .error: - movi eax, ERROR_FS_FAIL - ret 8 - - -;---------------------------------------------------------------- -; push extent_data -; call xfs_extent_unpack -;---------------------------------------------------------------- -xfs_extent_unpack: - - ; extents come as packet 128bit bitfields - ; lets unpack them to access internal fields - ; write result to the XFS.extent structure - - push eax ebx ecx edx - mov ebx, [esp + 20] - - xor eax, eax - mov edx, [ebx + 0] - bswap edx - test edx, 0x80000000 ; mask, see documentation - setnz al - mov [ebp + XFS.extent.br_state], eax - - and edx, 0x7fffffff ; mask - mov eax, [ebx + 4] - bswap eax - shrd eax, edx, 9 - shr edx, 9 - mov dword[ebp + XFS.extent.br_startoff + 0], eax - mov dword[ebp + XFS.extent.br_startoff + 4], edx - - mov edx, [ebx + 4] - mov eax, [ebx + 8] - mov ecx, [ebx + 12] - bswap edx - bswap eax - bswap ecx - and edx, 0x000001ff ; mask - shrd ecx, eax, 21 - shrd eax, edx, 21 - mov dword[ebp + XFS.extent.br_startblock + 0], ecx - mov dword[ebp + XFS.extent.br_startblock + 4], eax - - mov eax, [ebx + 12] - bswap eax - and eax, 0x001fffff ; mask - mov [ebp + XFS.extent.br_blockcount], eax - - pop edx ecx ebx eax -;DEBUGF 1,"extent.br_startoff : %d %d\n",[ebp+XFS.extent.br_startoff+4],[ebp+XFS.extent.br_startoff+0] -;DEBUGF 1,"extent.br_startblock: %d %d\n",[ebp+XFS.extent.br_startblock+4],[ebp+XFS.extent.br_startblock+0] -;DEBUGF 1,"extent.br_blockcount: %d\n",[ebp+XFS.extent.br_blockcount] -;DEBUGF 1,"extent.br_state : %d\n",[ebp+XFS.extent.br_state] - ret 4 - - -;---------------------------------------------------------------- -; push namelen -; push name -; call xfs_hashname -;---------------------------------------------------------------- -xfs_hashname: ; xfs_da_hashname - - ; simple hash function - ; never fails) - - push ecx esi - xor eax, eax - mov esi, [esp + 12] ; name - mov ecx, [esp + 16] ; namelen -;mov esi, '.' -;mov ecx, 1 -;DEBUGF 1,"hashname: %d %s\n",ecx,esi - - @@: - rol eax, 7 - xor al, [esi] - add esi, 1 - loop @b - - pop esi ecx - ret 8 - - -;---------------------------------------------------------------- -; push len -; push base -; eax -- hash value -; call xfs_get_addr_by_hash -;---------------------------------------------------------------- -xfs_get_addr_by_hash: - - ; look for the directory entry offset by its file name hash - ; allows fast file search for block, leaf and node directories - ; binary (ternary) search - -;DEBUGF 1,"get_addr_by_hash\n" - push ebx esi - mov ebx, [esp + 12] ; left - mov edx, [esp + 16] ; len - .next: - mov ecx, edx -; jecxz .error - test ecx, ecx - jz .error - shr ecx, 1 - mov esi, [ebx + ecx*8 + xfs_dir2_leaf_entry.hashval] - bswap esi -;DEBUGF 1,"cmp 0x%x",esi - cmp eax, esi - jb .below - ja .above - mov eax, [ebx + ecx*8 + xfs_dir2_leaf_entry.address] - pop esi ebx - ret 8 - .below: -;DEBUGF 1,"b\n" - mov edx, ecx - jmp .next - .above: -;DEBUGF 1,"a\n" - lea ebx, [ebx + ecx*8 + 8] - sub edx, ecx - dec edx - jmp .next - .error: - mov eax, -1 - pop esi ebx - ret 8 - - -;---------------------------------------------------------------- -; xfs_GetFileInfo - XFS implementation of getting file info -; 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_GetFileInfo: - - ; lock partition - ; get inode number by file name - ; read inode - ; get info - ; unlock partition - - push ecx edx esi edi - call xfs_lock - - add esi, [esp + 20] ; name -;DEBUGF 1,"xfs_GetFileInfo: |%s|\n",esi - stdcall xfs_get_inode, esi - mov ecx, edx - or ecx, eax - jnz @f - movi eax, ERROR_FILE_NOT_FOUND - jmp .error - @@: - stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode] - test eax, eax - movi eax, ERROR_FS_FAIL - jnz .error - - stdcall xfs_get_inode_info, edx, [ebx + 16] - - .quit: - call xfs_unlock - pop edi esi edx ecx - xor eax, eax -;DEBUGF 1,"quit\n\n" - ret - .error: - call xfs_unlock - pop edi esi edx ecx -;DEBUGF 1,"error\n\n" - ret - - -;---------------------------------------------------------------- -; 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_ReadFile: - push ebx ecx edx esi edi - call xfs_lock - add esi, [esp + 24] - stdcall xfs_get_inode, esi - mov ecx, edx - or ecx, eax - jnz @f - movi eax, ERROR_FILE_NOT_FOUND - jmp .error - @@: - stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode] - test eax, eax - movi eax, ERROR_FS_FAIL - jnz .error - mov [ebp + XFS.cur_inode_save], edx - - cmp byte[edx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS - jne .not_extent_list - jmp .extent_list - .not_extent_list: - cmp byte[edx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE - jne .not_btree - jmp .btree - .not_btree: -DEBUGF 1,"XFS: NOT IMPLEMENTED: FILE FORMAT\n" - movi eax, ERROR_FS_FAIL - jmp .error - .extent_list: - mov ecx, [ebx + 12] ; bytes to read - mov edi, [ebx + 16] ; buffer for data - mov esi, [ebx + 8] ; offset_hi - mov ebx, [ebx + 4] ; offset_lo - - mov eax, dword[edx + xfs_inode.di_core.di_size + 4] ; lo - bswap eax - mov dword[ebp + XFS.bytes_left_in_file + 0], eax ; lo - mov eax, dword[edx + xfs_inode.di_core.di_size + 0] ; hi - bswap eax - mov dword[ebp + XFS.bytes_left_in_file + 4], eax ; hi - - mov eax, [edx + xfs_inode.di_core.di_nextents] - bswap eax - mov [ebp + XFS.left_extents], eax - - mov dword[ebp + XFS.bytes_read], 0 ; actually read bytes - - xor eax, eax ; extent offset in list - .extent_list.next_extent: -;DEBUGF 1,"extent_list.next_extent, eax: 0x%x\n",eax -;DEBUGF 1,"bytes_to_read: %d\n",ecx -;DEBUGF 1,"cur file offset: %d %d\n",esi,ebx -;DEBUGF 1,"esp: 0x%x\n",esp - cmp [ebp + XFS.left_extents], 0 - jne @f - test ecx, ecx - jz .quit - movi eax, ERROR_END_OF_FILE - jmp .error - @@: - push eax - lea eax, [edx + xfs_inode.di_u + eax + xfs_bmbt_rec.l0] - stdcall xfs_extent_unpack, eax - pop eax - dec [ebp + XFS.left_extents] - add eax, sizeof.xfs_bmbt_rec - push eax ebx ecx edx esi - mov ecx, [ebp + XFS.blocklog] - shrd ebx, esi, cl - shr esi, cl - cmp esi, dword[ebp + XFS.extent.br_startoff + 4] - jb .extent_list.to_hole ; handle sparse files - ja @f - cmp ebx, dword[ebp + XFS.extent.br_startoff + 0] - jb .extent_list.to_hole ; handle sparse files - je .extent_list.to_extent ; read from the start of current extent - @@: - xor edx, edx - mov eax, [ebp + XFS.extent.br_blockcount] - add eax, dword[ebp + XFS.extent.br_startoff + 0] - adc edx, dword[ebp + XFS.extent.br_startoff + 4] -;DEBUGF 1,"br_startoff: %d %d\n",edx,eax - cmp esi, edx - ja .extent_list.skip_extent - jb .extent_list.to_extent - cmp ebx, eax - jae .extent_list.skip_extent - jmp .extent_list.to_extent - .extent_list.to_hole: -;DEBUGF 1,"extent_list.to_hole\n" - pop esi edx ecx ebx eax - jmp .extent_list.read_hole - .extent_list.to_extent: -;DEBUGF 1,"extent_list.to_extent\n" - pop esi edx ecx ebx eax - jmp .extent_list.read_extent - .extent_list.skip_extent: -;DEBUGF 1,"extent_list.skip_extent\n" - pop esi edx ecx ebx eax - jmp .extent_list.next_extent - - .extent_list.read_hole: -;DEBUGF 1,"hole: offt: 0x%x%x ",esi,ebx - push eax edx - mov eax, dword[ebp + XFS.extent.br_startoff + 0] - mov edx, dword[ebp + XFS.extent.br_startoff + 4] - push esi ebx - mov ebx, ecx - sub eax, ebx ; get hole_size, it is 64 bit - sbb edx, 0 ; now edx:eax contains the size of hole -;DEBUGF 1,"size: 0x%x%x\n",edx,eax - jnz @f ; if hole size >= 2^32, write bytes_to_read zero bytes - cmp eax, ecx ; if hole size >= bytes_to_read, write bytes_to_read zeros - jae @f - mov ecx, eax ; if hole is < than bytes_to_read, write hole size zeros - @@: - sub ebx, ecx ; bytes_to_read - hole_size = left_to_read - add dword[esp + 0], ecx ; update pushed file offset - adc dword[esp + 4], 0 - xor eax, eax ; hole is made of zeros - rep stosb - mov ecx, ebx - pop ebx esi - - test ecx, ecx ; all requested bytes are read? - pop edx eax - jz .quit - jmp .extent_list.read_extent ; continue from the start of unpacked extent - - .extent_list.read_extent: -;DEBUGF 1,"extent_list.read_extent\n" - push eax ebx ecx edx esi - mov eax, ebx - mov edx, esi - mov ecx, [ebp + XFS.blocklog] - shrd eax, edx, cl - shr edx, cl - sub eax, dword[ebp + XFS.extent.br_startoff + 0] ; skip esi:ebx ? - sbb edx, dword[ebp + XFS.extent.br_startoff + 4] - sub [ebp + XFS.extent.br_blockcount], eax - add dword[ebp + XFS.extent.br_startblock + 0], eax - adc dword[ebp + XFS.extent.br_startblock + 4], 0 - .extent_list.read_extent.next_block: -;DEBUGF 1,"extent_list.read_extent.next_block\n" - cmp [ebp + XFS.extent.br_blockcount], 0 ; out of blocks in current extent? - jne @f - pop esi edx ecx ebx eax - jmp .extent_list.next_extent ; go to next extent - @@: - mov eax, dword[ebp + XFS.extent.br_startblock + 0] - mov edx, dword[ebp + XFS.extent.br_startblock + 4] - push ebx - mov ebx, [ebp + XFS.cur_block] -;DEBUGF 1,"read block: 0x%x%x\n",edx,eax - stdcall xfs_read_block - test eax, eax - pop ebx - jz @f - pop esi edx ecx ebx eax - movi eax, ERROR_FS_FAIL - jmp .error - @@: - dec [ebp + XFS.extent.br_blockcount] - add dword[ebp + XFS.extent.br_startblock + 0], 1 - adc dword[ebp + XFS.extent.br_startblock + 4], 0 - mov esi, [ebp + XFS.cur_block] - mov ecx, [ebp + XFS.blocklog] - mov eax, 1 - shl eax, cl - dec eax ; get blocklog mask - and eax, ebx ; offset in current block - add esi, eax - neg eax - add eax, [ebp + XFS.blocksize] - mov ecx, [esp + 8] ; pushed ecx, bytes_to_read - cmp ecx, eax ; is current block enough? - jbe @f ; if so, read bytes_to_read bytes - mov ecx, eax ; otherwise read the block up to the end - @@: - sub [esp + 8], ecx ; left_to_read - add [esp + 12], ecx ; update current file offset, pushed ebx - sub dword[ebp + XFS.bytes_left_in_file + 0], ecx - sbb dword[ebp + XFS.bytes_left_in_file + 4], 0 - jnc @f - add dword[ebp + XFS.bytes_left_in_file + 0], ecx - mov ecx, dword[ebp + XFS.bytes_left_in_file + 0] - mov dword[ebp + XFS.bytes_left_in_file + 0], 0 - mov dword[ebp + XFS.bytes_left_in_file + 4], 0 - @@: - add [ebp + XFS.bytes_read], ecx - adc [esp + 0], dword 0 ; pushed esi -;DEBUGF 1,"read data: %d\n",ecx - rep movsb - mov ecx, [esp + 8] -;DEBUGF 1,"left_to_read: %d\n",ecx - xor ebx, ebx - test ecx, ecx - jz @f - cmp dword[ebp + XFS.bytes_left_in_file + 4], 0 - jne .extent_list.read_extent.next_block - cmp dword[ebp + XFS.bytes_left_in_file + 0], 0 - jne .extent_list.read_extent.next_block - @@: - pop esi edx ecx ebx eax - jmp .quit - - .btree: - mov ecx, [ebx + 12] ; bytes to read - mov [ebp + XFS.bytes_to_read], ecx - mov edi, [ebx + 16] ; buffer for data - mov esi, [ebx + 8] ; offset_hi - mov ebx, [ebx + 4] ; offset_lo - mov dword[ebp + XFS.file_offset + 0], ebx - mov dword[ebp + XFS.file_offset + 4], esi - mov [ebp + XFS.buffer_pos], edi - - mov eax, dword[edx + xfs_inode.di_core.di_size + 4] ; lo - bswap eax - mov dword[ebp + XFS.bytes_left_in_file + 0], eax ; lo - mov eax, dword[edx + xfs_inode.di_core.di_size + 0] ; hi - bswap eax - mov dword[ebp + XFS.bytes_left_in_file + 4], eax ; hi - - mov eax, [edx + xfs_inode.di_core.di_nextents] - bswap eax - mov [ebp + XFS.left_extents], eax - - mov dword[ebp + XFS.bytes_read], 0 ; actually read bytes - - push ebx ecx edx esi edi - mov [ebp + XFS.eof], 0 - mov eax, dword[ebp + XFS.file_offset + 0] - mov edx, dword[ebp + XFS.file_offset + 4] - add eax, [ebp + XFS.bytes_to_read] - adc edx, 0 - sub eax, dword[ebp + XFS.bytes_left_in_file + 0] - sbb edx, dword[ebp + XFS.bytes_left_in_file + 4] - jc @f ; file_offset + bytes_to_read < file_size - jz @f ; file_offset + bytes_to_read = file_size - mov [ebp + XFS.eof], 1 - cmp edx, 0 - jne .error.eof - sub dword[ebp + XFS.bytes_to_read], eax - jc .error.eof - jz .error.eof - @@: - stdcall xfs_btree_read, 0, 0, 1 - pop edi esi edx ecx ebx - test eax, eax - jnz .error - cmp [ebp + XFS.eof], 1 - jne .quit - jmp .error.eof - - - .quit: - call xfs_unlock - pop edi esi edx ecx ebx - xor eax, eax - mov ebx, [ebp + XFS.bytes_read] -;DEBUGF 1,"quit: %d\n\n",ebx - ret - .error.eof: - movi eax, ERROR_END_OF_FILE - .error: -;DEBUGF 1,"error\n\n" - call xfs_unlock - pop edi esi edx ecx ebx - mov ebx, [ebp + XFS.bytes_read] - ret - - -;---------------------------------------------------------------- -; push max_offset_hi -; push max_offset_lo -; push nextents -; push block_number_hi -; push block_number_lo -; push extent_list -; -1 / read block number -;---------------------------------------------------------------- -xfs_extent_list_read_dirblock: ; skips holes -;DEBUGF 1,"xfs_extent_list_read_dirblock\n" - push ebx esi edi -;mov eax, [esp+28] -;DEBUGF 1,"nextents: %d\n",eax -;mov eax, [esp+20] -;mov edx, [esp+24] -;DEBUGF 1,"block_number: 0x%x%x\n",edx,eax -;mov eax, [esp+32] -;mov edx, [esp+36] -;DEBUGF 1,"max_addr : 0x%x%x\n",edx,eax - mov ebx, [esp + 16] - mov esi, [esp + 20] - mov edi, [esp + 24] -; mov ecx, [esp + 28] ; nextents - .next_extent: -;DEBUGF 1,"next_extent\n" - dec dword[esp + 28] - js .error - stdcall xfs_extent_unpack, ebx - add ebx, sizeof.xfs_bmbt_rec ; next extent - mov edx, dword[ebp + XFS.extent.br_startoff + 4] - mov eax, dword[ebp + XFS.extent.br_startoff + 0] - cmp edx, [esp + 36] ; max_offset_hi - ja .error - jb @f - cmp eax, [esp + 32] ; max_offset_lo - jae .error - @@: - cmp edi, edx - jb .hole - ja .check_count - cmp esi, eax - jb .hole - ja .check_count - jmp .read_block - .hole: -;DEBUGF 1,"hole\n" - mov esi, eax - mov edi, edx - jmp .read_block - .check_count: -;DEBUGF 1,"check_count\n" - add eax, [ebp + XFS.extent.br_blockcount] - adc edx, 0 - cmp edi, edx - ja .next_extent - jb .read_block - cmp esi, eax - jae .next_extent -; jmp .read_block - .read_block: -;DEBUGF 1,"read_block\n" - push esi edi - sub esi, dword[ebp + XFS.extent.br_startoff + 0] - sbb edi, dword[ebp + XFS.extent.br_startoff + 4] - add esi, dword[ebp + XFS.extent.br_startblock + 0] - adc edi, dword[ebp + XFS.extent.br_startblock + 4] - stdcall xfs_read_dirblock, esi, edi, [ebp + XFS.cur_dirblock] - pop edx eax - .quit: -;DEBUGF 1,"xfs_extent_list_read_dirblock: quit\n" - pop edi esi ebx - ret 24 - .error: -;DEBUGF 1,"xfs_extent_list_read_dirblock: error\n" - xor eax, eax - dec eax - mov edx, eax - pop edi esi ebx - ret 24 - - -;---------------------------------------------------------------- -; push dirblock_num -; push nextents -; push extent_list -;---------------------------------------------------------------- -xfs_dir2_node_get_numfiles: - - ; unfortunately, we need to set 'total entries' field - ; this often requires additional effort, since there is no such a number in most directory ondisk formats - -;DEBUGF 1,"xfs_dir2_node_get_numfiles\n" - push ebx ecx edx esi edi - - mov eax, [esp + 24] - mov edx, [esp + 28] - mov esi, [esp + 32] - stdcall xfs_extent_list_read_dirblock, eax, esi, 0, edx, -1, -1 - mov ecx, eax - and ecx, edx - inc ecx - jnz @f - movi eax, ERROR_FS_FAIL - jmp .error - @@: - mov ebx, [ebp + XFS.cur_dirblock] - cmp word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DA_NODE_MAGIC - je .node - cmp word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DIR2_LEAFN_MAGIC - je .leaf - mov eax, ERROR_FS_FAIL - jmp .error - - .node: -;DEBUGF 1,".node\n" - mov edi, [ebx + xfs_da_intnode.hdr.info.forw] - bswap edi - mov eax, [esp + 24] - mov edx, [esp + 28] - mov esi, [ebx + xfs_da_intnode.btree.before] - bswap esi - stdcall xfs_dir2_node_get_numfiles, eax, edx, esi - test eax, eax - jnz .error - jmp .common - - .leaf: -;DEBUGF 1,".leaf\n" - movzx ecx, word[ebx + xfs_dir2_leaf.hdr.count] - xchg cl, ch - movzx eax, word[ebx + xfs_dir2_leaf.hdr.stale] - xchg al, ah - sub ecx, eax - add [ebp + XFS.entries_read], ecx - mov edi, [ebx + xfs_dir2_leaf.hdr.info.forw] - bswap edi - jmp .common - - .common: - test edi, edi - jz .quit - mov esi, edi - mov eax, [esp + 24] - mov edx, [esp + 28] - stdcall xfs_dir2_node_get_numfiles, eax, edx, esi - test eax, eax - jnz .error - jmp .quit - - .quit: -;DEBUGF 1,".quit\n" - pop edi esi edx ecx ebx - xor eax, eax - ret 12 - .error: -;DEBUGF 1,".error\n" - pop edi esi edx ecx ebx - movi eax, ERROR_FS_FAIL - ret 12 - - -;---------------------------------------------------------------- -; push hash -; push dirblock_num -; push nextents -; push extent_list -;---------------------------------------------------------------- -xfs_dir2_lookupdir_node: -DEBUGF 1,"xfs_dir2_lookupdir_node\n" - push ebx edx esi edi - - mov eax, [esp + 20] - mov edx, [esp + 24] - mov esi, [esp + 28] -DEBUGF 1,"read dirblock: 0x%x %d\n",esi,esi - stdcall xfs_extent_list_read_dirblock, eax, esi, 0, edx, -1, -1 -DEBUGF 1,"dirblock read: 0x%x%x\n",edx,eax - mov ecx, eax - and ecx, edx - inc ecx - jnz @f - movi eax, ERROR_FS_FAIL - jmp .error - @@: -DEBUGF 1,"checkpoint #1\n" - mov ebx, [ebp + XFS.cur_dirblock] - cmp word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DA_NODE_MAGIC - je .node - cmp word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DIR2_LEAFN_MAGIC - je .leaf - mov eax, ERROR_FS_FAIL -DEBUGF 1,"checkpoint #2\n" - jmp .error - - .node: -DEBUGF 1,".node\n" - mov edi, [esp + 32] ; hash - movzx ecx, word[ebx + xfs_da_intnode.hdr.count] - xchg cl, ch - mov [ebp + XFS.left_leaves], ecx - xor ecx, ecx - .node.next_leaf: - mov esi, [ebx + xfs_da_intnode.btree + ecx*sizeof.xfs_da_node_entry + xfs_da_node_entry.hashval] - bswap esi - cmp edi, esi - jbe .node.leaf_found - inc ecx - cmp ecx, [ebp + XFS.left_leaves] - jne .node.next_leaf - mov eax, ERROR_FILE_NOT_FOUND - jmp .error - @@: - .node.leaf_found: - mov eax, [esp + 20] - mov edx, [esp + 24] - mov esi, [ebx + xfs_da_intnode.btree + ecx*sizeof.xfs_da_node_entry + xfs_da_node_entry.before] - bswap esi - stdcall xfs_dir2_lookupdir_node, eax, edx, esi, edi - test eax, eax - jz .quit - movi eax, ERROR_FILE_NOT_FOUND - jmp .error - - .leaf: -DEBUGF 1,".leaf\n" - movzx ecx, [ebx + xfs_dir2_leaf.hdr.count] - xchg cl, ch - lea esi, [ebx + xfs_dir2_leaf.ents] - mov eax, [esp + 32] - stdcall xfs_get_addr_by_hash, esi, ecx - cmp eax, -1 - je .error - mov ecx, eax - jmp .quit - - .quit: -DEBUGF 1,".quit\n" - pop edi esi edx ebx - xor eax, eax - ret 16 - .error: -DEBUGF 1,".error\n" - pop edi esi edx ebx - ret 16 - - -;---------------------------------------------------------------- -; push dirblock_num -; push nextents -; push extent_list -;---------------------------------------------------------------- -xfs_dir2_btree_get_numfiles: -;DEBUGF 1,"xfs_dir2_node_get_numfiles\n" - push ebx ecx edx esi edi - - mov eax, [esp + 24] - mov edx, [esp + 28] - mov esi, [esp + 32] - stdcall xfs_extent_list_read_dirblock, eax, esi, 0, edx, -1, -1 - mov ecx, eax - and ecx, edx - inc ecx - jnz @f - movi eax, ERROR_FS_FAIL - jmp .error - @@: - mov ebx, [ebp + XFS.cur_dirblock] - cmp word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DA_NODE_MAGIC - je .node - cmp word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DIR2_LEAFN_MAGIC - je .leaf - mov eax, ERROR_FS_FAIL - jmp .error - - .node: -;DEBUGF 1,".node\n" - mov edi, [ebx + xfs_da_intnode.hdr.info.forw] - bswap edi - mov eax, [esp + 24] - mov edx, [esp + 28] - mov esi, [ebx + xfs_da_intnode.btree.before] - bswap esi - stdcall xfs_dir2_node_get_numfiles, eax, edx, esi - test eax, eax - jnz .error - jmp .common - - .leaf: -;DEBUGF 1,".leaf\n" - movzx ecx, word[ebx + xfs_dir2_leaf.hdr.count] - xchg cl, ch - movzx eax, word[ebx + xfs_dir2_leaf.hdr.stale] - xchg al, ah - sub ecx, eax - add [ebp + XFS.entries_read], ecx - mov edi, [ebx + xfs_dir2_leaf.hdr.info.forw] - bswap edi - jmp .common - - .common: - test edi, edi - jz .quit - mov esi, edi - mov eax, [esp + 24] - mov edx, [esp + 28] - stdcall xfs_dir2_node_get_numfiles, eax, edx, esi - test eax, eax - jnz .error - jmp .quit - - .quit: -;DEBUGF 1,".quit\n" - pop edi esi edx ecx ebx - xor eax, eax - ret 12 - .error: -;DEBUGF 1,".error\n" - pop edi esi edx ecx ebx - movi eax, ERROR_FS_FAIL - ret 12 - - -;---------------------------------------------------------------- -; push is_root -; push block_hi -; push block_lo -;---------------------------------------------------------------- -xfs_btree_read: - push ebx ecx edx esi edi - cmp dword[esp + 32], 1 ; is root? - je .root - jmp .not_root - .root: -DEBUGF 1,".root\n" - mov ebx, [ebp + XFS.cur_inode_save] - add ebx, xfs_inode.di_u - movzx edx, [ebx + xfs_bmdr_block.bb_numrecs] - xchg dl, dh - dec edx - add ebx, sizeof.xfs_bmdr_block - xor eax, eax - dec eax - .root.next_key: -DEBUGF 1,".root.next_key\n" - cmp [ebp + XFS.bytes_to_read], 0 - je .quit - inc eax - cmp eax, edx ; out of keys? - ja .root.key_found ; there is no length field, so try the last key - lea edi, [ebx + sizeof.xfs_bmbt_key*eax + 0] - lea esi, [ebx + sizeof.xfs_bmbt_key*eax + 4] - bswap edi - bswap esi - mov ecx, [ebp + XFS.blocklog] - shld edi, esi, cl - shl esi, cl - cmp edi, dword[ebp + XFS.file_offset + 4] - ja .root.prev_or_hole - jb .root.next_key - cmp esi, dword[ebp + XFS.file_offset + 0] - ja .root.prev_or_hole - jb .root.next_key - jmp .root.key_found - .root.prev_or_hole: -DEBUGF 1,".root.prev_or_hole\n" - test eax, eax - jz .root.hole - dec eax - jmp .root.key_found - .root.hole: -DEBUGF 1,".root.hole\n" - push eax edx esi edi - mov ecx, [ebp + XFS.blocklog] - shld edi, esi, cl - shl esi, cl - sub esi, dword[ebp + XFS.file_offset + 0] - sbb edi, dword[ebp + XFS.file_offset + 4] - mov ecx, [ebp + XFS.bytes_to_read] - cmp edi, 0 ; hole size >= 2^32 - jne @f - cmp ecx, esi - jbe @f - mov ecx, esi - @@: - add dword[ebp + XFS.file_offset + 0], ecx - adc dword[ebp + XFS.file_offset + 4], 0 - sub [ebp + XFS.bytes_to_read], ecx - xor eax, eax - mov edi, [ebp + XFS.buffer_pos] - rep stosb - mov [ebp + XFS.buffer_pos], edi - pop edi esi edx eax - jmp .root.next_key - .root.key_found: -DEBUGF 1,".root.key_found\n" - mov edx, [ebp + XFS.cur_inode_save] - mov eax, [ebp + XFS.inodesize] - sub eax, xfs_inode.di_u - cmp [edx + xfs_inode.di_core.di_forkoff], 0 - je @f - movzx eax, [edx + xfs_inode.di_core.di_forkoff] - shl eax, XFS_DIR2_DATA_ALIGN_LOG ; 3 - @@: - sub eax, sizeof.xfs_bmdr_block - shr eax, 4 ;log2(sizeof.xfs_bmbt_key + sizeof.xfs_bmdr_ptr) - mov edx, [ebx + sizeof.xfs_bmbt_key*eax + 0] ; hi - mov eax, [ebx + sizeof.xfs_bmbt_key*eax + 4] ; hi - bswap edx - bswap eax - stdcall xfs_btree_read, eax, edx, 0 - test eax, eax - jnz .error - jmp .root.next_key - - .not_root: -DEBUGF 1,".root.not_root\n" - mov eax, [esp + 24] ; block_lo - mov edx, [esp + 28] ; block_hi - mov ebx, [ebp + XFS.cur_block] - stdcall xfs_read_block - test eax, eax - jnz .error - mov ebx, [ebp + XFS.cur_block] - - cmp [ebx + xfs_bmbt_block.bb_magic], XFS_BMAP_MAGIC - jne .error - cmp [ebx + xfs_bmbt_block.bb_level], 0 ; leaf? - je .leaf - jmp .node - - .node: -; mov eax, [ebp + XFS.blocksize] -; sub eax, sizeof.xfs_bmbt_block -; shr eax, 4 ; maxnumrecs - mov eax, dword[ebp + XFS.file_offset + 0] ; lo - mov edx, dword[ebp + XFS.file_offset + 4] ; hi - movzx edx, [ebx + xfs_bmbt_block.bb_numrecs] - xchg dl, dh - dec edx - add ebx, sizeof.xfs_bmbt_block - xor eax, eax - dec eax - .node.next_key: - push eax ecx edx esi edi - mov eax, [esp + 44] ; block_lo - mov edx, [esp + 48] ; block_hi - mov ebx, [ebp + XFS.cur_block] - stdcall xfs_read_block - test eax, eax - jnz .error - mov ebx, [ebp + XFS.cur_block] - add ebx, sizeof.xfs_bmbt_block - pop edi esi edx ecx eax - cmp [ebp + XFS.bytes_to_read], 0 - je .quit - inc eax - cmp eax, edx ; out of keys? - ja .node.key_found ; there is no length field, so try the last key - lea edi, [ebx + sizeof.xfs_bmbt_key*eax + 0] - lea esi, [ebx + sizeof.xfs_bmbt_key*eax + 4] - bswap edi - bswap esi - mov ecx, [ebp + XFS.blocklog] - shld edi, esi, cl - shl esi, cl - cmp edi, dword[ebp + XFS.file_offset + 4] - ja .node.prev_or_hole - jb .node.next_key - cmp esi, dword[ebp + XFS.file_offset + 0] - ja .node.prev_or_hole - jb .node.next_key - jmp .node.key_found - .node.prev_or_hole: - test eax, eax - jz .node.hole - dec eax - jmp .node.key_found - .node.hole: - push eax edx esi edi - mov ecx, [ebp + XFS.blocklog] - shld edi, esi, cl - shl esi, cl - sub esi, dword[ebp + XFS.file_offset + 0] - sbb edi, dword[ebp + XFS.file_offset + 4] - mov ecx, [ebp + XFS.bytes_to_read] - cmp edi, 0 ; hole size >= 2^32 - jne @f - cmp ecx, esi - jbe @f - mov ecx, esi - @@: - add dword[ebp + XFS.file_offset + 0], ecx - adc dword[ebp + XFS.file_offset + 4], 0 - sub [ebp + XFS.bytes_to_read], ecx - xor eax, eax - mov edi, [ebp + XFS.buffer_pos] - rep stosb - mov [ebp + XFS.buffer_pos], edi - pop edi esi edx eax - jmp .node.next_key - .node.key_found: - mov edx, [ebp + XFS.cur_inode_save] - mov eax, [ebp + XFS.inodesize] - sub eax, xfs_inode.di_u - cmp [edx + xfs_inode.di_core.di_forkoff], 0 - je @f - movzx eax, [edx + xfs_inode.di_core.di_forkoff] - shl eax, XFS_DIR2_DATA_ALIGN_LOG ; 3 - @@: - sub eax, sizeof.xfs_bmdr_block - shr eax, 4 ;log2(sizeof.xfs_bmbt_key + sizeof.xfs_bmdr_ptr) - mov edx, [ebx + sizeof.xfs_bmbt_key*eax + 0] ; hi - mov eax, [ebx + sizeof.xfs_bmbt_key*eax + 4] ; hi - bswap edx - bswap eax - stdcall xfs_btree_read, eax, edx, 0 - test eax, eax - jnz .error - jmp .node.next_key - jmp .quit - - .leaf: - - jmp .quit - - .error: - pop edi esi edx ecx ebx - movi eax, ERROR_FS_FAIL - ret 4 - .quit: - pop edi esi edx ecx ebx - xor eax, eax - ret 4 - - -;---------------------------------------------------------------- -; push nextents -; push extent_list -; push file_offset_hi -; push file_offset_lo -;---------------------------------------------------------------- -;xfs_extent_list_read: -; push ebx 0 edx esi edi ; zero means actually_read_bytes -; -; .quit: -; pop edi esi edx ecx ebx -; xor eax, eax -; ret 24 -; .error: -; pop edi esi edx ecx ebx -; ret 24 diff --git a/xfs.inc b/xfs.inc deleted file mode 100644 index ac81944..0000000 --- a/xfs.inc +++ /dev/null @@ -1,528 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2013-2015. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision: 5363 $ - - -; from stat.h -; distinguish file types -S_IFMT = 0170000o ; These bits determine file type. -S_IFDIR = 0040000o ; Directory. -S_IFCHR = 0020000o ; Character device. -S_IFBLK = 0060000o ; Block device. -S_IFREG = 0100000o ; Regular file. -S_IFIFO = 0010000o ; FIFO. -S_IFLNK = 0120000o ; Symbolic link. -S_IFSOCK = 0140000o ; Socket. -; end stat.h - - -; XFS null constant: empty fields must be all ones, not zeros! -XFS_NULL = -1 - - -; static sector numbers -XFS_SECT_SB = 0 -XFS_SECT_AGF = 1 -XFS_SECT_AGI = 2 -XFS_SECT_AGFL = 3 - - -; signatures of file system structures -; 'string' numbers are treated by fasm as big endian -XFS_SB_MAGIC = 'XFSB' -XFS_AGF_MAGIC = 'XAGF' -XFS_AGI_MAGIC = 'XAGI' -XFS_ABTB_MAGIC = 'ABTB' -XFS_ABTC_MAGIC = 'ABTC' -XFS_IBT_MAGIC = 'IABT' -XFS_DINODE_MAGIC = 'IN' -XFS_BMAP_MAGIC = 'BMAP' -XFS_DA_NODE_MAGIC = 0xbefe ; those are little endian here -XFS_ATTR_LEAF_MAGIC = 0xeefb ; but big endian in docs -XFS_DIR2_LEAF1_MAGIC = 0xf1d2 ; pay attention! -XFS_DIR2_LEAFN_MAGIC = 0xffd2 ; -XFS_DIR2_BLOCK_MAGIC = 'XD2B' -XFS_DIR2_DATA_MAGIC = 'XD2D' -XFS_DIR2_FREE_MAGIC = 'XD2F' -XFS_DQUOT_MAGIC = 'DQ' - - -; bitfield lengths for packed extent -; MSB to LSB / left to right -BMBT_EXNTFLAG_BITLEN = 1 -BMBT_STARTOFF_BITLEN = 54 -BMBT_STARTBLOCK_BITLEN = 52 -BMBT_BLOCKCOUNT_BITLEN = 21 - - -; those constants are taken from linux source (xfs_dir2_leaf.h) -; they are magic infile offsets for directories -XFS_DIR2_DATA_ALIGN_LOG = 3 ; i.e., 8 bytes -XFS_DIR2_LEAF_SPACE = 1 -XFS_DIR2_SPACE_SIZE = (1 SHL (32 + XFS_DIR2_DATA_ALIGN_LOG)) -XFS_DIR2_LEAF_OFFSET = (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE) -XFS_DIR2_FREE_SPACE = 2 -XFS_DIR2_SPACE_SIZE = (1 SHL (32 + XFS_DIR2_DATA_ALIGN_LOG)) -XFS_DIR2_FREE_OFFSET = (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE) - - -; data section magic constants for directories (xfs_dir2_data.h) -XFS_DIR2_DATA_FD_COUNT = 3 -XFS_DIR2_DATA_FREE_TAG = 0xffff - - -; valid inode formats -; enum xfs_dinode_fmt (xfs_dinode.h) -XFS_DINODE_FMT_DEV = 0 ; xfs_dev_t -XFS_DINODE_FMT_LOCAL = 1 ; one inode is enough (shortdir) -XFS_DINODE_FMT_EXTENTS = 2 ; one or more extents (leafdir, nodedir, regular files) -XFS_DINODE_FMT_BTREE = 3 ; highly fragmented files or really huge directories -XFS_DINODE_FMT_UUID = 4 ; uuid_t - - -; size of the unlinked inode hash table in the agi -XFS_AGI_UNLINKED_BUCKETS = 64 - - -; possible extent states -; enum xfs_exntst_t (xfs_bmap_btree.h) -XFS_EXT_NORM = 0 -XFS_EXT_UNWRITTEN = 1 -XFS_EXT_DMAPI_OFFLINE = 2 -XFS_EXT_INVALID = 3 - - -; values for inode core flags / di_flags (xfs_dinode.h) -XFS_DIFLAG_REALTIME_BIT = 0 ; file's blocks come from rt area -XFS_DIFLAG_PREALLOC_BIT = 1 ; file space has been preallocated -XFS_DIFLAG_NEWRTBM_BIT = 2 ; for rtbitmap inode, new format -XFS_DIFLAG_IMMUTABLE_BIT = 3 ; inode is immutable -XFS_DIFLAG_APPEND_BIT = 4 ; inode is append-only -XFS_DIFLAG_SYNC_BIT = 5 ; inode is written synchronously -XFS_DIFLAG_NOATIME_BIT = 6 ; do not update atime -XFS_DIFLAG_NODUMP_BIT = 7 ; do not dump -XFS_DIFLAG_RTINHERIT_BIT = 8 ; create with realtime bit set -XFS_DIFLAG_PROJINHERIT_BIT = 9 ; create with parents projid -XFS_DIFLAG_NOSYMLINKS_BIT = 10 ; disallow symlink creation -XFS_DIFLAG_EXTSIZE_BIT = 11 ; inode extent size allocator hint -XFS_DIFLAG_EXTSZINHERIT_BIT = 12 ; inherit inode extent size -XFS_DIFLAG_NODEFRAG_BIT = 13 ; do not reorganize/defragment -XFS_DIFLAG_FILESTREAM_BIT = 14 ; use filestream allocator -XFS_DIFLAG_REALTIME = (1 SHL XFS_DIFLAG_REALTIME_BIT) -XFS_DIFLAG_PREALLOC = (1 SHL XFS_DIFLAG_PREALLOC_BIT) -XFS_DIFLAG_NEWRTBM = (1 SHL XFS_DIFLAG_NEWRTBM_BIT) -XFS_DIFLAG_IMMUTABLE = (1 SHL XFS_DIFLAG_IMMUTABLE_BIT) -XFS_DIFLAG_APPEND = (1 SHL XFS_DIFLAG_APPEND_BIT) -XFS_DIFLAG_SYNC = (1 SHL XFS_DIFLAG_SYNC_BIT) -XFS_DIFLAG_NOATIME = (1 SHL XFS_DIFLAG_NOATIME_BIT) -XFS_DIFLAG_NODUMP = (1 SHL XFS_DIFLAG_NODUMP_BIT) -XFS_DIFLAG_RTINHERIT = (1 SHL XFS_DIFLAG_RTINHERIT_BIT) -XFS_DIFLAG_PROJINHERIT = (1 SHL XFS_DIFLAG_PROJINHERIT_BIT) -XFS_DIFLAG_NOSYMLINKS = (1 SHL XFS_DIFLAG_NOSYMLINKS_BIT) -XFS_DIFLAG_EXTSIZE = (1 SHL XFS_DIFLAG_EXTSIZE_BIT) -XFS_DIFLAG_EXTSZINHERIT = (1 SHL XFS_DIFLAG_EXTSZINHERIT_BIT) -XFS_DIFLAG_NODEFRAG = (1 SHL XFS_DIFLAG_NODEFRAG_BIT) -XFS_DIFLAG_FILESTREAM = (1 SHL XFS_DIFLAG_FILESTREAM_BIT) - - -; superblock _ondisk_ structure (xfs_sb.h) -; this is _not_ the partition structure -; for XFS partition structure see XFS below -struct xfs_sb - sb_magicnum dd ? ; signature, must be XFS_SB_MAGIC - sb_blocksize dd ? ; block is the minimal file system unit, in bytes - sb_dblocks dq ? ; number of data blocks - sb_rblocks dq ? ; number of realtime blocks (not supported yet!) - sb_rextents dq ? ; number of realtime extents (not supported yet!) - sb_uuid rb 16 ; file system unique identifier - sb_logstart dq ? ; starting block of log (for internal journal; journals on separate devices are not supported!) - sb_rootino dq ? ; root inode number - sb_rbmino dq ? ; bitmap inode for realtime extents (ignored) - sb_rsumino dq ? ; summary inode for rt bitmap (ignored) - sb_rextsize dd ? ; realtime extent size, blocks - sb_agblocks dd ? ; size of an allocation group (the last one may be smaller!) - sb_agcount dd ? ; number of allocation groups - sb_rbmblocks dd ? ; number of rt bitmap blocks - sb_logblocks dd ? ; number of log blocks - sb_versionnum dw ? ; header version == XFS_SB_VERSION - sb_sectsize dw ? ; volume sector size in bytes (only 512B sectors are supported) - sb_inodesize dw ? ; inode size, bytes - sb_inopblock dw ? ; inodes per block - sb_fname rb 12 ; inodes per block (aka label) - sb_blocklog db ? ; log2 of sb_blocksize - sb_sectlog db ? ; log2 of sb_blocksize - sb_inodelog db ? ; log2 of sb_inodesize - sb_inopblog db ? ; log2 of sb_inopblock - sb_agblklog db ? ; log2 of sb_agblocks (rounded up!) - sb_rextslog db ? ; log2 of sb_rextents - sb_inprogress db ? ; mkfs is in progress, don't mount - sb_imax_pct db ? ; max % of fs for inode space - ; statistics - sb_icount dq ? ; allocated inodes - sb_ifree dq ? ; free inodes - sb_fdblocks dq ? ; free data blocks - sb_frextents dq ? ; free realtime extents - - sb_uquotino dq ? ; user quota inode - sb_gquotino dq ? ; group quota inode - sb_qflags dw ? ; quota flags - sb_flags db ? ; misc. flags - sb_shared_vn db ? ; shared version number - sb_inoalignmt dd ? ; inode chunk alignment, fsblocks - sb_unit dd ? ; stripe or raid unit - sb_width dd ? ; stripe or raid width - sb_dirblklog db ? ; log2 of dir block size (fsbs) - sb_logsectlog db ? ; log2 of the log sector size - sb_logsectsize dw ? ; sector size for the log, bytes - sb_logsunit dd ? ; stripe unit size for the log - sb_features2 dd ? ; additional feature bits -ends - - -; allocation group inode (xfs_ag.h) -struct xfs_agi - agi_magicnum dd ? ; magic number == XFS_AGI_MAGIC - agi_versionnum dd ? ; header version == XFS_AGI_VERSION - agi_seqno dd ? ; sequence number starting from 0 - agi_length dd ? ; size in blocks of a.g. - agi_count dd ? ; count of allocated inodes - agi_root dd ? ; root of inode btree - agi_level dd ? ; levels in inode btree - agi_freecount dd ? ; number of free inodes - agi_newino dd ? ; new inode just allocated - agi_dirino dd ? ; last directory inode chunk - agi_unlinked rd XFS_AGI_UNLINKED_BUCKETS ; Hash table of inodes which have been unlinked but are still being referenced -ends - - -; superblock structure of b+tree node/leaf (same structure, bb_level matters) -struct xfs_btree_sblock - bb_magic dd ? - bb_level dw ? ; distinguishes nodeds and leaves - bb_numrecs dw ? - bb_leftsib dd ? - bb_rightsib dd ? -ends - - -; record of b+tree inode -struct xfs_inobt_rec - ir_startino dd ? - ir_freecount dd ? - ir_free dq ? -ends - - -; structure to store create, access and modification time in inode core -struct xfs_timestamp - t_sec dd ? - t_nsec dd ? ; nanoseconds -ends - - -; inode core structure: basic information about file -struct xfs_dinode_core - di_magic dw ? ; inode magic = XFS_DINODE_MAGIC - di_mode dw ? ; mode and type of file - di_version db ? ; inode version - di_format db ? ; format of di_c data - di_onlink dw ? ; old number of links to file - di_uid dd ? ; owner's user id - di_gid dd ? ; owner's group id - di_nlink dd ? ; number of links to file - di_projid dw ? ; owner's project id - di_pad rb 8 ; unused, zeroed space - di_flushiter dw ? ; incremented on flush - di_atime xfs_timestamp ; time last accessed - di_mtime xfs_timestamp ; time last modified - di_ctime xfs_timestamp ; time created/inode modified - di_size dq ? ; number of bytes in file - di_nblocks dq ? ; number of direct & btree blocks used - di_extsize dd ? ; basic/minimum extent size for file - di_nextents dd ? ; number of extents in data fork - di_anextents dw ? ; number of extents in attribute fork - di_forkoff db ? ; attr fork offs, <<3 for 64b align - di_aformat db ? ; format of attr fork's data - di_dmevmask dd ? ; DMIG event mask - di_dmstate dw ? ; DMIG state info - di_flags dw ? ; random flags, XFS_DIFLAG_... - di_gen dd ? ; generation number -ends - - -; shortform dir header -struct xfs_dir2_sf_hdr - count db ? ; the number of directory entries, used only if each inode number fits 4 bytes; zero otherwise - i8count db ? ; the number of directory entries, used only when count is zero - parent dq ? ; parent inode number: xfs_dir2_inou_t (4 or 8 bytes) -ends - - -; shortform dir entry -struct xfs_dir2_sf_entry - namelen db ? ; actual name length (ASCII) - offset rb 2 ; saved offset - name db ? ; name, variable size -; inumber dq ? ; xfs_dir2_inou_t -ends - - -; active entry in a data block -; aligned to 8 bytes -; tag appears as the last 2 bytes -struct xfs_dir2_data_entry - inumber dq ? ; inode number - namelen db ? ; name length - name db ? ; name bytes, no null -; tag dw ? ; starting offset of us -ends - - -; unused entry in a data block -; aligned to 8 bytes -; tag appears as the last 2 bytes -struct xfs_dir2_data_unused - freetag dw ? ; XFS_DIR2_DATA_FREE_TAG - length dw ? ; total free length -; tag dw ? ; starting offset of us -ends - - -; generic data entry -struct xfs_dir2_data_union - union - xentry xfs_dir2_data_entry - unused xfs_dir2_data_unused - ends -ends - - -; describe a free area in the data block -; the freespace will be formatted as a xfs_dir2_data_unused_t -struct xfs_dir2_data_free - offset dw ? ; start of freespace - length dw ? ; length of freespace -ends - - -; header for the data blocks -; always at the beginning of a directory-sized block -; the code knows that XFS_DIR2_DATA_FD_COUNT is 3 -struct xfs_dir2_data_hdr - magic dd ? ; XFS_DIR2_DATA_MAGIC or XFS_DIR2_BLOCK_MAGIC - bestfree xfs_dir2_data_free - bestfree2 xfs_dir2_data_free - bestfree3 xfs_dir2_data_free -ends - - -; leaf block entry -struct xfs_dir2_leaf_entry - hashval dd ? ; hash value of name - address dd ? ; address of data entry -ends - - -; the tail of directory block -struct xfs_dir2_block_tail - count dd ? ; count of leaf entries - stale dd ? ; count of stale leaf entries -ends - - -; generic single-block structure, for xfs_db -struct xfs_dir2_block - hdr xfs_dir2_data_hdr - u xfs_dir2_data_union -; leaf xfs_dir2_leaf_entry -; tail xfs_dir2_block_tail -ends - - -; -struct xfs_dir2_data - hdr xfs_dir2_data_hdr ; magic XFS_DIR2_DATA_MAGIC - u xfs_dir2_data_union -ends - - -; -struct xfs_da_blkinfo - forw dd ? ; previous block in list - back dd ? ; following block in list - magic dw ? ; validity check on block - pad dw ? ; unused -ends - - -; leaf block header -struct xfs_dir2_leaf_hdr - info xfs_da_blkinfo ; header for da routines - count dw ? ; count of entries - stale dw ? ; count of stale entries -ends - - -; leaf block tail -struct xfs_dir2_leaf_tail - bestcount dd ? -ends - - -; leaf block -; bests and tail are at the end of the block for single-leaf only -; (magic = XFS_DIR2_LEAF1_MAGIC not XFS_DIR2_LEAFN_MAGIC) -struct xfs_dir2_leaf - hdr xfs_dir2_leaf_hdr ; leaf header - ents xfs_dir2_leaf_entry ; entries -; bests dw ? ; best free counts -; tail xfs_dir2_leaf_tail ; leaf tail -ends - - -; header of 'free' block part -struct xfs_dir2_free_hdr - magic dd ? ; XFS_DIR2_FREE_MAGIC - firstdb dd ? ; db of first entry - nvalid dd ? ; count of valid entries - nused dd ? ; count of used entries -ends - - -; 'free' part of directiry block -struct xfs_dir2_free - hdr xfs_dir2_free_hdr ; block header - bests dw ? ; best free counts - ; unused entries are -1 (XFS_NULL) -ends - - -; b+tree node header -struct xfs_da_node_hdr - info xfs_da_blkinfo - count dw ? - level dw ? -ends - - -; b+tree node -struct xfs_da_node_entry - hashval dd ? ; hash value for this descendant - before dd ? ; Btree block before this key -ends - - -; -struct xfs_da_intnode - hdr xfs_da_node_hdr - btree xfs_da_node_entry -ends - - -; packet extent -struct xfs_bmbt_rec - l0 dq ? - l1 dq ? -ends - - -; unpacked extent -struct xfs_bmbt_irec - br_startoff dq ? ; starting file offset - br_startblock dq ? ; starting block number - br_blockcount dd ? ; number of blocks - br_state dd ? ; extent state -ends - - -; bmap root header, on-disk form only -struct xfs_bmdr_block - bb_level dw ? ; 0 is a leaf - bb_numrecs dw ? ; current number of data records -ends - - -; key structure for non-leaf levels of the tree -struct xfs_bmbt_key - br_startoff dq ? ; starting file offset -ends - - -sizeof.xfs_bmbt_ptr = 8 ; workaround -sizeof.xfs_bmdr_ptr = 8 ; workaround - - -; long form header: bmap btrees -; xfs_btree_lblock is xfs_bmbt_block (xfs_btree.h) -struct xfs_bmbt_block - bb_magic dd ? ; magic number for block type - bb_level dw ? ; 0 is a leaf - bb_numrecs dw ? ; current number of data records - bb_leftsib dq ? ; left sibling block or NULLDFSBNO - bb_rightsib dq ? ; right sibling block or NULLDFSBNO -ends - - -; high level inode structure -struct xfs_inode - di_core xfs_dinode_core ; main info, aka core - di_next_unlinked dd ? ; unlinked but still used inode (if any, XFS_NULL otherwise) - di_u db ? ; data fork inode part -; di_a db ? ; data attribute -ends - - -; internal data for every XFS partition -; this _is_ XFS partition structure -; most fields are unpacked or bswap'ed values from the superblock, so see xfs_sb structure above -struct XFS PARTITION - Lock MUTEX ? ; access mutex - blocksize dd ? - sectsize dd ? - dirblocksize dd ? - rootino dq ? - cur_block dd ? - cur_inode dd ? - cur_sect dd ? - cur_dirblock dd ? - tmp_inode dd ? - versionnum dd ? - features2 dd ? - inodesize dd ? - inopblock dd ? - blocklog dd ? - sectlog dd ? - inodelog dd ? - inopblog dd ? - agblklog dd ? - blockmsectlog dd ? - inodetoblocklog dd ? - dirblklog dd ? - sectpblock dd ? - agblocks dd ? - ; helpers, temporary vars, etc - agblockmask dq ? - extent xfs_bmbt_irec - left_extents dd ? - left_leaves dd ? - bytes_to_read dd ? - bytes_read dd ? - entries_read dd ? - file_offset dq ? - max_dirblockaddr dd ? - next_block_num dq ? - dir2_leaf_offset_blocks dd ? - dir2_free_offset_blocks dd ? - cur_inode_save dd ? - bytes_left_in_file dq ? - ro_nextents dd ? - bb_ptrs dd ? - maxnumrecs dd ? - buffer_pos dd ? - eof dd ? -ends