Subversion Repositories Kolibri OS

Rev

Rev 6845 | Rev 6849 | 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: 6848 $
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
6462 pathoswith 1021
; eax = inode number
1022
; ecx = new size
1023
        push    ebx ecx edx esi edi eax
6575 pathoswith 1024
        lea     esi, [ebp+EXTFS.inodeBuffer]
6643 pathoswith 1025
        mov     eax, ecx
1026
        mov     edx, [esi+INODE.fileSize]
1027
        cmp     edx, eax
1028
        jnc     .ret
1029
        mov     [esi+INODE.fileSize], eax
1030
        mov     ecx, [ebp+EXTFS.sectorsPerBlockLog]
1031
        add     ecx, 9
1032
        dec     eax
1033
        shr     eax, cl
1034
        inc     eax
1035
        sub     edx, 1
1036
        jc      @f
1037
        shr     edx, cl
1038
@@:
1039
        inc     edx
6575 pathoswith 1040
        sub     eax, edx
6643 pathoswith 1041
        jz      .ret
1042
        push    eax
1043
@@:
1044
        mov     ecx, [esp]
1045
        mov     eax, [esp+4]
1046
        test    ecx, ecx
1047
        jz      .done
1048
        call    extfsExtentAlloc
1049
        jc      .errDone
1050
        sub     [esp], ecx
1051
        cmp     edx, 12
1052
        jc      .directBlocks
1053
        sub     edx, 12
1054
        cmp     edx, [ebp+EXTFS.dwordsPerBlock]
1055
        jc      .indirectBlocks
1056
        sub     edx, [ebp+EXTFS.dwordsPerBlock]
1057
        cmp     edx, [ebp+EXTFS.dwordsPerBranch]
1058
        jc      .doublyIndirectBlock
1059
        sub     edx, [ebp+EXTFS.dwordsPerBranch]
1060
        jmp     .triplyIndirectBlock
1061
 
1062
.newExtent:
1063
        jmp     @b
1064
 
1065
.directBlocks:
1066
        lea     edi, [esi+INODE.blockNumbers+edx*4]
1067
        test    edx, edx
1068
        jz      @f
1069
        cmp     dword[edi-4], 0
1070
        jz      .errDone
6575 pathoswith 1071
@@:
1072
        mov     eax, ebx
6643 pathoswith 1073
        mov     ebx, ecx
1074
        mov     ecx, 12
1075
        sub     ecx, edx
1076
        sub     ebx, ecx
1077
        jnc     @f
1078
        add     ecx, ebx
1079
        xor     ebx, ebx
1080
@@:
1081
        add     edx, ecx
1082
@@:
1083
        stosd
1084
        inc     eax
1085
        loop    @b
1086
        mov     ecx, ebx
1087
        mov     ebx, eax
1088
        jecxz   .newExtent
6462 pathoswith 1089
        xor     edx, edx
6643 pathoswith 1090
.indirectBlocks:
1091
        lea     edi, [esi+INODE.addressBlock]
1092
        cmp     dword[edi], 0
1093
        jnz     @f
1094
        inc     dword[esp]
1095
@@:
1096
        call    indirectBlockAlloc
1097
        jc      .errDone
1098
        add     edx, 12
1099
        jecxz   .newExtent
1100
        xor     edx, edx
1101
.doublyIndirectBlock:
1102
        lea     edi, [esi+INODE.doubleAddress]
1103
        call    doublyIndirectBlockAlloc
1104
        jc      .errDone
1105
        mov     edx, [ebp+EXTFS.dwordsPerBranch]
1106
        add     edx, [ebp+EXTFS.dwordsPerBlock]
1107
        add     edx, 12
1108
        jecxz   .newExtent
1109
        xor     edx, edx
1110
.triplyIndirectBlock:
1111
        push    ecx ebx edx
1112
        stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
1113
        pop     edx
1114
        mov     esi, eax
1115
        mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1116
        test    eax, eax
1117
        jz      .newBlock
1118
        mov     ebx, esi
1119
        call    extfsReadBlock
1120
        pop     ebx ecx
1121
        jc      .errFree
1122
        mov     eax, edx
1123
        xor     edx, edx
1124
        div     [ebp+EXTFS.dwordsPerBranch]
1125
        lea     edi, [esi+eax*4]
1126
        test    eax, eax
1127
        jz      @f
1128
        cmp     dword[edi-4], 0
1129
        jnz     @f
1130
        mov     al, ERROR_FS_FAIL
1131
.errFree:
1132
        push    ecx eax
1133
        stdcall kernel_free, esi
1134
        pop     eax ecx
1135
.errDone:
1136
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
1137
        sub     [ebp+EXTFS.inodeBuffer.sectorsUsed], ecx
1138
        pop     ebx
1139
        imul    ebx, [ebp+EXTFS.sectorsPerBlock]
6575 pathoswith 1140
        add     ebx, ecx
6643 pathoswith 1141
        shl     ebx, 9
1142
        sub     [ebp+EXTFS.inodeBuffer.fileSize], ebx
1143
        stc
1144
        jmp     .ret
1145
 
1146
.newBlock:
1147
        pop     ebx ecx
1148
        mov     al, ERROR_FS_FAIL
1149
        test    edx, edx
1150
        jnz     .errFree
1151
        mov     [ebp+EXTFS.inodeBuffer.tripleAddress], ebx
1152
        inc     ebx
1153
        dec     ecx
1154
        inc     dword[esp]
1155
        push    ecx
1156
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
1157
        mov     edi, esi
1158
        xor     eax, eax
1159
        rep stosd
1160
        mov     edi, esi
1161
        pop     ecx
1162
@@:
1163
        jecxz   .extentAlloc
1164
        call    doublyIndirectBlockAlloc
1165
        jc      .errSave
1166
        add     edi, 4
1167
        jmp     @b
1168
 
1169
.extentAlloc:
1170
        mov     ecx, [esp]
1171
        mov     eax, [esp+4]
1172
        jecxz   @f
1173
        call    extfsExtentAlloc
1174
        jc      .errSave
1175
        sub     [esp], ecx
1176
        jmp     @b
1177
 
1178
@@:
1179
        mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1180
        mov     ebx, esi
1181
        call    extfsWriteBlock
1182
        stdcall kernel_free, esi
6558 pathoswith 1183
.done:
6462 pathoswith 1184
        xor     eax, eax
6643 pathoswith 1185
        pop     edi
6462 pathoswith 1186
.ret:
1187
        pop     edi edi esi edx ecx ebx
1188
        ret
1189
 
6643 pathoswith 1190
.errSave:
1191
        push    eax
1192
        mov     eax, [ebp+EXTFS.inodeBuffer.tripleAddress]
1193
        mov     ebx, esi
1194
        call    extfsWriteBlock
1195
        pop     eax
1196
        jmp     .errFree
1197
 
1198
freeIndirectBlock:
1199
; in: edi -> indirect block number, edx = starting block
1200
; out: edi = edi+4, eax=-1 -> done, eax=0 -> end
1201
        pushd   ecx 0 edi edx
1202
        mov     eax, [edi]
1203
        test    eax, eax
1204
        jz      .ret
1205
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1206
        call    extfsReadBlock
1207
        jc      .ret
1208
        lea     edi, [ebx+edx*4]
1209
        neg     edx
1210
        add     edx, [ebp+EXTFS.dwordsPerBlock]
6756 pathoswith 1211
.freeExtent:
1212
        mov     ebx, [edi]
1213
        test    ebx, ebx
1214
        jz      .end
1215
        xor     eax, eax
6643 pathoswith 1216
        xor     ecx, ecx
1217
@@:
1218
        stosd
6756 pathoswith 1219
        inc     ecx
6643 pathoswith 1220
        dec     edx
6756 pathoswith 1221
        jz      @f
1222
        mov     eax, [edi]
1223
        sub     eax, ebx
