Subversion Repositories Kolibri OS

Rev

Rev 7736 | Rev 9889 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2013-2022. All rights reserved. ;;
  4. ;;  Distributed under terms of the GNU General Public License   ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 9888 $
  9.  
  10.  
  11. include 'xfs.inc'
  12.  
  13. macro omit_frame_pointer_prologue procname,flag,parmbytes,localbytes,reglist {
  14.   local loc
  15.   loc = (localbytes+3) and (not 3)
  16.   if localbytes
  17.         sub     esp, loc
  18.   end if
  19.   irps reg, reglist \{ push reg \}
  20.   counter = 0
  21.   irps reg, reglist \{counter = counter+1 \}
  22.   parmbase@proc equ esp+counter*4+loc+4
  23.   localbase@proc equ esp
  24. }
  25.  
  26. macro omit_frame_pointer_epilogue procname,flag,parmbytes,localbytes,reglist {
  27.   local loc
  28.   loc = (localbytes+3) and (not 3)
  29.   irps reg, reglist \{ reverse pop reg \}
  30.   if localbytes
  31.         lea     esp, [esp+loc]
  32.   end if
  33.   if flag and 10000b
  34.         retn
  35.   else
  36.         retn    parmbytes
  37.   end if
  38. }
  39.  
  40. prologue@proc equ omit_frame_pointer_prologue
  41. epilogue@proc equ omit_frame_pointer_epilogue
  42.  
  43. macro movbe reg, arg {
  44.  if CPUID_MOVBE eq Y
  45.         movbe   reg, arg
  46.  else
  47.         mov     reg, arg
  48.   if reg in <eax,ebx,ecx,edx,esi,edi,ebp,esp>
  49.         bswap   reg
  50.   else if ax eq reg
  51.         xchg    al, ah
  52.   else if bx eq reg
  53.         xchg    bl, bh
  54.   else if cx eq reg
  55.         xchg    cl, ch
  56.   else if dx eq reg
  57.         xchg    dl, dh
  58.   else
  59.    err
  60.   end if
  61.  end if
  62. }
  63.  
  64. ;
  65. ; This file contains XFS related code.
  66. ; For more information on XFS check links and source below.
  67. ;
  68. ; 1. https://xfs.wiki.kernel.org/
  69. ;
  70. ; 2. XFS Algorithms & Data Structures:
  71. ;    git://git.kernel.org/pub/scm/fs/xfs/xfs-documentation.git
  72. ;    https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf
  73. ;
  74. ; 3. Linux source at https://www.kernel.org/
  75. ;    git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
  76. ;    /fs/xfs
  77. ;
  78.  
  79. iglobal
  80. align 4
  81. xfs._.user_functions:
  82.         dd      xfs._.free
  83.         dd      (xfs._.user_functions_end-xfs._.user_functions-4)/4
  84.         dd      xfs_Read
  85.         dd      xfs_ReadFolder
  86.         dd      0;xfs_Rewrite
  87.         dd      0;xfs_Write
  88.         dd      0;xfs_SetFileEnd
  89.         dd      xfs_GetFileInfo
  90. xfs._.user_functions_end:
  91. endg
  92.  
  93. ; test partition type (valid XFS one?)
  94. ; alloc and fill XFS (see xfs.inc) structure
  95. ; this function is called for each partition
  96. ; return 0 (not XFS or invalid) / pointer to partition structure
  97. proc xfs_create_partition uses ebx esi edi
  98.         ; check XFS signature
  99.         cmp     [ebx+xfs_sb.sb_magicnum], XFS_SB_MAGIC
  100.         jnz     .error_nofree
  101.         ; test for supported feature flags and version in sb_versionnum
  102.         movzx   eax, [ebx+xfs_sb.sb_versionnum]
  103.         xchg    al, ah
  104.         ; allow only known and supported features
  105.         ; return error otherwise
  106.         test    eax, NOT XFS_SB_VERSION_SUPPORTED
  107.         jnz     .error_nofree
  108.         ; version < 4 obsolete, not supported
  109.         ; version = 4,5 supported
  110.         ; version > 5 unknown
  111.         and     al, XFS_SB_VERSION_NUMBITS
  112.         cmp     al, 4
  113.         jb      .error_nofree
  114.         cmp     al, 5
  115.         ja      .error_nofree
  116.         ; if MOREBITS bit is set, additional feature flags are in sb_features2
  117.         test    eax, XFS_SB_VERSION_MOREBITSBIT
  118.         jz      @f
  119.         movbe   eax, [ebx+xfs_sb.sb_features2]
  120.         test    eax, NOT XFS_SB_VERSION2_SUPPORTED
  121.         jnz     .error_nofree
  122. @@:
  123.         movbe   eax, [ebx+xfs_sb.sb_features_incompat]
  124.         test    eax, NOT XFS_SB_FEAT_INCOMPAT_SUPPORTED
  125.         jnz     .error_nofree
  126.         ; all presented features are either supported or don't affect reading
  127.         movi    eax, sizeof.XFS
  128.         call    malloc
  129.         mov     edi, eax
  130.         test    eax, eax
  131.         jz      .error
  132.  
  133.         ; standard partition initialization, common for all file systems
  134.         mov     eax, dword[ebp+PARTITION.FirstSector+DQ.lo]
  135.         mov     dword[edi+XFS.FirstSector+DQ.lo], eax
  136.         mov     eax, dword[ebp+PARTITION.FirstSector+DQ.hi]
  137.         mov     dword[edi+XFS.FirstSector+DQ.hi], eax
  138.         mov     eax, dword[ebp+PARTITION.Length+DQ.lo]
  139.         mov     dword[edi+XFS.Length+DQ.lo], eax
  140.         mov     eax, dword[ebp+PARTITION.Length+DQ.hi]
  141.         mov     dword[edi+XFS.Length+DQ.hi], eax
  142.         mov     eax, [ebp+PARTITION.Disk]
  143.         mov     [edi+XFS.Disk], eax
  144.         mov     [edi+XFS.FSUserFunctions], xfs._.user_functions
  145.         ; here we initialize only one mutex (for the entire partition)
  146.         ; XFS potentially allows parallel r/w access to different AGs, keep it in mind
  147.         lea     ecx, [edi+XFS.Lock]
  148.         call    mutex_init
  149.  
  150. ;        movzx   eax, [ebx+xfs_sb.sb_sectsize]
  151. ;        xchg    al, ah
  152.         mov     eax, [eax+DISK.MediaInfo.SectorSize]
  153.         mov     [edi+XFS.sectsize], eax
  154.  
  155.         movbe   eax, [ebx+xfs_sb.sb_blocksize]
  156.         mov     [edi+XFS.blocksize], eax
  157.  
  158.         movzx   eax, [ebx+xfs_sb.sb_versionnum]
  159.         xchg    al, ah
  160.         mov     [edi+XFS.versionnum], eax
  161.         and     eax, XFS_SB_VERSION_NUMBITS
  162.         mov     [edi+XFS.version], eax
  163.  
  164.         mov     [edi+XFS.conv_time_to_kos_epoch], xfs._.conv_time_to_kos_epoch
  165.  
  166.         movbe   eax, [ebx+xfs_sb.sb_features2]
  167.         mov     [edi+XFS.features2], eax
  168.         cmp     [edi+XFS.version], 5
  169.         jz      .v5
  170. .v4:
  171.         mov     [edi+XFS.inode_core_size], sizeof.xfs_dinode_core
  172.         test    eax, XFS_SB_VERSION2_FTYPE
  173.         setnz   al
  174.         movzx   eax, al
  175.         mov     [edi+XFS.ftype_size], eax
  176.         mov     [edi+XFS.dir_block_magic], XFS_DIR2_BLOCK_MAGIC
  177.         mov     [edi+XFS.dir_data_magic], XFS_DIR2_DATA_MAGIC
  178.         mov     [edi+XFS.dir_leaf1_magic], XFS_DIR2_LEAF1_MAGIC
  179.         mov     [edi+XFS.dir_leafn_magic], XFS_DIR2_LEAFN_MAGIC
  180.         mov     [edi+XFS.da_node_magic], XFS_DA_NODE_MAGIC
  181.         mov     [edi+XFS.bmap_magic], XFS_BMAP_MAGIC
  182.         mov     [edi+XFS.dir_block_size], sizeof.xfs_dir2_data_hdr
  183.         mov     [edi+XFS.bmbt_block_size], sizeof.xfs_bmbt_block
  184.         mov     [edi+XFS.da_blkinfo_size], sizeof.xfs_da_blkinfo
  185.         jmp     .vcommon
  186. .v5:
  187.         mov     [edi+XFS.inode_core_size], sizeof.xfs_dinode3_core
  188.         movbe   eax, [ebx+xfs_sb.sb_features_incompat]
  189.         mov     [edi+XFS.features_incompat], eax
  190.         test    eax, XFS_SB_FEAT_INCOMPAT_FTYPE
  191.         setnz   al
  192.         movzx   eax, al
  193.         mov     [edi+XFS.ftype_size], eax
  194.         mov     [edi+XFS.dir_block_magic], XFS_DIR3_BLOCK_MAGIC
  195.         mov     [edi+XFS.dir_data_magic], XFS_DIR3_DATA_MAGIC
  196.         mov     [edi+XFS.dir_leaf1_magic], XFS_DIR3_LEAF1_MAGIC
  197.         mov     [edi+XFS.dir_leafn_magic], XFS_DIR3_LEAFN_MAGIC
  198.         mov     [edi+XFS.da_node_magic], XFS_DA3_NODE_MAGIC
  199.         mov     [edi+XFS.bmap_magic], XFS_BMAP3_MAGIC
  200.         mov     [edi+XFS.dir_block_size], sizeof.xfs_dir3_data_hdr
  201.         mov     [edi+XFS.bmbt_block_size], sizeof.xfs_bmbt3_block
  202.         mov     [edi+XFS.da_blkinfo_size], sizeof.xfs_da3_blkinfo
  203.         test    [edi+XFS.features_incompat], XFS_SB_FEAT_INCOMPAT_BIGTIME
  204.         jz      @f      ; no bigtime
  205.         mov     [edi+XFS.conv_time_to_kos_epoch], xfs._.conv_bigtime_to_kos_epoch
  206. @@:
  207. .vcommon:
  208.  
  209.         movzx   eax, [ebx+xfs_sb.sb_inodesize]
  210.         xchg    al, ah
  211.         mov     [edi+XFS.inodesize], eax
  212.  
  213.         movzx   eax, [ebx+xfs_sb.sb_inopblock]
  214.         xchg    al, ah
  215.         mov     [edi+XFS.inopblock], eax
  216.  
  217.         movzx   eax, [ebx+xfs_sb.sb_blocklog]
  218.         mov     [edi+XFS.blocklog], eax
  219.  
  220. ;        movzx   eax, [ebx+xfs_sb.sb_sectlog]
  221.         mov     eax, [edi+XFS.sectsize]
  222.         bsf     eax, eax
  223.         mov     [edi+XFS.sectlog], eax
  224.  
  225.         movzx   eax, [ebx+xfs_sb.sb_inodelog]
  226.         mov     [edi+XFS.inodelog], eax
  227.  
  228.         movzx   eax, [ebx+xfs_sb.sb_inopblog]
  229.         mov     [edi+XFS.inopblog], eax
  230.  
  231.         movzx   ecx, [ebx+xfs_sb.sb_dirblklog]
  232.         mov     [edi+XFS.dirblklog], ecx
  233.         movi    eax, 1
  234.         shl     eax, cl
  235.         mov     [edi+XFS.blkpdirblk], eax
  236.  
  237.         movbe   eax, [ebx+xfs_sb.sb_rootino.hi]
  238.         mov     [edi+XFS.rootino.lo], eax
  239.         movbe   eax, [ebx+xfs_sb.sb_rootino.lo]
  240.         mov     [edi+XFS.rootino.hi], eax
  241.  
  242.         mov     eax, [edi+XFS.blocksize]
  243.         mov     ecx, [edi+XFS.dirblklog]
  244.         shl     eax, cl
  245.         mov     [edi+XFS.dirblocksize], eax           ; blocks are for files, dirblocks are for directories
  246.  
  247.         ; sector is always smaller than block
  248.         ; so precalculate shift order to allow faster sector_num->block_num conversion
  249.         mov     ecx, [edi+XFS.blocklog]
  250.         sub     ecx, [edi+XFS.sectlog]
  251.         mov     [edi+XFS.sectpblog], ecx
  252.  
  253.         mov     eax, 1
  254.         shl     eax, cl
  255.         mov     [edi+XFS.sectpblock], eax
  256.  
  257.         movbe   eax, [ebx+xfs_sb.sb_agblocks]
  258.         mov     [edi+XFS.agblocks], eax
  259.  
  260.         movzx   ecx, [ebx+xfs_sb.sb_agblklog]
  261.         mov     [edi+XFS.agblklog], ecx
  262.  
  263.         ; get the mask for block numbers
  264.         ; block numbers are AG relative!
  265.         ; bitfield length may vary between partitions
  266.         mov     eax, 1
  267.         xor     edx, edx
  268.         shld    edx, eax, cl
  269.         shl     eax, cl
  270.         sub     eax, 1
  271.         sbb     edx, 0
  272.         mov     [edi+XFS.agblockmask.lo], eax
  273.         mov     [edi+XFS.agblockmask.hi], edx
  274.  
  275.         ; calculate magic offsets for directories
  276.         mov     ecx, [edi+XFS.blocklog]
  277.         mov     eax, XFS_DIR2_LEAF_OFFSET AND 0xffffffff        ; lo
  278.         mov     edx, XFS_DIR2_LEAF_OFFSET SHR 32                ; hi
  279.         shrd    eax, edx, cl
  280.         shr     edx, cl
  281.         mov     [edi+XFS.dir2_leaf_offset_blocks.lo], eax
  282.         mov     [edi+XFS.dir2_leaf_offset_blocks.hi], edx
  283.  
  284.         mov     ecx, [edi+XFS.blocklog]
  285.         mov     eax, XFS_DIR2_FREE_OFFSET AND 0xffffffff        ; lo
  286.         mov     edx, XFS_DIR2_FREE_OFFSET SHR 32                ; hi
  287.         shrd    eax, edx, cl
  288.         shr     edx, cl
  289.         mov     [edi+XFS.dir2_free_offset_blocks.lo], eax
  290.         mov     [edi+XFS.dir2_free_offset_blocks.hi], edx
  291.  
  292.  
  293.         ; allocate memory for temp block, dirblock, inode, etc
  294.         mov     eax, [edi+XFS.blocksize]
  295.         call    malloc
  296.         mov     [edi+XFS.cur_block], eax
  297.         test    eax, eax
  298.         jz      .error
  299.  
  300.         mov     eax, [edi+XFS.blocksize]
  301.         call    malloc
  302.         mov     [edi+XFS.cur_block_data], eax
  303.         test    eax, eax
  304.         jz      .error
  305.  
  306.         ; we do need XFS.blocksize bytes for single inode
  307.         ; minimal file system structure is block, inodes are packed in blocks
  308.         ; FIXME
  309.         mov     eax, [edi+XFS.blocksize]
  310.         call    malloc
  311.         mov     [edi+XFS.cur_inode], eax
  312.         test    eax, eax
  313.         jz      .error
  314.  
  315.         mov     eax, [edi+XFS.blocksize]
  316.         call    malloc
  317.         test    eax, eax
  318.         jz      .error
  319.         mov     [edi+XFS.tmp_inode], eax
  320.  
  321.         ; current sector
  322.         ; only for sector sized structures like AGF
  323.         ; inodes usually fit this size, but not always!
  324.         ; therefore never store inode here
  325.         mov     eax, [edi+XFS.sectsize]
  326.         call    malloc
  327.         mov     [edi+XFS.cur_sect], eax
  328.         test    eax, eax
  329.         jz      .error
  330.  
  331.         mov     eax, [edi+XFS.dirblocksize]
  332.         call    malloc
  333.         mov     [edi+XFS.cur_dirblock], eax
  334.         test    eax, eax
  335.         jz      .error
  336.  
  337. .quit:
  338.         ; return pointer to allocated XFS partition structure
  339.         mov     eax, edi
  340.         ret
  341. .error:
  342.         mov     eax, edi
  343.         call    xfs._.free
  344. .error_nofree:
  345.         xor     eax, eax
  346.         ret
  347. endp
  348.  
  349.  
  350. ; lock partition access mutex
  351. xfs._.lock:
  352.         lea     ecx, [ebp+XFS.Lock]
  353.         jmp     mutex_lock
  354.  
  355.  
  356. ; unlock partition access mutex
  357. xfs._.unlock:
  358.         lea     ecx, [ebp+XFS.Lock]
  359.         jmp     mutex_unlock
  360.  
  361.  
  362. ; free all the allocated memory
  363. ; called on partition destroy
  364. ; or during failed initialization from xfs_create_partition
  365. xfs._.free:
  366.         test    eax, eax
  367.         jz      .done
  368.         push    ebx
  369.         mov     ebx, eax
  370.  
  371.  
  372.         ; freeing order must correspond the order of
  373.         ; allocation in xfs_create_partition
  374.         mov     eax, [ebx+XFS.cur_block]
  375.         test    eax, eax
  376.         jz      .done
  377.         call    free
  378.  
  379.         mov     eax, [ebx+XFS.cur_block_data]
  380.         test    eax, eax
  381.         jz      .done
  382.         call    free
  383.  
  384.         mov     eax, [ebx+XFS.cur_inode]
  385.         test    eax, eax
  386.         jz      .done
  387.         call    free
  388.  
  389.         mov     eax, [ebx+XFS.tmp_inode]
  390.         test    eax, eax
  391.         jz      .done
  392.         call    free
  393.  
  394.         mov     eax, [ebx+XFS.cur_sect]
  395.         test    eax, eax
  396.         jz      .done
  397.         call    free
  398.  
  399.         mov     eax, [ebx+XFS.cur_dirblock]
  400.         test    eax, eax
  401.         jz      .done
  402.         call    free
  403.  
  404.  
  405.         mov     eax, ebx
  406.         call    free
  407.         pop     ebx
  408. .done:
  409.         ret
  410.  
  411.  
  412. ;---------------------------------------------------------------
  413. ; block number
  414. ; eax -- inode_lo
  415. ; edx -- inode_hi
  416. ; ebx -- buffer
  417. ;---------------------------------------------------------------
  418. proc xfs._.read_block
  419.         movi    ecx, 1
  420.         call    xfs._.read_blocks
  421.         ret
  422. endp
  423.  
  424.  
  425. proc xfs._.blkrel2sectabs uses esi
  426.         push    edx eax
  427.  
  428.         ; XFS block numbers are AG relative
  429.         ; they come in bitfield form of concatenated AG and block numbers
  430.         ; to get absolute block number for fs_read64_sys we should
  431.         ; 1. get AG number and multiply it by the AG size in blocks
  432.         ; 2. extract and add AG relative block number
  433.  
  434.         ; 1.
  435.         mov     ecx, [ebp+XFS.agblklog]
  436.         shrd    eax, edx, cl
  437.         shr     edx, cl
  438.         mul     [ebp+XFS.agblocks]
  439.         ; 2.
  440.         pop     ecx esi
  441.         and     ecx, [ebp+XFS.agblockmask.lo]
  442.         and     esi, [ebp+XFS.agblockmask.hi]
  443.         add     eax, ecx
  444.         adc     edx, esi
  445.  
  446.         mov     ecx, [ebp+XFS.sectpblog]
  447.         shld    edx, eax, cl
  448.         shl     eax, cl
  449.         ret
  450. endp
  451.  
  452.  
  453. ;---------------------------------------------------------------
  454. ; start block number
  455. ; edx:eax -- block
  456. ; ebx -- buffer
  457. ; ecx -- count
  458. ;---------------------------------------------------------------
  459. proc xfs._.read_blocks
  460.         push    ecx
  461.         call    xfs._.blkrel2sectabs
  462.         pop     ecx
  463.         imul    ecx, [ebp+XFS.sectpblock]
  464.         call    fs_read64_sys
  465.         test    eax, eax
  466.         ret
  467. endp
  468.  
  469.  
  470. proc xfs._.read_dirblock uses ebx, _startblock:qword, _buffer
  471.         mov     eax, dword[_startblock+DQ.lo]
  472.         mov     edx, dword[_startblock+DQ.hi]
  473.         mov     ebx, [_buffer]
  474.         mov     ecx, [ebp+XFS.blkpdirblk]
  475.         call    xfs._.read_blocks
  476.         ret
  477. endp
  478.  
  479.  
  480. ;---------------------------------------------------------------
  481. ; test eax, eax
  482. ;---------------------------------------------------------------
  483. proc xfs_read_inode uses ebx, _inode_lo, _inode_hi, _buffer
  484.         mov     eax, [_inode_lo]
  485.         mov     edx, [_inode_hi]
  486.         mov     ebx, [_buffer]
  487.         ; inodes are packed into blocks
  488.         ; 1. calculate block number
  489.         ; 2. read the block
  490.         ; 3. add inode offset to block base address
  491.         ; 1.
  492.         mov     ecx, [ebp+XFS.inopblog]
  493.         shrd    eax, edx, cl
  494.         shr     edx, cl
  495.         ; 2.
  496.         call    xfs._.read_block
  497.         jnz     .error
  498.         ; inode numbers should be first extracted from bitfields by mask
  499.  
  500.         mov     eax, [_inode_lo]
  501.         mov     edx, 1
  502.         mov     ecx, [ebp+XFS.inopblog]
  503.         shl     edx, cl
  504.         dec     edx             ; get inode number mask
  505.         and     eax, edx        ; apply mask
  506.         mov     ecx, [ebp+XFS.inodelog]
  507.         shl     eax, cl
  508.         add     ebx, eax
  509.         xor     eax, eax
  510.  
  511.         cmp     [ebx+xfs_inode.di_core.di_magic], XFS_DINODE_MAGIC
  512.         jz      .quit
  513.         movi    eax, ERROR_FS_FAIL
  514. .quit:
  515.         mov     edx, ebx
  516. .error:
  517.         ret
  518. endp
  519.  
  520.  
  521. ; skip ecx first entries
  522. proc xfs._.dir_sf_skip _count
  523.         mov     ecx, [_count]
  524. .next:
  525.         dec     ecx
  526.         js      .quit
  527.         dec     [ebp+XFS.entries_left_in_dir]
  528.         js      .quit
  529. .self:
  530.         bts     [ebp+XFS.dir_sf_self_done], 0
  531.         jc      .parent
  532.         jmp     .next
  533. .parent:
  534.         bts     [ebp+XFS.dir_sf_parent_done], 0
  535.         jc      .common
  536.         jmp     .next
  537. .common:
  538.         movzx   eax, [esi+xfs_dir2_sf_entry.namelen]
  539.         add     esi, xfs_dir2_sf_entry.name
  540.         add     esi, eax
  541.         add     esi, [ebp+XFS.ftype_size]
  542.         add     esi, [ebp+XFS.shortform_inodelen]
  543.         jmp     .next
  544. .quit:
  545.         ret
  546. endp
  547.  
  548.  
  549. proc xfs._.dir_sf_read uses edi, _count
  550. locals
  551.         _dst dd ?
  552. endl
  553. .next:
  554.         dec     [_count]
  555.         js      .quit
  556.         dec     [ebp+XFS.entries_left_in_dir]
  557.         js      .quit
  558.         mov     [_dst], edx
  559. .self:
  560.         bts     [ebp+XFS.dir_sf_self_done], 0
  561.         jc      .parent
  562.         lea     edi, [edx+bdfe.name]
  563.         mov     dword[edi], '.'
  564.         stdcall xfs_get_inode_info, [ebp+XFS.cur_inode], edx
  565.         jmp     .common
  566. .parent:
  567.         bts     [ebp+XFS.dir_sf_parent_done], 0
  568.         jc      .not_special
  569.         lea     edi, [edx+bdfe.name]         ; get file name offset
  570.         mov     dword[edi], '..'        ; terminator included
  571.         mov     edi, edx
  572.         lea     edx, [ebx+xfs_dir2_sf.hdr.parent]
  573.         call    xfs._.get_inode_number_sf
  574.         stdcall xfs_read_inode, eax, edx, [ebp+XFS.tmp_inode]
  575.         test    eax, eax
  576.         jnz     .error
  577.         stdcall xfs_get_inode_info, edx, edi
  578.         jmp     .common
  579. .not_special:
  580.         movzx   ecx, [esi+xfs_dir2_sf_entry.namelen]
  581.         add     esi, xfs_dir2_sf_entry.name
  582.         lea     edi, [edx+bdfe.name]
  583.         stdcall xfs._.copy_filename
  584.         add     esi, [ebp+XFS.ftype_size]
  585.         mov     edi, edx
  586.         mov     edx, esi
  587.         call    xfs._.get_inode_number_sf
  588.         stdcall xfs_read_inode, eax, edx, [ebp+XFS.tmp_inode]
  589.         test    eax, eax
  590.         jnz     .error
  591.         stdcall xfs_get_inode_info, edx, edi
  592.         add     esi, [ebp+XFS.shortform_inodelen]
  593. .common:
  594.         mov     edx, [_dst]
  595.         mov     eax, [ebp+XFS.bdfe_nameenc]
  596.         mov     [edx+bdfe.nameenc], eax
  597.         add     edx, [ebp+XFS.bdfe_len]
  598.         inc     [ebp+XFS.entries_read]
  599.         jmp     .next
  600. .quit:
  601.         xor     eax, eax
  602. .error:
  603.         ret
  604. endp
  605.  
  606.  
  607. proc xfs._.readdir_sf uses esi, _src, _dst
  608.         mov     ebx, [_src]
  609.         mov     edx, [_dst]
  610.         mov     [ebp+XFS.dir_sf_self_done], 0
  611.         mov     [ebp+XFS.dir_sf_parent_done], 0
  612.         mov     [ebp+XFS.entries_read], 0
  613.         movzx   eax, [ebx+xfs_dir2_sf.hdr.count]
  614.         ; '..' and '.' are implicit
  615.         add     eax, 2
  616.         mov     [ebp+XFS.entries_left_in_dir], eax
  617.         mov     [edx+bdfe_hdr.total_cnt], eax
  618.         ; inode numbers are often saved as 4 bytes (iff they fit)
  619.         ; compute the length of inode numbers
  620.         ; 8 iff i8count != 0, 4 otherwise
  621.         cmp     [ebx+xfs_dir2_sf.hdr.i8count], 0
  622.         setnz   al
  623.         lea     eax, [eax*4+4]
  624.         mov     [ebp+XFS.shortform_inodelen], eax
  625.         add     edx, sizeof.bdfe_hdr
  626.         lea     esi, [ebx+xfs_dir2_sf.hdr.parent+eax]
  627.         stdcall xfs._.dir_sf_skip, [ebp+XFS.entries_to_skip]
  628.         stdcall xfs._.dir_sf_read, [ebp+XFS.requested_cnt]
  629.         ret
  630. endp
  631.  
  632.  
  633. proc xfs._.readdir_block _literal_area, _out_buf
  634.         mov     ebx, [_literal_area]
  635.         mov     [ebp+XFS.entries_read], 0
  636.         mov     eax, ebx
  637.         mov     ebx, [ebp+XFS.cur_dirblock]
  638.         stdcall xfs._.extent_unpack, eax
  639.         stdcall xfs._.read_dirblock, [ebp+XFS.extent.br_startblock.lo], [ebp+XFS.extent.br_startblock.hi], ebx
  640.         mov     edx, [_out_buf]
  641.         jnz     .error
  642.         mov     eax, [ebp+XFS.dir_block_magic]
  643.         cmp     [ebx+xfs_dir2_block.hdr.magic], eax
  644.         movi    eax, ERROR_FS_FAIL
  645.         jnz     .error
  646.         mov     eax, [ebp+XFS.dirblocksize]
  647.         movbe   ecx, [ebx+eax-sizeof.xfs_dir2_block_tail+xfs_dir2_block_tail.stale]
  648.         movbe   eax, [ebx+eax-sizeof.xfs_dir2_block_tail+xfs_dir2_block_tail.count]
  649.         sub     eax, ecx        ; actual number of entries = count - stale
  650.         mov     [ebp+XFS.entries_left_in_dir], eax
  651.         mov     [edx+bdfe_hdr.total_cnt], eax
  652.  
  653.         add     ebx, [ebp+XFS.dir_block_size]
  654.         add     edx, sizeof.bdfe_hdr
  655.         mov     [_out_buf], edx
  656.         lea     edi, [_out_buf]
  657. .next:
  658.         movi    eax, ERROR_SUCCESS
  659.         cmp     [ebp+XFS.requested_cnt], 0
  660.         jz      .quit
  661.         cmp     [ebp+XFS.entries_left_in_dir], 0
  662.         jz      .quit
  663.         stdcall xfs._.dir_entry_skip_read, edi
  664.         jz      .next
  665. .error:
  666. .quit:
  667.         ret
  668. endp
  669.  
  670.  
  671. proc xfs._.readdir_leaf_node uses esi, _inode_data, _out_buf
  672.         mov     ebx, [_inode_data]
  673.         mov     edx, [_out_buf]
  674.         mov     [ebp+XFS.cur_inode_save], ebx
  675.         mov     [ebp+XFS.entries_read], 0
  676.         mov     eax, ebx
  677.         add     eax, [ebp+XFS.inode_core_size]
  678.         movbe   edx, [ebx+xfs_inode.di_core.di_nextents]
  679.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo]
  680.         mov     [ebp+XFS.offset_begin.lo], ecx
  681.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi]
  682.         mov     [ebp+XFS.offset_begin.hi], ecx
  683.         mov     ecx, [ebp+XFS.dir2_free_offset_blocks.lo]
  684.         mov     [ebp+XFS.offset_end.lo], ecx
  685.         mov     ecx, [ebp+XFS.dir2_free_offset_blocks.hi]
  686.         mov     [ebp+XFS.offset_end.hi], ecx
  687.         stdcall xfs._.walk_extent_list, edx, eax, xfs._.extent_iterate_dirblocks, xfs._.leafn_calc_entries, 0
  688.         jnz     .error
  689.         mov     eax, [ebp+XFS.entries_read]
  690.         mov     edx, [_out_buf]
  691.         mov     [edx+bdfe_hdr.total_cnt], eax
  692.         mov     [ebp+XFS.entries_left_in_dir], eax
  693.         add     [_out_buf], sizeof.bdfe_hdr
  694.         mov     [ebp+XFS.entries_read], 0
  695.         movbe   edx, [ebx+xfs_inode.di_core.di_nextents]
  696.         mov     eax, ebx
  697.         add     eax, [ebp+XFS.inode_core_size]
  698.         lea     ecx, [_out_buf]
  699.         push    ecx
  700.         mov     [ebp+XFS.offset_begin.lo], 0
  701.         mov     [ebp+XFS.offset_begin.hi], 0
  702.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo]
  703.         mov     [ebp+XFS.offset_end.lo], ecx
  704.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi]
  705.         mov     [ebp+XFS.offset_end.hi], ecx
  706.         pop     ecx
  707.         stdcall xfs._.walk_extent_list, edx, eax, xfs._.extent_iterate_dirblocks, xfs._.dir_btree_skip_read, ecx
  708. ;        jnz     .error
  709. .error:
  710. .quit:
  711.         ret
  712. endp
  713.  
  714.  
  715. proc xfs._.dir_entry_skip_read uses esi edi, _arg
  716.         cmp     [ebx+xfs_dir2_data_union.unused.freetag], XFS_NULL
  717.         jnz     @f
  718.         movzx   eax, [ebx+xfs_dir2_data_union.unused.length]
  719.         xchg    al, ah
  720.         add     ebx, eax
  721.         jmp     .quit
  722. @@:
  723.         cmp     [ebp+XFS.entries_to_skip], 0
  724.         jz      .read
  725. .skip:
  726.         dec     [ebp+XFS.entries_to_skip]
  727.         movzx   ecx, [ebx+xfs_dir2_data_union.xentry.namelen]
  728.         lea     ebx, [ebx+xfs_dir2_data_union.xentry.name+ecx+2]
  729.         add     ebx, [ebp+XFS.ftype_size]
  730.         jmp     .common
  731. .read:
  732.         dec     [ebp+XFS.requested_cnt]
  733.         inc     [ebp+XFS.entries_read]
  734.         mov     edi, [_arg]
  735.         mov     edi, [edi]
  736.         movbe   edx, [ebx+xfs_dir2_data_union.xentry.inumber.lo]
  737.         movbe   eax, [ebx+xfs_dir2_data_union.xentry.inumber.hi]
  738.         stdcall xfs_read_inode, eax, edx, [ebp+XFS.tmp_inode]
  739.         stdcall xfs_get_inode_info, edx, edi
  740.         jnz     .error
  741.         mov     edx, [_arg]
  742.         mov     edx, [edx]
  743.         mov     ecx, [ebp+XFS.bdfe_nameenc]
  744.         mov     [edx+bdfe.nameenc], ecx
  745.         lea     edi, [edx+bdfe.name]
  746.         movzx   ecx, [ebx+xfs_dir2_data_union.xentry.namelen]
  747.         lea     esi, [ebx+xfs_dir2_data_union.xentry.name]
  748.         stdcall xfs._.copy_filename
  749.         lea     ebx, [esi+2]  ; skip 'tag'
  750.         add     ebx, [ebp+XFS.ftype_size]
  751.         mov     eax, [_arg]
  752.         mov     edx, [eax]
  753.         add     edx, [ebp+XFS.bdfe_len]
  754.         mov     [eax], edx
  755. .common:
  756.         sub     ebx, [ebp+XFS.cur_dirblock]
  757.         add     ebx, 7          ; xfs_dir2_data_entries are aligned to 8 bytes
  758.         and     ebx, not 7
  759.         add     ebx, [ebp+XFS.cur_dirblock]
  760.         dec     [ebp+XFS.entries_left_in_dir]
  761. .quit:
  762.         movi    eax, ERROR_SUCCESS
  763.         cmp     esp, esp
  764. .error:
  765.         ret
  766. endp
  767.  
  768.  
  769. proc xfs._.dir_btree_skip_read uses ebx ecx edx esi edi, _cur_dirblock, _offset_lo, _offset_hi, _arg
  770.         mov     ebx, [_cur_dirblock]
  771.         mov     eax, [ebp+XFS.dir_data_magic]
  772.         cmp     [ebx+xfs_dir2_block.hdr.magic], eax
  773.         movi    eax, ERROR_FS_FAIL
  774.         jnz     .error
  775.         mov     eax, ebx
  776.         add     eax, [ebp+XFS.dirblocksize]
  777.         mov     [ebp+XFS.max_dirblockaddr], eax
  778. ;        add     ebx, xfs_dir2_block.u
  779.         add     ebx, [ebp+XFS.dir_block_size]
  780. .next:
  781.         movi    eax, ERROR_SUCCESS
  782.         cmp     [ebp+XFS.requested_cnt], 0
  783.         jz      .quit
  784.         cmp     [ebp+XFS.entries_left_in_dir], 0
  785.         jz      .quit
  786.         cmp     ebx, [ebp+XFS.max_dirblockaddr]
  787.         jz      .quit
  788.         stdcall xfs._.dir_entry_skip_read, [_arg]
  789.         jz      .next
  790. .error:
  791. .quit:
  792.         ret
  793. endp
  794.  
  795.  
  796. proc xfs._.readdir_btree uses esi, _inode_data, _out_buf
  797.         mov     [ebp+XFS.cur_inode_save], ebx
  798.         mov     [ebp+XFS.entries_read], 0
  799.         mov     eax, [ebp+XFS.inodesize]
  800.         sub     eax, xfs_inode.di_u
  801.         movzx   ecx, [ebx+xfs_inode.di_core.di_forkoff]
  802.         jecxz   @f
  803.         shl     ecx, 3
  804.         mov     eax, ecx
  805. @@:
  806.         lea     edx, [ebx+xfs_inode.di_u]
  807.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo]
  808.         mov     [ebp+XFS.offset_begin.lo], ecx
  809.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi]
  810.         mov     [ebp+XFS.offset_begin.hi], ecx
  811.         mov     ecx, [ebp+XFS.dir2_free_offset_blocks.lo]
  812.         mov     [ebp+XFS.offset_end.lo], ecx
  813.         mov     ecx, [ebp+XFS.dir2_free_offset_blocks.hi]
  814.         mov     [ebp+XFS.offset_end.hi], ecx
  815.         stdcall xfs._.walk_btree, edx, eax, xfs._.extent_iterate_dirblocks, xfs._.leafn_calc_entries, 0, 1
  816.         mov     eax, [ebp+XFS.entries_read]
  817.         mov     edx, [_out_buf]
  818.         mov     [edx+bdfe_hdr.total_cnt], eax
  819.         mov     [ebp+XFS.entries_left_in_dir], eax
  820.         mov     [ebp+XFS.entries_read], 0
  821.         add     [_out_buf], sizeof.bdfe_hdr
  822.         mov     eax, [ebp+XFS.inodesize]
  823.         sub     eax, xfs_inode.di_u
  824.         movzx   ecx, [ebx+xfs_inode.di_core.di_forkoff]
  825.         jecxz   @f
  826.         shl     ecx, 3
  827.         mov     eax, ecx
  828. @@:
  829.         lea     edx, [ebx+xfs_inode.di_u]
  830.         mov     [ebp+XFS.offset_begin.lo], 0
  831.         mov     [ebp+XFS.offset_begin.hi], 0
  832.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.lo]
  833.         mov     [ebp+XFS.offset_end.lo], ecx
  834.         mov     ecx, [ebp+XFS.dir2_leaf_offset_blocks.hi]
  835.         mov     [ebp+XFS.offset_end.hi], ecx
  836.         mov     ecx, [_out_buf]
  837.         push    ecx
  838.         mov     ecx, esp
  839.         stdcall xfs._.walk_btree, edx, eax, xfs._.extent_iterate_dirblocks, xfs._.dir_btree_skip_read, ecx, 1
  840.         pop     ecx
  841. .error:
  842. .quit:
  843.         ret
  844. endp
  845.  
  846.  
  847. proc xfs._.copy_filename uses eax
  848.         mov     eax, [ebp+XFS.bdfe_nameenc]
  849.         cmp     eax, 3
  850.         jz      .utf8
  851.         cmp     eax, 2
  852.         jz      .utf16
  853. .cp866:
  854.         call    unicode.utf8.decode
  855.         call    unicode.cp866.encode
  856.         stosb
  857.         test    ecx, ecx
  858.         jnz     .cp866
  859.         mov     byte[edi], 0
  860.         jmp     .done
  861. .utf16:
  862.         call    unicode.utf8.decode
  863.         call    unicode.utf16.encode
  864.         stosw
  865.         shr     eax, 16
  866.         jz      @f
  867.         stosw
  868. @@:
  869.         test    ecx, ecx
  870.         jnz     .utf16
  871.         mov     word[edi], 0
  872.         jmp     .done
  873. .utf8:
  874.         rep movsb
  875.         mov     byte[edi], 0
  876. .done:
  877.         ret
  878. endp
  879.  
  880. ;----------------------------------------------------------------
  881. ; src              ; inode
  882. ; dst              ; bdfe
  883. ; start_number     ; from 0
  884. ;----------------------------------------------------------------
  885. proc xfs._.readdir uses ebx esi edi, _start_number, _entries_to_read, _dst, _src, _encoding
  886.         mov     ecx, [_start_number]
  887.         mov     [ebp+XFS.entries_to_skip], ecx
  888.         mov     eax, [_entries_to_read]
  889.         mov     [ebp+XFS.requested_cnt], eax
  890.         mov     eax, [_encoding]
  891.         mov     [ebp+XFS.bdfe_nameenc], eax
  892.         mov     ecx, 304
  893.         cmp     eax, 1  ; CP866
  894.         jbe     @f
  895.         mov     ecx, 560
  896. @@:
  897.         mov     [ebp+XFS.bdfe_len], ecx
  898.         mov     edx, [_dst]
  899.         mov     [ebp+XFS.bdfe_buf], edx
  900.         mov     ebx, [_src]
  901.         mov     [ebp+XFS.cur_inode_save], ebx
  902.  
  903.         mov     [edx+bdfe_hdr.version], 1
  904.         mov     [edx+bdfe_hdr.zeroed+0x00], 0
  905.         mov     [edx+bdfe_hdr.zeroed+0x04], 0
  906.         mov     [edx+bdfe_hdr.zeroed+0x08], 0
  907.         mov     [edx+bdfe_hdr.zeroed+0x0c], 0
  908.         mov     [edx+bdfe_hdr.zeroed+0x10], 0
  909.  
  910.         movzx   eax, [ebx+xfs_inode.di_core.di_format]
  911.         ; switch directory ondisk format and jump to corresponding label
  912.         cmp     eax, XFS_DINODE_FMT_LOCAL
  913.         jnz     @f
  914.         add     ebx, [ebp+XFS.inode_core_size]
  915.         stdcall xfs._.readdir_sf, ebx, [_dst]
  916.         test    eax, eax
  917.         jnz     .error
  918.         jmp     .quit
  919. @@:
  920.         cmp     eax, XFS_DINODE_FMT_BTREE
  921.         jnz     @f
  922.         stdcall xfs._.readdir_btree, ebx, [_dst]
  923.         jmp     .quit
  924. @@:
  925.         cmp     eax, XFS_DINODE_FMT_EXTENTS
  926.         movi    eax, ERROR_FS_FAIL
  927.         jnz     .error
  928.         call    xfs._.get_last_dirblock
  929.         test    eax, eax
  930.         jnz     @f
  931.         add     ebx, [ebp+XFS.inode_core_size]
  932.         stdcall xfs._.readdir_block, ebx, [_dst]
  933.         jmp     .quit
  934. @@:
  935.         stdcall xfs._.readdir_leaf_node, ebx, [_dst]
  936.         jmp     .quit
  937. .quit:
  938.         mov     edx, [_dst]
  939.         mov     ebx, [ebp+XFS.entries_read]
  940.         mov     [edx+bdfe_hdr.read_cnt], ebx
  941.         xor     eax, eax
  942. .error:
  943.         ret
  944. endp
  945.  
  946.  
  947. ; returns edx:eax inode or 0
  948. proc xfs._.lookup_sf _name, _len
  949.         add     ebx, [ebp+XFS.inode_core_size]
  950.         mov     esi, [_name]
  951.         mov     ecx, [_len]
  952.         cmp     ecx, 2
  953.         ja      .common
  954.         jz      .check_parent
  955. .check_self:
  956.         cmp     byte[esi], '.'
  957.         jnz     .common
  958.         mov     eax, [ebp+XFS.inode_self.lo]
  959.         mov     edx, [ebp+XFS.inode_self.hi]
  960.         jmp     .quit
  961. .check_parent:
  962.         cmp     word[esi], '..'
  963.         jnz     .common
  964.         lea     edx, [ebx+xfs_dir2_sf.hdr.parent]
  965.         call    xfs._.get_inode_number_sf
  966.         jmp     .quit
  967. .common:
  968.         movzx   edx, [ebx+xfs_dir2_sf.hdr.count]
  969.         movi    eax, 0
  970.         cmp     [ebx+xfs_dir2_sf.hdr.i8count], 0
  971.         setnz   al
  972.         lea     eax, [eax*4+4]
  973.         lea     edi, [ebx+xfs_dir2_sf.hdr.parent+eax]
  974. .next_name:
  975.         dec     edx
  976.         jns     @f
  977.         movi    eax, ERROR_FILE_NOT_FOUND
  978.         jmp     .error
  979. @@:
  980.         movzx   ecx, [edi+xfs_dir2_sf_entry.namelen]
  981.         add     edi, xfs_dir2_sf_entry.name
  982.         mov     esi, [_name]
  983.         cmp     ecx, [_len]
  984.         jnz     @f
  985.         repz cmpsb
  986.         jz      .found
  987. @@:
  988.         add     edi, [ebp+XFS.ftype_size]
  989.         add     edi, ecx
  990.         add     edi, eax
  991.         jmp     .next_name
  992. .found:
  993.         add     edi, [ebp+XFS.ftype_size]
  994.         mov     edx, edi
  995.         call    xfs._.get_inode_number_sf
  996. .quit:
  997.         cmp     esp, esp
  998. .error:
  999.         ret
  1000. endp
  1001.  
  1002.  
  1003. proc xfs._.lookup_block uses esi, _name, _len
  1004.         add     ebx, [ebp+XFS.inode_core_size]
  1005.         mov     eax, ebx
  1006.         mov     ebx, [ebp+XFS.cur_dirblock]
  1007.         stdcall xfs._.extent_unpack, eax
  1008.         stdcall xfs._.read_dirblock, [ebp+XFS.extent.br_startblock.lo], [ebp+XFS.extent.br_startblock.hi], ebx
  1009.         jnz     .error
  1010.         mov     eax, [ebp+XFS.dir_block_magic]
  1011.         cmp     [ebx+xfs_dir2_block.hdr.magic], eax
  1012.         movi    eax, ERROR_FS_FAIL
  1013.         jnz     .error
  1014.         stdcall xfs_hashname, [_name+4], [_len]
  1015.         add     ebx, [ebp+XFS.dirblocksize]
  1016.         movbe   ecx, [ebx-sizeof.xfs_dir2_block_tail+xfs_dir2_block_tail.count]
  1017.         lea     edx, [ecx*sizeof.xfs_dir2_leaf_entry+sizeof.xfs_dir2_block_tail]
  1018.         sub     ebx, edx
  1019.         stdcall xfs._.get_addr_by_hash, ebx, ecx
  1020.         jnz     .error
  1021.         mov     ebx, [ebp+XFS.cur_dirblock]
  1022.         movbe   edx, [ebx+eax*XFS_DIR2_DATA_ALIGN+xfs_dir2_data_entry.inumber.lo]
  1023.         movbe   eax, [ebx+eax*XFS_DIR2_DATA_ALIGN+xfs_dir2_data_entry.inumber.hi]
  1024. .quit:
  1025. .error:
  1026.         ret
  1027. endp
  1028.  
  1029.  
  1030. proc xfs._.get_inode_by_addr uses ebx esi edi, _inode_buf
  1031.         xor     edx, edx
  1032.         shld    edx, eax, XFS_DIR2_DATA_ALIGN_LOG
  1033.         shl     eax, XFS_DIR2_DATA_ALIGN_LOG
  1034.         mov     esi, [ebp+XFS.dirblocksize]
  1035.         dec     esi
  1036.         and     esi, eax
  1037.         mov     ecx, [ebp+XFS.blocklog]
  1038.         add     ecx, [ebp+XFS.dirblklog]
  1039.         shrd    eax, edx, cl
  1040.         shr     edx, cl
  1041.         mov     ecx, [ebp+XFS.dirblklog]
  1042.         shld    edx, eax, cl
  1043.         shl     eax, cl
  1044.         mov     ebx, [_inode_buf]
  1045.         cmp     [ebx+xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  1046.         jz      .extents
  1047.         cmp     [ebx+xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE
  1048.         jz      .btree
  1049.         jmp     .error
  1050. .extents:
  1051.         movbe   ecx, [ebx+xfs_inode.di_core.di_nextents]
  1052.         add     ebx, [ebp+XFS.inode_core_size]
  1053.         mov     [ebp+XFS.offset_begin.lo], eax
  1054.         mov     [ebp+XFS.offset_begin.hi], edx
  1055.         stdcall xfs._.extent_list.seek, ecx
  1056.         stdcall xfs._.read_dirblock, [ebp+XFS.extent.br_startblock.lo], [ebp+XFS.extent.br_startblock.hi], [ebp+XFS.cur_dirblock]
  1057.         jnz     .error
  1058.         jmp     .common
  1059. .btree:
  1060.         movzx   ecx, [ebx+xfs_inode.di_core.di_forkoff]
  1061.         shl     ecx, 3
  1062.         test    ecx, ecx
  1063.         jnz     @f
  1064.         mov     ecx, [ebp+XFS.inodesize]
  1065.         sub     ecx, [ebp+XFS.inode_core_size]
  1066. @@:
  1067.         add     ebx, [ebp+XFS.inode_core_size]
  1068.         stdcall xfs._.btree_read_block, ebx, ecx, eax, edx, [ebp+XFS.cur_dirblock]
  1069. .common:
  1070.         mov     ebx, [ebp+XFS.cur_dirblock]
  1071.         mov     eax, [ebp+XFS.dir_data_magic]
  1072.         cmp     [ebx+xfs_dir2_block.hdr.magic], eax
  1073.         movi    eax, ERROR_FS_FAIL
  1074.         jnz     .error
  1075.         movbe   edx, [ebx+esi+xfs_dir2_data_entry.inumber.lo]
  1076.         movbe   eax, [ebx+esi+xfs_dir2_data_entry.inumber.hi]
  1077. .error:
  1078. .quit:
  1079.         ret
  1080. endp
  1081.  
  1082.  
  1083. proc xfs._.lookup_leaf uses ebx esi edi, _name, _len
  1084.         movbe   ecx, [ebx+xfs_inode.di_core.di_nextents]
  1085.         add     ebx, [ebp+XFS.inode_core_size]
  1086.         mov     eax, [ebp+XFS.dir2_leaf_offset_blocks.lo]
  1087.         mov     [ebp+XFS.offset_begin.lo], ecx
  1088.         mov     eax, [ebp+XFS.dir2_leaf_offset_blocks.hi]
  1089.         mov     [ebp+XFS.offset_begin.hi], ecx
  1090.         stdcall xfs._.extent_list.seek, ecx
  1091.         stdcall xfs._.read_dirblock, [ebp+XFS.extent.br_startblock.lo], [ebp+XFS.extent.br_startblock.hi], [ebp+XFS.cur_dirblock]
  1092.         jnz     .error
  1093.         mov     ebx, [ebp+XFS.cur_dirblock]
  1094.         movzx   eax, [ebp+XFS.dir_leaf1_magic]
  1095.         cmp     [ebx+xfs_dir2_leaf.hdr.info.magic], ax
  1096.         movi    eax, ERROR_FS_FAIL
  1097.         jnz     .error
  1098.         stdcall xfs_hashname, [_name+4], [_len]
  1099.         cmp     [ebp+XFS.version], 5
  1100.         jz      .v5
  1101. .v4:
  1102.         movzx   ecx, [ebx+xfs_dir2_leaf.hdr.count]
  1103.         xchg    cl, ch
  1104.         add     ebx, xfs_dir2_leaf.ents
  1105.         jmp     .vcommon
  1106. .v5:
  1107.         movzx   ecx, [ebx+xfs_dir3_leaf.hdr.count]
  1108.         xchg    cl, ch
  1109.         add     ebx, xfs_dir3_leaf.ents
  1110. .vcommon:
  1111.         stdcall xfs._.get_addr_by_hash, ebx, ecx
  1112.         jnz     .error
  1113.         stdcall xfs._.get_inode_by_addr, [ebp+XFS.cur_inode_save]
  1114. .quit:
  1115. .error:
  1116.         ret
  1117. endp
  1118.  
  1119.  
  1120. proc xfs._.lookup_node uses ebx esi edi, _name, _len
  1121. locals
  1122.         .hash dd ?
  1123. endl
  1124.         mov     [ebp+XFS.cur_inode_save], ebx
  1125.         stdcall xfs_hashname, [_name+4], [_len]
  1126.         mov     [.hash], eax
  1127.         mov     eax, ebx
  1128.         add     eax, [ebp+XFS.inode_core_size]
  1129.         movbe   edx, [ebx+xfs_inode.di_core.di_nextents]
  1130.         mov     esi, [ebp+XFS.dir2_leaf_offset_blocks.lo]
  1131. .begin:
  1132.         mov     ebx, [ebp+XFS.cur_inode_save]
  1133.         mov     eax, ebx
  1134.         add     eax, [ebp+XFS.inode_core_size]
  1135.         movbe   edx, [ebx+xfs_inode.di_core.di_nextents]
  1136.         mov     ebx, eax
  1137.         mov     [ebp+XFS.offset_begin.lo], esi
  1138.         mov     [ebp+XFS.offset_begin.hi], 0
  1139.         stdcall xfs._.extent_list.seek, edx
  1140.         stdcall xfs._.read_dirblock, [ebp+XFS.extent.br_startblock.lo], [ebp+XFS.extent.br_startblock.hi], [ebp+XFS.cur_dirblock]
  1141.         jnz     .error
  1142.         mov     ebx, [ebp+XFS.cur_dirblock]
  1143.         movzx   eax, [ebp+XFS.da_node_magic]
  1144.         cmp     [ebx+xfs_da_intnode.hdr.info.magic], ax
  1145.         jz      .node
  1146.         movzx   eax, [ebp+XFS.dir_leafn_magic]
  1147.         cmp     [ebx+xfs_dir2_leaf.hdr.info.magic], ax
  1148.         jz      .leaf
  1149.         movi    eax, ERROR_FS_FAIL
  1150.         jmp     .error
  1151. .node:
  1152.         cmp     [ebp+XFS.version], 5
  1153.         jz      .node.v5
  1154. .node.v4:
  1155.         lea     eax, [ebx+sizeof.xfs_da_intnode]
  1156.         movzx   edx, [ebx+xfs_da_intnode.hdr.count]
  1157.         jmp     .node.vcommon
  1158. .node.v5:
  1159.         lea     eax, [ebx+sizeof.xfs_da3_intnode]
  1160.         movzx   edx, [ebx+xfs_da3_intnode.hdr.count]
  1161. .node.vcommon:
  1162.         xchg    dl, dh
  1163.         stdcall xfs._.get_before_by_hashval, eax, edx, [.hash]
  1164.         jnz     .error
  1165.         mov     esi, eax
  1166.         jmp     .begin
  1167. .leaf:
  1168.         cmp     [ebp+XFS.version], 5
  1169.         jz      .leaf.v5
  1170. .leaf.v4:
  1171.         movzx   ecx, [ebx+xfs_dir2_leaf.hdr.count]
  1172.         xchg    cl, ch
  1173.         add     ebx, xfs_dir2_leaf.ents
  1174.         jmp     .leaf.vcommon
  1175. .leaf.v5:
  1176.         movzx   ecx, [ebx+xfs_dir3_leaf.hdr.count]
  1177.         xchg    cl, ch
  1178.         add     ebx, xfs_dir3_leaf.ents
  1179. .leaf.vcommon:
  1180.         mov     eax, [.hash]
  1181.         stdcall xfs._.get_addr_by_hash, ebx, ecx
  1182.         jnz     .error
  1183.         stdcall xfs._.get_inode_by_addr, [ebp+XFS.cur_inode_save]
  1184. .quit:
  1185.         cmp     esp, esp
  1186.         ret
  1187. .error:
  1188.         test    esp, esp
  1189.         ret
  1190. endp
  1191.  
  1192.  
  1193. proc xfs._.lookup_btree uses ebx esi edi, _name, _len
  1194. locals
  1195.         .hash dd ?
  1196. endl
  1197.         mov     [ebp+XFS.cur_inode_save], ebx
  1198.         stdcall xfs_hashname, [_name+4], [_len]
  1199.         mov     [.hash], eax
  1200.         mov     edx, [ebp+XFS.dir2_leaf_offset_blocks.hi]
  1201.         mov     eax, [ebp+XFS.dir2_leaf_offset_blocks.lo]
  1202.         jmp     .next_level.first
  1203. .next_level:
  1204.         lea     eax, [ebx+sizeof.xfs_da_intnode]
  1205.         movzx   edx, [ebx+xfs_da_intnode.hdr.count]
  1206.         xchg    dl, dh
  1207.         stdcall xfs._.get_before_by_hashval, eax, edx, [.hash]
  1208.         jnz     .error
  1209.         xor     edx, edx
  1210. .next_level.first:
  1211.         mov     ebx, [ebp+XFS.cur_inode_save]
  1212.         movzx   ecx, [ebx+xfs_inode.di_core.di_forkoff]
  1213.         shl     ecx, 3
  1214.         test    ecx, ecx
  1215.         jnz     @f
  1216.         mov     ecx, [ebp+XFS.inodesize]
  1217.         sub     ecx, xfs_inode.di_u
  1218. @@:
  1219.         add     ebx, xfs_inode.di_u
  1220.         stdcall xfs._.btree_read_block, ebx, ecx, eax, edx, [ebp+XFS.cur_dirblock]
  1221.         mov     ebx, [ebp+XFS.cur_dirblock]
  1222.         cmp     [ebx+xfs_da_intnode.hdr.info.magic], XFS_DA_NODE_MAGIC
  1223.         jz      .next_level
  1224.         cmp     [ebx+xfs_dir2_leaf.hdr.info.magic], XFS_DIR2_LEAFN_MAGIC
  1225.         jz      .leafn
  1226.         cmp     [ebx+xfs_dir2_leaf.hdr.info.magic], XFS_DIR2_LEAF1_MAGIC
  1227.         jnz     .error
  1228.         mov     eax, [.hash]
  1229.         movzx   ecx, [ebx+xfs_dir2_leaf.hdr.count]
  1230.         xchg    cl, ch
  1231.         add     ebx, xfs_dir2_leaf.ents
  1232.         stdcall xfs._.get_addr_by_hash, ebx, ecx
  1233.         jnz     .error
  1234.         mov     ebx, [ebp+XFS.cur_dirblock]
  1235.         jmp     .got_addr
  1236. .leafn:
  1237.         movzx   ecx, [ebx+xfs_dir2_leaf.hdr.count]
  1238.         xchg    cl, ch
  1239.         add     ebx, xfs_dir2_leaf.ents
  1240.         mov     eax, [.hash]
  1241.         stdcall xfs._.get_addr_by_hash, ebx, ecx
  1242.         jnz     .error
  1243.         mov     ebx, [ebp+XFS.cur_block]
  1244. .got_addr:
  1245.         stdcall xfs._.get_inode_by_addr, [ebp+XFS.cur_inode_save]
  1246. .quit:
  1247.         cmp     esp, esp
  1248.         ret
  1249. .error:
  1250.         test    esp, esp
  1251.         ret
  1252. endp
  1253.  
  1254.  
  1255. ; search for the _name in _inode dir
  1256. ; called for each /path/component/to/my/file
  1257. ; out:
  1258. ; ZF/zf   = ok/fail
  1259. ; edx:eax = inode/garbage:error
  1260. proc xfs._.get_inode_short uses esi, _inode:qword, _len, _name
  1261.         mov     esi, [_name]
  1262.         mov     eax, dword[_inode+DQ.lo]
  1263.         mov     edx, dword[_inode+DQ.hi]
  1264.         stdcall xfs_read_inode, eax, edx, [ebp+XFS.cur_inode]
  1265.         test    eax, eax
  1266.         movi    eax, ERROR_FS_FAIL
  1267.         jnz     .error
  1268.         ; switch directory ondisk format
  1269.         mov     ebx, edx
  1270.         mov     [ebp+XFS.cur_inode_save], ebx
  1271.         movzx   eax, [ebx+xfs_inode.di_core.di_format]
  1272.         cmp     eax, XFS_DINODE_FMT_LOCAL
  1273.         mov     edi, xfs._.lookup_sf
  1274.         jz      .lookup
  1275.         cmp     eax, XFS_DINODE_FMT_BTREE
  1276.         mov     edi, xfs._.lookup_btree
  1277.         jz      .lookup
  1278.         cmp     eax, XFS_DINODE_FMT_EXTENTS
  1279.         jnz     .error
  1280.         call    xfs._.get_last_dirblock
  1281.         test    eax, eax
  1282.         mov     edi, xfs._.lookup_block
  1283.         jz      .lookup
  1284.         cmp     edx, [ebp+XFS.dir2_free_offset_blocks.hi]
  1285.         mov     edi, xfs._.lookup_node
  1286.         ja      .lookup
  1287.         cmp     eax, [ebp+XFS.dir2_free_offset_blocks.lo]
  1288.         jae     .lookup
  1289.         mov     edi, xfs._.lookup_leaf
  1290. .lookup:
  1291.         stdcall edi, [_name+4], [_len]
  1292. .error:
  1293.         ret
  1294. endp
  1295.  
  1296.  
  1297. ; ZF/zf   = ok/fail
  1298. ; edx:eax = inode/garbage:error
  1299. proc xfs_get_inode uses ebx esi edi, _name
  1300.         ; call *._.get_inode_short until file is found / error returned
  1301.         ; start from the root inode
  1302.         mov     eax, [ebp+XFS.rootino.lo]
  1303.         mov     edx, [ebp+XFS.rootino.hi]
  1304.         mov     esi, [_name]
  1305. .next_dir:
  1306. @@:
  1307.         cmp     byte[esi], '/'
  1308.         jnz     @f
  1309.         inc     esi
  1310.         jmp     @b
  1311. @@:
  1312.         cmp     byte[esi], 0
  1313.         jz      .found
  1314.         push    esi
  1315.         inc     esi
  1316. @@:
  1317.         cmp     byte[esi], 0
  1318.         jz      @f
  1319.         cmp     byte[esi], '/'
  1320.         jz      @f
  1321.         inc     esi
  1322.         jmp     @b
  1323. @@:
  1324.         mov     ecx, esi
  1325.         sub     ecx, [esp]
  1326.         mov     [ebp+XFS.inode_self.lo], eax
  1327.         mov     [ebp+XFS.inode_self.hi], edx
  1328.         stdcall xfs._.get_inode_short, eax, edx, ecx      ; esi pushed above
  1329.         jz      .next_dir
  1330. .error:
  1331. .found:
  1332.         ret
  1333. endp
  1334.  
  1335.  
  1336. ; in:  ebp = pointer to XFS structure
  1337. ; in:  esi
  1338. ; in:  ebx = pointer to parameters from sysfunc 70
  1339. ; out: eax, ebx = return values for sysfunc 70
  1340. ; out: [edx] -- f70.1 out structure
  1341. proc xfs_ReadFolder uses esi edi
  1342.         call    xfs._.lock
  1343.         stdcall xfs_get_inode, esi
  1344.         jnz     .error
  1345.         stdcall xfs_read_inode, eax, edx, [ebp+XFS.cur_inode]
  1346.         test    eax, eax
  1347.         jnz     .error
  1348.         stdcall xfs._.readdir, [ebx+f70s1arg.start_idx], [ebx+f70s1arg.count], [ebx+f70s1arg.buf], edx, [ebx+f70s1arg.encoding]
  1349.         test    eax, eax
  1350.         jnz     .error
  1351.         mov     edx, [ebx+f70s1arg.buf]
  1352.         mov     ecx, [ebx+f70s1arg.count]
  1353.         cmp     [edx+bdfe_hdr.read_cnt], ecx
  1354.         jz      .quit
  1355.         movi    eax, ERROR_END_OF_FILE
  1356. .quit:
  1357.         mov     ebx, [edx+bdfe_hdr.read_cnt]
  1358.  
  1359. .error:
  1360.         push    eax
  1361.         call    xfs._.unlock
  1362.         pop     eax
  1363.         ret
  1364. endp
  1365.  
  1366.  
  1367. ; edx -- pointer to inode number in big endian
  1368. ; ZF -- must be set at exit
  1369. proc xfs._.get_inode_number_sf
  1370.         cmp     [ebx+xfs_dir2_sf.hdr.i8count], 0
  1371.         jz      .i4bytes
  1372. .i8bytes:
  1373.         movbe   eax, [edx+DQ.hi]
  1374.         movbe   edx, [edx+DQ.lo]
  1375.         ret
  1376. .i4bytes:
  1377.         movbe   eax, [edx+DQ.lo]
  1378.         xor     edx, edx
  1379.         ret
  1380. endp
  1381.  
  1382. proc xfs._.conv_time_to_kos_epoch
  1383.         movbe   eax, [ecx+DQ.hi_be]
  1384.         call    fsTime2bdfe
  1385.         ret
  1386. endp
  1387.  
  1388. proc xfs._.conv_bigtime_to_kos_epoch
  1389. NANOSEC_PER_SEC = 1_000_000_000
  1390. BIGTIME_TO_UNIX_OFFSET = 0x80000000     ; int32 min
  1391. UNIXTIME_TO_KOS_OFFSET = (365*31+8)*24*60*60  ; 01.01.1970--01.01.2001
  1392. BIGTIME_TO_KOS_OFFSET = BIGTIME_TO_UNIX_OFFSET + UNIXTIME_TO_KOS_OFFSET
  1393. BIGTIME_TO_KOS_OFFSET_NS = BIGTIME_TO_KOS_OFFSET * NANOSEC_PER_SEC
  1394.         movbe   edx, [ecx+DQ.hi_be]
  1395.         movbe   eax, [ecx+DQ.lo_be]
  1396.         sub     eax, BIGTIME_TO_KOS_OFFSET_NS AND 0xffffffff
  1397.         sbb     edx, BIGTIME_TO_KOS_OFFSET_NS SHR 32
  1398.         jnc     .after_kos_epoch_begin
  1399.         xor     eax, eax        ; set to very begin of kolibrios epoch
  1400.         xor     edx, edx
  1401.         jmp     .time_to_bdfe
  1402. .after_kos_epoch_begin:
  1403.         cmp     edx, NANOSEC_PER_SEC
  1404.         jb      .time_to_bdfe
  1405.         mov     edx, NANOSEC_PER_SEC - 1
  1406.         mov     eax, -1         ; very end of kolibrios epoch
  1407. .time_to_bdfe:
  1408.         mov     ecx, NANOSEC_PER_SEC
  1409.         div     ecx
  1410.         call    fsTime2bdfe
  1411.         ret
  1412. endp
  1413.  
  1414. proc xfs_get_inode_info uses ebx esi edi, _src, _dst
  1415.         ; get access time and other file properties
  1416.         ; useful for browsing directories
  1417.         ; called for each dir entry
  1418.         xor     eax, eax
  1419.         mov     esi, [_src]
  1420.         movzx   ecx, [esi+xfs_inode.di_core.di_mode]
  1421.         xchg    cl, ch
  1422.         test    ecx, S_IFDIR
  1423.         jz      @f
  1424.         movi    eax, 0x10       ; set directory flag
  1425. @@:
  1426.         mov     edi, [_dst]
  1427.         mov     [edi+bdfe.attr], eax
  1428.         movbe   edx, [esi+xfs_inode.di_core.di_size.hi_be]
  1429.         movbe   eax, [esi+xfs_inode.di_core.di_size.lo_be]
  1430.         mov     [edi+bdfe.size.hi], edx
  1431.         mov     [edi+bdfe.size.lo], eax
  1432.  
  1433.         add     edi, bdfe.ctime
  1434.         lea     ecx, [esi+xfs_inode.di_core.di_ctime]
  1435.         call    [ebp+XFS.conv_time_to_kos_epoch]
  1436.         lea     ecx, [esi+xfs_inode.di_core.di_atime]
  1437.         call    [ebp+XFS.conv_time_to_kos_epoch]
  1438.         lea     ecx, [esi+xfs_inode.di_core.di_mtime]
  1439.         call    [ebp+XFS.conv_time_to_kos_epoch]
  1440.  
  1441.         movi    eax, ERROR_SUCCESS
  1442.         cmp     esp, esp
  1443.         ret
  1444. endp
  1445.  
  1446.  
  1447. proc xfs._.extent_unpack uses eax ebx ecx edx, _extent_data
  1448.         ; extents come as packet 128bit bitfields
  1449.         ; unpack them to access internal fields
  1450.         ; write result to the XFS.extent structure
  1451.         mov     ebx, [_extent_data]
  1452.  
  1453.         xor     eax, eax
  1454.         movbe   edx, [ebx+0]
  1455.         test    edx, 0x80000000         ; mask, see documentation
  1456.         setnz   al
  1457.         mov     [ebp+XFS.extent.br_state], eax
  1458.  
  1459.         and     edx, 0x7fffffff         ; mask
  1460.         movbe   eax, [ebx+4]
  1461.         shrd    eax, edx, 9
  1462.         shr     edx, 9
  1463.         mov     [ebp+XFS.extent.br_startoff.lo], eax
  1464.         mov     [ebp+XFS.extent.br_startoff.hi], edx
  1465.  
  1466.         movbe   edx, [ebx+4]
  1467.         movbe   eax, [ebx+8]
  1468.         movbe   ecx, [ebx+12]
  1469.         and     edx, 0x000001ff         ; mask
  1470.         shrd    ecx, eax, 21
  1471.         shrd    eax, edx, 21
  1472.         mov     [ebp+XFS.extent.br_startblock.lo], ecx
  1473.         mov     [ebp+XFS.extent.br_startblock.hi], eax
  1474.  
  1475.         movbe   eax, [ebx+12]
  1476.         and     eax, 0x001fffff         ; mask
  1477.         mov     [ebp+XFS.extent.br_blockcount], eax
  1478.         ret
  1479. endp
  1480.  
  1481.  
  1482. proc xfs_hashname uses ecx esi, _name, _len
  1483.         xor     eax, eax
  1484.         mov     esi, [_name]
  1485.         mov     ecx, [_len]
  1486. @@:
  1487.         rol     eax, 7
  1488.         xor     al, [esi]
  1489.         add     esi, 1
  1490.         dec     ecx
  1491.         jnz     @b
  1492.         ret
  1493. endp
  1494.  
  1495.  
  1496. ; eax -- hash value
  1497. proc xfs._.get_addr_by_hash uses ebx esi, _base, _len
  1498.         ; look for the directory entry offset by its file name hash
  1499.         ; allows fast file search for block, leaf and node directories
  1500.         ; binary (ternary) search
  1501.         mov     ebx, [_base]
  1502.         mov     edx, [_len]
  1503. .next:
  1504.         mov     ecx, edx
  1505. ;        jecxz   .error
  1506.         test    ecx, ecx
  1507.         jz      .not_found
  1508.         shr     ecx, 1
  1509.         movbe   esi, [ebx+ecx*sizeof.xfs_dir2_leaf_entry+xfs_dir2_leaf_entry.hashval]
  1510.         cmp     eax, esi
  1511.         jb      .below
  1512.         ja      .above
  1513.         movbe   eax, [ebx+ecx*sizeof.xfs_dir2_leaf_entry+xfs_dir2_leaf_entry.address]
  1514.         ret
  1515. .below:
  1516.         mov     edx, ecx
  1517.         jmp     .next
  1518. .above:
  1519.         lea     ebx, [ebx+(ecx+1)*sizeof.xfs_dir2_leaf_entry]
  1520.         sub     edx, ecx
  1521.         dec     edx
  1522.         jmp     .next
  1523. .not_found:
  1524.         movi    eax, ERROR_FILE_NOT_FOUND
  1525.         test    esp, esp
  1526.         ret
  1527. endp
  1528.  
  1529.  
  1530. ;----------------------------------------------------------------
  1531. ; xfs_GetFileInfo: XFS implementation of getting file info
  1532. ; in:  ebp = pointer to XFS structure
  1533. ; in:  esi = name
  1534. ; in:  ebx = pointer to parameters from sysfunc 70
  1535. ; out: eax, ebx = return values for sysfunc 70
  1536. ;----------------------------------------------------------------
  1537. proc xfs_GetFileInfo uses ecx edx esi edi
  1538.         call    xfs._.lock
  1539.         stdcall xfs_get_inode, esi
  1540.         jnz     .error
  1541.         stdcall xfs_read_inode, eax, edx, [ebp+XFS.cur_inode]
  1542.         test    eax, eax
  1543.         movi    eax, ERROR_FS_FAIL
  1544.         jnz     .error
  1545.         stdcall xfs_get_inode_info, edx, [ebx+f70s5arg.buf]
  1546. .quit:
  1547.         call    xfs._.unlock
  1548.         xor     eax, eax
  1549.         ret
  1550. .error:
  1551.         push    eax
  1552.         call    xfs._.unlock
  1553.         pop     eax
  1554.         ret
  1555. endp
  1556.  
  1557.  
  1558. proc xfs._.file.read_extent uses ebx ecx edx, _callback, _callback_data
  1559.         mov     eax, [ebp+XFS.file_offset.lo]
  1560.         mov     edx, [ebp+XFS.file_offset.hi]
  1561.         mov     esi, [ebp+XFS.extent.br_startoff.lo]
  1562.         mov     edi, [ebp+XFS.extent.br_startoff.hi]
  1563.         mov     ecx, [ebp+XFS.blocklog]
  1564.         shld    edi, esi, cl
  1565.         shl     esi, cl
  1566.         cmp     edx, edi
  1567.         jb      .hole
  1568.         ja      .try_head
  1569.         cmp     eax, esi
  1570.         ja      .try_head
  1571.         jz      .try_match
  1572. .hole:
  1573.         sub     esi, eax
  1574.         sbb     edi, edx
  1575.         movi    ecx, -1
  1576.         test    edi, edi
  1577.         jnz     @f
  1578.         mov     ecx, esi
  1579. @@:
  1580.         cmp     ecx, [ebp+XFS.bytes_to_read]
  1581.         jbe     @f
  1582.         mov     ecx, [ebp+XFS.bytes_to_read]
  1583. @@:
  1584.         mov     edi, [ebp+XFS.file_buffer]
  1585.         xor     eax, eax
  1586.         sub     [ebp+XFS.bytes_to_read], ecx
  1587.         sub     [ebp+XFS.bytes_left_in_file.lo], ecx
  1588.         sbb     [ebp+XFS.bytes_left_in_file.hi], 0
  1589.         add     [ebp+XFS.bytes_read], ecx
  1590.         add     [ebp+XFS.file_buffer], ecx
  1591.         add     [ebp+XFS.file_offset.lo], ecx
  1592.         adc     [ebp+XFS.file_offset.hi], 0
  1593.         rep stosb
  1594.         cmp     [ebp+XFS.bytes_to_read], 0
  1595.         jz      .quit
  1596.         jmp     .try_match
  1597. .try_head:
  1598.         mov     eax, [ebp+XFS.file_offset.lo]
  1599.         mov     ecx, [ebp+XFS.blocksize]
  1600.         dec     ecx
  1601.         test    eax, ecx
  1602.         jz      .try_match
  1603. .head:
  1604.         mov     eax, [ebp+XFS.extent.br_startblock.lo]
  1605.         mov     edx, [ebp+XFS.extent.br_startblock.hi]
  1606.         mov     ebx, [ebp+XFS.cur_block_data]
  1607.         stdcall xfs._.read_block
  1608.         mov     esi, [ebp+XFS.cur_block_data]
  1609.         mov     edi, [ebp+XFS.file_buffer]
  1610.         mov     eax, [ebp+XFS.file_offset.lo]
  1611.         mov     ecx, [ebp+XFS.blocksize]
  1612.         dec     ecx
  1613.         and     eax, ecx
  1614.         add     esi, eax
  1615.         inc     ecx
  1616.         sub     ecx, eax
  1617.         cmp     ecx, [ebp+XFS.bytes_to_read]
  1618.         jbe     @f
  1619.         mov     ecx, [ebp+XFS.bytes_to_read]
  1620. @@:
  1621.         sub     [ebp+XFS.bytes_to_read], ecx
  1622.         sub     [ebp+XFS.bytes_left_in_file.lo], ecx
  1623.         sbb     [ebp+XFS.bytes_left_in_file.hi], 0
  1624.         add     [ebp+XFS.bytes_read], ecx
  1625.         add     [ebp+XFS.file_buffer], ecx
  1626.         add     [ebp+XFS.file_offset.lo], ecx
  1627.         adc     [ebp+XFS.file_offset.hi], 0
  1628.         rep movsb
  1629.         add     [ebp+XFS.extent.br_startoff.lo], 1
  1630.         adc     [ebp+XFS.extent.br_startoff.hi], 0
  1631.         add     [ebp+XFS.extent.br_startblock.lo], 1
  1632.         adc     [ebp+XFS.extent.br_startblock.hi], 0
  1633.         dec     [ebp+XFS.extent.br_blockcount]
  1634. ;        cmp     [ebp+XFS.bytes_to_read], 0
  1635.         jz      .quit
  1636. .try_match:
  1637.         mov     eax, [ebp+XFS.bytes_to_read]
  1638.         test    eax, eax
  1639.         jz      .quit
  1640.         cmp     eax, [ebp+XFS.blocksize]
  1641.         jb      .tail
  1642.         mov     ecx, [ebp+XFS.blocklog]
  1643.         shr     eax, cl
  1644.         cmp     eax, [ebp+XFS.extent.br_blockcount]
  1645.         jbe     @f
  1646.         mov     eax, [ebp+XFS.extent.br_blockcount]
  1647. @@:
  1648.         mov     ecx, eax
  1649.         mov     eax, [ebp+XFS.extent.br_startblock.lo]
  1650.         mov     edx, [ebp+XFS.extent.br_startblock.hi]
  1651.         mov     ebx, [ebp+XFS.file_buffer]
  1652.         push    ecx
  1653.         stdcall xfs._.read_blocks
  1654.         pop     eax
  1655.         add     [ebp+XFS.extent.br_startoff.lo], eax
  1656.         adc     [ebp+XFS.extent.br_startoff.hi], 0
  1657.         add     [ebp+XFS.extent.br_startblock.lo], eax
  1658.         adc     [ebp+XFS.extent.br_startblock.hi], 0
  1659.         sub     [ebp+XFS.extent.br_blockcount], eax
  1660.         imul    eax, [ebp+XFS.blocksize]
  1661.         sub     [ebp+XFS.bytes_to_read], eax
  1662.         sub     [ebp+XFS.bytes_left_in_file.lo], eax
  1663.         sbb     [ebp+XFS.bytes_left_in_file.hi], 0
  1664.         add     [ebp+XFS.bytes_read], eax
  1665.         add     [ebp+XFS.file_buffer], eax
  1666.         add     [ebp+XFS.file_offset.lo], eax
  1667.         adc     [ebp+XFS.file_offset.hi], 0
  1668. ;        cmp     [ebp+XFS.bytes_to_read], 0
  1669.         cmp     [ebp+XFS.extent.br_blockcount], 0
  1670.         jz      .quit
  1671. .tail:
  1672.         mov     eax, [ebp+XFS.extent.br_startblock.lo]
  1673.         mov     edx, [ebp+XFS.extent.br_startblock.hi]
  1674.         mov     ebx, [ebp+XFS.cur_block_data]
  1675.         stdcall xfs._.read_block
  1676.         mov     ecx, [ebp+XFS.bytes_to_read]
  1677.         cmp     [ebp+XFS.bytes_left_in_file.hi], 0
  1678.         jnz     @f
  1679.         cmp     ecx, [ebp+XFS.bytes_left_in_file.lo]
  1680.         jbe     @f
  1681.         mov     ecx, [ebp+XFS.bytes_left_in_file.lo]
  1682. @@:
  1683.         mov     esi, [ebp+XFS.cur_block_data]
  1684.         mov     edi, [ebp+XFS.file_buffer]
  1685.         mov     eax, ecx
  1686.         rep movsb
  1687.         add     [ebp+XFS.bytes_read], eax
  1688.         sub     [ebp+XFS.bytes_to_read], eax
  1689.         sub     [ebp+XFS.bytes_left_in_file.lo], eax
  1690.         sbb     [ebp+XFS.bytes_left_in_file.hi], 0
  1691.         add     [ebp+XFS.file_buffer], eax
  1692.         add     [ebp+XFS.file_offset.lo], eax
  1693.         adc     [ebp+XFS.file_offset.hi], 0
  1694.         add     [ebp+XFS.extent.br_startoff.lo], 1
  1695.         adc     [ebp+XFS.extent.br_startoff.hi], 0
  1696.         add     [ebp+XFS.extent.br_startblock.lo], 1
  1697.         adc     [ebp+XFS.extent.br_startblock.hi], 0
  1698.         dec     [ebp+XFS.extent.br_blockcount]
  1699. .quit:
  1700.         mov     esi, [ebp+XFS.extent.br_startoff.lo]
  1701.         mov     edi, [ebp+XFS.extent.br_startoff.hi]
  1702.         movi    eax, ERROR_SUCCESS
  1703.         cmp     esp, esp
  1704.         ret
  1705. endp
  1706.  
  1707.  
  1708. ;----------------------------------------------------------------
  1709. ; in:  ebp = pointer to XFS structure
  1710. ; in:  esi = name
  1711. ; in:  ebx = pointer to parameters from sysfunc 70
  1712. ; out: eax, ebx = return values for sysfunc 70
  1713. ;----------------------------------------------------------------
  1714. proc xfs_Read uses ecx edx esi edi
  1715. locals
  1716.         .offset_begin DQ ?
  1717.         .offset_end   DQ ?
  1718. endl
  1719.         call    xfs._.lock
  1720.         mov     [ebp+XFS.bytes_read], 0
  1721.         mov     eax, [ebx+f70s0arg.count]
  1722.         mov     [ebp+XFS.bytes_to_read], eax
  1723.         test    eax, eax
  1724.         jz      .quit
  1725.         mov     eax, [ebx+f70s0arg.buf]
  1726.         mov     [ebp+XFS.file_buffer], eax
  1727.         mov     eax, [ebx+f70s0arg.offset.hi]
  1728.         mov     [ebp+XFS.file_offset.hi], eax
  1729.         mov     eax, [ebx+f70s0arg.offset.lo]
  1730.         mov     [ebp+XFS.file_offset.lo], eax
  1731.  
  1732.         stdcall xfs_get_inode, esi
  1733.         jnz     .error
  1734.         stdcall xfs_read_inode, eax, edx, [ebp+XFS.cur_inode]
  1735.         test    eax, eax
  1736.         movi    eax, ERROR_FS_FAIL
  1737.         jnz     .error
  1738.         mov     [ebp+XFS.cur_inode_save], edx
  1739.         mov     ebx, edx
  1740.         ; precompute .offset_begin
  1741.         mov     esi, [ebp+XFS.file_offset.lo]
  1742.         mov     edi, [ebp+XFS.file_offset.hi]
  1743.         mov     ecx, [ebp+XFS.blocklog]
  1744.         shrd    esi, edi, cl
  1745.         shr     edi, cl
  1746.         mov     [.offset_begin.lo], esi
  1747.         mov     [.offset_begin.hi], edi
  1748.         ; precompute .offset_end
  1749.         mov     esi, [ebp+XFS.file_offset.lo]
  1750.         mov     edi, [ebp+XFS.file_offset.hi]
  1751.         add     esi, [ebp+XFS.bytes_to_read]
  1752.         adc     edi, 0
  1753.         mov     ecx, [ebp+XFS.blocksize]
  1754.         dec     ecx
  1755.         add     esi, ecx
  1756.         adc     edi, 0
  1757.         mov     ecx, [ebp+XFS.blocklog]
  1758.         shrd    esi, edi, cl
  1759.         shr     edi, cl
  1760.         mov     [.offset_end.lo], esi
  1761.         mov     [.offset_end.hi], edi
  1762.  
  1763.         movbe   ecx, [ebx+xfs_inode.di_core.di_size.hi]
  1764.         movbe   edx, [ebx+xfs_inode.di_core.di_size.lo]
  1765.         mov     [ebp+XFS.bytes_left_in_file.lo], ecx
  1766.         mov     [ebp+XFS.bytes_left_in_file.hi], edx
  1767.  
  1768.         sub     ecx, [ebp+XFS.file_offset.lo]
  1769.         sbb     edx, [ebp+XFS.file_offset.hi]
  1770.         movi    eax, ERROR_END_OF_FILE
  1771.         jb      .error
  1772.         mov     [ebp+XFS.eof], 0
  1773.         test    edx, edx
  1774.         jnz     @f
  1775.         cmp     ecx, [ebp+XFS.bytes_to_read]
  1776.         jae     @f
  1777.         mov     [ebp+XFS.eof], ERROR_END_OF_FILE
  1778.         mov     [ebp+XFS.bytes_to_read], ecx
  1779. @@:
  1780.  
  1781.         cmp     [ebx+xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE
  1782.         jz      .btree
  1783. .extent_list:
  1784.         mov     eax, ebx
  1785.         add     eax, [ebp+XFS.inode_core_size]
  1786.         movbe   edx, [ebx+xfs_inode.di_core.di_nextents]
  1787.         mov     ecx, [.offset_begin.lo]
  1788.         mov     [ebp+XFS.offset_begin.lo], ecx
  1789.         mov     ecx, [.offset_begin.hi]
  1790.         mov     [ebp+XFS.offset_begin.hi], ecx
  1791.         mov     ecx, [.offset_end.lo]
  1792.         mov     [ebp+XFS.offset_end.lo], ecx
  1793.         mov     ecx, [.offset_end.hi]
  1794.         mov     [ebp+XFS.offset_end.hi], ecx
  1795.         stdcall xfs._.walk_extent_list, edx, eax, xfs._.file.read_extent, 0, 0
  1796.         jnz     .error
  1797.         jmp     .hole_check
  1798. .btree:
  1799.         mov     eax, [ebp+XFS.inodesize]
  1800.         sub     eax, [ebp+XFS.inode_core_size]
  1801.         movzx   ecx, [ebx+xfs_inode.di_core.di_forkoff]
  1802.         jecxz   @f
  1803.         shl     ecx, 3
  1804.         mov     eax, ecx
  1805. @@:
  1806.         mov     edx, ebx
  1807.         add     edx, [ebp+XFS.inode_core_size]
  1808.         mov     ecx, [.offset_begin.lo]
  1809.         mov     [ebp+XFS.offset_begin.lo], ecx
  1810.         mov     ecx, [.offset_begin.hi]
  1811.         mov     [ebp+XFS.offset_begin.hi], ecx
  1812.         mov     ecx, [.offset_end.lo]
  1813.         mov     [ebp+XFS.offset_end.lo], ecx
  1814.         mov     ecx, [.offset_end.hi]
  1815.         mov     [ebp+XFS.offset_end.hi], ecx
  1816.         stdcall xfs._.walk_btree, edx, eax, xfs._.file.read_extent, 0, 0, 1
  1817. .hole_check:
  1818.         cmp     [ebp+XFS.bytes_left_in_file.hi], 0
  1819.         jnz     @f
  1820.         cmp     [ebp+XFS.bytes_left_in_file.lo], 0
  1821.         jz      .hole_done
  1822. @@:
  1823.         cmp     [ebp+XFS.bytes_to_read], 0
  1824.         jz      .hole_done
  1825.         mov     ebx, [ebp+XFS.cur_inode_save]
  1826.         movbe   edx, [ebx+xfs_inode.di_core.di_size.lo]
  1827.         movbe   eax, [ebx+xfs_inode.di_core.di_size.hi]
  1828.         sub     eax, [ebp+XFS.file_offset.lo]
  1829.         sbb     edx, [ebp+XFS.file_offset.hi]
  1830.         jc      .hole_done
  1831.         mov     ecx, [ebp+XFS.bytes_to_read]
  1832.         test    edx, edx
  1833.         jnz     .hole_read
  1834.         cmp     eax, [ebp+XFS.bytes_to_read]
  1835.         jae     .hole_read
  1836.         mov     ecx, eax
  1837.         jmp     .hole_read
  1838. .hole_read:
  1839.         sub     [ebp+XFS.bytes_to_read], ecx
  1840.         add     [ebp+XFS.bytes_read], ecx
  1841.         mov     edi, [ebp+XFS.file_buffer]
  1842.         xor     eax, eax
  1843.         rep stosb
  1844. .hole_done:
  1845. .quit:
  1846.         mov     eax, [ebp+XFS.eof]
  1847. .error:
  1848.         push    eax
  1849.         call    xfs._.unlock
  1850.         pop     eax
  1851.         mov     ebx, [ebp+XFS.bytes_read]
  1852.         ret
  1853. endp
  1854.  
  1855.  
  1856. proc xfs._.leafn_calc_entries uses ebx ecx edx esi edi, _cur_dirblock, _offset_lo, _offset_hi, _arg
  1857.         mov     edx, [_cur_dirblock]
  1858.         movzx   eax, [ebp+XFS.da_node_magic]
  1859.         cmp     [edx+xfs_dir2_leaf.hdr.info.magic], ax
  1860.         jz      .quit
  1861.         cmp     [ebp+XFS.version], 5
  1862.         jnz     @f
  1863.         add     edx, xfs_dir3_leaf.hdr.count-xfs_dir2_leaf.hdr.count
  1864. @@:
  1865.         movzx   eax, [edx+xfs_dir2_leaf.hdr.count]
  1866.         movzx   ecx, [edx+xfs_dir2_leaf.hdr.stale]
  1867.         xchg    al, ah
  1868.         xchg    cl, ch
  1869.         sub     eax, ecx
  1870.         add     [ebp+XFS.entries_read], eax
  1871. .quit:
  1872.         movi    eax, ERROR_SUCCESS
  1873.         cmp     esp, esp
  1874.         ret
  1875. endp
  1876.  
  1877.  
  1878. proc xfs._.get_before_by_hashval uses ebx edx esi edi, _base, _count, _hash
  1879.         mov     edi, [_hash]
  1880.         mov     edx, [_count]
  1881.         xor     ecx, ecx
  1882. .node.next:
  1883.         movbe   eax, [ebx+xfs_da_intnode.btree+ecx*sizeof.xfs_da_node_entry+xfs_da_node_entry.hashval]
  1884.         cmp     [ebp+XFS.version], 5
  1885.         jnz     @f
  1886.         movbe   eax, [ebx+xfs_da3_intnode.btree+ecx*sizeof.xfs_da_node_entry+xfs_da_node_entry.hashval]
  1887. @@:
  1888.         cmp     eax, edi
  1889.         ja      .node.leaf_found
  1890.         inc     ecx
  1891.         cmp     ecx, edx
  1892.         jnz     .node.next
  1893.         movi    eax, ERROR_FILE_NOT_FOUND
  1894.         test    esp, esp
  1895.         jmp     .error
  1896. .node.leaf_found:
  1897.         movbe   eax, [ebx+xfs_da_intnode.btree+ecx*sizeof.xfs_da_node_entry+xfs_da_node_entry.before]
  1898.         cmp     [ebp+XFS.version], 5
  1899.         jnz     @f
  1900.         movbe   eax, [ebx+xfs_da3_intnode.btree+ecx*sizeof.xfs_da_node_entry+xfs_da_node_entry.before]
  1901. @@:
  1902.         jmp     .quit
  1903. .error:
  1904.         test    esp, esp
  1905.         ret
  1906. .quit:
  1907.         cmp     esp, esp
  1908.         ret
  1909. endp
  1910.  
  1911.  
  1912. proc xfs._.long_btree.seek uses ebx esi edi, _ptr, _size
  1913.         mov     ebx, [_ptr]
  1914.         mov     esi, [_size]
  1915.         sub     esi, sizeof.xfs_bmdr_block
  1916.         shr     esi, 4
  1917.         shl     esi, 3
  1918.         movzx   eax, [ebx+xfs_bmdr_block.bb_level]
  1919.         movzx   ecx, [ebx+xfs_bmdr_block.bb_numrecs]
  1920.         xchg    cl, ch
  1921.         add     ebx, sizeof.xfs_bmdr_block
  1922.         jmp     .common
  1923. .not_root:
  1924.         mov     esi, [ebp+XFS.blocksize]
  1925.         sub     esi, sizeof.xfs_bmbt_block
  1926.         shr     esi, 4
  1927.         shl     esi, 3
  1928.         movzx   eax, [ebx+xfs_bmbt_block.bb_level]
  1929.         movzx   ecx, [ebx+xfs_bmbt_block.bb_numrecs]
  1930.         xchg    cl, ch
  1931.         add     ebx, sizeof.xfs_bmbt_block
  1932. .common:
  1933.         test    eax, eax
  1934.         jz      .leaf
  1935. .node:
  1936. .next_rec:
  1937.         dec     ecx
  1938.         js      .error
  1939.         movbe   eax, [ebx+ecx*sizeof.xfs_bmbt_key+xfs_bmbt_key.br_startoff.lo]
  1940.         cmp     [ebp+XFS.offset_begin.hi], eax
  1941.         ja      .node_found
  1942.         jb      .next_rec
  1943.         movbe   eax, [ebx+ecx*sizeof.xfs_bmbt_key+xfs_bmbt_key.br_startoff.hi]
  1944.         cmp     [ebp+XFS.offset_begin.lo], eax
  1945.         jae     .node_found
  1946.         jmp     .next_rec
  1947. .node_found:
  1948.         add     ebx, esi
  1949.         movbe   edx, [ebx+ecx*sizeof.xfs_bmbt_ptr+xfs_bmbt_ptr.lo]
  1950.         movbe   eax, [ebx+ecx*sizeof.xfs_bmbt_ptr+xfs_bmbt_ptr.hi]
  1951.         mov     ebx, [ebp+XFS.cur_block]
  1952.         stdcall xfs._.read_block
  1953.         test    eax, eax
  1954.         jnz     .error
  1955.         mov     ebx, [ebp+XFS.cur_block]
  1956.         jmp     .not_root
  1957. .leaf:
  1958.         jmp     .quit
  1959. .error:
  1960. .quit:
  1961.         ret
  1962. endp
  1963.  
  1964.  
  1965. proc xfs._.walk_btree uses ebx esi edi, _ptr, _size, _callback_extent, _callback_block, _callback_data, _is_root
  1966.         stdcall xfs._.long_btree.seek, [_ptr+4], [_size]
  1967.         mov     [_is_root], 0
  1968. .begin:
  1969.         mov     ebx, [ebp+XFS.cur_block]
  1970.         mov     eax, [ebp+XFS.bmap_magic]
  1971.         cmp     [ebx+xfs_bmbt_block.bb_magic], eax
  1972.         movi    eax, ERROR_FS_FAIL
  1973.         jnz     .error
  1974.         movzx   ecx, [ebx+xfs_bmbt_block.bb_numrecs]
  1975.         xchg    cl, ch
  1976.         add     ebx, [ebp+XFS.bmbt_block_size]
  1977.         stdcall xfs._.walk_extent_list, ecx, ebx, [_callback_extent+8], [_callback_block+4], [_callback_data]
  1978.         jnz     .error
  1979.         mov     esi, [ebp+XFS.offset_begin.lo]
  1980.         mov     edi, [ebp+XFS.offset_begin.hi]
  1981.         cmp     edi, [ebp+XFS.offset_end.hi]
  1982.         ja      .quit
  1983.         cmp     esi, [ebp+XFS.offset_end.lo]
  1984.         jae     .quit
  1985.         sub     ebx, [ebp+XFS.bmbt_block_size]
  1986.         movbe   edx, [ebx+xfs_bmbt_block.bb_rightsib.lo]
  1987.         movbe   eax, [ebx+xfs_bmbt_block.bb_rightsib.hi]
  1988.         mov     ecx, eax
  1989.         and     ecx, edx
  1990.         inc     ecx
  1991.         jz      .quit
  1992.         mov     ebx, [ebp+XFS.cur_block]
  1993.         stdcall xfs._.read_block
  1994.         jnz     .error
  1995.         jmp     .begin
  1996. .error:
  1997. .quit:
  1998.         ret
  1999. endp
  2000.  
  2001.  
  2002. proc xfs._.btree_read_block uses ebx esi edi, _tree, _size, _block_lo, _block_hi, _buf
  2003.         mov     eax, [_block_lo]
  2004.         mov     [ebp+XFS.offset_begin.lo], eax
  2005.         mov     eax, [_block_hi]
  2006.         mov     [ebp+XFS.offset_begin.hi], eax
  2007.         stdcall xfs._.long_btree.seek, [_tree+4], [_size]
  2008.         jnz     .error
  2009.         mov     ebx, [ebp+XFS.cur_block]
  2010.         mov     eax, [ebp+XFS.bmap_magic]
  2011.         cmp     [ebx+xfs_bmbt_block.bb_magic], eax
  2012.         jnz     .error
  2013.         movzx   ecx, [ebx+xfs_bmbt_block.bb_numrecs]
  2014.         xchg    cl, ch
  2015.         add     ebx, [ebp+XFS.bmbt_block_size]
  2016.         mov     eax, [_block_lo]
  2017.         mov     [ebp+XFS.offset_begin.lo], eax
  2018.         mov     eax, [_block_hi]
  2019.         mov     [ebp+XFS.offset_begin.hi], eax
  2020.         stdcall xfs._.extent_list.seek, ecx
  2021.         stdcall xfs._.read_dirblock, [ebp+XFS.extent.br_startblock.lo], [ebp+XFS.extent.br_startblock.hi], [_buf]
  2022. .error:
  2023. .quit:
  2024.         ret
  2025. endp
  2026.  
  2027.  
  2028. proc xfs._.extent_list.seek uses esi, _count
  2029.         sub     ebx, sizeof.xfs_bmbt_rec
  2030.         inc     [_count]
  2031. .find_low:
  2032.         add     ebx, sizeof.xfs_bmbt_rec
  2033.         dec     [_count]
  2034.         jz      .quit
  2035.         stdcall xfs._.extent_unpack, ebx
  2036.         mov     eax, [ebp+XFS.extent.br_startoff.lo]
  2037.         mov     edx, [ebp+XFS.extent.br_startoff.hi]
  2038.         mov     esi, [ebp+XFS.extent.br_blockcount]
  2039.         add     eax, esi
  2040.         adc     edx, 0
  2041.  
  2042.         cmp     edx, [ebp+XFS.offset_begin.hi]
  2043.         ja      .low_found
  2044.         jb      .find_low
  2045.         cmp     eax, [ebp+XFS.offset_begin.lo]
  2046.         ja      .low_found
  2047.         jmp     .find_low
  2048. .low_found:
  2049.         add     ebx, sizeof.xfs_bmbt_rec
  2050.  
  2051.         mov     eax, [ebp+XFS.offset_begin.lo]
  2052.         mov     edx, [ebp+XFS.offset_begin.hi]
  2053.         mov     esi, eax
  2054.         sub     esi, [ebp+XFS.extent.br_startoff.lo]
  2055.         jbe     .quit
  2056.         ; same br_blockcount for block and dirblock?
  2057.         mov     [ebp+XFS.extent.br_startoff.lo], eax
  2058.         mov     [ebp+XFS.extent.br_startoff.hi], edx
  2059.         sub     [ebp+XFS.extent.br_blockcount], esi
  2060.         add     [ebp+XFS.extent.br_startblock.lo], esi
  2061.         adc     [ebp+XFS.extent.br_startblock.hi], 0
  2062.         jmp     .quit
  2063. .quit:
  2064.         mov     eax, [_count]
  2065.         ret
  2066. endp
  2067.  
  2068.  
  2069. proc xfs._.extent_iterate_dirblocks _callback, _callback_data
  2070. .check_high:
  2071.         cmp     edi, [ebp+XFS.offset_end.hi]
  2072.         ja      .quit
  2073.         jb      .read_dirblock
  2074.         cmp     esi, [ebp+XFS.offset_end.lo]
  2075.         jae     .quit
  2076. .read_dirblock:
  2077.         stdcall xfs._.read_dirblock, [ebp+XFS.extent.br_startblock.lo], [ebp+XFS.extent.br_startblock.hi], [ebp+XFS.cur_dirblock]
  2078.         mov     edx, [ebp+XFS.cur_dirblock]
  2079.         mov     eax, [_callback]
  2080.         stdcall eax, edx, esi, edi, [_callback_data]
  2081.         test    eax, eax
  2082.         jnz     .error
  2083.         mov     eax, [ebp+XFS.blkpdirblk]
  2084.         add     esi, eax
  2085.         adc     edi, 0
  2086.         add     [ebp+XFS.extent.br_startblock.lo], eax
  2087.         adc     [ebp+XFS.extent.br_startblock.hi], 0
  2088.         sub     [ebp+XFS.extent.br_blockcount], eax
  2089.         jnz     .check_high
  2090. .error:
  2091. .quit:
  2092.         ret
  2093. endp
  2094.  
  2095.  
  2096. proc xfs._.walk_extent_list uses ebx esi edi, _count, _ptr, _callback_extent, _callback_block, _callback_data
  2097.         mov     ebx, [_ptr]
  2098.         stdcall xfs._.extent_list.seek, [_count]
  2099.         mov     [_count], eax
  2100.         dec     [_count]
  2101.         js      .quit
  2102.         jmp     .next_extent.decoded
  2103. .next_extent:
  2104.         stdcall xfs._.extent_unpack, ebx
  2105.         add     ebx, sizeof.xfs_bmbt_rec
  2106. .next_extent.decoded:
  2107.         mov     eax, [ebp+XFS.extent.br_blockcount]
  2108.         add     [ebp+XFS.offset_begin.lo], eax
  2109.         adc     [ebp+XFS.offset_begin.hi], 0
  2110.         mov     esi, [ebp+XFS.extent.br_startoff.lo]
  2111.         mov     edi, [ebp+XFS.extent.br_startoff.hi]
  2112.         stdcall [_callback_extent+8], [_callback_block+4], [_callback_data]
  2113.         jnz     .error
  2114.         cmp     edi, [ebp+XFS.offset_end.hi]
  2115.         ja      .quit
  2116.         jb      @f
  2117.         cmp     esi, [ebp+XFS.offset_end.lo]
  2118.         jae     .quit
  2119. @@:
  2120.         dec     [_count]
  2121.         js      .quit
  2122.         jmp     .next_extent
  2123. .quit:
  2124.         movi    eax, ERROR_SUCCESS
  2125. .error:
  2126.         test    eax, eax
  2127.         ret
  2128. endp
  2129.  
  2130.  
  2131. proc xfs._.get_last_dirblock uses ecx
  2132.         movbe   eax, [ebx+xfs_inode.di_core.di_nextents]
  2133. assert (sizeof.xfs_bmbt_rec AND (sizeof.xfs_bmbt_rec - 1)) = 0
  2134.         shl     eax, BSF sizeof.xfs_bmbt_rec
  2135.         add     eax, [ebp+XFS.inode_core_size]
  2136.         lea     eax, [ebx+eax-sizeof.xfs_bmbt_rec]
  2137.         stdcall xfs._.extent_unpack, eax
  2138.         xor     edx, edx
  2139.         mov     eax, [ebp+XFS.extent.br_blockcount]
  2140.         mov     ecx, [ebp+XFS.dirblklog]
  2141.         shr     eax, cl
  2142.         dec     eax
  2143.         add     eax, [ebp+XFS.extent.br_startoff.lo]
  2144.         adc     edx, [ebp+XFS.extent.br_startoff.hi]
  2145.         ret
  2146. endp
  2147.  
  2148.  
  2149. restore prologue@proc,epilogue@proc
  2150. restore movbe
  2151.