[docs] Replace cyrillic 'с' with latin 'c' in register names
[kolibrios.git] / kernel / trunk / fs / xfs.asm
blob1fb482629658468b44b3452fe95df45810ba8505
1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2 ;; ;;
3 ;; Copyright (C) KolibriOS team 2013-2024. All rights reserved. ;;
4 ;; Distributed under terms of the GNU General Public License ;;
5 ;; ;;
6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 include 'xfs.inc'
11 macro omit_frame_pointer_prologue procname,flag,parmbytes,localbytes,reglist {
12 local loc
13 loc = (localbytes+3) and (not 3)
14 if localbytes
15 sub esp, loc
16 end if
17 irps reg, reglist \{ push reg \}
18 counter = 0
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 {
25 local loc
26 loc = (localbytes+3) and (not 3)
27 irps reg, reglist \{ reverse pop reg \}
28 if localbytes
29 lea esp, [esp+loc]
30 end if
31 if flag and 10000b
32 retn
33 else
34 retn parmbytes
35 end if
38 prologue@proc equ omit_frame_pointer_prologue
39 epilogue@proc equ omit_frame_pointer_epilogue
41 macro movbe reg, arg {
42 if CPUID_MOVBE eq Y
43 movbe reg, arg
44 else
45 mov reg, arg
46 if reg in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
47 bswap reg
48 else if ax eq reg
49 xchg al, ah
50 else if bx eq reg
51 xchg bl, bh
52 else if cx eq reg
53 xchg cl, ch
54 else if dx eq reg
55 xchg dl, dh
56 else
57 err
58 end if
59 end if
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
74 ; /fs/xfs
77 iglobal
78 align 4
79 xfs._.user_functions:
80 dd xfs._.free
81 dd (xfs._.user_functions_end-xfs._.user_functions-8)/4
82 dd xfs_Read
83 dd xfs_ReadFolder
84 dd 0;xfs_Rewrite
85 dd 0;xfs_Write
86 dd 0;xfs_SetFileEnd
87 dd xfs_GetFileInfo
88 xfs._.user_functions_end:
89 endg
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
96 ; check XFS signature
97 cmp [ebx+xfs_sb.sb_magicnum], XFS_SB_MAGIC
98 jnz .error_nofree
99 ; test for supported feature flags and version in sb_versionnum
100 movzx eax, [ebx+xfs_sb.sb_versionnum]
101 xchg al, ah
102 ; allow only known and supported features
103 ; return error otherwise
104 test eax, NOT XFS_SB_VERSION_SUPPORTED
105 jnz .error_nofree
106 ; version < 4 obsolete, not supported
107 ; version = 4,5 supported
108 ; version > 5 unknown
109 and al, XFS_SB_VERSION_NUMBITS
110 cmp al, 4
111 jb .error_nofree
112 cmp al, 5
113 ja .error_nofree
114 ; if MOREBITS bit is set, additional feature flags are in sb_features2
115 test eax, XFS_SB_VERSION_MOREBITSBIT
116 jz @f
117 movbe eax, [ebx+xfs_sb.sb_features2]
118 test eax, NOT XFS_SB_VERSION2_SUPPORTED
119 jnz .error_nofree
121 movbe eax, [ebx+xfs_sb.sb_features_incompat]
122 test eax, NOT XFS_SB_FEAT_INCOMPAT_SUPPORTED
123 jnz .error_nofree
124 ; all presented features are either supported or don't affect reading
125 movi eax, sizeof.XFS
126 call malloc
127 mov edi, eax
128 test eax, eax
129 jz .error
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]
146 call mutex_init
148 ; movzx eax, [ebx+xfs_sb.sb_sectsize]
149 ; xchg al, ah
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]
157 xchg al, ah
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
168 jz .v5
169 .v4:
170 mov [edi+XFS.inode_core_size], sizeof.xfs_dinode_core
171 test eax, XFS_SB_VERSION2_FTYPE
172 setnz al
173 movzx eax, al
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
186 jmp .vcommon
187 .v5:
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
192 setnz al
193 movzx eax, al
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
207 jz @f ; no 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
211 jz @f ; no bigtime
212 mov [edi+XFS.nextents_offset], xfs_inode.di_core.di_big_nextents.lo_be
214 .vcommon:
216 movzx eax, [ebx+xfs_sb.sb_inodesize]
217 xchg al, ah
218 mov [edi+XFS.inodesize], eax
220 movzx eax, [ebx+xfs_sb.sb_inopblock]
221 xchg al, ah
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]
229 bsf eax, eax
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
240 movi eax, 1
241 shl eax, cl
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]
251 shl eax, cl
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
260 mov eax, 1
261 shl eax, cl
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
273 mov eax, 1
274 xor edx, edx
275 shld edx, eax, cl
276 shl eax, cl
277 sub eax, 1
278 sbb edx, 0
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
286 shrd eax, edx, cl
287 shr edx, cl
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
294 shrd eax, edx, cl
295 shr edx, cl
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]
302 call malloc
303 mov [edi+XFS.cur_block], eax
304 test eax, eax
305 jz .error
307 mov eax, [edi+XFS.blocksize]
308 call malloc
309 mov [edi+XFS.cur_block_data], eax
310 test eax, eax
311 jz .error
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]
316 call malloc
317 mov [edi+XFS.cur_inode], eax
318 test eax, eax
319 jz .error
321 mov eax, [edi+XFS.blocksize]
322 call malloc
323 test eax, eax
324 jz .error
325 mov [edi+XFS.tmp_inode], eax
327 ; current sector
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]
332 call malloc
333 mov [edi+XFS.cur_sect], eax
334 test eax, eax
335 jz .error
337 mov eax, [edi+XFS.dirblocksize]
338 call malloc
339 mov [edi+XFS.cur_dirblock], eax
340 test eax, eax
341 jz .error
343 .quit:
344 ; return pointer to allocated XFS partition structure
345 mov eax, edi
347 .error:
348 mov eax, edi
349 call xfs._.free
350 .error_nofree:
351 xor eax, eax
353 endp
356 ; lock partition access mutex
357 xfs._.lock:
358 lea ecx, [ebp+XFS.Lock]
359 jmp mutex_lock
362 ; unlock partition access mutex
363 xfs._.unlock:
364 lea ecx, [ebp+XFS.Lock]
365 jmp mutex_unlock
368 ; free all the allocated memory
369 ; called on partition destroy
370 ; or during failed initialization from xfs_create_partition
371 xfs._.free:
372 test eax, eax
373 jz .done
374 push ebx
375 mov ebx, eax
378 ; freeing order must correspond the order of
379 ; allocation in xfs_create_partition
380 mov eax, [ebx+XFS.cur_block]
381 test eax, eax
382 jz .done
383 call free
385 mov eax, [ebx+XFS.cur_block_data]
386 test eax, eax
387 jz .done
388 call free
390 mov eax, [ebx+XFS.cur_inode]
391 test eax, eax
392 jz .done
393 call free
395 mov eax, [ebx+XFS.tmp_inode]
396 test eax, eax
397 jz .done
398 call free
400 mov eax, [ebx+XFS.cur_sect]
401 test eax, eax
402 jz .done
403 call free
405 mov eax, [ebx+XFS.cur_dirblock]
406 test eax, eax
407 jz .done
408 call free
411 mov eax, ebx
412 call free
413 pop ebx
414 .done:
418 ;---------------------------------------------------------------
419 ; block number
420 ; eax -- inode_lo
421 ; edx -- inode_hi
422 ; ebx -- buffer
423 ;---------------------------------------------------------------
424 proc xfs._.read_block
425 movi ecx, 1
426 call xfs._.read_blocks
428 endp
431 proc xfs._.blkrel2sectabs uses esi
432 push edx eax
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
440 ; 1.
441 mov ecx, [ebp+XFS.agblklog]
442 shrd eax, edx, cl
443 shr edx, cl
444 mul [ebp+XFS.agblocks]
445 ; 2.
446 pop ecx esi
447 and ecx, [ebp+XFS.agblockmask.lo]
448 and esi, [ebp+XFS.agblockmask.hi]
449 add eax, ecx
450 adc edx, esi
452 mov ecx, [ebp+XFS.sectpblog]
453 shld edx, eax, cl
454 shl eax, cl
456 endp
459 ;---------------------------------------------------------------
460 ; start block number
461 ; edx:eax -- block
462 ; ebx -- buffer
463 ; ecx -- count
464 ;---------------------------------------------------------------
465 proc xfs._.read_blocks
466 push ecx
467 call xfs._.blkrel2sectabs
468 pop ecx
469 imul ecx, [ebp+XFS.sectpblock]
470 call fs_read64_sys
471 test eax, eax
473 endp
476 proc xfs._.read_dirblock uses ebx, _startblock:qword, _buffer
477 mov eax, dword[_startblock+DQ.lo]
478 mov edx, dword[_startblock+DQ.hi]
479 mov ebx, [_buffer]
480 mov ecx, [ebp+XFS.blkpdirblk]
481 call xfs._.read_blocks
483 endp
486 ;---------------------------------------------------------------
487 ; test eax, eax
488 ;---------------------------------------------------------------
489 proc xfs_read_inode uses ebx, _inode_lo, _inode_hi, _buffer
490 mov eax, [_inode_lo]
491 mov edx, [_inode_hi]
492 mov ebx, [_buffer]
493 ; inodes are packed into blocks
494 ; 1. calculate block number
495 ; 2. read the block
496 ; 3. add inode offset to block base address
497 ; 1.
498 mov ecx, [ebp+XFS.inopblog]
499 shrd eax, edx, cl
500 shr edx, cl
501 ; 2.
502 call xfs._.read_block
503 jnz .error
504 ; inode numbers should be first extracted from bitfields by mask
506 mov eax, [_inode_lo]
507 mov edx, 1
508 mov ecx, [ebp+XFS.inopblog]
509 shl edx, cl
510 dec edx ; get inode number mask
511 and eax, edx ; apply mask
512 mov ecx, [ebp+XFS.inodelog]
513 shl eax, cl
514 add ebx, eax
515 xor eax, eax
517 cmp [ebx+xfs_inode.di_core.di_magic], XFS_DINODE_MAGIC
518 jz .quit
519 movi eax, ERROR_FS_FAIL
520 .quit:
521 mov edx, ebx
522 .error:
524 endp
527 ; skip ecx first entries
528 proc xfs._.dir_sf_skip _count
529 mov ecx, [_count]
530 .next:
531 dec ecx
532 js .quit
533 dec [ebp+XFS.entries_left_in_dir]
534 js .quit
535 .self:
536 bts [ebp+XFS.dir_sf_self_done], 0
537 jc .parent
538 jmp .next
539 .parent:
540 bts [ebp+XFS.dir_sf_parent_done], 0
541 jc .common
542 jmp .next
543 .common:
544 movzx eax, [esi+xfs_dir2_sf_entry.namelen]
545 add esi, xfs_dir2_sf_entry.name
546 add esi, eax
547 add esi, [ebp+XFS.ftype_size]
548 add esi, [ebp+XFS.shortform_inodelen]
549 jmp .next
550 .quit:
552 endp
555 proc xfs._.dir_sf_read uses edi, _count
556 locals
557 _dst dd ?
558 endl
559 .next:
560 dec [_count]
561 js .quit
562 dec [ebp+XFS.entries_left_in_dir]
563 js .quit
564 mov [_dst], edx
565 .self:
566 bts [ebp+XFS.dir_sf_self_done], 0
567 jc .parent
568 lea edi, [edx+bdfe.name]
569 mov dword[edi], '.'
570 stdcall xfs_get_inode_info, [ebp+XFS.cur_inode], edx
571 jmp .common
572 .parent:
573 bts [ebp+XFS.dir_sf_parent_done], 0
574 jc .not_special
575 lea edi, [edx+bdfe.name] ; get file name offset
576 mov dword[edi], '..' ; terminator included
577 mov edi, edx
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]
581 test eax, eax
582 jnz .error
583 stdcall xfs_get_inode_info, edx, edi
584 jmp .common
585 .not_special:
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]
591 mov edi, edx
592 mov edx, esi
593 call xfs._.get_inode_number_sf
594 stdcall xfs_read_inode, eax, edx, [ebp+XFS.tmp_inode]
595 test eax, eax
596 jnz .error
597 stdcall xfs_get_inode_info, edx, edi
598 add esi, [ebp+XFS.shortform_inodelen]
599 .common:
600 mov edx, [_dst]
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]
605 jmp .next
606 .quit:
607 xor eax, eax
608 .error:
610 endp
613 proc xfs._.readdir_sf uses esi, _src, _dst
614 mov ebx, [_src]
615 mov edx, [_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
621 add eax, 2
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
628 setnz al
629 lea eax, [eax*4+4]
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]
636 endp
639 proc xfs._.readdir_block _literal_area, _out_buf
640 mov ebx, [_literal_area]
641 mov [ebp+XFS.entries_read], 0
642 mov eax, ebx
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
646 mov edx, [_out_buf]
647 jnz .error
648 mov eax, [ebp+XFS.dir_block_magic]
649 cmp [ebx+xfs_dir2_block.hdr.magic], eax
650 movi eax, ERROR_FS_FAIL
651 jnz .error
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
661 mov [_out_buf], edx
662 lea edi, [_out_buf]
663 .next:
664 movi eax, ERROR_SUCCESS
665 cmp [ebp+XFS.requested_cnt], 0
666 jz .quit
667 cmp [ebp+XFS.entries_left_in_dir], 0
668 jz .quit
669 stdcall xfs._.dir_entry_skip_read, edi
670 jz .next
671 .error:
672 .quit:
674 endp
677 proc xfs._.readdir_leaf_node uses esi, _inode_data, _out_buf
678 mov ebx, [_inode_data]
679 mov edx, [_out_buf]
680 mov [ebp+XFS.cur_inode_save], ebx
681 mov [ebp+XFS.entries_read], 0
682 mov eax, ebx
683 add eax, [ebp+XFS.inode_core_size]
684 mov edx, [ebp+XFS.nextents_offset]
685 movbe edx, [ebx+edx]
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
695 jnz .error
696 mov eax, [ebp+XFS.entries_read]
697 mov edx, [_out_buf]
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]
703 movbe edx, [ebx+edx]
704 mov eax, ebx
705 add eax, [ebp+XFS.inode_core_size]
706 lea ecx, [_out_buf]
707 push ecx
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
714 pop ecx
715 stdcall xfs._.walk_extent_list, edx, eax, xfs._.extent_iterate_dirblocks, xfs._.dir_btree_skip_read, ecx
716 ; jnz .error
717 .error:
718 .quit:
720 endp
723 proc xfs._.dir_entry_skip_read uses esi edi, _arg
724 cmp [ebx+xfs_dir2_data_union.unused.freetag], XFS_NULL
725 jnz @f
726 movzx eax, [ebx+xfs_dir2_data_union.unused.length]
727 xchg al, ah
728 add ebx, eax
729 jmp .quit
731 cmp [ebp+XFS.entries_to_skip], 0
732 jz .read
733 .skip:
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]
738 jmp .common
739 .read:
740 dec [ebp+XFS.requested_cnt]
741 inc [ebp+XFS.entries_read]
742 mov edi, [_arg]
743 mov edi, [edi]
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
748 jnz .error
749 mov edx, [_arg]
750 mov edx, [edx]
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]
759 mov eax, [_arg]
760 mov edx, [eax]
761 add edx, [ebp+XFS.bdfe_len]
762 mov [eax], edx
763 .common:
764 sub ebx, [ebp+XFS.cur_dirblock]
765 add ebx, 7 ; xfs_dir2_data_entries are aligned to 8 bytes
766 and ebx, not 7
767 add ebx, [ebp+XFS.cur_dirblock]
768 dec [ebp+XFS.entries_left_in_dir]
769 .quit:
770 movi eax, ERROR_SUCCESS
771 cmp esp, esp
772 .error:
774 endp
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
782 jnz .error
783 mov eax, ebx
784 add eax, [ebp+XFS.dirblocksize]
785 mov [ebp+XFS.max_dirblockaddr], eax
786 add ebx, [ebp+XFS.dir_block_size]
787 .next:
788 movi eax, ERROR_SUCCESS
789 cmp [ebp+XFS.requested_cnt], 0
790 jz .quit
791 cmp [ebp+XFS.entries_left_in_dir], 0
792 jz .quit
793 cmp ebx, [ebp+XFS.max_dirblockaddr]
794 jz .quit
795 stdcall xfs._.dir_entry_skip_read, [_arg]
796 jz .next
797 .error:
798 .quit:
800 endp
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]
809 jecxz @f
810 shl ecx, 3
811 mov eax, ecx
813 mov edx, ebx
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]
825 mov edx, [_out_buf]
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]
833 jecxz @f
834 shl ecx, 3
835 mov eax, ecx
837 mov edx, ebx
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
845 mov ecx, [_out_buf]
846 push ecx
847 mov ecx, esp
848 stdcall xfs._.walk_btree, edx, eax, xfs._.extent_iterate_dirblocks, xfs._.dir_btree_skip_read, ecx, 1
849 pop ecx
850 .error:
851 .quit:
853 endp
856 proc xfs._.copy_filename uses eax
857 mov eax, [ebp+XFS.bdfe_nameenc]
858 cmp eax, 3
859 jz .utf8
860 cmp eax, 2
861 jz .utf16
862 .cp866:
863 call unicode.utf8.decode
864 call unicode.cp866.encode
865 stosb
866 test ecx, ecx
867 jnz .cp866
868 mov byte[edi], 0
869 jmp .done
870 .utf16:
871 call unicode.utf8.decode
872 call unicode.utf16.encode
873 stosw
874 shr eax, 16
875 jz @f
876 stosw
878 test ecx, ecx
879 jnz .utf16
880 mov word[edi], 0
881 jmp .done
882 .utf8:
883 rep movsb
884 mov byte[edi], 0
885 .done:
887 endp
889 ;----------------------------------------------------------------
890 ; src ; inode
891 ; dst ; bdfe
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
899 mov eax, [_encoding]
900 mov [ebp+XFS.bdfe_nameenc], eax
901 mov ecx, 304
902 cmp eax, 1 ; CP866
903 jbe @f
904 mov ecx, 560
906 mov [ebp+XFS.bdfe_len], ecx
907 mov edx, [_dst]
908 mov [ebp+XFS.bdfe_buf], edx
909 mov ebx, [_src]
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
922 jnz @f
923 add ebx, [ebp+XFS.inode_core_size]
924 stdcall xfs._.readdir_sf, ebx, [_dst]
925 test eax, eax
926 jnz .error
927 jmp .quit
929 cmp eax, XFS_DINODE_FMT_BTREE
930 jnz @f
931 stdcall xfs._.readdir_btree, ebx, [_dst]
932 jmp .quit
934 cmp eax, XFS_DINODE_FMT_EXTENTS
935 movi eax, ERROR_FS_FAIL
936 jnz .error
937 call xfs._.get_last_dirblock
938 test eax, eax
939 jnz @f
940 add ebx, [ebp+XFS.inode_core_size]
941 stdcall xfs._.readdir_block, ebx, [_dst]
942 jmp .quit
944 stdcall xfs._.readdir_leaf_node, ebx, [_dst]
945 jmp .quit
946 .quit:
947 mov edx, [_dst]
948 mov ebx, [ebp+XFS.entries_read]
949 mov [edx+bdfe_hdr.read_cnt], ebx
950 xor eax, eax
951 .error:
953 endp
956 ; returns edx:eax inode or 0
957 proc xfs._.lookup_sf _name, _len
958 add ebx, [ebp+XFS.inode_core_size]
959 mov esi, [_name]
960 mov ecx, [_len]
961 cmp ecx, 2
962 ja .common
963 jz .check_parent
964 .check_self:
965 cmp byte[esi], '.'
966 jnz .common
967 mov eax, [ebp+XFS.inode_self.lo]
968 mov edx, [ebp+XFS.inode_self.hi]
969 jmp .quit
970 .check_parent:
971 cmp word[esi], '..'
972 jnz .common
973 lea edx, [ebx+xfs_dir2_sf.hdr.parent]
974 call xfs._.get_inode_number_sf
975 jmp .quit
976 .common:
977 movzx edx, [ebx+xfs_dir2_sf.hdr.count]
978 movi eax, 0
979 cmp [ebx+xfs_dir2_sf.hdr.i8count], 0
980 setnz al
981 lea eax, [eax*4+4]
982 lea edi, [ebx+xfs_dir2_sf.hdr.parent+eax]
983 .next_name:
984 dec edx
985 jns @f
986 movi eax, ERROR_FILE_NOT_FOUND
987 jmp .error
989 movzx ecx, [edi+xfs_dir2_sf_entry.namelen]
990 add edi, xfs_dir2_sf_entry.name
991 mov esi, [_name]
992 cmp ecx, [_len]
993 jnz @f
994 repz cmpsb
995 jz .found
997 add edi, [ebp+XFS.ftype_size]
998 add edi, ecx
999 add edi, eax
1000 jmp .next_name
1001 .found:
1002 add edi, [ebp+XFS.ftype_size]
1003 mov edx, edi
1004 call xfs._.get_inode_number_sf
1005 .quit:
1006 cmp esp, esp
1007 .error:
1009 endp
1012 proc xfs._.lookup_block uses esi, _name, _len
1013 add ebx, [ebp+XFS.inode_core_size]
1014 mov eax, ebx
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
1019 jnz .error
1020 mov eax, [ebp+XFS.dir_block_magic]
1021 cmp [ebx+xfs_dir2_block.hdr.magic], eax
1022 movi eax, ERROR_FS_FAIL
1023 jnz .error
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]
1028 sub ebx, edx
1029 stdcall xfs._.get_addr_by_hash, ebx, ecx
1030 jnz .error
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]
1034 .quit:
1035 .error:
1037 endp
1040 proc xfs._.get_inode_by_addr uses ebx esi edi, _inode_buf
1041 xor edx, edx
1042 shld edx, eax, XFS_DIR2_DATA_ALIGN_LOG
1043 shl eax, XFS_DIR2_DATA_ALIGN_LOG
1044 mov esi, [ebp+XFS.dirblocksize]
1045 dec esi
1046 and esi, eax
1047 mov ecx, [ebp+XFS.blocklog]
1048 add ecx, [ebp+XFS.dirblklog]
1049 shrd eax, edx, cl
1050 shr edx, cl
1051 mov ecx, [ebp+XFS.dirblklog]
1052 shld edx, eax, cl
1053 shl eax, cl
1054 mov ebx, [_inode_buf]
1055 cmp [ebx+xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
1056 jz .extents
1057 cmp [ebx+xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE
1058 jz .btree
1059 jmp .error
1060 .extents:
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]
1068 jnz .error
1069 jmp .common
1070 .btree:
1071 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff]
1072 shl ecx, 3
1073 test ecx, ecx
1074 jnz @f
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]
1080 .common:
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
1085 jnz .error
1086 movbe edx, [ebx+esi+xfs_dir2_data_entry.inumber.lo]
1087 movbe eax, [ebx+esi+xfs_dir2_data_entry.inumber.hi]
1088 .error:
1089 .quit:
1091 endp
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]
1105 jnz .error
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
1110 jnz .error
1111 stdcall xfs_hashname, [_name+4], [_len]
1112 cmp [ebp+XFS.version], 5
1113 jz .v5
1114 .v4:
1115 movzx ecx, [ebx+xfs_dir2_leaf.hdr.count]
1116 xchg cl, ch
1117 add ebx, xfs_dir2_leaf.ents
1118 jmp .vcommon
1119 .v5:
1120 movzx ecx, [ebx+xfs_dir3_leaf.hdr.count]
1121 xchg cl, ch
1122 add ebx, xfs_dir3_leaf.ents
1123 .vcommon:
1124 stdcall xfs._.get_addr_by_hash, ebx, ecx
1125 jnz .error
1126 stdcall xfs._.get_inode_by_addr, [ebp+XFS.cur_inode_save]
1127 .quit:
1128 .error:
1130 endp
1133 proc xfs._.lookup_node uses ebx esi edi, _name, _len
1134 locals
1135 .hash dd ?
1136 endl
1137 mov [ebp+XFS.cur_inode_save], ebx
1138 stdcall xfs_hashname, [_name+4], [_len]
1139 mov [.hash], eax
1140 mov edx, [ebp+XFS.nextents_offset]
1141 movbe edx, [ebx+edx]
1142 mov esi, [ebp+XFS.dir2_leaf_offset_blocks.lo]
1143 .begin:
1144 mov ebx, [ebp+XFS.cur_inode_save]
1145 mov eax, ebx
1146 add eax, [ebp+XFS.inode_core_size]
1147 mov edx, [ebp+XFS.nextents_offset]
1148 movbe edx, [ebx+edx]
1149 mov ebx, eax
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]
1154 jnz .error
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
1158 jz .node
1159 movzx eax, [ebp+XFS.dir_leafn_magic]
1160 cmp [ebx+xfs_dir2_leaf.hdr.info.magic], ax
1161 jz .leaf
1162 movi eax, ERROR_FS_FAIL
1163 jmp .error
1164 .node:
1165 cmp [ebp+XFS.version], 5
1166 jz .node.v5
1167 .node.v4:
1168 lea eax, [ebx+sizeof.xfs_da_intnode]
1169 movzx edx, [ebx+xfs_da_intnode.hdr.count]
1170 jmp .node.vcommon
1171 .node.v5:
1172 lea eax, [ebx+sizeof.xfs_da3_intnode]
1173 movzx edx, [ebx+xfs_da3_intnode.hdr.count]
1174 .node.vcommon:
1175 xchg dl, dh
1176 stdcall xfs._.get_before_by_hashval, eax, edx, [.hash]
1177 jnz .error
1178 mov esi, eax
1179 jmp .begin
1180 .leaf:
1181 cmp [ebp+XFS.version], 5
1182 jz .leaf.v5
1183 .leaf.v4:
1184 movzx ecx, [ebx+xfs_dir2_leaf.hdr.count]
1185 xchg cl, ch
1186 add ebx, xfs_dir2_leaf.ents
1187 jmp .leaf.vcommon
1188 .leaf.v5:
1189 movzx ecx, [ebx+xfs_dir3_leaf.hdr.count]
1190 xchg cl, ch
1191 add ebx, xfs_dir3_leaf.ents
1192 .leaf.vcommon:
1193 mov eax, [.hash]
1194 stdcall xfs._.get_addr_by_hash, ebx, ecx
1195 jnz .error
1196 stdcall xfs._.get_inode_by_addr, [ebp+XFS.cur_inode_save]
1197 .quit:
1198 cmp esp, esp
1200 .error:
1201 test esp, esp
1203 endp
1206 proc xfs._.lookup_btree uses ebx esi edi, _name, _len
1207 locals
1208 .hash dd ?
1209 endl
1210 mov [ebp+XFS.cur_inode_save], ebx
1211 stdcall xfs_hashname, [_name+4], [_len]
1212 mov [.hash], eax
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
1216 .next_level:
1217 lea eax, [ebx+sizeof.xfs_da_intnode]
1218 movzx edx, [ebx+xfs_da_intnode.hdr.count]
1219 xchg dl, dh
1220 stdcall xfs._.get_before_by_hashval, eax, edx, [.hash]
1221 jnz .error
1222 xor edx, edx
1223 .next_level.first:
1224 mov ebx, [ebp+XFS.cur_inode_save]
1225 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff]
1226 shl ecx, 3
1227 test ecx, ecx
1228 jnz @f
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
1237 jz .next_level
1238 movzx eax, [ebp+XFS.dir_leafn_magic]
1239 cmp [ebx+xfs_da_blkinfo.magic], ax
1240 jz .leafn
1241 movzx eax, [ebp+XFS.dir_leaf1_magic]
1242 cmp [ebx+xfs_da_blkinfo.magic], ax
1243 jnz .error
1244 mov eax, [.hash]
1245 mov ecx, [ebp+XFS.dirx_leaf_hdr_count_offset]
1246 movzx ecx, word[ebx+ecx]
1247 xchg cl, ch
1248 add ebx, [ebp+XFS.dirx_leaf_ents_offset]
1249 stdcall xfs._.get_addr_by_hash, ebx, ecx
1250 jnz .error
1251 mov ebx, [ebp+XFS.cur_dirblock]
1252 jmp .got_addr
1253 .leafn:
1254 mov ecx, [ebp+XFS.dirx_leaf_hdr_count_offset]
1255 movzx ecx, word[ebx+ecx]
1256 xchg cl, ch
1257 add ebx, [ebp+XFS.dirx_leaf_ents_offset]
1258 mov eax, [.hash]
1259 stdcall xfs._.get_addr_by_hash, ebx, ecx
1260 jnz .error
1261 mov ebx, [ebp+XFS.cur_block]
1262 .got_addr:
1263 stdcall xfs._.get_inode_by_addr, [ebp+XFS.cur_inode_save]
1264 .quit:
1265 cmp esp, esp
1267 .error:
1268 test esp, esp
1270 endp
1273 ; search for the _name in _inode dir
1274 ; called for each /path/component/to/my/file
1275 ; out:
1276 ; ZF/zf = ok/fail
1277 ; edx:eax = inode/garbage:error
1278 proc xfs._.get_inode_short uses esi, _inode:qword, _len, _name
1279 mov esi, [_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]
1283 test eax, eax
1284 movi eax, ERROR_FS_FAIL
1285 jnz .error
1286 ; switch directory ondisk format
1287 mov ebx, edx
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
1292 jz .lookup
1293 cmp eax, XFS_DINODE_FMT_BTREE
1294 mov edi, xfs._.lookup_btree
1295 jz .lookup
1296 cmp eax, XFS_DINODE_FMT_EXTENTS
1297 jnz .error
1298 call xfs._.get_last_dirblock
1299 test eax, eax
1300 mov edi, xfs._.lookup_block
1301 jz .lookup
1302 cmp edx, [ebp+XFS.dir2_free_offset_blocks.hi]
1303 mov edi, xfs._.lookup_node
1304 ja .lookup
1305 cmp eax, [ebp+XFS.dir2_free_offset_blocks.lo]
1306 jae .lookup
1307 mov edi, xfs._.lookup_leaf
1308 .lookup:
1309 stdcall edi, [_name+4], [_len]
1310 .error:
1312 endp
1315 ; ZF/zf = ok/fail
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]
1322 mov esi, [_name]
1323 .next_dir:
1325 cmp byte[esi], '/'
1326 jnz @f
1327 inc esi
1328 jmp @b
1330 cmp byte[esi], 0
1331 jz .found
1332 push esi
1333 inc esi
1335 cmp byte[esi], 0
1336 jz @f
1337 cmp byte[esi], '/'
1338 jz @f
1339 inc esi
1340 jmp @b
1342 mov ecx, esi
1343 sub ecx, [esp]
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
1347 jz .next_dir
1348 .error:
1349 .found:
1351 endp
1354 ; in: ebp = pointer to XFS structure
1355 ; in: esi
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
1360 call xfs._.lock
1361 stdcall xfs_get_inode, esi
1362 jnz .error
1363 stdcall xfs_read_inode, eax, edx, [ebp+XFS.cur_inode]
1364 test eax, eax
1365 jnz .error
1366 stdcall xfs._.readdir, [ebx+f70s1arg.start_idx], [ebx+f70s1arg.count], [ebx+f70s1arg.buf], edx, [ebx+f70s1arg.encoding]
1367 test eax, eax
1368 jnz .error
1369 mov edx, [ebx+f70s1arg.buf]
1370 mov ecx, [ebx+f70s1arg.count]
1371 cmp [edx+bdfe_hdr.read_cnt], ecx
1372 jz .quit
1373 movi eax, ERROR_END_OF_FILE
1374 .quit:
1375 mov ebx, [edx+bdfe_hdr.read_cnt]
1377 .error:
1378 push eax
1379 call xfs._.unlock
1380 pop eax
1382 endp
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
1389 jz .i4bytes
1390 .i8bytes:
1391 movbe eax, [edx+DQ.hi]
1392 movbe edx, [edx+DQ.lo]
1394 .i4bytes:
1395 movbe eax, [edx+DQ.lo]
1396 xor edx, edx
1398 endp
1400 proc xfs._.conv_time_to_kos_epoch
1401 movbe eax, [ecx+DQ.hi_be]
1402 call fsTime2bdfe
1404 endp
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
1418 xor edx, edx
1419 jmp .time_to_bdfe
1420 .after_kos_epoch_begin:
1421 cmp edx, NANOSEC_PER_SEC
1422 jb .time_to_bdfe
1423 mov edx, NANOSEC_PER_SEC - 1
1424 mov eax, -1 ; very end of kolibrios epoch
1425 .time_to_bdfe:
1426 mov ecx, NANOSEC_PER_SEC
1427 div ecx
1428 call fsTime2bdfe
1430 endp
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
1436 xor eax, eax
1437 mov esi, [_src]
1438 movzx ecx, [esi+xfs_inode.di_core.di_mode]
1439 xchg cl, ch
1440 test ecx, S_IFDIR
1441 jz @f
1442 movi eax, 0x10 ; set directory flag
1444 mov edi, [_dst]
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
1451 add edi, bdfe.ctime
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
1460 cmp esp, esp
1462 endp
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]
1471 xor eax, eax
1472 movbe edx, [ebx+0]
1473 test edx, 0x80000000 ; mask, see documentation
1474 setnz al
1475 mov [ebp+XFS.extent.br_state], eax
1477 and edx, 0x7fffffff ; mask
1478 movbe eax, [ebx+4]
1479 shrd eax, edx, 9
1480 shr edx, 9
1481 mov [ebp+XFS.extent.br_startoff.lo], eax
1482 mov [ebp+XFS.extent.br_startoff.hi], edx
1484 movbe edx, [ebx+4]
1485 movbe eax, [ebx+8]
1486 movbe ecx, [ebx+12]
1487 and edx, 0x000001ff ; mask
1488 shrd ecx, eax, 21
1489 shrd eax, edx, 21
1490 mov [ebp+XFS.extent.br_startblock.lo], ecx
1491 mov [ebp+XFS.extent.br_startblock.hi], eax
1493 movbe eax, [ebx+12]
1494 and eax, 0x001fffff ; mask
1495 mov [ebp+XFS.extent.br_blockcount], eax
1497 endp
1500 proc xfs_hashname uses ecx esi, _name, _len
1501 xor eax, eax
1502 mov esi, [_name]
1503 mov ecx, [_len]
1505 rol eax, 7
1506 xor al, [esi]
1507 add esi, 1
1508 dec ecx
1509 jnz @b
1511 endp
1514 ; eax -- hash value
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
1519 mov ebx, [_base]
1520 mov edx, [_len]
1521 .next:
1522 mov ecx, edx
1523 ; jecxz .error
1524 test ecx, ecx
1525 jz .not_found
1526 shr ecx, 1
1527 movbe esi, [ebx+ecx*sizeof.xfs_dir2_leaf_entry+xfs_dir2_leaf_entry.hashval]
1528 cmp eax, esi
1529 jb .below
1530 ja .above
1531 movbe eax, [ebx+ecx*sizeof.xfs_dir2_leaf_entry+xfs_dir2_leaf_entry.address]
1533 .below:
1534 mov edx, ecx
1535 jmp .next
1536 .above:
1537 lea ebx, [ebx+(ecx+1)*sizeof.xfs_dir2_leaf_entry]
1538 sub edx, ecx
1539 dec edx
1540 jmp .next
1541 .not_found:
1542 movi eax, ERROR_FILE_NOT_FOUND
1543 test esp, esp
1545 endp
1548 ;----------------------------------------------------------------
1549 ; xfs_GetFileInfo: XFS implementation of getting file info
1550 ; in: ebp = pointer to XFS structure
1551 ; in: esi = name
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
1556 call xfs._.lock
1557 stdcall xfs_get_inode, esi
1558 jnz .error
1559 stdcall xfs_read_inode, eax, edx, [ebp+XFS.cur_inode]
1560 test eax, eax
1561 movi eax, ERROR_FS_FAIL
1562 jnz .error
1563 stdcall xfs_get_inode_info, edx, [ebx+f70s5arg.buf]
1564 .quit:
1565 call xfs._.unlock
1566 xor eax, eax
1568 .error:
1569 push eax
1570 call xfs._.unlock
1571 pop eax
1573 endp
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]
1582 shld edi, esi, cl
1583 shl esi, cl
1584 cmp edx, edi
1585 jb .hole
1586 ja .try_head
1587 cmp eax, esi
1588 ja .try_head
1589 jz .try_match
1590 .hole:
1591 sub esi, eax
1592 sbb edi, edx
1593 movi ecx, -1
1594 test edi, edi
1595 jnz @f
1596 mov ecx, esi
1598 cmp ecx, [ebp+XFS.bytes_to_read]
1599 jbe @f
1600 mov ecx, [ebp+XFS.bytes_to_read]
1602 mov edi, [ebp+XFS.file_buffer]
1603 xor eax, eax
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
1611 rep stosb
1612 cmp [ebp+XFS.bytes_to_read], 0
1613 jz .quit
1614 jmp .try_match
1615 .try_head:
1616 mov eax, [ebp+XFS.file_offset.lo]
1617 mov ecx, [ebp+XFS.blocksize]
1618 dec ecx
1619 test eax, ecx
1620 jz .try_match
1621 .head:
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]
1630 dec ecx
1631 and eax, ecx
1632 add esi, eax
1633 inc ecx
1634 sub ecx, eax
1635 cmp ecx, [ebp+XFS.bytes_to_read]
1636 jbe @f
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
1646 rep movsb
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
1653 jz .quit
1654 .try_match:
1655 mov eax, [ebp+XFS.bytes_to_read]
1656 test eax, eax
1657 jz .quit
1658 cmp eax, [ebp+XFS.blocksize]
1659 jb .tail
1660 mov ecx, [ebp+XFS.blocklog]
1661 shr eax, cl
1662 cmp eax, [ebp+XFS.extent.br_blockcount]
1663 jbe @f
1664 mov eax, [ebp+XFS.extent.br_blockcount]
1666 mov ecx, eax
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]
1670 push ecx
1671 stdcall xfs._.read_blocks
1672 pop eax
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
1688 jz .quit
1689 .tail:
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
1696 jnz @f
1697 cmp ecx, [ebp+XFS.bytes_left_in_file.lo]
1698 jbe @f
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]
1703 mov eax, ecx
1704 rep movsb
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]
1717 .quit:
1718 mov esi, [ebp+XFS.extent.br_startoff.lo]
1719 mov edi, [ebp+XFS.extent.br_startoff.hi]
1720 movi eax, ERROR_SUCCESS
1721 cmp esp, esp
1723 endp
1726 ;----------------------------------------------------------------
1727 ; in: ebp = pointer to XFS structure
1728 ; in: esi = name
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
1733 locals
1734 .offset_begin DQ ?
1735 .offset_end DQ ?
1736 endl
1737 call xfs._.lock
1738 mov [ebp+XFS.bytes_read], 0
1739 mov eax, [ebx+f70s0arg.count]
1740 mov [ebp+XFS.bytes_to_read], eax
1741 test eax, eax
1742 jz .quit
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
1751 jnz .error
1752 stdcall xfs_read_inode, eax, edx, [ebp+XFS.cur_inode]
1753 test eax, eax
1754 movi eax, ERROR_FS_FAIL
1755 jnz .error
1756 mov [ebp+XFS.cur_inode_save], edx
1757 mov ebx, 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]
1762 shrd esi, edi, cl
1763 shr edi, cl
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]
1770 adc edi, 0
1771 mov ecx, [ebp+XFS.blocksize]
1772 dec ecx
1773 add esi, ecx
1774 adc edi, 0
1775 mov ecx, [ebp+XFS.blocklog]
1776 shrd esi, edi, cl
1777 shr edi, cl
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
1789 jb .error
1790 mov [ebp+XFS.eof], 0
1791 test edx, edx
1792 jnz @f
1793 cmp ecx, [ebp+XFS.bytes_to_read]
1794 jae @f
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
1800 jz .btree
1801 .extent_list:
1802 mov eax, ebx
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
1815 jnz .error
1816 jmp .hole_check
1817 .btree:
1818 mov eax, [ebp+XFS.inodesize]
1819 sub eax, [ebp+XFS.inode_core_size]
1820 movzx ecx, [ebx+xfs_inode.di_core.di_forkoff]
1821 jecxz @f
1822 shl ecx, 3
1823 mov eax, ecx
1825 mov edx, ebx
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
1836 .hole_check:
1837 cmp [ebp+XFS.bytes_left_in_file.hi], 0
1838 jnz @f
1839 cmp [ebp+XFS.bytes_left_in_file.lo], 0
1840 jz .hole_done
1842 cmp [ebp+XFS.bytes_to_read], 0
1843 jz .hole_done
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]
1849 jc .hole_done
1850 mov ecx, [ebp+XFS.bytes_to_read]
1851 test edx, edx
1852 jnz .hole_read
1853 cmp eax, [ebp+XFS.bytes_to_read]
1854 jae .hole_read
1855 mov ecx, eax
1856 jmp .hole_read
1857 .hole_read:
1858 sub [ebp+XFS.bytes_to_read], ecx
1859 add [ebp+XFS.bytes_read], ecx
1860 mov edi, [ebp+XFS.file_buffer]
1861 xor eax, eax
1862 rep stosb
1863 .hole_done:
1864 .quit:
1865 mov eax, [ebp+XFS.eof]
1866 .error:
1867 push eax
1868 call xfs._.unlock
1869 pop eax
1870 mov ebx, [ebp+XFS.bytes_read]
1872 endp
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
1879 jz .quit
1880 cmp [ebp+XFS.version], 5
1881 jnz @f
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]
1886 xchg al, ah
1887 xchg cl, ch
1888 sub eax, ecx
1889 add [ebp+XFS.entries_read], eax
1890 .quit:
1891 movi eax, ERROR_SUCCESS
1892 cmp esp, esp
1894 endp
1897 proc xfs._.get_before_by_hashval uses ebx edx esi edi, _base, _count, _hash
1898 mov edi, [_hash]
1899 mov edx, [_count]
1900 xor ecx, ecx
1901 .node.next:
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
1904 jnz @f
1905 movbe eax, [ebx+xfs_da3_intnode.btree+ecx*sizeof.xfs_da_node_entry+xfs_da_node_entry.hashval]
1907 cmp eax, edi
1908 jae .node.leaf_found
1909 inc ecx
1910 cmp ecx, edx
1911 jnz .node.next
1912 movi eax, ERROR_FILE_NOT_FOUND
1913 test esp, esp
1914 jmp .error
1915 .node.leaf_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
1918 jnz @f
1919 movbe eax, [ebx+xfs_da3_intnode.btree+ecx*sizeof.xfs_da_node_entry+xfs_da_node_entry.before]
1921 jmp .quit
1922 .error:
1923 test esp, esp
1925 .quit:
1926 cmp esp, esp
1928 endp
1931 proc xfs._.long_btree.seek uses ebx esi edi, _ptr, _size
1932 mov ebx, [_ptr]
1933 mov esi, [_size]
1934 sub esi, sizeof.xfs_bmdr_block
1935 shr esi, 4
1936 shl esi, 3
1937 movzx eax, [ebx+xfs_bmdr_block.bb_level]
1938 movzx ecx, [ebx+xfs_bmdr_block.bb_numrecs]
1939 xchg cl, ch
1940 add ebx, sizeof.xfs_bmdr_block
1941 jmp .common
1942 .not_root:
1943 mov esi, [ebp+XFS.blocksize]
1944 sub esi, [ebp+XFS.bmbt_block_size]
1945 shr esi, 4
1946 shl esi, 3
1947 movzx eax, [ebx+xfs_bmbt_block.bb_level]
1948 movzx ecx, [ebx+xfs_bmbt_block.bb_numrecs]
1949 xchg cl, ch
1950 add ebx, [ebp+XFS.bmbt_block_size]
1951 .common:
1952 test eax, eax
1953 jz .leaf
1954 .node:
1955 .next_rec:
1956 dec ecx
1957 js .error
1958 movbe eax, [ebx+ecx*sizeof.xfs_bmbt_key+xfs_bmbt_key.br_startoff.lo]
1959 cmp [ebp+XFS.offset_begin.hi], eax
1960 ja .node_found
1961 jb .next_rec
1962 movbe eax, [ebx+ecx*sizeof.xfs_bmbt_key+xfs_bmbt_key.br_startoff.hi]
1963 cmp [ebp+XFS.offset_begin.lo], eax
1964 jae .node_found
1965 jmp .next_rec
1966 .node_found:
1967 add ebx, esi
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
1972 test eax, eax
1973 jnz .error
1974 mov ebx, [ebp+XFS.cur_block]
1975 jmp .not_root
1976 .leaf:
1977 jmp .quit
1978 .error:
1979 .quit:
1981 endp
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]
1986 mov [_is_root], 0
1987 .begin:
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
1992 jnz .error
1993 movzx ecx, [ebx+xfs_bmbt_block.bb_numrecs]
1994 xchg cl, ch
1995 add ebx, [ebp+XFS.bmbt_block_size]
1996 stdcall xfs._.walk_extent_list, ecx, ebx, [_callback_extent+8], [_callback_block+4], [_callback_data]
1997 jnz .error
1998 mov esi, [ebp+XFS.offset_begin.lo]
1999 mov edi, [ebp+XFS.offset_begin.hi]
2000 cmp edi, [ebp+XFS.offset_end.hi]
2001 ja .quit
2002 cmp esi, [ebp+XFS.offset_end.lo]
2003 jae .quit
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]
2007 mov ecx, eax
2008 and ecx, edx
2009 inc ecx
2010 jz .quit
2011 mov ebx, [ebp+XFS.cur_block]
2012 stdcall xfs._.read_block
2013 jnz .error
2014 jmp .begin
2015 .error:
2016 .quit:
2018 endp
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]
2027 jnz .error
2028 mov ebx, [ebp+XFS.cur_block]
2029 mov eax, [ebp+XFS.bmap_magic]
2030 cmp [ebx+xfs_bmbt_block.bb_magic], eax
2031 jnz .error
2032 movzx ecx, [ebx+xfs_bmbt_block.bb_numrecs]
2033 xchg cl, ch
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]
2042 .error:
2043 .quit:
2045 endp
2048 proc xfs._.extent_list.seek uses esi, _count
2049 sub ebx, sizeof.xfs_bmbt_rec
2050 inc [_count]
2051 .find_low:
2052 add ebx, sizeof.xfs_bmbt_rec
2053 dec [_count]
2054 jz .quit
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]
2059 add eax, esi
2060 adc edx, 0
2062 cmp edx, [ebp+XFS.offset_begin.hi]
2063 ja .low_found
2064 jb .find_low
2065 cmp eax, [ebp+XFS.offset_begin.lo]
2066 ja .low_found
2067 jmp .find_low
2068 .low_found:
2069 add ebx, sizeof.xfs_bmbt_rec
2071 mov eax, [ebp+XFS.offset_begin.lo]
2072 mov edx, [ebp+XFS.offset_begin.hi]
2073 mov esi, eax
2074 sub esi, [ebp+XFS.extent.br_startoff.lo]
2075 jbe .quit
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
2082 jmp .quit
2083 .quit:
2084 mov eax, [_count]
2086 endp
2089 proc xfs._.extent_iterate_dirblocks _callback, _callback_data
2090 .check_high:
2091 cmp edi, [ebp+XFS.offset_end.hi]
2092 ja .quit
2093 jb .read_dirblock
2094 cmp esi, [ebp+XFS.offset_end.lo]
2095 jae .quit
2096 .read_dirblock:
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]
2101 test eax, eax
2102 jnz .error
2103 mov eax, [ebp+XFS.blkpdirblk]
2104 add esi, eax
2105 adc edi, 0
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
2109 jnz .check_high
2110 .error:
2111 .quit:
2113 endp
2116 proc xfs._.walk_extent_list uses ebx esi edi, _count, _ptr, _callback_extent, _callback_block, _callback_data
2117 mov ebx, [_ptr]
2118 stdcall xfs._.extent_list.seek, [_count]
2119 mov [_count], eax
2120 dec [_count]
2121 js .quit
2122 jmp .next_extent.decoded
2123 .next_extent:
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]
2133 jnz .error
2134 cmp edi, [ebp+XFS.offset_end.hi]
2135 ja .quit
2136 jb @f
2137 cmp esi, [ebp+XFS.offset_end.lo]
2138 jae .quit
2140 dec [_count]
2141 js .quit
2142 jmp .next_extent
2143 .quit:
2144 movi eax, ERROR_SUCCESS
2145 .error:
2146 test eax, eax
2148 endp
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
2159 xor edx, edx
2160 mov eax, [ebp+XFS.extent.br_blockcount]
2161 mov ecx, [ebp+XFS.dirblklog]
2162 shr eax, cl
2163 dec eax
2164 add eax, [ebp+XFS.extent.br_startoff.lo]
2165 adc edx, [ebp+XFS.extent.br_startoff.hi]
2167 endp
2170 restore prologue@proc,epilogue@proc
2171 restore movbe