1224
        sub     eax, ecx
1225
        jz      @b
1226
@@:
1227
        mov     eax, ebx
1228
        call    extfsExtentFree
1229
        test    edx, edx
1230
        jnz     .freeExtent
6643 pathoswith 1231
        dec     dword[esp+8]
1232
.end:
1233
        pop     edx edi
1234
        mov     eax, [edi]
1235
        test    edx, edx
1236
        jnz     @f
6756 pathoswith 1237
        xor     ecx, ecx
1238
        inc     ecx
1239
        call    extfsExtentFree
6643 pathoswith 1240
        stosd
1241
        jmp     .done
1242
 
1243
@@:
6756 pathoswith 1244
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
6643 pathoswith 1245
        call    extfsWriteBlock
1246
        add     edi, 4
1247
.done:
1248
        pop     eax ecx
1249
        xor     edx, edx
1250
        ret
1251
 
1252
.ret:
1253
        pop     edi edi edx ecx
1254
        ret
1255
 
1256
freeDoublyIndirectBlock:
1257
; in: edi -> doubly-indirect block number, edx = starting block
1258
; out: edi = edi+4, eax=-1 -> done, eax=0 -> end
1259
        mov     eax, [edi]
1260
        test    eax, eax
1261
        jz      .ret
1262
        push    ecx eax edx
1263
        stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
1264
        mov     ebx, eax
1265
        pop     edx eax
1266
        pushd   0 ebx edx
1267
        call    extfsReadBlock
1268
        jc      .err
1269
        mov     eax, edx
1270
        xor     edx, edx
1271
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
1272
        div     ecx
1273
        sub     ecx, eax
1274
        push    edi
1275
        lea     edi, [ebx+eax*4]
1276
@@:
1277
        call    freeIndirectBlock
1278
        test    eax, eax
1279
        jz      .end
1280
        dec     ecx
1281
        jnz     @b
1282
        dec     dword[esp+12]
1283
.end:
1284
        pop     edi edx
1285
        mov     eax, [edi]
1286
        test    edx, edx
1287
        jnz     @f
1288
        xor     ecx, ecx
6756 pathoswith 1289
        inc     ecx
1290
        call    extfsExtentFree
6643 pathoswith 1291
        stosd
1292
        jmp     .done
1293
 
1294
@@:
1295
        mov     ebx, [esp]
1296
        call    extfsWriteBlock
1297
        add     edi, 4
1298
        jmp     .done
1299
 
1300
.err:
1301
        mov     [esp+8], eax
1302
        pop     eax
1303
.done:
1304
        call    kernel_free
1305
        pop     eax ecx
1306
.ret:
1307
        xor     edx, edx
1308
        ret
1309
 
6462 pathoswith 1310
extfsTruncateFile:
6756 pathoswith 1311
; in: ecx = new size, [ebp+EXTFS.inodeBuffer] = inode
6558 pathoswith 1312
        push    ebx ecx edx esi edi
6575 pathoswith 1313
        lea     esi, [ebp+EXTFS.inodeBuffer]
6643 pathoswith 1314
        cmp     ecx, [esi+INODE.fileSize]
6462 pathoswith 1315
        jnc     .ret
6643 pathoswith 1316
        mov     [esi+INODE.fileSize], ecx
1317
        mov     edx, ecx
1318
        jecxz   .directBlocks
1319
        dec     edx
1320
        mov     ecx, [ebp+EXTFS.sectorsPerBlockLog]
1321
        add     ecx, 9
1322
        shr     edx, cl
1323
        inc     edx
1324
        cmp     edx, 12
1325
        jc      .directBlocks
1326
        sub     edx, 12
1327
        cmp     edx, [ebp+EXTFS.dwordsPerBlock]
1328
        jc      .indirectBlocks
1329
        sub     edx, [ebp+EXTFS.dwordsPerBlock]
1330
        cmp     edx, [ebp+EXTFS.dwordsPerBranch]
1331
        jc      .doublyIndirectBlock
1332
        sub     edx, [ebp+EXTFS.dwordsPerBranch]
1333
        jmp     .triplyIndirectBlock
1334
 
1335
.directBlocks:
1336
        lea     edi, [esi+INODE.blockNumbers+edx*4]
1337
        neg     edx
1338
        add     edx, 12
1339
        xor     ecx, ecx
6756 pathoswith 1340
        inc     ecx
6643 pathoswith 1341
@@:
1342
        mov     eax, [edi]
1343
        test    eax, eax
1344
        jz      .ret
6756 pathoswith 1345
        call    extfsExtentFree
6643 pathoswith 1346
        stosd
1347
        dec     edx
1348
        jnz     @b
1349
.indirectBlocks:
1350
        lea     edi, [esi+INODE.addressBlock]
1351
        call    freeIndirectBlock
1352
        test    eax, eax
1353
        jz      .ret
1354
.doublyIndirectBlock:
1355
        lea     edi, [esi+INODE.doubleAddress]
1356
        call    freeDoublyIndirectBlock
1357
        test    eax, eax
1358
        jz      .ret
1359
.triplyIndirectBlock:
1360
        mov     eax, [esi+INODE.tripleAddress]
1361
        test    eax, eax
1362
        jz      .ret
1363
        push    eax edx
1364
        stdcall kernel_alloc, [ebp+EXTFS.bytesPerBlock]
6575 pathoswith 1365
        mov     ebx, eax
6643 pathoswith 1366
        pop     edx eax
1367
        push    ebx eax edx
1368
        call    extfsReadBlock
1369
        jc      .err
1370
        mov     eax, edx
6462 pathoswith 1371
        xor     edx, edx
6643 pathoswith 1372
        div     [ebp+EXTFS.dwordsPerBranch]
1373
        mov     ecx, [ebp+EXTFS.dwordsPerBlock]
1374
        sub     ecx, eax
1375
        lea     edi, [ebx+eax*4]
1376
@@:
1377
        call    freeDoublyIndirectBlock
1378
        test    eax, eax
1379
        jz      .end
1380
        dec     ecx
1381
        jnz     @b
1382
.end:
1383
        pop     edx eax
6462 pathoswith 1384
        test    edx, edx
6575 pathoswith 1385
        jnz     @f
1386
        xor     ecx, ecx
6756 pathoswith 1387
        inc     ecx
1388
        call    extfsExtentFree
6643 pathoswith 1389
        mov     [esi+INODE.tripleAddress], eax
1390
        jmp     .done
1391
 
6575 pathoswith 1392
@@:
6643 pathoswith 1393
        mov     ebx, [esp]
1394
        call    extfsWriteBlock
1395
        jmp     .done
6462 pathoswith 1396
 
6643 pathoswith 1397
.err:
1398
        pop     eax eax
6558 pathoswith 1399
.done:
6643 pathoswith 1400
        call    kernel_free
6462 pathoswith 1401
.ret:
6558 pathoswith 1402
        pop     edi esi edx ecx ebx
6462 pathoswith 1403
        ret
1404
 
1405
linkInode:
1406
;   in:
1407
; eax = inode on which to link
1408
; ebx = inode to link
6471 pathoswith 1409
; esi -> name in UTF-8
6462 pathoswith 1410
;  dl = file type
1411
        push    esi edi ebx ecx eax edx
1412
        call    strlen
1413
        add     ecx, 8  ; directory entry size
1414
        push    esi ebx ecx
1415
        xor     ecx, ecx
6558 pathoswith 1416
        lea     esi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1417
        mov     ebx, esi
1418
        call    readInode
1419
        jc      .error_inode_read
1420
        mov     ecx, [ebp+EXTFS.sectorsPerBlockLog]
6643 pathoswith 1421
        add     ecx, 9
1422
        mov     eax, [esi+INODE.fileSize]
6462 pathoswith 1423
        shr     eax, cl
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]
6462 pathoswith 1437
        mov     edi, [ebp+EXTFS.tempBlockBuffer]
