Subversion Repositories Kolibri OS

Rev

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

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