Subversion Repositories Kolibri OS

Rev

Rev 6778 | Rev 6809 | 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: 6798 $
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
6756 pathoswith 812
        mov     eax, edx
6462 pathoswith 813
        mul     [ebp+EXTFS.superblock.inodeSize]
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_ACCESS_DENIED
1757
        cmp     byte [esi], 0
1758
        jz      @f
1759
        movi    eax, ERROR_UNSUPPORTED_FS
1760
        test    [ebp+EXTFS.mountType], READ_ONLY
1761
        jnz     @f
1762
ext_lock:
1763
        lea     ecx, [ebp+EXTFS.Lock]
1764
        jmp     mutex_lock
1765
 
1766
@@:
1767
        pop     ebx
1768
        xor     ebx, ebx
1769
        ret
1770
 
1771
ext_unlock:
1772
        lea     ecx, [ebp+EXTFS.Lock]
1773
        jmp     mutex_unlock
1774
 
1775
;----------------------------------------------------------------
1776
ext_ReadFolder:
1777
        call    ext_lock
1778
        cmp     byte [esi], 0
1779
        jz      .root_folder
1780
        push    ebx
6468 pathoswith 1781
        call    findInode
6462 pathoswith 1782
        pop     ebx
1783
        jc      .error_ret
6558 pathoswith 1784
        lea     esi, [ebp+EXTFS.inodeBuffer]
6522 pathoswith 1785
        test    [esi+INODE.accessMode], FLAG_FILE
1786
        jnz     .error_not_found
6462 pathoswith 1787
        jmp     @f
1788
 
1789
.root_folder:
1790
        lea     esi, [ebp+EXTFS.rootInodeBuffer]
6558 pathoswith 1791
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1792
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
1793
        shr     ecx, 2
1794
        push    edi
1795
        rep movsd
1796
        pop     esi
1797
@@:
1798
        cmp     [esi+INODE.fileSize], 0
1799
        je      .error_empty_dir
1800
        mov     edx, [ebx+16]
1801
        push    edx         ; [edi+28] result buffer
1802
        push    0           ; [edi+24] end of the current block in folder
1803
        pushd   [ebx+12]    ; [edi+20] files to read
1804
        pushd   [ebx+4]     ; [edi+16] first wanted file
1805
        pushd   [ebx+8]     ; [edi+12] flags
1806
        push    0           ; [edi+8]  read files
1807
        push    0           ; [edi+4]  files in folder
1808
        push    0           ; [edi]    current block index
1809
        mov     edi, esp    ; edi -> local variables
1810
        add     edx, 32
1811
        xor     ecx, ecx
6726 pathoswith 1812
        call    extfsGetExtent
6462 pathoswith 1813
        jc      .error_get_block
1814
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1815
        call    extfsReadBlock
1816
        jc      .error_get_block
1817
        mov     eax, ebx
1818
        add     eax, [ebp+EXTFS.bytesPerBlock]
1819
        mov     [edi+24], eax
1820
        mov     ecx, [edi+16]
1821
.find_wanted_start:
1822
        jecxz   .find_wanted_end
1823
.find_wanted_cycle:
1824
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1825
        jz      @f
1826
        inc     dword [edi+4]
1827
        dec     ecx
1828
@@:
1829
        movzx   eax, [ebx+DIRENTRY.entryLength]
1830
        cmp     eax, 12     ; minimum entry length
1831
        jb      .error_bad_len
1832
        test    eax, 3      ; length must be aligned
1833
        jnz     .error_bad_len
1834
        sub     [esi+INODE.fileSize], eax
1835
        add     ebx, eax
1836
        cmp     ebx, [edi+24]
1837
        jb      .find_wanted_start
1838
        push    .find_wanted_start
1839
.end_block: ; read next block
1840
        cmp     [esi+INODE.fileSize], 0
1841
        jle     .end_dir
1842
        inc     dword [edi]
1843
        push    ecx
1844
        mov     ecx, [edi]
6726 pathoswith 1845
        call    extfsGetExtent
6462 pathoswith 1846
        jc      .error_get_block
1847
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1848
        call    extfsReadBlock
1849
        jc      .error_get_block
1850
        pop     ecx
1851
        mov     eax, ebx
1852
        add     eax, [ebp+EXTFS.bytesPerBlock]
1853
        mov     [edi+24], eax
1854
        ret
1855
 
1856
.wanted_end:
1857
        loop    .find_wanted_cycle
