Subversion Repositories Kolibri OS

Rev

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