Subversion Repositories Kolibri OS

Rev

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