Subversion Repositories Kolibri OS

Rev

Rev 10015 | Details | Compare with Previous | Last modification | View Log | RSS feed

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