Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
6462 pathoswith 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
10051 ace_dent 3
;; Copyright (C) KolibriOS team 2013-2024. All rights reserved. ;;
6462 pathoswith 4
;;  Distributed under terms of the GNU General Public License.  ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
 
9
; EXT external functions
10
;   in:
11
; ebx -> parameter structure of sysfunc 70
12
; ebp -> EXTFS structure
6471 pathoswith 13
; esi -> path string in UTF-8
6462 pathoswith 14
;   out:
15
; eax, ebx = return values for sysfunc 70
16
iglobal
17
align 4
18
ext_user_functions:
19
        dd      ext_free
10015 Doczom 20
        dd      (ext_user_functions_end - ext_user_functions - 8) / 4
6462 pathoswith 21
        dd      ext_ReadFile
22
        dd      ext_ReadFolder
23
        dd      ext_CreateFile
24
        dd      ext_WriteFile
25
        dd      ext_SetFileEnd
26
        dd      ext_GetFileInfo
27
        dd      ext_SetFileInfo
28
        dd      0
29
        dd      ext_Delete
30
        dd      ext_CreateFolder
6933 pathoswith 31
        dd      ext_Rename
6462 pathoswith 32
ext_user_functions_end:
33
endg
34
 
35
struct DIRENTRY
36
inodeNumber     dd  ?
37
entryLength     dw  ?
38
nameLength      db  ?
39
fileType        db  ?
40
name            db  ?   ; rb [nameLength]
41
ends
42
 
43
struct INODE
44
accessMode      dw  ?
45
UID             dw  ?
46
fileSize        dd  ?
47
accessedTime    dd  ?
48
inodeModified   dd  ?
49
dataModified    dd  ?
50
deletedTime     dd  ?
51
GID             dw  ?
52
linksCount      dw  ?
53
sectorsUsed     dd  ?
54
featureFlags    dd  ?
55
reserved        dd  ?
56
blockNumbers    rd  12
57
addressBlock    dd  ?
58
doubleAddress   dd  ?
59
tripleAddress   dd  ?
60
generation      dd  ?
61
ACL             dd  ?
62
fileSizeHigh    dd  ?
63
ends
64
 
65
struct BGDESCR  ; block group descriptor
66
blockBitmap         dd  ?
67
inodeBitmap         dd  ?
68
inodeTable          dd  ?
69
blocksFree          dw  ?
70
inodesFree          dw  ?
71
directoriesCount    dw  ?
72
reserved            rb  14
73
ends
74
 
75
struct SUPERBLOCK
76
inodesTotal         dd  ?
77
blocksTotal         dd  ?
78
blocksReserved      dd  ?
79
blocksFree          dd  ?
80
inodesFree          dd  ?
81
firstGroupBlock     dd  ?
82
sectorsPerBlockLog  dd  ?   ; shift for 1024
83
fragmentSizeLog     dd  ?
84
blocksPerGroup      dd  ?
85
fragmentsPerGroup   dd  ?
86
inodesPerGroup      dd  ?
87
lastMountTime       dd  ?
88
lastWriteTime       dd  ?
89
mountCount          dw  ?
90
mountMax            dw  ?
91
magic               dw  ?
92
state               dw  ?
93
errorHandling       dw  ?
94
additionalVersion   dw  ?
95
lastCheck           dd  ?
96
checkInterval       dd  ?
97
creatorOS           dd  ?
98
dynamicVersionFlag  dd  ?
99
reservedUID         dw  ?
100
reservedGID         dw  ?
101
firstInode          dd  ?
102
inodeSize           dw  ?
103
thisBlockGroup      dw  ?
104
compatibleFlags     dd  ?
105
incompatibleFlags   dd  ?
106
RO_compatibleFlags  dd  ?
6871 pathoswith 107
UUID                rb  16
108
volumeLabel         rb  16
6462 pathoswith 109
ends
110
 
111
; ext4 extent tree
112
struct NODEHEADER       ; tree node header
113
magic           dw  ?   ; 0xF30A
114
entriesFolow    dw  ?
115
entriesMax      dw  ?
116
currentDepth    dw  ?
117
generation      dd  ?
118
ends
119
 
120
struct INDEX    ; root/branch
121
fileBlock       dd  ?
122
nodeBlock       dd  ?
123
nodeBlockHigh   dw  ?
124
reserved        dw  ?
125
ends
126
 
127
struct EXTENT   ; leaf
128
fileBlock       dd  ?
129
blocksCount     dw  ?
130
fsBlockHigh     dw  ?
131
fsBlock         dd  ?
132
ends
133
 
134
ROOT_INODE = 2
135
EXTENTS_USED = 80000h
136
TYPE_MASK = 0F000h
137
FLAG_FILE = 8000h
138
DIRECTORY = 4000h
139
DIR_FLAG_FILE = 1
140
DIR_DIRECTORY = 2
141
KOS_HIDDEN = 2
142
KOS_DIRECTORY = 10h
143
READ_ONLY = 1
144
 
145
; Implemented "incompatible" features:
146
; 2 = have file type in directory entry
147
; 40h = extents
148
; 200h = flexible block groups
149
INCOMPATIBLE_SUPPORT = 242h
150
; Read only support for "incompatible" features:
151
INCOMPATIBLE_READ_SUPPORT = 240h
152
 
153
; Implemented "read-only" features:
154
; 1 = sparse superblock
155
; 2 = 64-bit file size
156
READ_ONLY_SUPPORT = 3
157
 
158
struct EXTFS PARTITION
159
Lock                MUTEX
160
mountType           dd  ?
161
bytesPerBlock       dd  ?
162
sectorsPerBlock     dd  ?
163
dwordsPerBlock      dd  ?
164
dwordsPerBranch     dd  ?   ; dwordsPerBlock ^ 2
165
mainBlockBuffer     dd  ?
166
tempBlockBuffer     dd  ?
6848 pathoswith 167
descriptorTable     dd  ?
168
descriptorTableEnd  dd  ?
6558 pathoswith 169
align0  rb  200h-EXTFS.align0
6462 pathoswith 170
superblock          SUPERBLOCK
6558 pathoswith 171
align1  rb  400h-EXTFS.align1
6462 pathoswith 172
rootInodeBuffer     INODE
6558 pathoswith 173
align2  rb  600h-EXTFS.align2
174
inodeBuffer         INODE
175
align3  rb  800h-EXTFS.align3
6462 pathoswith 176
ends
177
 
178
; mount if it's a valid EXT partition
179
ext2_create_partition:
180
;   in:
181
; ebp -> PARTITION structure
182
; ebx -> boot sector
183
; ebx+512 -> buffer
184
;   out:
185
; eax -> EXTFS structure, 0 = not EXT
186
        push    ebx
187
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
188
        jnz     .fail
189
        mov     eax, 2
190
        add     ebx, 512
191
        call    fs_read32_sys
192
        test    eax, eax
193
        jnz     .fail
194
        cmp     [ebx+SUPERBLOCK.magic], 0xEF53
195
        jne     .fail
196
        cmp     [ebx+SUPERBLOCK.state], 1
6471 pathoswith 197
        ja      .fail
6462 pathoswith 198
        test    [ebx+SUPERBLOCK.incompatibleFlags], not INCOMPATIBLE_SUPPORT
199
        jnz     .fail
200
        cmp     [ebx+SUPERBLOCK.sectorsPerBlockLog], 6  ; 64KB
201
        ja      .fail
6852 pathoswith 202
        cmp     [ebx+SUPERBLOCK.inodeSize], 512
6462 pathoswith 203
        ja      .fail
204
        cmp     [ebx+SUPERBLOCK.blocksPerGroup], 0
205
        je      .fail
206
        cmp     [ebx+SUPERBLOCK.inodesPerGroup], 0
207
        je      .fail
6558 pathoswith 208
        movi    eax, sizeof.EXTFS
209
        call    malloc
6462 pathoswith 210
        test    eax, eax
211
        jz      .fail
212
        mov     ecx, dword [ebp+PARTITION.FirstSector]
213
        mov     dword [eax+EXTFS.FirstSector], ecx
214
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
215
        mov     dword [eax+EXTFS.FirstSector+4], ecx
216
        mov     ecx, dword [ebp+PARTITION.Length]
217
        mov     dword [eax+EXTFS.Length], ecx
218
        mov     ecx, dword [ebp+PARTITION.Length+4]
219
        mov     dword [eax+EXTFS.Length+4], ecx
220
        mov     ecx, [ebp+PARTITION.Disk]
221
        mov     [eax+EXTFS.Disk], ecx
222
        mov     [eax+EXTFS.FSUserFunctions], ext_user_functions
223
 
224
        push    ebp esi edi
225
        mov     ebp, eax
226
        lea     ecx, [eax+EXTFS.Lock]
227
        call    mutex_init
228
        mov     esi, ebx
229
        lea     edi, [ebp+EXTFS.superblock]
230
        mov     ecx, 512/4
231
        rep movsd   ; copy superblock
232
        mov     ecx, [ebx+SUPERBLOCK.sectorsPerBlockLog]
233
        inc     ecx
234
        mov     eax, 1
235
        shl     eax, cl
236
        mov     [ebp+EXTFS.sectorsPerBlock], eax
237
        shl     eax, 9
238
        mov     [ebp+EXTFS.bytesPerBlock], eax
239
        shl     eax, 1
240
        push    eax
241
        shr     eax, 3
242
        mov     [ebp+EXTFS.dwordsPerBlock], eax
243
        mul     eax
244
        mov     [ebp+EXTFS.dwordsPerBranch], eax
245
        call    kernel_alloc
246
        test    eax, eax
247
        jz      .error
248
        mov     [ebp+EXTFS.mainBlockBuffer], eax
249
        add     eax, [ebp+EXTFS.bytesPerBlock]
250
        mov     [ebp+EXTFS.tempBlockBuffer], eax
251
        mov     [ebp+EXTFS.mountType], 0
252
        test    [ebx+SUPERBLOCK.RO_compatibleFlags], not READ_ONLY_SUPPORT
253
        jnz     .read_only
254
        test    [ebx+SUPERBLOCK.incompatibleFlags], INCOMPATIBLE_READ_SUPPORT
255
        jz      @f
256
.read_only:
257
        or      [ebp+EXTFS.mountType], READ_ONLY
6848 pathoswith 258
@@:
259
        mov     eax, [ebx+SUPERBLOCK.inodesTotal]
260
        dec     eax
261
        xor     edx, edx
262
        div     [ebx+SUPERBLOCK.inodesPerGroup]
263
        inc     eax
264
        shl     eax, 5
265
        push    eax eax
266
        call    kernel_alloc
267
        pop     ecx
268
        test    eax, eax
269
        jz      .error2
270
        mov     [ebp+EXTFS.descriptorTable], eax
271
        mov     ebx, eax
272
        add     eax, ecx
273
        mov     [ebp+EXTFS.descriptorTableEnd], eax
274
        mov     eax, [ebp+EXTFS.superblock.firstGroupBlock]
275
        inc     eax
276
        mul     [ebp+EXTFS.sectorsPerBlock]
277
        dec     ecx
278
        shr     ecx, 9
279
        inc     ecx
280
        call    fs_read64_sys
281
        test    eax, eax
282
        jnz     @f
283
        mov     al, ROOT_INODE
6462 pathoswith 284
        lea     ebx, [ebp+EXTFS.rootInodeBuffer]
285
        call    readInode
286
        test    eax, eax
287
        jnz     @f
288
        mov     eax, ebp
289
        pop     edi esi ebp ebx
290
        ret
291
 
292
@@:
6848 pathoswith 293
        stdcall kernel_free, [ebp+EXTFS.descriptorTable]
294
.error2:
6462 pathoswith 295
        stdcall kernel_free, [ebp+EXTFS.mainBlockBuffer]
296
.error:
6558 pathoswith 297
        mov     eax, ebp
298
        call    free
6462 pathoswith 299
        pop     edi esi ebp
300
.fail:
301
        pop     ebx
302
        xor     eax, eax
303
        ret
304
 
305
; unmount EXT partition
306
ext_free:
307
; in: eax -> EXTFS structure
6848 pathoswith 308
        push    eax [eax+EXTFS.mainBlockBuffer]
309
        stdcall kernel_free, [eax+EXTFS.descriptorTable]
310
        call    kernel_free
6558 pathoswith 311
        pop     eax
312
        jmp     free
6462 pathoswith 313
 
314
extfsWriteBlock:
315
        push    fs_write64_sys
316
        jmp     @f
6575 pathoswith 317
; in: eax = block number, ebx -> buffer
6462 pathoswith 318
extfsReadBlock:
319
        push    fs_read64_sys
320
@@:
321
        push    ecx edx
322
        mov     ecx, [ebp+EXTFS.sectorsPerBlock]
323
        mul     ecx
324
        call    dword[esp+8]
325
        pop     edx ecx
326
        add     esp, 4
327
        test    eax, eax
328
        jz      @f
329
        movi    eax, ERROR_DEVICE
330
        stc
331
@@:
332
        ret
333
 
334
extfsWriteDescriptor:
6848 pathoswith 335
; in: ebx = block group descriptor
336
        mov     eax, [ebp+EXTFS.superblock.firstGroupBlock]
337
        inc     eax
338
        mul     [ebp+EXTFS.sectorsPerBlock]