1438
        mov     edx, edi
1439
        add     edx, [ebp+EXTFS.bytesPerBlock]
1440
.searchSpace:
1441
        movzx   eax, [edi+DIRENTRY.entryLength]
1442
        test    eax, eax
1443
        jz      .zeroLength
1444
        cmp     [edi+DIRENTRY.inodeNumber], 0
1445
        je      .unusedEntry
1446
        movzx   ebx, [edi+DIRENTRY.nameLength]
1447
        add     ebx, 8+3
1448
        and     ebx, -4
1449
        sub     eax, ebx
1450
        add     edi, ebx
1451
        cmp     eax, ecx
1452
        jb      .nextEntry
1453
        sub     edi, ebx
1454
        mov     [edi+DIRENTRY.entryLength], bx
1455
        add     edi, ebx
1456
        mov     [edi+DIRENTRY.entryLength], ax
1457
        jmp     .found
1458
 
1459
.unusedEntry:
1460
        cmp     eax, ecx
1461
        jge     .found
1462
.nextEntry:
1463
        add     edi, eax
1464
        cmp     edi, edx
1465
        jb      .searchSpace
6558 pathoswith 1466
        pop     ecx ecx eax
1467
        inc     ecx
1468
        jmp     .searchBlock
6462 pathoswith 1469
 
1470
.zeroLength:
1471
        mov     [edi+DIRENTRY.entryLength], cx
1472
        mov     eax, edx
1473
        sub     eax, edi
1474
        cmp     eax, ecx
1475
        jge     .found
1476
        mov     [edi+DIRENTRY.inodeNumber], 0
1477
        mov     [edi+DIRENTRY.entryLength], ax
1478
; this block wasn't linking to the next one, so write it, and use the next block
1479
        pop     eax
1480
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1481
        call    extfsWriteBlock
6726 pathoswith 1482
        pop     ecx
1483
        inc     ecx
1484
        cmp     ecx, [esp]
1485
        push    ecx
1486
        jnz     @f
1487
.alloc_block:
1488
        mov     ecx, [esi+INODE.fileSize]
1489
        add     ecx, [ebp+EXTFS.bytesPerBlock]
1490
        mov     eax, [esp+24]
1491
        call    extfsExtendFile
1492
        jc      .error_get_inode_block
1493
        mov     eax, [esp+24]
1494
        mov     ebx, esi
1495
        call    writeInode
1496
        jc      .error_get_inode_block
1497
        mov     ecx, [esp]
6643 pathoswith 1498
@@:
6726 pathoswith 1499
        call    extfsGetExtent
6462 pathoswith 1500
        jc      .error_get_inode_block
6726 pathoswith 1501
        push    eax
6575 pathoswith 1502
        mov     edi, [ebp+EXTFS.tempBlockBuffer]
6462 pathoswith 1503
        mov     eax, [ebp+EXTFS.bytesPerBlock]
1504
        mov     [edi+DIRENTRY.entryLength], ax
1505
.found:
1506
        pop     edx ecx ecx ecx ebx esi
1507
        push    ebx
6575 pathoswith 1508
        mov     [edi+DIRENTRY.inodeNumber], ebx
1509
        sub     ecx, 8
1510
        mov     word [edi+DIRENTRY.nameLength], cx
6462 pathoswith 1511
        cmp     [ebp+EXTFS.superblock.dynamicVersionFlag], 0
1512
        je      .name
6575 pathoswith 1513
        mov     eax, [esp+4]
6462 pathoswith 1514
        mov     [edi+DIRENTRY.fileType], al
1515
.name:
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:
6756 pathoswith 1545
; in: eax = inode from which to unlink, ebx = inode to unlink
1546
; out: eax = current number of links to inode, -1 = error
6522 pathoswith 1547
        push    edx ebx
6558 pathoswith 1548
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1549
        call    readInode
1550
        jc      .fail
1551
        push    eax
1552
.loop:
1553
        mov     ecx, [esp]
6726 pathoswith 1554
        call    extfsGetExtent
6462 pathoswith 1555
        jc      .fail_loop
6726 pathoswith 1556
        mov     edi, eax
6462 pathoswith 1557
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1558
        call    extfsReadBlock
1559
        jc      .fail_loop
1560
.first_dir_entry:   ; edi -> block
1561
        mov     eax, [esp+4]
1562
        cmp     [ebx+DIRENTRY.inodeNumber], eax
1563
        jne     @f
1564
        mov     [ebx+DIRENTRY.inodeNumber], 0
1565
        mov     word [ebx+DIRENTRY.nameLength], 0   ; fileType = 0
1566
        jmp     .write_block
1567
 
1568
@@:
1569
        mov     edx, ebx
1570
        add     edx, [ebp+EXTFS.bytesPerBlock]
1571
        push    edx
1572
        mov     edx, ebx
1573
        movzx   ecx, [ebx+DIRENTRY.entryLength]
1574
        add     ebx, ecx
1575
.dir_entry:
1576
        cmp     [ebx+DIRENTRY.inodeNumber], eax
1577
        jne     @f
1578
        mov     cx, [ebx+DIRENTRY.entryLength]
1579
        add     [edx+DIRENTRY.entryLength], cx
1580
        pop     eax
1581
        jmp     .write_block
1582
 
1583
@@:
1584
        mov     edx, ebx
1585
        movzx   ecx, [ebx+DIRENTRY.entryLength]
1586
        test    ecx, ecx
1587
        jz      .fail_inode
1588
        add     ebx, ecx
1589
        cmp     ebx, [esp]
1590
        jb      .dir_entry
1591
        pop     ecx
1592
        inc     dword[esp]
1593
        jmp     .loop
1594
 
1595
.fail_inode:
1596
        pop     eax
1597
.fail_loop:
1598
        pop     eax
1599
.fail:
1600
        or      eax, -1
1601
        jmp     @f
1602
 
1603
.write_block:
1604
        pop     eax
1605
        mov     eax, edi
1606
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
1607
        call    extfsWriteBlock
1608
        mov     eax, [esp]
6558 pathoswith 1609
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1610
        call    readInode
1611
        jc      .fail
1612
        dec     word [ebx+INODE.linksCount]
1613
        mov     eax, [esp]
1614
        call    writeInode
1615
        jc      .fail
1616
        movzx   eax, word [ebx+INODE.linksCount]
1617
@@:
6522 pathoswith 1618
        pop     ebx edx
6462 pathoswith 1619
        ret
1620
 
6522 pathoswith 1621
findInode:
6471 pathoswith 1622
; in: esi -> path string in UTF-8
6462 pathoswith 1623
;   out:
6471 pathoswith 1624
; edi -> file name in UTF-8
6522 pathoswith 1625
; esi = last inode number
6558 pathoswith 1626
; [ebp+EXTFS.inodeBuffer] = last inode
6522 pathoswith 1627
; ecx = parent inode number
1628
; CF=1 -> file not found, edi=0 -> error
6462 pathoswith 1629
        push    esi
1630
        lea     esi, [ebp+EXTFS.rootInodeBuffer]
6558 pathoswith 1631
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1632
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
6522 pathoswith 1633
        mov     edx, esi
6462 pathoswith 1634
        rep movsb
6522 pathoswith 1635
        pop     esi
1636
        pushd   0 ROOT_INODE
6558 pathoswith 1637
        mov     edi, esi
6756 pathoswith 1638
        cmp     [edx+INODE.fileSize], 0
6522 pathoswith 1639
        jz      .not_found
1640
        cmp     byte [esi], 0
1641
        jnz     .next_path_part
6462 pathoswith 1642
        xor     eax, eax
6522 pathoswith 1643
        pop     esi ecx
6468 pathoswith 1644
        ret
6462 pathoswith 1645
 
6522 pathoswith 1646
@@:
1647
        pop     esi esi
1648
.error:
1649
        pop     esi ecx
