Subversion Repositories Kolibri OS

Rev

Rev 6849 | Rev 6853 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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