339
        sub     ebx, [ebp+EXTFS.descriptorTable]
340
        shr     ebx, 9
341
        add     eax, ebx
342
        shl     ebx, 9
343
        add     ebx, [ebp+EXTFS.descriptorTable]
6756 pathoswith 344
        call    fs_write32_sys
6462 pathoswith 345
        ret
346
 
6756 pathoswith 347
extfsExtentFree:
348
; in: eax = first block number, ecx = extent size
349
        push    ebx edx edi
6462 pathoswith 350
        sub     eax, [ebp+EXTFS.superblock.firstGroupBlock]
351
        xor     edx, edx
6756 pathoswith 352
        mov     ebx, [ebp+EXTFS.superblock.blocksPerGroup]
353
        div     ebx
354
        sub     ebx, edx
355
        sub     ebx, ecx
356
        jc      .ret
6848 pathoswith 357
        push    edx
358
        mov     ebx, [ebp+EXTFS.descriptorTable]
359
        shl     eax, 5
360
        add     ebx, eax
361
        mov     eax, ecx
362
        mul     [ebp+EXTFS.sectorsPerBlock]
6756 pathoswith 363
        add     [ebx+BGDESCR.blocksFree], cx
6848 pathoswith 364
        add     [ebp+EXTFS.superblock.blocksFree], ecx