1858
.find_wanted_end:
1859
        mov     ecx, [edi+20]
1860
.wanted_start:
1861
        jecxz   .wanted_end
1862
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1863
        jz      .empty_rec
1864
        inc     dword [edi+8]
1865
        inc     dword [edi+4]
6558 pathoswith 1866
        push    ebx edi ecx esi edx edi
6471 pathoswith 1867
        pushd   [edi+12]
6462 pathoswith 1868
        mov     edi, edx
1869
        xor     eax, eax
1870
        mov     ecx, 40 / 4
1871
        rep stosd
6558 pathoswith 1872
        popd    [edx+4] edi
6462 pathoswith 1873
        mov     eax, [ebx+DIRENTRY.inodeNumber]
6558 pathoswith 1874
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
6462 pathoswith 1875
        call    readInode
1876
        jc      .error_read_subinode
1877
        mov     esi, ebx
1878
        lea     edi, [edx+8]
1879
        mov     eax, [ebx+INODE.inodeModified]
1880
        sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
1881
        call    fsTime2bdfe
1882
 
1883
        mov     eax, [esi+INODE.accessedTime]
1884
        sub     eax, 978307200
1885
        call    fsTime2bdfe
1886
 
1887
        mov     eax, [esi+INODE.dataModified]
1888
        sub     eax, 978307200
1889
        call    fsTime2bdfe
1890
        pop     edx
1891
        or      dword [edx], KOS_DIRECTORY
6522 pathoswith 1892
        test    [esi+INODE.accessMode], FLAG_FILE
1893
        jz      @f
6462 pathoswith 1894
        xor     dword [edx], KOS_DIRECTORY  ; mark as file
1895
        mov     eax, [esi+INODE.fileSize]
1896
        stosd
1897
        mov     eax, [esi+INODE.fileSizeHigh]
1898
        stosd
1899
@@:
1900
        mov     esi, [esp+12]
1901
        movzx   ecx, [esi+DIRENTRY.nameLength]
6471 pathoswith 1902
        lea     esi, [esi+DIRENTRY.name]
1903
        cmp     byte [esi], '.'
1904
        jnz     @f
1905
        or      byte [edx], KOS_HIDDEN
1906
@@:
6462 pathoswith 1907
        lea     edi, [edx+40]
6798 pathoswith 1908
        cmp     byte [edx+4], 3
1909
        jz      .utf8
1910
        add     ecx, esi
1911
        cmp     byte [edx+4], 2
6471 pathoswith 1912
        jz      .utf16
1913
@@:
1914
        call    utf8to16
1915
        call    uni2ansi_char
1916
        stosb
1917
        cmp     esi, ecx
1918
        jc      @b
6462 pathoswith 1919
        and     byte [edi], 0
6471 pathoswith 1920
        add     edx, 40+264
1921
@@:
6462 pathoswith 1922
        pop     esi ecx edi ebx
1923
        dec     ecx
1924
.empty_rec:
1925
        movzx   eax, [ebx+DIRENTRY.entryLength]
1926
        cmp     eax, 12
1927
        jb      .error_bad_len
1928
        test    eax, 3
1929
        jnz     .error_bad_len
1930
        sub     [esi+INODE.fileSize], eax
1931
        add     ebx, eax
1932
        cmp     ebx, [edi+24]
1933
        jb      .wanted_start
1934
        push    .wanted_start
1935
        jmp     .end_block
1936
 
6798 pathoswith 1937
.utf8:
1938
        rep movsb
1939
        mov     byte [edi], 0
1940
        add     edx, 40+520
1941
        jmp     @b
1942
 
6471 pathoswith 1943
.utf16:
1944
        call    utf8to16
1945
        stosw
1946
        cmp     esi, ecx
1947
        jc      .utf16
1948
        and     word [edi], 0
1949
        add     edx, 40+520
1950
        jmp     @b
1951
 
6462 pathoswith 1952
.end_dir:
1953
        call    ext_unlock
1954
        mov     edx, [edi+28]
1955
        mov     ebx, [edi+8]
1956
        mov     ecx, [edi+4]
1957
        mov     dword [edx], 1  ; version
1958
        mov     [edx+4], ebx
1959
        mov     [edx+8], ecx
1960
        lea     esp, [edi+32]
1961
        mov     ecx, 20/4
1962
        lea     edi, [edx+12]
1963
        xor     eax, eax
1964
        rep stosd
1965
        ret
1966
 
1967
.error_bad_len:
1968
        movi    eax, ERROR_FS_FAIL