1650
        xor     edi, edi
1651
        stc
1652
        ret
1653
 
6462 pathoswith 1654
.next_path_part:
6756 pathoswith 1655
        push    [edx+INODE.fileSize]
6462 pathoswith 1656
        xor     ecx, ecx
1657
.folder_block_cycle:
1658
        push    ecx
6726 pathoswith 1659
        call    extfsGetExtent
6522 pathoswith 1660
        jc      @b
6462 pathoswith 1661
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1662
        call    extfsReadBlock
6522 pathoswith 1663
        jc      @b
6462 pathoswith 1664
        push    esi edx
1665
        mov     edx, ebx
1666
        add     edx, [ebp+EXTFS.bytesPerBlock]
1667
.start_rec:
1668
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1669
        jz      .next_rec
1670
        push    esi
1671
        movzx   ecx, [ebx+DIRENTRY.nameLength]
6471 pathoswith 1672
        lea     edi, [ebx+DIRENTRY.name]
1673
        repz cmpsb
1674
        jz      .test_find
6462 pathoswith 1675
@@: ; doesn't match
1676
        pop     esi
1677
.next_rec:
1678
        movzx   eax, [ebx+DIRENTRY.entryLength]
1679
        add     ebx, eax
1680
        cmp     ebx, edx
1681
        jb      .start_rec
1682
        push    eax
1683
        jmp     @f
1684
 
1685
.test_find:
1686
        cmp     byte [esi], 0
1687
        je      @f
1688
        cmp     byte [esi], '/'
1689
        jne     @b
1690
        inc     esi
1691
@@:
6522 pathoswith 1692
        pop     edx edx edi ecx eax
6462 pathoswith 1693
; ebx -> matched directory entry, esi -> name without parent, or not changed
1694
        cmp     edi, esi
6522 pathoswith 1695
        jnz     @f
6756 pathoswith 1696
        sub     eax, [ebp+EXTFS.bytesPerBlock]
6462 pathoswith 1697
        jle     .not_found
1698
        push    eax
1699
        inc     ecx
1700
        jmp     .folder_block_cycle
1701
 
6522 pathoswith 1702
@@:
6462 pathoswith 1703
        pop     eax
6522 pathoswith 1704
        mov     [esp], eax
6462 pathoswith 1705
        mov     eax, [ebx+DIRENTRY.inodeNumber]
6558 pathoswith 1706
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6522 pathoswith 1707
        push    eax
6462 pathoswith 1708
        call    readInode
6522 pathoswith 1709
        jc      .error
1710
        cmp     byte [esi], 0
1711
        je      .ret
1712
        mov     edx, ebx
1713
        movzx   eax, [ebx+INODE.accessMode]
1714
        and     eax, TYPE_MASK
1715
        cmp     eax, DIRECTORY
1716
        jz      .next_path_part
6558 pathoswith 1717
        xor     edi, edi    ; path folder is a file
1718
        jmp     @f
1719
 
6462 pathoswith 1720
.not_found:
6558 pathoswith 1721
        mov     esi, edi
1722
        call    strlen
1723
        mov     al, '/'
1724
        repnz scasb
1725
        mov     edi, esi
1726
        jnz     @f
1727
        xor     edi, edi    ; path folder not found
1728
@@:
6462 pathoswith 1729
        movi    eax, ERROR_FILE_NOT_FOUND
1730
        stc
6522 pathoswith 1731
.ret:
1732
        pop     esi ecx
6468 pathoswith 1733
        ret
6462 pathoswith 1734
 
1735
writeSuperblock:
1736
        push    ebx
1737
        mov     eax, 2
1738
        lea     ebx, [ebp+EXTFS.superblock]
1739
        call    fs_write32_sys
1740
        pop     ebx
1741
        ret
1742
 
1743
extfsWritingInit:
1744
        movi    eax, ERROR_UNSUPPORTED_FS
1745
        test    [ebp+EXTFS.mountType], READ_ONLY
1746
        jnz     @f
1747
ext_lock:
1748
        lea     ecx, [ebp+EXTFS.Lock]
1749
        jmp     mutex_lock
1750
 
1751
@@:
1752
        pop     ebx
1753
        xor     ebx, ebx
1754
        ret
1755
 
1756
ext_unlock:
1757
        lea     ecx, [ebp+EXTFS.Lock]
1758
        jmp     mutex_unlock
1759
 
1760
;----------------------------------------------------------------
1761
ext_ReadFolder:
1762
        call    ext_lock
1763
        cmp     byte [esi], 0
1764
        jz      .root_folder
1765
        push    ebx
6468 pathoswith 1766
        call    findInode
6462 pathoswith 1767
        pop     ebx
1768
        jc      .error_ret
6558 pathoswith 1769
        lea     esi, [ebp+EXTFS.inodeBuffer]
6522 pathoswith 1770
        test    [esi+INODE.accessMode], FLAG_FILE
1771
        jnz     .error_not_found
6462 pathoswith 1772
        jmp     @f
1773
 
1774
.root_folder:
1775
        lea     esi, [ebp+EXTFS.rootInodeBuffer]
6558 pathoswith 1776
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 1777
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
1778
        shr     ecx, 2
1779
        push    edi
1780
        rep movsd
1781
        pop     esi
1782
@@:
1783
        cmp     [esi+INODE.fileSize], 0
1784
        je      .error_empty_dir
1785
        mov     edx, [ebx+16]
1786
        push    edx         ; [edi+28] result buffer
1787
        push    0           ; [edi+24] end of the current block in folder
1788
        pushd   [ebx+12]    ; [edi+20] files to read
1789
        pushd   [ebx+4]     ; [edi+16] first wanted file
1790
        pushd   [ebx+8]     ; [edi+12] flags
1791
        push    0           ; [edi+8]  read files
1792
        push    0           ; [edi+4]  files in folder
1793
        push    0           ; [edi]    current block index
1794
        mov     edi, esp    ; edi -> local variables
1795
        add     edx, 32
1796
        xor     ecx, ecx
6726 pathoswith 1797
        call    extfsGetExtent
6462 pathoswith 1798
        jc      .error_get_block
1799
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1800
        call    extfsReadBlock
1801
        jc      .error_get_block
1802
        mov     eax, ebx
1803
        add     eax, [ebp+EXTFS.bytesPerBlock]
1804
        mov     [edi+24], eax
1805
        mov     ecx, [edi+16]
1806
.find_wanted_start:
1807
        jecxz   .find_wanted_end
1808
.find_wanted_cycle:
1809
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1810
        jz      @f
1811
        inc     dword [edi+4]
1812
        dec     ecx
1813
@@:
1814
        movzx   eax, [ebx+DIRENTRY.entryLength]
1815
        cmp     eax, 12     ; minimum entry length
1816
        jb      .error_bad_len
1817
        test    eax, 3      ; length must be aligned
1818
        jnz     .error_bad_len
1819
        sub     [esi+INODE.fileSize], eax
1820
        add     ebx, eax
1821
        cmp     ebx, [edi+24]
1822
        jb      .find_wanted_start
1823
        push    .find_wanted_start
1824
.end_block: ; read next block
1825
        cmp     [esi+INODE.fileSize], 0
1826
        jle     .end_dir
1827
        inc     dword [edi]
1828
        push    ecx
1829
        mov     ecx, [edi]
6726 pathoswith 1830
        call    extfsGetExtent
6462 pathoswith 1831
        jc      .error_get_block
1832
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
1833
        call    extfsReadBlock
1834
        jc      .error_get_block
1835
        pop     ecx
1836
        mov     eax, ebx
1837
        add     eax, [ebp+EXTFS.bytesPerBlock]
1838
        mov     [edi+24], eax
1839
        ret
1840
 
1841
.wanted_end:
1842
        loop    .find_wanted_cycle
1843
.find_wanted_end:
1844
        mov     ecx, [edi+20]