365
        sub     [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
366
        push    [ebx+BGDESCR.blockBitmap]
367
        call    extfsWriteDescriptor
6575 pathoswith 368
        pop     eax
369
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
6848 pathoswith 370
        mov     edx, eax
6462 pathoswith 371
        call    extfsReadBlock
372
        pop     eax
6848 pathoswith 373
        jc      .ret
374
        push    ebx edx
6756 pathoswith 375
        mov     edi, eax
376
        shr     edi, 5
377
        shl     edi, 2
378
        add     edi, ebx
6774 pathoswith 379
        mov     edx, ecx
6756 pathoswith 380
        and     eax, 31
6774 pathoswith 381
        jz      .aligned
6756 pathoswith 382
        mov     ecx, 32
383
        sub     ecx, eax
384
        sub     edx, ecx
385
        jnc     @f
386
        add     ecx, edx
387
        xor     edx, edx
388
@@:
389
        or      ebx, -1
390
        shl     ebx, cl
391
        not     ebx
392
        mov     ecx, eax
393
        shl     ebx, cl
394
        not     ebx
395
        and     [edi], ebx
6774 pathoswith 396
        add     edi, 4
397
        xor     eax, eax
398
.aligned:
6756 pathoswith 399
        mov     ecx, edx
400
        shr     ecx, 5
401
        rep stosd
6462 pathoswith 402
        and     edx, 31
6774 pathoswith 403
        jz      @f
6756 pathoswith 404
        mov     ecx, edx
405
        not     eax
406
        shl     eax, cl
407
        and     [edi], eax
408
@@:
409
        pop     eax ebx
6462 pathoswith 410
        call    extfsWriteBlock
6756 pathoswith 411
.ret:
412
        pop     edi edx ebx
6643 pathoswith 413
        xor     eax, eax
6462 pathoswith 414
        ret
415
 
6643 pathoswith 416
extfsInodeAlloc:
417
; in: eax = parent inode number
418
; out: ebx = allocated inode number
6848 pathoswith 419
        push    ecx edx edi
6462 pathoswith 420
        dec     eax
421
        xor     edx, edx
422
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6848 pathoswith 423
        mov     ebx, [ebp+EXTFS.descriptorTable]
424
        shl     eax, 5
425
        add     ebx, eax
426
        push    ebx
6462 pathoswith 427
.test_block_group:
6848 pathoswith 428
        push    ebx
6774 pathoswith 429
        cmp     [ebx+BGDESCR.blocksFree], 0
430
        jz      .next
6848 pathoswith 431
        cmp     [ebx+BGDESCR.inodesFree], 0
432
        jz      .next
6756 pathoswith 433
        dec     [ebx+BGDESCR.inodesFree]
6848 pathoswith 434
        dec     [ebp+EXTFS.superblock.inodesFree]
435
        push    [ebx+BGDESCR.inodeBitmap]
6575 pathoswith 436
        call    extfsWriteDescriptor
6848 pathoswith 437
        pop     eax
6575 pathoswith 438
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
6848 pathoswith 439
        mov     edx, eax
6462 pathoswith 440
        mov     edi, ebx
441
        call    extfsReadBlock
442
        jc      .fail
6643 pathoswith 443
        mov     ecx, [ebp+EXTFS.superblock.inodesPerGroup]
6462 pathoswith 444
        or      eax, -1
445
        shr     ecx, 5
446
        repz scasd
447
        jz      .next
448
        sub     edi, 4
449
        mov     eax, [edi]
450
        not     eax
451
        bsf     eax, eax
452
        bts     [edi], eax
6575 pathoswith 453
        sub     edi, [ebp+EXTFS.tempBlockBuffer]
6462 pathoswith 454
        shl     edi, 3
455
        add     eax, edi
456
        mov     ecx, eax
457
        mov     eax, edx
458
        call    extfsWriteBlock
6575 pathoswith 459
        pop     eax
6848 pathoswith 460
        sub     eax, [ebp+EXTFS.descriptorTable]
461
        shr     eax, 5
6643 pathoswith 462
        mul     [ebp+EXTFS.superblock.inodesPerGroup]
6756 pathoswith 463
        lea     ebx, [eax+ecx+1]
6575 pathoswith 464
        xor     eax, eax
6756 pathoswith 465
.ret:
6848 pathoswith 466
        pop     edi edi edx ecx
6462 pathoswith 467
        ret
468
 
6848 pathoswith 469
.next:      ; search forward, then backward
470
        pop     ebx
471
        cmp     ebx, [esp]
472
        jc      .backward
473
        add     ebx, 32
474
        cmp     ebx, [ebp+EXTFS.descriptorTableEnd]
475
        jc      .test_block_group
476
        mov     ebx, [esp]
6462 pathoswith 477
.backward:
6848 pathoswith 478
        sub     ebx, 32
479
        cmp     ebx, [ebp+EXTFS.descriptorTable]
6756 pathoswith 480
        jnc     .test_block_group
481
        movi    eax, ERROR_DISK_FULL
6848 pathoswith 482
        push    eax
6756 pathoswith 483
.fail:
484
        pop     edi
485
        jmp     .ret
6462 pathoswith 486
 
6643 pathoswith 487
extfsExtentAlloc:
6756 pathoswith 488
; in: eax = parent inode number, ecx = blocks max
489
; out: ebx = first block number, ecx = blocks allocated
6643 pathoswith 490
        push    edx esi edi ecx
491
        dec     eax
492
        xor     edx, edx
493
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6848 pathoswith 494
        mov     ebx, [ebp+EXTFS.descriptorTable]
495
        shl     eax, 5
496
        add     ebx, eax
497
        push    ebx
6643 pathoswith 498
.test_block_group:
6848 pathoswith 499
        push    ebx
500
        cmp     [ebx+BGDESCR.blocksFree], 0
501
        jz      .next
6756 pathoswith 502
        mov     eax, [ebx+BGDESCR.blockBitmap]
6643 pathoswith 503
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
504
        mov     edx, eax
505
        mov     edi, ebx
506
        call    extfsReadBlock
507
        jc      .fail
508
        mov     ecx, [ebp+EXTFS.superblock.blocksPerGroup]
509
        shr     ecx, 5
510
        or      eax, -1
511
        repz scasd
512
        jz      .next
513
        mov     esi, edi
514
        sub     esi, 4
515
        push    edx ecx
516
        mov     eax, [esi]
517
        not     eax
518
        bsf     ecx, eax
519
        not     eax
520
        shr     eax, cl
521
        shl     eax, cl
6774 pathoswith 522
        mov     ebx, 32
6756 pathoswith 523
        bsf     ebx, eax
6643 pathoswith 524
        sub     ebx, ecx
525
        mov     eax, [esp+16]
526
        cmp     ebx, eax
527
        jc      @f
528
        mov     ebx, eax
529
@@:
6774 pathoswith 530
        or      eax, -1
531
        cmp     ebx, 32
532
        jz      @f
6643 pathoswith 533
        xchg    ebx, ecx
534
        shl     eax, cl
535
        not     eax
536
        xchg    ebx, ecx
537
        shl     eax, cl
6774 pathoswith 538
@@:
6643 pathoswith 539
        or      [esi], eax
540
        sub     esi, [ebp+EXTFS.tempBlockBuffer]
541
        shl     esi, 3
542
        add     esi, ecx
543
        mov     eax, [esp+16]
544
        sub     eax, ebx
545
        mov     [esp+16], ebx
546
        add     ebx, ecx
547
        pop     ecx
548
        test    eax, eax
549
        jz      .done
550
        cmp     ebx, 32
551
        jnz     .done
552
        jecxz   .done
553
        mov     ebx, eax
554
        shr     eax, 5
555
        inc     eax
556
        and     ebx, 31
557
        cmp     ecx, eax
558
        jnc     @f
559
        mov     eax, ecx
560
        mov     bl, 32
561
@@:
562
        mov     ecx, eax
563
        shl     eax, 5
564
        add     [esp+12], eax
565
        xor     eax, eax
566
        push    edi
567
        repz scasd
568
        jz      @f
569
        mov     eax, [edi-4]
570
        bsf     eax, eax
571
        xchg    eax, ebx
572
        test    ecx, ecx
573
        jnz     @f
574
        cmp     ebx, eax
575
        jc      @f
576
        mov     ebx, eax
577
@@:
578
        inc     ecx
579
        shl     ecx, 5
580
        sub     ecx, ebx
581
        sub     [esp+16], ecx
582
        mov     ecx, edi
583
        pop     edi
584
        sub     ecx, edi
585
        shr     ecx, 2
586
        dec     ecx
587
        or      eax, -1
588
        rep stosd
589
        mov     ecx, ebx
6859 pathoswith 590
        jecxz   .done
6774 pathoswith 591
        neg     ecx
592
        add     ecx, 32
593
        shr     eax, cl
6643 pathoswith 594
        or      [edi], eax
595
.done:
596
        pop     eax
597
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
598
        call    extfsWriteBlock
6848 pathoswith 599
        mov     ebx, [esp]
6643 pathoswith 600
        mov     ecx, [esp+8]
6756 pathoswith 601
        sub     [ebx+BGDESCR.blocksFree], cx
6848 pathoswith 602
        jnc     @f
603
        mov     [ebx+BGDESCR.blocksFree], 0
604
@@:
6643 pathoswith 605
        sub     [ebp+EXTFS.superblock.blocksFree], ecx
606
        call    extfsWriteDescriptor
607
        pop     eax ebx
6848 pathoswith 608
        sub     eax, [ebp+EXTFS.descriptorTable]
609
        shr     eax, 5
6643 pathoswith 610
        mul     [ebp+EXTFS.superblock.blocksPerGroup]
611
        mov     ebx, eax
612
        add     ebx, esi
6756 pathoswith 613
        add     ebx, [ebp+EXTFS.superblock.firstGroupBlock]
614
        pop     ecx
615
        mov     eax, ecx
616
        mul     [ebp+EXTFS.sectorsPerBlock]
617
        add     [ebp+EXTFS.inodeBuffer.sectorsUsed], eax
6643 pathoswith 618
        xor     eax, eax
619
.ret:
620
        pop     edi esi edx
621
        ret
622
 
623
.next:      ; search forward, then backward
6848 pathoswith 624
        pop     ebx
625
        cmp     ebx, [esp]
6643 pathoswith 626
        jc      .backward
6848 pathoswith 627
        add     ebx, 32
628
        cmp     ebx, [ebp+EXTFS.descriptorTableEnd]
629
        jc      .test_block_group
630
        mov     ebx, [esp]
6643 pathoswith 631
.backward:
6848 pathoswith 632
        sub     ebx, 32
633
        cmp     ebx, [ebp+EXTFS.descriptorTable]
634
        jnc     .test_block_group
635
        movi    eax, ERROR_DISK_FULL
6643 pathoswith 636
        push    eax
6756 pathoswith 637
.fail:
638
        add     esp, 12
6643 pathoswith 639
        xor     ecx, ecx
6756 pathoswith 640
        stc
6643 pathoswith 641
        jmp     .ret
642
 
6726 pathoswith 643
extfsGetExtent:
644
; in: ecx = starting file block
645
; out: eax = first block number, ecx = extent size
646
        push    ebx edx esi
647
        lea     esi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 648
        test    [esi+INODE.featureFlags], EXTENTS_USED
649
        jz      .listTreeSearch
650
        add     esi, INODE.blockNumbers
651
.extentTreeSearch:
652
        cmp     word [esi+NODEHEADER.magic], 0xF30A
653
        jne     .fail
654
        movzx   ebx, [esi+NODEHEADER.entriesFolow]
655
        add     esi, sizeof.NODEHEADER
6726 pathoswith 656
        test    ebx, ebx
657
        jz      .noBlock
6462 pathoswith 658
        cmp     word [esi-sizeof.NODEHEADER+NODEHEADER.currentDepth], 0
659
        je      .leaf_block
6726 pathoswith 660
        dec     ebx
661
        jz      .end_search_index
6462 pathoswith 662
@@:
663
        cmp     ecx, [esi+sizeof.INDEX+INDEX.fileBlock]
664
        jb      .end_search_index
665
        add     esi, sizeof.INDEX
666
        dec     ebx
6726 pathoswith 667
        jnz     @b
6462 pathoswith 668
.end_search_index:
669
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
670
        mov     eax, [esi+INDEX.nodeBlock]
671
        call    extfsReadBlock
6726 pathoswith 672
        jc      .fail2
6462 pathoswith 673
        mov     esi, ebx
674
        jmp     .extentTreeSearch
675
 
6726 pathoswith 676
.fail:
677
        movi    eax, ERROR_FS_FAIL
678
        jmp     .fail2
679
 
6462 pathoswith 680
.leaf_block:
6726 pathoswith 681
        movzx   edx, [esi+EXTENT.blocksCount]
682
        add     edx, [esi+EXTENT.fileBlock]
683
        sub     edx, ecx
684
        ja      .end_search_extent
6462 pathoswith 685
        add     esi, sizeof.EXTENT
686
        dec     ebx
6726 pathoswith 687
        jnz     .leaf_block
688
.noBlock:
689
        movi    eax, ERROR_END_OF_FILE
690
.fail2:
691
        pop     esi edx ebx
692
        stc
693
        ret
6462 pathoswith 694
 
695
.end_search_extent:
696
        sub     ecx, [esi+EXTENT.fileBlock]
6726 pathoswith 697
        jc      .fail
6462 pathoswith 698
        add     ecx, [esi+EXTENT.fsBlock]
6726 pathoswith 699
        mov     eax, ecx
700
        mov     ecx, edx
701
        pop     esi edx ebx
6462 pathoswith 702
        ret
703
 
704
.listTreeSearch:
705
        cmp     ecx, 12
706
        jb      .get_direct_block
707
        sub     ecx, 12
708
        cmp     ecx, [ebp+EXTFS.dwordsPerBlock]
709
        jb      .get_indirect_block
710
        sub     ecx, [ebp+EXTFS.dwordsPerBlock]
711
        cmp     ecx, [ebp+EXTFS.dwordsPerBranch]
712
        jb      .get_double_indirect_block
713
; triply-indirect blocks
714
        sub     ecx, [ebp+EXTFS.dwordsPerBranch]
715
        mov     eax, [esi+INODE.tripleAddress]
6558 pathoswith 716
        test    eax, eax
717
        jz      .noBlock
6462 pathoswith 718
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
719
        call    extfsReadBlock
720
        jc      .fail2
721
        xor     edx, edx
722
        mov     eax, ecx
723
        div     [ebp+EXTFS.dwordsPerBranch]
724
; eax = number in triply-indirect block, edx = number in branch
725
        mov     eax, [ebx+eax*4]
726
        test    eax, eax
6558 pathoswith 727
        jz      .noBlock
6462 pathoswith 728
        call    extfsReadBlock
729
        jc      .fail2
730
        mov     eax, edx
731
        jmp     @f
732
 
6726 pathoswith 733
.get_direct_block:
734
        mov     edx, ecx
735
        mov     cl, 12
736
        lea     ebx, [esi+INODE.blockNumbers]
737
        jmp     .calculateExtent
6462 pathoswith 738
 
6726 pathoswith 739
.get_indirect_block:
740
        mov     eax, [esi+INODE.addressBlock]
741
        test    eax, eax
742
        jz      .noBlock
743
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
744
        call    extfsReadBlock
745
        jc      .fail2
746
        mov     edx, ecx
747
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
748
        jmp     .calculateExtent
749
 
6462 pathoswith 750
.get_double_indirect_block:
751
        mov     eax, [esi+INODE.doubleAddress]
752
        test    eax, eax
6558 pathoswith 753
        jz      .noBlock
6462 pathoswith 754
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
755
        call    extfsReadBlock
756
        jc      .fail2
757
        mov     eax, ecx
758
@@:
759
        xor     edx, edx
6726 pathoswith 760
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
761
        div     ecx
6462 pathoswith 762
; eax = number in doubly-indirect block, edx = number in indirect block
763
        mov     eax, [ebx+eax*4]
764
        test    eax, eax
6558 pathoswith 765
        jz      .noBlock
6462 pathoswith 766
        call    extfsReadBlock
767
        jc      .fail2
6726 pathoswith 768
.calculateExtent:
769
        lea     esi, [ebx+edx*4]
770
        lodsd
6756 pathoswith 771
        test    eax, eax
772
        jz      .noBlock
6726 pathoswith 773
        mov     ebx, eax
774
        sub     ecx, edx
775
        xor     edx, edx
776
@@:
777
        inc     edx
778
        dec     ecx
6462 pathoswith 779
        jz      @f
6726 pathoswith 780
        lodsd
781
        sub     eax, ebx
782
        sub     eax, edx
6462 pathoswith 783
        jz      @b
784
@@:
6726 pathoswith 785
        mov     eax, ebx
786
        mov     ecx, edx
787
        pop     esi edx ebx
788
        clc
6462 pathoswith 789
        ret
790
 
791
getInodeLocation:
792
; in: eax = inode number
6756 pathoswith 793
; out: eax = inode sector, edx = offset in sector
6462 pathoswith 794
        dec     eax
795
        xor     edx, edx
796
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6848 pathoswith 797
        shl     eax, 5
798
        add     eax, [ebp+EXTFS.descriptorTable]
799
        mov     ebx, [eax+BGDESCR.inodeTable]
800
        imul    ebx, [ebp+EXTFS.sectorsPerBlock]
6809 pathoswith 801
        movzx   eax, [ebp+EXTFS.superblock.inodeSize]
802
        mul     edx
6462 pathoswith 803
        mov     edx, eax
804
        shr     eax, 9
805
        and     edx, 511
6756 pathoswith 806
        add     eax, ebx
6462 pathoswith 807
        ret
808
 
809
writeInode:
6575 pathoswith 810
; in: eax = inode number, ebx -> inode data
6462 pathoswith 811
        push    edx edi esi ecx ebx eax
812
        mov     edi, ebx
813
        call    fsGetTime
814
        add     eax, 978307200
815
        mov     [edi+INODE.inodeModified], eax
816
        pop     eax
6774 pathoswith 817
        cmp     eax, ROOT_INODE
818
        jnz     @f
819
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
820
        mov     esi, edi
6852 pathoswith 821
        lea     edi, [ebp+EXTFS.rootInodeBuffer]
6774 pathoswith 822
        rep movsb
823
@@:
6462 pathoswith 824
        call    getInodeLocation
825
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
826
        mov     ecx, eax
827
        call    fs_read32_sys
828
        test    eax, eax
829
        jnz     @f
830
        mov     eax, ecx
831
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
832
        mov     edi, edx
833
        add     edi, ebx
6774 pathoswith 834
        mov     esi, [esp]
6462 pathoswith 835
        rep movsb
836
        call    fs_write32_sys
837
.ret:
838
        pop     ebx ecx esi edi edx
839
        ret
840
 
841
@@:
842
        movi    eax, ERROR_DEVICE
843
        stc
844
        jmp     .ret
845
 
846
readInode:
6575 pathoswith 847
; in: eax = inode number, ebx -> inode buffer
6462 pathoswith 848
        push    edx edi esi ecx ebx
849
        mov     edi, ebx
850
        call    getInodeLocation
851
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
852
        call    fs_read32_sys
853
        test    eax, eax
854
        jnz     @b
855
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
856
        mov     esi, edx
857
        add     esi, ebx
858
        rep movsb
859
        xor     eax, eax
860
        pop     ebx ecx esi edi edx
861
        ret
862
 
6643 pathoswith 863
indirectBlockAlloc:
864
;   in:
865
; edi -> indirect block number
866
; ebx = starting extent block
867
; ecx = extent size
868
; edx = starting file block
869
        mov     eax, [edi]
870
        test    eax, eax
871
        jz      .newBlock
872
        push    edi ebx ecx
873
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
874
        call    extfsReadBlock
875
        jc      .err2
876
        lea     edi, [ebx+edx*4]
877
        test    edx, edx
878
        jz      @f
879
        cmp     dword[edi-4], 0
880
        jnz     @f
881
        pop     ecx ebx edi
882
.err:
883
        mov     al, ERROR_FS_FAIL
884
        stc
885
        ret
886
 
887
.err2:
888
        pop     ecx ebx edi
889
        ret
890
 
891
.newBlock:
892
        test    edx, edx
893
        jnz     .err
894
        mov     [edi], ebx
895
        inc     ebx
896
        dec     ecx
897
        push    edi ebx ecx
898
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
899
        mov     edi, [ebp+EXTFS.tempBlockBuffer]
900
        push    edi
901
        rep stosd
902
        pop     edi
903
@@:
904
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
905
        sub     ecx, edx
906
        pop     ebx eax
907
        sub     ebx, ecx
908
        jnc     @f
909
        add     ecx, ebx
910
        xor     ebx, ebx
911
@@:
912
        jecxz   .done
913
        add     edx, ecx
914
@@:
915
        stosd
916
        inc     eax
917
        loop    @b
918
.done:
919
        pop     edi
920
        push    eax ebx
921
        mov     eax, [edi]
922
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
923
        call    extfsWriteBlock
924
        pop     ecx ebx
925
        ret
926
 
927
doublyIndirectBlockAlloc:
928
;   in:
929
; edi -> indirect block number
930
; edx = starting file block
931
; ebx = starting extent block
932
; ecx = extent size
933
; [esp+4] = rest of size
934
; [esp+8] = parent inode number
935
        mov     eax, [edi]
936
        test    eax, eax
937
        jz      .newBlock
938
        push    edi ecx ebx
939
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
940
        call    extfsReadBlock
941
        jc      .err2
942
        mov     eax, edx
943
        xor     edx, edx
944
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
945
        div     ecx
946
        lea     edi, [ebx+eax*4]
947
        pop     ebx
948
        test    eax, eax
949
        jz      @f
950
        cmp     dword[edi-4], 0
951
        jnz     @f
952
        pop     ecx edi
953
.err:
954
        mov     al, ERROR_FS_FAIL
955
        stc
956
        ret
957
 
958
.err2:
959
        pop     ebx ecx edi
960
        ret
961
 
962
.newBlock:
963
        test    edx, edx
964
        jnz     .err
965
        mov     [edi], ebx
966
        inc     ebx
967
        dec     ecx
968
        inc     dword[esp+4]
969
        push    edi ecx
970
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
971
        mov     edi, [ebp+EXTFS.mainBlockBuffer]
972
        push    ecx edi
973
        rep stosd
974
        pop     edi ecx
975
@@:
976
        sub     ecx, eax
977
        xchg    [esp], ecx
978
.loop:
979
        cmp     dword[edi], 0
980
        jnz     @f
981
        inc     dword[esp+12]
982
@@:
983
        jecxz   .extentAlloc
984
        call    indirectBlockAlloc
985
        jc      .end
986
        cmp     edx, [ebp+EXTFS.dwordsPerBlock]
987
        jnz     @b
988
        add     edi, 4
989
        xor     edx, edx
990
        dec     dword[esp]
991
        jnz     .loop
992
.end:
993
        pop     edi edi
994
        push    ebx eax
995
        mov     eax, [edi]
996
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
997
        call    extfsWriteBlock
998
        pop     ebx
999
        add     eax, ebx
1000
        xor     ebx, ebx
1001
        cmp     ebx, eax
1002
        pop     ebx
1003
        ret
1004
 
1005
.extentAlloc:
1006
        mov     ecx, [esp+12]
1007
        xor     eax, eax
1008
        jecxz   .end
1009
        mov     eax, [esp+16]
1010
        call    extfsExtentAlloc
1011
        jc      .end
1012
        sub     [esp+12], ecx
1013
        jmp     @b
1014
 
6462 pathoswith 1015
extfsExtendFile:
1016
;   in:
6558 pathoswith 1017
; [ebp+EXTFS.inodeBuffer] = inode
6849 pathoswith 1018
; ecx = inode number
1019
; edx:eax = new size
1020
        push    ebx esi edi ecx
6575 pathoswith 1021
        lea     esi, [ebp+EXTFS.inodeBuffer]
6849 pathoswith 1022
        mov     ebx, [esi+INODE.fileSize]
1023
        mov     ecx, [esi+INODE.fileSizeHigh]
1024
        cmp     ebx, eax
1025
        sbb     ecx, edx
6643 pathoswith 1026
        jnc     .ret
6849 pathoswith 1027
        mov     ecx, [esi+INODE.fileSizeHigh]
6643 pathoswith 1028
        mov     [esi+INODE.fileSize], eax
6849 pathoswith 1029
        mov     [esi+INODE.fileSizeHigh], edx
1030
        sub     eax, 1
1031
        sbb     edx, 0
1032
        div     [ebp+EXTFS.bytesPerBlock]
6643 pathoswith 1033
        inc     eax
6849 pathoswith 1034
        xchg    eax, ebx
1035
        mov     edx, ecx
1036
        sub     eax, 1
1037
        sbb     edx, 0
6643 pathoswith 1038
        jc      @f
6849 pathoswith 1039
        div     [ebp+EXTFS.bytesPerBlock]
6643 pathoswith 1040
@@:
6849 pathoswith 1041
        inc     eax
1042
        sub     ebx, eax
6643 pathoswith 1043
        jz      .ret
6849 pathoswith 1044
        push    ebx
1045
        mov     edx, eax
6643 pathoswith 1046
@@:
1047
        mov     ecx, [esp]
1048
        mov     eax, [esp+4]
1049
        test    ecx, ecx
1050
        jz      .done
1051
        call    extfsExtentAlloc
1052
        jc      .errDone
1053
        sub     [esp], ecx
1054
        cmp     edx, 12
1055
        jc      .directBlocks
1056
        sub     edx, 12
1057
        cmp     edx, [ebp+EXTFS.dwordsPerBlock]
1058
        jc      .indirectBlocks
1059
        sub     edx, [ebp+EXTFS.dwordsPerBlock]
1060
        cmp     edx, [ebp+EXTFS.dwordsPerBranch]
1061
        jc      .doublyIndirectBlock
1062
        sub     edx, [ebp+EXTFS.dwordsPerBranch]
1063
        jmp     .triplyIndirectBlock
1064
 
1065
.newExtent:
1066
        jmp     @b
1067
 
1068
.directBlocks:
1069
        lea     edi, [esi+INODE.blockNumbers+edx*4]
1070
        test    edx, edx
1071
        jz      @f
1072
        cmp     dword[edi-4], 0
1073
        jz      .errDone
6575 pathoswith 1074
@@:
1075
        mov     eax, ebx
6643 pathoswith 1076
        mov     ebx, ecx
1077
        mov     ecx, 12
1078
        sub     ecx, edx
1079
        sub     ebx, ecx
1080
        jnc     @f
1081
        add     ecx, ebx
1082
        xor     ebx, ebx
1083
@@:
1084
        add     edx, ecx
1085
@@:
1086
        stosd
1087
        inc     eax
1088
        loop    @b
1089
        mov     ecx, ebx
1090
        mov     ebx, eax
1091
        jecxz   .newExtent
6462 pathoswith 1092
        xor     edx, edx
6643 pathoswith 1093
.indirectBlocks:
1094
        lea     edi, [esi+INODE.addressBlock]
1095
        cmp     dword[edi], 0
1096
        jnz     @f
1097
        inc     dword[esp]
1098
@@:
1099
        call    indirectBlockAlloc
1100
        jc      .errDone
1101
        add     edx, 12
1102
        jecxz   .newExtent
1103
        xor     edx, edx
1104
.doublyIndirectBlock:
1105
        lea     edi, [esi+INODE.doubleAddress]
1106
        call    doublyIndirectBlockAlloc
1107
        jc      .errDone
1108
        mov     edx, [ebp+EXTFS.dwordsPerBranch]
1109
        add     edx, [ebp+EXTFS.dwordsPerBlock]
1110
        add     edx, 12
1111
        jecxz   .newExtent
1112
        xor     edx, edx
1113
.triplyIndirectBlock:
1114
        push    ecx ebx edx
1115
        stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
1116
        pop     edx
1117
        mov     esi, eax
1118
        mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1119
        test    eax, eax
1120
        jz      .newBlock
1121
        mov     ebx, esi
1122
        call    extfsReadBlock
1123
        pop     ebx ecx
1124
        jc      .errFree
1125
        mov     eax, edx
1126
        xor     edx, edx
1127
        div     [ebp+EXTFS.dwordsPerBranch]
1128
        lea     edi, [esi+eax*4]
1129
        test    eax, eax
1130
        jz      @f
1131
        cmp     dword[edi-4], 0
1132
        jnz     @f
1133
        mov     al, ERROR_FS_FAIL
1134
.errFree:
1135
        push    ecx eax
1136
        stdcall kernel_free, esi
1137
        pop     eax ecx
1138
.errDone:
1139
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
1140
        sub     [ebp+EXTFS.inodeBuffer.sectorsUsed], ecx
1141
        pop     ebx
1142
        imul    ebx, [ebp+EXTFS.sectorsPerBlock]
6575 pathoswith 1143
        add     ebx, ecx
6643 pathoswith 1144
        shl     ebx, 9
1145
        sub     [ebp+EXTFS.inodeBuffer.fileSize], ebx
1146
        stc
1147
        jmp     .ret
1148
 
1149
.newBlock:
1150
        pop     ebx ecx
1151
        mov     al, ERROR_FS_FAIL
1152
        test    edx, edx
1153
        jnz     .errFree
1154
        mov     [ebp+EXTFS.inodeBuffer.tripleAddress], ebx
1155
        inc     ebx
1156
        dec     ecx
1157
        inc     dword[esp]
1158
        push    ecx
1159
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
1160
        mov     edi, esi
1161
        xor     eax, eax
1162
        rep stosd
1163
        mov     edi, esi
1164
        pop     ecx
1165
@@:
1166
        jecxz   .extentAlloc
1167
        call    doublyIndirectBlockAlloc
1168
        jc      .errSave
1169
        add     edi, 4
1170
        jmp     @b
1171
 
1172
.extentAlloc:
1173
        mov     ecx, [esp]
1174
        mov     eax, [esp+4]
1175
        jecxz   @f
1176
        call    extfsExtentAlloc
1177
        jc      .errSave
1178
        sub     [esp], ecx
1179
        jmp     @b
1180
 
1181
@@:
1182
        mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1183
        mov     ebx, esi
1184
        call    extfsWriteBlock
1185
        stdcall kernel_free, esi
6558 pathoswith 1186
.done:
6462 pathoswith 1187
        xor     eax, eax
6643 pathoswith 1188
        pop     edi
6462 pathoswith 1189
.ret:
6849 pathoswith 1190
        pop     edi edi esi ebx
6462 pathoswith 1191
        ret
1192
 
6643 pathoswith 1193
.errSave:
1194
        push    eax
1195
        mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1196
        mov     ebx, esi
1197
        call    extfsWriteBlock
1198
        pop     eax
1199
        jmp     .errFree
1200
 
6856 pathoswith 1201
freeBlockList:
1202
; in: edi -> list of blocks, edx = amount of blocks
1203
; out: ebx=0 -> end of list
6756 pathoswith 1204
        mov     ebx, [edi]
1205
        test    ebx, ebx
6856 pathoswith 1206
        jz      .ret
6756 pathoswith 1207
        xor     eax, eax
6643 pathoswith 1208
        xor     ecx, ecx
1209
@@:
1210
        stosd
6756 pathoswith 1211
        inc     ecx
6643 pathoswith 1212
        dec     edx
6756 pathoswith 1213
        jz      @f
1214
        mov     eax, [edi]
1215
        sub     eax, ebx
1216
        sub     eax, ecx
1217
        jz      @b
1218
@@:
1219
        mov     eax, ebx
1220
        call    extfsExtentFree
1221
        test    edx, edx
6856 pathoswith 1222
        jnz     freeBlockList
1223
.ret:
1224
        ret
1225
 
1226
freeIndirectBlock:
1227
; in: edi -> indirect block number, edx = starting block
1228
; out: edi = edi+4, eax=0 -> end
1229
        pushd   ecx 0 edi edx
1230
        mov     eax, [edi]
1231
        test    eax, eax
1232
        jz      .ret
1233
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1234
        call    extfsReadBlock
1235
        jc      .ret
1236
        lea     edi, [ebx+edx*4]
1237
        neg     edx
1238
        add     edx, [ebp+EXTFS.dwordsPerBlock]
1239
        call    freeBlockList
1240
        test    ebx, ebx
1241
        jz      @f
1242
        inc     dword[esp+8]
1243
@@:
6643 pathoswith 1244
        pop     edx edi
1245
        mov     eax, [edi]
1246
        test    edx, edx
1247
        jnz     @f
6756 pathoswith 1248
        xor     ecx, ecx
1249
        inc     ecx
1250
        call    extfsExtentFree
6643 pathoswith 1251
        stosd
1252
        jmp     .done
1253
 
1254
@@:
6756 pathoswith 1255
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
6643 pathoswith 1256
        call    extfsWriteBlock
1257
        add     edi, 4
1258
.done:
1259
        pop     eax ecx
1260
        xor     edx, edx
1261
        ret
1262
 
1263
.ret:
1264
        pop     edi edi edx ecx
1265
        ret
1266
 
1267
freeDoublyIndirectBlock:
1268
; in: edi -> doubly-indirect block number, edx = starting block
1269
; out: edi = edi+4, eax=-1 -> done, eax=0 -> end
1270
        mov     eax, [edi]
1271
        test    eax, eax
1272
        jz      .ret
1273
        push    ecx eax edx
1274
        stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
1275
        mov     ebx, eax
1276
        pop     edx eax
1277
        pushd   0 ebx edx
1278
        call    extfsReadBlock
1279
        jc      .err
1280
        mov     eax, edx
1281
        xor     edx, edx
1282
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
1283
        div     ecx
1284
        sub     ecx, eax
1285
        push    edi
1286
        lea     edi, [ebx+eax*4]
1287
@@:
1288
        call    freeIndirectBlock
1289
        test    eax, eax
1290
        jz      .end
1291
        dec     ecx
1292
        jnz     @b
1293
        dec     dword[esp+12]
1294
.end:
1295
        pop     edi edx
1296
        mov     eax, [edi]
1297
        test    edx, edx
1298
        jnz     @f
1299
        xor     ecx, ecx
6756 pathoswith 1300
        inc     ecx
1301
        call    extfsExtentFree
6643 pathoswith 1302
        stosd
1303
        jmp     .done
1304
 
1305
@@:
1306
        mov     ebx, [esp]
1307
        call    extfsWriteBlock
1308
        add     edi, 4
1309
        jmp     .done
1310
 
1311
.err:
1312
        mov     [esp+8], eax
1313
        pop     eax
1314
.done:
1315
        call    kernel_free
1316
        pop     eax ecx
1317
.ret:
1318
        xor     edx, edx
1319
        ret
1320
 
6462 pathoswith 1321
extfsTruncateFile:
6849 pathoswith 1322
; in: edx:eax = new size, [ebp+EXTFS.inodeBuffer] = inode
6575 pathoswith 1323
        lea     esi, [ebp+EXTFS.inodeBuffer]
6849 pathoswith 1324
        mov     ecx, edx
1325
        cmp     eax, [esi+INODE.fileSize]
1326
        sbb     ecx, [esi+INODE.fileSizeHigh]
6462 pathoswith 1327
        jnc     .ret
6849 pathoswith 1328
        mov     [esi+INODE.fileSize], eax
1329
        mov     [esi+INODE.fileSizeHigh], edx
1330
        sub     eax, 1
1331
        sbb     edx, 0
1332
        jc      @f
1333
        div     [ebp+EXTFS.bytesPerBlock]
1334
@@:
1335
        inc     eax
1336
        mov     edx, eax
6643 pathoswith 1337
        cmp     edx, 12
1338
        jc      .directBlocks
1339
        sub     edx, 12
1340
        cmp     edx, [ebp+EXTFS.dwordsPerBlock]
1341
        jc      .indirectBlocks
1342
        sub     edx, [ebp+EXTFS.dwordsPerBlock]
1343
        cmp     edx, [ebp+EXTFS.dwordsPerBranch]
1344
        jc      .doublyIndirectBlock
1345
        sub     edx, [ebp+EXTFS.dwordsPerBranch]
1346
        jmp     .triplyIndirectBlock
1347
 
1348
.directBlocks:
1349
        lea     edi, [esi+INODE.blockNumbers+edx*4]
1350
        neg     edx
1351
        add     edx, 12
6856 pathoswith 1352
        call    freeBlockList
1353
        test    ebx, ebx
6643 pathoswith 1354
        jz      .ret
1355
.indirectBlocks:
1356
        lea     edi, [esi+INODE.addressBlock]
1357
        call    freeIndirectBlock
1358
        test    eax, eax
1359
        jz      .ret
1360
.doublyIndirectBlock:
1361
        lea     edi, [esi+INODE.doubleAddress]
1362
        call    freeDoublyIndirectBlock
1363
        test    eax, eax
1364
        jz      .ret
1365
.triplyIndirectBlock:
1366
        mov     eax, [esi+INODE.tripleAddress]
1367
        test    eax, eax
1368
        jz      .ret
1369
        push    eax edx
1370
        stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
6575 pathoswith 1371
        mov     ebx, eax
6643 pathoswith 1372
        pop     edx eax
1373
        push    ebx eax edx
1374
        call    extfsReadBlock
1375
        jc      .err
1376
        mov     eax, edx
6462 pathoswith 1377
        xor     edx, edx
6643 pathoswith 1378
        div     [ebp+EXTFS.dwordsPerBranch]
1379
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
1380
        sub     ecx, eax
1381
        lea     edi, [ebx+eax*4]
1382
@@:
1383
        call    freeDoublyIndirectBlock
1384
        test    eax, eax
1385
        jz      .end
1386
        dec     ecx
1387
        jnz     @b
1388
.end:
1389
        pop     edx eax
6462 pathoswith 1390
        test    edx, edx
6575 pathoswith 1391
        jnz     @f
1392
        xor     ecx, ecx
6756 pathoswith 1393
        inc     ecx
1394
        call    extfsExtentFree
6643 pathoswith 1395
        mov     [esi+INODE.tripleAddress], eax
1396
        jmp     .done
1397
 
6575 pathoswith 1398
@@:
6643 pathoswith 1399
        mov     ebx, [esp]
1400
        call    extfsWriteBlock
1401
        jmp     .done
6462 pathoswith 1402
 
6643 pathoswith 1403
.err:
1404
        pop     eax eax
6558 pathoswith 1405
.done:
6643 pathoswith 1406
        call    kernel_free
6462 pathoswith 1407
.ret:
1408
        ret
1409
 
1410
linkInode:
1411
;   in:
1412
; eax = inode on which to link
1413
; ebx = inode to link
6471 pathoswith 1414
; esi -> name in UTF-8
6462 pathoswith 1415
;  dl = file type
1416
        push    esi edi ebx ecx eax edx
1417
        call    strlen
1418
        push    esi ebx ecx
6558 pathoswith 1419
        lea     esi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1420
        mov     ebx, esi
1421
        call    readInode
1422
        jc      .error_inode_read
6643 pathoswith 1423
        mov     eax, [esi+INODE.fileSize]
6852 pathoswith 1424
        xor     edx, edx
1425
        div     [ebp+EXTFS.bytesPerBlock]
6462 pathoswith 1426
        xor     ecx, ecx
6558 pathoswith 1427
.searchBlock:
1428
        push    eax     ; blocks total
6462 pathoswith 1429
        push    ecx     ; current file block number
6558 pathoswith 1430
        cmp     eax, ecx
1431
        jz      .alloc_block
6726 pathoswith 1432
        call    extfsGetExtent
6462 pathoswith 1433
        jc      .error_get_inode_block
6726 pathoswith 1434
        push    eax
6462 pathoswith 1435
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1436
        call    extfsReadBlock
1437
        jc      .error_block_read
6558 pathoswith 1438
        mov     ecx, [esp+12]
6856 pathoswith 1439
        add     ecx, 8  ; directory entry size
6462 pathoswith 1440
        mov     edi, [ebp+EXTFS.tempBlockBuffer]
1441
        mov     edx, edi
1442
        add     edx, [ebp+EXTFS.bytesPerBlock]
1443
.searchSpace:
1444
        movzx   eax, [edi+DIRENTRY.entryLength]
1445
        test    eax, eax
1446
        jz      .zeroLength
1447
        cmp     [edi+DIRENTRY.inodeNumber], 0
1448
        je      .unusedEntry
1449
        movzx   ebx, [edi+DIRENTRY.nameLength]
1450
        add     ebx, 8+3
1451
        and     ebx, -4
1452
        sub     eax, ebx
1453
        add     edi, ebx
1454
        cmp     eax, ecx
1455
        jb      .nextEntry
1456
        sub     edi, ebx
1457
        mov     [edi+DIRENTRY.entryLength], bx
1458
        add     edi, ebx
1459
        mov     [edi+DIRENTRY.entryLength], ax
1460
        jmp     .found
1461
 
1462
.unusedEntry:
1463
        cmp     eax, ecx
1464
        jge     .found
1465
.nextEntry:
1466
        add     edi, eax
1467
        cmp     edi, edx
1468
        jb      .searchSpace
6856 pathoswith 1469
        pop     ecx
1470
@@:
1471
        pop     ecx eax
6558 pathoswith 1472
        inc     ecx
1473
        jmp     .searchBlock
6462 pathoswith 1474
 
1475
.zeroLength:
1476
        mov     eax, edx
1477
        sub     eax, edi
6856 pathoswith 1478
        mov     [edi+DIRENTRY.entryLength], ax
6462 pathoswith 1479
        cmp     eax, ecx
1480
        jge     .found
1481
        mov     [edi+DIRENTRY.inodeNumber], 0
1482
        pop     eax
1483
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1484
        call    extfsWriteBlock
6856 pathoswith 1485
        jmp     @b
1486
 
6726 pathoswith 1487
.alloc_block:
6849 pathoswith 1488
        mov     eax, [esi+INODE.fileSize]
1489
        add     eax, [ebp+EXTFS.bytesPerBlock]
1490
        xor     edx, edx
1491
        mov     ecx, [esp+24]
6726 pathoswith 1492
        call    extfsExtendFile
1493
        jc      .error_get_inode_block
1494
        mov     eax, [esp+24]
1495
        mov     ebx, esi
1496
        call    writeInode
1497
        jc      .error_get_inode_block
1498
        mov     ecx, [esp]
1499
        call    extfsGetExtent
6462 pathoswith 1500
        jc      .error_get_inode_block
6726 pathoswith 1501
        push    eax
6575 pathoswith 1502
        mov     edi, [ebp+EXTFS.tempBlockBuffer]
6462 pathoswith 1503
        mov     eax, [ebp+EXTFS.bytesPerBlock]
1504
        mov     [edi+DIRENTRY.entryLength], ax
1505
.found:
1506
        pop     edx ecx ecx ecx ebx esi
6575 pathoswith 1507
        mov     [edi+DIRENTRY.inodeNumber], ebx
1508
        mov     word [edi+DIRENTRY.nameLength], cx
6856 pathoswith 1509
        sub     eax, 8
1510
        cmp     ecx, eax
1511
        adc     ecx, 0
1512
        test    [ebp+EXTFS.superblock.incompatibleFlags], 2
1513
        jz      @f
1514
        mov     eax, [esp]
6462 pathoswith 1515
        mov     [edi+DIRENTRY.fileType], al
6856 pathoswith 1516
@@:
6462 pathoswith 1517
        add     edi, 8
1518
        rep movsb
1519
        mov     eax, edx
1520
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1521
        call    extfsWriteBlock
1522
@@:
1523
        pop     edx ecx ecx ebx edi esi
1524
        ret
1525
 
1526
.error_block_read:
1527
        pop     ebx
1528
.error_get_inode_block:
1529
        pop     ebx ebx
1530
.error_inode_read:
6933 pathoswith 1531
        pop     ebx ebx ebx
6462 pathoswith 1532
        jmp     @b
1533
 
1534
unlinkInode:
6853 pathoswith 1535
; in: eax = directory inode number, esi = inode to unlink
1536
        push    edi
6558 pathoswith 1537
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1538
        call    readInode
6853 pathoswith 1539
        jc      .ret
1540
        xor     ecx, ecx
6462 pathoswith 1541
.loop:
6853 pathoswith 1542
        push    ecx
6726 pathoswith 1543
        call    extfsGetExtent
6462 pathoswith 1544
        jc      .fail_loop
6726 pathoswith 1545
        mov     edi, eax
6462 pathoswith 1546
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1547
        call    extfsReadBlock
1548
        jc      .fail_loop
1549
.first_dir_entry:   ; edi -> block
6853 pathoswith 1550
        cmp     [ebx+DIRENTRY.inodeNumber], esi
6462 pathoswith 1551
        jne     @f
1552
        mov     [ebx+DIRENTRY.inodeNumber], 0
1553
        mov     word [ebx+DIRENTRY.nameLength], 0   ; fileType = 0
1554
        jmp     .write_block
1555
 
6853 pathoswith 1556
.fail:
1557
        pop     edi
1558
        movi    eax, ERROR_FS_FAIL
1559
        stc
1560
.fail_loop:
1561
        pop     edi
1562
        jmp     .ret
1563
 
1564
.next:
1565
        pop     ecx ecx
1566
        inc     ecx
1567
        jmp     .loop
1568
 
6462 pathoswith 1569
@@:
1570
        mov     edx, ebx
1571
        add     edx, [ebp+EXTFS.bytesPerBlock]
1572
        push    edx
6853 pathoswith 1573
@@:
1574
        movzx   ecx, [ebx+DIRENTRY.entryLength]
1575
        jecxz   .fail
6462 pathoswith 1576
        mov     edx, ebx
1577
        add     ebx, ecx
6853 pathoswith 1578
        cmp     ebx, [esp]
1579
        jnc     .next
1580
        cmp     [ebx+DIRENTRY.inodeNumber], esi
1581
        jnz     @b
6462 pathoswith 1582
        mov     cx, [ebx+DIRENTRY.entryLength]
1583
        add     [edx+DIRENTRY.entryLength], cx
1584
        pop     eax
1585
.write_block:
1586
        pop     eax
1587
        mov     eax, edi
1588
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1589
        call    extfsWriteBlock
6853 pathoswith 1590
.ret:
1591
        pop     edi
6462 pathoswith 1592
        ret
1593
 
6522 pathoswith 1594
findInode:
6471 pathoswith 1595
; in: esi -> path string in UTF-8
6462 pathoswith 1596
;   out:
6471 pathoswith 1597
; edi -> file name in UTF-8
6522 pathoswith 1598
; esi = last inode number
6558 pathoswith 1599
; [ebp+EXTFS.inodeBuffer] = last inode
6522 pathoswith 1600
; ecx = parent inode number
1601
; CF=1 -> file not found, edi=0 -> error
6462 pathoswith 1602
        push    esi
1603
        lea     esi, [ebp+EXTFS.rootInodeBuffer]
6558 pathoswith 1604
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1605
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
6522 pathoswith 1606
        mov     edx, esi
6462 pathoswith 1607
        rep movsb
6522 pathoswith 1608
        pop     esi
6849 pathoswith 1609
        pushd   ebx 0 ROOT_INODE
6558 pathoswith 1610
        mov     edi, esi
6756 pathoswith 1611
        cmp     [edx+INODE.fileSize], 0
6522 pathoswith 1612
        jz      .not_found
1613
        cmp     byte [esi], 0
1614
        jnz     .next_path_part
6462 pathoswith 1615
        xor     eax, eax
6849 pathoswith 1616
        pop     esi ecx ebx
6468 pathoswith 1617
        ret
6462 pathoswith 1618
 
6522 pathoswith 1619
@@:
1620
        pop     esi esi
1621
.error:
6849 pathoswith 1622
        pop     esi ecx ebx
6522 pathoswith 1623
        xor     edi, edi
1624
        stc
1625
        ret
1626
 
6462 pathoswith 1627
.next_path_part:
6756 pathoswith 1628
        push    [edx+INODE.fileSize]
6462 pathoswith 1629
        xor     ecx, ecx
1630
.folder_block_cycle:
1631
        push    ecx
6726 pathoswith 1632
        call    extfsGetExtent
6522 pathoswith 1633
        jc      @b
6462 pathoswith 1634
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1635
        call    extfsReadBlock
6522 pathoswith 1636
        jc      @b
6462 pathoswith 1637
        push    esi edx
1638
        mov     edx, ebx
1639
        add     edx, [ebp+EXTFS.bytesPerBlock]
1640
.start_rec:
1641
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1642
        jz      .next_rec
1643
        push    esi
1644
        movzx   ecx, [ebx+DIRENTRY.nameLength]
6471 pathoswith 1645
        lea     edi, [ebx+DIRENTRY.name]
1646
        repz cmpsb
1647
        jz      .test_find
6462 pathoswith 1648
@@: ; doesn't match
1649
        pop     esi
1650
.next_rec:
6856 pathoswith 1651
        movzx   ecx, [ebx+DIRENTRY.entryLength]
1652
        jecxz   .stop
1653
        add     ebx, ecx
6462 pathoswith 1654
        cmp     ebx, edx
1655
        jb      .start_rec
6856 pathoswith 1656
        jmp     .stop
6462 pathoswith 1657
 
1658
.test_find:
1659
        cmp     byte [esi], 0
1660
        je      @f
1661
        cmp     byte [esi], '/'
1662
        jne     @b
1663
        inc     esi
1664
@@:
6856 pathoswith 1665
        pop     edx
1666
.stop:
1667
        pop     edx edi ecx eax
6462 pathoswith 1668
; ebx -> matched directory entry, esi -> name without parent, or not changed
1669
        cmp     edi, esi
6522 pathoswith 1670
        jnz     @f
6756 pathoswith 1671
        sub     eax, [ebp+EXTFS.bytesPerBlock]
6462 pathoswith 1672
        jle     .not_found
1673
        push    eax
1674
        inc     ecx
1675
        jmp     .folder_block_cycle
1676
 
6522 pathoswith 1677
@@:
6462 pathoswith 1678
        pop     eax
6522 pathoswith 1679
        mov     [esp], eax
6462 pathoswith 1680
        mov     eax, [ebx+DIRENTRY.inodeNumber]
6558 pathoswith 1681
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6522 pathoswith 1682
        push    eax
6462 pathoswith 1683
        call    readInode
6522 pathoswith 1684
        jc      .error
1685
        cmp     byte [esi], 0
1686
        je      .ret
1687
        mov     edx, ebx
1688
        movzx   eax, [ebx+INODE.accessMode]
1689
        and     eax, TYPE_MASK
1690
        cmp     eax, DIRECTORY
1691
        jz      .next_path_part
6558 pathoswith 1692
        xor     edi, edi    ; path folder is a file
1693
        jmp     @f
1694
 
6462 pathoswith 1695
.not_found:
6558 pathoswith 1696
        mov     esi, edi
1697
        call    strlen
1698
        mov     al, '/'
1699
        repnz scasb
1700
        mov     edi, esi
1701
        jnz     @f
1702
        xor     edi, edi    ; path folder not found
1703
@@:
6462 pathoswith 1704
        movi    eax, ERROR_FILE_NOT_FOUND
1705
        stc
6522 pathoswith 1706
.ret:
6849 pathoswith 1707
        pop     esi ecx ebx
6468 pathoswith 1708
        ret
6462 pathoswith 1709
 
1710
writeSuperblock:
1711
        push    ebx
1712
        mov     eax, 2
1713
        lea     ebx, [ebp+EXTFS.superblock]
1714
        call    fs_write32_sys
1715
        pop     ebx
1716
        ret
1717
 
1718
extfsWritingInit:
1719
        movi    eax, ERROR_UNSUPPORTED_FS
1720
        test    [ebp+EXTFS.mountType], READ_ONLY
1721
        jnz     @f
1722
ext_lock:
1723
        lea     ecx, [ebp+EXTFS.Lock]
1724
        jmp     mutex_lock
1725
 
1726
@@:
1727
        pop     ebx
1728
        xor     ebx, ebx
1729
        ret
1730
 
1731
ext_unlock:
1732
        lea     ecx, [ebp+EXTFS.Lock]
1733
        jmp     mutex_unlock
1734
 
1735
;----------------------------------------------------------------
1736
ext_ReadFolder:
1737
        call    ext_lock
1738
        cmp     byte [esi], 0
1739
        jz      .root_folder
6468 pathoswith 1740
        call    findInode
6462 pathoswith 1741
        jc      .error_ret
6558 pathoswith 1742
        lea     esi, [ebp+EXTFS.inodeBuffer]
6522 pathoswith 1743
        test    [esi+INODE.accessMode], FLAG_FILE
1744
        jnz     .error_not_found
6462 pathoswith 1745
        jmp     @f
1746
 
1747
.root_folder:
1748
        lea     esi, [ebp+EXTFS.rootInodeBuffer]
6558 pathoswith 1749
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1750
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
1751
        shr     ecx, 2
1752
        push    edi
1753
        rep movsd
1754
        pop     esi
1755
@@:
1756
        cmp     [esi+INODE.fileSize], 0
1757
        je      .error_empty_dir
1758
        mov     edx, [ebx+16]
1759
        push    edx         ; [edi+28] result buffer
1760
        push    0           ; [edi+24] end of the current block in folder
1761
        pushd   [ebx+12]    ; [edi+20] files to read
1762
        pushd   [ebx+4]     ; [edi+16] first wanted file
1763
        pushd   [ebx+8]     ; [edi+12] flags
1764
        push    0           ; [edi+8]  read files
1765
        push    0           ; [edi+4]  files in folder
1766
        push    0           ; [edi]    current block index
1767
        mov     edi, esp    ; edi -> local variables
1768
        add     edx, 32
1769
        xor     ecx, ecx
6726 pathoswith 1770
        call    extfsGetExtent
6462 pathoswith 1771
        jc      .error_get_block
1772
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1773
        call    extfsReadBlock
1774
        jc      .error_get_block
1775
        mov     eax, ebx
1776
        add     eax, [ebp+EXTFS.bytesPerBlock]
1777
        mov     [edi+24], eax
1778
        mov     ecx, [edi+16]
1779
.find_wanted_start:
1780
        jecxz   .find_wanted_end
1781
.find_wanted_cycle:
1782
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1783
        jz      @f
1784
        inc     dword [edi+4]
1785
        dec     ecx
1786
@@:
1787
        movzx   eax, [ebx+DIRENTRY.entryLength]
1788
        cmp     eax, 12     ; minimum entry length
1789
        jb      .error_bad_len
1790
        test    eax, 3      ; length must be aligned
1791
        jnz     .error_bad_len
1792
        sub     [esi+INODE.fileSize], eax
1793
        add     ebx, eax
1794
        cmp     ebx, [edi+24]
1795
        jb      .find_wanted_start
1796
        push    .find_wanted_start
1797
.end_block: ; read next block
1798
        cmp     [esi+INODE.fileSize], 0
1799
        jle     .end_dir
1800
        inc     dword [edi]
1801
        push    ecx
1802
        mov     ecx, [edi]
6726 pathoswith 1803
        call    extfsGetExtent
6462 pathoswith 1804
        jc      .error_get_block
1805
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1806
        call    extfsReadBlock
1807
        jc      .error_get_block
1808
        pop     ecx
1809
        mov     eax, ebx
1810
        add     eax, [ebp+EXTFS.bytesPerBlock]
1811
        mov     [edi+24], eax
1812
        ret
1813
 
1814
.wanted_end:
1815
        loop    .find_wanted_cycle
1816
.find_wanted_end:
1817
        mov     ecx, [edi+20]
1818
.wanted_start:
1819
        jecxz   .wanted_end
1820
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1821
        jz      .empty_rec
1822
        inc     dword [edi+8]
1823
        inc     dword [edi+4]
6558 pathoswith 1824
        push    ebx edi ecx esi edx edi
6471 pathoswith 1825
        pushd   [edi+12]
6462 pathoswith 1826
        mov     edi, edx
1827
        xor     eax, eax
1828
        mov     ecx, 40 / 4
1829
        rep stosd
6558 pathoswith 1830
        popd    [edx+4] edi
6462 pathoswith 1831
        mov     eax, [ebx+DIRENTRY.inodeNumber]
6558 pathoswith 1832
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
6462 pathoswith 1833
        call    readInode
1834
        jc      .error_read_subinode
1835
        mov     esi, ebx
1836
        lea     edi, [edx+8]
1837
        mov     eax, [ebx+INODE.inodeModified]
1838
        sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
1839
        call    fsTime2bdfe
1840
 
1841
        mov     eax, [esi+INODE.accessedTime]
1842
        sub     eax, 978307200
1843
        call    fsTime2bdfe
1844
 
1845
        mov     eax, [esi+INODE.dataModified]
1846
        sub     eax, 978307200
1847
        call    fsTime2bdfe
1848
        pop     edx
1849
        or      dword [edx], KOS_DIRECTORY
6522 pathoswith 1850
        test    [esi+INODE.accessMode], FLAG_FILE
1851
        jz      @f
6462 pathoswith 1852
        xor     dword [edx], KOS_DIRECTORY  ; mark as file
1853
        mov     eax, [esi+INODE.fileSize]
1854
        stosd
1855
        mov     eax, [esi+INODE.fileSizeHigh]
1856
        stosd
1857
@@:
1858
        mov     esi, [esp+12]
1859
        movzx   ecx, [esi+DIRENTRY.nameLength]
6471 pathoswith 1860
        lea     esi, [esi+DIRENTRY.name]
1861
        cmp     byte [esi], '.'
1862
        jnz     @f
1863
        or      byte [edx], KOS_HIDDEN
1864
@@:
6462 pathoswith 1865
        lea     edi, [edx+40]
6798 pathoswith 1866
        cmp     byte [edx+4], 3
1867
        jz      .utf8
1868
        add     ecx, esi
1869
        cmp     byte [edx+4], 2
6471 pathoswith 1870
        jz      .utf16
1871
@@:
1872
        call    utf8to16
1873
        call    uni2ansi_char
1874
        stosb
1875
        cmp     esi, ecx
1876
        jc      @b
6462 pathoswith 1877
        and     byte [edi], 0
6471 pathoswith 1878
        add     edx, 40+264
1879
@@:
6462 pathoswith 1880
        pop     esi ecx edi ebx
1881
        dec     ecx
1882
.empty_rec:
1883
        movzx   eax, [ebx+DIRENTRY.entryLength]
1884
        cmp     eax, 12
1885
        jb      .error_bad_len
1886
        test    eax, 3
1887
        jnz     .error_bad_len
1888
        sub     [esi+INODE.fileSize], eax
1889
        add     ebx, eax
1890
        cmp     ebx, [edi+24]
1891
        jb      .wanted_start
1892
        push    .wanted_start
1893
        jmp     .end_block
1894
 
6798 pathoswith 1895
.utf8:
1896
        rep movsb
1897
        mov     byte [edi], 0
1898
        add     edx, 40+520
1899
        jmp     @b
1900
 
6471 pathoswith 1901
.utf16:
1902
        call    utf8to16
1903
        stosw
1904
        cmp     esi, ecx
1905
        jc      .utf16
1906
        and     word [edi], 0
1907
        add     edx, 40+520
1908
        jmp     @b
1909
 
6462 pathoswith 1910
.end_dir:
1911
        call    ext_unlock
1912
        mov     edx, [edi+28]
1913
        mov     ebx, [edi+8]
1914
        mov     ecx, [edi+4]
1915
        mov     dword [edx], 1  ; version
1916
        mov     [edx+4], ebx
1917
        mov     [edx+8], ecx
1918
        lea     esp, [edi+32]
1919
        mov     ecx, 20/4
1920
        lea     edi, [edx+12]
1921
        xor     eax, eax
1922
        rep stosd
1923
        ret
1924
 
1925
.error_bad_len:
1926
        movi    eax, ERROR_FS_FAIL
1927
.error_read_subinode:
1928
.error_get_block:
1929
        lea     esp, [edi+32]
1930
.error_ret:
6880 pathoswith 1931
        xor     ebx, ebx
6462 pathoswith 1932
        push    eax
1933
        call    ext_unlock
1934
        pop     eax
1935
        ret
1936
 
1937
.error_empty_dir:
1938
        movi    eax, ERROR_FS_FAIL
1939
        jmp     .error_ret
1940
 
1941
.error_not_found:
1942
        movi    eax, ERROR_FILE_NOT_FOUND
1943
        jmp     .error_ret
1944
 
1945
;----------------------------------------------------------------
1946
ext_ReadFile:
1947
        call    ext_lock
6468 pathoswith 1948
        call    findInode
6849 pathoswith 1949
        pushd   0 eax
6726 pathoswith 1950
        jc      .ret
6558 pathoswith 1951
        lea     esi, [ebp+EXTFS.inodeBuffer]
6726 pathoswith 1952
        mov     byte [esp], ERROR_ACCESS_DENIED
1953
        test    [esi+INODE.accessMode], FLAG_FILE
1954
        jz      .ret    ; not a file
1955
        mov     byte [esp], ERROR_END_OF_FILE
1956
        mov     eax, [esi+INODE.fileSize]
1957
        mov     edx, [esi+INODE.fileSizeHigh]
1958
        sub     eax, [ebx+4]
1959
        sbb     edx, [ebx+8]
1960
        jc      .ret
6462 pathoswith 1961
        mov     ecx, [ebx+12]
6726 pathoswith 1962
        sub     eax, ecx
1963
        sbb     edx, 0
1964
        jc      @f
1965
        xor     eax, eax
1966
        mov     [esp], eax
1967
@@:
1968
        add     ecx, eax
6462 pathoswith 1969
        mov     eax, [ebx+4]
1970
        mov     edx, [ebx+8]
6726 pathoswith 1971
        mov     edi, [ebx+16]
6462 pathoswith 1972
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 1973
        test    edx, edx
1974
        jz      .aligned
1975
.piece:
1976
        push    eax ecx
1977
        mov     esi, edx
6462 pathoswith 1978
        mov     ecx, eax
6726 pathoswith 1979
        call    extfsGetExtent
1980
        jc      .errorGet
1981
        mov     ecx, [ebp+EXTFS.sectorsPerBlock]
1982
        mul     ecx
6462 pathoswith 1983
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
6726 pathoswith 1984
        call    fs_read64_sys
1985
        test    eax, eax
1986
        jnz     .errorRead
1987
        pop     eax
1988
        mov     ecx, [ebp+EXTFS.bytesPerBlock]
1989
        sub     ecx, esi
1990
        sub     eax, ecx
1991
        jnc     @f
1992
        add     ecx, eax
1993
        xor     eax, eax
1994
@@:
1995
        add     esi, ebx
1996
        add     [esp+8], ecx
6462 pathoswith 1997
        rep movsb
6726 pathoswith 1998
        mov     ecx, eax
1999
        pop     eax
2000
        inc     eax
6462 pathoswith 2001
        xor     edx, edx
6726 pathoswith 2002
        jecxz   .ret
2003
.aligned:
2004
        xchg    eax, ecx
6462 pathoswith 2005
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2006
        push    edx
2007
        mov     edx, eax
2008
.writeExtent:
2009
        test    edx, edx
2010
        jz      .end
2011
        push    ecx
2012
        call    extfsGetExtent
2013
        jc      .errorGet
2014
        sub     edx, ecx
2015
        jnc     @f
2016
        add     ecx, edx
2017
        xor     edx, edx
6462 pathoswith 2018
@@:
6726 pathoswith 2019
        add     [esp], ecx
2020
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
2021
        mov     ebx, edi
2022
        push    edx ecx
2023
        mul     [ebp+EXTFS.sectorsPerBlock]
2024
        call    fs_read64_sys
2025
        pop     ecx edx
2026
        test    eax, eax
2027
        jnz     .errorRead
2028
        shl     ecx, 9
2029
        add     edi, ecx
2030
        add     [esp+12], ecx
2031
        pop     ecx
2032
        jmp     .writeExtent
6462 pathoswith 2033
 
6726 pathoswith 2034
.end:
6462 pathoswith 2035
        mov     eax, ecx
6726 pathoswith 2036
        pop     ecx
2037
        jecxz   .ret
2038
        jmp     .piece
6462 pathoswith 2039
 
6726 pathoswith 2040
.errorRead:
2041
        movi    eax, ERROR_DEVICE
2042
.errorGet:
6462 pathoswith 2043
        pop     ebx ebx
6726 pathoswith 2044
        mov     [esp], eax
2045
.ret:
6462 pathoswith 2046
        call    ext_unlock
6726 pathoswith 2047
        pop     eax ebx
6462 pathoswith 2048
        ret
2049
 
2050
;----------------------------------------------------------------
2051
ext_GetFileInfo:
6871 pathoswith 2052
        cmp     byte [esi], 0
2053
        jz      .volume
6462 pathoswith 2054
        call    ext_lock
6468 pathoswith 2055
        call    findInode
6871 pathoswith 2056
        jc      .ret
6558 pathoswith 2057
        lea     esi, [ebp+EXTFS.inodeBuffer]
6849 pathoswith 2058
        mov     edx, [ebx+16]
6522 pathoswith 2059
        mov     bl, [edi]
6462 pathoswith 2060
        xor     eax, eax
2061
        mov     edi, edx
2062
        mov     ecx, 40/4
2063
        rep stosd
2064
        cmp     bl, '.'
2065
        jne     @f
2066
        or      dword [edx], KOS_HIDDEN
2067
@@:
2068
        or      dword [edx], KOS_DIRECTORY
6522 pathoswith 2069
        test    [esi+INODE.accessMode], FLAG_FILE
2070
        jz      @f
6462 pathoswith 2071
        xor     dword [edx], KOS_DIRECTORY  ; mark as file
2072
        mov     eax, [esi+INODE.fileSize]
2073
        mov     ebx, [esi+INODE.fileSizeHigh]
2074
        mov     dword [edx+32], eax
2075
        mov     dword [edx+36], ebx
2076
@@:
2077
        lea     edi, [edx+8]
2078
        mov     eax, [esi+INODE.inodeModified]
2079
        sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2080
        call    fsTime2bdfe
2081
 
2082
        mov     eax, [esi+INODE.accessedTime]
2083
        sub     eax, 978307200
2084
        call    fsTime2bdfe
2085
 
2086
        mov     eax, [esi+INODE.dataModified]
2087
        sub     eax, 978307200
2088
        call    fsTime2bdfe
6871 pathoswith 2089
        xor     eax, eax
2090
.ret:
2091
        push    eax
6462 pathoswith 2092
        call    ext_unlock
6871 pathoswith 2093
        pop     eax
6876 pathoswith 2094
@@:
6871 pathoswith 2095
        ret
2096
 
2097
.volume:
2098
        mov     eax, dword[ebp+EXTFS.Length]
2099
        mov     edx, dword[ebp+EXTFS.Length+4]
2100
        mov     edi, [ebx+16]
2101
        shld    edx, eax, 9
2102
        shl     eax, 9
2103
        mov     [edi+36], edx
2104
        mov     [edi+32], eax
2105
        mov     eax, [ebx+8]
2106
        mov     byte [edi], 8
2107
        mov     [edi+4], eax
6876 pathoswith 2108
        test    eax, eax
2109
        jz      @b
6871 pathoswith 2110
        lea     esi, [ebp+EXTFS.superblock.volumeLabel]
2111
        mov     ecx, 16
2112
        add     edi, 40
2113
        cmp     eax, 3
2114
        jz      .utf8
2115
        add     ecx, esi
2116
        cmp     eax, 2
2117
        jz      .utf16
2118
@@:
2119
        call    utf8to16
2120
        call    uni2ansi_char
2121
        stosb
2122
        cmp     esi, ecx
2123
        jc      @b
2124
        jmp     @f
2125
 
2126
.utf8:
2127
        rep movsb
2128
        jmp     @f
2129
 
2130
.utf16:
2131
        call    utf8to16
2132
        stosw
2133
        cmp     esi, ecx
2134
        jc      .utf16
2135
@@:
6462 pathoswith 2136
        xor     eax, eax
6871 pathoswith 2137
        mov     [edi], ax
6462 pathoswith 2138
        ret
2139
 
2140
;----------------------------------------------------------------
2141
ext_SetFileInfo:
2142
        call    extfsWritingInit
6468 pathoswith 2143
        call    findInode
6462 pathoswith 2144
        jc      @f
6849 pathoswith 2145
        push    esi
2146
        mov     esi, [ebx+16]
2147
        add     esi, 16
6558 pathoswith 2148
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2149
        call    fsCalculateTime
2150
        add     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2151
        mov     [edi+INODE.accessedTime], eax
2152
 
2153
        add     esi, 8
2154
        call    fsCalculateTime
2155
        add     eax, 978307200
2156
        mov     [edi+INODE.dataModified], eax
2157
        mov     ebx, edi
2158
        pop     eax
2159
        call    writeInode
2160
@@:
2161
        push    eax
2162
        jc      @f
2163
        call    writeSuperblock
2164
        mov     esi, [ebp+PARTITION.Disk]
2165
        call    disk_sync
2166
@@:
2167
        call    ext_unlock
2168
        pop     eax
2169
        ret
2170
 
2171
;----------------------------------------------------------------
2172
ext_Delete:
2173
        call    extfsWritingInit
6468 pathoswith 2174
        call    findInode
6853 pathoswith 2175
        jc      .error
2176
        push    ecx
2177
        movzx   edi, [ebp+EXTFS.inodeBuffer.accessMode]
2178
        and     edi, TYPE_MASK
2179
        cmp     edi, DIRECTORY
6462 pathoswith 2180
        jne     .file
6726 pathoswith 2181
        xor     ecx, ecx
6462 pathoswith 2182
.checkDirectory:
6726 pathoswith 2183
        push    ecx
2184
        call    extfsGetExtent
2185
        jc      .empty
6462 pathoswith 2186
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
2187
        call    extfsReadBlock
6853 pathoswith 2188
        jc      .error8
6462 pathoswith 2189
        mov     edx, ebx
2190
        add     edx, [ebp+EXTFS.bytesPerBlock]
2191
.dir_entry:
6853 pathoswith 2192
        movzx   ecx, [ebx+DIRENTRY.nameLength]
2193
        mov     ax, word [ebx+DIRENTRY.name]
2194
        jecxz   @f
2195
        cmp     al, '.'
2196
        jnz     .not_empty
2197
        dec     ecx
2198
        jz      @f
2199
        cmp     al, ah
2200
        jnz     .not_empty
2201
        dec     ecx
2202
        jnz     .not_empty
6462 pathoswith 2203
@@:
6853 pathoswith 2204
        mov     cx, [ebx+DIRENTRY.entryLength]
2205
        jecxz   @f
6462 pathoswith 2206
        add     ebx, ecx
2207
        cmp     ebx, edx
2208
        jb      .dir_entry
6853 pathoswith 2209
@@:
6726 pathoswith 2210
        pop     ecx
2211
        inc     ecx
6462 pathoswith 2212
        jmp     .checkDirectory
2213
 
6756 pathoswith 2214
.not_empty:
2215
        pop     eax eax
2216
        push    ERROR_ACCESS_DENIED
2217
        jmp     .ret
2218
 
6853 pathoswith 2219
.error8:
2220
        pop     ebx
2221
.error4:
2222
        pop     ebx
2223
.error:
2224
        push    eax
2225
        jmp     .ret
2226
 
6462 pathoswith 2227
.empty:
6853 pathoswith 2228
        pop     ecx ecx
6726 pathoswith 2229
        cmp     eax, ERROR_END_OF_FILE
6853 pathoswith 2230
        jnz     .error
2231
        push    ecx
6462 pathoswith 2232
.file:
6522 pathoswith 2233
        mov     eax, ecx
6462 pathoswith 2234
        call    unlinkInode
6853 pathoswith 2235
        jc      .error4
2236
        pop     eax
2237
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2238
        cmp     edi, DIRECTORY
2239
        jnz     @f
2240
        dec     [ebx+INODE.linksCount]
2241
        call    writeInode
2242
@@:
2243
        mov     eax, esi
2244
        call    readInode
2245
        jc      .error
2246
        dec     [ebx+INODE.linksCount]
6462 pathoswith 2247
        jz      @f
6853 pathoswith 2248
        cmp     edi, DIRECTORY
2249
        jnz     .hardlinks
6462 pathoswith 2250
@@:
6853 pathoswith 2251
        push    esi edi
6849 pathoswith 2252
        xor     eax, eax
2253
        xor     edx, edx
6643 pathoswith 2254
        call    extfsTruncateFile   ; free file's data
6778 pathoswith 2255
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
2256
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2257
        xor     eax, eax
6849 pathoswith 2258
        push    edi
6462 pathoswith 2259
        rep stosb
2260
        call    fsGetTime
6853 pathoswith 2261
        pop     ebx edi esi
6462 pathoswith 2262
        add     eax, 978307200
6778 pathoswith 2263
        mov     [ebx+INODE.deletedTime], eax
6853 pathoswith 2264
        mov     eax, esi
6462 pathoswith 2265
        dec     eax
2266
        xor     edx, edx
2267
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6848 pathoswith 2268
        push    edx
2269
        mov     ebx, [ebp+EXTFS.descriptorTable]
2270
        shl     eax, 5
2271
        add     ebx, eax
6853 pathoswith 2272
        cmp     edi, DIRECTORY
6756 pathoswith 2273
        jnz     @f
2274
        dec     [ebx+BGDESCR.directoriesCount]
2275
@@:
2276
        inc     [ebx+BGDESCR.inodesFree]
6848 pathoswith 2277
        push    [ebx+BGDESCR.inodeBitmap]
2278
        call    extfsWriteDescriptor
6462 pathoswith 2279
        pop     eax
6756 pathoswith 2280
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
6848 pathoswith 2281
        mov     ecx, eax
6756 pathoswith 2282
        call    extfsReadBlock
6853 pathoswith 2283
        pop     edx
2284
        jc      .error
2285
        mov     eax, edx
6756 pathoswith 2286
        and     edx, 31
2287
        shr     eax, 5
2288
        shl     eax, 2
2289
        add     eax, ebx
2290
        btr     [eax], edx
2291
        mov     eax, ecx
2292
        call    extfsWriteBlock
2293
        inc     [ebp+EXTFS.superblock.inodesFree]
6853 pathoswith 2294
.hardlinks:
2295
        mov     eax, esi
2296
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2297
        call    writeInode
6462 pathoswith 2298
        push    eax
2299
        call    writeSuperblock
2300
        mov     esi, [ebp+PARTITION.Disk]
2301
        call    disk_sync
2302
.ret:
2303
        call    ext_unlock
2304
        xor     ebx, ebx
2305
        pop     eax
2306
        ret
2307
 
2308
;----------------------------------------------------------------
2309
ext_CreateFolder:
2310
        call    extfsWritingInit
6468 pathoswith 2311
        call    findInode
6462 pathoswith 2312
        jnc     .success    ; exist
6522 pathoswith 2313
        test    edi, edi
2314
        jz      .error
6462 pathoswith 2315
        mov     eax, esi
6643 pathoswith 2316
        call    extfsInodeAlloc
6462 pathoswith 2317
        jc      .error
2318
        push    ebx esi edi
6558 pathoswith 2319
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2320
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
6852 pathoswith 2321
        xor     eax, eax
6462 pathoswith 2322
        rep stosb
2323
        call    fsGetTime
2324
        add     eax, 978307200
6852 pathoswith 2325
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2326
        mov     [ebx+INODE.accessedTime], eax
2327
        mov     [ebx+INODE.dataModified], eax
6462 pathoswith 2328
        pop     edi esi edx
2329
; edx = allocated inode number, edi -> filename, esi = parent inode number
6861 pathoswith 2330
        mov     [ebx+INODE.accessMode], DIRECTORY or 511
6933 pathoswith 2331
        mov     byte [ebx+INODE.linksCount], 2
6462 pathoswith 2332
        mov     eax, edx
2333
        call    writeInode
2334
        jc      .error
2335
; link to self
2336
        push    edx esi
2337
        mov     eax, edx
2338
        mov     ebx, eax
2339
        mov     dl, DIR_DIRECTORY
2340
        mov     esi, self_link
2341
        call    linkInode
2342
        pop     esi edx
2343
        jc      .error
2344
; link to parent
2345
        push    edx esi
2346
        mov     eax, ebx
2347
        mov     ebx, esi
2348
        mov     dl, DIR_DIRECTORY
2349
        mov     esi, parent_link
2350
        call    linkInode
2351
        pop     esi edx
2352
        jc      .error
2353
; link parent to child
6933 pathoswith 2354
        push    esi
6462 pathoswith 2355
        mov     eax, esi
2356
        mov     ebx, edx
2357
        mov     esi, edi
2358
        mov     dl, DIR_DIRECTORY
2359
        call    linkInode
6933 pathoswith 2360
        pop     edx
6462 pathoswith 2361
        jc      .error
6933 pathoswith 2362
        push    ebx
2363
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2364
        inc     [ebx+INODE.linksCount]
2365
        mov     eax, edx
2366
        call    writeInode
2367
        pop     ebx
2368
        jc      .error
6462 pathoswith 2369
        mov     eax, ebx
2370
        dec     eax
2371
        xor     edx, edx
2372
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6848 pathoswith 2373
        mov     ebx, [ebp+EXTFS.descriptorTable]
2374
        shl     eax, 5
2375
        add     ebx, eax
6756 pathoswith 2376
        inc     [ebx+BGDESCR.directoriesCount]
6462 pathoswith 2377
        call    extfsWriteDescriptor
2378
.success:
2379
.error:
2380
        push    eax
2381
        call    writeSuperblock
2382
        mov     esi, [ebp+PARTITION.Disk]
2383
        call    disk_sync
2384
        call    ext_unlock
2385
        pop     eax
2386
        ret
2387
 
2388
self_link   db ".", 0
2389
parent_link db "..", 0
2390
 
2391
;----------------------------------------------------------------
2392
ext_CreateFile:
2393
        call    extfsWritingInit
6726 pathoswith 2394
        pushd   0 0 ebx
6468 pathoswith 2395
        call    findInode
6522 pathoswith 2396
        jnc     .exist
2397
        test    edi, edi
2398
        jz      .error
6462 pathoswith 2399
        mov     eax, esi
6643 pathoswith 2400
        call    extfsInodeAlloc
6462 pathoswith 2401
        jc      .error
6522 pathoswith 2402
        push    ebx ebx esi edi
6558 pathoswith 2403
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2404
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
6852 pathoswith 2405
        xor     eax, eax
6462 pathoswith 2406
        rep stosb
2407
        call    fsGetTime
2408
        add     eax, 978307200
6852 pathoswith 2409
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2410
        mov     [ebx+INODE.accessedTime], eax
2411
        mov     [ebx+INODE.dataModified], eax
6462 pathoswith 2412
        pop     edi esi edx
2413
; edx = allocated inode number, edi -> filename, esi = parent inode number
6861 pathoswith 2414
        mov     [ebx+INODE.accessMode], FLAG_FILE or 110110110b
6933 pathoswith 2415
        mov     byte [ebx+INODE.linksCount], 1
6462 pathoswith 2416
        mov     eax, edx
2417
        call    writeInode
6522 pathoswith 2418
        jc      .error2
6462 pathoswith 2419
; link parent to child
2420
        mov     eax, esi
2421
        mov     ebx, edx
2422
        mov     esi, edi
2423
        mov     dl, DIR_FLAG_FILE
2424
        call    linkInode
6522 pathoswith 2425
        jc      .error2
6933 pathoswith 2426
        mov     eax, ebx
2427
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2428
        call    readInode
2429
        jc      .error2
6462 pathoswith 2430
        pop     esi ebx
6849 pathoswith 2431
        mov     eax, [ebx+12]
2432
        xor     edx, edx
6522 pathoswith 2433
        jmp     ext_WriteFile.start
6462 pathoswith 2434
 
6522 pathoswith 2435
.exist:
2436
        movi    eax, ERROR_ACCESS_DENIED
6726 pathoswith 2437
        test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
6522 pathoswith 2438
        jz      .error  ; not a file
2439
        pop     ebx
6849 pathoswith 2440
        mov     eax, [ebx+12]
2441
        xor     edx, edx
2442
        push    eax edx ebx esi
6522 pathoswith 2443
        call    extfsTruncateFile
6849 pathoswith 2444
        pop     esi ebx edx eax
6643 pathoswith 2445
        jmp     ext_WriteFile.start
2446
 
6522 pathoswith 2447
.error2:
2448
        pop     ebx
6462 pathoswith 2449
.error:
2450
        push    eax
2451
        call    ext_unlock
6726 pathoswith 2452
        pop     eax ebx ebx ebx
6462 pathoswith 2453
        ret
2454
 
2455
;----------------------------------------------------------------
2456
ext_WriteFile:
2457
        call    extfsWritingInit
6468 pathoswith 2458
        call    findInode
6726 pathoswith 2459
        pushd   0 eax
2460
        jc      .ret
2461
        mov     byte [esp], ERROR_ACCESS_DENIED
2462
        test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
2463
        jz      .ret    ; not a file
6849 pathoswith 2464
        mov     byte [esp], 0
2465
        mov     eax, [ebx+4]
2466
        mov     edx, [ebx+8]
2467
        add     eax, [ebx+12]
2468
        adc     edx, 0
6522 pathoswith 2469
.start:
6726 pathoswith 2470
        push    esi
6849 pathoswith 2471
        mov     ecx, esi
6462 pathoswith 2472
        call    extfsExtendFile
6726 pathoswith 2473
        jc      .errorExtend
2474
        mov     eax, [ebx+4]
6849 pathoswith 2475
        mov     edx, [ebx+8]
6643 pathoswith 2476
        mov     ecx, [ebx+12]
6726 pathoswith 2477
        mov     esi, [ebx+16]
2478
.write:
6861 pathoswith 2479
        jecxz   .zero
6462 pathoswith 2480
        div     [ebp+EXTFS.bytesPerBlock]
2481
        test    edx, edx
6726 pathoswith 2482
        jz      .aligned
2483
.piece:
2484
        mov     ebx, ecx
2485
        mov     edi, edx
2486
        mov     ecx, eax
2487
        push    eax
2488
        call    extfsGetExtent
2489
        jc      .errorGet
2490
        mov     ecx, [ebp+EXTFS.sectorsPerBlock]
2491
        mul     ecx
2492
        push    ecx eax ebx
2493
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
2494
        call    fs_read64_sys
2495
        test    eax, eax
2496
        jnz     .errorDevice
2497
        pop     eax
2498
        mov     ecx, [ebp+EXTFS.bytesPerBlock]
2499
        sub     ecx, edi
2500
        sub     eax, ecx
2501
        jnc     @f
2502
        add     ecx, eax
2503
        xor     eax, eax
6462 pathoswith 2504
@@:
6726 pathoswith 2505
        add     edi, ebx
2506
        add     [esp+20], ecx
2507
        rep movsb
6575 pathoswith 2508
        mov     edi, eax
6726 pathoswith 2509
        pop     eax ecx
6462 pathoswith 2510
        xor     edx, edx
6726 pathoswith 2511
        call    fs_write64_sys
2512
        mov     ecx, edi
2513
        pop     eax
2514
        inc     eax
6462 pathoswith 2515
        xor     edx, edx
6861 pathoswith 2516
.zero:
6726 pathoswith 2517
        jecxz   .done
2518
.aligned:
2519
        xchg    eax, ecx
6462 pathoswith 2520
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2521
        push    edx
2522
        mov     edx, eax
2523
.writeExtent:
2524
        test    edx, edx
2525
        jz      .end
6462 pathoswith 2526
        push    ecx
6726 pathoswith 2527
        call    extfsGetExtent
2528
        jc      .errorGet2
2529
        sub     edx, ecx
2530
        jnc     @f
2531
        add     ecx, edx
2532
        xor     edx, edx
2533
@@:
2534
        add     [esp], ecx
2535
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
2536
        mov     ebx, esi
2537
        push    edx ecx
2538
        mul     [ebp+EXTFS.sectorsPerBlock]
2539
        call    fs_write64_sys
2540
        test    eax, eax
2541
        jnz     .errorDevice
2542
        pop     ebx edx ecx
2543
        shl     ebx, 9
2544
        add     esi, ebx
2545
        add     [esp+12], ebx
2546
        jmp     .writeExtent
2547
 
2548
.end:
2549
        mov     eax, ecx
6462 pathoswith 2550
        pop     ecx
6726 pathoswith 2551
        jecxz   .done
2552
        jmp     .piece
2553
 
2554
.errorDevice:
2555
        pop     eax eax
2556
        movi    eax, ERROR_DEVICE
2557
.errorGet2:
2558
        pop     ebx
2559
.errorGet:
2560
        pop     ebx
2561
.errorExtend:
2562
        mov     [esp+4], eax
2563
.done:
6558 pathoswith 2564
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6726 pathoswith 2565
        pop     eax
6462 pathoswith 2566
        call    writeInode
6726 pathoswith 2567
        add     [esp], eax
6462 pathoswith 2568
        call    writeSuperblock
2569
        mov     esi, [ebp+PARTITION.Disk]
2570
        call    disk_sync
6726 pathoswith 2571
.ret:
6462 pathoswith 2572
        call    ext_unlock
6726 pathoswith 2573
        pop     eax ebx
6462 pathoswith 2574
        ret
2575
 
6726 pathoswith 2576
.erase:
6849 pathoswith 2577
        push    eax eax edi
6726 pathoswith 2578
        mov     eax, ebx
2579
        jmp     .write
6462 pathoswith 2580
 
2581
;----------------------------------------------------------------
2582
ext_SetFileEnd:
2583
        call    extfsWritingInit
6468 pathoswith 2584
        call    findInode
6643 pathoswith 2585
        jc      .error2
6575 pathoswith 2586
        lea     edi, [ebp+EXTFS.inodeBuffer]
2587
        movi    eax, ERROR_ACCESS_DENIED
6726 pathoswith 2588
        test    [edi+INODE.accessMode], FLAG_FILE
2589
        jz      .error2 ; not a file
6849 pathoswith 2590
        mov     eax, [ebx+4]
2591
        mov     edx, [ebx+8]
6575 pathoswith 2592
        mov     ebx, [edi+INODE.fileSize]
6849 pathoswith 2593
        mov     ecx, [edi+INODE.fileSizeHigh]
2594
        push    esi ecx
2595
        cmp     ebx, eax
2596
        sbb     ecx, edx
2597
        mov     ecx, esi
6726 pathoswith 2598
        jnc     @f
6575 pathoswith 2599
        call    extfsExtendFile
6849 pathoswith 2600
        pop     esi
6575 pathoswith 2601
        jc      .error
6849 pathoswith 2602
        mov     eax, [edi+INODE.fileSize]
2603
        mov     edx, [edi+INODE.fileSizeHigh]
2604
        sub     eax, ebx
2605
        sbb     edx, esi
2606
        jnz     .done
2607
        cmp     eax, 1000001h
6726 pathoswith 2608
        jnc     .done
6849 pathoswith 2609
        push    eax
2610
        stdcall kernel_alloc, eax
6726 pathoswith 2611
        pop     ecx
2612
        test    eax, eax
2613
        jz      .error
2614
        push    ecx
2615
        add     ecx, 3
2616
        shr     ecx, 2
6849 pathoswith 2617
        mov     edx, esi
6726 pathoswith 2618
        mov     esi, eax
6575 pathoswith 2619
        mov     edi, eax
2620
        xor     eax, eax
6726 pathoswith 2621
        rep stosd
6849 pathoswith 2622
        pop     ecx edi
6726 pathoswith 2623
        push    esi
2624
        call    ext_WriteFile.erase
2625
        call    kernel_free
6575 pathoswith 2626
        xor     eax, eax
6726 pathoswith 2627
        ret
2628
 
6575 pathoswith 2629
@@:
6726 pathoswith 2630
        call    extfsTruncateFile
6849 pathoswith 2631
        pop     eax
6575 pathoswith 2632
.done:
6643 pathoswith 2633
        xor     eax, eax
2634
.error:
2635
        xchg    eax, [esp]
6558 pathoswith 2636
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2637
        call    writeInode
6726 pathoswith 2638
        add     [esp], eax
6462 pathoswith 2639
        call    writeSuperblock
2640
        mov     esi, [ebp+PARTITION.Disk]
2641
        call    disk_sync
6726 pathoswith 2642
        pop     eax
6643 pathoswith 2643
.error2:
6726 pathoswith 2644
        push    eax
6462 pathoswith 2645
        call    ext_unlock
2646
        pop     eax
2647
        ret
6933 pathoswith 2648
 
2649
;----------------------------------------------------------------
2650
ext_Rename:
2651
        call    extfsWritingInit
2652
        push    esi
2653
        mov     esi, edi
2654
        call    findInode
2655
        jnc     .error
2656
        test    edi, edi
2657
        jz      .error
2658
        xchg    [esp], esi
2659
        push    edi
2660
        call    findInode
2661
        pop     edi
2662
        jc      .error
2663
        xor     edx, edx
2664
        inc     edx
2665
        test    [ebp+EXTFS.inodeBuffer.accessMode], DIRECTORY
2666
        jz      @f
2667
        inc     edx
2668
@@:
2669
        mov     eax, ecx
2670
        push    ecx edx
2671
        call    unlinkInode
2672
        pop     edx ecx
2673
        jc      .error
2674
        cmp     edx, 1
2675
        jz      @f
2676
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2677
        dec     [ebx+INODE.linksCount]
2678
        mov     eax, ecx
2679
        call    writeInode
2680
        jc      .error
2681
@@:
2682
        mov     ebx, esi
2683
        mov     esi, edi
2684
        pop     eax
2685
        push    eax edx
2686
        call    linkInode
2687
        pop     edx
2688
        jc      .error
2689
        pop     eax
2690
        cmp     edx, 1
2691
        jz      @f
2692
        lea     ebx, [ebp+EXTFS.inodeBuffer]
2693
        inc     [ebx+INODE.linksCount]
2694
        call    writeInode
2695
@@:
2696
        call    writeSuperblock
2697
        mov     esi, [ebp+PARTITION.Disk]
2698
        call    disk_sync
2699
        call    ext_unlock
2700
        xor     eax, eax
2701
        ret
2702
 
2703
.error:
2704
        push    eax
2705
        call    ext_unlock
2706
        pop     eax ebx
2707
        ret