Subversion Repositories Kolibri OS

Rev

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