1845
.wanted_start:
1846
        jecxz   .wanted_end
1847
        cmp     [ebx+DIRENTRY.inodeNumber], 0
1848
        jz      .empty_rec
1849
        inc     dword [edi+8]
1850
        inc     dword [edi+4]
6558 pathoswith 1851
        push    ebx edi ecx esi edx edi
6471 pathoswith 1852
        pushd   [edi+12]
6462 pathoswith 1853
        mov     edi, edx
1854
        xor     eax, eax
1855
        mov     ecx, 40 / 4
1856
        rep stosd
6558 pathoswith 1857
        popd    [edx+4] edi
6462 pathoswith 1858
        mov     eax, [ebx+DIRENTRY.inodeNumber]
6558 pathoswith 1859
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
6462 pathoswith 1860
        call    readInode
1861
        jc      .error_read_subinode
1862
        mov     esi, ebx
1863
        lea     edi, [edx+8]
1864
        mov     eax, [ebx+INODE.inodeModified]
1865
        sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
1866
        call    fsTime2bdfe
1867
 
1868
        mov     eax, [esi+INODE.accessedTime]
1869
        sub     eax, 978307200
1870
        call    fsTime2bdfe
1871
 
1872
        mov     eax, [esi+INODE.dataModified]
1873
        sub     eax, 978307200
1874
        call    fsTime2bdfe
1875
        pop     edx
1876
        or      dword [edx], KOS_DIRECTORY
6522 pathoswith 1877
        test    [esi+INODE.accessMode], FLAG_FILE
1878
        jz      @f
6462 pathoswith 1879
        xor     dword [edx], KOS_DIRECTORY  ; mark as file
1880
        mov     eax, [esi+INODE.fileSize]
1881
        stosd
1882
        mov     eax, [esi+INODE.fileSizeHigh]
1883
        stosd
1884
@@:
1885
        mov     esi, [esp+12]
1886
        movzx   ecx, [esi+DIRENTRY.nameLength]
6471 pathoswith 1887
        lea     esi, [esi+DIRENTRY.name]
1888
        cmp     byte [esi], '.'
1889
        jnz     @f
1890
        or      byte [edx], KOS_HIDDEN
1891
@@:
6462 pathoswith 1892
        lea     edi, [edx+40]
6798 pathoswith 1893
        cmp     byte [edx+4], 3
1894
        jz      .utf8
1895
        add     ecx, esi
1896
        cmp     byte [edx+4], 2
6471 pathoswith 1897
        jz      .utf16
1898
@@:
1899
        call    utf8to16
1900
        call    uni2ansi_char
1901
        stosb
1902
        cmp     esi, ecx
1903
        jc      @b
6462 pathoswith 1904
        and     byte [edi], 0
6471 pathoswith 1905
        add     edx, 40+264
1906
@@:
6462 pathoswith 1907
        pop     esi ecx edi ebx
1908
        dec     ecx
1909
.empty_rec:
1910
        movzx   eax, [ebx+DIRENTRY.entryLength]
1911
        cmp     eax, 12
1912
        jb      .error_bad_len
1913
        test    eax, 3
1914
        jnz     .error_bad_len
1915
        sub     [esi+INODE.fileSize], eax
1916
        add     ebx, eax
1917
        cmp     ebx, [edi+24]
1918
        jb      .wanted_start
1919
        push    .wanted_start
1920
        jmp     .end_block
1921
 
6798 pathoswith 1922
.utf8:
1923
        rep movsb
1924
        mov     byte [edi], 0
1925
        add     edx, 40+520
1926
        jmp     @b
1927
 
6471 pathoswith 1928
.utf16:
1929
        call    utf8to16
1930
        stosw
1931
        cmp     esi, ecx
1932
        jc      .utf16
1933
        and     word [edi], 0
1934
        add     edx, 40+520
1935
        jmp     @b
1936
 
6462 pathoswith 1937
.end_dir:
1938
        call    ext_unlock
1939
        mov     edx, [edi+28]
1940
        mov     ebx, [edi+8]
1941
        mov     ecx, [edi+4]
1942
        mov     dword [edx], 1  ; version
1943
        mov     [edx+4], ebx
1944
        mov     [edx+8], ecx
1945
        lea     esp, [edi+32]
1946
        mov     ecx, 20/4
1947
        lea     edi, [edx+12]
1948
        xor     eax, eax
1949
        rep stosd
1950
        ret
1951
 
1952
.error_bad_len:
1953
        movi    eax, ERROR_FS_FAIL
1954
.error_read_subinode:
1955
.error_get_block:
1956
        lea     esp, [edi+32]
1957
.error_ret:
1958
        or      ebx, -1
1959
        push    eax
1960
        call    ext_unlock
1961
        pop     eax
1962
        ret
1963
 
1964
.error_empty_dir:
1965
        movi    eax, ERROR_FS_FAIL
1966
        jmp     .error_ret
1967
 
1968
.error_not_found:
1969
        movi    eax, ERROR_FILE_NOT_FOUND
1970
        jmp     .error_ret
1971
 
1972
;----------------------------------------------------------------
1973
ext_ReadFile:
1974
        call    ext_lock
6845 pathoswith 1975
        pushd   0 ebx
6468 pathoswith 1976
        call    findInode
6462 pathoswith 1977
        pop     ebx
6726 pathoswith 1978
        push    eax
1979
        jc      .ret
6558 pathoswith 1980
        lea     esi, [ebp+EXTFS.inodeBuffer]
6726 pathoswith 1981
        mov     byte [esp], ERROR_ACCESS_DENIED
1982
        test    [esi+INODE.accessMode], FLAG_FILE
1983
        jz      .ret    ; not a file
1984
        mov     byte [esp], ERROR_END_OF_FILE
1985
        mov     eax, [esi+INODE.fileSize]
1986
        mov     edx, [esi+INODE.fileSizeHigh]
1987
        sub     eax, [ebx+4]
1988
        sbb     edx, [ebx+8]
1989
        jc      .ret
6462 pathoswith 1990
        mov     ecx, [ebx+12]
6726 pathoswith 1991
        sub     eax, ecx
1992
        sbb     edx, 0
1993
        jc      @f
1994
        xor     eax, eax
1995
        mov     [esp], eax
1996
@@:
1997
        add     ecx, eax
6462 pathoswith 1998
        mov     eax, [ebx+4]
1999
        mov     edx, [ebx+8]
6726 pathoswith 2000
        mov     edi, [ebx+16]
6462 pathoswith 2001
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2002
        test    edx, edx
2003
        jz      .aligned
2004
.piece:
2005
        push    eax ecx
2006
        mov     esi, edx
6462 pathoswith 2007
        mov     ecx, eax
6726 pathoswith 2008
        call    extfsGetExtent
2009
        jc      .errorGet
2010
        mov     ecx, [ebp+EXTFS.sectorsPerBlock]
2011
        mul     ecx
6462 pathoswith 2012
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
6726 pathoswith 2013
        call    fs_read64_sys
2014
        test    eax, eax
2015
        jnz     .errorRead
2016
        pop     eax
2017
        mov     ecx, [ebp+EXTFS.bytesPerBlock]
2018
        sub     ecx, esi
2019
        sub     eax, ecx
2020
        jnc     @f
2021
        add     ecx, eax
2022
        xor     eax, eax
2023
@@:
2024
        add     esi, ebx
2025
        add     [esp+8], ecx
6462 pathoswith 2026
        rep movsb
6726 pathoswith 2027
        mov     ecx, eax
2028
        pop     eax
2029
        inc     eax
6462 pathoswith 2030
        xor     edx, edx
6726 pathoswith 2031
        jecxz   .ret
2032
.aligned:
2033
        xchg    eax, ecx
6462 pathoswith 2034
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2035
        push    edx
2036
        mov     edx, eax
2037
.writeExtent:
2038
        test    edx, edx
