Subversion Repositories Kolibri OS

Rev

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

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