1969
.error_read_subinode:
1970
.error_get_block:
1971
        lea     esp, [edi+32]
1972
.error_ret:
1973
        or      ebx, -1
1974
        push    eax
1975
        call    ext_unlock
1976
        pop     eax
1977
        ret
1978
 
1979
.error_empty_dir:
1980
        movi    eax, ERROR_FS_FAIL
1981
        jmp     .error_ret
1982
 
1983
.error_not_found:
1984
        movi    eax, ERROR_FILE_NOT_FOUND
1985
        jmp     .error_ret
1986
 
1987
;----------------------------------------------------------------
1988
ext_ReadFile:
1989
        call    ext_lock
6726 pathoswith 1990
        pushd   0 ERROR_ACCESS_DENIED
6462 pathoswith 1991
        cmp     byte [esi], 0
6726 pathoswith 1992
        jz      .ret  ; root
6462 pathoswith 1993
        mov     [esp], ebx
6468 pathoswith 1994
        call    findInode
6462 pathoswith 1995
        pop     ebx
6726 pathoswith 1996
        push    eax
1997
        jc      .ret
6558 pathoswith 1998
        lea     esi, [ebp+EXTFS.inodeBuffer]
6726 pathoswith 1999
        mov     byte [esp], ERROR_ACCESS_DENIED
2000
        test    [esi+INODE.accessMode], FLAG_FILE
2001
        jz      .ret    ; not a file
2002
        mov     byte [esp], ERROR_END_OF_FILE
2003
        mov     eax, [esi+INODE.fileSize]
2004
        mov     edx, [esi+INODE.fileSizeHigh]
2005
        sub     eax, [ebx+4]
2006
        sbb     edx, [ebx+8]
2007
        jc      .ret
6462 pathoswith 2008
        mov     ecx, [ebx+12]
6726 pathoswith 2009
        sub     eax, ecx
2010
        sbb     edx, 0
2011
        jc      @f
2012
        xor     eax, eax
2013
        mov     [esp], eax
2014
@@:
2015
        add     ecx, eax
6462 pathoswith 2016
        mov     eax, [ebx+4]
2017
        mov     edx, [ebx+8]
6726 pathoswith 2018
        mov     edi, [ebx+16]
6462 pathoswith 2019
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2020
        test    edx, edx
2021
        jz      .aligned
2022
.piece:
2023
        push    eax ecx
2024
        mov     esi, edx
6462 pathoswith 2025
        mov     ecx, eax
6726 pathoswith 2026
        call    extfsGetExtent
2027
        jc      .errorGet
2028
        mov     ecx, [ebp+EXTFS.sectorsPerBlock]
2029
        mul     ecx
6462 pathoswith 2030
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
6726 pathoswith 2031
        call    fs_read64_sys
2032
        test    eax, eax
2033
        jnz     .errorRead
2034
        pop     eax
2035
        mov     ecx, [ebp+EXTFS.bytesPerBlock]
2036
        sub     ecx, esi
2037
        sub     eax, ecx
2038
        jnc     @f
2039
        add     ecx, eax
2040
        xor     eax, eax
2041
@@:
2042
        add     esi, ebx
2043
        add     [esp+8], ecx
6462 pathoswith 2044
        rep movsb
6726 pathoswith 2045
        mov     ecx, eax
2046
        pop     eax
2047
        inc     eax
6462 pathoswith 2048
        xor     edx, edx
6726 pathoswith 2049
        jecxz   .ret
2050
.aligned:
2051
        xchg    eax, ecx
6462 pathoswith 2052
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2053
        push    edx
2054
        mov     edx, eax
2055
.writeExtent:
2056
        test    edx, edx
2057
        jz      .end
2058
        push    ecx
2059
        call    extfsGetExtent
2060
        jc      .errorGet
2061
        sub     edx, ecx
2062
        jnc     @f
2063
        add     ecx, edx
2064
        xor     edx, edx
6462 pathoswith 2065
@@:
6726 pathoswith 2066
        add     [esp], ecx
2067
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
2068
        mov     ebx, edi
2069
        push    edx ecx
2070
        mul     [ebp+EXTFS.sectorsPerBlock]
2071
        call    fs_read64_sys
2072
        pop     ecx edx
2073
        test    eax, eax
2074
        jnz     .errorRead
2075
        shl     ecx, 9
2076
        add     edi, ecx
2077
        add     [esp+12], ecx
2078
        pop     ecx
2079
        jmp     .writeExtent
