Subversion Repositories Kolibri OS

Rev

Rev 10015 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2013-2024. All rights reserved. ;;
  4. ;;  Distributed under terms of the GNU General Public License   ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8.  
  9. include 'xfs.inc'
  10.  
  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
  22. }
  23.  
  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
  36. }
  37.  
  38. prologue@proc equ omit_frame_pointer_prologue
  39. epilogue@proc equ omit_frame_pointer_epilogue
  40.  
  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
  60. }
  61.  
  62. ;
  63. ; This file contains XFS related code.
  64. ; For more information on XFS check links and source below.
  65. ;
  66. ; 1. https://xfs.wiki.kernel.org/
  67. ;
  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
  71. ;
  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
  75. ;
  76.  
  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
  90.  
  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
  120. @@:
  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
  130.  
  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
  147.  
  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
  152.  
  153.         movbe   eax, [ebx+xfs_sb.sb_blocksize]
  154.         mov     [edi+XFS.blocksize], eax
  155.  
  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
  161.  
  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
  164.  
  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
  209. @@:
  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
  213. @@:
  214. .vcommon:
  215.  
  216.         movzx   eax, [ebx+xfs_sb.sb_inodesize]
  217.         xchg    al, ah
  218.         mov     [edi+XFS.inodesize], eax
  219.  
  220.         movzx   eax, [ebx+xfs_sb.sb_inopblock]
  221.         xchg    al, ah
  222.         mov     [edi+XFS.inopblock], eax
  223.  
  224.         movzx   eax, [ebx+xfs_sb.sb_blocklog]
  225.         mov     [edi+XFS.blocklog], eax
  226.  
  227. ;        movzx   eax, [ebx+xfs_sb.sb_sectlog]
  228.         mov     eax, [edi+XFS.sectsize]
  229.         bsf     eax, eax
  230.         mov     [edi+XFS.sectlog], eax
  231.  
  232.         movzx   eax, [ebx+xfs_sb.sb_inodelog]
  233.         mov     [edi+XFS.inodelog], eax
  234.  
  235.         movzx   eax, [ebx+xfs_sb.sb_inopblog]
  236.         mov     [edi+XFS.inopblog], eax
  237.  
  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
  243.  
  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
  248.  
  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
  253.  
  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
  259.  
  260.         mov     eax, 1
  261.         shl     eax, cl
  262.         mov     [edi+XFS.sectpblock], eax
  263.  
  264.         movbe   eax, [ebx+xfs_sb.sb_agblocks]
  265.         mov     [edi+XFS.agblocks], eax
  266.  
  267.         movzx   ecx, [ebx+xfs_sb.sb_agblklog]
  268.         mov     [edi+XFS.agblklog], ecx
  269.  
  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
  281.  
  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
  290.  
  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
  298.  
  299.  
  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
  306.  
  307.         mov     eax, [edi+XFS.blocksize]
  308.         call    malloc
  309.         mov     [edi+XFS.cur_block_data], eax
  310.         test    eax, eax
  311.         jz      .error
  312.  
  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
  320.  
  321.         mov     eax, [edi+XFS.blocksize]
  322.         call    malloc
  323.         test    eax, eax
  324.         jz      .error
  325.         mov     [edi+XFS.tmp_inode], eax
  326.  
  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
  336.  
  337.         mov     eax, [edi+XFS.dirblocksize]
  338.         call    malloc
  339.         mov     [edi+XFS.cur_dirblock], eax
  340.         test    eax, eax
  341.         jz      .error
  342.  
  343. .quit:
  344.         ; return pointer to allocated XFS partition structure
  345.         mov     eax, edi
  346.         ret
  347. .error:
  348.         mov     eax, edi
  349.         call    xfs._.free
  350. .error_nofree:
  351.         xor     eax, eax
  352.         ret
  353. endp
  354.  
  355.  
  356. ; lock partition access mutex
  357. xfs._.lock:
  358.         lea     ecx, [ebp+XFS.Lock]
  359.         jmp     mutex_lock
  360.  
  361.  
  362. ; unlock partition access mutex
  363. xfs._.unlock:
  364.         lea     ecx, [ebp+XFS.Lock]
  365.         jmp     mutex_unlock
  366.  
  367.  
  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
  376.  
  377.  
  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
  384.  
  385.         mov     eax, [ebx+XFS.cur_block_data]
  386.         test    eax, eax
  387.         jz      .done
  388.         call    free
  389.  
  390.         mov     eax, [ebx+XFS.cur_inode]
  391.         test    eax, eax
  392.         jz      .done
  393.         call    free
  394.  
  395.         mov     eax, [ebx+XFS.tmp_inode]
  396.         test    eax, eax
  397.         jz      .done
  398.         call    free
  399.  
  400.         mov     eax, [ebx+XFS.cur_sect]
  401.         test    eax, eax
  402.         jz      .done
  403.         call    free
  404.  
  405.         mov     eax, [ebx+XFS.cur_dirblock]
  406.         test    eax, eax
  407.         jz      .done
  408.         call    free
  409.  
  410.  
  411.         mov     eax, ebx
  412.         call    free
  413.         pop     ebx
  414. .done:
  415.         ret
  416.  
  417.  
  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
  427.         ret
  428. endp
  429.  
  430.  
  431. proc xfs._.blkrel2sectabs uses esi
  432.         push    edx eax
  433.  
  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
  439.  
  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
  451.  
  452.         mov     ecx, [ebp+XFS.sectpblog]
  453.         shld    edx, eax, cl
  454.         shl     eax, cl
  455.         ret
  456. endp
  457.  
  458.  
  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
  472.         ret
  473. endp
  474.  
  475.  
  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
  482.         ret
  483. endp
  484.  
  485.  
  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
  505.  
  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
  516.  
  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:
  523.         ret
  524. endp
  525.  
  526.  
  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:
  551.         ret
  552. endp
  553.  
  554.  
  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:
  609.         ret
  610. endp
  611.  
  612.  
  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]
  635.         ret
  636. endp
  637.  
  638.  
  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
  658.  
  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:
  673.         ret
  674. endp
  675.  
  676.  
  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:
  719.         ret
  720. endp
  721.  
  722.  
  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
  730. @@:
  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:
  773.         ret
  774. endp
  775.  
  776.  
  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:
  799.         ret
  800. endp
  801.  
  802.  
  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
  812. @@:
  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
  836. @@:
  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:
  852.         ret
  853. endp
  854.  
  855.  
  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
  877. @@:
  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:
  886.         ret
  887. endp
  888.  
  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
  905. @@:
  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
  911.  
  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
  918.  
  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
  928. @@:
  929.         cmp     eax, XFS_DINODE_FMT_BTREE
  930.         jnz     @f
  931.         stdcall xfs._.readdir_btree, ebx, [_dst]
  932.         jmp     .quit
  933. @@:
  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
  943. @@:
  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:
  952.         ret
  953. endp
  954.  
  955.  
  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
  988. @@:
  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
  996. @@:
  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:
  1008.         ret
  1009. endp
  1010.  
  1011.  
  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:
  1036.         ret
  1037. endp
  1038.  
  1039.  
  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]
  1077. @@:
  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:
  1090.         ret
  1091. endp
  1092.  
  1093.  
  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:
  1129.         ret
  1130. endp
  1131.  
  1132.  
  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
  1199.         ret
  1200. .error:
  1201.         test    esp, esp
  1202.         ret
  1203. endp
  1204.  
  1205.  
  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]
  1231. @@:
  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
  1266.         ret
  1267. .error:
  1268.         test    esp, esp
  1269.         ret
  1270. endp
  1271.  
  1272.  
  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:
  1311.         ret
  1312. endp
  1313.  
  1314.  
  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:
  1324. @@:
  1325.         cmp     byte[esi], '/'
  1326.         jnz     @f
  1327.         inc     esi
  1328.         jmp     @b
  1329. @@:
  1330.         cmp     byte[esi], 0
  1331.         jz      .found
  1332.         push    esi
  1333.         inc     esi
  1334. @@:
  1335.         cmp     byte[esi], 0
  1336.         jz      @f
  1337.         cmp     byte[esi], '/'
  1338.         jz      @f
  1339.         inc     esi
  1340.         jmp     @b
  1341. @@:
  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:
  1350.         ret
  1351. endp
  1352.  
  1353.  
  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]
  1376.  
  1377. .error:
  1378.         push    eax
  1379.         call    xfs._.unlock
  1380.         pop     eax
  1381.         ret
  1382. endp
  1383.  
  1384.  
  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]
  1393.         ret
  1394. .i4bytes:
  1395.         movbe   eax, [edx+DQ.lo]
  1396.         xor     edx, edx
  1397.         ret
  1398. endp
  1399.  
  1400. proc xfs._.conv_time_to_kos_epoch
  1401.         movbe   eax, [ecx+DQ.hi_be]
  1402.         call    fsTime2bdfe
  1403.         ret
  1404. endp
  1405.  
  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
  1429.         ret
  1430. endp
  1431.  
  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
  1443. @@:
  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
  1450.  
  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]
  1458.  
  1459.         movi    eax, ERROR_SUCCESS
  1460.         cmp     esp, esp
  1461.         ret
  1462. endp
  1463.  
  1464.  
  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]
  1470.  
  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
  1476.  
  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
  1483.  
  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
  1492.  
  1493.         movbe   eax, [ebx+12]
  1494.         and     eax, 0x001fffff         ; mask
  1495.         mov     [ebp+XFS.extent.br_blockcount], eax
  1496.         ret
  1497. endp
  1498.  
  1499.  
  1500. proc xfs_hashname uses ecx esi, _name, _len
  1501.         xor     eax, eax
  1502.         mov     esi, [_name]
  1503.         mov     ecx, [_len]
  1504. @@:
  1505.         rol     eax, 7
  1506.         xor     al, [esi]
  1507.         add     esi, 1
  1508.         dec     ecx
  1509.         jnz     @b
  1510.         ret
  1511. endp
  1512.  
  1513.  
  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]
  1532.         ret
  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
  1544.         ret
  1545. endp
  1546.  
  1547.  
  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
  1567.         ret
  1568. .error:
  1569.         push    eax
  1570.         call    xfs._.unlock
  1571.         pop     eax
  1572.         ret
  1573. endp
  1574.  
  1575.  
  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
  1597. @@:
  1598.         cmp     ecx, [ebp+XFS.bytes_to_read]
  1599.         jbe     @f
  1600.         mov     ecx, [ebp+XFS.bytes_to_read]
  1601. @@:
  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]
  1638. @@:
  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]
  1665. @@:
  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]
  1700. @@:
  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
  1722.         ret
  1723. endp
  1724.  
  1725.  
  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
  1749.  
  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
  1780.  
  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
  1785.  
  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
  1797. @@:
  1798.  
  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
  1824. @@:
  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
  1841. @@:
  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]
  1871.         ret
  1872. endp
  1873.  
  1874.  
  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
  1883. @@:
  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
  1893.         ret
  1894. endp
  1895.  
  1896.  
  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]
  1906. @@:
  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]
  1920. @@:
  1921.         jmp     .quit
  1922. .error:
  1923.         test    esp, esp
  1924.         ret
  1925. .quit:
  1926.         cmp     esp, esp
  1927.         ret
  1928. endp
  1929.  
  1930.  
  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:
  1980.         ret
  1981. endp
  1982.  
  1983.  
  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:
  2017.         ret
  2018. endp
  2019.  
  2020.  
  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:
  2044.         ret
  2045. endp
  2046.  
  2047.  
  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
  2061.  
  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
  2070.  
  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]
  2085.         ret
  2086. endp
  2087.  
  2088.  
  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:
  2112.         ret
  2113. endp
  2114.  
  2115.  
  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
  2139. @@:
  2140.         dec     [_count]
  2141.         js      .quit
  2142.         jmp     .next_extent
  2143. .quit:
  2144.         movi    eax, ERROR_SUCCESS
  2145. .error:
  2146.         test    eax, eax
  2147.         ret
  2148. endp
  2149.  
  2150.  
  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]
  2166.         ret
  2167. endp
  2168.  
  2169.  
  2170. restore prologue@proc,epilogue@proc
  2171. restore movbe
  2172.