Subversion Repositories Kolibri OS

Rev

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