Subversion Repositories Kolibri OS

Rev

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