Subversion Repositories Kolibri OS

Rev

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