2039
        jz      .end
2040
        push    ecx
2041
        call    extfsGetExtent
2042
        jc      .errorGet
2043
        sub     edx, ecx
2044
        jnc     @f
2045
        add     ecx, edx
2046
        xor     edx, edx
6462 pathoswith 2047
@@:
6726 pathoswith 2048
        add     [esp], ecx
2049
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
2050
        mov     ebx, edi
2051
        push    edx ecx
2052
        mul     [ebp+EXTFS.sectorsPerBlock]
2053
        call    fs_read64_sys
2054
        pop     ecx edx
2055
        test    eax, eax
2056
        jnz     .errorRead
2057
        shl     ecx, 9
2058
        add     edi, ecx
2059
        add     [esp+12], ecx
2060
        pop     ecx
2061
        jmp     .writeExtent
6462 pathoswith 2062
 
6726 pathoswith 2063
.end:
6462 pathoswith 2064
        mov     eax, ecx
6726 pathoswith 2065
        pop     ecx
2066
        jecxz   .ret
2067
        jmp     .piece
6462 pathoswith 2068
 
6726 pathoswith 2069
.errorRead:
2070
        movi    eax, ERROR_DEVICE
2071
.errorGet:
6462 pathoswith 2072
        pop     ebx ebx
6726 pathoswith 2073
        mov     [esp], eax
2074
.ret:
6462 pathoswith 2075
        call    ext_unlock
6726 pathoswith 2076
        pop     eax ebx
6462 pathoswith 2077
        ret
2078
 
2079
;----------------------------------------------------------------
2080
ext_GetFileInfo:
2081
        call    ext_lock
2082
        mov     edx, [ebx+16]
2083
        cmp     byte [esi], 0
2084
        jz      .is_root
2085
        push    edx
6468 pathoswith 2086
        call    findInode
6462 pathoswith 2087
        pop     edx
6558 pathoswith 2088
        lea     esi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2089
        jnc     @f
2090
        push    eax
2091
        call    ext_unlock
2092
        pop     eax
2093
        ret
2094
 
2095
.is_root:
6522 pathoswith 2096
        mov     edi, esi
6462 pathoswith 2097
        lea     esi, [ebp+EXTFS.rootInodeBuffer]
2098
@@:
6522 pathoswith 2099
        mov     bl, [edi]
6462 pathoswith 2100
        xor     eax, eax
2101
        mov     edi, edx
2102
        mov     ecx, 40/4
2103
        rep stosd
2104
        cmp     bl, '.'
2105
        jne     @f
2106
        or      dword [edx], KOS_HIDDEN
2107
@@:
2108
        or      dword [edx], KOS_DIRECTORY
6522 pathoswith 2109
        test    [esi+INODE.accessMode], FLAG_FILE
2110
        jz      @f
6462 pathoswith 2111
        xor     dword [edx], KOS_DIRECTORY  ; mark as file
2112
        mov     eax, [esi+INODE.fileSize]
2113
        mov     ebx, [esi+INODE.fileSizeHigh]
2114
        mov     dword [edx+32], eax
2115
        mov     dword [edx+36], ebx
2116
@@:
2117
        lea     edi, [edx+8]
2118
        mov     eax, [esi+INODE.inodeModified]
2119
        sub     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2120
        call    fsTime2bdfe
2121
 
2122
        mov     eax, [esi+INODE.accessedTime]
2123
        sub     eax, 978307200
2124
        call    fsTime2bdfe
2125
 
2126
        mov     eax, [esi+INODE.dataModified]
2127
        sub     eax, 978307200
2128
        call    fsTime2bdfe
2129
        call    ext_unlock
2130
        xor     eax, eax
2131
        ret
2132
 
2133
;----------------------------------------------------------------
2134
ext_SetFileInfo:
2135
        call    extfsWritingInit
2136
        pushd   [ebx+16]
6468 pathoswith 2137
        call    findInode
6462 pathoswith 2138
        pop     edx
2139
        jc      @f
2140
        push    esi     ; inode number
2141
        lea     esi, [edx+16]
6558 pathoswith 2142
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2143
        call    fsCalculateTime
2144
        add     eax, 978307200  ; 01.01.1970-01.01.2001 = (365*31+8)*24*60*60
2145
        mov     [edi+INODE.accessedTime], eax
2146
 
2147
        add     esi, 8
2148
        call    fsCalculateTime
2149
        add     eax, 978307200
2150
        mov     [edi+INODE.dataModified], eax
2151
        mov     ebx, edi
2152
        pop     eax
2153
        call    writeInode
2154
@@:
2155
        push    eax
2156
        jc      @f
2157
        call    writeSuperblock
2158
        mov     esi, [ebp+PARTITION.Disk]
2159
        call    disk_sync
2160
@@:
2161
        call    ext_unlock
2162
        pop     eax
2163
        ret
2164
 
2165
;----------------------------------------------------------------
2166
ext_Delete:
2167
        call    extfsWritingInit
6468 pathoswith 2168
        call    findInode
6462 pathoswith 2169
        mov     ebx, esi
2170
        push    eax
2171
        jc      .ret
2172
        pop     eax
6558 pathoswith 2173
        lea     edx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2174
        movzx   edx, [edx+INODE.accessMode]
2175
        and     edx, TYPE_MASK
2176
        cmp     edx, DIRECTORY
2177
        jne     .file
6726 pathoswith 2178
        push    ebx ecx edx
2179
        xor     ecx, ecx
6462 pathoswith 2180
.checkDirectory:
6726 pathoswith 2181
        push    ecx
2182
        call    extfsGetExtent
2183
        jc      .empty
6462 pathoswith 2184
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
2185
        call    extfsReadBlock
2186
        jc      .not_empty_eax
2187
        mov     edx, ebx
2188
        add     edx, [ebp+EXTFS.bytesPerBlock]
2189
        movzx   ecx, [ebx+DIRENTRY.entryLength]
2190
        add     ebx, ecx
2191
.dir_entry:
2192
        cmp     byte [ebx+DIRENTRY.nameLength], 1
2193
        jne     @f
2194
        cmp     byte [ebx+DIRENTRY.name], '.'
2195
        jne     .not_empty
2196
@@:
2197
        cmp     byte [ebx+DIRENTRY.nameLength], 2
2198
        jne     .not_empty
2199
        cmp     word [ebx+DIRENTRY.name], '..'
2200
        jne     .not_empty
2201
        movzx   ecx, [ebx+DIRENTRY.entryLength]
2202
        add     ebx, ecx
2203
        cmp     ebx, edx
2204
        jb      .dir_entry
6726 pathoswith 2205
        pop     ecx
2206
        inc     ecx
6462 pathoswith 2207
        jmp     .checkDirectory
2208
 
6756 pathoswith 2209
.not_empty:
2210
        pop     eax eax
2211
.error_stack8:
2212
        pop     eax eax
2213
        push    ERROR_ACCESS_DENIED
2214
        jmp     .ret
2215
 
6462 pathoswith 2216
.empty:
6726 pathoswith 2217
        cmp     eax, ERROR_END_OF_FILE
2218
        jnz     .not_empty_eax
6522 pathoswith 2219
        pop     edx edx ecx ebx
6462 pathoswith 2220
.file:
6522 pathoswith 2221
        mov     eax, ecx
2222
        push    ebx ecx
6462 pathoswith 2223
        call    unlinkInode
2224
        cmp     eax, -1
2225
        je      .error_stack8
6522 pathoswith 2226
        pop     ebx
6462 pathoswith 2227
        test    eax, eax
2228
        jz      @f
2229
        xor     eax, eax
6522 pathoswith 2230
        cmp     edx, DIRECTORY
2231
        jnz     .error_stack4_eax   ; hardlinks
2232
        mov     eax, [esp]
2233
        call    unlinkInode
6462 pathoswith 2234
@@:
2235
        mov     eax, [esp]
