Subversion Repositories Kolibri OS

Rev

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