6462 pathoswith 2080
 
6726 pathoswith 2081
.end:
6462 pathoswith 2082
        mov     eax, ecx
6726 pathoswith 2083
        pop     ecx
2084
        jecxz   .ret
2085
        jmp     .piece
6462 pathoswith 2086
 
6726 pathoswith 2087
.errorRead:
2088
        movi    eax, ERROR_DEVICE
2089
.errorGet:
6462 pathoswith 2090
        pop     ebx ebx
6726 pathoswith 2091
        mov     [esp], eax
2092
.ret:
6462 pathoswith 2093
        call    ext_unlock
6726 pathoswith 2094
        pop     eax ebx
6462 pathoswith 2095
        ret
2096
 
2097
;----------------------------------------------------------------
2098
ext_GetFileInfo:
2099
        call    ext_lock
2100
        mov     edx, [ebx+16]
2101
        cmp     byte [esi], 0
2102
        jz      .is_root
2103
        push    edx
6468 pathoswith 2104
        call    findInode
6462 pathoswith 2105
        pop     edx
6558 pathoswith 2106
        lea     esi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2107
        jnc     @f
2108
        push    eax
2109
        call    ext_unlock
2110
        pop     eax
2111
        ret
2112
 
2113
.is_root:
6522 pathoswith 2114
        mov     edi, esi
6462 pathoswith 2115
        lea     esi, [ebp+EXTFS.rootInodeBuffer]
2116
@@:
6522 pathoswith 2117
        mov     bl, [edi]
6462 pathoswith 2118
        xor     eax, eax
2119
        mov     edi, edx
2120
        mov     ecx, 40/4
2121
        rep stosd
2122
        cmp     bl, '.'
2123
        jne     @f
2124
        or      dword [edx], KOS_HIDDEN
2125
@@:
2126
        or      dword [edx], KOS_DIRECTORY
6522 pathoswith 2127
        test    [esi+INODE.accessMode], FLAG_FILE
2128
        jz      @f
6462 pathoswith 2129
        xor     dword [edx], KOS_DIRECTORY  ; mark as file
2130
        mov     eax, [esi+INODE.fileSize]
2131
        mov     ebx, [esi+INODE.fileSizeHigh]
2132
        mov     dword [edx+32], eax
2133
        mov     dword [edx+36], ebx
2134
@@:
2135
        lea     edi, [edx+8]
2136
        mov     eax, [esi+INODE.inodeModified]
2137
        sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2138
        call    fsTime2bdfe
2139
 
2140
        mov     eax, [esi+INODE.accessedTime]
2141
        sub     eax, 978307200
2142
        call    fsTime2bdfe
2143
 
2144
        mov     eax, [esi+INODE.dataModified]
2145
        sub     eax, 978307200
2146
        call    fsTime2bdfe
2147
        call    ext_unlock
2148
        xor     eax, eax
2149
        ret
2150
 
2151
;----------------------------------------------------------------
2152
ext_SetFileInfo:
2153
        call    extfsWritingInit
2154
        pushd   [ebx+16]
6468 pathoswith 2155
        call    findInode
6462 pathoswith 2156
        pop     edx
2157
        jc      @f
2158
        push    esi     ; inode number
2159
        lea     esi, [edx+16]
6558 pathoswith 2160
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2161
        call    fsCalculateTime
2162
        add     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2163
        mov     [edi+INODE.accessedTime], eax
2164
 
2165
        add     esi, 8
2166
        call    fsCalculateTime
2167
        add     eax, 978307200
2168
        mov     [edi+INODE.dataModified], eax
2169
        mov     ebx, edi
2170
        pop     eax
2171
        call    writeInode
2172
@@:
2173
        push    eax
2174
        jc      @f
2175
        call    writeSuperblock
2176
        mov     esi, [ebp+PARTITION.Disk]
2177
        call    disk_sync
2178
@@:
2179
        call    ext_unlock
2180
        pop     eax
2181
        ret
2182
 
2183
;----------------------------------------------------------------
2184
ext_Delete:
2185
        call    extfsWritingInit
6468 pathoswith 2186
        call    findInode
6462 pathoswith 2187
        mov     ebx, esi
2188
        push    eax
2189
        jc      .ret
2190
        pop     eax
6558 pathoswith 2191
        lea     edx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2192
        movzx   edx, [edx+INODE.accessMode]
2193
        and     edx, TYPE_MASK
2194
        cmp     edx, DIRECTORY
