Subversion Repositories Kolibri OS

Rev

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