Subversion Repositories Kolibri OS

Rev

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