Subversion Repositories Kolibri OS

Rev

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

  1. include 'xfs.inc'
  2.  
  3. ;
  4. ; This file contains XFS related code.
  5. ; For more information on XFS check sources below.
  6. ;
  7. ; 1. XFS Filesystem Structure, 2nd Edition, Revision 1. Silicon Graphics Inc. 2006
  8. ; 2. Linux source http://kernel.org
  9. ;
  10.  
  11.  
  12. ; test partition type (valid XFS one?)
  13. ; alloc and fill XFS (see xfs.inc) structure
  14. ; this function is called for each partition
  15. ; returns 0 (not XFS or invalid) / pointer to partition structure
  16. xfs_create_partition:
  17.         push    ebx ecx edx esi edi
  18.         cmp     dword[ebx + xfs_sb.sb_magicnum], XFS_SB_MAGIC   ; signature
  19.         jne     .error
  20.  
  21.         ; TODO: check XFS.versionnum and XFS.features2
  22.         ;       print superblock params for debugging (waiting for bug reports)
  23.  
  24.         movi    eax, sizeof.XFS
  25.         call    malloc
  26.         test    eax, eax
  27.         jz      .error
  28.  
  29.         ; standard partition initialization, common for all file systems
  30.  
  31.         mov     edi, eax
  32.         mov     eax, dword[ebp + PARTITION.FirstSector]
  33.         mov     dword[edi + XFS.FirstSector], eax
  34.         mov     eax, dword[ebp + PARTITION.FirstSector + 4]
  35.         mov     dword[edi + XFS.FirstSector + 4], eax
  36.         mov     eax, dword[ebp + PARTITION.Length]
  37.         mov     dword[edi + XFS.Length], eax
  38.         mov     eax, dword[ebp + PARTITION.Length + 4]
  39.         mov     dword[edi + XFS.Length + 4], eax
  40.         mov     eax, [ebp + PARTITION.Disk]
  41.         mov     [edi + XFS.Disk], eax
  42.         mov     [edi + XFS.FSUserFunctions], xfs_user_functions
  43.  
  44.         ; here we initialize only one mutex so far (for the entire partition)
  45.         ; XFS potentially allows parallel r/w access to several AGs, keep it in mind for SMP times
  46.  
  47.         lea     ecx, [edi + XFS.Lock]
  48.         call    mutex_init
  49.  
  50.         ; read superblock and fill just allocated XFS partition structure
  51.  
  52.         mov     eax, [ebx + xfs_sb.sb_blocksize]
  53.         bswap   eax                                     ; XFS is big endian
  54.         mov     [edi + XFS.blocksize], eax
  55.         movzx   eax, word[ebx + xfs_sb.sb_sectsize]
  56.         xchg    al, ah
  57.         mov     [edi + XFS.sectsize], eax
  58.         movzx   eax, word[ebx + xfs_sb.sb_versionnum]
  59.         xchg    al, ah
  60.         mov     [edi + XFS.versionnum], eax
  61.         mov     eax, [ebx + xfs_sb.sb_features2]
  62.         bswap   eax
  63.         mov     [edi + XFS.features2], eax
  64.         movzx   eax, word[ebx + xfs_sb.sb_inodesize]
  65.         xchg    al, ah
  66.         mov     [edi + XFS.inodesize], eax
  67.         movzx   eax, word[ebx + xfs_sb.sb_inopblock]    ; inodes per block
  68.         xchg    al, ah
  69.         mov     [edi + XFS.inopblock], eax
  70.         movzx   eax, byte[ebx + xfs_sb.sb_blocklog]     ; log2 of block size, in bytes
  71.         mov     [edi + XFS.blocklog], eax
  72.         movzx   eax, byte[ebx + xfs_sb.sb_sectlog]
  73.         mov     [edi + XFS.sectlog], eax
  74.         movzx   eax, byte[ebx + xfs_sb.sb_inodelog]
  75.         mov     [edi + XFS.inodelog], eax
  76.         movzx   eax, byte[ebx + xfs_sb.sb_inopblog]
  77.         mov     [edi + XFS.inopblog], eax
  78.         movzx   eax, byte[ebx + xfs_sb.sb_dirblklog]
  79.         mov     [edi + XFS.dirblklog], eax
  80.         mov     eax, dword[ebx + xfs_sb.sb_rootino + 4] ;
  81.         bswap   eax                                     ; big
  82.         mov     dword[edi + XFS.rootino + 0], eax       ; endian
  83.         mov     eax, dword[ebx + xfs_sb.sb_rootino + 0] ; 64bit
  84.         bswap   eax                                     ; number
  85.         mov     dword[edi + XFS.rootino + 4], eax       ;
  86.  
  87.         mov     eax, [edi + XFS.blocksize]
  88.         mov     ecx, [edi + XFS.dirblklog]
  89.         shl     eax, cl
  90.         mov     [edi + XFS.dirblocksize], eax           ; blocks for files, dirblocks for directories
  91.  
  92.         ; sector is always smaller than block
  93.         ; so precalculate shift order to allow faster sector_num->block_num conversion
  94.  
  95.         mov     ecx, [edi + XFS.blocklog]
  96.         sub     ecx, [edi + XFS.sectlog]
  97.         mov     [edi + XFS.blockmsectlog], ecx
  98.  
  99.         mov     eax, 1
  100.         shl     eax, cl
  101.         mov     [edi + XFS.sectpblock], eax
  102.  
  103.         ; shift order for inode_num->block_num conversion
  104.  
  105.         mov     eax, [edi + XFS.blocklog]
  106.         sub     eax, [edi + XFS.inodelog]
  107.         mov     [edi + XFS.inodetoblocklog], eax
  108.  
  109.         mov     eax, [ebx + xfs_sb.sb_agblocks]
  110.         bswap   eax
  111.         mov     [edi + XFS.agblocks], eax
  112.         movzx   ecx, byte[ebx + xfs_sb.sb_agblklog]
  113.         mov     [edi + XFS.agblklog], ecx
  114.  
  115.         ; get the mask for block numbers
  116.         ; block numbers are AG relative!
  117.         ; bitfield length may vary between partitions
  118.  
  119.         mov     eax, 1
  120.         shl     eax, cl
  121.         dec     eax
  122.         mov     dword[edi + XFS.agblockmask + 0], eax
  123.         mov     eax, 1
  124.         sub     ecx, 32
  125.         jc      @f
  126.         shl     eax, cl
  127.     @@:
  128.         dec     eax
  129.         mov     dword[edi + XFS.agblockmask + 4], eax
  130.  
  131.         ; calculate magic offsets for directories
  132.  
  133.         mov     ecx, [edi + XFS.blocklog]
  134.         mov     eax, XFS_DIR2_LEAF_OFFSET AND 0xffffffff        ; lo
  135.         mov     edx, XFS_DIR2_LEAF_OFFSET SHR 32                ; hi
  136.         shrd    eax, edx, cl
  137.         mov     [edi + XFS.dir2_leaf_offset_blocks], eax
  138.  
  139.         mov     ecx, [edi + XFS.blocklog]
  140.         mov     eax, XFS_DIR2_FREE_OFFSET AND 0xffffffff        ; lo
  141.         mov     edx, XFS_DIR2_FREE_OFFSET SHR 32                ; hi
  142.         shrd    eax, edx, cl
  143.         mov     [edi + XFS.dir2_free_offset_blocks], eax
  144.  
  145. ;        mov     ecx, [edi + XFS.dirblklog]
  146. ;        mov     eax, [edi + XFS.blocksize]
  147. ;        shl     eax, cl
  148. ;        mov     [edi + XFS.dirblocksize], eax
  149.  
  150.         mov     eax, [edi + XFS.blocksize]
  151.         call    malloc
  152.         test    eax, eax
  153.         jz      .error
  154.         mov     [edi + XFS.cur_block], eax
  155.  
  156.         ; we do need XFS.blocksize bytes for single inode
  157.         ; minimal file system structure is block, inodes are packed in blocks
  158.  
  159.         mov     eax, [edi + XFS.blocksize]
  160.         call    malloc
  161.         test    eax, eax
  162.         jz      .error
  163.         mov     [edi + XFS.cur_inode], eax
  164.  
  165.         ; temporary inode
  166.         ; used for browsing directories
  167.  
  168.         mov     eax, [edi + XFS.blocksize]
  169.         call    malloc
  170.         test    eax, eax
  171.         jz      .error
  172.         mov     [edi + XFS.tmp_inode], eax
  173.  
  174.         ; current sector
  175.         ; only for sector size structures like AGI
  176.         ; inodes has usually the same size, but never store them here
  177.  
  178.         mov     eax, [edi + XFS.sectsize]
  179.         call    malloc
  180.         test    eax, eax
  181.         jz      .error
  182.         mov     [edi + XFS.cur_sect], eax
  183.  
  184.         ; current directory block
  185.  
  186.         mov     eax, [edi + XFS.dirblocksize]
  187.         call    malloc
  188.         test    eax, eax
  189.         jz      .error
  190.         mov     [edi + XFS.cur_dirblock], eax
  191.  
  192.   .quit:
  193.         mov     eax, edi                ; return pointer to allocated XFS partition structure
  194.         pop     edi esi edx ecx ebx
  195.         ret
  196.   .error:
  197.         xor     eax, eax
  198.         pop     edi esi edx ecx ebx
  199.         ret
  200.  
  201.  
  202. iglobal
  203. align 4
  204. xfs_user_functions:
  205.         dd      xfs_free
  206.         dd      (xfs_user_functions_end - xfs_user_functions - 4) / 4
  207.         dd      xfs_Read
  208.         dd      xfs_ReadFolder
  209.         dd      0;xfs_Rewrite
  210.         dd      0;xfs_Write
  211.         dd      0;xfs_SetFileEnd
  212.         dd      xfs_GetFileInfo
  213.         dd      0;xfs_SetFileInfo
  214.         dd      0
  215.         dd      0;xfs_Delete
  216.         dd      0;xfs_CreateFolder
  217. xfs_user_functions_end:
  218. endg
  219.  
  220.  
  221. ; lock partition access mutex
  222. proc xfs_lock
  223. ;DEBUGF 1,"xfs_lock\n"
  224.         lea     ecx, [ebp + XFS.Lock]
  225.         jmp     mutex_lock
  226. endp
  227.  
  228.  
  229. ; unlock partition access mutex
  230. proc xfs_unlock
  231. ;DEBUGF 1,"xfs_unlock\n"
  232.         lea     ecx, [ebp + XFS.Lock]
  233.         jmp     mutex_unlock
  234. endp
  235.  
  236.  
  237. ; free all the allocated memory
  238. ; called on partition destroy
  239. proc xfs_free
  240.         push    ebp
  241.         xchg    ebp, eax
  242.         stdcall kernel_free, [ebp + XFS.cur_block]
  243.         stdcall kernel_free, [ebp + XFS.cur_inode]
  244.         stdcall kernel_free, [ebp + XFS.cur_sect]
  245.         stdcall kernel_free, [ebp + XFS.cur_dirblock]
  246.         stdcall kernel_free, [ebp + XFS.tmp_inode]
  247.         xchg    ebp, eax
  248.         call    free
  249.         pop     ebp
  250.         ret
  251. endp
  252.  
  253.  
  254. ;---------------------------------------------------------------
  255. ; block number (AG relative)
  256. ; eax -- inode_lo
  257. ; edx -- inode_hi
  258. ; ebx -- buffer
  259. ;---------------------------------------------------------------
  260. xfs_read_block:
  261.         push    ebx esi
  262.  
  263.         push    edx
  264.         push    eax
  265.  
  266.         ; XFS block numbers are AG relative
  267.         ; they come in bitfield form of concatenated AG and block numbers
  268.         ; to get absolute block number for fs_read32_sys we should
  269.         ; 1. extract AG number (using precalculated mask)
  270.         ; 2. multiply it by the AG size in blocks
  271.         ; 3. add AG relative block number
  272.  
  273.         ; 1.
  274.         mov     ecx, [ebp + XFS.agblklog]
  275.         shrd    eax, edx, cl
  276.         shr     edx, cl
  277.         ; 2.
  278.         mul     dword[ebp + XFS.agblocks]
  279.         pop     ecx
  280.         pop     esi
  281.         and     ecx, dword[ebp + XFS.agblockmask + 0]
  282.         and     esi, dword[ebp + XFS.agblockmask + 4]
  283.         ; 3.
  284.         add     eax, ecx
  285.         adc     edx, esi
  286.  
  287. ;DEBUGF 1,"read block: 0x%x%x\n",edx,eax
  288.         ; there is no way to read file system block at once, therefore we
  289.         ; 1. calculate the number of sectors first
  290.         ; 2. and then read them in series
  291.  
  292.         ; 1.
  293.         mov     ecx, [ebp + XFS.blockmsectlog]
  294.         shld    edx, eax, cl
  295.         shl     eax, cl
  296.         mov     esi, [ebp + XFS.sectpblock]
  297.  
  298.         ; 2.
  299.   .next_sector:
  300.         push    eax edx
  301.         call    fs_read32_sys
  302.         mov     ecx, eax
  303.         pop     edx eax
  304.         test    ecx, ecx
  305.         jnz     .error
  306.         add     eax, 1                          ; be ready to fs_read64_sys
  307.         adc     edx, 0
  308.         add     ebx, [ebp + XFS.sectsize]       ; update buffer offset
  309.         dec     esi
  310.         jnz     .next_sector
  311.  
  312.   .quit:
  313.         xor     eax, eax
  314.         pop     esi ebx
  315.         ret
  316.   .error:
  317.         mov     eax, ecx
  318.         pop     esi ebx
  319.         ret
  320.  
  321.  
  322. ;---------------------------------------------------------------
  323. ; push buffer
  324. ; push startblock_hi
  325. ; push startblock_lo
  326. ; call xfs_read_dirblock
  327. ; test eax, eax
  328. ;---------------------------------------------------------------
  329. xfs_read_dirblock:
  330. ;mov eax, [esp + 4]
  331. ;mov edx, [esp + 8]
  332. ;DEBUGF 1,"read dirblock at: %d %d\n",edx,eax
  333. ;DEBUGF 1,"dirblklog: %d\n",[ebp + XFS.dirblklog]
  334.         push    ebx esi
  335.  
  336.         mov     eax, [esp + 12]         ; startblock_lo
  337.         mov     edx, [esp + 16]         ; startblock_hi
  338.         mov     ebx, [esp + 20]         ; buffer
  339.  
  340.         ; dirblock >= block
  341.         ; read dirblocks by blocks
  342.  
  343.         mov     ecx, [ebp + XFS.dirblklog]
  344.         mov     esi, 1
  345.         shl     esi, cl
  346.   .next_block:
  347.         push    eax edx
  348.         call    xfs_read_block
  349.         mov     ecx, eax
  350.         pop     edx eax
  351.         test    ecx, ecx
  352.         jnz     .error
  353.         add     eax, 1          ; be ready to fs_read64_sys
  354.         adc     edx, 0
  355.         add     ebx, [ebp + XFS.blocksize]
  356.         dec     esi
  357.         jnz     .next_block
  358.  
  359.   .quit:
  360.         xor     eax, eax
  361.         pop     esi ebx
  362.         ret     12
  363.   .error:
  364.         mov     eax, ecx
  365.         pop     esi ebx
  366.         ret     12
  367.  
  368.  
  369. ;---------------------------------------------------------------
  370. ; push buffer
  371. ; push inode_hi
  372. ; push inode_lo
  373. ; call xfs_read_inode
  374. ; test eax, eax
  375. ;---------------------------------------------------------------
  376. xfs_read_inode:
  377. ;DEBUGF 1,"reading inode: 0x%x%x\n",[esp+8],[esp+4]
  378.         push    ebx
  379.         mov     eax, [esp + 8]  ; inode_lo
  380.         mov     edx, [esp + 12] ; inode_hi
  381.         mov     ebx, [esp + 16] ; buffer
  382.  
  383.         ; inodes are packed into blocks
  384.         ; 1. calculate block number
  385.         ; 2. read the block
  386.         ; 3. add inode offset to block base address
  387.  
  388.         ; 1.
  389.         mov     ecx, [ebp + XFS.inodetoblocklog]
  390.         shrd    eax, edx, cl
  391.         shr     edx, cl
  392.         ; 2.
  393.         call    xfs_read_block
  394.         test    eax, eax
  395.         jnz     .error
  396.  
  397.         ; note that inode numbers should be first extracted from bitfields using mask
  398.  
  399.         mov     eax, [esp + 8]
  400.         mov     edx, 1
  401.         mov     ecx, [ebp + XFS.inopblog]
  402.         shl     edx, cl
  403.         dec     edx             ; get inode number mask
  404.         and     eax, edx        ; apply mask
  405.         mov     ecx, [ebp + XFS.inodelog]
  406.         shl     eax, cl
  407.         add     ebx, eax
  408.  
  409.         cmp     word[ebx], XFS_DINODE_MAGIC     ; test signature
  410.         jne     .error
  411.   .quit:
  412.         xor     eax, eax
  413.         mov     edx, ebx
  414.         pop     ebx
  415.         ret     12
  416.   .error:
  417.         movi    eax, ERROR_FS_FAIL
  418.         mov     edx, ebx
  419.         pop     ebx
  420.         ret     12
  421.  
  422.  
  423. ;----------------------------------------------------------------
  424. ; push encoding         ; ASCII / UNICODE
  425. ; push src              ; inode
  426. ; push dst              ; bdfe
  427. ; push entries_to_read
  428. ; push start_number     ; from 0
  429. ;----------------------------------------------------------------
  430. xfs_dir_get_bdfes:
  431. DEBUGF 1,"xfs_dir_get_bdfes: %d entries from %d\n",[esp+8],[esp+4]
  432.         sub     esp, 4     ; local vars
  433.         push    ecx edx esi edi
  434.  
  435.         mov     ebx, [esp + 36]         ; src
  436.         mov     edx, [esp + 32]         ; dst
  437.         mov     ecx, [esp + 24]         ; start_number
  438.  
  439.         ; define directory ondisk format and jump to corresponding label
  440.  
  441.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_LOCAL
  442.         jne     .not_shortdir
  443.         jmp     .shortdir
  444.   .not_shortdir:
  445.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  446.         jne     .not_blockdir
  447.         mov     eax, [ebx + xfs_inode.di_core.di_nextents]
  448.         bswap   eax
  449.         cmp     eax, 1
  450.         jne     .not_blockdir
  451.         jmp     .blockdir
  452.   .not_blockdir:
  453.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  454.         jne     .not_leafdir
  455.         mov     eax, [ebx + xfs_inode.di_core.di_nextents]
  456.         bswap   eax
  457.         cmp     eax, 4
  458.         ja      .not_leafdir
  459.         jmp     .leafdir
  460.   .not_leafdir:
  461.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  462.         jne     .not_nodedir
  463.         jmp     .nodedir
  464.   .not_nodedir:
  465.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE
  466.         jne     .not_btreedir
  467.         jmp     .btreedir
  468.   .not_btreedir:
  469.         movi    eax, ERROR_FS_FAIL
  470.         jmp     .error
  471.  
  472.         ; short form directory (all the data fits into inode)
  473.   .shortdir:
  474. ;DEBUGF 1,"shortdir\n",
  475.         movzx   eax, word[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count]
  476.         test    al, al                  ; is count zero?
  477.         jnz     @f                      ; if not, use it (i8count must be zero then)
  478.         shr     eax, 8                  ; use i8count
  479.     @@:
  480.         add     eax, 1                  ; '..' and '.' are implicit
  481.         mov     dword[edx + 0], 1       ; version
  482.         mov     [edx + 8], eax          ; total entries
  483.         sub     eax, [esp + 24]         ; start number
  484.         cmp     eax, [esp + 28]         ; entries to read
  485.         jbe     @f
  486.         mov     eax, [esp + 28]
  487.     @@:
  488.         mov     [esp + 28], eax
  489.         mov     [edx + 4], eax          ; number of actually read entries
  490.         mov     [ebp + XFS.entries_read], eax
  491.  
  492.         ; inode numbers are often saved as 4 bytes (iff they fit)
  493.         ; compute the length of inode numbers
  494.  
  495.         mov     eax, 4          ; 4 by default
  496.         cmp     byte[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.i8count], 0
  497.         je      @f
  498.         add     eax, eax        ; 4+4=8, iff i8count != 0
  499.     @@:
  500.         mov     dword[edx + 12], 0      ; reserved
  501.         mov     dword[edx + 16], 0      ;
  502.         mov     dword[edx + 20], 0      ;
  503.         mov     dword[edx + 24], 0      ;
  504.         mov     dword[edx + 28], 0      ;
  505.         add     edx, 32
  506.         lea     esi, [ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent + eax]
  507.         dec     ecx
  508.         js      .shortdir.fill
  509.  
  510.         ; skip some entries if the first entry to read is not 0
  511.  
  512.   .shortdir.skip:
  513.         test    ecx, ecx
  514.         jz      .shortdir.skipped
  515.         movzx   edi, byte[esi + xfs_dir2_sf_entry.namelen]
  516.         lea     esi, [esi + xfs_dir2_sf_entry.name + edi]
  517.         add     esi, eax
  518.         dec     ecx
  519.         jnz     .shortdir.skip
  520.         mov     ecx, [esp + 28]         ; entries to read
  521.         jmp     .shortdir.skipped
  522.   .shortdir.fill:
  523.         mov     ecx, [esp + 28]         ; total number
  524.         test    ecx, ecx
  525.         jz      .quit
  526.         push    ecx
  527. ;DEBUGF 1,"ecx: %d\n",ecx
  528.         lea     edi, [edx + 40]         ; get file name offset
  529. ;DEBUGF 1,"filename: ..\n"
  530.         mov     dword[edi], '..'
  531.         mov     edi, edx
  532.         push    eax ebx edx esi
  533.         stdcall xfs_get_inode_number_sf, dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count], dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent + 4], dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent]
  534.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode]
  535. ;        test    eax, eax
  536. ;        jnz     .error
  537.         stdcall xfs_get_inode_info, edx, edi
  538.         test    eax, eax
  539.         pop     esi edx ebx eax
  540.         jnz     .error
  541.         mov     ecx, [esp + 44]         ; file name encding
  542.         mov     [edx + 4], ecx
  543.         add     edx, 304                ; ASCII only for now
  544.         pop     ecx
  545.         dec     ecx
  546.         jz      .quit
  547.  
  548. ;        push    ecx
  549. ;        lea     edi, [edx + 40]
  550. ;DEBUGF 1,"filename: .\n"
  551. ;        mov     dword[edi], '.'
  552. ;        mov     edi, edx
  553. ;        push    eax edx
  554. ;        stdcall xfs_get_inode_info, [ebp + XFS.cur_inode], edi
  555. ;        test    eax, eax
  556. ;        pop     edx eax
  557. ;        jnz     .error
  558. ;        mov     ecx, [esp + 44]
  559. ;        mov     [edx + 4], ecx
  560. ;        add     edx, 304                ; ASCII only for now
  561. ;        pop     ecx
  562. ;        dec     ecx
  563. ;        jz      .quit
  564.  
  565.         ; we skipped some entries
  566.         ; now we fill min(required, present) number of bdfe's
  567.  
  568.   .shortdir.skipped:
  569. ;DEBUGF 1,"ecx: %d\n",ecx
  570.         push    ecx
  571.         movzx   ecx, byte[esi + xfs_dir2_sf_entry.namelen]
  572.         add     esi, xfs_dir2_sf_entry.name
  573.         lea     edi, [edx + 40]         ; bdfe offset of file name
  574. ;DEBUGF 1,"filename: |%s|\n",esi
  575.         rep movsb
  576.         mov     word[edi], 0            ; terminator (ASCIIZ)
  577.  
  578.         push    eax ebx ecx edx esi
  579. ;        push    edx     ; for xfs_get_inode_info
  580.         mov     edi, edx
  581.         stdcall xfs_get_inode_number_sf, dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count], [esi + 4], [esi]
  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.         test    eax, eax
  587.         pop     esi edx ecx ebx eax
  588.         jnz     .error
  589.         mov     ecx, [esp + 44]         ; file name encoding
  590.         mov     [edx + 4], ecx
  591.  
  592.         add     edx, 304                ; ASCII only for now
  593.         add     esi, eax
  594.         pop     ecx
  595.         dec     ecx
  596.         jnz     .shortdir.skipped
  597.         jmp     .quit
  598.  
  599.   .blockdir:
  600. ;DEBUGF 1,"blockdir\n"
  601.         push    edx
  602.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  603.         stdcall xfs_extent_unpack, eax
  604. ;DEBUGF 1,"extent.br_startoff  : 0x%x%x\n",[ebp+XFS.extent.br_startoff+4],[ebp+XFS.extent.br_startoff+0]
  605. ;DEBUGF 1,"extent.br_startblock: 0x%x%x\n",[ebp+XFS.extent.br_startblock+4],[ebp+XFS.extent.br_startblock+0]
  606. ;DEBUGF 1,"extent.br_blockcount: %d\n",[ebp+XFS.extent.br_blockcount]
  607. ;DEBUGF 1,"extent.br_state     : %d\n",[ebp+XFS.extent.br_state]
  608.         stdcall xfs_read_dirblock, dword[ebp + XFS.extent.br_startblock + 0], dword[ebp + XFS.extent.br_startblock + 4], [ebp + XFS.cur_dirblock]
  609.         test    eax, eax
  610.         pop     edx
  611.         jnz     .error
  612. ;DEBUGF 1,"dirblock signature: %s\n",[ebp+XFS.cur_dirblock]
  613.         mov     ebx, [ebp + XFS.cur_dirblock]
  614.         mov     dword[edx + 0], 1       ; version
  615.         mov     eax, [ebp + XFS.dirblocksize]
  616.         mov     ecx, [ebx + eax - sizeof.xfs_dir2_block_tail + xfs_dir2_block_tail.stale]
  617.         mov     eax, [ebx + eax - sizeof.xfs_dir2_block_tail + xfs_dir2_block_tail.count]
  618.         bswap   ecx
  619.         bswap   eax
  620.         sub     eax, ecx                ; actual number of entries = count - stale
  621.         mov     [edx + 8], eax          ; total entries
  622. ;DEBUGF 1,"total entries: %d\n",eax
  623.         sub     eax, [esp + 24]         ; start number
  624.         cmp     eax, [esp + 28]         ; entries to read
  625.         jbe     @f
  626.         mov     eax, [esp + 28]
  627.     @@:
  628.         mov     [esp + 28], eax
  629.         mov     [edx + 4], eax          ; number of actually read entries
  630.         mov     [ebp + XFS.entries_read], eax
  631. ;DEBUGF 1,"actually read entries: %d\n",eax
  632.         mov     dword[edx + 12], 0      ; reserved
  633.         mov     dword[edx + 16], 0      ;
  634.         mov     dword[edx + 20], 0      ;
  635.         mov     dword[edx + 24], 0      ;
  636.         mov     dword[edx + 28], 0      ;
  637.         add     ebx, xfs_dir2_block.u
  638.  
  639.         mov     ecx, [esp + 24]         ; start entry number
  640.                                         ; also means how many to skip
  641.         test    ecx, ecx
  642.         jz      .blockdir.skipped
  643.   .blockdir.skip:
  644.         cmp     word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG
  645.         jne     @f
  646.         movzx   eax, word[ebx + xfs_dir2_data_union.unused.length]
  647.         xchg    al, ah
  648.         add     ebx, eax
  649.         jmp     .blockdir.skip
  650.     @@:
  651.         movzx   eax, [ebx + xfs_dir2_data_union.xentry.namelen]
  652.         lea     ebx, [ebx + xfs_dir2_data_union.xentry.name + eax + 2]       ; 2 bytes for 'tag'
  653.         add     ebx, 7                  ; align on 8 bytes
  654.         and     ebx, not 7
  655.         dec     ecx
  656.         jnz     .blockdir.skip
  657.   .blockdir.skipped:
  658.         mov     ecx, [edx + 4]          ; actually read entries
  659.         test    ecx, ecx
  660.         jz      .quit
  661.         add     edx, 32                 ; set edx to the first bdfe
  662.   .blockdir.next_entry:
  663.         cmp     word[ebx + xfs_dir2_data_union.unused.freetag], XFS_NULL
  664.         jne     @f
  665.         movzx   eax, word[ebx + xfs_dir2_data_union.unused.length]
  666.         xchg    al, ah
  667.         add     ebx, eax
  668.         jmp     .blockdir.next_entry
  669.     @@:
  670.         push    ecx
  671.         push    eax ebx ecx edx esi
  672.         mov     edi, edx
  673.         mov     edx, dword[ebx + xfs_dir2_data_union.xentry.inumber + 0]
  674.         mov     eax, dword[ebx + xfs_dir2_data_union.xentry.inumber + 4]
  675.         bswap   edx
  676.         bswap   eax
  677.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode]
  678.         stdcall xfs_get_inode_info, edx, edi
  679.         test    eax, eax
  680.         pop     esi edx ecx ebx eax
  681.         jnz     .error
  682.         mov     ecx, [esp + 44]
  683.         mov     [edx + 4], ecx
  684.         lea     edi, [edx + 40]
  685.         movzx   ecx, byte[ebx + xfs_dir2_data_union.xentry.namelen]
  686.         lea     esi, [ebx + xfs_dir2_data_union.xentry.name]
  687. ;DEBUGF 1,"filename: |%s|\n",esi
  688.         rep movsb
  689. ;        call    utf8_to_cp866
  690.         mov     word[edi], 0            ; terminator
  691.         lea     ebx, [esi + 2]          ; skip 'tag'
  692.         add     ebx, 7                  ; xfs_dir2_data_entries are aligned to 8 bytes
  693.         and     ebx, not 7
  694.         add     edx, 304
  695.         pop     ecx
  696.         dec     ecx
  697.         jnz     .blockdir.next_entry
  698.         jmp     .quit
  699.  
  700.   .leafdir:
  701. ;DEBUGF 1,"readdir: leaf\n"
  702.         mov     [ebp + XFS.cur_inode_save], ebx
  703.         push    ebx ecx edx
  704.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  705.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  706.         bswap   edx
  707.         stdcall xfs_extent_list_read_dirblock, eax, [ebp + XFS.dir2_leaf_offset_blocks], 0, edx, 0xffffffff, 0xffffffff
  708.         mov     ecx, eax
  709.         and     ecx, edx
  710.         inc     ecx
  711.         pop     edx ecx ebx
  712.         jz      .error
  713.  
  714.         mov     eax, [ebp + XFS.cur_dirblock]
  715.         movzx   ecx, word[eax + xfs_dir2_leaf.hdr.stale]
  716.         movzx   eax, word[eax + xfs_dir2_leaf.hdr.count]
  717.         xchg    cl, ch
  718.         xchg    al, ah
  719.         sub     eax, ecx
  720. ;DEBUGF 1,"total count: %d\n",eax
  721.  
  722.         mov     dword[edx + 0], 1       ; version
  723.         mov     [edx + 8], eax          ; total entries
  724.         sub     eax, [esp + 24]         ; start number
  725.         cmp     eax, [esp + 28]         ; entries to read
  726.         jbe     @f
  727.         mov     eax, [esp + 28]
  728.     @@:
  729.         mov     [esp + 28], eax
  730.         mov     [edx + 4], eax          ; number of actually read entries
  731.  
  732.         mov     dword[edx + 12], 0      ; reserved
  733.         mov     dword[edx + 16], 0      ;
  734.         mov     dword[edx + 20], 0      ;
  735.         mov     dword[edx + 24], 0      ;
  736.         mov     dword[edx + 28], 0      ;
  737.  
  738.         mov     eax, [ebp + XFS.cur_dirblock]
  739.         add     eax, [ebp + XFS.dirblocksize]
  740.         mov     [ebp + XFS.max_dirblockaddr], eax
  741.         mov     dword[ebp + XFS.next_block_num + 0], 0
  742.         mov     dword[ebp + XFS.next_block_num + 4], 0
  743.  
  744.         mov     ebx, [ebp + XFS.max_dirblockaddr]       ; to read dirblock immediately
  745.         mov     ecx, [esp + 24]         ; start number
  746.         test    ecx, ecx
  747.         jz      .leafdir.skipped
  748.   .leafdir.skip:
  749.         cmp     ebx, [ebp + XFS.max_dirblockaddr]
  750.         jne     @f
  751.         push    ecx edx
  752.         mov     ebx, [ebp + XFS.cur_inode_save]
  753.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  754.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  755.         bswap   edx
  756.         stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0
  757.         mov     ecx, eax
  758.         and     ecx, edx
  759.         inc     ecx
  760.         jz      .error
  761.         add     eax, 1
  762.         adc     edx, 0
  763.         mov     dword[ebp + XFS.next_block_num + 0], eax
  764.         mov     dword[ebp + XFS.next_block_num + 4], edx
  765.         mov     ebx, [ebp + XFS.cur_dirblock]
  766.         add     ebx, sizeof.xfs_dir2_data_hdr
  767.         pop     edx ecx
  768.     @@:
  769.         cmp     word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG
  770.         jne     @f
  771.         movzx   eax, word[ebx + xfs_dir2_data_union.unused.length]
  772.         xchg    al, ah
  773.         add     ebx, eax
  774.         jmp     .leafdir.skip
  775.     @@:
  776.         movzx   eax, [ebx + xfs_dir2_data_union.xentry.namelen]
  777.         lea     ebx, [ebx + xfs_dir2_data_union.xentry.name + eax + 2]       ; 2 for 'tag'
  778.         add     ebx, 7
  779.         and     ebx, not 7
  780.         dec     ecx
  781.         jnz     .leafdir.skip
  782.   .leafdir.skipped:
  783.         mov     [ebp + XFS.entries_read], 0
  784.         mov     ecx, [edx + 4]          ; actually read entries
  785.         test    ecx, ecx
  786.         jz      .quit
  787.         add     edx, 32                 ; first bdfe entry
  788.   .leafdir.next_entry:
  789. ;DEBUGF 1,"next_extry\n"
  790.         cmp     ebx, [ebp + XFS.max_dirblockaddr]
  791.         jne     .leafdir.process_current_block
  792.         push    ecx edx
  793.         mov     ebx, [ebp + XFS.cur_inode_save]
  794.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  795.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  796.         bswap   edx
  797.         stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0
  798. ;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax
  799.         mov     ecx, eax
  800.         and     ecx, edx
  801.         inc     ecx
  802.         jnz     @f
  803.         pop     edx ecx
  804.         jmp     .quit
  805.     @@:
  806.         add     eax, 1
  807.         adc     edx, 0
  808.         mov     dword[ebp + XFS.next_block_num + 0], eax
  809.         mov     dword[ebp + XFS.next_block_num + 4], edx
  810.         mov     ebx, [ebp + XFS.cur_dirblock]
  811.         add     ebx, sizeof.xfs_dir2_data_hdr
  812.         pop     edx ecx
  813.   .leafdir.process_current_block:
  814.         cmp     word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG
  815.         jne     @f
  816.         movzx   eax, word[ebx + xfs_dir2_data_union.unused.length]
  817.         xchg    al, ah
  818.         add     ebx, eax
  819.         jmp     .leafdir.next_entry
  820.     @@:
  821.         push    eax ebx ecx edx esi
  822.         mov     edi, edx
  823.         mov     edx, dword[ebx + xfs_dir2_data_union.xentry.inumber + 0]
  824.         mov     eax, dword[ebx + xfs_dir2_data_union.xentry.inumber + 4]
  825.         bswap   edx
  826.         bswap   eax
  827.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode]
  828.         stdcall xfs_get_inode_info, edx, edi
  829.         test    eax, eax
  830.         pop     esi edx ecx ebx eax
  831.         jnz     .error
  832.         push    ecx
  833.         mov     ecx, [esp + 44]
  834.         mov     [edx + 4], ecx
  835.         lea     edi, [edx + 40]
  836.         movzx   ecx, byte[ebx + xfs_dir2_data_union.xentry.namelen]
  837.         lea     esi, [ebx + xfs_dir2_data_union.xentry.name]
  838. ;DEBUGF 1,"filename: |%s|\n",esi
  839.         rep movsb
  840.         pop     ecx
  841.         mov     word[edi], 0
  842.         lea     ebx, [esi + 2]  ; skip 'tag'
  843.         add     ebx, 7          ; xfs_dir2_data_entries are aligned to 8 bytes
  844.         and     ebx, not 7
  845.         add     edx, 304        ; ASCII only for now
  846.         inc     [ebp + XFS.entries_read]
  847.         dec     ecx
  848.         jnz     .leafdir.next_entry
  849.         jmp     .quit
  850.  
  851.   .nodedir:
  852. ;DEBUGF 1,"readdir: node\n"
  853.         push    edx
  854.         mov     [ebp + XFS.cur_inode_save], ebx
  855.         mov     [ebp + XFS.entries_read], 0
  856.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  857.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  858.         bswap   edx
  859.         stdcall xfs_dir2_node_get_numfiles, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks]
  860.         pop     edx
  861.         test    eax, eax
  862.         jnz     .error
  863.         mov     eax, [ebp + XFS.entries_read]
  864.         mov     [ebp + XFS.entries_read], 0
  865. ;DEBUGF 1,"numfiles: %d\n",eax
  866.         mov     dword[edx + 0], 1       ; version
  867.         mov     [edx + 8], eax          ; total entries
  868.         sub     eax, [esp + 24]         ; start number
  869.         cmp     eax, [esp + 28]         ; entries to read
  870.         jbe     @f
  871.         mov     eax, [esp + 28]
  872.     @@:
  873.         mov     [esp + 28], eax
  874.         mov     [edx + 4], eax          ; number of actually read entries
  875.  
  876.         mov     dword[edx + 12], 0      ; reserved
  877.         mov     dword[edx + 16], 0      ;
  878.         mov     dword[edx + 20], 0      ;
  879.         mov     dword[edx + 24], 0      ;
  880.         mov     dword[edx + 28], 0      ;
  881.  
  882.         mov     eax, [ebp + XFS.cur_dirblock]
  883.         add     eax, [ebp + XFS.dirblocksize]
  884.         mov     [ebp + XFS.max_dirblockaddr], eax
  885.         mov     dword[ebp + XFS.next_block_num + 0], 0
  886.         mov     dword[ebp + XFS.next_block_num + 4], 0
  887.  
  888.         mov     ebx, [ebp + XFS.max_dirblockaddr]       ; to read dirblock immediately
  889.         mov     ecx, [esp + 24]         ; start number
  890.         test    ecx, ecx
  891.         jz      .leafdir.skipped
  892.         jmp     .leafdir.skip
  893.  
  894.   .btreedir:
  895. ;DEBUGF 1,"readdir: btree\n"
  896.         mov     [ebp + XFS.cur_inode_save], ebx
  897.         push    ebx edx
  898.         mov     eax, [ebx + xfs_inode.di_core.di_nextents]
  899.         bswap   eax
  900.         mov     [ebp + XFS.ro_nextents], eax
  901.         mov     eax, [ebp + XFS.inodesize]
  902.         sub     eax, xfs_inode.di_u
  903.         sub     eax, sizeof.xfs_bmdr_block
  904.         shr     eax, 4
  905. ;DEBUGF 1,"maxnumresc: %d\n",eax
  906.         mov     edx, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 0]
  907.         mov     eax, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 4]
  908.         bswap   eax
  909.         bswap   edx
  910.         mov     ebx, [ebp + XFS.cur_block]
  911. ;DEBUGF 1,"read_block: %x %x ",edx,eax
  912.         stdcall xfs_read_block
  913.         pop     edx ebx
  914.         test    eax, eax
  915.         jnz     .error
  916. ;DEBUGF 1,"ok\n"
  917.  
  918.         mov     ebx, [ebp + XFS.cur_block]
  919.         push    edx
  920.         mov     [ebp + XFS.entries_read], 0
  921.         lea     eax, [ebx + sizeof.xfs_bmbt_block]
  922.         mov     edx, [ebp + XFS.ro_nextents]
  923.         stdcall xfs_dir2_node_get_numfiles, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks]
  924.         pop     edx
  925.         test    eax, eax
  926.         jnz     .error
  927.         mov     eax, [ebp + XFS.entries_read]
  928.         mov     [ebp + XFS.entries_read], 0
  929. ;DEBUGF 1,"numfiles: %d\n",eax
  930.  
  931.         mov     dword[edx + 0], 1       ; version
  932.         mov     [edx + 8], eax          ; total entries
  933.         sub     eax, [esp + 24]         ; start number
  934.         cmp     eax, [esp + 28]         ; entries to read
  935.         jbe     @f
  936.         mov     eax, [esp + 28]
  937.     @@:
  938.         mov     [esp + 28], eax
  939.         mov     [edx + 4], eax          ; number of actually read entries
  940.  
  941.         mov     dword[edx + 12], 0
  942.         mov     dword[edx + 16], 0
  943.         mov     dword[edx + 20], 0
  944.         mov     dword[edx + 24], 0
  945.         mov     dword[edx + 28], 0
  946.  
  947.         mov     eax, [ebp + XFS.cur_dirblock]   ; fsblock?
  948.         add     eax, [ebp + XFS.dirblocksize]
  949.         mov     [ebp + XFS.max_dirblockaddr], eax
  950.         mov     dword[ebp + XFS.next_block_num + 0], 0
  951.         mov     dword[ebp + XFS.next_block_num + 4], 0
  952.  
  953.         mov     ebx, [ebp + XFS.max_dirblockaddr]       ; to read dirblock immediately
  954.         mov     ecx, [esp + 24]         ; start number
  955.         test    ecx, ecx
  956.         jz      .btreedir.skipped
  957. ;        jmp     .btreedir.skip
  958.   .btreedir.skip:
  959.         cmp     ebx, [ebp + XFS.max_dirblockaddr]
  960.         jne     @f
  961.         push    ecx edx
  962.         mov     ebx, [ebp + XFS.cur_block]
  963.         lea     eax, [ebx + sizeof.xfs_bmbt_block]
  964.         mov     edx, [ebp + XFS.ro_nextents]
  965.         stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0
  966. ;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax
  967.         mov     ecx, eax
  968.         and     ecx, edx
  969.         inc     ecx
  970.         jz      .error
  971.         add     eax, 1
  972.         adc     edx, 0
  973.         mov     dword[ebp + XFS.next_block_num + 0], eax
  974.         mov     dword[ebp + XFS.next_block_num + 4], edx
  975.         mov     ebx, [ebp + XFS.cur_dirblock]
  976.         add     ebx, sizeof.xfs_dir2_data_hdr
  977.         pop     edx ecx
  978.     @@:
  979.         cmp     word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG
  980.         jne     @f
  981.         movzx   eax, word[ebx + xfs_dir2_data_union.unused.length]
  982.         xchg    al, ah
  983.         add     ebx, eax
  984.         jmp     .btreedir.skip
  985.     @@:
  986.         movzx   eax, [ebx + xfs_dir2_data_union.xentry.namelen]
  987.         lea     ebx, [ebx + xfs_dir2_data_union.xentry.name + eax + 2]       ; 2 for 'tag'
  988.         add     ebx, 7
  989.         and     ebx, not 7
  990.         dec     ecx
  991.         jnz     .btreedir.skip
  992.   .btreedir.skipped:
  993.         mov     [ebp + XFS.entries_read], 0
  994.         mov     ecx, [edx + 4]          ; actually read entries
  995.         test    ecx, ecx
  996.         jz      .quit
  997.         add     edx, 32
  998.   .btreedir.next_entry:
  999. ;mov eax, [ebp + XFS.entries_read]
  1000. ;DEBUGF 1,"next_extry: %d\n",eax
  1001.         cmp     ebx, [ebp + XFS.max_dirblockaddr]
  1002.         jne     .btreedir.process_current_block
  1003.         push    ecx edx
  1004.         mov     ebx, [ebp + XFS.cur_block]
  1005.         lea     eax, [ebx + sizeof.xfs_bmbt_block]
  1006.         mov     edx, [ebp + XFS.ro_nextents]
  1007.         stdcall xfs_extent_list_read_dirblock, eax, dword[ebp + XFS.next_block_num + 0], dword[ebp + XFS.next_block_num + 4], edx, [ebp + XFS.dir2_leaf_offset_blocks], 0
  1008. ;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax
  1009.         mov     ecx, eax
  1010.         and     ecx, edx
  1011.         inc     ecx
  1012.         jnz     @f
  1013.         pop     edx ecx
  1014.         jmp     .quit
  1015.     @@:
  1016.         add     eax, 1
  1017.         adc     edx, 0
  1018.         mov     dword[ebp + XFS.next_block_num + 0], eax
  1019.         mov     dword[ebp + XFS.next_block_num + 4], edx
  1020.         mov     ebx, [ebp + XFS.cur_dirblock]
  1021.         add     ebx, sizeof.xfs_dir2_data_hdr
  1022.         pop     edx ecx
  1023.   .btreedir.process_current_block:
  1024.         cmp     word[ebx + xfs_dir2_data_union.unused.freetag], XFS_DIR2_DATA_FREE_TAG
  1025.         jne     @f
  1026.         movzx   eax, word[ebx + xfs_dir2_data_union.unused.length]
  1027.         xchg    al, ah
  1028.         add     ebx, eax
  1029.         jmp     .btreedir.next_entry
  1030.     @@:
  1031.         push    eax ebx ecx edx esi
  1032.         mov     edi, edx
  1033.         mov     edx, dword[ebx + xfs_dir2_data_union.xentry.inumber + 0]
  1034.         mov     eax, dword[ebx + xfs_dir2_data_union.xentry.inumber + 4]
  1035.         bswap   edx
  1036.         bswap   eax
  1037.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.tmp_inode]
  1038.         stdcall xfs_get_inode_info, edx, edi
  1039.         test    eax, eax
  1040.         pop     esi edx ecx ebx eax
  1041.         jnz     .error
  1042.         push    ecx
  1043.         mov     ecx, [esp + 44]
  1044.         mov     [edx + 4], ecx
  1045.         lea     edi, [edx + 40]
  1046.         movzx   ecx, byte[ebx + xfs_dir2_data_union.xentry.namelen]
  1047.         lea     esi, [ebx + xfs_dir2_data_union.xentry.name]
  1048. ;DEBUGF 1,"filename: |%s|\n",esi
  1049.         rep movsb
  1050.         pop     ecx
  1051.         mov     word[edi], 0
  1052.         lea     ebx, [esi + 2]  ; skip 'tag'
  1053.         add     ebx, 7          ; xfs_dir2_data_entries are aligned to 8 bytes
  1054.         and     ebx, not 7
  1055.         add     edx, 304
  1056.         inc     [ebp + XFS.entries_read]
  1057.         dec     ecx
  1058.         jnz     .btreedir.next_entry
  1059.         jmp     .quit
  1060.  
  1061.  
  1062.   .quit:
  1063.         pop     edi esi edx ecx
  1064.         add     esp, 4  ; pop vars
  1065.         xor     eax, eax
  1066. ;        mov     ebx, [esp + 8]
  1067.         mov     ebx, [ebp + XFS.entries_read]
  1068. DEBUGF 1,"xfs_dir_get_bdfes done: %d\n",ebx
  1069.         ret     20
  1070.   .error:
  1071.         pop     edi esi edx ecx
  1072.         add     esp, 4  ; pop vars
  1073.         mov     eax, ERROR_FS_FAIL
  1074.         movi    ebx, -1
  1075.         ret     20
  1076.  
  1077.  
  1078. ;----------------------------------------------------------------
  1079. ; push inode_hi
  1080. ; push inode_lo
  1081. ; push name
  1082. ;----------------------------------------------------------------
  1083. xfs_get_inode_short:
  1084.         ; this function searches for the file in _current_ dir
  1085.         ; it is called recursively for all the subdirs /path/to/my/file
  1086.  
  1087. ;DEBUGF 1,"xfs_get_inode_short: %s\n",[esp+4]
  1088.         mov     esi, [esp + 4]  ; name
  1089.         movzx   eax, word[esi]
  1090.         cmp     eax, '.'        ; current dir; it is already read, just return
  1091.         je      .quit
  1092.         cmp     eax, './'       ; same thing
  1093.         je      .quit
  1094.  
  1095.         ; read inode
  1096.  
  1097.         mov     eax, [esp + 8]  ; inode_lo
  1098.         mov     edx, [esp + 12] ; inode_hi
  1099.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode]
  1100.         test    eax, eax
  1101.         movi    eax, ERROR_FS_FAIL
  1102.         jnz     .error
  1103.  
  1104.         ; find file name in directory
  1105.         ; switch directory ondisk format
  1106.  
  1107.         mov     ebx, edx
  1108.         mov     [ebp + XFS.cur_inode_save], ebx
  1109.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_LOCAL
  1110.         jne     .not_shortdir
  1111. ;DEBUGF 1,"dir: shortdir\n"
  1112.         jmp     .shortdir
  1113.   .not_shortdir:
  1114.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  1115.         jne     .not_blockdir
  1116.         mov     eax, [ebx + xfs_inode.di_core.di_nextents]
  1117.         bswap   eax
  1118.         cmp     eax, 1
  1119.         jne     .not_blockdir
  1120.         jmp     .blockdir
  1121.   .not_blockdir:
  1122.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  1123.         jne     .not_leafdir
  1124.         mov     eax, [ebx + xfs_inode.di_core.di_nextents]
  1125.         bswap   eax
  1126.         cmp     eax, 4
  1127.         ja      .not_leafdir
  1128.         jmp     .leafdir
  1129.   .not_leafdir:
  1130.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  1131.         jne     .not_nodedir
  1132.         jmp     .nodedir
  1133.   .not_nodedir:
  1134.         cmp     byte[ebx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE
  1135.         jne     .not_btreedir
  1136.         jmp     .btreedir
  1137.   .not_btreedir:
  1138. DEBUGF 1,"NOT IMPLEMENTED: DIR FORMAT\n"
  1139.         jmp     .error
  1140.  
  1141.   .shortdir:
  1142.   .shortdir.check_parent:
  1143.         ; parent inode number in shortform directories is always implicit, check this case
  1144.         mov     eax, [esi]
  1145.         and     eax, 0x00ffffff
  1146.         cmp     eax, '..'
  1147.         je      .shortdir.parent2
  1148.         cmp     eax, '../'
  1149.         je      .shortdir.parent3
  1150.         jmp     .shortdir.common
  1151.   .shortdir.parent3:
  1152.         inc     esi
  1153.   .shortdir.parent2:
  1154.         add     esi, 2
  1155.         add     ebx, xfs_inode.di_u
  1156.         stdcall xfs_get_inode_number_sf, dword[ebx + xfs_dir2_sf_hdr.count], dword[ebx + xfs_dir2_sf_hdr.parent + 4], dword[ebx + xfs_dir2_sf_hdr.parent]
  1157. ;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax
  1158.         jmp     .quit
  1159.  
  1160.         ; not a parent inode?
  1161.         ; search in the list, all the other files are stored uniformly
  1162.  
  1163.   .shortdir.common:
  1164.         mov     eax, 4
  1165.         movzx   edx, word[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count] ; read count (byte) and i8count (byte) at once
  1166.         test    dl, dl          ; is count zero?
  1167.         jnz     @f
  1168.         shr     edx, 8          ; use i8count
  1169.         add     eax, eax        ; inode_num size
  1170.     @@:
  1171.         lea     edi, [ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.parent + eax]
  1172.  
  1173.   .next_name:
  1174.         movzx   ecx, byte[edi + xfs_dir2_sf_entry.namelen]
  1175.         add     edi, xfs_dir2_sf_entry.name
  1176.         mov     esi, [esp + 4]
  1177. ;DEBUGF 1,"esi: %s\n",esi
  1178. ;DEBUGF 1,"edi: %s\n",edi
  1179.         repe cmpsb
  1180.         jne     @f
  1181.         cmp     byte[esi], 0            ; HINT: use adc here?
  1182.         je      .found
  1183.         cmp     byte[esi], '/'
  1184.         je      .found_inc
  1185.     @@:
  1186.         add     edi, ecx
  1187.         add     edi, eax
  1188.         dec     edx
  1189.         jnz     .next_name
  1190.         movi    eax, ERROR_FILE_NOT_FOUND
  1191.         jmp     .error
  1192.   .found_inc:           ; increment esi to skip '/' symbol
  1193.                         ; this means esi always points to valid file name or zero terminator byte
  1194.         inc     esi
  1195.   .found:
  1196.         stdcall xfs_get_inode_number_sf, dword[ebx + xfs_inode.di_u + xfs_dir2_sf_hdr.count], [edi + 4], [edi]
  1197. ;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax
  1198.         jmp     .quit
  1199.  
  1200.   .blockdir:
  1201.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  1202.         stdcall xfs_extent_unpack, eax
  1203.         stdcall xfs_read_dirblock, dword[ebp + XFS.extent.br_startblock + 0], dword[ebp + XFS.extent.br_startblock + 4], [ebp + XFS.cur_dirblock]
  1204.         test    eax, eax
  1205.         jnz     .error
  1206. ;DEBUGF 1,"dirblock signature: %s\n",[ebp+XFS.cur_dirblock]
  1207.         mov     ebx, [ebp + XFS.cur_dirblock]
  1208.         mov     eax, [ebp + XFS.dirblocksize]
  1209.         mov     eax, [ebx + eax - sizeof.xfs_dir2_block_tail + xfs_dir2_block_tail.count]
  1210.         ; note that we don't subtract xfs_dir2_block_tail.stale here,
  1211.         ; since we need the number of leaf entries rather than file number
  1212.         bswap   eax
  1213.         add     ebx, [ebp + XFS.dirblocksize]
  1214. ;        mov     ecx, sizeof.xfs_dir2_leaf_entry
  1215.         imul    ecx, eax, sizeof.xfs_dir2_leaf_entry
  1216.         sub     ebx, sizeof.xfs_dir2_block_tail
  1217.         sub     ebx, ecx
  1218.         shr     ecx, 3
  1219.         push    ecx     ; for xfs_get_inode_by_hash
  1220.         push    ebx     ; for xfs_get_inode_by_hash
  1221.  
  1222.         mov     edi, esi
  1223.         xor     eax, eax
  1224.         mov     ecx, 4096       ; MAX_PATH_LEN
  1225.         repne scasb
  1226.         movi    eax, ERROR_FS_FAIL
  1227.         jne     .error
  1228.         neg     ecx
  1229.         add     ecx, 4096       ; MAX_PATH_LEN
  1230.         dec     ecx
  1231.         mov     edx, ecx
  1232. ;DEBUGF 1,"strlen total  : %d\n",edx
  1233.         mov     edi, esi
  1234.         mov     eax, '/'
  1235.         mov     ecx, edx
  1236.         repne scasb
  1237.         jne     @f
  1238.         inc     ecx
  1239.     @@:
  1240.         neg     ecx
  1241.         add     ecx, edx
  1242. ;DEBUGF 1,"strlen current: %d\n",ecx
  1243.         stdcall xfs_hashname, esi, ecx
  1244.         add     esi, ecx
  1245.         cmp     byte[esi], '/'
  1246.         jne     @f
  1247.         inc     esi
  1248.     @@:
  1249. ;DEBUGF 1,"hashed: 0x%x\n",eax
  1250. ;        bswap   eax
  1251.         stdcall xfs_get_addr_by_hash
  1252.         bswap   eax
  1253. ;DEBUGF 1,"got address: 0x%x\n",eax
  1254.         cmp     eax, -1
  1255.         jne     @f
  1256.         movi    eax, ERROR_FILE_NOT_FOUND
  1257.         mov     ebx, -1
  1258.         jmp     .error
  1259.     @@:
  1260.         shl     eax, 3
  1261.         mov     ebx, [ebp + XFS.cur_dirblock]
  1262.         add     ebx, eax
  1263.         mov     edx, [ebx + 0]
  1264.         mov     eax, [ebx + 4]
  1265.         bswap   edx
  1266.         bswap   eax
  1267. ;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax
  1268.         jmp     .quit
  1269.  
  1270.   .leafdir:
  1271. ;DEBUGF 1,"dirblock signature: %s\n",[ebp+XFS.cur_dirblock]
  1272.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  1273.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  1274.         bswap   edx
  1275.         stdcall xfs_extent_list_read_dirblock, eax, [ebp + XFS.dir2_leaf_offset_blocks], 0, edx, -1, -1
  1276. ;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax
  1277.         mov     ecx, eax
  1278.         and     ecx, edx
  1279.         inc     ecx
  1280.         jz      .error
  1281.  
  1282.         mov     ebx, [ebp + XFS.cur_dirblock]
  1283.         movzx   eax, [ebx + xfs_dir2_leaf.hdr.count]
  1284.         ; note that we don't subtract xfs_dir2_leaf.hdr.stale here,
  1285.         ; since we need the number of leaf entries rather than file number
  1286.         xchg    al, ah
  1287.         add     ebx, xfs_dir2_leaf.ents
  1288. ;        imul    ecx, eax, sizeof.xfs_dir2_leaf_entry
  1289. ;        shr     ecx, 3
  1290.         push    eax     ; for xfs_get_addr_by_hash: len
  1291.         push    ebx     ; for xfs_get_addr_by_hash: base
  1292.  
  1293.         mov     edi, esi
  1294.         xor     eax, eax
  1295.         mov     ecx, 4096       ; MAX_PATH_LEN
  1296.         repne scasb
  1297.         movi    eax, ERROR_FS_FAIL
  1298.         jne     .error
  1299.         neg     ecx
  1300.         add     ecx, 4096
  1301.         dec     ecx
  1302.         mov     edx, ecx
  1303. ;DEBUGF 1,"strlen total  : %d\n",edx
  1304.         mov     edi, esi
  1305.         mov     eax, '/'
  1306.         mov     ecx, edx
  1307.         repne scasb
  1308.         jne     @f
  1309.         inc     ecx
  1310.     @@:
  1311.         neg     ecx
  1312.         add     ecx, edx
  1313. ;DEBUGF 1,"strlen current: %d\n",ecx
  1314.         stdcall xfs_hashname, esi, ecx
  1315.         add     esi, ecx
  1316.         cmp     byte[esi], '/'
  1317.         jne     @f
  1318.         inc     esi
  1319.     @@:
  1320. ;DEBUGF 1,"hashed: 0x%x\n",eax
  1321.         stdcall xfs_get_addr_by_hash
  1322.         bswap   eax
  1323. ;DEBUGF 1,"got address: 0x%x\n",eax
  1324.         cmp     eax, -1
  1325.         jne     @f
  1326.         movi    eax, ERROR_FILE_NOT_FOUND
  1327.         mov     ebx, -1
  1328.         jmp     .error
  1329.     @@:
  1330.  
  1331.         mov     ebx, [ebp + XFS.cur_inode_save]
  1332.         push    esi edi
  1333.         xor     edi, edi
  1334.         mov     esi, eax
  1335.         shld    edi, esi, 3     ; get offset
  1336.         shl     esi, 3          ; 2^3 = 8 byte align
  1337.         mov     edx, esi
  1338.         mov     ecx, [ebp + XFS.dirblklog]
  1339.         add     ecx, [ebp + XFS.blocklog]
  1340.         mov     eax, 1
  1341.         shl     eax, cl
  1342.         dec     eax
  1343.         and     edx, eax
  1344.         push    edx
  1345.         shrd    esi, edi, cl
  1346.         shr     edi, cl
  1347.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  1348.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  1349.         bswap   edx
  1350.         stdcall xfs_extent_list_read_dirblock, eax, esi, edi, edx, [ebp + XFS.dir2_leaf_offset_blocks], 0
  1351. ;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax
  1352.         pop     edx
  1353.         pop     edi esi
  1354.         mov     ecx, eax
  1355.         and     ecx, edx
  1356.         inc     ecx
  1357.         jz      .error
  1358.  
  1359.         mov     ebx, [ebp + XFS.cur_dirblock]
  1360.         add     ebx, edx
  1361.         mov     edx, [ebx + 0]
  1362.         mov     eax, [ebx + 4]
  1363.         bswap   edx
  1364.         bswap   eax
  1365. ;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax
  1366.         jmp     .quit
  1367.  
  1368.   .nodedir:
  1369. ;DEBUGF 1,"lookupdir: node\n"
  1370.         mov     [ebp + XFS.cur_inode_save], ebx
  1371.  
  1372.         mov     edi, esi
  1373.         xor     eax, eax
  1374.         mov     ecx, 4096       ; MAX_PATH_LEN
  1375.         repne scasb
  1376.         movi    eax, ERROR_FS_FAIL
  1377.         jne     .error
  1378.         neg     ecx
  1379.         add     ecx, 4096       ; MAX_PATH_LEN
  1380.         dec     ecx
  1381.         mov     edx, ecx
  1382. ;DEBUGF 1,"strlen total  : %d\n",edx
  1383.         mov     edi, esi
  1384.         mov     eax, '/'
  1385.         mov     ecx, edx
  1386.         repne scasb
  1387.         jne     @f
  1388.         inc     ecx
  1389.     @@:
  1390.         neg     ecx
  1391.         add     ecx, edx
  1392. ;DEBUGF 1,"strlen current: %d\n",ecx
  1393.         stdcall xfs_hashname, esi, ecx
  1394.         add     esi, ecx
  1395.         cmp     byte[esi], '/'
  1396.         jne     @f
  1397.         inc     esi
  1398.     @@:
  1399. ;DEBUGF 1,"hashed: 0x%x\n",eax
  1400.         push    edi edx
  1401.         mov     edi, eax
  1402.         mov     [ebp + XFS.entries_read], 0
  1403.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  1404.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  1405.         bswap   edx
  1406.         stdcall xfs_dir2_lookupdir_node, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks], edi
  1407.         pop     edx edi
  1408.         test    eax, eax
  1409.         jnz     .error
  1410.         bswap   ecx
  1411. ;DEBUGF 1,"got address: 0x%x\n",ecx
  1412.  
  1413.         mov     ebx, [ebp + XFS.cur_inode_save]
  1414.         push    esi edi
  1415.         xor     edi, edi
  1416.         mov     esi, ecx
  1417.         shld    edi, esi, 3     ; get offset
  1418.         shl     esi, 3          ; 8 byte align
  1419.         mov     edx, esi
  1420.         mov     ecx, [ebp + XFS.dirblklog]
  1421.         add     ecx, [ebp + XFS.blocklog]
  1422.         mov     eax, 1
  1423.         shl     eax, cl
  1424.         dec     eax
  1425.         and     edx, eax
  1426.         push    edx
  1427.         shrd    esi, edi, cl
  1428.         shr     edi, cl
  1429.         lea     eax, [ebx + xfs_inode.di_u + xfs_bmbt_rec.l0]
  1430.         mov     edx, [ebx + xfs_inode.di_core.di_nextents]
  1431.         bswap   edx
  1432.         stdcall xfs_extent_list_read_dirblock, eax, esi, edi, edx, [ebp + XFS.dir2_leaf_offset_blocks], 0
  1433. ;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax
  1434.         pop     edx
  1435.         pop     edi esi
  1436.         mov     ecx, eax
  1437.         and     ecx, edx
  1438.         inc     ecx
  1439.         jz      .error
  1440.  
  1441.         mov     ebx, [ebp + XFS.cur_dirblock]
  1442.         add     ebx, edx
  1443.         mov     edx, [ebx + 0]
  1444.         mov     eax, [ebx + 4]
  1445.         bswap   edx
  1446.         bswap   eax
  1447. ;DEBUGF 1,"found inode: 0x%x%x\n",edx,eax
  1448.         jmp     .quit
  1449.  
  1450.   .btreedir:
  1451. DEBUGF 1,"lookupdir: btree\n"
  1452.         mov     [ebp + XFS.cur_inode_save], ebx
  1453.  
  1454.         push    ebx edx
  1455.         mov     eax, [ebx + xfs_inode.di_core.di_nextents]
  1456.         bswap   eax
  1457.         mov     [ebp + XFS.ro_nextents], eax
  1458.         mov     eax, [ebp + XFS.inodesize]
  1459.         sub     eax, xfs_inode.di_u
  1460.         sub     eax, sizeof.xfs_bmdr_block
  1461.         shr     eax, 4  ; FIXME forkoff
  1462. ;DEBUGF 1,"maxnumresc: %d\n",eax
  1463.         mov     edx, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 0]
  1464.         mov     eax, dword[ebx + xfs_inode.di_u + sizeof.xfs_bmdr_block + sizeof.xfs_bmbt_key*eax + 4]
  1465.         bswap   eax
  1466.         bswap   edx
  1467.         mov     ebx, [ebp + XFS.cur_block]
  1468. ;DEBUGF 1,"read_block: %x %x ",edx,eax
  1469.         stdcall xfs_read_block
  1470.         pop     edx ebx
  1471.         test    eax, eax
  1472.         jnz     .error
  1473. ;DEBUGF 1,"ok\n"
  1474.         mov     ebx, [ebp + XFS.cur_block]
  1475.  
  1476.         mov     edi, esi
  1477.         xor     eax, eax
  1478.         mov     ecx, 4096       ; MAX_PATH_LEN
  1479.         repne scasb
  1480.         movi    eax, ERROR_FS_FAIL
  1481.         jne     .error
  1482.         neg     ecx
  1483.         add     ecx, 4096
  1484.         dec     ecx
  1485.         mov     edx, ecx
  1486. DEBUGF 1,"strlen total  : %d\n",edx
  1487.         mov     edi, esi
  1488.         mov     eax, '/'
  1489.         mov     ecx, edx
  1490.         repne scasb
  1491.         jne     @f
  1492.         inc     ecx
  1493.     @@:
  1494.         neg     ecx
  1495.         add     ecx, edx
  1496. DEBUGF 1,"strlen current: %d\n",ecx
  1497.         stdcall xfs_hashname, esi, ecx
  1498.         add     esi, ecx
  1499.         cmp     byte[esi], '/'
  1500.         jne     @f
  1501.         inc     esi
  1502.     @@:
  1503. DEBUGF 1,"hashed: 0x%x\n",eax
  1504.         push    edi edx
  1505.         mov     edi, eax
  1506.         mov     [ebp + XFS.entries_read], 0
  1507.         lea     eax, [ebx + sizeof.xfs_bmbt_block]
  1508.         mov     edx, [ebp + XFS.ro_nextents]
  1509. ;push eax
  1510. ;mov eax, [ebp + XFS.dir2_leaf_offset_blocks]
  1511. ;DEBUGF 1,": 0x%x %d\n",eax,eax
  1512. ;pop eax
  1513.         stdcall xfs_dir2_lookupdir_node, eax, edx, [ebp + XFS.dir2_leaf_offset_blocks], edi
  1514.         pop     edx edi
  1515.         test    eax, eax
  1516.         jnz     .error
  1517.         bswap   ecx
  1518. DEBUGF 1,"got address: 0x%x\n",ecx
  1519.  
  1520.         mov     ebx, [ebp + XFS.cur_block]
  1521.         push    esi edi
  1522.         xor     edi, edi
  1523.         mov     esi, ecx
  1524.         shld    edi, esi, 3  ; get offset
  1525.         shl     esi, 3
  1526.         mov     edx, esi
  1527.         mov     ecx, [ebp + XFS.dirblklog]
  1528.         add     ecx, [ebp + XFS.blocklog]
  1529.         mov     eax, 1
  1530.         shl     eax, cl
  1531.         dec     eax
  1532.         and     edx, eax
  1533.         push    edx
  1534.         shrd    esi, edi, cl
  1535.         shr     edi, cl
  1536.         lea     eax, [ebx + sizeof.xfs_bmbt_block]
  1537.         mov     edx, [ebp + XFS.ro_nextents]
  1538.         stdcall xfs_extent_list_read_dirblock, eax, esi, edi, edx, [ebp + XFS.dir2_leaf_offset_blocks], 0
  1539. ;DEBUGF 1,"RETVALUE: %d %d\n",edx,eax
  1540.         pop     edx
  1541.         pop     edi esi
  1542.         mov     ecx, eax
  1543.         and     ecx, edx
  1544.         inc     ecx
  1545.         jz      .error
  1546.  
  1547.         mov     ebx, [ebp + XFS.cur_dirblock]
  1548.         add     ebx, edx
  1549.         mov     edx, [ebx + 0]
  1550.         mov     eax, [ebx + 4]
  1551.         bswap   edx
  1552.         bswap   eax
  1553. DEBUGF 1,"found inode: 0x%x%x\n",edx,eax
  1554.         jmp     .quit
  1555.  
  1556.   .quit:
  1557.         ret     12
  1558.   .error:
  1559.         xor     eax, eax
  1560.         mov     edx, eax
  1561.         ret     12
  1562.  
  1563.  
  1564. ;----------------------------------------------------------------
  1565. ; push name
  1566. ; call xfs_get_inode
  1567. ; test eax, eax
  1568. ;----------------------------------------------------------------
  1569. xfs_get_inode:
  1570.         ; call xfs_get_inode_short until file is found / error returned
  1571.  
  1572. ;DEBUGF 1,"getting inode of: %s\n",[esp+4]
  1573.         push    ebx esi edi
  1574.  
  1575.         ; start from the root inode
  1576.  
  1577.         mov     edx, dword[ebp + XFS.rootino + 4]       ; hi
  1578.         mov     eax, dword[ebp + XFS.rootino + 0]       ; lo
  1579.         mov     esi, [esp + 16] ; name
  1580.  
  1581.   .next_dir:
  1582.         cmp     byte[esi], 0
  1583.         je      .found
  1584.  
  1585. ;DEBUGF 1,"next_level: |%s|\n",esi
  1586.         stdcall xfs_get_inode_short, esi, eax, edx
  1587.         test    edx, edx
  1588.         jnz     @f
  1589.         test    eax, eax
  1590.         jz      .error
  1591.     @@:
  1592.         jmp     .next_dir       ; file name found, go to next directory level
  1593.  
  1594.   .found:
  1595.  
  1596.   .quit:
  1597.         pop     edi esi ebx
  1598.         ret     4
  1599.   .error:
  1600.         pop     edi esi ebx
  1601.         xor     eax, eax
  1602.         mov     edx, eax
  1603.         ret     4
  1604.  
  1605.  
  1606. ;----------------------------------------------------------------
  1607. ; xfs_ReadFolder - XFS implementation of reading a folder
  1608. ; in:  ebp = pointer to XFS structure
  1609. ; in:  esi+[esp+4] = name
  1610. ; in:  ebx = pointer to parameters from sysfunc 70
  1611. ; out: eax, ebx = return values for sysfunc 70
  1612. ;----------------------------------------------------------------
  1613. xfs_ReadFolder:
  1614.  
  1615.         ; to read folder
  1616.         ; 1. lock partition
  1617.         ; 2. find inode number
  1618.         ; 3. read this inode
  1619.         ; 4. get bdfe's
  1620.         ; 5. unlock partition
  1621.  
  1622.         ; 1.
  1623.         call    xfs_lock
  1624.         push    ecx edx esi edi
  1625.  
  1626.         ; 2.
  1627.         push    ebx esi edi
  1628.         add     esi, [esp + 32]         ; directory name
  1629. ;DEBUGF 1,"xfs_ReadFolder: |%s|\n",esi
  1630.         stdcall xfs_get_inode, esi
  1631.         pop     edi esi ebx
  1632.         mov     ecx, edx
  1633.         or      ecx, eax
  1634.         jnz     @f
  1635.         movi    eax, ERROR_FILE_NOT_FOUND
  1636.     @@:
  1637.  
  1638.         ; 3.
  1639.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode]
  1640.         test    eax, eax
  1641.         movi    eax, ERROR_FS_FAIL
  1642.         jnz     .error
  1643.  
  1644.         ; 4.
  1645.         mov     eax, [ebx + 8]          ; encoding
  1646.         and     eax, 1
  1647.         stdcall xfs_dir_get_bdfes, [ebx + 4], [ebx + 12], [ebx + 16], edx, eax
  1648.         test    eax, eax
  1649.         jnz     .error
  1650.  
  1651.   .quit:
  1652. ;DEBUGF 1,"\n\n"
  1653.         pop     edi esi edx ecx
  1654.         ; 5.
  1655.         call    xfs_unlock
  1656.         xor     eax, eax
  1657.         ret
  1658.   .error:
  1659. ;DEBUGF 1,"\n\n"
  1660.         pop     edi esi edx ecx
  1661.         push    eax
  1662.         call    xfs_unlock
  1663.         pop     eax
  1664.         ret
  1665.  
  1666.  
  1667. ;----------------------------------------------------------------
  1668. ; push inode_num_hi
  1669. ; push inode_num_lo
  1670. ; push [count]
  1671. ; call xfs_get_inode_number_sf
  1672. ;----------------------------------------------------------------
  1673. xfs_get_inode_number_sf:
  1674.  
  1675.         ; inode numbers in short form directories may be 4 or 8 bytes long
  1676.         ; determine the length in run time and read inode number at given address
  1677.  
  1678.         cmp     byte[esp + 4 + xfs_dir2_sf_hdr.i8count], 0      ; i8count == 0 means 4 byte per inode number
  1679.         je      .i4bytes
  1680.   .i8bytes:
  1681.         mov     edx, [esp + 12] ; hi
  1682.         mov     eax, [esp + 8]  ; lo
  1683.         bswap   edx             ; big endian
  1684.         bswap   eax
  1685.         ret     12
  1686.   .i4bytes:
  1687.         xor     edx, edx        ; no hi
  1688.         mov     eax, [esp + 12] ; hi = lo
  1689.         bswap   eax             ; big endian
  1690.         ret     12
  1691.  
  1692.  
  1693. ;----------------------------------------------------------------
  1694. ; push dest
  1695. ; push src
  1696. ; call xfs_get_inode_info
  1697. ;----------------------------------------------------------------
  1698. xfs_get_inode_info:
  1699.  
  1700.         ; get access time and other file properties
  1701.         ; useful for browsing directories
  1702.         ; called for each dir entry
  1703.  
  1704. ;DEBUGF 1,"get_inode_info\n"
  1705.         xor     eax, eax
  1706.         mov     edx, [esp + 4]
  1707.         movzx   ecx, word[edx + xfs_inode.di_core.di_mode]
  1708.         xchg    cl, ch
  1709. ;DEBUGF 1,"di_mode: %x\n",ecx
  1710.         test    ecx, S_IFDIR    ; directory?
  1711.         jz      @f
  1712.         mov     eax, 0x10       ; set directory flag
  1713.     @@:
  1714.  
  1715.         mov     edi, [esp + 8]
  1716.         mov     [edi + 0], eax
  1717.         mov     eax, dword[edx + xfs_inode.di_core.di_size + 0] ; hi
  1718.         bswap   eax
  1719.         mov     dword[edi + 36], eax    ; file size hi
  1720. ;DEBUGF 1,"file_size hi: %d\n",eax
  1721.         mov     eax, dword[edx + xfs_inode.di_core.di_size + 4] ; lo
  1722.         bswap   eax
  1723.         mov     dword[edi + 32], eax    ; file size lo
  1724. ;DEBUGF 1,"file_size lo: %d\n",eax
  1725.  
  1726.         add     edi, 8
  1727.         mov     eax, [edx + xfs_inode.di_core.di_ctime.t_sec]
  1728.         bswap   eax
  1729.         push    edx
  1730.         xor     edx, edx
  1731.         add     eax, 3054539008                                     ;(369 * 365 + 89) * 24 * 3600
  1732.         adc     edx, 2
  1733.         call    ntfs_datetime_to_bdfe.sec
  1734.         pop     edx
  1735.  
  1736.         mov     eax, [edx + xfs_inode.di_core.di_atime.t_sec]
  1737.         bswap   eax
  1738.         push    edx
  1739.         xor     edx, edx
  1740.         add     eax, 3054539008                                     ;(369 * 365 + 89) * 24 * 3600
  1741.         adc     edx, 2
  1742.         call    ntfs_datetime_to_bdfe.sec
  1743.         pop     edx
  1744.  
  1745.         mov     eax, [edx + xfs_inode.di_core.di_mtime.t_sec]
  1746.         bswap   eax
  1747.         push    edx
  1748.         xor     edx, edx
  1749.         add     eax, 3054539008                                     ;(369 * 365 + 89) * 24 * 3600
  1750.         adc     edx, 2
  1751.         call    ntfs_datetime_to_bdfe.sec
  1752.         pop     edx
  1753.  
  1754.   .quit:
  1755.         xor     eax, eax
  1756.         ret     8
  1757.   .error:
  1758.         movi    eax, ERROR_FS_FAIL
  1759.         ret     8
  1760.  
  1761.  
  1762. ;----------------------------------------------------------------
  1763. ; push extent_data
  1764. ; call xfs_extent_unpack
  1765. ;----------------------------------------------------------------
  1766. xfs_extent_unpack:
  1767.  
  1768.         ; extents come as packet 128bit bitfields
  1769.         ; lets unpack them to access internal fields
  1770.         ; write result to the XFS.extent structure
  1771.  
  1772.         push    eax ebx ecx edx
  1773.         mov     ebx, [esp + 20]
  1774.  
  1775.         xor     eax, eax
  1776.         mov     edx, [ebx + 0]
  1777.         bswap   edx
  1778.         test    edx, 0x80000000         ; mask, see documentation
  1779.         setnz   al
  1780.         mov     [ebp + XFS.extent.br_state], eax
  1781.  
  1782.         and     edx, 0x7fffffff         ; mask
  1783.         mov     eax, [ebx + 4]
  1784.         bswap   eax
  1785.         shrd    eax, edx, 9
  1786.         shr     edx, 9
  1787.         mov     dword[ebp + XFS.extent.br_startoff + 0], eax
  1788.         mov     dword[ebp + XFS.extent.br_startoff + 4], edx
  1789.  
  1790.         mov     edx, [ebx + 4]
  1791.         mov     eax, [ebx + 8]
  1792.         mov     ecx, [ebx + 12]
  1793.         bswap   edx
  1794.         bswap   eax
  1795.         bswap   ecx
  1796.         and     edx, 0x000001ff         ; mask
  1797.         shrd    ecx, eax, 21
  1798.         shrd    eax, edx, 21
  1799.         mov     dword[ebp + XFS.extent.br_startblock + 0], ecx
  1800.         mov     dword[ebp + XFS.extent.br_startblock + 4], eax
  1801.  
  1802.         mov     eax, [ebx + 12]
  1803.         bswap   eax
  1804.         and     eax, 0x001fffff         ; mask
  1805.         mov     [ebp + XFS.extent.br_blockcount], eax
  1806.  
  1807.         pop     edx ecx ebx eax
  1808. ;DEBUGF 1,"extent.br_startoff  : %d %d\n",[ebp+XFS.extent.br_startoff+4],[ebp+XFS.extent.br_startoff+0]
  1809. ;DEBUGF 1,"extent.br_startblock: %d %d\n",[ebp+XFS.extent.br_startblock+4],[ebp+XFS.extent.br_startblock+0]
  1810. ;DEBUGF 1,"extent.br_blockcount: %d\n",[ebp+XFS.extent.br_blockcount]
  1811. ;DEBUGF 1,"extent.br_state     : %d\n",[ebp+XFS.extent.br_state]
  1812.         ret     4
  1813.  
  1814.  
  1815. ;----------------------------------------------------------------
  1816. ; push namelen
  1817. ; push name
  1818. ; call xfs_hashname
  1819. ;----------------------------------------------------------------
  1820. xfs_hashname:   ; xfs_da_hashname
  1821.  
  1822.         ; simple hash function
  1823.         ; never fails)
  1824.  
  1825.         push    ecx esi
  1826.         xor     eax, eax
  1827.         mov     esi, [esp + 12] ; name
  1828.         mov     ecx, [esp + 16] ; namelen
  1829. ;mov esi, '.'
  1830. ;mov ecx, 1
  1831. ;DEBUGF 1,"hashname: %d %s\n",ecx,esi
  1832.  
  1833.     @@:
  1834.         rol     eax, 7
  1835.         xor     al, [esi]
  1836.         add     esi, 1
  1837.         loop    @b
  1838.  
  1839.         pop     esi ecx
  1840.         ret     8
  1841.  
  1842.  
  1843. ;----------------------------------------------------------------
  1844. ; push  len
  1845. ; push  base
  1846. ; eax -- hash value
  1847. ; call xfs_get_addr_by_hash
  1848. ;----------------------------------------------------------------
  1849. xfs_get_addr_by_hash:
  1850.  
  1851.         ; look for the directory entry offset by its file name hash
  1852.         ; allows fast file search for block, leaf and node directories
  1853.         ; binary (ternary) search
  1854.  
  1855. ;DEBUGF 1,"get_addr_by_hash\n"
  1856.         push    ebx esi
  1857.         mov     ebx, [esp + 12] ; left
  1858.         mov     edx, [esp + 16] ; len
  1859.   .next:
  1860.         mov     ecx, edx
  1861. ;        jecxz   .error
  1862.         test    ecx, ecx
  1863.         jz      .error
  1864.         shr     ecx, 1
  1865.         mov     esi, [ebx + ecx*8 + xfs_dir2_leaf_entry.hashval]
  1866.         bswap   esi
  1867. ;DEBUGF 1,"cmp 0x%x",esi
  1868.         cmp     eax, esi
  1869.         jb      .below
  1870.         ja      .above
  1871.         mov     eax, [ebx + ecx*8 + xfs_dir2_leaf_entry.address]
  1872.         pop     esi ebx
  1873.         ret     8
  1874.   .below:
  1875. ;DEBUGF 1,"b\n"
  1876.         mov     edx, ecx
  1877.         jmp     .next
  1878.   .above:
  1879. ;DEBUGF 1,"a\n"
  1880.         lea     ebx, [ebx + ecx*8 + 8]
  1881.         sub     edx, ecx
  1882.         dec     edx
  1883.         jmp     .next
  1884.   .error:
  1885.         mov     eax, -1
  1886.         pop     esi ebx
  1887.         ret     8
  1888.  
  1889.  
  1890. ;----------------------------------------------------------------
  1891. ; xfs_GetFileInfo - XFS implementation of getting file info
  1892. ; in:  ebp = pointer to XFS structure
  1893. ; in:  esi+[esp+4] = name
  1894. ; in:  ebx = pointer to parameters from sysfunc 70
  1895. ; out: eax, ebx = return values for sysfunc 70
  1896. ;----------------------------------------------------------------
  1897. xfs_GetFileInfo:
  1898.  
  1899.         ; lock partition
  1900.         ; get inode number by file name
  1901.         ; read inode
  1902.         ; get info
  1903.         ; unlock partition
  1904.  
  1905.         push    ecx edx esi edi
  1906.         call    xfs_lock
  1907.  
  1908.         add     esi, [esp + 20]         ; name
  1909. ;DEBUGF 1,"xfs_GetFileInfo: |%s|\n",esi
  1910.         stdcall xfs_get_inode, esi
  1911.         mov     ecx, edx
  1912.         or      ecx, eax
  1913.         jnz     @f
  1914.         movi    eax, ERROR_FILE_NOT_FOUND
  1915.         jmp     .error
  1916.     @@:
  1917.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode]
  1918.         test    eax, eax
  1919.         movi    eax, ERROR_FS_FAIL
  1920.         jnz     .error
  1921.  
  1922.         stdcall xfs_get_inode_info, edx, [ebx + 16]
  1923.  
  1924.   .quit:
  1925.         call    xfs_unlock
  1926.         pop     edi esi edx ecx
  1927.         xor     eax, eax
  1928. ;DEBUGF 1,"quit\n\n"
  1929.         ret
  1930.   .error:
  1931.         call    xfs_unlock
  1932.         pop     edi esi edx ecx
  1933. ;DEBUGF 1,"error\n\n"
  1934.         ret
  1935.  
  1936.  
  1937. ;----------------------------------------------------------------
  1938. ; xfs_Read - XFS implementation of reading a file
  1939. ; in:  ebp = pointer to XFS structure
  1940. ; in:  esi+[esp+4] = name
  1941. ; in:  ebx = pointer to parameters from sysfunc 70
  1942. ; out: eax, ebx = return values for sysfunc 70
  1943. ;----------------------------------------------------------------
  1944. xfs_Read:
  1945.         push    ebx ecx edx esi edi
  1946.         call    xfs_lock
  1947.  
  1948.         add     esi, [esp + 24]
  1949. ;DEBUGF 1,"xfs_Read: %d %d |%s|\n",[ebx+4],[ebx+12],esi
  1950.         stdcall xfs_get_inode, esi
  1951.         mov     ecx, edx
  1952.         or      ecx, eax
  1953.         jnz     @f
  1954.         movi    eax, ERROR_FILE_NOT_FOUND
  1955.         jmp     .error
  1956.     @@:
  1957.         stdcall xfs_read_inode, eax, edx, [ebp + XFS.cur_inode]
  1958.         test    eax, eax
  1959.         movi    eax, ERROR_FS_FAIL
  1960.         jnz     .error
  1961.         mov     [ebp + XFS.cur_inode_save], edx
  1962.  
  1963.         cmp     byte[edx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_EXTENTS
  1964.         jne     .not_extent_list
  1965.         jmp     .extent_list
  1966.   .not_extent_list:
  1967.         cmp     byte[edx + xfs_inode.di_core.di_format], XFS_DINODE_FMT_BTREE
  1968.         jne     .not_btree
  1969.         jmp     .btree
  1970.   .not_btree:
  1971. DEBUGF 1,"XFS: NOT IMPLEMENTED: FILE FORMAT\n"
  1972.         movi    eax, ERROR_FS_FAIL
  1973.         jmp     .error
  1974.   .extent_list:
  1975.         mov     ecx, [ebx + 12]         ; bytes to read
  1976.         mov     edi, [ebx + 16]         ; buffer for data
  1977.         mov     esi, [ebx + 8]          ; offset_hi
  1978.         mov     ebx, [ebx + 4]          ; offset_lo
  1979.  
  1980.         mov     eax, dword[edx + xfs_inode.di_core.di_size + 4] ; lo
  1981.         bswap   eax
  1982.         mov     dword[ebp + XFS.bytes_left_in_file + 0], eax    ; lo
  1983.         mov     eax, dword[edx + xfs_inode.di_core.di_size + 0] ; hi
  1984.         bswap   eax
  1985.         mov     dword[ebp + XFS.bytes_left_in_file + 4], eax    ; hi
  1986.  
  1987.         mov     eax, [edx + xfs_inode.di_core.di_nextents]
  1988.         bswap   eax
  1989.         mov     [ebp + XFS.left_extents], eax
  1990.  
  1991.         mov     dword[ebp + XFS.bytes_read], 0          ; actually read bytes
  1992.  
  1993.         xor     eax, eax                ; extent offset in list
  1994.   .extent_list.next_extent:
  1995. ;DEBUGF 1,"extent_list.next_extent, eax: 0x%x\n",eax
  1996. ;DEBUGF 1,"bytes_to_read: %d\n",ecx
  1997. ;DEBUGF 1,"cur file offset: %d %d\n",esi,ebx
  1998. ;DEBUGF 1,"esp: 0x%x\n",esp
  1999.         cmp     [ebp + XFS.left_extents], 0
  2000.         jne     @f
  2001.         test    ecx, ecx
  2002.         jz      .quit
  2003.         movi    eax, ERROR_END_OF_FILE
  2004.         jmp     .error
  2005.     @@:
  2006.         push    eax
  2007.         lea     eax, [edx + xfs_inode.di_u + eax + xfs_bmbt_rec.l0]
  2008.         stdcall xfs_extent_unpack, eax
  2009.         pop     eax
  2010.         dec     [ebp + XFS.left_extents]
  2011.         add     eax, sizeof.xfs_bmbt_rec
  2012.         push    eax ebx ecx edx esi
  2013.         mov     ecx, [ebp + XFS.blocklog]
  2014.         shrd    ebx, esi, cl
  2015.         shr     esi, cl
  2016.         cmp     esi, dword[ebp + XFS.extent.br_startoff + 4]
  2017.         jb      .extent_list.to_hole          ; handle sparse files
  2018.         ja      @f
  2019.         cmp     ebx, dword[ebp + XFS.extent.br_startoff + 0]
  2020.         jb      .extent_list.to_hole          ; handle sparse files
  2021.         je      .extent_list.to_extent        ; read from the start of current extent
  2022.     @@:
  2023.         xor     edx, edx
  2024.         mov     eax, [ebp + XFS.extent.br_blockcount]
  2025.         add     eax, dword[ebp + XFS.extent.br_startoff + 0]
  2026.         adc     edx, dword[ebp + XFS.extent.br_startoff + 4]
  2027. ;DEBUGF 1,"br_startoff: %d %d\n",edx,eax
  2028.         cmp     esi, edx
  2029.         ja      .extent_list.skip_extent
  2030.         jb      .extent_list.to_extent
  2031.         cmp     ebx, eax
  2032.         jae     .extent_list.skip_extent
  2033.         jmp     .extent_list.to_extent
  2034.   .extent_list.to_hole:
  2035. ;DEBUGF 1,"extent_list.to_hole\n"
  2036.         pop     esi edx ecx ebx eax
  2037.         jmp     .extent_list.read_hole
  2038.   .extent_list.to_extent:
  2039. ;DEBUGF 1,"extent_list.to_extent\n"
  2040.         pop     esi edx ecx ebx eax
  2041.         jmp     .extent_list.read_extent
  2042.   .extent_list.skip_extent:
  2043. ;DEBUGF 1,"extent_list.skip_extent\n"
  2044.         pop     esi edx ecx ebx eax
  2045.         jmp     .extent_list.next_extent
  2046.  
  2047.   .extent_list.read_hole:
  2048. ;DEBUGF 1,"hole: offt: 0x%x%x ",esi,ebx
  2049.         push    eax edx
  2050.         mov     eax, dword[ebp + XFS.extent.br_startoff + 0]
  2051.         mov     edx, dword[ebp + XFS.extent.br_startoff + 4]
  2052.         push    esi ebx
  2053.         mov     ebx, ecx
  2054.         sub     eax, ebx        ; get hole_size, it is 64 bit
  2055.         sbb     edx, 0          ; now edx:eax contains the size of hole
  2056. ;DEBUGF 1,"size: 0x%x%x\n",edx,eax
  2057.         jnz     @f              ; if hole size >= 2^32, write bytes_to_read zero bytes
  2058.         cmp     eax, ecx        ; if hole size >= bytes_to_read, write bytes_to_read zeros
  2059.         jae     @f
  2060.         mov     ecx, eax        ; if hole is < than bytes_to_read, write hole size zeros
  2061.     @@:
  2062.         sub     ebx, ecx        ; bytes_to_read - hole_size = left_to_read
  2063.         add     dword[esp + 0], ecx     ; update pushed file offset
  2064.         adc     dword[esp + 4], 0
  2065.         xor     eax, eax        ; hole is made of zeros
  2066.         rep stosb
  2067.         mov     ecx, ebx
  2068.         pop     ebx esi
  2069.  
  2070.         test    ecx, ecx        ; all requested bytes are read?
  2071.         pop     edx eax
  2072.         jz      .quit
  2073.         jmp     .extent_list.read_extent        ; continue from the start of unpacked extent
  2074.  
  2075.   .extent_list.read_extent:
  2076. ;DEBUGF 1,"extent_list.read_extent\n"
  2077.         push    eax ebx ecx edx esi
  2078.         mov     eax, ebx
  2079.         mov     edx, esi
  2080.         mov     ecx, [ebp + XFS.blocklog]
  2081.         shrd    eax, edx, cl
  2082.         shr     edx, cl
  2083.         sub     eax, dword[ebp + XFS.extent.br_startoff + 0]    ; skip esi:ebx ?
  2084.         sbb     edx, dword[ebp + XFS.extent.br_startoff + 4]
  2085.         sub     [ebp + XFS.extent.br_blockcount], eax
  2086.         add     dword[ebp + XFS.extent.br_startblock + 0], eax
  2087.         adc     dword[ebp + XFS.extent.br_startblock + 4], 0
  2088.   .extent_list.read_extent.next_block:
  2089. ;DEBUGF 1,"extent_list.read_extent.next_block\n"
  2090.         cmp     [ebp + XFS.extent.br_blockcount], 0     ; out of blocks in current extent?
  2091.         jne     @f
  2092.         pop     esi edx ecx ebx eax
  2093.         jmp     .extent_list.next_extent                ; go to next extent
  2094.     @@:
  2095.         mov     eax, dword[ebp + XFS.extent.br_startblock + 0]
  2096.         mov     edx, dword[ebp + XFS.extent.br_startblock + 4]
  2097.         push    ebx
  2098.         mov     ebx, [ebp + XFS.cur_block]
  2099. ;DEBUGF 1,"read block: 0x%x%x\n",edx,eax
  2100.         stdcall xfs_read_block
  2101.         test    eax, eax
  2102.         pop     ebx
  2103.         jz      @f
  2104.         pop     esi edx ecx ebx eax
  2105.         movi    eax, ERROR_FS_FAIL
  2106.         jmp     .error
  2107.     @@:
  2108.         dec     [ebp + XFS.extent.br_blockcount]
  2109.         add     dword[ebp + XFS.extent.br_startblock + 0], 1
  2110.         adc     dword[ebp + XFS.extent.br_startblock + 4], 0
  2111.         mov     esi, [ebp + XFS.cur_block]
  2112.         mov     ecx, [ebp + XFS.blocklog]
  2113.         mov     eax, 1
  2114.         shl     eax, cl
  2115.         dec     eax             ; get blocklog mask
  2116.         and     eax, ebx        ; offset in current block
  2117.         add     esi, eax
  2118.         neg     eax
  2119.         add     eax, [ebp + XFS.blocksize]
  2120.         mov     ecx, [esp + 8]  ; pushed ecx, bytes_to_read
  2121.         cmp     ecx, eax        ; is current block enough?
  2122.         jbe     @f              ; if so, read bytes_to_read bytes
  2123.         mov     ecx, eax        ; otherwise read the block up to the end
  2124.     @@:
  2125.         sub     [esp + 8], ecx          ; left_to_read
  2126.         add     [esp + 12], ecx         ; update current file offset, pushed ebx
  2127.         sub     dword[ebp + XFS.bytes_left_in_file + 0], ecx
  2128.         sbb     dword[ebp + XFS.bytes_left_in_file + 4], 0
  2129.         jnc     @f
  2130.         add     dword[ebp + XFS.bytes_left_in_file + 0], ecx
  2131.         mov     ecx, dword[ebp + XFS.bytes_left_in_file + 0]
  2132.         mov     dword[ebp + XFS.bytes_left_in_file + 0], 0
  2133.         mov     dword[ebp + XFS.bytes_left_in_file + 4], 0
  2134.     @@:
  2135.         add     [ebp + XFS.bytes_read], ecx
  2136.         adc     [esp + 0], dword 0      ; pushed esi
  2137. ;DEBUGF 1,"read data: %d\n",ecx
  2138.         rep movsb
  2139.         mov     ecx, [esp + 8]
  2140. ;DEBUGF 1,"left_to_read: %d\n",ecx
  2141.         xor     ebx, ebx
  2142.         test    ecx, ecx
  2143.         jz      @f
  2144.         cmp     dword[ebp + XFS.bytes_left_in_file + 4], 0
  2145.         jne     .extent_list.read_extent.next_block
  2146.         cmp     dword[ebp + XFS.bytes_left_in_file + 0], 0
  2147.         jne     .extent_list.read_extent.next_block
  2148.     @@:
  2149.         pop     esi edx ecx ebx eax
  2150.         jmp     .quit
  2151.  
  2152.   .btree:
  2153.         mov     ecx, [ebx + 12]         ; bytes to read
  2154.         mov     [ebp + XFS.bytes_to_read], ecx
  2155.         mov     edi, [ebx + 16]         ; buffer for data
  2156.         mov     esi, [ebx + 8]          ; offset_hi
  2157.         mov     ebx, [ebx + 4]          ; offset_lo
  2158.         mov     dword[ebp + XFS.file_offset + 0], ebx
  2159.         mov     dword[ebp + XFS.file_offset + 4], esi
  2160.         mov     [ebp + XFS.buffer_pos], edi
  2161.  
  2162.         mov     eax, dword[edx + xfs_inode.di_core.di_size + 4] ; lo
  2163.         bswap   eax
  2164.         mov     dword[ebp + XFS.bytes_left_in_file + 0], eax    ; lo
  2165.         mov     eax, dword[edx + xfs_inode.di_core.di_size + 0] ; hi
  2166.         bswap   eax
  2167.         mov     dword[ebp + XFS.bytes_left_in_file + 4], eax    ; hi
  2168.  
  2169.         mov     eax, [edx + xfs_inode.di_core.di_nextents]
  2170.         bswap   eax
  2171.         mov     [ebp + XFS.left_extents], eax
  2172.  
  2173.         mov     dword[ebp + XFS.bytes_read], 0          ; actually read bytes
  2174.  
  2175.         push    ebx ecx edx esi edi
  2176.         mov     [ebp + XFS.eof], 0
  2177.         mov     eax, dword[ebp + XFS.file_offset + 0]
  2178.         mov     edx, dword[ebp + XFS.file_offset + 4]
  2179.         add     eax, [ebp + XFS.bytes_to_read]
  2180.         adc     edx, 0
  2181.         sub     eax, dword[ebp + XFS.bytes_left_in_file + 0]
  2182.         sbb     edx, dword[ebp + XFS.bytes_left_in_file + 4]
  2183.         jc      @f      ; file_offset + bytes_to_read < file_size
  2184.         jz      @f      ; file_offset + bytes_to_read = file_size
  2185.         mov     [ebp + XFS.eof], 1
  2186.         cmp     edx, 0
  2187.         jne     .error.eof
  2188.         sub     dword[ebp + XFS.bytes_to_read], eax
  2189.         jc      .error.eof
  2190.         jz      .error.eof
  2191.     @@:
  2192.         stdcall xfs_btree_read, 0, 0, 1
  2193.         pop     edi esi edx ecx ebx
  2194.         test    eax, eax
  2195.         jnz     .error
  2196.         cmp     [ebp + XFS.eof], 1
  2197.         jne     .quit
  2198.         jmp     .error.eof
  2199.  
  2200.  
  2201.   .quit:
  2202.         call    xfs_unlock
  2203.         pop     edi esi edx ecx ebx
  2204.         xor     eax, eax
  2205.         mov     ebx, [ebp + XFS.bytes_read]
  2206. ;DEBUGF 1,"quit: %d\n\n",ebx
  2207.         ret
  2208.   .error.eof:
  2209.         movi    eax, ERROR_END_OF_FILE
  2210.   .error:
  2211. ;DEBUGF 1,"error\n\n"
  2212.         call    xfs_unlock
  2213.         pop     edi esi edx ecx ebx
  2214.         mov     ebx, [ebp + XFS.bytes_read]
  2215.         ret
  2216.  
  2217.  
  2218. ;----------------------------------------------------------------
  2219. ; push  max_offset_hi
  2220. ; push  max_offset_lo
  2221. ; push  nextents
  2222. ; push  block_number_hi
  2223. ; push  block_number_lo
  2224. ; push  extent_list
  2225. ; -1 / read block number
  2226. ;----------------------------------------------------------------
  2227. xfs_extent_list_read_dirblock:  ; skips holes
  2228. ;DEBUGF 1,"xfs_extent_list_read_dirblock\n"
  2229.         push    ebx esi edi
  2230. ;mov eax, [esp+28]
  2231. ;DEBUGF 1,"nextents: %d\n",eax
  2232. ;mov eax, [esp+20]
  2233. ;mov edx, [esp+24]
  2234. ;DEBUGF 1,"block_number: 0x%x%x\n",edx,eax
  2235. ;mov eax, [esp+32]
  2236. ;mov edx, [esp+36]
  2237. ;DEBUGF 1,"max_addr    : 0x%x%x\n",edx,eax
  2238.         mov     ebx, [esp + 16]
  2239.         mov     esi, [esp + 20]
  2240.         mov     edi, [esp + 24]
  2241. ;        mov     ecx, [esp + 28] ; nextents
  2242.   .next_extent:
  2243. ;DEBUGF 1,"next_extent\n"
  2244.         dec     dword[esp + 28]
  2245.         js      .error
  2246.         stdcall xfs_extent_unpack, ebx
  2247.         add     ebx, sizeof.xfs_bmbt_rec        ; next extent
  2248.         mov     edx, dword[ebp + XFS.extent.br_startoff + 4]
  2249.         mov     eax, dword[ebp + XFS.extent.br_startoff + 0]
  2250.         cmp     edx, [esp + 36] ; max_offset_hi
  2251.         ja      .error
  2252.         jb      @f
  2253.         cmp     eax, [esp + 32] ; max_offset_lo
  2254.         jae     .error
  2255.     @@:
  2256.         cmp     edi, edx
  2257.         jb      .hole
  2258.         ja      .check_count
  2259.         cmp     esi, eax
  2260.         jb      .hole
  2261.         ja      .check_count
  2262.         jmp     .read_block
  2263.   .hole:
  2264. ;DEBUGF 1,"hole\n"
  2265.         mov     esi, eax
  2266.         mov     edi, edx
  2267.         jmp     .read_block
  2268.   .check_count:
  2269. ;DEBUGF 1,"check_count\n"
  2270.         add     eax, [ebp + XFS.extent.br_blockcount]
  2271.         adc     edx, 0
  2272.         cmp     edi, edx
  2273.         ja      .next_extent
  2274.         jb      .read_block
  2275.         cmp     esi, eax
  2276.         jae     .next_extent
  2277. ;        jmp     .read_block
  2278.   .read_block:
  2279. ;DEBUGF 1,"read_block\n"
  2280.         push    esi edi
  2281.         sub     esi, dword[ebp + XFS.extent.br_startoff + 0]
  2282.         sbb     edi, dword[ebp + XFS.extent.br_startoff + 4]
  2283.         add     esi, dword[ebp + XFS.extent.br_startblock + 0]
  2284.         adc     edi, dword[ebp + XFS.extent.br_startblock + 4]
  2285.         stdcall xfs_read_dirblock, esi, edi, [ebp + XFS.cur_dirblock]
  2286.         pop     edx eax
  2287.   .quit:
  2288. ;DEBUGF 1,"xfs_extent_list_read_dirblock: quit\n"
  2289.         pop     edi esi ebx
  2290.         ret     24
  2291.   .error:
  2292. ;DEBUGF 1,"xfs_extent_list_read_dirblock: error\n"
  2293.         xor     eax, eax
  2294.         dec     eax
  2295.         mov     edx, eax
  2296.         pop     edi esi ebx
  2297.         ret     24
  2298.  
  2299.  
  2300. ;----------------------------------------------------------------
  2301. ; push  dirblock_num
  2302. ; push  nextents
  2303. ; push  extent_list
  2304. ;----------------------------------------------------------------
  2305. xfs_dir2_node_get_numfiles:
  2306.  
  2307.         ; unfortunately, we need to set 'total entries' field
  2308.         ; this often requires additional effort, since there is no such a number in most directory ondisk formats
  2309.  
  2310. ;DEBUGF 1,"xfs_dir2_node_get_numfiles\n"
  2311.         push    ebx ecx edx esi edi
  2312.  
  2313.         mov     eax, [esp + 24]
  2314.         mov     edx, [esp + 28]
  2315.         mov     esi, [esp + 32]
  2316.         stdcall xfs_extent_list_read_dirblock, eax, esi, 0, edx, -1, -1
  2317.         mov     ecx, eax
  2318.         and     ecx, edx
  2319.         inc     ecx
  2320.         jnz     @f
  2321.         movi    eax, ERROR_FS_FAIL
  2322.         jmp     .error
  2323.     @@:
  2324.         mov     ebx, [ebp + XFS.cur_dirblock]
  2325.         cmp     word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DA_NODE_MAGIC
  2326.         je      .node
  2327.         cmp     word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DIR2_LEAFN_MAGIC
  2328.         je      .leaf
  2329.         mov     eax, ERROR_FS_FAIL
  2330.         jmp     .error
  2331.  
  2332.   .node:
  2333. ;DEBUGF 1,".node\n"
  2334.         mov     edi, [ebx + xfs_da_intnode.hdr.info.forw]
  2335.         bswap   edi
  2336.         mov     eax, [esp + 24]
  2337.         mov     edx, [esp + 28]
  2338.         mov     esi, [ebx + xfs_da_intnode.btree.before]
  2339.         bswap   esi
  2340.         stdcall xfs_dir2_node_get_numfiles, eax, edx, esi
  2341.         test    eax, eax
  2342.         jnz     .error
  2343.         jmp     .common
  2344.        
  2345.   .leaf:
  2346. ;DEBUGF 1,".leaf\n"
  2347.         movzx   ecx, word[ebx + xfs_dir2_leaf.hdr.count]
  2348.         xchg    cl, ch
  2349.         movzx   eax, word[ebx + xfs_dir2_leaf.hdr.stale]
  2350.         xchg    al, ah
  2351.         sub     ecx, eax
  2352.         add     [ebp + XFS.entries_read], ecx
  2353.         mov     edi, [ebx + xfs_dir2_leaf.hdr.info.forw]
  2354.         bswap   edi
  2355.         jmp     .common
  2356.  
  2357.   .common:
  2358.         test    edi, edi
  2359.         jz      .quit
  2360.         mov     esi, edi
  2361.         mov     eax, [esp + 24]
  2362.         mov     edx, [esp + 28]
  2363.         stdcall xfs_dir2_node_get_numfiles, eax, edx, esi
  2364.         test    eax, eax
  2365.         jnz     .error
  2366.         jmp     .quit
  2367.  
  2368.   .quit:
  2369. ;DEBUGF 1,".quit\n"
  2370.         pop     edi esi edx ecx ebx
  2371.         xor     eax, eax
  2372.         ret     12
  2373.   .error:
  2374. ;DEBUGF 1,".error\n"
  2375.         pop     edi esi edx ecx ebx
  2376.         movi    eax, ERROR_FS_FAIL
  2377.         ret     12
  2378.  
  2379.  
  2380. ;----------------------------------------------------------------
  2381. ; push  hash
  2382. ; push  dirblock_num
  2383. ; push  nextents
  2384. ; push  extent_list
  2385. ;----------------------------------------------------------------
  2386. xfs_dir2_lookupdir_node:
  2387. DEBUGF 1,"xfs_dir2_lookupdir_node\n"
  2388.         push    ebx edx esi edi
  2389.  
  2390.         mov     eax, [esp + 20]
  2391.         mov     edx, [esp + 24]
  2392.         mov     esi, [esp + 28]
  2393. DEBUGF 1,"read dirblock: 0x%x %d\n",esi,esi
  2394.         stdcall xfs_extent_list_read_dirblock, eax, esi, 0, edx, -1, -1
  2395. DEBUGF 1,"dirblock read: 0x%x%x\n",edx,eax
  2396.         mov     ecx, eax
  2397.         and     ecx, edx
  2398.         inc     ecx
  2399.         jnz     @f
  2400.         movi    eax, ERROR_FS_FAIL
  2401.         jmp     .error
  2402.     @@:
  2403. DEBUGF 1,"checkpoint #1\n"
  2404.         mov     ebx, [ebp + XFS.cur_dirblock]
  2405.         cmp     word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DA_NODE_MAGIC
  2406.         je      .node
  2407.         cmp     word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DIR2_LEAFN_MAGIC
  2408.         je      .leaf
  2409.         mov     eax, ERROR_FS_FAIL
  2410. DEBUGF 1,"checkpoint #2\n"
  2411.         jmp     .error
  2412.  
  2413.   .node:
  2414. DEBUGF 1,".node\n"
  2415.         mov     edi, [esp + 32] ; hash
  2416.         movzx   ecx, word[ebx + xfs_da_intnode.hdr.count]
  2417.         xchg    cl, ch
  2418.         mov     [ebp + XFS.left_leaves], ecx
  2419.         xor     ecx, ecx
  2420.   .node.next_leaf:
  2421.         mov     esi, [ebx + xfs_da_intnode.btree + ecx*sizeof.xfs_da_node_entry + xfs_da_node_entry.hashval]
  2422.         bswap   esi
  2423.         cmp     edi, esi
  2424.         jbe     .node.leaf_found
  2425.         inc     ecx
  2426.         cmp     ecx, [ebp + XFS.left_leaves]
  2427.         jne     .node.next_leaf
  2428.         mov     eax, ERROR_FILE_NOT_FOUND
  2429.         jmp     .error
  2430.     @@:
  2431.   .node.leaf_found:
  2432.         mov     eax, [esp + 20]
  2433.         mov     edx, [esp + 24]
  2434.         mov     esi, [ebx + xfs_da_intnode.btree + ecx*sizeof.xfs_da_node_entry + xfs_da_node_entry.before]
  2435.         bswap   esi
  2436.         stdcall xfs_dir2_lookupdir_node, eax, edx, esi, edi
  2437.         test    eax, eax
  2438.         jz      .quit
  2439.         movi    eax, ERROR_FILE_NOT_FOUND
  2440.         jmp     .error
  2441.  
  2442.   .leaf:
  2443. DEBUGF 1,".leaf\n"
  2444.         movzx   ecx, [ebx + xfs_dir2_leaf.hdr.count]
  2445.         xchg    cl, ch
  2446.         lea     esi, [ebx + xfs_dir2_leaf.ents]
  2447.         mov     eax, [esp + 32]
  2448.         stdcall xfs_get_addr_by_hash, esi, ecx
  2449.         cmp     eax, -1
  2450.         je      .error
  2451.         mov     ecx, eax
  2452.         jmp     .quit
  2453.  
  2454.   .quit:
  2455. DEBUGF 1,".quit\n"
  2456.         pop     edi esi edx ebx
  2457.         xor     eax, eax
  2458.         ret     16
  2459.   .error:
  2460. DEBUGF 1,".error\n"
  2461.         pop     edi esi edx ebx
  2462.         ret     16
  2463.  
  2464.  
  2465. ;----------------------------------------------------------------
  2466. ; push  dirblock_num
  2467. ; push  nextents
  2468. ; push  extent_list
  2469. ;----------------------------------------------------------------
  2470. xfs_dir2_btree_get_numfiles:
  2471. ;DEBUGF 1,"xfs_dir2_node_get_numfiles\n"
  2472.         push    ebx ecx edx esi edi
  2473.  
  2474.         mov     eax, [esp + 24]
  2475.         mov     edx, [esp + 28]
  2476.         mov     esi, [esp + 32]
  2477.         stdcall xfs_extent_list_read_dirblock, eax, esi, 0, edx, -1, -1
  2478.         mov     ecx, eax
  2479.         and     ecx, edx
  2480.         inc     ecx
  2481.         jnz     @f
  2482.         movi    eax, ERROR_FS_FAIL
  2483.         jmp     .error
  2484.     @@:
  2485.         mov     ebx, [ebp + XFS.cur_dirblock]
  2486.         cmp     word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DA_NODE_MAGIC
  2487.         je      .node
  2488.         cmp     word[ebx + xfs_da_intnode.hdr.info.magic], XFS_DIR2_LEAFN_MAGIC
  2489.         je      .leaf
  2490.         mov     eax, ERROR_FS_FAIL
  2491.         jmp     .error
  2492.  
  2493.   .node:
  2494. ;DEBUGF 1,".node\n"
  2495.         mov     edi, [ebx + xfs_da_intnode.hdr.info.forw]
  2496.         bswap   edi
  2497.         mov     eax, [esp + 24]
  2498.         mov     edx, [esp + 28]
  2499.         mov     esi, [ebx + xfs_da_intnode.btree.before]
  2500.         bswap   esi
  2501.         stdcall xfs_dir2_node_get_numfiles, eax, edx, esi
  2502.         test    eax, eax
  2503.         jnz     .error
  2504.         jmp     .common
  2505.        
  2506.   .leaf:
  2507. ;DEBUGF 1,".leaf\n"
  2508.         movzx   ecx, word[ebx + xfs_dir2_leaf.hdr.count]
  2509.         xchg    cl, ch
  2510.         movzx   eax, word[ebx + xfs_dir2_leaf.hdr.stale]
  2511.         xchg    al, ah
  2512.         sub     ecx, eax
  2513.         add     [ebp + XFS.entries_read], ecx
  2514.         mov     edi, [ebx + xfs_dir2_leaf.hdr.info.forw]
  2515.         bswap   edi
  2516.         jmp     .common
  2517.  
  2518.   .common:
  2519.         test    edi, edi
  2520.         jz      .quit
  2521.         mov     esi, edi
  2522.         mov     eax, [esp + 24]
  2523.         mov     edx, [esp + 28]
  2524.         stdcall xfs_dir2_node_get_numfiles, eax, edx, esi
  2525.         test    eax, eax
  2526.         jnz     .error
  2527.         jmp     .quit
  2528.  
  2529.   .quit:
  2530. ;DEBUGF 1,".quit\n"
  2531.         pop     edi esi edx ecx ebx
  2532.         xor     eax, eax
  2533.         ret     12
  2534.   .error:
  2535. ;DEBUGF 1,".error\n"
  2536.         pop     edi esi edx ecx ebx
  2537.         movi    eax, ERROR_FS_FAIL
  2538.         ret     12
  2539.  
  2540.  
  2541. ;----------------------------------------------------------------
  2542. ; push  is_root
  2543. ; push  block_hi
  2544. ; push  block_lo
  2545. ;----------------------------------------------------------------
  2546. xfs_btree_read:
  2547.         push    ebx ecx edx esi edi
  2548.         cmp     dword[esp + 32], 1      ; is root?
  2549.         je      .root
  2550.         jmp     .not_root
  2551.   .root:
  2552. DEBUGF 1,".root\n"
  2553.         mov     ebx, [ebp + XFS.cur_inode_save]
  2554.         add     ebx, xfs_inode.di_u
  2555.         movzx   edx, [ebx + xfs_bmdr_block.bb_numrecs]
  2556.         xchg    dl, dh
  2557.         dec     edx
  2558.         add     ebx, sizeof.xfs_bmdr_block
  2559.         xor     eax, eax
  2560.         dec     eax
  2561.  .root.next_key:
  2562. DEBUGF 1,".root.next_key\n"
  2563.         cmp     [ebp + XFS.bytes_to_read], 0
  2564.         je      .quit
  2565.         inc     eax
  2566.         cmp     eax, edx        ; out of keys?
  2567.         ja      .root.key_found ; there is no length field, so try the last key
  2568.         lea     edi, [ebx + sizeof.xfs_bmbt_key*eax + 0]
  2569.         lea     esi, [ebx + sizeof.xfs_bmbt_key*eax + 4]
  2570.         bswap   edi
  2571.         bswap   esi
  2572.         mov     ecx, [ebp + XFS.blocklog]
  2573.         shld    edi, esi, cl
  2574.         shl     esi, cl
  2575.         cmp     edi, dword[ebp + XFS.file_offset + 4]
  2576.         ja      .root.prev_or_hole
  2577.         jb      .root.next_key
  2578.         cmp     esi, dword[ebp + XFS.file_offset + 0]
  2579.         ja      .root.prev_or_hole
  2580.         jb      .root.next_key
  2581.         jmp     .root.key_found
  2582.   .root.prev_or_hole:
  2583. DEBUGF 1,".root.prev_or_hole\n"
  2584.         test    eax, eax
  2585.         jz      .root.hole
  2586.         dec     eax
  2587.         jmp     .root.key_found
  2588.   .root.hole:
  2589. DEBUGF 1,".root.hole\n"
  2590.         push    eax edx esi edi
  2591.         mov     ecx, [ebp + XFS.blocklog]
  2592.         shld    edi, esi, cl
  2593.         shl     esi, cl
  2594.         sub     esi, dword[ebp + XFS.file_offset + 0]
  2595.         sbb     edi, dword[ebp + XFS.file_offset + 4]
  2596.         mov     ecx, [ebp + XFS.bytes_to_read]
  2597.         cmp     edi, 0  ; hole size >= 2^32
  2598.         jne     @f
  2599.         cmp     ecx, esi
  2600.         jbe     @f
  2601.         mov     ecx, esi
  2602.     @@:
  2603.         add     dword[ebp + XFS.file_offset + 0], ecx
  2604.         adc     dword[ebp + XFS.file_offset + 4], 0
  2605.         sub     [ebp + XFS.bytes_to_read], ecx
  2606.         xor     eax, eax
  2607.         mov     edi, [ebp + XFS.buffer_pos]
  2608.         rep stosb
  2609.         mov     [ebp + XFS.buffer_pos], edi
  2610.         pop     edi esi edx eax
  2611.         jmp     .root.next_key
  2612.   .root.key_found:
  2613. DEBUGF 1,".root.key_found\n"
  2614.         mov     edx, [ebp + XFS.cur_inode_save]
  2615.         mov     eax, [ebp + XFS.inodesize]
  2616.         sub     eax, xfs_inode.di_u
  2617.         cmp     [edx + xfs_inode.di_core.di_forkoff], 0
  2618.         je      @f
  2619.         movzx   eax, [edx + xfs_inode.di_core.di_forkoff]
  2620.         shl     eax, XFS_DIR2_DATA_ALIGN_LOG    ; 3
  2621.     @@:
  2622.         sub     eax, sizeof.xfs_bmdr_block
  2623.         shr     eax, 4  ;log2(sizeof.xfs_bmbt_key + sizeof.xfs_bmdr_ptr)
  2624.         mov     edx, [ebx + sizeof.xfs_bmbt_key*eax + 0]        ; hi
  2625.         mov     eax, [ebx + sizeof.xfs_bmbt_key*eax + 4]        ; hi
  2626.         bswap   edx
  2627.         bswap   eax
  2628.         stdcall xfs_btree_read, eax, edx, 0
  2629.         test    eax, eax
  2630.         jnz     .error
  2631.         jmp     .root.next_key
  2632.  
  2633.   .not_root:
  2634. DEBUGF 1,".root.not_root\n"
  2635.         mov     eax, [esp + 24] ; block_lo
  2636.         mov     edx, [esp + 28] ; block_hi
  2637.         mov     ebx, [ebp + XFS.cur_block]
  2638.         stdcall xfs_read_block
  2639.         test    eax, eax
  2640.         jnz     .error
  2641.         mov     ebx, [ebp + XFS.cur_block]
  2642.  
  2643.         cmp     [ebx + xfs_bmbt_block.bb_magic], XFS_BMAP_MAGIC
  2644.         jne     .error
  2645.         cmp     [ebx + xfs_bmbt_block.bb_level], 0      ; leaf?
  2646.         je      .leaf
  2647.         jmp     .node
  2648.  
  2649.   .node:
  2650. ;        mov     eax, [ebp + XFS.blocksize]
  2651. ;        sub     eax, sizeof.xfs_bmbt_block
  2652. ;        shr     eax, 4  ; maxnumrecs
  2653.         mov     eax, dword[ebp + XFS.file_offset + 0]   ; lo
  2654.         mov     edx, dword[ebp + XFS.file_offset + 4]   ; hi
  2655.         movzx   edx, [ebx + xfs_bmbt_block.bb_numrecs]
  2656.         xchg    dl, dh
  2657.         dec     edx
  2658.         add     ebx, sizeof.xfs_bmbt_block
  2659.         xor     eax, eax
  2660.         dec     eax
  2661.   .node.next_key:
  2662.         push    eax ecx edx esi edi
  2663.         mov     eax, [esp + 44] ; block_lo
  2664.         mov     edx, [esp + 48] ; block_hi
  2665.         mov     ebx, [ebp + XFS.cur_block]
  2666.         stdcall xfs_read_block
  2667.         test    eax, eax
  2668.         jnz     .error
  2669.         mov     ebx, [ebp + XFS.cur_block]
  2670.         add     ebx, sizeof.xfs_bmbt_block
  2671.         pop     edi esi edx ecx eax
  2672.         cmp     [ebp + XFS.bytes_to_read], 0
  2673.         je      .quit
  2674.         inc     eax
  2675.         cmp     eax, edx        ; out of keys?
  2676.         ja      .node.key_found ; there is no length field, so try the last key
  2677.         lea     edi, [ebx + sizeof.xfs_bmbt_key*eax + 0]
  2678.         lea     esi, [ebx + sizeof.xfs_bmbt_key*eax + 4]
  2679.         bswap   edi
  2680.         bswap   esi
  2681.         mov     ecx, [ebp + XFS.blocklog]
  2682.         shld    edi, esi, cl
  2683.         shl     esi, cl
  2684.         cmp     edi, dword[ebp + XFS.file_offset + 4]
  2685.         ja      .node.prev_or_hole
  2686.         jb      .node.next_key
  2687.         cmp     esi, dword[ebp + XFS.file_offset + 0]
  2688.         ja      .node.prev_or_hole
  2689.         jb      .node.next_key
  2690.         jmp     .node.key_found
  2691.   .node.prev_or_hole:
  2692.         test    eax, eax
  2693.         jz      .node.hole
  2694.         dec     eax
  2695.         jmp     .node.key_found
  2696.   .node.hole:
  2697.         push    eax edx esi edi
  2698.         mov     ecx, [ebp + XFS.blocklog]
  2699.         shld    edi, esi, cl
  2700.         shl     esi, cl
  2701.         sub     esi, dword[ebp + XFS.file_offset + 0]
  2702.         sbb     edi, dword[ebp + XFS.file_offset + 4]
  2703.         mov     ecx, [ebp + XFS.bytes_to_read]
  2704.         cmp     edi, 0  ; hole size >= 2^32
  2705.         jne     @f
  2706.         cmp     ecx, esi
  2707.         jbe     @f
  2708.         mov     ecx, esi
  2709.     @@:
  2710.         add     dword[ebp + XFS.file_offset + 0], ecx
  2711.         adc     dword[ebp + XFS.file_offset + 4], 0
  2712.         sub     [ebp + XFS.bytes_to_read], ecx
  2713.         xor     eax, eax
  2714.         mov     edi, [ebp + XFS.buffer_pos]
  2715.         rep stosb
  2716.         mov     [ebp + XFS.buffer_pos], edi
  2717.         pop     edi esi edx eax
  2718.         jmp     .node.next_key
  2719.   .node.key_found:
  2720.         mov     edx, [ebp + XFS.cur_inode_save]
  2721.         mov     eax, [ebp + XFS.inodesize]
  2722.         sub     eax, xfs_inode.di_u
  2723.         cmp     [edx + xfs_inode.di_core.di_forkoff], 0
  2724.         je      @f
  2725.         movzx   eax, [edx + xfs_inode.di_core.di_forkoff]
  2726.         shl     eax, XFS_DIR2_DATA_ALIGN_LOG    ; 3
  2727.     @@:
  2728.         sub     eax, sizeof.xfs_bmdr_block
  2729.         shr     eax, 4  ;log2(sizeof.xfs_bmbt_key + sizeof.xfs_bmdr_ptr)
  2730.         mov     edx, [ebx + sizeof.xfs_bmbt_key*eax + 0]        ; hi
  2731.         mov     eax, [ebx + sizeof.xfs_bmbt_key*eax + 4]        ; hi
  2732.         bswap   edx
  2733.         bswap   eax
  2734.         stdcall xfs_btree_read, eax, edx, 0
  2735.         test    eax, eax
  2736.         jnz     .error
  2737.         jmp     .node.next_key
  2738.         jmp     .quit
  2739.  
  2740.   .leaf:
  2741.        
  2742.         jmp     .quit
  2743.  
  2744.   .error:
  2745.         pop     edi esi edx ecx ebx
  2746.         movi    eax, ERROR_FS_FAIL
  2747.         ret     4
  2748.   .quit:
  2749.         pop     edi esi edx ecx ebx
  2750.         xor     eax, eax
  2751.         ret     4
  2752.  
  2753.  
  2754. ;----------------------------------------------------------------
  2755. ; push  nextents
  2756. ; push  extent_list
  2757. ; push  file_offset_hi
  2758. ; push  file_offset_lo
  2759. ;----------------------------------------------------------------
  2760. ;xfs_extent_list_read:
  2761. ;        push    ebx 0 edx esi edi       ; zero means actually_read_bytes
  2762. ;
  2763. ;  .quit:
  2764. ;        pop     edi esi edx ecx ebx
  2765. ;        xor     eax, eax
  2766. ;        ret     24
  2767. ;  .error:
  2768. ;        pop     edi esi edx ecx ebx
  2769. ;        ret     24
  2770.