Subversion Repositories Kolibri OS

Rev

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