2195
        jne     .file
6726 pathoswith 2196
        push    ebx ecx edx
2197
        xor     ecx, ecx
6462 pathoswith 2198
.checkDirectory:
6726 pathoswith 2199
        push    ecx
2200
        call    extfsGetExtent
2201
        jc      .empty
6462 pathoswith 2202
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
2203
        call    extfsReadBlock
2204
        jc      .not_empty_eax
2205
        mov     edx, ebx
2206
        add     edx, [ebp+EXTFS.bytesPerBlock]
2207
        movzx   ecx, [ebx+DIRENTRY.entryLength]
2208
        add     ebx, ecx
2209
.dir_entry:
2210
        cmp     byte [ebx+DIRENTRY.nameLength], 1
2211
        jne     @f
2212
        cmp     byte [ebx+DIRENTRY.name], '.'
2213
        jne     .not_empty
2214
@@:
2215
        cmp     byte [ebx+DIRENTRY.nameLength], 2
2216
        jne     .not_empty
2217
        cmp     word [ebx+DIRENTRY.name], '..'
2218
        jne     .not_empty
2219
        movzx   ecx, [ebx+DIRENTRY.entryLength]
2220
        add     ebx, ecx
2221
        cmp     ebx, edx
2222
        jb      .dir_entry
6726 pathoswith 2223
        pop     ecx
2224
        inc     ecx
6462 pathoswith 2225
        jmp     .checkDirectory
2226
 
6756 pathoswith 2227
.not_empty:
2228
        pop     eax eax
2229
.error_stack8:
2230
        pop     eax eax
2231
        push    ERROR_ACCESS_DENIED
2232
        jmp     .ret
2233
 
6462 pathoswith 2234
.empty:
6726 pathoswith 2235
        cmp     eax, ERROR_END_OF_FILE
2236
        jnz     .not_empty_eax
6522 pathoswith 2237
        pop     edx edx ecx ebx
6462 pathoswith 2238
.file:
6522 pathoswith 2239
        mov     eax, ecx
2240
        push    ebx ecx
6462 pathoswith 2241
        call    unlinkInode
2242
        cmp     eax, -1
2243
        je      .error_stack8
6522 pathoswith 2244
        pop     ebx
6462 pathoswith 2245
        test    eax, eax
2246
        jz      @f
2247
        xor     eax, eax
6522 pathoswith 2248
        cmp     edx, DIRECTORY
2249
        jnz     .error_stack4_eax   ; hardlinks
2250
        mov     eax, [esp]
2251
        call    unlinkInode
6462 pathoswith 2252
@@:
2253
        mov     eax, [esp]
6558 pathoswith 2254
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2255
        call    readInode
2256
        jc      .error_stack4_eax
2257
        xor     ecx, ecx
6643 pathoswith 2258
        call    extfsTruncateFile   ; free file's data
6778 pathoswith 2259
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
2260
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2261
        xor     eax, eax
6778 pathoswith 2262
        push    edx edi
6462 pathoswith 2263
        rep stosb
2264
        call    fsGetTime
6778 pathoswith 2265
        pop     ebx ecx
6462 pathoswith 2266
        add     eax, 978307200
6778 pathoswith 2267
        mov     [ebx+INODE.deletedTime], eax
6462 pathoswith 2268
        mov     eax, [esp]
2269
        call    writeInode
2270
        jc      .error_stack4_eax
6756 pathoswith 2271
        pop     eax
6462 pathoswith 2272
        dec     eax
2273
        xor     edx, edx
2274
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6756 pathoswith 2275
        push    edx eax
6462 pathoswith 2276
        call    extfsReadDescriptor
6756 pathoswith 2277
        jc      .error_stack8_eax
2278
        cmp     ecx, DIRECTORY
2279
        jnz     @f
2280
        dec     [ebx+BGDESCR.directoriesCount]
2281
@@:
2282
        inc     [ebx+BGDESCR.inodesFree]
2283
        mov     ecx, [ebx+BGDESCR.inodeBitmap]
6462 pathoswith 2284
        pop     eax
2285
        call    extfsWriteDescriptor
6756 pathoswith 2286
        mov     eax, ecx
2287
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
2288
        call    extfsReadBlock
2289
        jc      .error_stack4_eax
6462 pathoswith 2290
        pop     eax
6756 pathoswith 2291
        mov     edx, eax
2292
        and     edx, 31
2293
        shr     eax, 5
2294
        shl     eax, 2
2295
        add     eax, ebx
