Subversion Repositories Kolibri OS

Rev

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