1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3 ;; Copyright (C) KolibriOS team 2013-2024. All rights reserved. ;;
4 ;; Distributed under terms of the GNU General Public License ;;
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
11 macro omit_frame_pointer_prologue procname
,flag
,parmbytes
,localbytes
,reglist
{
13 loc = (localbytes+3) and (not 3)
17 irps reg, reglist \{ push reg \}
19 irps reg
, reglist \
{counter = counter+1 \}
20 parmbase
@proc equ esp+counter
*4+loc
+4
21 localbase
@proc equ esp
24 macro omit_frame_pointer_epilogue procname
,flag
,parmbytes
,localbytes
,reglist
{
26 loc = (localbytes+3) and (not 3)
27 irps reg, reglist \{ reverse pop reg \}
38 prologue
@proc equ omit_frame_pointer_prologue
39 epilogue
@proc equ omit_frame_pointer_epilogue
41 macro movbe reg
, arg
{
46 if reg in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
63 ; This file contains XFS related code.
64 ; For more information on XFS check links and source below.
66 ; 1. https://xfs.wiki.kernel.org/
68 ; 2. XFS Algorithms & Data Structures:
69 ; git://git.kernel.org/pub/scm/fs/xfs/xfs-documentation.git
70 ; https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
72 ; 3. Linux source at https://www.kernel.org/
73 ; git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
81 dd (xfs._.user_functions_end
-xfs._.user_functions
-8)/4
88 xfs._.
user_functions_end:
91 ; test partition type (valid XFS one?)
92 ; alloc and fill XFS (see xfs.inc) structure
93 ; this function is called for each partition
94 ; return 0 (not XFS or invalid) / pointer to partition structure
95 proc xfs_create_partition uses
ebx esi edi
97 cmp [ebx+xfs_sb.sb_magicnum
], XFS_SB_MAGIC
99 ; test for supported feature flags and version in sb_versionnum
100 movzx eax, [ebx+xfs_sb.sb_versionnum
]
102 ; allow only known and supported features
103 ; return error otherwise
104 test eax, NOT XFS_SB_VERSION_SUPPORTED
106 ; version < 4 obsolete, not supported
107 ; version = 4,5 supported
108 ; version > 5 unknown
109 and al, XFS_SB_VERSION_NUMBITS
114 ; if MOREBITS bit is set, additional feature flags are in sb_features2
115 test eax, XFS_SB_VERSION_MOREBITSBIT
117 movbe
eax, [ebx+xfs_sb.sb_features2
]
118 test eax, NOT XFS_SB_VERSION2_SUPPORTED
121 movbe
eax, [ebx+xfs_sb.sb_features_incompat
]
122 test eax, NOT XFS_SB_FEAT_INCOMPAT_SUPPORTED
124 ; all presented features are either supported or don't affect reading
131 ; standard partition initialization, common for all file systems
132 mov eax, dword[ebp+PARTITION.FirstSector
+DQ.lo
]
133 mov dword[edi+XFS.FirstSector
+DQ.lo
], eax
134 mov eax, dword[ebp+PARTITION.FirstSector
+DQ.hi
]
135 mov dword[edi+XFS.FirstSector
+DQ.hi
], eax
136 mov eax, dword[ebp+PARTITION.
Length+DQ.lo
]
137 mov dword[edi+XFS.
Length+DQ.lo
], eax
138 mov eax, dword[ebp+PARTITION.
Length+DQ.hi
]
139 mov dword[edi+XFS.
Length+DQ.hi
], eax
140 mov eax, [ebp+PARTITION.Disk
]
141 mov [edi+XFS.Disk
], eax
142 mov [edi+XFS.FSUserFunctions
], xfs._.user_functions
143 ; here we initialize only one mutex (for the entire partition)
144 ; XFS potentially allows parallel r/w access to different AGs, keep it in mind
145 lea ecx, [edi+XFS.
Lock]
148 ; movzx eax, [ebx+xfs_sb.sb_sectsize]
150 mov eax, [eax+DISK.MediaInfo.SectorSize
]
151 mov [edi+XFS.sectsize
], eax
153 movbe
eax, [ebx+xfs_sb.sb_blocksize
]
154 mov [edi+XFS.blocksize
], eax
156 movzx eax, [ebx+xfs_sb.sb_versionnum
]
158 mov [edi+XFS.versionnum
], eax
159 and eax, XFS_SB_VERSION_NUMBITS
160 mov [edi+XFS.version
], eax
162 mov [edi+XFS.conv_time_to_kos_epoch
], xfs._.conv_time_to_kos_epoch
163 mov [edi+XFS.nextents_offset
], xfs_inode.di_core.di_nextents
165 movbe
eax, [ebx+xfs_sb.sb_features2
]
166 mov [edi+XFS.features2
], eax
167 cmp [edi+XFS.version
], 5
170 mov [edi+XFS.inode_core_size
], sizeof.xfs_dinode_core
171 test eax, XFS_SB_VERSION2_FTYPE
174 mov [edi+XFS.ftype_size
], eax
175 mov [edi+XFS.dir_block_magic
], XFS_DIR2_BLOCK_MAGIC
176 mov [edi+XFS.dir_data_magic
], XFS_DIR2_DATA_MAGIC
177 mov [edi+XFS.dir_leaf1_magic
], XFS_DIR2_LEAF1_MAGIC
178 mov [edi+XFS.dir_leafn_magic
], XFS_DIR2_LEAFN_MAGIC
179 mov [edi+XFS.da_node_magic
], XFS_DA_NODE_MAGIC
180 mov [edi+XFS.bmap_magic
], XFS_BMAP_MAGIC
181 mov [edi+XFS.dirx_leaf_ents_offset
], xfs_dir2_leaf.ents
182 mov [edi+XFS.dirx_leaf_hdr_count_offset
], xfs_dir2_leaf_hdr.count
183 mov [edi+XFS.dir_block_size
], sizeof.xfs_dir2_data_hdr
184 mov [edi+XFS.bmbt_block_size
], sizeof.xfs_bmbt_block
185 mov [edi+XFS.da_blkinfo_size
], sizeof.xfs_da_blkinfo
188 mov [edi+XFS.inode_core_size
], sizeof.xfs_dinode3_core
189 movbe
eax, [ebx+xfs_sb.sb_features_incompat
]
190 mov [edi+XFS.features_incompat
], eax
191 test eax, XFS_SB_FEAT_INCOMPAT_FTYPE
194 mov [edi+XFS.ftype_size
], eax
195 mov [edi+XFS.dir_block_magic
], XFS_DIR3_BLOCK_MAGIC
196 mov [edi+XFS.dir_data_magic
], XFS_DIR3_DATA_MAGIC
197 mov [edi+XFS.dir_leaf1_magic
], XFS_DIR3_LEAF1_MAGIC
198 mov [edi+XFS.dir_leafn_magic
], XFS_DIR3_LEAFN_MAGIC
199 mov [edi+XFS.da_node_magic
], XFS_DA3_NODE_MAGIC
200 mov [edi+XFS.bmap_magic
], XFS_BMAP3_MAGIC
201 mov [edi+XFS.dirx_leaf_ents_offset
], xfs_dir3_leaf.ents
202 mov [edi+XFS.dirx_leaf_hdr_count_offset
], xfs_dir3_leaf_hdr.count
203 mov [edi+XFS.dir_block_size
], sizeof.xfs_dir3_data_hdr
204 mov [edi+XFS.bmbt_block_size
], sizeof.xfs_bmbt3_block
205 mov [edi+XFS.da_blkinfo_size
], sizeof.xfs_da3_blkinfo
206 test [edi+XFS.features_incompat
], XFS_SB_FEAT_INCOMPAT_BIGTIME
208 mov [edi+XFS.conv_time_to_kos_epoch
], xfs._.conv_bigtime_to_kos_epoch
210 test [edi+XFS.features_incompat
], XFS_SB_FEAT_INCOMPAT_NREXT64
212 mov [edi+XFS.nextents_offset
], xfs_inode.di_core.di_big_nextents.lo_be
216 movzx eax, [ebx+xfs_sb.sb_inodesize
]
218 mov [edi+XFS.inodesize
], eax
220 movzx eax, [ebx+xfs_sb.sb_inopblock
]
222 mov [edi+XFS.inopblock
], eax
224 movzx eax, [ebx+xfs_sb.sb_blocklog
]
225 mov [edi+XFS.blocklog
], eax
227 ; movzx eax, [ebx+xfs_sb.sb_sectlog]
228 mov eax, [edi+XFS.sectsize
]
230 mov [edi+XFS.sectlog
], eax
232 movzx eax, [ebx+xfs_sb.sb_inodelog
]
233 mov [edi+XFS.inodelog
], eax
235 movzx eax, [ebx+xfs_sb.sb_inopblog
]
236 mov [edi+XFS.inopblog
], eax
238 movzx ecx, [ebx+xfs_sb.sb_dirblklog
]
239 mov [edi+XFS.dirblklog
], ecx
242 mov [edi+XFS.blkpdirblk
], eax
244 movbe
eax, [ebx+xfs_sb.sb_rootino.hi
]
245 mov [edi+XFS.rootino.lo
], eax
246 movbe
eax, [ebx+xfs_sb.sb_rootino.lo
]
247 mov [edi+XFS.rootino.hi
], eax
249 mov eax, [edi+XFS.blocksize
]
250 mov ecx, [edi+XFS.dirblklog
]
252 mov [edi+XFS.dirblocksize
], eax ; blocks are for files, dirblocks are for directories
254 ; sector is always smaller than block
255 ; so precalculate shift order to allow faster sector_num->block_num conversion
256 mov ecx, [edi+XFS.blocklog
]
257 sub ecx, [edi+XFS.sectlog
]
258 mov [edi+XFS.sectpblog
], ecx
262 mov [edi+XFS.sectpblock
], eax
264 movbe
eax, [ebx+xfs_sb.sb_agblocks
]
265 mov [edi+XFS.agblocks
], eax
267 movzx ecx, [ebx+xfs_sb.sb_agblklog
]
268 mov [edi+XFS.agblklog
], ecx
270 ; get the mask for block numbers
271 ; block numbers are AG relative!
272 ; bitfield length may vary between partitions
279 mov [edi+XFS.agblockmask.lo
], eax
280 mov [edi+XFS.agblockmask.hi
], edx
282 ; calculate magic offsets for directories
283 mov ecx, [edi+XFS.blocklog
]
284 mov eax, XFS_DIR2_LEAF_OFFSET
AND 0xffffffff ; lo
285 mov edx, XFS_DIR2_LEAF_OFFSET
SHR 32 ; hi
288 mov [edi+XFS.dir2_leaf_offset_blocks.lo
], eax
289 mov [edi+XFS.dir2_leaf_offset_blocks.hi
], edx
291 mov ecx, [edi+XFS.blocklog
]
292 mov eax, XFS_DIR2_FREE_OFFSET
AND 0xffffffff ; lo
293 mov edx, XFS_DIR2_FREE_OFFSET
SHR 32 ; hi
296 mov [edi+XFS.dir2_free_offset_blocks.lo
], eax
297 mov [edi+XFS.dir2_free_offset_blocks.hi
], edx
300 ; allocate memory for temp block, dirblock, inode, etc
301 mov eax, [edi+XFS.blocksize
]
303 mov [edi+XFS.cur_block
], eax
307 mov eax, [edi+XFS.blocksize
]
309 mov [edi+XFS.cur_block_data
], eax
313 ; we do need XFS.blocksize bytes for single inode
314 ; minimal file system structure is block, inodes are packed in blocks
315 mov eax, [edi+XFS.blocksize
]
317 mov [edi+XFS.cur_inode
], eax
321 mov eax, [edi+XFS.blocksize
]
325 mov [edi+XFS.tmp_inode
], eax
328 ; only for sector sized structures like AGF
329 ; inodes usually fit this size, but not always!
330 ; therefore never store inode here
331 mov eax, [edi+XFS.sectsize
]
333 mov [edi+XFS.cur_sect
], eax
337 mov eax, [edi+XFS.dirblocksize
]
339 mov [edi+XFS.cur_dirblock
], eax
344 ; return pointer to allocated XFS partition structure
356 ; lock partition access mutex
358 lea ecx, [ebp+XFS.
Lock]
362 ; unlock partition access mutex
364 lea ecx, [ebp+XFS.
Lock]
368 ; free all the allocated memory
369 ; called on partition destroy
370 ; or during failed initialization from xfs_create_partition
378 ; freeing order must correspond the order of
379 ; allocation in xfs_create_partition
380 mov eax, [ebx+XFS.cur_block
]
385 mov eax, [ebx+XFS.cur_block_data
]
390 mov eax, [ebx+XFS.cur_inode
]
395 mov eax, [ebx+XFS.tmp_inode
]
400 mov eax, [ebx+XFS.cur_sect
]
405 mov eax, [ebx+XFS.cur_dirblock
]
418 ;---------------------------------------------------------------
423 ;---------------------------------------------------------------
424 proc xfs._.read_block
426 call xfs._.read_blocks
431 proc xfs._.blkrel2sectabs uses
esi
434 ; XFS block numbers are AG relative
435 ; they come in bitfield form of concatenated AG and block numbers
436 ; to get absolute block number for fs_read64_sys we should
437 ; 1. get AG number and multiply it by the AG size in blocks
438 ; 2. extract and add AG relative block number
441 mov ecx, [ebp+XFS.agblklog
]
444 mul [ebp+XFS.agblocks
]
447 and ecx, [ebp+XFS.agblockmask.lo
]
448 and esi, [ebp+XFS.agblockmask.hi
]
452 mov ecx, [ebp+XFS.sectpblog
]
459 ;---------------------------------------------------------------
464 ;---------------------------------------------------------------
465 proc xfs._.read_blocks
467 call xfs._.blkrel2sectabs
469 imul
ecx, [ebp+XFS.sectpblock
]
476 proc xfs._.read_dirblock uses
ebx, _startblock:qword, _buffer
477 mov eax, dword[_startblock
+DQ.lo
]
478 mov edx, dword[_startblock
+DQ.hi
]
480 mov ecx, [ebp+XFS.blkpdirblk
]
481 call xfs._.read_blocks
486 ;---------------------------------------------------------------
488 ;---------------------------------------------------------------
489 proc xfs_read_inode uses
ebx, _inode_lo
, _inode_hi
, _buffer
493 ; inodes are packed into blocks
494 ; 1. calculate block number
496 ; 3. add inode offset to block base address
498 mov ecx, [ebp+XFS.inopblog
]
502 call xfs._.read_block
504 ; inode numbers should be first extracted from bitfields by mask
508 mov ecx, [ebp+XFS.inopblog
]
510 dec edx ; get inode number mask
511 and eax, edx ; apply mask
512 mov ecx, [ebp+XFS.inodelog
]
517 cmp [ebx+xfs_inode.di_core.di_magic
], XFS_DINODE_MAGIC
519 movi
eax, ERROR_FS_FAIL
527 ; skip ecx first entries
528 proc xfs._.dir_sf_skip _count
533 dec [ebp+XFS.entries_left_in_dir
]
536 bts [ebp+XFS.dir_sf_self_done
], 0
540 bts [ebp+XFS.dir_sf_parent_done
], 0
544 movzx eax, [esi+xfs_dir2_sf_entry.namelen
]
545 add esi, xfs_dir2_sf_entry.
name
547 add esi, [ebp+XFS.ftype_size
]
548 add esi, [ebp+XFS.shortform_inodelen
]
555 proc xfs._.dir_sf_read uses
edi, _count
562 dec [ebp+XFS.entries_left_in_dir
]
566 bts [ebp+XFS.dir_sf_self_done
], 0
568 lea edi, [edx+bdfe.
name]
570 stdcall xfs_get_inode_info
, [ebp+XFS.cur_inode
], edx
573 bts [ebp+XFS.dir_sf_parent_done
], 0
575 lea edi, [edx+bdfe.
name] ; get file name offset
576 mov dword[edi], '..' ; terminator included
578 lea edx, [ebx+xfs_dir2_sf.hdr.parent
]
579 call xfs._.get_inode_number_sf
580 stdcall xfs_read_inode
, eax, edx, [ebp+XFS.tmp_inode
]
583 stdcall xfs_get_inode_info
, edx, edi
586 movzx ecx, [esi+xfs_dir2_sf_entry.namelen
]
587 add esi, xfs_dir2_sf_entry.
name
588 lea edi, [edx+bdfe.
name]
589 stdcall xfs._.copy_filename
590 add esi, [ebp+XFS.ftype_size
]
593 call xfs._.get_inode_number_sf
594 stdcall xfs_read_inode
, eax, edx, [ebp+XFS.tmp_inode
]
597 stdcall xfs_get_inode_info
, edx, edi
598 add esi, [ebp+XFS.shortform_inodelen
]
601 mov eax, [ebp+XFS.bdfe_nameenc
]
602 mov [edx+bdfe.nameenc
], eax
603 add edx, [ebp+XFS.bdfe_len
]
604 inc [ebp+XFS.entries_read
]
613 proc xfs._.readdir_sf uses
esi, _src
, _dst
616 mov [ebp+XFS.dir_sf_self_done
], 0
617 mov [ebp+XFS.dir_sf_parent_done
], 0
618 mov [ebp+XFS.entries_read
], 0
619 movzx eax, [ebx+xfs_dir2_sf.hdr.count
]
620 ; '..' and '.' are implicit
622 mov [ebp+XFS.entries_left_in_dir
], eax
623 mov [edx+bdfe_hdr.total_cnt
], eax
624 ; inode numbers are often saved as 4 bytes (iff they fit)
625 ; compute the length of inode numbers
626 ; 8 iff i8count != 0, 4 otherwise
627 cmp [ebx+xfs_dir2_sf.hdr.i8count
], 0
630 mov [ebp+XFS.shortform_inodelen
], eax
631 add edx, sizeof.bdfe_hdr
632 lea esi, [ebx+xfs_dir2_sf.hdr.parent
+eax]
633 stdcall xfs._.dir_sf_skip
, [ebp+XFS.entries_to_skip
]
634 stdcall xfs._.dir_sf_read
, [ebp+XFS.requested_cnt
]
639 proc xfs._.readdir_block _literal_area
, _out_buf
640 mov ebx, [_literal_area
]
641 mov [ebp+XFS.entries_read
], 0
643 mov ebx, [ebp+XFS.cur_dirblock
]
644 stdcall xfs._.extent_unpack
, eax
645 stdcall xfs._.read_dirblock
, [ebp+XFS.extent.br_startblock.lo
], [ebp+XFS.extent.br_startblock.hi
], ebx
648 mov eax, [ebp+XFS.dir_block_magic
]
649 cmp [ebx+xfs_dir2_block.hdr.magic
], eax
650 movi
eax, ERROR_FS_FAIL
652 mov eax, [ebp+XFS.dirblocksize
]
653 movbe
ecx, [ebx+eax-sizeof.xfs_dir2_block_tail
+xfs_dir2_block_tail.stale
]
654 movbe
eax, [ebx+eax-sizeof.xfs_dir2_block_tail
+xfs_dir2_block_tail.count
]
655 sub eax, ecx ; actual number of entries = count - stale
656 mov [ebp+XFS.entries_left_in_dir
], eax
657 mov [edx+bdfe_hdr.total_cnt
], eax
659 add ebx, [ebp+XFS.dir_block_size
]
660 add edx, sizeof.bdfe_hdr
664 movi
eax, ERROR_SUCCESS
665 cmp [ebp+XFS.requested_cnt
], 0
667 cmp [ebp+XFS.entries_left_in_dir
], 0
669 stdcall xfs._.dir_entry_skip_read
, edi
677 proc xfs._.readdir_leaf_node uses
esi, _inode_data
, _out_buf
678 mov ebx, [_inode_data
]
680 mov [ebp+XFS.cur_inode_save
], ebx
681 mov [ebp+XFS.entries_read
], 0
683 add eax, [ebp+XFS.inode_core_size
]
684 mov edx, [ebp+XFS.nextents_offset
]
686 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo
]
687 mov [ebp+XFS.offset_begin.lo
], ecx
688 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi
]
689 mov [ebp+XFS.offset_begin.hi
], ecx
690 mov ecx, [ebp+XFS.dir2_free_offset_blocks.lo
]
691 mov [ebp+XFS.offset_end.lo
], ecx
692 mov ecx, [ebp+XFS.dir2_free_offset_blocks.hi
]
693 mov [ebp+XFS.offset_end.hi
], ecx
694 stdcall xfs._.walk_extent_list
, edx, eax, xfs._.extent_iterate_dirblocks
, xfs._.leafn_calc_entries
, 0
696 mov eax, [ebp+XFS.entries_read
]
698 mov [edx+bdfe_hdr.total_cnt
], eax
699 mov [ebp+XFS.entries_left_in_dir
], eax
700 add [_out_buf
], sizeof.bdfe_hdr
701 mov [ebp+XFS.entries_read
], 0
702 mov edx, [ebp+XFS.nextents_offset
]
705 add eax, [ebp+XFS.inode_core_size
]
708 mov [ebp+XFS.offset_begin.lo
], 0
709 mov [ebp+XFS.offset_begin.hi
], 0
710 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo
]
711 mov [ebp+XFS.offset_end.lo
], ecx
712 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi
]
713 mov [ebp+XFS.offset_end.hi
], ecx
715 stdcall xfs._.walk_extent_list
, edx, eax, xfs._.extent_iterate_dirblocks
, xfs._.dir_btree_skip_read
, ecx
723 proc xfs._.dir_entry_skip_read uses
esi edi, _arg
724 cmp [ebx+xfs_dir2_data_union.unused.freetag
], XFS_NULL
726 movzx eax, [ebx+xfs_dir2_data_union.unused.
length]
731 cmp [ebp+XFS.entries_to_skip
], 0
734 dec [ebp+XFS.entries_to_skip
]
735 movzx ecx, [ebx+xfs_dir2_data_union.xentry.namelen
]
736 lea ebx, [ebx+xfs_dir2_data_union.xentry.
name+ecx+2]
737 add ebx, [ebp+XFS.ftype_size
]
740 dec [ebp+XFS.requested_cnt
]
741 inc [ebp+XFS.entries_read
]
744 movbe
edx, [ebx+xfs_dir2_data_union.xentry.inumber.lo
]
745 movbe
eax, [ebx+xfs_dir2_data_union.xentry.inumber.hi
]
746 stdcall xfs_read_inode
, eax, edx, [ebp+XFS.tmp_inode
]
747 stdcall xfs_get_inode_info
, edx, edi
751 mov ecx, [ebp+XFS.bdfe_nameenc
]
752 mov [edx+bdfe.nameenc
], ecx
753 lea edi, [edx+bdfe.
name]
754 movzx ecx, [ebx+xfs_dir2_data_union.xentry.namelen
]
755 lea esi, [ebx+xfs_dir2_data_union.xentry.
name]
756 stdcall xfs._.copy_filename
757 lea ebx, [esi+2] ; skip 'tag'
758 add ebx, [ebp+XFS.ftype_size
]
761 add edx, [ebp+XFS.bdfe_len
]
764 sub ebx, [ebp+XFS.cur_dirblock
]
765 add ebx, 7 ; xfs_dir2_data_entries are aligned to 8 bytes
767 add ebx, [ebp+XFS.cur_dirblock
]
768 dec [ebp+XFS.entries_left_in_dir
]
770 movi
eax, ERROR_SUCCESS
777 proc xfs._.dir_btree_skip_read uses
ebx ecx edx esi edi, _cur_dirblock
, _offset_lo
, _offset_hi
, _arg
778 mov ebx, [_cur_dirblock
]
779 mov eax, [ebp+XFS.dir_data_magic
]
780 cmp [ebx+xfs_dir2_block.hdr.magic
], eax
781 movi
eax, ERROR_FS_FAIL
784 add eax, [ebp+XFS.dirblocksize
]
785 mov [ebp+XFS.max_dirblockaddr
], eax
786 add ebx, [ebp+XFS.dir_block_size
]
788 movi
eax, ERROR_SUCCESS
789 cmp [ebp+XFS.requested_cnt
], 0
791 cmp [ebp+XFS.entries_left_in_dir
], 0
793 cmp ebx, [ebp+XFS.max_dirblockaddr
]
795 stdcall xfs._.dir_entry_skip_read
, [_arg
]
803 proc xfs._.readdir_btree uses
esi, _inode_data
, _out_buf
804 mov [ebp+XFS.cur_inode_save
], ebx
805 mov [ebp+XFS.entries_read
], 0
806 mov eax, [ebp+XFS.inodesize
]
807 sub eax, [ebp+XFS.inode_core_size
]
808 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff
]
814 add edx, [ebp+XFS.inode_core_size
]
815 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo
]
816 mov [ebp+XFS.offset_begin.lo
], ecx
817 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi
]
818 mov [ebp+XFS.offset_begin.hi
], ecx
819 mov ecx, [ebp+XFS.dir2_free_offset_blocks.lo
]
820 mov [ebp+XFS.offset_end.lo
], ecx
821 mov ecx, [ebp+XFS.dir2_free_offset_blocks.hi
]
822 mov [ebp+XFS.offset_end.hi
], ecx
823 stdcall xfs._.walk_btree
, edx, eax, xfs._.extent_iterate_dirblocks
, xfs._.leafn_calc_entries
, 0, 1
824 mov eax, [ebp+XFS.entries_read
]
826 mov [edx+bdfe_hdr.total_cnt
], eax
827 mov [ebp+XFS.entries_left_in_dir
], eax
828 mov [ebp+XFS.entries_read
], 0
829 add [_out_buf
], sizeof.bdfe_hdr
830 mov eax, [ebp+XFS.inodesize
]
831 sub eax, [ebp+XFS.inode_core_size
]
832 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff
]
838 add edx, [ebp+XFS.inode_core_size
]
839 mov [ebp+XFS.offset_begin.lo
], 0
840 mov [ebp+XFS.offset_begin.hi
], 0
841 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo
]
842 mov [ebp+XFS.offset_end.lo
], ecx
843 mov ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi
]
844 mov [ebp+XFS.offset_end.hi
], ecx
848 stdcall xfs._.walk_btree
, edx, eax, xfs._.extent_iterate_dirblocks
, xfs._.dir_btree_skip_read
, ecx, 1
856 proc xfs._.copy_filename uses
eax
857 mov eax, [ebp+XFS.bdfe_nameenc
]
863 call unicode.utf8.decode
864 call unicode.cp866.encode
871 call unicode.utf8.decode
872 call unicode.utf16.encode
889 ;----------------------------------------------------------------
892 ; start_number ; from 0
893 ;----------------------------------------------------------------
894 proc xfs._.readdir uses
ebx esi edi, _start_number
, _entries_to_read
, _dst
, _src
, _encoding
895 mov ecx, [_start_number
]
896 mov [ebp+XFS.entries_to_skip
], ecx
897 mov eax, [_entries_to_read
]
898 mov [ebp+XFS.requested_cnt
], eax
900 mov [ebp+XFS.bdfe_nameenc
], eax
906 mov [ebp+XFS.bdfe_len
], ecx
908 mov [ebp+XFS.bdfe_buf
], edx
910 mov [ebp+XFS.cur_inode_save
], ebx
912 mov [edx+bdfe_hdr.version
], 1
913 mov [edx+bdfe_hdr.zeroed
+0x00], 0
914 mov [edx+bdfe_hdr.zeroed
+0x04], 0
915 mov [edx+bdfe_hdr.zeroed
+0x08], 0
916 mov [edx+bdfe_hdr.zeroed
+0x0c], 0
917 mov [edx+bdfe_hdr.zeroed
+0x10], 0
919 movzx eax, [ebx+xfs_inode.di_core.di_format
]
920 ; switch directory ondisk format and jump to corresponding label
921 cmp eax, XFS_DINODE_FMT_LOCAL
923 add ebx, [ebp+XFS.inode_core_size
]
924 stdcall xfs._.readdir_sf
, ebx, [_dst
]
929 cmp eax, XFS_DINODE_FMT_BTREE
931 stdcall xfs._.readdir_btree
, ebx, [_dst
]
934 cmp eax, XFS_DINODE_FMT_EXTENTS
935 movi
eax, ERROR_FS_FAIL
937 call xfs._.get_last_dirblock
940 add ebx, [ebp+XFS.inode_core_size
]
941 stdcall xfs._.readdir_block
, ebx, [_dst
]
944 stdcall xfs._.readdir_leaf_node
, ebx, [_dst
]
948 mov ebx, [ebp+XFS.entries_read
]
949 mov [edx+bdfe_hdr.read_cnt
], ebx
956 ; returns edx:eax inode or 0
957 proc xfs._.lookup_sf _name
, _len
958 add ebx, [ebp+XFS.inode_core_size
]
967 mov eax, [ebp+XFS.inode_self.lo
]
968 mov edx, [ebp+XFS.inode_self.hi
]
973 lea edx, [ebx+xfs_dir2_sf.hdr.parent
]
974 call xfs._.get_inode_number_sf
977 movzx edx, [ebx+xfs_dir2_sf.hdr.count
]
979 cmp [ebx+xfs_dir2_sf.hdr.i8count
], 0
982 lea edi, [ebx+xfs_dir2_sf.hdr.parent
+eax]
986 movi
eax, ERROR_FILE_NOT_FOUND
989 movzx ecx, [edi+xfs_dir2_sf_entry.namelen
]
990 add edi, xfs_dir2_sf_entry.
name
997 add edi, [ebp+XFS.ftype_size
]
1002 add edi, [ebp+XFS.ftype_size
]
1004 call xfs._.get_inode_number_sf
1012 proc xfs._.lookup_block uses
esi, _name
, _len
1013 add ebx, [ebp+XFS.inode_core_size
]
1015 mov ebx, [ebp+XFS.cur_dirblock
]
1016 stdcall xfs._.extent_unpack
, eax
1017 stdcall xfs._.read_dirblock
, [ebp+XFS.extent.br_startblock.lo
], \
1018 [ebp+XFS.extent.br_startblock.hi
], ebx
1020 mov eax, [ebp+XFS.dir_block_magic
]
1021 cmp [ebx+xfs_dir2_block.hdr.magic
], eax
1022 movi
eax, ERROR_FS_FAIL
1024 stdcall xfs_hashname
, [_name
+4], [_len
]
1025 add ebx, [ebp+XFS.dirblocksize
]
1026 movbe
ecx, [ebx-sizeof.xfs_dir2_block_tail
+xfs_dir2_block_tail.count
]
1027 lea edx, [ecx*sizeof.xfs_dir2_leaf_entry
+sizeof.xfs_dir2_block_tail
]
1029 stdcall xfs._.get_addr_by_hash
, ebx, ecx
1031 mov ebx, [ebp+XFS.cur_dirblock
]
1032 movbe
edx, [ebx+eax*XFS_DIR2_DATA_ALIGN
+xfs_dir2_data_entry.inumber.lo
]
1033 movbe
eax, [ebx+eax*XFS_DIR2_DATA_ALIGN
+xfs_dir2_data_entry.inumber.hi
]
1040 proc xfs._.get_inode_by_addr uses
ebx esi edi, _inode_buf
1042 shld edx, eax, XFS_DIR2_DATA_ALIGN_LOG
1043 shl eax, XFS_DIR2_DATA_ALIGN_LOG
1044 mov esi, [ebp+XFS.dirblocksize
]
1047 mov ecx, [ebp+XFS.blocklog
]
1048 add ecx, [ebp+XFS.dirblklog
]
1051 mov ecx, [ebp+XFS.dirblklog
]
1054 mov ebx, [_inode_buf
]
1055 cmp [ebx+xfs_inode.di_core.di_format
], XFS_DINODE_FMT_EXTENTS
1057 cmp [ebx+xfs_inode.di_core.di_format
], XFS_DINODE_FMT_BTREE
1061 mov ecx, [ebp+XFS.nextents_offset
]
1062 movbe
ecx, [ebx+ecx]
1063 add ebx, [ebp+XFS.inode_core_size
]
1064 mov [ebp+XFS.offset_begin.lo
], eax
1065 mov [ebp+XFS.offset_begin.hi
], edx
1066 stdcall xfs._.extent_list.seek
, ecx
1067 stdcall xfs._.read_dirblock
, [ebp+XFS.extent.br_startblock.lo
], [ebp+XFS.extent.br_startblock.hi
], [ebp+XFS.cur_dirblock
]
1071 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff
]
1075 mov ecx, [ebp+XFS.inodesize
]
1076 sub ecx, [ebp+XFS.inode_core_size
]
1078 add ebx, [ebp+XFS.inode_core_size
]
1079 stdcall xfs._.btree_read_block
, ebx, ecx, eax, edx, [ebp+XFS.cur_dirblock
]
1081 mov ebx, [ebp+XFS.cur_dirblock
]
1082 mov eax, [ebp+XFS.dir_data_magic
]
1083 cmp [ebx+xfs_dir2_block.hdr.magic
], eax
1084 movi
eax, ERROR_FS_FAIL
1086 movbe
edx, [ebx+esi+xfs_dir2_data_entry.inumber.lo
]
1087 movbe
eax, [ebx+esi+xfs_dir2_data_entry.inumber.hi
]
1094 proc xfs._.lookup_leaf uses
ebx esi edi, _name
, _len
1095 mov ecx, [ebp+XFS.nextents_offset
]
1096 movbe
ecx, [ebx+ecx]
1097 add ebx, [ebp+XFS.inode_core_size
]
1098 mov eax, [ebp+XFS.dir2_leaf_offset_blocks.lo
]
1099 mov [ebp+XFS.offset_begin.lo
], ecx
1100 mov eax, [ebp+XFS.dir2_leaf_offset_blocks.hi
]
1101 mov [ebp+XFS.offset_begin.hi
], ecx
1102 stdcall xfs._.extent_list.seek
, ecx
1103 stdcall xfs._.read_dirblock
, [ebp+XFS.extent.br_startblock.lo
], \
1104 [ebp+XFS.extent.br_startblock.hi
], [ebp+XFS.cur_dirblock
]
1106 mov ebx, [ebp+XFS.cur_dirblock
]
1107 movzx eax, [ebp+XFS.dir_leaf1_magic
]
1108 cmp [ebx+xfs_dir2_leaf.hdr.info.magic
], ax
1109 movi
eax, ERROR_FS_FAIL
1111 stdcall xfs_hashname
, [_name
+4], [_len
]
1112 cmp [ebp+XFS.version
], 5
1115 movzx ecx, [ebx+xfs_dir2_leaf.hdr.count
]
1117 add ebx, xfs_dir2_leaf.ents
1120 movzx ecx, [ebx+xfs_dir3_leaf.hdr.count
]
1122 add ebx, xfs_dir3_leaf.ents
1124 stdcall xfs._.get_addr_by_hash
, ebx, ecx
1126 stdcall xfs._.get_inode_by_addr
, [ebp+XFS.cur_inode_save
]
1133 proc xfs._.lookup_node uses
ebx esi edi, _name
, _len
1137 mov [ebp+XFS.cur_inode_save
], ebx
1138 stdcall xfs_hashname
, [_name
+4], [_len
]
1140 mov edx, [ebp+XFS.nextents_offset
]
1141 movbe
edx, [ebx+edx]
1142 mov esi, [ebp+XFS.dir2_leaf_offset_blocks.lo
]
1144 mov ebx, [ebp+XFS.cur_inode_save
]
1146 add eax, [ebp+XFS.inode_core_size
]
1147 mov edx, [ebp+XFS.nextents_offset
]
1148 movbe
edx, [ebx+edx]
1150 mov [ebp+XFS.offset_begin.lo
], esi
1151 mov [ebp+XFS.offset_begin.hi
], 0
1152 stdcall xfs._.extent_list.seek
, edx
1153 stdcall xfs._.read_dirblock
, [ebp+XFS.extent.br_startblock.lo
], [ebp+XFS.extent.br_startblock.hi
], [ebp+XFS.cur_dirblock
]
1155 mov ebx, [ebp+XFS.cur_dirblock
]
1156 movzx eax, [ebp+XFS.da_node_magic
]
1157 cmp [ebx+xfs_da_intnode.hdr.info.magic
], ax
1159 movzx eax, [ebp+XFS.dir_leafn_magic
]
1160 cmp [ebx+xfs_dir2_leaf.hdr.info.magic
], ax
1162 movi
eax, ERROR_FS_FAIL
1165 cmp [ebp+XFS.version
], 5
1168 lea eax, [ebx+sizeof.xfs_da_intnode
]
1169 movzx edx, [ebx+xfs_da_intnode.hdr.count
]
1172 lea eax, [ebx+sizeof.xfs_da3_intnode
]
1173 movzx edx, [ebx+xfs_da3_intnode.hdr.count
]
1176 stdcall xfs._.get_before_by_hashval
, eax, edx, [.hash
]
1181 cmp [ebp+XFS.version
], 5
1184 movzx ecx, [ebx+xfs_dir2_leaf.hdr.count
]
1186 add ebx, xfs_dir2_leaf.ents
1189 movzx ecx, [ebx+xfs_dir3_leaf.hdr.count
]
1191 add ebx, xfs_dir3_leaf.ents
1194 stdcall xfs._.get_addr_by_hash
, ebx, ecx
1196 stdcall xfs._.get_inode_by_addr
, [ebp+XFS.cur_inode_save
]
1206 proc xfs._.lookup_btree uses
ebx esi edi, _name
, _len
1210 mov [ebp+XFS.cur_inode_save
], ebx
1211 stdcall xfs_hashname
, [_name
+4], [_len
]
1213 mov edx, [ebp+XFS.dir2_leaf_offset_blocks.hi
]
1214 mov eax, [ebp+XFS.dir2_leaf_offset_blocks.lo
]
1215 jmp .next_level.first
1217 lea eax, [ebx+sizeof.xfs_da_intnode
]
1218 movzx edx, [ebx+xfs_da_intnode.hdr.count
]
1220 stdcall xfs._.get_before_by_hashval
, eax, edx, [.hash
]
1224 mov ebx, [ebp+XFS.cur_inode_save
]
1225 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff
]
1229 mov ecx, [ebp+XFS.inodesize
]
1230 sub ecx, [ebp+XFS.inode_core_size
]
1232 add ebx, [ebp+XFS.inode_core_size
]
1233 stdcall xfs._.btree_read_block
, ebx, ecx, eax, edx, [ebp+XFS.cur_dirblock
]
1234 mov ebx, [ebp+XFS.cur_dirblock
]
1235 movzx eax, [ebp+XFS.da_node_magic
]
1236 cmp [ebx+xfs_da_blkinfo.magic
], ax
1238 movzx eax, [ebp+XFS.dir_leafn_magic
]
1239 cmp [ebx+xfs_da_blkinfo.magic
], ax
1241 movzx eax, [ebp+XFS.dir_leaf1_magic
]
1242 cmp [ebx+xfs_da_blkinfo.magic
], ax
1245 mov ecx, [ebp+XFS.dirx_leaf_hdr_count_offset
]
1246 movzx ecx, word[ebx+ecx]
1248 add ebx, [ebp+XFS.dirx_leaf_ents_offset
]
1249 stdcall xfs._.get_addr_by_hash
, ebx, ecx
1251 mov ebx, [ebp+XFS.cur_dirblock
]
1254 mov ecx, [ebp+XFS.dirx_leaf_hdr_count_offset
]
1255 movzx ecx, word[ebx+ecx]
1257 add ebx, [ebp+XFS.dirx_leaf_ents_offset
]
1259 stdcall xfs._.get_addr_by_hash
, ebx, ecx
1261 mov ebx, [ebp+XFS.cur_block
]
1263 stdcall xfs._.get_inode_by_addr
, [ebp+XFS.cur_inode_save
]
1273 ; search for the _name in _inode dir
1274 ; called for each /path/component/to/my/file
1277 ; edx:eax = inode/garbage:error
1278 proc xfs._.get_inode_short uses
esi, _inode:qword, _len
, _name
1280 mov eax, dword[_inode
+DQ.lo
]
1281 mov edx, dword[_inode
+DQ.hi
]
1282 stdcall xfs_read_inode
, eax, edx, [ebp+XFS.cur_inode
]
1284 movi
eax, ERROR_FS_FAIL
1286 ; switch directory ondisk format
1288 mov [ebp+XFS.cur_inode_save
], ebx
1289 movzx eax, [ebx+xfs_inode.di_core.di_format
]
1290 cmp eax, XFS_DINODE_FMT_LOCAL
1291 mov edi, xfs._.lookup_sf
1293 cmp eax, XFS_DINODE_FMT_BTREE
1294 mov edi, xfs._.lookup_btree
1296 cmp eax, XFS_DINODE_FMT_EXTENTS
1298 call xfs._.get_last_dirblock
1300 mov edi, xfs._.lookup_block
1302 cmp edx, [ebp+XFS.dir2_free_offset_blocks.hi
]
1303 mov edi, xfs._.lookup_node
1305 cmp eax, [ebp+XFS.dir2_free_offset_blocks.lo
]
1307 mov edi, xfs._.lookup_leaf
1309 stdcall
edi, [_name
+4], [_len
]
1316 ; edx:eax = inode/garbage:error
1317 proc xfs_get_inode uses
ebx esi edi, _name
1318 ; call *._.get_inode_short until file is found / error returned
1319 ; start from the root inode
1320 mov eax, [ebp+XFS.rootino.lo
]
1321 mov edx, [ebp+XFS.rootino.hi
]
1344 mov [ebp+XFS.inode_self.lo
], eax
1345 mov [ebp+XFS.inode_self.hi
], edx
1346 stdcall xfs._.get_inode_short
, eax, edx, ecx ; esi pushed above
1354 ; in: ebp = pointer to XFS structure
1356 ; in: ebx = pointer to parameters from sysfunc 70
1357 ; out: eax, ebx = return values for sysfunc 70
1358 ; out: [edx] -- f70.1 out structure
1359 proc xfs_ReadFolder uses
esi edi
1361 stdcall xfs_get_inode
, esi
1363 stdcall xfs_read_inode
, eax, edx, [ebp+XFS.cur_inode
]
1366 stdcall xfs._.readdir
, [ebx+f70s1arg.start_idx
], [ebx+f70s1arg.count
], [ebx+f70s1arg.buf
], edx, [ebx+f70s1arg.encoding
]
1369 mov edx, [ebx+f70s1arg.buf
]
1370 mov ecx, [ebx+f70s1arg.count
]
1371 cmp [edx+bdfe_hdr.read_cnt
], ecx
1373 movi
eax, ERROR_END_OF_FILE
1375 mov ebx, [edx+bdfe_hdr.read_cnt
]
1385 ; edx -- pointer to inode number in big endian
1386 ; ZF -- must be set at exit
1387 proc xfs._.get_inode_number_sf
1388 cmp [ebx+xfs_dir2_sf.hdr.i8count
], 0
1391 movbe
eax, [edx+DQ.hi
]
1392 movbe
edx, [edx+DQ.lo
]
1395 movbe
eax, [edx+DQ.lo
]
1400 proc xfs._.conv_time_to_kos_epoch
1401 movbe
eax, [ecx+DQ.hi_be
]
1406 proc xfs._.conv_bigtime_to_kos_epoch
1407 NANOSEC_PER_SEC
= 1_000_000_000
1408 BIGTIME_TO_UNIX_OFFSET
= 0x80000000 ; int32 min
1409 UNIXTIME_TO_KOS_OFFSET
= (365*31+8)*24*60*60 ; 01.01.1970--01.01.2001
1410 BIGTIME_TO_KOS_OFFSET
= BIGTIME_TO_UNIX_OFFSET
+ UNIXTIME_TO_KOS_OFFSET
1411 BIGTIME_TO_KOS_OFFSET_NS
= BIGTIME_TO_KOS_OFFSET
* NANOSEC_PER_SEC
1412 movbe
edx, [ecx+DQ.hi_be
]
1413 movbe
eax, [ecx+DQ.lo_be
]
1414 sub eax, BIGTIME_TO_KOS_OFFSET_NS
AND 0xffffffff
1415 sbb edx, BIGTIME_TO_KOS_OFFSET_NS
SHR 32
1416 jnc .after_kos_epoch_begin
1417 xor eax, eax ; set to very begin of kolibrios epoch
1420 .
after_kos_epoch_begin:
1421 cmp edx, NANOSEC_PER_SEC
1423 mov edx, NANOSEC_PER_SEC
- 1
1424 mov eax, -1 ; very end of kolibrios epoch
1426 mov ecx, NANOSEC_PER_SEC
1432 proc xfs_get_inode_info uses
ebx esi edi, _src
, _dst
1433 ; get access time and other file properties
1434 ; useful for browsing directories
1435 ; called for each dir entry
1438 movzx ecx, [esi+xfs_inode.di_core.di_mode
]
1442 movi
eax, 0x10 ; set directory flag
1445 mov [edi+bdfe.attr
], eax
1446 movbe
edx, [esi+xfs_inode.di_core.di_size.hi_be
]
1447 movbe
eax, [esi+xfs_inode.di_core.di_size.lo_be
]
1448 mov [edi+bdfe.
size.hi
], edx
1449 mov [edi+bdfe.
size.lo
], eax
1452 lea ecx, [esi+xfs_inode.di_core.di_ctime
]
1453 call [ebp+XFS.conv_time_to_kos_epoch
]
1454 lea ecx, [esi+xfs_inode.di_core.di_atime
]
1455 call [ebp+XFS.conv_time_to_kos_epoch
]
1456 lea ecx, [esi+xfs_inode.di_core.di_mtime
]
1457 call [ebp+XFS.conv_time_to_kos_epoch
]
1459 movi
eax, ERROR_SUCCESS
1465 proc xfs._.extent_unpack uses
eax ebx ecx edx, _extent_data
1466 ; extents come as packed 128bit bitfields
1467 ; unpack them to access internal fields
1468 ; write result to the XFS.extent structure
1469 mov ebx, [_extent_data
]
1473 test edx, 0x80000000 ; mask, see documentation
1475 mov [ebp+XFS.extent.br_state
], eax
1477 and edx, 0x7fffffff ; mask
1481 mov [ebp+XFS.extent.br_startoff.lo
], eax
1482 mov [ebp+XFS.extent.br_startoff.hi
], edx
1487 and edx, 0x000001ff ; mask
1490 mov [ebp+XFS.extent.br_startblock.lo
], ecx
1491 mov [ebp+XFS.extent.br_startblock.hi
], eax
1494 and eax, 0x001fffff ; mask
1495 mov [ebp+XFS.extent.br_blockcount
], eax
1500 proc xfs_hashname uses
ecx esi, _name
, _len
1515 proc xfs._.get_addr_by_hash uses
ebx esi, _base
, _len
1516 ; look for the directory entry offset by its file name hash
1517 ; allows fast file search for block, leaf and node directories
1518 ; binary (ternary) search
1527 movbe
esi, [ebx+ecx*sizeof.xfs_dir2_leaf_entry
+xfs_dir2_leaf_entry.hashval
]
1531 movbe
eax, [ebx+ecx*sizeof.xfs_dir2_leaf_entry
+xfs_dir2_leaf_entry.address
]
1537 lea ebx, [ebx+(ecx+1)*sizeof.xfs_dir2_leaf_entry
]
1542 movi
eax, ERROR_FILE_NOT_FOUND
1548 ;----------------------------------------------------------------
1549 ; xfs_GetFileInfo: XFS implementation of getting file info
1550 ; in: ebp = pointer to XFS structure
1552 ; in: ebx = pointer to parameters from sysfunc 70
1553 ; out: eax, ebx = return values for sysfunc 70
1554 ;----------------------------------------------------------------
1555 proc xfs_GetFileInfo uses
ecx edx esi edi
1557 stdcall xfs_get_inode
, esi
1559 stdcall xfs_read_inode
, eax, edx, [ebp+XFS.cur_inode
]
1561 movi
eax, ERROR_FS_FAIL
1563 stdcall xfs_get_inode_info
, edx, [ebx+f70s5arg.buf
]
1576 proc xfs._.file.read_extent uses
ebx ecx edx, _callback
, _callback_data
1577 mov eax, [ebp+XFS.file_offset.lo
]
1578 mov edx, [ebp+XFS.file_offset.hi
]
1579 mov esi, [ebp+XFS.extent.br_startoff.lo
]
1580 mov edi, [ebp+XFS.extent.br_startoff.hi
]
1581 mov ecx, [ebp+XFS.blocklog
]
1598 cmp ecx, [ebp+XFS.bytes_to_read
]
1600 mov ecx, [ebp+XFS.bytes_to_read
]
1602 mov edi, [ebp+XFS.file_buffer
]
1604 sub [ebp+XFS.bytes_to_read
], ecx
1605 sub [ebp+XFS.bytes_left_in_file.lo
], ecx
1606 sbb [ebp+XFS.bytes_left_in_file.hi
], 0
1607 add [ebp+XFS.bytes_read
], ecx
1608 add [ebp+XFS.file_buffer
], ecx
1609 add [ebp+XFS.file_offset.lo
], ecx
1610 adc [ebp+XFS.file_offset.hi
], 0
1612 cmp [ebp+XFS.bytes_to_read
], 0
1616 mov eax, [ebp+XFS.file_offset.lo
]
1617 mov ecx, [ebp+XFS.blocksize
]
1622 mov eax, [ebp+XFS.extent.br_startblock.lo
]
1623 mov edx, [ebp+XFS.extent.br_startblock.hi
]
1624 mov ebx, [ebp+XFS.cur_block_data
]
1625 stdcall xfs._.read_block
1626 mov esi, [ebp+XFS.cur_block_data
]
1627 mov edi, [ebp+XFS.file_buffer
]
1628 mov eax, [ebp+XFS.file_offset.lo
]
1629 mov ecx, [ebp+XFS.blocksize
]
1635 cmp ecx, [ebp+XFS.bytes_to_read
]
1637 mov ecx, [ebp+XFS.bytes_to_read
]
1639 sub [ebp+XFS.bytes_to_read
], ecx
1640 sub [ebp+XFS.bytes_left_in_file.lo
], ecx
1641 sbb [ebp+XFS.bytes_left_in_file.hi
], 0
1642 add [ebp+XFS.bytes_read
], ecx
1643 add [ebp+XFS.file_buffer
], ecx
1644 add [ebp+XFS.file_offset.lo
], ecx
1645 adc [ebp+XFS.file_offset.hi
], 0
1647 add [ebp+XFS.extent.br_startoff.lo
], 1
1648 adc [ebp+XFS.extent.br_startoff.hi
], 0
1649 add [ebp+XFS.extent.br_startblock.lo
], 1
1650 adc [ebp+XFS.extent.br_startblock.hi
], 0
1651 dec [ebp+XFS.extent.br_blockcount
]
1652 ; cmp [ebp+XFS.bytes_to_read], 0
1655 mov eax, [ebp+XFS.bytes_to_read
]
1658 cmp eax, [ebp+XFS.blocksize
]
1660 mov ecx, [ebp+XFS.blocklog
]
1662 cmp eax, [ebp+XFS.extent.br_blockcount
]
1664 mov eax, [ebp+XFS.extent.br_blockcount
]
1667 mov eax, [ebp+XFS.extent.br_startblock.lo
]
1668 mov edx, [ebp+XFS.extent.br_startblock.hi
]
1669 mov ebx, [ebp+XFS.file_buffer
]
1671 stdcall xfs._.read_blocks
1673 add [ebp+XFS.extent.br_startoff.lo
], eax
1674 adc [ebp+XFS.extent.br_startoff.hi
], 0
1675 add [ebp+XFS.extent.br_startblock.lo
], eax
1676 adc [ebp+XFS.extent.br_startblock.hi
], 0
1677 sub [ebp+XFS.extent.br_blockcount
], eax
1678 imul
eax, [ebp+XFS.blocksize
]
1679 sub [ebp+XFS.bytes_to_read
], eax
1680 sub [ebp+XFS.bytes_left_in_file.lo
], eax
1681 sbb [ebp+XFS.bytes_left_in_file.hi
], 0
1682 add [ebp+XFS.bytes_read
], eax
1683 add [ebp+XFS.file_buffer
], eax
1684 add [ebp+XFS.file_offset.lo
], eax
1685 adc [ebp+XFS.file_offset.hi
], 0
1686 ; cmp [ebp+XFS.bytes_to_read], 0
1687 cmp [ebp+XFS.extent.br_blockcount
], 0
1690 mov eax, [ebp+XFS.extent.br_startblock.lo
]
1691 mov edx, [ebp+XFS.extent.br_startblock.hi
]
1692 mov ebx, [ebp+XFS.cur_block_data
]
1693 stdcall xfs._.read_block
1694 mov ecx, [ebp+XFS.bytes_to_read
]
1695 cmp [ebp+XFS.bytes_left_in_file.hi
], 0
1697 cmp ecx, [ebp+XFS.bytes_left_in_file.lo
]
1699 mov ecx, [ebp+XFS.bytes_left_in_file.lo
]
1701 mov esi, [ebp+XFS.cur_block_data
]
1702 mov edi, [ebp+XFS.file_buffer
]
1705 add [ebp+XFS.bytes_read
], eax
1706 sub [ebp+XFS.bytes_to_read
], eax
1707 sub [ebp+XFS.bytes_left_in_file.lo
], eax
1708 sbb [ebp+XFS.bytes_left_in_file.hi
], 0
1709 add [ebp+XFS.file_buffer
], eax
1710 add [ebp+XFS.file_offset.lo
], eax
1711 adc [ebp+XFS.file_offset.hi
], 0
1712 add [ebp+XFS.extent.br_startoff.lo
], 1
1713 adc [ebp+XFS.extent.br_startoff.hi
], 0
1714 add [ebp+XFS.extent.br_startblock.lo
], 1
1715 adc [ebp+XFS.extent.br_startblock.hi
], 0
1716 dec [ebp+XFS.extent.br_blockcount
]
1718 mov esi, [ebp+XFS.extent.br_startoff.lo
]
1719 mov edi, [ebp+XFS.extent.br_startoff.hi
]
1720 movi
eax, ERROR_SUCCESS
1726 ;----------------------------------------------------------------
1727 ; in: ebp = pointer to XFS structure
1729 ; in: ebx = pointer to parameters from sysfunc 70
1730 ; out: eax, ebx = return values for sysfunc 70
1731 ;----------------------------------------------------------------
1732 proc xfs_Read uses
ecx edx esi edi
1738 mov [ebp+XFS.bytes_read
], 0
1739 mov eax, [ebx+f70s0arg.count
]
1740 mov [ebp+XFS.bytes_to_read
], eax
1743 mov eax, [ebx+f70s0arg.buf
]
1744 mov [ebp+XFS.file_buffer
], eax
1745 mov eax, [ebx+f70s0arg.
offset.hi
]
1746 mov [ebp+XFS.file_offset.hi
], eax
1747 mov eax, [ebx+f70s0arg.
offset.lo
]
1748 mov [ebp+XFS.file_offset.lo
], eax
1750 stdcall xfs_get_inode
, esi
1752 stdcall xfs_read_inode
, eax, edx, [ebp+XFS.cur_inode
]
1754 movi
eax, ERROR_FS_FAIL
1756 mov [ebp+XFS.cur_inode_save
], edx
1758 ; precompute .offset_begin
1759 mov esi, [ebp+XFS.file_offset.lo
]
1760 mov edi, [ebp+XFS.file_offset.hi
]
1761 mov ecx, [ebp+XFS.blocklog
]
1764 mov [.offset_begin.lo
], esi
1765 mov [.offset_begin.hi
], edi
1766 ; precompute .offset_end
1767 mov esi, [ebp+XFS.file_offset.lo
]
1768 mov edi, [ebp+XFS.file_offset.hi
]
1769 add esi, [ebp+XFS.bytes_to_read
]
1771 mov ecx, [ebp+XFS.blocksize
]
1775 mov ecx, [ebp+XFS.blocklog
]
1778 mov [.offset_end.lo
], esi
1779 mov [.offset_end.hi
], edi
1781 movbe
ecx, [ebx+xfs_inode.di_core.di_size.hi
]
1782 movbe
edx, [ebx+xfs_inode.di_core.di_size.lo
]
1783 mov [ebp+XFS.bytes_left_in_file.lo
], ecx
1784 mov [ebp+XFS.bytes_left_in_file.hi
], edx
1786 sub ecx, [ebp+XFS.file_offset.lo
]
1787 sbb edx, [ebp+XFS.file_offset.hi
]
1788 movi
eax, ERROR_END_OF_FILE
1790 mov [ebp+XFS.eof
], 0
1793 cmp ecx, [ebp+XFS.bytes_to_read
]
1795 mov [ebp+XFS.eof
], ERROR_END_OF_FILE
1796 mov [ebp+XFS.bytes_to_read
], ecx
1799 cmp [ebx+xfs_inode.di_core.di_format
], XFS_DINODE_FMT_BTREE
1803 add eax, [ebp+XFS.inode_core_size
]
1804 mov edx, [ebp+XFS.nextents_offset
]
1805 movbe
edx, [ebx+edx]
1806 mov ecx, [.offset_begin.lo
]
1807 mov [ebp+XFS.offset_begin.lo
], ecx
1808 mov ecx, [.offset_begin.hi
]
1809 mov [ebp+XFS.offset_begin.hi
], ecx
1810 mov ecx, [.offset_end.lo
]
1811 mov [ebp+XFS.offset_end.lo
], ecx
1812 mov ecx, [.offset_end.hi
]
1813 mov [ebp+XFS.offset_end.hi
], ecx
1814 stdcall xfs._.walk_extent_list
, edx, eax, xfs._.file.read_extent
, 0, 0
1818 mov eax, [ebp+XFS.inodesize
]
1819 sub eax, [ebp+XFS.inode_core_size
]
1820 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff
]
1826 add edx, [ebp+XFS.inode_core_size
]
1827 mov ecx, [.offset_begin.lo
]
1828 mov [ebp+XFS.offset_begin.lo
], ecx
1829 mov ecx, [.offset_begin.hi
]
1830 mov [ebp+XFS.offset_begin.hi
], ecx
1831 mov ecx, [.offset_end.lo
]
1832 mov [ebp+XFS.offset_end.lo
], ecx
1833 mov ecx, [.offset_end.hi
]
1834 mov [ebp+XFS.offset_end.hi
], ecx
1835 stdcall xfs._.walk_btree
, edx, eax, xfs._.file.read_extent
, 0, 0, 1
1837 cmp [ebp+XFS.bytes_left_in_file.hi
], 0
1839 cmp [ebp+XFS.bytes_left_in_file.lo
], 0
1842 cmp [ebp+XFS.bytes_to_read
], 0
1844 mov ebx, [ebp+XFS.cur_inode_save
]
1845 movbe
edx, [ebx+xfs_inode.di_core.di_size.lo
]
1846 movbe
eax, [ebx+xfs_inode.di_core.di_size.hi
]
1847 sub eax, [ebp+XFS.file_offset.lo
]
1848 sbb edx, [ebp+XFS.file_offset.hi
]
1850 mov ecx, [ebp+XFS.bytes_to_read
]
1853 cmp eax, [ebp+XFS.bytes_to_read
]
1858 sub [ebp+XFS.bytes_to_read
], ecx
1859 add [ebp+XFS.bytes_read
], ecx
1860 mov edi, [ebp+XFS.file_buffer
]
1865 mov eax, [ebp+XFS.eof
]
1870 mov ebx, [ebp+XFS.bytes_read
]
1875 proc xfs._.leafn_calc_entries uses
ebx ecx edx esi edi, _cur_dirblock
, _offset_lo
, _offset_hi
, _arg
1876 mov edx, [_cur_dirblock
]
1877 movzx eax, [ebp+XFS.da_node_magic
]
1878 cmp [edx+xfs_dir2_leaf.hdr.info.magic
], ax
1880 cmp [ebp+XFS.version
], 5
1882 add edx, xfs_dir3_leaf.hdr.count
-xfs_dir2_leaf.hdr.count
1884 movzx eax, [edx+xfs_dir2_leaf.hdr.count
]
1885 movzx ecx, [edx+xfs_dir2_leaf.hdr.stale
]
1889 add [ebp+XFS.entries_read
], eax
1891 movi
eax, ERROR_SUCCESS
1897 proc xfs._.get_before_by_hashval uses
ebx edx esi edi, _base
, _count
, _hash
1902 movbe
eax, [ebx+xfs_da_intnode.btree
+ecx*sizeof.xfs_da_node_entry
+xfs_da_node_entry.hashval
]
1903 cmp [ebp+XFS.version
], 5
1905 movbe
eax, [ebx+xfs_da3_intnode.btree
+ecx*sizeof.xfs_da_node_entry
+xfs_da_node_entry.hashval
]
1908 jae .node.leaf_found
1912 movi
eax, ERROR_FILE_NOT_FOUND
1916 movbe
eax, [ebx+xfs_da_intnode.btree
+ecx*sizeof.xfs_da_node_entry
+xfs_da_node_entry.before
]
1917 cmp [ebp+XFS.version
], 5
1919 movbe
eax, [ebx+xfs_da3_intnode.btree
+ecx*sizeof.xfs_da_node_entry
+xfs_da_node_entry.before
]
1931 proc xfs._.long_btree.seek uses
ebx esi edi, _ptr
, _size
1934 sub esi, sizeof.xfs_bmdr_block
1937 movzx eax, [ebx+xfs_bmdr_block.bb_level
]
1938 movzx ecx, [ebx+xfs_bmdr_block.bb_numrecs
]
1940 add ebx, sizeof.xfs_bmdr_block
1943 mov esi, [ebp+XFS.blocksize
]
1944 sub esi, [ebp+XFS.bmbt_block_size
]
1947 movzx eax, [ebx+xfs_bmbt_block.bb_level
]
1948 movzx ecx, [ebx+xfs_bmbt_block.bb_numrecs
]
1950 add ebx, [ebp+XFS.bmbt_block_size
]
1958 movbe
eax, [ebx+ecx*sizeof.xfs_bmbt_key
+xfs_bmbt_key.br_startoff.lo
]
1959 cmp [ebp+XFS.offset_begin.hi
], eax
1962 movbe
eax, [ebx+ecx*sizeof.xfs_bmbt_key
+xfs_bmbt_key.br_startoff.hi
]
1963 cmp [ebp+XFS.offset_begin.lo
], eax
1968 movbe
edx, [ebx+ecx*sizeof.xfs_bmbt_ptr
+xfs_bmbt_ptr.lo
]
1969 movbe
eax, [ebx+ecx*sizeof.xfs_bmbt_ptr
+xfs_bmbt_ptr.hi
]
1970 mov ebx, [ebp+XFS.cur_block
]
1971 stdcall xfs._.read_block
1974 mov ebx, [ebp+XFS.cur_block
]
1984 proc xfs._.walk_btree uses
ebx esi edi, _ptr
, _size
, _callback_extent
, _callback_block
, _callback_data
, _is_root
1985 stdcall xfs._.long_btree.seek
, [_ptr
+4], [_size
]
1988 mov ebx, [ebp+XFS.cur_block
]
1989 mov eax, [ebp+XFS.bmap_magic
]
1990 cmp [ebx+xfs_bmbt_block.bb_magic
], eax
1991 movi
eax, ERROR_FS_FAIL
1993 movzx ecx, [ebx+xfs_bmbt_block.bb_numrecs
]
1995 add ebx, [ebp+XFS.bmbt_block_size
]
1996 stdcall xfs._.walk_extent_list
, ecx, ebx, [_callback_extent
+8], [_callback_block
+4], [_callback_data
]
1998 mov esi, [ebp+XFS.offset_begin.lo
]
1999 mov edi, [ebp+XFS.offset_begin.hi
]
2000 cmp edi, [ebp+XFS.offset_end.hi
]
2002 cmp esi, [ebp+XFS.offset_end.lo
]
2004 sub ebx, [ebp+XFS.bmbt_block_size
]
2005 movbe
edx, [ebx+xfs_bmbt_block.bb_rightsib.lo
]
2006 movbe
eax, [ebx+xfs_bmbt_block.bb_rightsib.hi
]
2011 mov ebx, [ebp+XFS.cur_block
]
2012 stdcall xfs._.read_block
2021 proc xfs._.btree_read_block uses
ebx esi edi, _tree
, _size
, _block_lo
, _block_hi
, _buf
2022 mov eax, [_block_lo
]
2023 mov [ebp+XFS.offset_begin.lo
], eax
2024 mov eax, [_block_hi
]
2025 mov [ebp+XFS.offset_begin.hi
], eax
2026 stdcall xfs._.long_btree.seek
, [_tree
+4], [_size
]
2028 mov ebx, [ebp+XFS.cur_block
]
2029 mov eax, [ebp+XFS.bmap_magic
]
2030 cmp [ebx+xfs_bmbt_block.bb_magic
], eax
2032 movzx ecx, [ebx+xfs_bmbt_block.bb_numrecs
]
2034 add ebx, [ebp+XFS.bmbt_block_size
]
2035 mov eax, [_block_lo
]
2036 mov [ebp+XFS.offset_begin.lo
], eax
2037 mov eax, [_block_hi
]
2038 mov [ebp+XFS.offset_begin.hi
], eax
2039 stdcall xfs._.extent_list.seek
, ecx
2040 stdcall xfs._.read_dirblock
, [ebp+XFS.extent.br_startblock.lo
], \
2041 [ebp+XFS.extent.br_startblock.hi
], [_buf
]
2048 proc xfs._.extent_list.seek uses
esi, _count
2049 sub ebx, sizeof.xfs_bmbt_rec
2052 add ebx, sizeof.xfs_bmbt_rec
2055 stdcall xfs._.extent_unpack
, ebx
2056 mov eax, [ebp+XFS.extent.br_startoff.lo
]
2057 mov edx, [ebp+XFS.extent.br_startoff.hi
]
2058 mov esi, [ebp+XFS.extent.br_blockcount
]
2062 cmp edx, [ebp+XFS.offset_begin.hi
]
2065 cmp eax, [ebp+XFS.offset_begin.lo
]
2069 add ebx, sizeof.xfs_bmbt_rec
2071 mov eax, [ebp+XFS.offset_begin.lo
]
2072 mov edx, [ebp+XFS.offset_begin.hi
]
2074 sub esi, [ebp+XFS.extent.br_startoff.lo
]
2076 ; same br_blockcount for block and dirblock?
2077 mov [ebp+XFS.extent.br_startoff.lo
], eax
2078 mov [ebp+XFS.extent.br_startoff.hi
], edx
2079 sub [ebp+XFS.extent.br_blockcount
], esi
2080 add [ebp+XFS.extent.br_startblock.lo
], esi
2081 adc [ebp+XFS.extent.br_startblock.hi
], 0
2089 proc xfs._.extent_iterate_dirblocks _callback
, _callback_data
2091 cmp edi, [ebp+XFS.offset_end.hi
]
2094 cmp esi, [ebp+XFS.offset_end.lo
]
2097 stdcall xfs._.read_dirblock
, [ebp+XFS.extent.br_startblock.lo
], [ebp+XFS.extent.br_startblock.hi
], [ebp+XFS.cur_dirblock
]
2098 mov edx, [ebp+XFS.cur_dirblock
]
2099 mov eax, [_callback
]
2100 stdcall
eax, edx, esi, edi, [_callback_data
]
2103 mov eax, [ebp+XFS.blkpdirblk
]
2106 add [ebp+XFS.extent.br_startblock.lo
], eax
2107 adc [ebp+XFS.extent.br_startblock.hi
], 0
2108 sub [ebp+XFS.extent.br_blockcount
], eax
2116 proc xfs._.walk_extent_list uses
ebx esi edi, _count
, _ptr
, _callback_extent
, _callback_block
, _callback_data
2118 stdcall xfs._.extent_list.seek
, [_count
]
2122 jmp .next_extent.decoded
2124 stdcall xfs._.extent_unpack
, ebx
2125 add ebx, sizeof.xfs_bmbt_rec
2126 .next_extent.
decoded:
2127 mov eax, [ebp+XFS.extent.br_blockcount
]
2128 add [ebp+XFS.offset_begin.lo
], eax
2129 adc [ebp+XFS.offset_begin.hi
], 0
2130 mov esi, [ebp+XFS.extent.br_startoff.lo
]
2131 mov edi, [ebp+XFS.extent.br_startoff.hi
]
2132 stdcall
[_callback_extent
+8], [_callback_block
+4], [_callback_data
]
2134 cmp edi, [ebp+XFS.offset_end.hi
]
2137 cmp esi, [ebp+XFS.offset_end.lo
]
2144 movi
eax, ERROR_SUCCESS
2151 proc xfs._.get_last_dirblock uses
ecx
2152 mov eax, [ebp+XFS.nextents_offset
]
2153 movbe
eax, [ebx+eax]
2154 assert
(sizeof.xfs_bmbt_rec
AND (sizeof.xfs_bmbt_rec
- 1)) = 0
2155 shl eax, BSF sizeof.xfs_bmbt_rec
2156 add eax, [ebp+XFS.inode_core_size
]
2157 lea eax, [ebx+eax-sizeof.xfs_bmbt_rec
]
2158 stdcall xfs._.extent_unpack
, eax
2160 mov eax, [ebp+XFS.extent.br_blockcount
]
2161 mov ecx, [ebp+XFS.dirblklog
]
2164 add eax, [ebp+XFS.extent.br_startoff.lo
]
2165 adc edx, [ebp+XFS.extent.br_startoff.hi
]
2170 restore prologue
@proc,epilogue
@proc