2296
        btr     [eax], edx
2297
        mov     eax, ecx
2298
        call    extfsWriteBlock
2299
        inc     [ebp+EXTFS.superblock.inodesFree]
6462 pathoswith 2300
        push    eax
2301
.disk_sync:
2302
        call    writeSuperblock
2303
        mov     esi, [ebp+PARTITION.Disk]
2304
        call    disk_sync
2305
.ret:
2306
        call    ext_unlock
2307
        xor     ebx, ebx
2308
        pop     eax
2309
        ret
2310
 
2311
.not_empty_eax:
6756 pathoswith 2312
        pop     ebx ebx
2313
.error_stack8_eax:
2314
        pop     ebx
6462 pathoswith 2315
.error_stack4_eax:
2316
        pop     ebx
2317
        push    eax
2318
        jmp     .disk_sync
2319
 
2320
;----------------------------------------------------------------
2321
ext_CreateFolder:
2322
        call    extfsWritingInit
6468 pathoswith 2323
        call    findInode
6462 pathoswith 2324
        jnc     .success    ; exist
6522 pathoswith 2325
        test    edi, edi
2326
        jz      .error
6462 pathoswith 2327
        mov     eax, esi
6643 pathoswith 2328
        call    extfsInodeAlloc
6462 pathoswith 2329
        jc      .error
2330
        push    ebx esi edi
2331
        xor     al, al
6558 pathoswith 2332
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2333
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
2334
        rep stosb
6558 pathoswith 2335
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2336
        call    fsGetTime
2337
        add     eax, 978307200
2338
        mov     [edi+INODE.accessedTime], eax
2339
        mov     [edi+INODE.dataModified], eax
2340
        mov     ebx, edi
2341
        pop     edi esi edx
2342
; edx = allocated inode number, edi -> filename, esi = parent inode number
2343
        mov     [ebx+INODE.accessMode], DIRECTORY or PERMISSIONS
2344
        mov     eax, edx
2345
        call    writeInode
2346
        jc      .error
2347
; link to self
2348
        push    edx esi
2349
        mov     eax, edx
2350
        mov     ebx, eax
2351
        mov     dl, DIR_DIRECTORY
2352
        mov     esi, self_link
2353
        call    linkInode
2354
        pop     esi edx
2355
        jc      .error
2356
; link to parent
2357
        push    edx esi
2358
        mov     eax, ebx
2359
        mov     ebx, esi
2360
        mov     dl, DIR_DIRECTORY
2361
        mov     esi, parent_link
2362
        call    linkInode
2363
        pop     esi edx
2364
        jc      .error
2365
; link parent to child
2366
        mov     eax, esi
2367
        mov     ebx, edx
2368
        mov     esi, edi
2369
        mov     dl, DIR_DIRECTORY
2370
        call    linkInode
2371
        jc      .error
2372
        mov     eax, ebx
2373
        dec     eax
2374
        xor     edx, edx
2375
        div     [ebp+EXTFS.superblock.inodesPerGroup]
2376
        mov     edx, eax
2377
        call    extfsReadDescriptor
6756 pathoswith 2378
        jc      .error
2379
        inc     [ebx+BGDESCR.directoriesCount]
6462 pathoswith 2380
        mov     eax, edx
2381
        call    extfsWriteDescriptor
2382
.success:
2383
.error:
2384
        push    eax
2385
        call    writeSuperblock
2386
        mov     esi, [ebp+PARTITION.Disk]
2387
        call    disk_sync
2388
        call    ext_unlock
2389
        pop     eax
2390
        ret
2391
 
2392
self_link   db ".", 0
2393
parent_link db "..", 0
2394
 
2395
;----------------------------------------------------------------
2396
ext_CreateFile:
2397
        call    extfsWritingInit
6726 pathoswith 2398
        pushd   0 0 ebx
6468 pathoswith 2399
        call    findInode
6522 pathoswith 2400
        jnc     .exist
2401
        test    edi, edi
2402
        jz      .error
6462 pathoswith 2403
        mov     eax, esi
6643 pathoswith 2404
        call    extfsInodeAlloc
6462 pathoswith 2405
        jc      .error
6522 pathoswith 2406
        push    ebx ebx esi edi
6462 pathoswith 2407
        xor     al, al
6558 pathoswith 2408
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2409
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
2410
        rep stosb
6558 pathoswith 2411
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2412
        call    fsGetTime
2413
        add     eax, 978307200
2414
        mov     [edi+INODE.accessedTime], eax
