Subversion Repositories Kolibri OS

Rev

Rev 4265 | Rev 5565 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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