Subversion Repositories Kolibri OS

Rev

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