2415
        mov     [edi+INODE.dataModified], eax
2416
        mov     ebx, edi
2417
        pop     edi esi edx
2418
; edx = allocated inode number, edi -> filename, esi = parent inode number
2419
        mov     [ebx+INODE.accessMode], FLAG_FILE or PERMISSIONS
2420
        mov     eax, edx
2421
        call    writeInode
6522 pathoswith 2422
        jc      .error2
6462 pathoswith 2423
; link parent to child
2424
        mov     eax, esi
2425
        mov     ebx, edx
2426
        mov     esi, edi
2427
        mov     dl, DIR_FLAG_FILE
2428
        call    linkInode
6522 pathoswith 2429
        jc      .error2
6462 pathoswith 2430
        pop     esi ebx
6522 pathoswith 2431
        mov     ecx, [ebx+12]
2432
        jmp     ext_WriteFile.start
6462 pathoswith 2433
 
6522 pathoswith 2434
.exist:
2435
        movi    eax, ERROR_ACCESS_DENIED
6726 pathoswith 2436
        test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
6522 pathoswith 2437
        jz      .error  ; not a file
2438
        pop     ebx
2439
        mov     ecx, [ebx+12]
2440
        call    extfsTruncateFile
6643 pathoswith 2441
        jmp     ext_WriteFile.start
2442
 
6522 pathoswith 2443
.error2:
2444
        pop     ebx
6462 pathoswith 2445
.error:
2446
        push    eax
2447
        call    ext_unlock
6726 pathoswith 2448
        pop     eax ebx ebx ebx
6462 pathoswith 2449
        ret
2450
 
2451
;----------------------------------------------------------------
2452
ext_WriteFile:
2453
        call    extfsWritingInit
6726 pathoswith 2454
        push    ebx
6468 pathoswith 2455
        call    findInode
6522 pathoswith 2456
        pop     ebx
6726 pathoswith 2457
        pushd   0 eax
2458
        jc      .ret
2459
        mov     byte [esp], ERROR_ACCESS_DENIED
2460
        test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
2461
        jz      .ret    ; not a file
6522 pathoswith 2462
        mov     ecx, [ebx+4]
2463
        add     ecx, [ebx+12]
2464
.start:
6726 pathoswith 2465
        push    esi
6462 pathoswith 2466
        mov     eax, esi
2467
        call    extfsExtendFile
6726 pathoswith 2468
        jc      .errorExtend
2469
        mov     eax, [ebx+4]
6643 pathoswith 2470
        mov     ecx, [ebx+12]
6726 pathoswith 2471
        mov     esi, [ebx+16]
2472
.write:
6462 pathoswith 2473
        xor     edx, edx
2474
        div     [ebp+EXTFS.bytesPerBlock]
2475
        test    edx, edx
6726 pathoswith 2476
        jz      .aligned
2477
.piece:
2478
        mov     ebx, ecx
2479
        mov     edi, edx
2480
        mov     ecx, eax
2481
        push    eax
2482
        call    extfsGetExtent
2483
        jc      .errorGet
2484
        mov     ecx, [ebp+EXTFS.sectorsPerBlock]
2485
        mul     ecx
2486
        push    ecx eax ebx
2487
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
2488
        call    fs_read64_sys
2489
        test    eax, eax
2490
        jnz     .errorDevice
2491
        pop     eax
2492
        mov     ecx, [ebp+EXTFS.bytesPerBlock]
2493
        sub     ecx, edi
2494
        sub     eax, ecx
2495
        jnc     @f
2496
        add     ecx, eax
2497
        xor     eax, eax
6462 pathoswith 2498
@@:
6726 pathoswith 2499
        add     edi, ebx
2500
        add     [esp+20], ecx
2501
        rep movsb
6575 pathoswith 2502
        mov     edi, eax
6726 pathoswith 2503
        pop     eax ecx
6462 pathoswith 2504
        xor     edx, edx
6726 pathoswith 2505
        call    fs_write64_sys
2506
        mov     ecx, edi
2507
        pop     eax
2508
        inc     eax
6462 pathoswith 2509
        xor     edx, edx
6726 pathoswith 2510
        jecxz   .done
2511
.aligned:
2512
        xchg    eax, ecx
6462 pathoswith 2513
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2514
        push    edx
2515
        mov     edx, eax
2516
.writeExtent:
2517
        test    edx, edx
2518
        jz      .end
6462 pathoswith 2519
        push    ecx
