Subversion Repositories Kolibri OS

Rev

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