Subversion Repositories Kolibri OS

Rev

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

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