Subversion Repositories Kolibri OS

Rev

Rev 6462 | Rev 9888 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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