6726 pathoswith 2520
        call    extfsGetExtent
2521
        jc      .errorGet2
2522
        sub     edx, ecx
2523
        jnc     @f
2524
        add     ecx, edx
2525
        xor     edx, edx
2526
@@:
2527
        add     [esp], ecx
2528
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
2529
        mov     ebx, esi
2530
        push    edx ecx
2531
        mul     [ebp+EXTFS.sectorsPerBlock]
2532
        call    fs_write64_sys
2533
        test    eax, eax
2534
        jnz     .errorDevice
2535
        pop     ebx edx ecx
2536
        shl     ebx, 9
2537
        add     esi, ebx
2538
        add     [esp+12], ebx
2539
        jmp     .writeExtent
2540
 
2541
.end:
2542
        mov     eax, ecx
6462 pathoswith 2543
        pop     ecx
6726 pathoswith 2544
        jecxz   .done
2545
        jmp     .piece
2546
 
2547
.errorDevice:
2548
        pop     eax eax
2549
        movi    eax, ERROR_DEVICE
2550
.errorGet2:
2551
        pop     ebx
2552
.errorGet:
2553
        pop     ebx
2554
.errorExtend:
2555
        mov     [esp+4], eax
2556
.done:
6558 pathoswith 2557
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6726 pathoswith 2558
        pop     eax
6462 pathoswith 2559
        call    writeInode
6726 pathoswith 2560
        add     [esp], eax
6462 pathoswith 2561
        call    writeSuperblock
2562
        mov     esi, [ebp+PARTITION.Disk]
2563
        call    disk_sync
6726 pathoswith 2564
.ret:
6462 pathoswith 2565
        call    ext_unlock
6726 pathoswith 2566
        pop     eax ebx
6462 pathoswith 2567
        ret
2568
 
6726 pathoswith 2569
.erase:
2570
        push    eax eax edx
2571
        mov     eax, ebx
2572
        jmp     .write
6462 pathoswith 2573
 
2574
;----------------------------------------------------------------
2575
ext_SetFileEnd:
2576
        call    extfsWritingInit
2577
        pushd   [ebx+4]
6468 pathoswith 2578
        call    findInode
6726 pathoswith 2579
        pop     ecx
6643 pathoswith 2580
        jc      .error2
6575 pathoswith 2581
        lea     edi, [ebp+EXTFS.inodeBuffer]
2582
        movi    eax, ERROR_ACCESS_DENIED
6726 pathoswith 2583
        test    [edi+INODE.accessMode], FLAG_FILE
2584
        jz      .error2 ; not a file
6575 pathoswith 2585
        push    esi
2586
        mov     ebx, [edi+INODE.fileSize]
6462 pathoswith 2587
        mov     eax, esi
6575 pathoswith 2588
        cmp     ebx, ecx
6726 pathoswith 2589
        jnc     @f
6575 pathoswith 2590
        call    extfsExtendFile
2591
        jc      .error
2592
        sub     ecx, ebx
6726 pathoswith 2593
        cmp     ecx, 1000001h
2594
        jnc     .done
2595
        push    ecx
2596
        stdcall kernel_alloc, ecx
2597
        pop     ecx
2598
        test    eax, eax
2599
        jz      .error
2600
        push    ecx
2601
        add     ecx, 3
2602
        shr     ecx, 2
2603
        mov     esi, eax
6575 pathoswith 2604
        mov     edi, eax
2605
        xor     eax, eax
6726 pathoswith 2606
        rep stosd
2607
        pop     ecx edx
2608
        push    esi
2609
        call    ext_WriteFile.erase
2610
        call    kernel_free
6575 pathoswith 2611
        xor     eax, eax
6726 pathoswith 2612
        ret
2613
 
6575 pathoswith 2614
@@:
6726 pathoswith 2615
        call    extfsTruncateFile
6575 pathoswith 2616
.done:
6643 pathoswith 2617
        xor     eax, eax
2618
.error:
2619
        xchg    eax, [esp]
6558 pathoswith 2620
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2621
        call    writeInode
6726 pathoswith 2622
        add     [esp], eax
6462 pathoswith 2623
        call    writeSuperblock
2624
        mov     esi, [ebp+PARTITION.Disk]
2625
        call    disk_sync
6726 pathoswith 2626
        pop     eax
6643 pathoswith 2627
.error2:
6726 pathoswith 2628
        push    eax
6462 pathoswith 2629
        call    ext_unlock
2630
        pop     eax
2631
        ret