Subversion Repositories Kolibri OS

Rev

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

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