6558 pathoswith 2236
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2237
        call    readInode
2238
        jc      .error_stack4_eax
2239
        xor     ecx, ecx
6643 pathoswith 2240
        call    extfsTruncateFile   ; free file's data
6778 pathoswith 2241
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
2242
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2243
        xor     eax, eax
6778 pathoswith 2244
        push    edx edi
6462 pathoswith 2245
        rep stosb
2246
        call    fsGetTime
6778 pathoswith 2247
        pop     ebx ecx
6462 pathoswith 2248
        add     eax, 978307200
6778 pathoswith 2249
        mov     [ebx+INODE.deletedTime], eax
6462 pathoswith 2250
        mov     eax, [esp]
2251
        call    writeInode
2252
        jc      .error_stack4_eax
6756 pathoswith 2253
        pop     eax
6462 pathoswith 2254
        dec     eax
2255
        xor     edx, edx
2256
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6848 pathoswith 2257
        push    edx
2258
        mov     ebx, [ebp+EXTFS.descriptorTable]
2259
        shl     eax, 5
2260
        add     ebx, eax
6756 pathoswith 2261
        cmp     ecx, DIRECTORY
2262
        jnz     @f
2263
        dec     [ebx+BGDESCR.directoriesCount]
2264
@@:
2265
        inc     [ebx+BGDESCR.inodesFree]
6848 pathoswith 2266
        push    [ebx+BGDESCR.inodeBitmap]
2267
        call    extfsWriteDescriptor
6462 pathoswith 2268
        pop     eax
6756 pathoswith 2269
        mov     ebx, [ebp+EXTFS.tempBlockBuffer]
6848 pathoswith 2270
        mov     ecx, eax
6756 pathoswith 2271
        call    extfsReadBlock
2272
        jc      .error_stack4_eax
6462 pathoswith 2273
        pop     eax
6756 pathoswith 2274
        mov     edx, eax
2275
        and     edx, 31
2276
        shr     eax, 5
2277
        shl     eax, 2
2278
        add     eax, ebx
2279
        btr     [eax], edx
2280
        mov     eax, ecx
2281
        call    extfsWriteBlock
2282
        inc     [ebp+EXTFS.superblock.inodesFree]
6462 pathoswith 2283
        push    eax
2284
.disk_sync:
2285
        call    writeSuperblock
2286
        mov     esi, [ebp+PARTITION.Disk]
2287
        call    disk_sync
2288
.ret:
2289
        call    ext_unlock
2290
        xor     ebx, ebx
2291
        pop     eax
2292
        ret
2293
 
2294
.not_empty_eax:
6848 pathoswith 2295
        add     esp, 12
6462 pathoswith 2296
.error_stack4_eax:
2297
        pop     ebx
2298
        push    eax
2299
        jmp     .disk_sync
2300
 
2301
;----------------------------------------------------------------
2302
ext_CreateFolder:
2303
        call    extfsWritingInit
6468 pathoswith 2304
        call    findInode
6462 pathoswith 2305
        jnc     .success    ; exist
6522 pathoswith 2306
        test    edi, edi
2307
        jz      .error
6462 pathoswith 2308
        mov     eax, esi
6643 pathoswith 2309
        call    extfsInodeAlloc
6462 pathoswith 2310
        jc      .error
2311
        push    ebx esi edi
2312
        xor     al, al
6558 pathoswith 2313
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2314
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
2315
        rep stosb
6558 pathoswith 2316
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2317
        call    fsGetTime
2318
        add     eax, 978307200
2319
        mov     [edi+INODE.accessedTime], eax
2320
        mov     [edi+INODE.dataModified], eax
2321
        mov     ebx, edi
2322
        pop     edi esi edx
2323
; edx = allocated inode number, edi -> filename, esi = parent inode number
2324
        mov     [ebx+INODE.accessMode], DIRECTORY or PERMISSIONS
2325
        mov     eax, edx
2326
        call    writeInode
2327
        jc      .error
2328
; link to self
2329
        push    edx esi
2330
        mov     eax, edx
2331
        mov     ebx, eax
2332
        mov     dl, DIR_DIRECTORY
2333
        mov     esi, self_link
2334
        call    linkInode
2335
        pop     esi edx
2336
        jc      .error
2337
; link to parent
2338
        push    edx esi
2339
        mov     eax, ebx
2340
        mov     ebx, esi
2341
        mov     dl, DIR_DIRECTORY
2342
        mov     esi, parent_link
2343
        call    linkInode
2344
        pop     esi edx
2345
        jc      .error
2346
; link parent to child
2347
        mov     eax, esi
2348
        mov     ebx, edx
2349
        mov     esi, edi
2350
        mov     dl, DIR_DIRECTORY
2351
        call    linkInode
2352
        jc      .error
2353
        mov     eax, ebx
2354
        dec     eax
2355
        xor     edx, edx
2356
        div     [ebp+EXTFS.superblock.inodesPerGroup]
6848 pathoswith 2357
        mov     ebx, [ebp+EXTFS.descriptorTable]
2358
        shl     eax, 5
2359
        add     ebx, eax
6756 pathoswith 2360
        inc     [ebx+BGDESCR.directoriesCount]
6462 pathoswith 2361
        call    extfsWriteDescriptor
2362
.success:
2363
.error:
2364
        push    eax
2365
        call    writeSuperblock
2366
        mov     esi, [ebp+PARTITION.Disk]
2367
        call    disk_sync
2368
        call    ext_unlock
2369
        pop     eax
2370
        ret
2371
 
2372
self_link   db ".", 0
2373
parent_link db "..", 0
2374
 
2375
;----------------------------------------------------------------
2376
ext_CreateFile:
2377
        call    extfsWritingInit
6726 pathoswith 2378
        pushd   0 0 ebx
6468 pathoswith 2379
        call    findInode
6522 pathoswith 2380
        jnc     .exist
2381
        test    edi, edi
2382
        jz      .error
6462 pathoswith 2383
        mov     eax, esi
6643 pathoswith 2384
        call    extfsInodeAlloc
6462 pathoswith 2385
        jc      .error
6522 pathoswith 2386
        push    ebx ebx esi edi
6462 pathoswith 2387
        xor     al, al
6558 pathoswith 2388
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2389
        movzx   ecx, [ebp+EXTFS.superblock.inodeSize]
2390
        rep stosb
6558 pathoswith 2391
        lea     edi, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2392
        call    fsGetTime
2393
        add     eax, 978307200
2394
        mov     [edi+INODE.accessedTime], eax
2395
        mov     [edi+INODE.dataModified], eax
2396
        mov     ebx, edi
2397
        pop     edi esi edx
2398
; edx = allocated inode number, edi -> filename, esi = parent inode number
2399
        mov     [ebx+INODE.accessMode], FLAG_FILE or PERMISSIONS
2400
        mov     eax, edx
2401
        call    writeInode
6522 pathoswith 2402
        jc      .error2
6462 pathoswith 2403
; link parent to child
2404
        mov     eax, esi
2405
        mov     ebx, edx
2406
        mov     esi, edi
2407
        mov     dl, DIR_FLAG_FILE
2408
        call    linkInode
6522 pathoswith 2409
        jc      .error2
6462 pathoswith 2410
        pop     esi ebx
6522 pathoswith 2411
        mov     ecx, [ebx+12]
2412
        jmp     ext_WriteFile.start
6462 pathoswith 2413
 
6522 pathoswith 2414
.exist:
2415
        movi    eax, ERROR_ACCESS_DENIED
6726 pathoswith 2416
        test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
6522 pathoswith 2417
        jz      .error  ; not a file
2418
        pop     ebx
2419
        mov     ecx, [ebx+12]
2420
        call    extfsTruncateFile
6643 pathoswith 2421
        jmp     ext_WriteFile.start
2422
 
6522 pathoswith 2423
.error2:
2424
        pop     ebx
6462 pathoswith 2425
.error:
2426
        push    eax
2427
        call    ext_unlock
6726 pathoswith 2428
        pop     eax ebx ebx ebx
6462 pathoswith 2429
        ret
2430
 
2431
;----------------------------------------------------------------
2432
ext_WriteFile:
2433
        call    extfsWritingInit
6726 pathoswith 2434
        push    ebx
6468 pathoswith 2435
        call    findInode
6522 pathoswith 2436
        pop     ebx
6726 pathoswith 2437
        pushd   0 eax
2438
        jc      .ret
2439
        mov     byte [esp], ERROR_ACCESS_DENIED
2440
        test    [ebp+EXTFS.inodeBuffer.accessMode], FLAG_FILE
2441
        jz      .ret    ; not a file
6522 pathoswith 2442
        mov     ecx, [ebx+4]
2443
        add     ecx, [ebx+12]
2444
.start:
6726 pathoswith 2445
        push    esi
6462 pathoswith 2446
        mov     eax, esi
2447
        call    extfsExtendFile
6726 pathoswith 2448
        jc      .errorExtend
2449
        mov     eax, [ebx+4]
6643 pathoswith 2450
        mov     ecx, [ebx+12]
6726 pathoswith 2451
        mov     esi, [ebx+16]
2452
.write:
6462 pathoswith 2453
        xor     edx, edx
2454
        div     [ebp+EXTFS.bytesPerBlock]
2455
        test    edx, edx
6726 pathoswith 2456
        jz      .aligned
2457
.piece:
2458
        mov     ebx, ecx
2459
        mov     edi, edx
2460
        mov     ecx, eax
2461
        push    eax
2462
        call    extfsGetExtent
2463
        jc      .errorGet
2464
        mov     ecx, [ebp+EXTFS.sectorsPerBlock]
2465
        mul     ecx
2466
        push    ecx eax ebx
2467
        mov     ebx, [ebp+EXTFS.mainBlockBuffer]
2468
        call    fs_read64_sys
2469
        test    eax, eax
2470
        jnz     .errorDevice
2471
        pop     eax
2472
        mov     ecx, [ebp+EXTFS.bytesPerBlock]
2473
        sub     ecx, edi
2474
        sub     eax, ecx
2475
        jnc     @f
2476
        add     ecx, eax
2477
        xor     eax, eax
6462 pathoswith 2478
@@:
6726 pathoswith 2479
        add     edi, ebx
2480
        add     [esp+20], ecx
2481
        rep movsb
6575 pathoswith 2482
        mov     edi, eax
6726 pathoswith 2483
        pop     eax ecx
6462 pathoswith 2484
        xor     edx, edx
6726 pathoswith 2485
        call    fs_write64_sys
2486
        mov     ecx, edi
2487
        pop     eax
2488
        inc     eax
6462 pathoswith 2489
        xor     edx, edx
6726 pathoswith 2490
        jecxz   .done
2491
.aligned:
2492
        xchg    eax, ecx
6462 pathoswith 2493
        div     [ebp+EXTFS.bytesPerBlock]
6726 pathoswith 2494
        push    edx
2495
        mov     edx, eax
2496
.writeExtent:
2497
        test    edx, edx
2498
        jz      .end
6462 pathoswith 2499
        push    ecx
6726 pathoswith 2500
        call    extfsGetExtent
2501
        jc      .errorGet2
2502
        sub     edx, ecx
2503
        jnc     @f
2504
        add     ecx, edx
2505
        xor     edx, edx
2506
@@:
2507
        add     [esp], ecx
2508
        imul    ecx, [ebp+EXTFS.sectorsPerBlock]
2509
        mov     ebx, esi
2510
        push    edx ecx
2511
        mul     [ebp+EXTFS.sectorsPerBlock]
2512
        call    fs_write64_sys
2513
        test    eax, eax
2514
        jnz     .errorDevice
2515
        pop     ebx edx ecx
2516
        shl     ebx, 9
2517
        add     esi, ebx
2518
        add     [esp+12], ebx
2519
        jmp     .writeExtent
2520
 
2521
.end:
2522
        mov     eax, ecx
6462 pathoswith 2523
        pop     ecx
6726 pathoswith 2524
        jecxz   .done
2525
        jmp     .piece
2526
 
2527
.errorDevice:
2528
        pop     eax eax
2529
        movi    eax, ERROR_DEVICE
2530
.errorGet2:
2531
        pop     ebx
2532
.errorGet:
2533
        pop     ebx
2534
.errorExtend:
2535
        mov     [esp+4], eax
2536
.done:
6558 pathoswith 2537
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6726 pathoswith 2538
        pop     eax
6462 pathoswith 2539
        call    writeInode
6726 pathoswith 2540
        add     [esp], eax
6462 pathoswith 2541
        call    writeSuperblock
2542
        mov     esi, [ebp+PARTITION.Disk]
2543
        call    disk_sync
6726 pathoswith 2544
.ret:
6462 pathoswith 2545
        call    ext_unlock
6726 pathoswith 2546
        pop     eax ebx
6462 pathoswith 2547
        ret
2548
 
6726 pathoswith 2549
.erase:
2550
        push    eax eax edx
2551
        mov     eax, ebx
2552
        jmp     .write
6462 pathoswith 2553
 
2554
;----------------------------------------------------------------
2555
ext_SetFileEnd:
2556
        call    extfsWritingInit
2557
        pushd   [ebx+4]
6468 pathoswith 2558
        call    findInode
6726 pathoswith 2559
        pop     ecx
6643 pathoswith 2560
        jc      .error2
6575 pathoswith 2561
        lea     edi, [ebp+EXTFS.inodeBuffer]
2562
        movi    eax, ERROR_ACCESS_DENIED
6726 pathoswith 2563
        test    [edi+INODE.accessMode], FLAG_FILE
2564
        jz      .error2 ; not a file
6575 pathoswith 2565
        push    esi
2566
        mov     ebx, [edi+INODE.fileSize]
6462 pathoswith 2567
        mov     eax, esi
6575 pathoswith 2568
        cmp     ebx, ecx
6726 pathoswith 2569
        jnc     @f
6575 pathoswith 2570
        call    extfsExtendFile
2571
        jc      .error
2572
        sub     ecx, ebx
6726 pathoswith 2573
        cmp     ecx, 1000001h
2574
        jnc     .done
2575
        push    ecx
2576
        stdcall kernel_alloc, ecx
2577
        pop     ecx
2578
        test    eax, eax
2579
        jz      .error
2580
        push    ecx
2581
        add     ecx, 3
2582
        shr     ecx, 2
2583
        mov     esi, eax
6575 pathoswith 2584
        mov     edi, eax
2585
        xor     eax, eax
6726 pathoswith 2586
        rep stosd
2587
        pop     ecx edx
2588
        push    esi
2589
        call    ext_WriteFile.erase
2590
        call    kernel_free
6575 pathoswith 2591
        xor     eax, eax
6726 pathoswith 2592
        ret
2593
 
6575 pathoswith 2594
@@:
6726 pathoswith 2595
        call    extfsTruncateFile
6575 pathoswith 2596
.done:
6643 pathoswith 2597
        xor     eax, eax
2598
.error:
2599
        xchg    eax, [esp]
6558 pathoswith 2600
        lea     ebx, [ebp+EXTFS.inodeBuffer]
6462 pathoswith 2601
        call    writeInode
6726 pathoswith 2602
        add     [esp], eax
6462 pathoswith 2603
        call    writeSuperblock
2604
        mov     esi, [ebp+PARTITION.Disk]
2605
        call    disk_sync
6726 pathoswith 2606
        pop     eax
6643 pathoswith 2607
.error2:
6726 pathoswith 2608
        push    eax
6462 pathoswith 2609
        call    ext_unlock
2610
        pop     eax
2611
        ret