Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
5578 Pathoswith 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
6468 pathoswith 3
;; Copyright (C) KolibriOS team 2004-2016. All rights reserved. ;;
4
;;  Distributed under terms of the GNU General Public License.  ;;
5578 Pathoswith 5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2288 clevermous 7
 
8
$Revision: 6917 $
9
 
6468 pathoswith 10
; FAT external functions
11
;   in:
12
; ebx -> parameter structure of sysfunc 70
13
; ebp -> FAT structure
6471 pathoswith 14
; esi -> path string in UTF-8
6468 pathoswith 15
;   out:
16
; eax, ebx = return values for sysfunc 70
17
iglobal
18
align 4
19
fat_user_functions:
20
        dd      fat_free
21
        dd      (fat_user_functions_end - fat_user_functions - 4) / 4
22
        dd      fat_Read
23
        dd      fat_ReadFolder
24
        dd      fat_CreateFile
25
        dd      fat_Write
26
        dd      fat_SetFileEnd
27
        dd      fat_GetFileInfo
28
        dd      fat_SetFileInfo
29
        dd      0
30
        dd      fat_Delete
31
        dd      fat_CreateFolder
6917 pathoswith 32
        dd      fat_Rename
6468 pathoswith 33
fat_user_functions_end:
34
endg
35
 
2288 clevermous 36
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
37
 
38
PUSHAD_EAX equ [esp+28]
39
PUSHAD_ECX equ [esp+24]
40
PUSHAD_EDX equ [esp+20]
41
PUSHAD_EBX equ [esp+16]
42
PUSHAD_EBP equ [esp+8]
43
PUSHAD_ESI equ [esp+4]
44
PUSHAD_EDI equ [esp+0]
45
 
2643 clevermous 46
; Internal data for every FAT partition.
3742 clevermous 47
struct FAT PARTITION
6468 pathoswith 48
fs_type             db  ?
49
fat_change          db  ?   ; 1=fat has changed
6917 pathoswith 50
createOption        db  ?
51
                    rb  1
6468 pathoswith 52
Lock                MUTEX   ; currently operations with one partition
5578 Pathoswith 53
; can not be executed in parallel since the legacy code is not ready
6468 pathoswith 54
SECTORS_PER_FAT     dd  ?
55
NUMBER_OF_FATS      dd  ?
56
SECTORS_PER_CLUSTER dd  ?
57
BYTES_PER_SECTOR    dd  ?   ; Note: if BPS <> 512 need lots of changes
58
ROOT_CLUSTER        dd  ?   ; first rootdir cluster
59
FAT_START           dd  ?   ; start of fat table
60
ROOT_START          dd  ?   ; start of rootdir (only fat16)
61
ROOT_SECTORS        dd  ?   ; count of rootdir sectors (only fat16)
62
DATA_START          dd  ?   ; start of data area (=first cluster 2)
63
LAST_CLUSTER        dd  ?   ; last availabe cluster
64
ADR_FSINFO          dd  ?   ; used only by fat32
65
fatRESERVED         dd  ?
66
fatBAD              dd  ?
67
fatEND              dd  ?
68
fatMASK             dd  ?
69
fatStartScan        dd  ?
70
cluster_tmp         dd  ?   ; used by analyze_directory and analyze_directory_to_write
71
longname_sec1       dd  ?   ; used by analyze_directory to save 2 previous
72
longname_sec2       dd  ?   ; directory sectors for delete long filename
73
fat_in_cache        dd  ?
4273 clevermous 74
; For FAT16/FAT32, this points to 512-byte buffer for the current sector of FAT.
75
; For FAT12, the entire FAT structure is read
76
; and unpacked from 12bit per cluster to word per cluster.
77
; Note: work with unpacked copy of FAT12 means
78
; additional memory and additional code for packing/unpacking.
79
; I'm not sure that the economy justifies the cost, but anyway,
80
; there is how work was done before my edits, and I'm just keeping the principle.
6468 pathoswith 81
fat_cache_ptr       dd  ?
82
fat12_unpacked_ptr  dd  ?
6868 pathoswith 83
volumeLabel         rb  12
6468 pathoswith 84
buffer              rb  512
85
fsinfo_buffer       rb  512
2643 clevermous 86
ends
87
 
2288 clevermous 88
uglobal
89
align 4
6468 pathoswith 90
partition_count     dd  ?   ; partitions found by set_FAT32_variables
91
hd_error            dd  ?
92
hd_setup            dd  ?
93
hd_wait_timeout     dd  ?
94
cache_search_start  dd  ?   ; used by find_empty_slot
5578 Pathoswith 95
Sector512:      ; label for dev_hdcd.inc
96
buffer:
97
rb 512
2288 clevermous 98
endg
99
 
2643 clevermous 100
; these labels are located before the main function to make
101
; most of jumps to these be short
102
fat_create_partition.free_return0:
103
        mov     eax, ebp
104
        call    free
105
        pop     ebp
106
fat_create_partition.return0:
107
        xor     eax, eax
108
        ret
6867 pathoswith 109
 
2643 clevermous 110
fat_create_partition:
5089 clevermous 111
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
112
        jnz     .return0
2643 clevermous 113
; bootsector must have been successfully read
3742 clevermous 114
        cmp     dword [esp+4], 0
2643 clevermous 115
        jnz     .return0
116
; bootsector signature must be correct
117
        cmp     word [ebx+0x1fe], 0xaa55
118
        jnz     .return0
119
; sectors per cluster must be nonzero
120
        cmp     byte [ebx+0xd], 0
121
        jz      .return0
122
; bytes per sector must be 0x200
123
        cmp     word [ebx+0xb], 0x200
124
        jnz     .return0
125
; number of fats must be nonzero
126
        cmp     byte [ebx+0x10], 0
127
        jz      .return0
128
; The only reason to be invalid partition now is FAT12. Since the test for
129
; FAT size requires knowledge of some calculated values, which are also used
130
; in the normal operation, let's hope for the best and allocate data now; if
131
; it will prove wrong, just deallocate it.
3598 clevermous 132
        movi    eax, sizeof.FAT
2643 clevermous 133
        call    malloc
134
        test    eax, eax
135
        jz      .return0
3742 clevermous 136
        mov     ecx, dword [ebp+PARTITION.FirstSector]
137
        mov     dword [eax+FAT.FirstSector], ecx
138
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
139
        mov     dword [eax+FAT.FirstSector+4], ecx
140
        mov     ecx, dword [ebp+PARTITION.Length]
141
        mov     dword [eax+FAT.Length], ecx
142
        mov     ecx, dword [ebp+PARTITION.Length+4]
143
        mov     dword [eax+FAT.Length+4], ecx
144
        mov     ecx, [ebp+PARTITION.Disk]
145
        mov     [eax+FAT.Disk], ecx
146
        mov     [eax+FAT.FSUserFunctions], fat_user_functions
2643 clevermous 147
        or      [eax+FAT.fat_in_cache], -1
148
        mov     [eax+FAT.fat_change], 0
149
        push    ebp
150
        mov     ebp, eax
151
        lea     ecx, [ebp+FAT.Lock]
152
        call    mutex_init
153
        movzx   eax, word [ebx+0xe]     ; sectors reserved
154
        mov     [ebp+FAT.FAT_START], eax
155
        movzx   eax, byte [ebx+0xd]     ; sectors per cluster
156
        mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
157
        movzx   ecx, word [ebx+0xb]     ; bytes per sector
158
        mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
159
        movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
160
        shl     eax, 5                  ; mul 32
161
        dec     ecx
162
        add     eax, ecx                ; round up if not equal count
163
        inc     ecx                     ; bytes per sector
164
        xor     edx, edx
165
        div     ecx
166
        mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
167
        movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
168
        test    eax, eax
169
        jnz     @f
170
        mov     eax, [ebx+0x24]         ; sectors per fat
2288 clevermous 171
@@:
2643 clevermous 172
        mov     [ebp+FAT.SECTORS_PER_FAT], eax
173
        movzx   eax, byte [ebx+0x10]    ; number of fats
174
        mov     [ebp+FAT.NUMBER_OF_FATS], eax
4273 clevermous 175
        mul     [ebp+FAT.SECTORS_PER_FAT]
176
        test    edx, edx
177
        jnz     .free_return0
2643 clevermous 178
        add     eax, [ebp+FAT.FAT_START]
4273 clevermous 179
        jc      .free_return0
2643 clevermous 180
        mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
181
        add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
4273 clevermous 182
        jc      .free_return0
2643 clevermous 183
        mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
184
        movzx   eax, word [ebx+0x13]    ; total sector count <65536
185
        test    eax, eax
186
        jnz     @f
187
        mov     eax, [ebx+0x20]         ; total sector count
188
@@:
4273 clevermous 189
        cmp     dword [ebp+FAT.Length+4], 0
190
        jnz     @f
191
        cmp     eax, dword [ebp+FAT.Length]
192
        ja      .free_return0
193
@@:
3742 clevermous 194
        mov     dword [ebp+FAT.Length], eax
195
        and     dword [ebp+FAT.Length+4], 0
2643 clevermous 196
        sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
4273 clevermous 197
        jc      .free_return0
2643 clevermous 198
        xor     edx, edx
199
        div     [ebp+FAT.SECTORS_PER_CLUSTER]
200
        inc     eax
201
        mov     [ebp+FAT.LAST_CLUSTER], eax
202
        dec     eax                     ; cluster count
4273 clevermous 203
        jz      .free_return0
2643 clevermous 204
        mov     [ebp+FAT.fatStartScan], 2
6867 pathoswith 205
        cmp     eax, 0xfff5
2643 clevermous 206
        jb      .fat16
207
.fat32:
6868 pathoswith 208
        pusha
209
        lea     esi, [ebx+71]
210
        lea     edi, [ebp+FAT.volumeLabel]
211
        movsd
212
        movsd
213
        movsd
214
        popa
2643 clevermous 215
        mov     eax, [ebx+0x2c]         ; rootdir cluster
216
        mov     [ebp+FAT.ROOT_CLUSTER], eax
217
        movzx   eax, word [ebx+0x30]
218
        mov     [ebp+FAT.ADR_FSINFO], eax
219
        push    ebx
220
        add     ebx, 512
221
        call    fs_read32_sys
222
        test    eax, eax
223
        jnz     @f
224
        mov     eax, [ebx+0x1ec]
225
        cmp     eax, -1
2288 clevermous 226
        jz      @f
2643 clevermous 227
        mov     [ebp+FAT.fatStartScan], eax
2288 clevermous 228
@@:
2643 clevermous 229
        pop     ebx
230
        mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
231
        mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
232
        mov     [ebp+FAT.fatEND], 0x0FFFFFF8
233
        mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
234
        mov     al, 32
4273 clevermous 235
.fat_not_12_finalize:
2643 clevermous 236
        mov     [ebp+FAT.fs_type], al
4273 clevermous 237
; For FAT16 and FAT32, allocate 512 bytes for FAT cache.
238
        mov     eax, 512
239
        call    malloc
240
        test    eax, eax
241
        jz      .free_return0
242
        mov     [ebp+FAT.fat_cache_ptr], eax
2643 clevermous 243
        mov     eax, ebp
244
        pop     ebp
2288 clevermous 245
        ret
6867 pathoswith 246
 
2643 clevermous 247
.fat16:
6868 pathoswith 248
        pusha
249
        lea     esi, [ebx+43]
250
        lea     edi, [ebp+FAT.volumeLabel]
251
        movsd
252
        movsd
253
        movsd
254
        popa
255
        cmp     eax, 0xff5
256
        jb      .fat12
2643 clevermous 257
        and     [ebp+FAT.ROOT_CLUSTER], 0
258
        mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
259
        mov     [ebp+FAT.fatBAD], 0x0000FFF7
260
        mov     [ebp+FAT.fatEND], 0x0000FFF8
261
        mov     [ebp+FAT.fatMASK], 0x0000FFFF
262
        mov     al, 16
4273 clevermous 263
        jmp     .fat_not_12_finalize
6867 pathoswith 264
 
4273 clevermous 265
.fat12:
266
        and     [ebp+FAT.ROOT_CLUSTER], 0
267
        mov     [ebp+FAT.fatRESERVED], 0xFF6
268
        mov     [ebp+FAT.fatBAD], 0xFF7
269
        mov     [ebp+FAT.fatEND], 0xFFF
270
        mov     [ebp+FAT.fatMASK], 0xFFF
271
        mov     al, 12
2643 clevermous 272
        mov     [ebp+FAT.fs_type], al
4273 clevermous 273
; For FAT12, allocate&read data for entire table:
274
; calculate A = ALIGN_UP(NUM_CLUSTERS, 8),
275
; allocate ALIGN_UP(A*3/2, 512) bytes for FAT table plus A*2 bytes for unpacked data.
276
        mov     eax, [ebp+FAT.LAST_CLUSTER]
277
        and     eax, not 7
278
        add     eax, 8
279
        mov     edx, eax
280
        lea     eax, [eax*3]
281
        add     eax, 512*2-1
282
        shr     eax, 10
283
        shl     eax, 9
284
        lea     eax, [eax+edx*2]
285
        call    malloc
286
        test    eax, eax
287
        jz      .free_return0
288
; Read ALIGN_UP(NUM_CLUSTERS*3/2, 512) bytes.
289
        push    ebx
290
        mov     [ebp+FAT.fat_cache_ptr], eax
291
        mov     edx, [ebp+FAT.LAST_CLUSTER]
292
        lea     edx, [(edx+1)*3 + 512*2-1]
293
        shr     edx, 10
294
        xchg    eax, ebx
295
        xor     eax, eax
296
.read_fat:
297
        push    eax
298
        add     eax, [ebp+FAT.FAT_START]
299
        call    fs_read32_sys
300
        test    eax, eax
301
        pop     eax
302
        jz      @f
303
        mov     eax, [ebp+FAT.fat_cache_ptr]
304
        call    free
305
        pop     ebx
306
        jmp     .free_return0
6867 pathoswith 307
 
4273 clevermous 308
@@:
309
        add     ebx, 512
310
        inc     eax
311
        cmp     eax, edx
312
        jb      .read_fat
313
        mov     [ebp+FAT.fat12_unpacked_ptr], ebx
314
        pushad
315
        mov     esi, [ebp+FAT.fat_cache_ptr]
316
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
317
        mov     edx, [ebp+FAT.LAST_CLUSTER]
318
        and     edx, not 7
319
        lea     edx, [edi+(edx+8)*2]
320
        push    edx
6867 pathoswith 321
@@:
4273 clevermous 322
        mov     eax, dword [esi]
323
        mov     ebx, dword [esi+4]
324
        mov     ecx, dword [esi+8]
325
        mov     edx, ecx
6867 pathoswith 326
        shr     edx, 4
327
        shr     dx, 4
4273 clevermous 328
        xor     ch, ch
6867 pathoswith 329
        shld    ecx, ebx, 20
330
        shr     cx, 4
4273 clevermous 331
        shld    ebx, eax, 12
6867 pathoswith 332
        and     ebx, 0x0fffffff
333
        shr     bx, 4
4273 clevermous 334
        shl     eax, 4
6867 pathoswith 335
        and     eax, 0x0fffffff
336
        shr     ax, 4
4273 clevermous 337
        mov     dword [edi], eax
338
        mov     dword [edi+4], ebx
339
        mov     dword [edi+8], ecx
340
        mov     dword [edi+12], edx
341
        add     edi, 16
342
        add     esi, 12
343
        cmp     edi, [esp]
6867 pathoswith 344
        jnz     @b
4273 clevermous 345
        pop     eax
346
        popad
6867 pathoswith 347
        mov     eax, ebp
348
        pop     ebx ebp
4273 clevermous 349
        ret
350
 
6867 pathoswith 351
fat_free:
4273 clevermous 352
        push    eax
6867 pathoswith 353
        mov     eax, [eax+FAT.fat_cache_ptr]
354
        call    free
4273 clevermous 355
        pop     eax
6867 pathoswith 356
        jmp     free
4273 clevermous 357
 
358
iglobal
359
label fat_legal_chars byte
360
; 0 = not allowed
361
; 1 = allowed only in long names
362
; 3 = allowed
363
        times 32 db 0
364
;                 ! " # $ % & ' ( ) * + , - . /
365
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
366
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
367
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
368
;               @ A B C D E F G H I J K L M N O
369
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
370
;               P Q R S T U V W X Y Z [ \ ] ^ _
371
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
372
;               ` a b c d e f g h i j k l m n o
373
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
374
;               p q r s t u v w x y z { | } ~
375
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
376
endg
377
 
378
fat_name_is_legal:
6471 pathoswith 379
; in: esi -> UTF-8 name
380
; out: CF=1 -> legal
4273 clevermous 381
        push    esi
382
        xor     eax, eax
383
@@:
384
        lodsb
385
        test    al, al
6471 pathoswith 386
        js      @b
4273 clevermous 387
        test    [fat_legal_chars+eax], 1
388
        jnz     @b
6471 pathoswith 389
        test    al, al
390
        jnz     @f
391
        stc
392
@@:
4273 clevermous 393
        pop     esi
394
        ret
395
 
396
fat_next_short_name:
397
; in: edi->8+3 name
6867 pathoswith 398
; out: name corrected, CF=1 -> error
4273 clevermous 399
        pushad
400
        mov     ecx, 8
401
        mov     al, '~'
402
        std
403
        push    edi
404
        add     edi, 7
405
        repnz scasb
406
        pop     edi
407
        cld
408
        jz      .tilde
409
; tilde is not found, insert "~1" at end
410
        add     edi, 6
411
        cmp     word [edi], '  '
412
        jnz     .insert_tilde
413
@@:
414
        dec     edi
415
        cmp     byte [edi], ' '
416
        jz      @b
417
        inc     edi
418
.insert_tilde:
419
        mov     word [edi], '~1'
420
        popad
421
        clc
422
        ret
6867 pathoswith 423
 
4273 clevermous 424
.tilde:
425
        push    edi
426
        add     edi, 7
427
        xor     ecx, ecx
6867 pathoswith 428
@@: ; after tilde may be only digits and trailing spaces
4273 clevermous 429
        cmp     byte [edi], '~'
430
        jz      .break
431
        cmp     byte [edi], ' '
432
        jz      .space
433
        cmp     byte [edi], '9'
434
        jnz     .found
435
        dec     edi
436
        jmp     @b
6867 pathoswith 437
 
4273 clevermous 438
.space:
439
        dec     edi
440
        inc     ecx
441
        jmp     @b
6867 pathoswith 442
 
4273 clevermous 443
.found:
444
        inc     byte [edi]
445
        add     dword [esp], 8
446
        jmp     .zerorest
6867 pathoswith 447
 
4273 clevermous 448
.break:
449
        jecxz   .noplace
450
        inc     edi
451
        mov     al, '1'
452
@@:
453
        xchg    al, [edi]
454
        inc     edi
455
        cmp     al, ' '
456
        mov     al, '0'
457
        jnz     @b
458
.succ:
459
        pop     edi
460
        popad
461
        clc
462
        ret
6867 pathoswith 463
 
4273 clevermous 464
.noplace:
465
        dec     edi
466
        cmp     edi, [esp]
467
        jz      .err
468
        add     dword [esp], 8
469
        mov     word [edi], '~1'
470
        inc     edi
471
        inc     edi
472
@@:
473
        mov     byte [edi], '0'
474
.zerorest:
475
        inc     edi
476
        cmp     edi, [esp]
477
        jb      @b
478
        pop     edi
479
        popad
480
        ret
6867 pathoswith 481
 
4273 clevermous 482
.err:
483
        pop     edi
484
        popad
485
        stc
486
        ret
487
 
488
fat_gen_short_name:
6471 pathoswith 489
;   in:
490
; esi -> UTF-8 name
491
; edi -> buffer (8+3=11 chars)
4273 clevermous 492
        pushad
493
        mov     eax, '    '
494
        push    edi
495
        stosd
496
        stosd
497
        stosd
498
        pop     edi
499
        xor     eax, eax
500
        movi    ebx, 8
501
        lea     ecx, [edi+8]
502
.loop:
503
        lodsb
504
        test    al, al
6471 pathoswith 505
        js      .space
4273 clevermous 506
        jz      .done
6471 pathoswith 507
        test    [fat_legal_chars+eax], 2
4273 clevermous 508
        jz      .space
509
        cmp     al, '.'
510
        jz      .dot
511
        dec     bl
512
        jns     .store
6471 pathoswith 513
        inc     bl
4273 clevermous 514
.space:
515
        or      bh, 1
516
        jmp     .loop
6471 pathoswith 517
 
4273 clevermous 518
.store:
6471 pathoswith 519
        call    cp866toUpper
4273 clevermous 520
        stosb
521
        jmp     .loop
6471 pathoswith 522
 
4273 clevermous 523
.dot:
524
        test    bh, 2
525
        jz      .firstdot
526
        pop     ebx
527
        add     ebx, edi
528
        sub     ebx, ecx
529
        push    ebx
530
        cmp     ebx, ecx
531
        jb      @f
532
        pop     ebx
533
        push    ecx
534
@@:
535
        cmp     edi, ecx
536
        jbe     .skip
537
@@:
538
        dec     edi
539
        mov     al, [edi]
540
        dec     ebx
541
        mov     [ebx], al
542
        mov     byte [edi], ' '
543
        cmp     edi, ecx
544
        ja      @b
545
.skip:
546
        mov     bh, 3
547
        jmp     @f
6867 pathoswith 548
 
4273 clevermous 549
.firstdot:
550
        cmp     bl, 8
551
        jz      .space
552
        push    edi
553
        or      bh, 2
554
@@:
555
        mov     edi, ecx
556
        mov     bl, 3
557
        jmp     .loop
6867 pathoswith 558
 
4273 clevermous 559
.done:
560
        test    bh, 2
561
        jz      @f
562
        pop     edi
563
@@:
564
        lea     edi, [ecx-8]
565
        test    bh, 1
566
        jz      @f
567
        call    fat_next_short_name
568
@@:
569
        popad
570
        ret
571
 
2288 clevermous 572
set_FAT:
6867 pathoswith 573
; in: eax = cluster, edx = value to save
574
; out: edx = old value, CF=1 -> error
2288 clevermous 575
        push    eax ebx esi
576
        cmp     eax, 2
6867 pathoswith 577
        jc      .ret
578
        cmp     [ebp+FAT.LAST_CLUSTER], eax
579
        jc      .ret
4273 clevermous 580
        cmp     [ebp+FAT.fs_type], 12
6867 pathoswith 581
        je      .FAT12
2643 clevermous 582
        cmp     [ebp+FAT.fs_type], 16
6867 pathoswith 583
        je      @f
2288 clevermous 584
        add     eax, eax
6867 pathoswith 585
@@:
2288 clevermous 586
        add     eax, eax
587
        mov     esi, 511
6867 pathoswith 588
        and     esi, eax
589
        shr     eax, 9
2643 clevermous 590
        add     eax, [ebp+FAT.FAT_START]
4273 clevermous 591
        mov     ebx, [ebp+FAT.fat_cache_ptr]
6867 pathoswith 592
        cmp     eax, [ebp+FAT.fat_in_cache]
593
        je      .inCache
594
        cmp     [ebp+FAT.fat_change], 0
595
        je      @f
596
        call    write_fat_sector
597
        jc      .ret
598
@@:
599
        mov     [ebp+FAT.fat_in_cache], eax
2643 clevermous 600
        call    fs_read32_sys
601
        test    eax, eax
6867 pathoswith 602
        jne     .error
603
.inCache:
2643 clevermous 604
        cmp     [ebp+FAT.fs_type], 16
6867 pathoswith 605
        jne     .test32
2288 clevermous 606
        xchg    [ebx+esi], dx   ; save new value and get old value
6867 pathoswith 607
        jmp     .write
2288 clevermous 608
 
6867 pathoswith 609
.test32:
2643 clevermous 610
        mov     eax, [ebp+FAT.fatMASK]
2288 clevermous 611
        and     edx, eax
612
        xor     eax, -1         ; mask for high bits
613
        and     eax, [ebx+esi]  ; get high 4 bits
614
        or      eax, edx
615
        mov     edx, [ebx+esi]  ; get old value
616
        mov     [ebx+esi], eax  ; save new value
6867 pathoswith 617
.write:
618
        mov     [ebp+FAT.fat_change], 1
2643 clevermous 619
        and     edx, [ebp+FAT.fatMASK]
6867 pathoswith 620
.ret:
2288 clevermous 621
        pop     esi ebx eax
622
        ret
6867 pathoswith 623
 
624
.error:
2643 clevermous 625
        stc
6867 pathoswith 626
        jmp     .ret
2288 clevermous 627
 
6867 pathoswith 628
.FAT12:
4273 clevermous 629
        test    edx, 0xF000
6867 pathoswith 630
        jnz     .error
4273 clevermous 631
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
632
        xchg    [ebx+eax*2], dx
633
        mov     [ebp+FAT.fat_change], 1
6867 pathoswith 634
        jmp     .ret
2288 clevermous 635
 
636
get_FAT:
6867 pathoswith 637
; in: eax = cluster
638
; out: eax = next cluster, CF=1 -> error
2288 clevermous 639
        push    ebx esi
4273 clevermous 640
        cmp     [ebp+FAT.fs_type], 12
6867 pathoswith 641
        je      .FAT12
2643 clevermous 642
        cmp     [ebp+FAT.fs_type], 16
6867 pathoswith 643
        je      @f
2288 clevermous 644
        add     eax, eax
6867 pathoswith 645
@@:
2288 clevermous 646
        add     eax, eax
647
        mov     esi, 511
6867 pathoswith 648
        and     esi, eax
649
        shr     eax, 9
2643 clevermous 650
        add     eax, [ebp+FAT.FAT_START]
4273 clevermous 651
        mov     ebx, [ebp+FAT.fat_cache_ptr]
6867 pathoswith 652
        cmp     eax, [ebp+FAT.fat_in_cache]
653
        je      .inCache
654
        cmp     [ebp+FAT.fat_change], 0
655
        je      @f
656
        call    write_fat_sector
657
        jc      .ret
658
@@:
2643 clevermous 659
        mov     [ebp+FAT.fat_in_cache], eax
660
        call    fs_read32_sys
661
        test    eax, eax
6867 pathoswith 662
        jnz     .error
663
.inCache:
2288 clevermous 664
        mov     eax, [ebx+esi]
2643 clevermous 665
        and     eax, [ebp+FAT.fatMASK]
6867 pathoswith 666
.ret:
2288 clevermous 667
        pop     esi ebx
668
        ret
6867 pathoswith 669
 
670
.error:
2643 clevermous 671
        stc
6867 pathoswith 672
        jmp     .ret
2288 clevermous 673
 
6867 pathoswith 674
.FAT12:
4273 clevermous 675
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
676
        movzx   eax, word [ebx+eax*2]
6867 pathoswith 677
        jmp     .ret
2288 clevermous 678
 
679
get_free_FAT:
6867 pathoswith 680
; out: eax = number of first free cluster, CF=1 -> disk full
2288 clevermous 681
        push    ecx
6867 pathoswith 682
        mov     ecx, [ebp+FAT.LAST_CLUSTER]
2643 clevermous 683
        mov     eax, [ebp+FAT.fatStartScan]
4273 clevermous 684
        cmp     [ebp+FAT.fs_type], 12
685
        jz      get_free_FAT12
686
        dec     ecx
2288 clevermous 687
        cmp     eax, 2
6867 pathoswith 688
        jb      .reset
689
.test:
690
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
691
        jbe     .inRange
692
.reset:
2288 clevermous 693
        mov     eax, 2
6867 pathoswith 694
.inRange:
2288 clevermous 695
        push    eax
6867 pathoswith 696
        call    get_FAT
697
        jc      @f
698
        test    eax, eax
2288 clevermous 699
        pop     eax
6867 pathoswith 700
        je      .found
701
        inc     eax
702
        dec     ecx
703
        jnz     .test
704
.notFound:
705
        pop     ecx
2288 clevermous 706
        stc
707
        ret
708
 
6867 pathoswith 709
@@:
2643 clevermous 710
        pop     eax
6867 pathoswith 711
        jmp     .notFound
2643 clevermous 712
 
6867 pathoswith 713
.found:
2288 clevermous 714
        lea     ecx, [eax+1]
2643 clevermous 715
        mov     [ebp+FAT.fatStartScan], ecx
2288 clevermous 716
        pop     ecx
717
        clc
718
        ret
719
 
4273 clevermous 720
get_free_FAT12:
721
        push    edx edi
722
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
723
        cmp     eax, 2
724
        jb      .reset
725
        cmp     eax, ecx
726
        jbe     @f
727
.reset:
728
        mov     eax, 2
729
@@:
730
        mov     edx, eax
731
        lea     edi, [edi+eax*2]
732
        sub     ecx, eax
733
        inc     ecx
734
        xor     eax, eax
735
        repnz scasw
736
        jz      .found
737
        cmp     edx, 2
738
        jz      .notfound
739
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
740
        lea     ecx, [edx-2]
741
        repnz scasw
742
        jnz     .notfound
743
.found:
744
        sub     edi, [ebp+FAT.fat12_unpacked_ptr]
745
        shr     edi, 1
746
        mov     [ebp+FAT.fatStartScan], edi
747
        lea     eax, [edi-1]
6867 pathoswith 748
@@:
4273 clevermous 749
        pop     edi edx ecx
750
        ret
6867 pathoswith 751
 
4273 clevermous 752
.notfound:
753
        stc
6867 pathoswith 754
        jmp     @b
2288 clevermous 755
 
756
write_fat_sector:
757
        push    eax ebx ecx
2643 clevermous 758
        mov     [ebp+FAT.fat_change], 0
759
        mov     eax, [ebp+FAT.fat_in_cache]
2288 clevermous 760
        cmp     eax, -1
6867 pathoswith 761
        jz      @f
4273 clevermous 762
        mov     ebx, [ebp+FAT.fat_cache_ptr]
2643 clevermous 763
        mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
6867 pathoswith 764
.write_next_fat:
2643 clevermous 765
        push    eax
766
        call    fs_write32_sys
767
        test    eax, eax
768
        pop     eax
6867 pathoswith 769
        jnz     @f
2643 clevermous 770
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
2288 clevermous 771
        dec     ecx
6867 pathoswith 772
        jnz     .write_next_fat
773
@@:
2288 clevermous 774
        pop     ecx ebx eax
775
        ret
776
 
777
get_date_for_file:
6867 pathoswith 778
;   out in ax:
779
; bits 0-4 = day
780
; bits 5-8 = month
781
; bits 9-15 = count of years from 1980
782
        mov     al, 7
783
        call    fsReadCMOS
2288 clevermous 784
        ror     eax, 5
6867 pathoswith 785
        mov     al, 8
786
        call    fsReadCMOS
2288 clevermous 787
        ror     eax, 4
6867 pathoswith 788
        mov     al, 9
789
        call    fsReadCMOS
790
        add     ax, 20
791
        rol     eax, 9
2288 clevermous 792
        ret
793
 
794
get_time_for_file:
6867 pathoswith 795
;   out in ax:
796
; bits 0-4 = second (the low bit is lost)
797
; bits 5-10 = minute
798
; bits 11-15 = hour
799
        mov     al, 0
800
        call    fsReadCMOS
2288 clevermous 801
        ror     eax, 6
6867 pathoswith 802
        mov     al, 2
803
        call    fsReadCMOS
2288 clevermous 804
        ror     eax, 6
6867 pathoswith 805
        mov     al, 4
806
        call    fsReadCMOS
2288 clevermous 807
        rol     eax, 11
808
        ret
809
 
810
add_disk_free_space:
6867 pathoswith 811
; in: ecx = cluster count (signed)
812
        test    ecx, ecx
813
        je      .ret
814
        cmp     [ebp+FAT.fs_type], 32
815
        jne     .ret
2288 clevermous 816
        push    eax ebx
2643 clevermous 817
        mov     eax, [ebp+FAT.ADR_FSINFO]
818
        lea     ebx, [ebp+FAT.fsinfo_buffer]
819
        call    fs_read32_sys
820
        test    eax, eax
6867 pathoswith 821
        jnz     @f
822
        cmp     dword [ebx+0x1fc], 0xaa550000   ; check sector id
823
        jne     @f
2288 clevermous 824
        add     [ebx+0x1e8], ecx
2643 clevermous 825
        push    [ebp+FAT.fatStartScan]
2288 clevermous 826
        pop     dword [ebx+0x1ec]
2643 clevermous 827
        mov     eax, [ebp+FAT.ADR_FSINFO]
828
        call    fs_write32_sys
6867 pathoswith 829
@@:
2288 clevermous 830
        pop     ebx eax
6867 pathoswith 831
.ret:
2288 clevermous 832
        ret
833
 
834
clear_cluster_chain:
6867 pathoswith 835
; in: eax = first cluster
2288 clevermous 836
        push    eax ecx edx
837
        xor     ecx, ecx        ; cluster count
6867 pathoswith 838
@@:
839
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
840
        ja      @f
841
        cmp     eax, 2
842
        jb      @f
843
        cmp     eax, [ebp+FAT.ROOT_CLUSTER]
844
        jz      @f
2288 clevermous 845
        xor     edx, edx
6867 pathoswith 846
        call    set_FAT
847
        jc      .ret
848
        inc     ecx
849
        mov     eax, edx
850
        jmp     @b
2288 clevermous 851
 
6867 pathoswith 852
@@:
853
        call    add_disk_free_space
2643 clevermous 854
        clc
6867 pathoswith 855
.ret:
2288 clevermous 856
        pop     edx ecx eax
857
        ret
858
 
859
update_disk:
6867 pathoswith 860
        cmp     [ebp+FAT.fat_change], 0
861
        jz      .noChange
4273 clevermous 862
        cmp     [ebp+FAT.fs_type], 12
863
        jz      .fat12
2288 clevermous 864
        call    write_fat_sector
6867 pathoswith 865
        jc      .ret
866
.noChange:
2643 clevermous 867
        mov     esi, [ebp+PARTITION.Disk]
868
        call    disk_sync
6867 pathoswith 869
.ret:
2288 clevermous 870
        ret
871
 
6867 pathoswith 872
.fat12:
873
        mov     esi, [ebp+FAT.fat12_unpacked_ptr]
874
        mov     edi, [ebp+FAT.fat_cache_ptr]
875
        mov     edx, [ebp+FAT.LAST_CLUSTER]
876
        and     edx, not 7
877
        lea     edx, [esi+(edx+8)*2]
878
@@:
879
        mov     eax, dword [esi]
880
        mov     ebx, dword [esi+4]
881
        shl     ax, 4
882
        shl     eax, 4
883
        shl     bx, 4
884
        shr     ebx, 4
885
        shrd    eax, ebx, 8
886
        shr     ebx, 8
887
        mov     dword [edi], eax
888
        mov     word [edi+4], bx
889
        add     edi, 6
890
        add     esi, 8
891
        cmp     esi, edx
892
        jb      @b
893
        mov     esi, [ebp+FAT.NUMBER_OF_FATS]
894
        mov     edx, [ebp+FAT.LAST_CLUSTER]
895
        lea     edx, [(edx+1)*3 + 512*2-1]
896
        shr     edx, 10
897
        push    [ebp+FAT.FAT_START]
898
.write_fats:
899
        xor     eax, eax
900
        mov     ebx, [ebp+FAT.fat_cache_ptr]
901
.loop1:
902
        push    eax
903
        add     eax, [esp+4]
904
        call    fs_write32_sys
905
        test    eax, eax
906
        pop     eax
907
        jnz     @f
908
        add     ebx, 512
909
        inc     eax
910
        cmp     eax, edx
911
        jb      .loop1
912
        pop     eax
913
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
914
        push    eax
915
        dec     esi
916
        jnz     .write_fats
917
@@:
918
        pop     eax
919
        mov     [ebp+FAT.fat_change], 0
920
        jmp     .noChange
921
 
2643 clevermous 922
fat_lock:
923
        lea     ecx, [ebp+FAT.Lock]
924
        jmp     mutex_lock
6867 pathoswith 925
 
2643 clevermous 926
fat_unlock:
927
        lea     ecx, [ebp+FAT.Lock]
928
        jmp     mutex_unlock
2288 clevermous 929
 
4273 clevermous 930
fat_get_name:
6868 pathoswith 931
; in: edi -> FAT entry, esi -> buffer for UTF-16 name
932
; out: CF=1 -> no valid entry
4273 clevermous 933
        cmp     byte [edi], 0
934
        jz      .no
935
        cmp     byte [edi], 0xE5
6471 pathoswith 936
        jz      .no
4273 clevermous 937
        cmp     byte [edi+11], 0xF
938
        jz      .longname
6868 pathoswith 939
        push    edi
940
        xchg    esi, edi
941
        test    byte [esi+11], 8
942
        jnz     .label
943
        pushd   ecx 8
944
        pop     ecx
945
        xor     eax, eax
4273 clevermous 946
@@:
6471 pathoswith 947
        lodsb
948
        stosw
4273 clevermous 949
        loop    @b
6471 pathoswith 950
        mov     cl, 8
4273 clevermous 951
@@:
6471 pathoswith 952
        cmp     word [edi-2], ' '
4273 clevermous 953
        jnz     @f
6471 pathoswith 954
        sub     edi, 2
4273 clevermous 955
        loop    @b
956
@@:
6471 pathoswith 957
        mov     word [edi], '.'
958
        add     edi, 2
959
        mov     cl, 3
4273 clevermous 960
@@:
6471 pathoswith 961
        lodsb
962
        stosw
4273 clevermous 963
        loop    @b
6471 pathoswith 964
        mov     cl, 3
4273 clevermous 965
@@:
6471 pathoswith 966
        cmp     word [edi-2], ' '
4273 clevermous 967
        jnz     @f
6471 pathoswith 968
        sub     edi, 2
4273 clevermous 969
        loop    @b
6471 pathoswith 970
        sub     edi, 2
4273 clevermous 971
@@:
6471 pathoswith 972
        and     word [edi], 0   ; CF=0
6868 pathoswith 973
        pop     ecx edi
4273 clevermous 974
        ret
6471 pathoswith 975
 
6868 pathoswith 976
.label:
977
        lea     edi, [ebp+FAT.volumeLabel]
978
        movsd
979
        movsd
980
        movsd
981
        pop     edi
6471 pathoswith 982
.no:
983
        stc
984
        ret
985
 
4273 clevermous 986
.longname:
987
        mov     al, byte [edi]
988
        and     eax, 0x3F
989
        dec     eax
990
        cmp     al, 20
991
        jae     .no     ; ignore invalid entries
6868 pathoswith 992
        mov     word [esi+260*2], 0     ; force null-terminating for orphans
4273 clevermous 993
        imul    eax, 13*2
994
        test    byte [edi], 0x40
995
        jz      @f
6868 pathoswith 996
        mov     word [esi+eax+13*2], 0
6471 pathoswith 997
@@: ; copy name (13 chars in UTF-16)
6868 pathoswith 998
        push    edi
999
        inc     edi
1000
        add     esi, eax
1001
        xchg    esi, edi
6471 pathoswith 1002
        movsd
1003
        movsd
6868 pathoswith 1004
        movsw
1005
        add     esi, 3
6471 pathoswith 1006
        movsd
1007
        movsd
1008
        movsd
1009
        add     esi, 2
1010
        movsd
6868 pathoswith 1011
        pop     edi
6471 pathoswith 1012
        test    eax, eax
1013
        jnz     .no ; if this is not first entry, more processing required
4273 clevermous 1014
        ret
1015
 
6868 pathoswith 1016
fat_find_lfn:
1017
;   in:
1018
; esi -> path in UTF-8
1019
; parameters in the stack
6471 pathoswith 1020
;   out:
6868 pathoswith 1021
; esi -> next name in the path
1022
; edi -> direntry
1023
; CF=1 -> file not found, eax = error code
1024
        lea     eax, [esp+12]
1025
        call    dword [eax-4]
1026
        jc      .reterr
1027
        sub     esp, 262*2      ; reserve place for LFN
1028
.l1:
1029
        push    esi
1030
        lea     esi, [esp+4]
1031
        call    fat_get_name
1032
        pop     esi
1033
        jc      .no
1034
        push    edi esi
1035
        lea     edi, [esp+8]
6471 pathoswith 1036
@@:
1037
        call    utf8to16
1038
        call    utf16toUpper
1039
        mov     edx, eax
6868 pathoswith 1040
        mov     ax, [edi]
6471 pathoswith 1041
        call    utf16toUpper
1042
        cmp     ax, dx
4273 clevermous 1043
        jnz     .done
6868 pathoswith 1044
        add     edi, 2
6471 pathoswith 1045
        test    ax, ax
1046
        jnz     @b
4273 clevermous 1047
        dec     esi
6868 pathoswith 1048
        pop     eax edi
1049
.found:
1050
        add     esp, 262*2
1051
; if this is LFN entry, advance to true entry
1052
        cmp     byte [edi+11], 0xF
1053
        jnz     @f
1054
        lea     eax, [esp+12]
1055
        call    dword[eax-8]
1056
        jc      .reterr
1057
@@:
1058
        xor     eax, eax
4273 clevermous 1059
        ret
6471 pathoswith 1060
 
4273 clevermous 1061
.done:
6471 pathoswith 1062
        cmp     dx, '/'
4273 clevermous 1063
        jnz     @f
6471 pathoswith 1064
        test    ax, ax
4273 clevermous 1065
        jnz     @f
6471 pathoswith 1066
        mov     [esp], esi
4273 clevermous 1067
@@:
6868 pathoswith 1068
        pop     esi edi
4273 clevermous 1069
        jz      .found
6868 pathoswith 1070
.no:
1071
        lea     eax, [esp+262*2+12]
1072
        call    dword[eax-8]
4273 clevermous 1073
        jnc     .l1
6471 pathoswith 1074
        add     esp, 262*2
4273 clevermous 1075
.reterr:
1076
        stc
1077
        ret
6471 pathoswith 1078
 
4273 clevermous 1079
fat_time_to_bdfe:
1080
; in: eax=FAT time
1081
; out: eax=BDFE time
1082
        push    ecx edx
1083
        mov     ecx, eax
1084
        mov     edx, eax
1085
        shr     eax, 11
1086
        shl     eax, 16 ; hours
1087
        and     edx, 0x1F
1088
        add     edx, edx
1089
        mov     al, dl  ; seconds
1090
        shr     ecx, 5
1091
        and     ecx, 0x3F
1092
        mov     ah, cl  ; minutes
1093
        pop     edx ecx
1094
        ret
1095
 
1096
fat_date_to_bdfe:
1097
        push    ecx edx
1098
        mov     ecx, eax
1099
        mov     edx, eax
1100
        shr     eax, 9
1101
        add     ax, 1980
1102
        shl     eax, 16 ; year
1103
        and     edx, 0x1F
1104
        mov     al, dl  ; day
1105
        shr     ecx, 5
1106
        and     ecx, 0xF
1107
        mov     ah, cl  ; month
1108
        pop     edx ecx
1109
        ret
1110
 
1111
bdfe_to_fat_time:
1112
        push    edx
1113
        mov     edx, eax
1114
        shr     eax, 16
1115
        and     dh, 0x3F
1116
        shl     eax, 6
1117
        or      al, dh
1118
        shr     dl, 1
1119
        and     dl, 0x1F
1120
        shl     eax, 5
1121
        or      al, dl
1122
        pop     edx
1123
        ret
1124
 
1125
bdfe_to_fat_date:
1126
        push    edx
1127
        mov     edx, eax
1128
        shr     eax, 16
1129
        sub     ax, 1980
1130
        and     dh, 0xF
1131
        shl     eax, 4
1132
        or      al, dh
1133
        and     dl, 0x1F
1134
        shl     eax, 5
1135
        or      al, dl
1136
        pop     edx
1137
        ret
1138
 
1139
fat_entry_to_bdfe:
1140
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
1141
        mov     eax, [ebp-4]
6471 pathoswith 1142
        mov     [esi+4], eax    ; cp866/UNICODE name
4273 clevermous 1143
fat_entry_to_bdfe2:
1144
        movzx   eax, byte [edi+11]
1145
        mov     [esi], eax      ; attributes
1146
        movzx   eax, word [edi+14]
1147
        call    fat_time_to_bdfe
1148
        mov     [esi+8], eax    ; creation time
1149
        movzx   eax, word [edi+16]
1150
        call    fat_date_to_bdfe
1151
        mov     [esi+12], eax   ; creation date
1152
        and     dword [esi+16], 0       ; last access time is not supported on FAT
1153
        movzx   eax, word [edi+18]
1154
        call    fat_date_to_bdfe
1155
        mov     [esi+20], eax   ; last access date
1156
        movzx   eax, word [edi+22]
1157
        call    fat_time_to_bdfe
1158
        mov     [esi+24], eax   ; last write time
1159
        movzx   eax, word [edi+24]
1160
        call    fat_date_to_bdfe
1161
        mov     [esi+28], eax   ; last write date
1162
        mov     eax, [edi+28]
1163
        mov     [esi+32], eax   ; file size (low dword)
1164
        xor     eax, eax
1165
        mov     [esi+36], eax   ; file size (high dword)
1166
        test    ebp, ebp
1167
        jz      .ret
6576 pathoswith 1168
        add     esi, 40
1169
        push    edi esi
1170
        mov     edi, esi
4273 clevermous 1171
        mov     esi, ebp
6798 pathoswith 1172
        cmp     byte [ebp-4], 2
1173
        jz      .utf16
1174
        cmp     byte [ebp-4], 3
1175
        jz      .utf8
1176
@@:
6576 pathoswith 1177
        lodsw
6798 pathoswith 1178
        call    uni2ansi_char
1179
        stosb
1180
        test    al, al
1181
        jnz     @b
6576 pathoswith 1182
        pop     esi edi
6798 pathoswith 1183
        add     esi, 264
4273 clevermous 1184
.ret:
1185
        ret
6471 pathoswith 1186
 
6798 pathoswith 1187
.utf8:
1188
        push    ecx
1189
        mov     ecx, 519
1190
        call    UTF16to8_string
1191
        pop     ecx
1192
        jmp     @f
1193
 
1194
.utf16:
6471 pathoswith 1195
        lodsw
6798 pathoswith 1196
        stosw
1197
        test    eax, eax
1198
        jnz     .utf16
1199
@@:
6576 pathoswith 1200
        pop     esi edi
6798 pathoswith 1201
        add     esi, 520
6576 pathoswith 1202
        ret
4273 clevermous 1203
 
1204
bdfe_to_fat_entry:
1205
; convert BDFE at edx to FAT entry at edi
1206
; destroys eax
1207
; attributes byte
1208
        test    byte [edi+11], 8        ; volume label?
1209
        jnz     @f
1210
        mov     al, [edx]
1211
        and     al, 0x27
1212
        and     byte [edi+11], 0x10
1213
        or      byte [edi+11], al
1214
@@:
1215
        mov     eax, [edx+8]
1216
        call    bdfe_to_fat_time
1217
        mov     [edi+14], ax            ; creation time
1218
        mov     eax, [edx+12]
1219
        call    bdfe_to_fat_date
1220
        mov     [edi+16], ax            ; creation date
1221
        mov     eax, [edx+20]
1222
        call    bdfe_to_fat_date
1223
        mov     [edi+18], ax            ; last access date
1224
        mov     eax, [edx+24]
1225
        call    bdfe_to_fat_time
1226
        mov     [edi+22], ax            ; last write time
1227
        mov     eax, [edx+28]
1228
        call    bdfe_to_fat_date
1229
        mov     [edi+24], ax            ; last write date
1230
        ret
1231
 
2288 clevermous 1232
hd_find_lfn:
6471 pathoswith 1233
; in: esi -> path string in UTF-8
2643 clevermous 1234
; out: CF=1 - file not found, eax=error code
2288 clevermous 1235
;      else CF=0 and edi->direntry, eax=sector
1236
        push    esi edi
1237
        push    0
1238
        push    0
4273 clevermous 1239
        push    fat1x_root_first
1240
        push    fat1x_root_next
2643 clevermous 1241
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
1242
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1243
        jz      .fat32
1244
.loop:
4273 clevermous 1245
        and     [ebp+FAT.longname_sec1], 0
1246
        and     [ebp+FAT.longname_sec2], 0
2288 clevermous 1247
        call    fat_find_lfn
1248
        jc      .notfound
1249
        cmp     byte [esi], 0
1250
        jz      .found
1251
        test    byte [edi+11], 10h
1252
        jz      .notfound
1253
        and     dword [esp+12], 0
1254
        mov     eax, [edi+20-2]
1255
        mov     ax, [edi+26]    ; cluster
1256
.fat32:
1257
        mov     [esp+8], eax
1258
        mov     dword [esp+4], fat_notroot_first
1259
        mov     dword [esp], fat_notroot_next
1260
        jmp     .loop
6468 pathoswith 1261
 
2288 clevermous 1262
.notfound:
1263
        add     esp, 16
1264
        pop     edi esi
1265
        stc
6468 pathoswith 1266
        ret
1267
 
2288 clevermous 1268
.found:
1269
        lea     eax, [esp+8]
1270
        cmp     dword [eax], 0
1271
        jz      .root
1272
        call    fat_get_sector
1273
        jmp     .cmn
6468 pathoswith 1274
 
2288 clevermous 1275
.root:
1276
        mov     eax, [eax+4]
2643 clevermous 1277
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 1278
.cmn:
1279
        add     esp, 20         ; CF=0
1280
        pop     esi
6468 pathoswith 1281
        ret
2288 clevermous 1282
 
1283
;----------------------------------------------------------------
2643 clevermous 1284
fat_Read:
1285
        call    fat_lock
6468 pathoswith 1286
        call    hd_find_lfn
6845 pathoswith 1287
        jc      .notFound
5578 Pathoswith 1288
        test    byte [edi+11], 0x10     ; do not allow read directories
2288 clevermous 1289
        jnz     .noaccess
2643 clevermous 1290
        cmp     dword [ebx+8], 0
6845 pathoswith 1291
        jnz     .endOfFile
5578 Pathoswith 1292
        mov     edx, [ebx+4]    ; file offset
2643 clevermous 1293
        mov     ecx, [ebx+12]   ; size
5578 Pathoswith 1294
        mov     ebx, [ebx+16]   ; buffer
1295
        push    ebx
2288 clevermous 1296
        push    0
6037 pathoswith 1297
        test    ecx, ecx
1298
        jz      .done
2288 clevermous 1299
        mov     eax, [edi+28]
5578 Pathoswith 1300
        sub     eax, edx
1301
        jb      .fileEnd
2288 clevermous 1302
        cmp     eax, ecx
1303
        jae     @f
1304
        mov     ecx, eax
1305
        mov     byte [esp], 6
1306
@@:
1307
        mov     eax, [edi+20-2]
1308
        mov     ax, [edi+26]
5578 Pathoswith 1309
; now eax=cluster, ebx=buffer for data, ecx=count, edx=position
1310
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1311
        shl     edi, 9
1312
@@:
2643 clevermous 1313
        cmp     eax, 2
5578 Pathoswith 1314
        jb      .fileEnd
2643 clevermous 1315
        cmp     eax, [ebp+FAT.fatRESERVED]
5578 Pathoswith 1316
        jae     .fileEnd
1317
        sub     edx, edi
1318
        jc      @f
1319
        call    get_FAT
1320
        jc      .noaccess2
1321
        jmp     @b
6845 pathoswith 1322
 
1323
.notFound:
1324
        push    eax
1325
        jmp     .ret
1326
 
1327
.noaccess:
1328
        push    ERROR_ACCESS_DENIED
1329
        jmp     .ret
1330
 
1331
.endOfFile:
1332
        push    ERROR_END_OF_FILE
1333
.ret:
1334
        call    fat_unlock
6867 pathoswith 1335
        pop     eax
6845 pathoswith 1336
        xor     ebx, ebx
1337
        ret
1338
 
5578 Pathoswith 1339
@@:
1340
        mov     esi, eax
2288 clevermous 1341
        dec     eax
1342
        dec     eax
5578 Pathoswith 1343
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2643 clevermous 1344
        add     eax, [ebp+FAT.DATA_START]
5578 Pathoswith 1345
        add     edx, edi
1346
        jz      .alignedCluster
1347
        mov     edi, edx
1348
        shr     edi, 9
1349
        add     eax, edi
1350
        and     edx, 511
5840 pathoswith 1351
        cmp     ecx, 512
1352
        jc      .sectorPiece
1353
        test    edx, edx
5578 Pathoswith 1354
        jz      .alignedSector
1355
.sectorPiece:
2643 clevermous 1356
        push    eax ebx
1357
        lea     ebx, [ebp+FAT.buffer]
1358
        call    fs_read32_app
1359
        test    eax, eax
2288 clevermous 1360
        mov     eax, ebx
1361
        pop     ebx
5578 Pathoswith 1362
        jne     .noaccess3
1363
        add     eax, edx
2288 clevermous 1364
        push    ecx
5578 Pathoswith 1365
        add     ecx, edx
2288 clevermous 1366
        cmp     ecx, 512
1367
        jbe     @f
1368
        mov     ecx, 512
1369
@@:
5578 Pathoswith 1370
        sub     ecx, edx
2288 clevermous 1371
        call    memmove
1372
        sub     [esp], ecx
5578 Pathoswith 1373
        add     ebx, ecx
1374
        pop     ecx eax
1375
        xor     edx, edx
1376
        inc     edi
2288 clevermous 1377
        inc     eax
5578 Pathoswith 1378
        test    ecx, ecx
1379
        jz      .done
1380
.alignedSector:
1381
        shl     edi, 9
1382
        add     ecx, edi
1383
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1384
        shl     edi, 9
1385
.alignedCluster:
1386
        cmp     ecx, 512
1387
        jc      .sectorPiece
1388
        mov     edx, eax
1389
        mov     eax, esi
1390
@@:
1391
        sub     ecx, edi
1392
        jbe     .readEnd
2288 clevermous 1393
        call    get_FAT
5578 Pathoswith 1394
        jc      .noaccess4
1395
        cmp     eax, 2
1396
        jb      .fileEnd2
1397
        cmp     eax, [ebp+FAT.fatRESERVED]
1398
        jae     .fileEnd2
1399
        inc     esi
1400
        cmp     eax, esi
1401
        jz      @b
1402
.fragmentEnd:
1403
        xchg    eax, esi
1404
        dec     eax
1405
        dec     eax
1406
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1407
        add     eax, [ebp+FAT.DATA_START]
1408
        push    ecx
1409
        mov     ecx, eax
5840 pathoswith 1410
        mov     eax, esi
1411
        dec     eax
1412
        dec     eax
1413
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1414
        add     eax, [ebp+FAT.DATA_START]
1415
        push    eax
1416
.readFragment:
1417
        sub     ecx, edx
5578 Pathoswith 1418
        mov     eax, edx
1419
        xor     edx, edx
1420
        call    fs_read64_app
1421
        shl     ecx, 9
1422
        add     ebx, ecx
1423
        test    eax, eax
2288 clevermous 1424
        pop     eax
5578 Pathoswith 1425
        jnz     .noaccess3
1426
        pop     ecx
1427
        xor     edx, edx
6036 pathoswith 1428
        jecxz   .done
5578 Pathoswith 1429
        jmp     .alignedCluster
6845 pathoswith 1430
 
5578 Pathoswith 1431
.readEnd:
1432
        add     ecx, edi
1433
        mov     edi, ecx
1434
        and     ecx, 511
1435
        shr     edi, 9
1436
        dec     eax
1437
        dec     eax
1438
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1439
        add     eax, [ebp+FAT.DATA_START]
1440
        add     eax, edi
5840 pathoswith 1441
        push    ecx
1442
        push    eax
1443
        mov     ecx, eax
5578 Pathoswith 1444
        jmp     .readFragment
6845 pathoswith 1445
 
5578 Pathoswith 1446
.noaccess3:
2288 clevermous 1447
        pop     eax
5578 Pathoswith 1448
.noaccess2:
1449
        mov     byte [esp], ERROR_DEVICE
2288 clevermous 1450
.done:
2643 clevermous 1451
        call    fat_unlock
6867 pathoswith 1452
        pop     eax edx
2288 clevermous 1453
        sub     ebx, edx
1454
        ret
6845 pathoswith 1455
 
5578 Pathoswith 1456
.fileEnd:
1457
        mov     byte [esp], ERROR_END_OF_FILE
1458
        jmp     .done
6845 pathoswith 1459
 
5578 Pathoswith 1460
.noaccess4:
1461
        mov     byte [esp], ERROR_DEVICE
1462
        jmp     @f
6845 pathoswith 1463
 
5578 Pathoswith 1464
.fileEnd2:
1465
        mov     byte [esp], ERROR_END_OF_FILE
1466
@@:
1467
        inc     esi
1468
        xor     ecx, ecx
1469
        jmp     .fragmentEnd
2288 clevermous 1470
 
1471
;----------------------------------------------------------------
2643 clevermous 1472
fat_ReadFolder:
1473
        call    fat_lock
1474
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
2288 clevermous 1475
        cmp     byte [esi], 0
1476
        jz      .doit
6468 pathoswith 1477
        call    hd_find_lfn
6867 pathoswith 1478
        jc      .error
2288 clevermous 1479
        test    byte [edi+11], 0x10     ; do not allow read files
6867 pathoswith 1480
        jz      .accessDenied
2288 clevermous 1481
        mov     eax, [edi+20-2]
1482
        mov     ax, [edi+26]    ; eax=cluster
1483
.doit:
1484
        sub     esp, 262*2      ; reserve space for LFN
6471 pathoswith 1485
        push    dword [ebx+8]   ; cp866/UNICODE name
2643 clevermous 1486
        mov     edx, [ebx+16]   ; pointer to buffer
2288 clevermous 1487
; init header
2643 clevermous 1488
        push    eax
2288 clevermous 1489
        mov     edi, edx
1490
        mov     ecx, 32/4
1491
        xor     eax, eax
1492
        rep stosd
2643 clevermous 1493
        pop     eax
2288 clevermous 1494
        mov     byte [edx], 1   ; version
1495
        mov     esi, edi        ; esi points to BDFE
2643 clevermous 1496
        mov     ecx, [ebx+12]   ; number of blocks to read
1497
        mov     ebx, [ebx+4]    ; index of the first block
2288 clevermous 1498
.new_cluster:
2643 clevermous 1499
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 1500
        test    eax, eax
1501
        jnz     @f
2643 clevermous 1502
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1503
        jz      .notfound
2643 clevermous 1504
        mov     eax, [ebp+FAT.ROOT_START]
1505
        push    [ebp+FAT.ROOT_SECTORS]
2288 clevermous 1506
        push    ebx
1507
        jmp     .new_sector
6867 pathoswith 1508
 
2288 clevermous 1509
@@:
1510
        dec     eax
1511
        dec     eax
2643 clevermous 1512
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1513
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
1514
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1515
        push    ebx
1516
.new_sector:
2643 clevermous 1517
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 1518
        mov     edi, ebx
2643 clevermous 1519
        push    eax
1520
        call    fs_read32_sys
1521
        test    eax, eax
1522
        pop     eax
2288 clevermous 1523
        jnz     .notfound2
1524
        add     ebx, 512
1525
        push    eax
1526
.l1:
6868 pathoswith 1527
        push    esi
1528
        lea     esi, [esp+20]
2288 clevermous 1529
        call    fat_get_name
6868 pathoswith 1530
        pop     esi
2288 clevermous 1531
        jc      .l2
1532
        cmp     byte [edi+11], 0xF
1533
        jnz     .do_bdfe
1534
        add     edi, 0x20
1535
        cmp     edi, ebx
1536
        jb      .do_bdfe
1537
        pop     eax
1538
        inc     eax
1539
        dec     dword [esp+4]
1540
        jnz     @f
2643 clevermous 1541
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 1542
        test    eax, eax
1543
        jz      .done
1544
        call    get_FAT
2643 clevermous 1545
        jc      .notfound2
2288 clevermous 1546
        cmp     eax, 2
1547
        jb      .done
2643 clevermous 1548
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1549
        jae     .done
1550
        push    eax
2643 clevermous 1551
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1552
        mov     [esp+8], eax
1553
        pop     eax
2643 clevermous 1554
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 1555
        dec     eax
1556
        dec     eax
2643 clevermous 1557
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1558
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1559
@@:
2643 clevermous 1560
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 1561
        mov     edi, ebx
2643 clevermous 1562
        push    eax
1563
        call    fs_read32_sys
1564
        test    eax, eax
1565
        pop     eax
2288 clevermous 1566
        jnz     .notfound2
1567
        add     ebx, 512
1568
        push    eax
1569
.do_bdfe:
1570
        inc     dword [edx+8]   ; new file found
1571
        dec     dword [esp+4]
1572
        jns     .l2
1573
        dec     ecx
1574
        js      .l2
1575
        inc     dword [edx+4]   ; new file block copied
2643 clevermous 1576
        push    ebp
1577
        lea     ebp, [esp+20]
2288 clevermous 1578
        call    fat_entry_to_bdfe
2643 clevermous 1579
        pop     ebp
2288 clevermous 1580
.l2:
1581
        add     edi, 0x20
1582
        cmp     edi, ebx
1583
        jb      .l1
1584
        pop     eax
1585
        inc     eax
1586
        dec     dword [esp+4]
1587
        jnz     .new_sector
2643 clevermous 1588
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 1589
        test    eax, eax
1590
        jz      .done
1591
        call    get_FAT
2643 clevermous 1592
        jc      .notfound2
2288 clevermous 1593
        cmp     eax, 2
1594
        jb      .done
2643 clevermous 1595
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1596
        jae     .done
1597
        push    eax
2643 clevermous 1598
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1599
        mov     [esp+8], eax
1600
        pop     eax
1601
        pop     ebx
1602
        add     esp, 4
1603
        jmp     .new_cluster
6867 pathoswith 1604
 
2288 clevermous 1605
.notfound2:
1606
        add     esp, 8
1607
.notfound:
6868 pathoswith 1608
        add     esp, 262*2+4
6867 pathoswith 1609
        push    ERROR_DEVICE
1610
        jmp     @f
1611
 
2288 clevermous 1612
.done:
6868 pathoswith 1613
        add     esp, 262*2+12
6867 pathoswith 1614
        pushd   0
2288 clevermous 1615
        dec     ecx
1616
        js      @f
6867 pathoswith 1617
        mov     byte [esp], ERROR_END_OF_FILE
2288 clevermous 1618
@@:
6867 pathoswith 1619
        mov     ebx, [edx+4]
1620
.ret:
2643 clevermous 1621
        call    fat_unlock
1622
        pop     eax
2288 clevermous 1623
        ret
1624
 
6867 pathoswith 1625
.error:
1626
        push    eax
1627
        xor     ebx, ebx
1628
        jmp     .ret
1629
 
1630
.accessDenied:
1631
        push    ERROR_ACCESS_DENIED
1632
        xor     ebx, ebx
1633
        jmp     .ret
1634
 
4273 clevermous 1635
fat1x_root_next:
2643 clevermous 1636
        push    ecx
1637
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1638
        cmp     edi, ecx
4273 clevermous 1639
        jae     fat1x_root_next_sector
6867 pathoswith 1640
        add     edi, 0x20
1641
@@:
2643 clevermous 1642
        pop     ecx
6867 pathoswith 1643
        ret
1644
 
1645
fat1x_root_next_write:
1646
        push    ecx
1647
        lea     ecx, [ebp+FAT.buffer+0x200]
1648
        cmp     edi, ecx
1649
        jc      @b
1650
        call    fat1x_root_end_write
4273 clevermous 1651
fat1x_root_next_sector:
2643 clevermous 1652
        push    [ebp+FAT.longname_sec2]
1653
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1654
        mov     ecx, [eax+4]
1655
        push    ecx
2643 clevermous 1656
        add     ecx, [ebp+FAT.ROOT_START]
1657
        mov     [ebp+FAT.longname_sec2], ecx
2288 clevermous 1658
        pop     ecx
1659
        inc     ecx
1660
        mov     [eax+4], ecx
2643 clevermous 1661
        cmp     ecx, [ebp+FAT.ROOT_SECTORS]
6867 pathoswith 1662
        jnc     fat_notroot_next_err
2288 clevermous 1663
        pop     ecx
4273 clevermous 1664
fat1x_root_first:
2288 clevermous 1665
        mov     eax, [eax+4]
2643 clevermous 1666
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 1667
        push    ebx
2643 clevermous 1668
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1669
        mov     ebx, edi
2643 clevermous 1670
        call    fs_read32_sys
2288 clevermous 1671
        pop     ebx
2643 clevermous 1672
        test    eax, eax
6867 pathoswith 1673
        jz      @f
1674
        movi    eax, ERROR_DEVICE
2288 clevermous 1675
        stc
6867 pathoswith 1676
@@:
2288 clevermous 1677
        ret
6867 pathoswith 1678
 
4273 clevermous 1679
fat1x_root_begin_write:
2288 clevermous 1680
        push    edi eax
4273 clevermous 1681
        call    fat1x_root_first
2288 clevermous 1682
        pop     eax edi
1683
        ret
6867 pathoswith 1684
 
4273 clevermous 1685
fat1x_root_end_write:
2288 clevermous 1686
        pusha
1687
        mov     eax, [eax+4]
2643 clevermous 1688
        add     eax, [ebp+FAT.ROOT_START]
1689
        lea     ebx, [ebp+FAT.buffer]
1690
        call    fs_write32_sys
2288 clevermous 1691
        popa
1692
        ret
6867 pathoswith 1693
 
1694
fat_notroot_next:
2643 clevermous 1695
        push    ecx
6867 pathoswith 1696
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
2643 clevermous 1697
        cmp     edi, ecx
6867 pathoswith 1698
        jae     fat_notroot_next_sector
1699
        add     edi, 0x20
1700
@@:
2643 clevermous 1701
        pop     ecx
2288 clevermous 1702
        ret
1703
 
6867 pathoswith 1704
fat_notroot_next_write:
2643 clevermous 1705
        push    ecx
6867 pathoswith 1706
        lea     ecx, [ebp+FAT.buffer+0x200]
2643 clevermous 1707
        cmp     edi, ecx
6867 pathoswith 1708
        jc      @b
1709
        push    eax
1710
        call    fat_notroot_end_write
1711
        pop     eax
2288 clevermous 1712
fat_notroot_next_sector:
2643 clevermous 1713
        push    [ebp+FAT.longname_sec2]
1714
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1715
        push    eax
1716
        call    fat_get_sector
2643 clevermous 1717
        mov     [ebp+FAT.longname_sec2], eax
2288 clevermous 1718
        pop     eax
1719
        mov     ecx, [eax+4]
1720
        inc     ecx
2643 clevermous 1721
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1722
        jae     fat_notroot_next_cluster
1723
        mov     [eax+4], ecx
1724
        jmp     @f
6867 pathoswith 1725
 
1726
fat_notroot_next_err:
1727
        pop     ecx
1728
        movi    eax, ERROR_FILE_NOT_FOUND
1729
fat1x_root_extend_dir:
1730
        stc
1731
        ret
1732
 
2288 clevermous 1733
fat_notroot_next_cluster:
1734
        push    eax
1735
        mov     eax, [eax]
1736
        call    get_FAT
1737
        mov     ecx, eax
1738
        pop     eax
2643 clevermous 1739
        jc      fat_notroot_first.deverr
1740
        cmp     ecx, 2
1741
        jb      fat_notroot_next_err
1742
        cmp     ecx, [ebp+FAT.fatRESERVED]
2288 clevermous 1743
        jae     fat_notroot_next_err
1744
        mov     [eax], ecx
1745
        and     dword [eax+4], 0
1746
@@:
1747
        pop     ecx
1748
fat_notroot_first:
1749
        call    fat_get_sector
1750
        push    ebx
2643 clevermous 1751
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1752
        mov     ebx, edi
2643 clevermous 1753
        call    fs_read32_sys
2288 clevermous 1754
        pop     ebx
2643 clevermous 1755
        test    eax, eax
1756
        jz      .ret ; CF=0
1757
        push    ecx
1758
.deverr:
1759
        pop     ecx
1760
        mov     eax, ERROR_DEVICE
1761
        stc
1762
.ret:
1763
        ret
6867 pathoswith 1764
 
2288 clevermous 1765
fat_notroot_begin_write:
1766
        push    eax edi
1767
        call    fat_notroot_first
1768
        pop     edi eax
1769
        ret
6867 pathoswith 1770
 
2288 clevermous 1771
fat_notroot_end_write:
1772
        call    fat_get_sector
1773
        push    ebx
2643 clevermous 1774
        lea     ebx, [ebp+FAT.buffer]
1775
        call    fs_write32_sys
2288 clevermous 1776
        pop     ebx
1777
        ret
6867 pathoswith 1778
 
1779
fat_notroot_extend_dir.writeerr:
1780
        pop     edx
2288 clevermous 1781
@@:
1782
        pop     eax
6867 pathoswith 1783
        ret
1784
 
2288 clevermous 1785
fat_notroot_extend_dir:
1786
        push    eax
1787
        call    get_free_FAT
6867 pathoswith 1788
        jc      @b
2288 clevermous 1789
        push    edx
2643 clevermous 1790
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 1791
        call    set_FAT
2643 clevermous 1792
        jc      .writeerr
2288 clevermous 1793
        mov     edx, eax
1794
        mov     eax, [esp+4]
1795
        mov     eax, [eax]
1796
        push    edx
1797
        call    set_FAT
1798
        pop     edx
6867 pathoswith 1799
        jc      .writeerr
2288 clevermous 1800
        push    ecx
1801
        or      ecx, -1
1802
        call    add_disk_free_space
1803
        mov     ecx, 512/4
2643 clevermous 1804
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1805
        push    edi
1806
        xor     eax, eax
1807
        rep stosd
1808
        pop     edi
1809
        pop     ecx
1810
        mov     eax, [esp+4]
1811
        mov     [eax], edx
1812
        and     dword [eax+4], 0
1813
        pop     edx
1814
        mov     eax, [eax]
1815
        dec     eax
1816
        dec     eax
1817
        push    ebx ecx
2643 clevermous 1818
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1819
        imul    eax, ecx
2643 clevermous 1820
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1821
        mov     ebx, edi
1822
@@:
2643 clevermous 1823
        push    eax
1824
        call    fs_write32_sys
1825
        pop     eax
2288 clevermous 1826
        inc     eax
1827
        loop    @b
1828
        pop     ecx ebx eax
1829
        clc
1830
        ret
1831
 
1832
fat_get_sector:
1833
        push    ecx
1834
        mov     ecx, [eax]
1835
        dec     ecx
1836
        dec     ecx
2643 clevermous 1837
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
1838
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 1839
        add     ecx, [eax+4]
1840
        mov     eax, ecx
1841
        pop     ecx
1842
        ret
1843
 
2643 clevermous 1844
;----------------------------------------------------------------
1845
fat_CreateFolder:
6917 pathoswith 1846
        mov     [ebp+FAT.createOption], 0
6468 pathoswith 1847
        jmp     @f
2643 clevermous 1848
 
6468 pathoswith 1849
fat_CreateFile:
6917 pathoswith 1850
        mov     [ebp+FAT.createOption], 1
6468 pathoswith 1851
@@:
2643 clevermous 1852
        call    fat_lock
1853
        mov     ecx, [ebx+12]
1854
        mov     edx, [ebx+16]
6917 pathoswith 1855
.rename:
2288 clevermous 1856
        pushad
1857
        xor     edi, edi
1858
        push    esi
1859
@@:
1860
        lodsb
1861
        test    al, al
1862
        jz      @f
1863
        cmp     al, '/'
1864
        jnz     @b
1865
        lea     edi, [esi-1]
1866
        jmp     @b
6468 pathoswith 1867
 
2288 clevermous 1868
@@:
1869
        pop     esi
1870
        test    edi, edi
1871
        jnz     .noroot
2643 clevermous 1872
        mov     edx, [ebp+FAT.ROOT_CLUSTER]
1873
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1874
        jz      .pushnotroot
2643 clevermous 1875
        xor     edx, edx
1876
        push    edx
4273 clevermous 1877
        push    fat1x_root_extend_dir
1878
        push    fat1x_root_end_write
1879
        push    fat1x_root_next_write
1880
        push    fat1x_root_begin_write
2643 clevermous 1881
        push    edx
1882
        push    edx
4273 clevermous 1883
        push    fat1x_root_first
1884
        push    fat1x_root_next
2288 clevermous 1885
        jmp     .common1
6468 pathoswith 1886
 
6867 pathoswith 1887
.retNotFound:
1888
        movi    eax, ERROR_FILE_NOT_FOUND
1889
        jmp     .ret1
1890
 
1891
.noAccess:
1892
        movi    eax, ERROR_ACCESS_DENIED
1893
.ret1:
1894
        mov     [esp+28], eax
1895
        call    fat_unlock
1896
        popad
1897
        xor     ebx, ebx
1898
        ret
1899
 
1900
.full:
1901
        movi    eax, ERROR_DISK_FULL
1902
        jmp     .ret1
1903
 
2288 clevermous 1904
.noroot:
1905
        cmp     byte [edi+1], 0
6867 pathoswith 1906
        jz      .noAccess
2288 clevermous 1907
; check existence
1908
        mov     byte [edi], 0
1909
        push    edi
6468 pathoswith 1910
        call    hd_find_lfn
2288 clevermous 1911
        pop     esi
1912
        mov     byte [esi], '/'
6867 pathoswith 1913
        jc      .retNotFound
2288 clevermous 1914
        inc     esi
6867 pathoswith 1915
        test    byte [edi+11], 0x10
1916
        jz      .noAccess   ; file
2643 clevermous 1917
        mov     edx, [edi+20-2]
6867 pathoswith 1918
        mov     dx, [edi+26]
1919
        movi    eax, ERROR_FS_FAIL
2643 clevermous 1920
        cmp     edx, 2
2288 clevermous 1921
        jb      .ret1
1922
.pushnotroot:
2643 clevermous 1923
        push    edx
2288 clevermous 1924
        push    fat_notroot_extend_dir
1925
        push    fat_notroot_end_write
1926
        push    fat_notroot_next_write
1927
        push    fat_notroot_begin_write
1928
        push    0
2643 clevermous 1929
        push    edx
2288 clevermous 1930
        push    fat_notroot_first
1931
        push    fat_notroot_next
1932
.common1:
1933
        call    fat_find_lfn
1934
        jc      .notfound
1935
        test    byte [edi+11], 10h
1936
        jz      .exists_file
6468 pathoswith 1937
; found directory
2643 clevermous 1938
        add     esp, 36
1939
        call    fat_unlock
2288 clevermous 1940
        popad
6917 pathoswith 1941
        xor     eax, eax
1942
        cmp     [ebp+FAT.createOption], 0
2288 clevermous 1943
        jz      @f
6917 pathoswith 1944
        mov     al, ERROR_ACCESS_DENIED
2288 clevermous 1945
@@:
1946
        xor     ebx, ebx
1947
        ret
6468 pathoswith 1948
 
2288 clevermous 1949
.exists_file:
6917 pathoswith 1950
        cmp     [ebp+FAT.createOption], 1
2288 clevermous 1951
        jz      @f
2643 clevermous 1952
        add     esp, 36
6867 pathoswith 1953
        jmp     .noAccess
6468 pathoswith 1954
 
1955
@@: ; delete FAT chain
2288 clevermous 1956
        push    edi
1957
        xor     eax, eax
1958
        mov     dword [edi+28], eax     ; zero size
1959
        xor     ecx, ecx
1960
        mov     eax, [edi+20-2]
1961
        mov     ax, [edi+26]
1962
        mov     word [edi+20], cx
1963
        mov     word [edi+26], cx
1964
        test    eax, eax
1965
        jz      .done1
1966
@@:
2643 clevermous 1967
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1968
        jae     .done1
1969
        xor     edx, edx
1970
        call    set_FAT
1971
        mov     eax, edx
2643 clevermous 1972
        jc      .done1
2288 clevermous 1973
        inc     ecx
1974
        jmp     @b
6468 pathoswith 1975
 
1976
.short_name_found:
1977
        pop     ecx edi esi
1978
        call    fat_next_short_name
1979
        jnc     .test_short_name_loop
1980
.disk_full:
1981
        add     esp, 12+36
6867 pathoswith 1982
        jmp     .full
6468 pathoswith 1983
 
1984
.notfound:  ; generate short name
2288 clevermous 1985
        call    fat_name_is_legal
1986
        jc      @f
2643 clevermous 1987
        add     esp, 36
6867 pathoswith 1988
        jmp     .retNotFound
6468 pathoswith 1989
 
2288 clevermous 1990
@@:
1991
        sub     esp, 12
1992
        mov     edi, esp
1993
        call    fat_gen_short_name
1994
.test_short_name_loop:
1995
        push    esi edi ecx
1996
        mov     esi, edi
1997
        lea     eax, [esp+12+12+8]
2643 clevermous 1998
        mov     edx, [eax+24]
1999
        mov     [eax], edx
2288 clevermous 2000
        and     dword [eax+4], 0
2001
        call    dword [eax-4]
2002
        jc      .found
2003
.test_short_name_entry:
2004
        cmp     byte [edi+11], 0xF
2005
        jz      .test_short_name_cont
2006
        mov     ecx, 11
2007
        push    esi edi
2008
        repz cmpsb
2009
        pop     edi esi
2010
        jz      .short_name_found
2011
.test_short_name_cont:
2012
        lea     eax, [esp+12+12+8]
2013
        call    dword [eax-8]
2014
        jnc     .test_short_name_entry
2015
.found:
2016
        pop     ecx edi esi
2017
; now find space in directory
2018
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
2019
        mov     al, '~'
2020
        push    ecx edi
2021
        mov     ecx, 8
2022
        repnz scasb
3598 clevermous 2023
        movi    eax, 1     ; 1 entry
2288 clevermous 2024
        jnz     .notilde
2025
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
6471 pathoswith 2026
        xor     ecx, ecx
2027
        push    esi
2288 clevermous 2028
@@:
6471 pathoswith 2029
        call    utf8to16
2030
        inc     ecx
2031
        test    ax, ax
2032
        jnz     @b
2033
        pop     esi
2034
        mov     eax, ecx
2035
        add     eax, 12+13-1
2288 clevermous 2036
        mov     ecx, 13
2037
        cdq
2038
        div     ecx
2039
.notilde:
2040
        push    -1
2041
        push    -1
2042
        push    -1
2043
; find  successive entries in directory
2044
        xor     ecx, ecx
2045
        push    eax
2046
        lea     eax, [esp+16+8+12+8]
2643 clevermous 2047
        mov     edx, [eax+24]
2048
        mov     [eax], edx
2288 clevermous 2049
        and     dword [eax+4], 0
2050
        call    dword [eax-4]
2051
        pop     eax
2052
        jnc     .scan_dir
2053
.fsfrfe3:
2643 clevermous 2054
        add     esp, 12+8+12+36
6867 pathoswith 2055
        movi    eax, ERROR_DEVICE
2056
        jmp     .ret1
6468 pathoswith 2057
 
2288 clevermous 2058
.scan_dir:
2059
        cmp     byte [edi], 0
2060
        jz      .free
2061
        cmp     byte [edi], 0xE5
2062
        jz      .free
2063
        xor     ecx, ecx
2064
.scan_cont:
2065
        push    eax
2066
        lea     eax, [esp+16+8+12+8]
2067
        call    dword [eax-8]
2643 clevermous 2068
        mov     edx, eax
2288 clevermous 2069
        pop     eax
2070
        jnc     .scan_dir
2643 clevermous 2071
        cmp     edx, ERROR_DEVICE
2072
        jz      .fsfrfe3
2288 clevermous 2073
        push    eax
2074
        lea     eax, [esp+16+8+12+8]
2075
        call    dword [eax+20]          ; extend directory
2076
        pop     eax
2077
        jnc     .scan_dir
2643 clevermous 2078
        add     esp, 12+8+12+36
6867 pathoswith 2079
        jmp     .full
6468 pathoswith 2080
 
2288 clevermous 2081
.free:
2082
        test    ecx, ecx
2083
        jnz     @f
2084
        mov     [esp], edi
2085
        mov     ecx, [esp+12+8+12+8]
2086
        mov     [esp+4], ecx
2087
        mov     ecx, [esp+12+8+12+12]
2088
        mov     [esp+8], ecx
2089
        xor     ecx, ecx
2090
@@:
2091
        inc     ecx
2092
        cmp     ecx, eax
2093
        jb      .scan_cont
2094
; found!
2643 clevermous 2095
        push    esi ecx
6917 pathoswith 2096
; If creating a directory, allocate one data cluster or fail immediately if this is impossible.
2097
; This prevents from creating an invalid directory entry on a full disk.
2098
        cmp     [ebp+FAT.createOption], 0
2099
        jnz     .notFolder
2643 clevermous 2100
        call    get_free_FAT
2101
        jnc     @f
2102
        add     esp, 8+12+8
2103
        jmp     .disk_full
6468 pathoswith 2104
 
2643 clevermous 2105
@@:
6471 pathoswith 2106
        mov     [esp+8+12+8+12+36+20], eax  ; store the cluster somewhere
6917 pathoswith 2107
.notFolder: ; calculate name checksum
2288 clevermous 2108
        mov     esi, [esp+8+12]
2109
        mov     ecx, 11
2110
        xor     eax, eax
2111
@@:
2112
        ror     al, 1
2113
        add     al, [esi]
2114
        inc     esi
2115
        loop    @b
6471 pathoswith 2116
        pop     ecx esi edi
2288 clevermous 2117
        pop     dword [esp+8+12+12]
2118
        pop     dword [esp+8+12+12]
2119
; edi points to first entry in free chunk
2120
        dec     ecx
2121
        jz      .nolfn
6471 pathoswith 2122
        push    esi eax
2288 clevermous 2123
        lea     eax, [esp+8+8+12+8]
6471 pathoswith 2124
        call    dword [eax+8]   ; begin write
2288 clevermous 2125
        mov     al, 40h
2126
.writelfn:
2127
        or      al, cl
6471 pathoswith 2128
        stosb
2288 clevermous 2129
        mov     esi, [esp+4]
2130
        push    ecx
2131
        dec     ecx
6471 pathoswith 2132
        jz      @f
2288 clevermous 2133
        imul    ecx, 13
6471 pathoswith 2134
.scroll:
2135
        call    utf8to16
2136
        loop    .scroll
2137
@@:
2288 clevermous 2138
        mov     cl, 5
4273 clevermous 2139
        call    fat_read_symbols
2288 clevermous 2140
        mov     ax, 0xF
2141
        stosw
2142
        mov     al, [esp+4]
2143
        stosb
2144
        mov     cl, 6
4273 clevermous 2145
        call    fat_read_symbols
2288 clevermous 2146
        xor     eax, eax
2147
        stosw
2148
        mov     cl, 2
4273 clevermous 2149
        call    fat_read_symbols
2288 clevermous 2150
        pop     ecx
2151
        lea     eax, [esp+8+8+12+8]
6471 pathoswith 2152
        call    dword [eax+12]  ; next write
2288 clevermous 2153
        xor     eax, eax
2154
        loop    .writelfn
6471 pathoswith 2155
        pop     eax esi
2288 clevermous 2156
.nolfn:
6917 pathoswith 2157
        pop     esi
2158
        add     esp, 16
2288 clevermous 2159
        mov     ecx, 11
2160
        rep movsb
6917 pathoswith 2161
        cmp     [ebp+FAT.createOption], 2
2162
        jz      .copy
2288 clevermous 2163
        mov     word [edi], 20h         ; attributes
2164
        sub     edi, 11
2165
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
2166
        call    get_time_for_file
2167
        mov     [edi+14], ax            ; creation time
2168
        mov     [edi+22], ax            ; last write time
2169
        call    get_date_for_file
2170
        mov     [edi+16], ax            ; creation date
2171
        mov     [edi+24], ax            ; last write date
2172
        mov     [edi+18], ax            ; last access date
2173
        mov     word [edi+20], cx       ; high word of cluster
2174
        mov     word [edi+26], cx       ; low word of cluster - to be filled
2175
        mov     dword [edi+28], ecx     ; file size - to be filled
6917 pathoswith 2176
        cmp     [ebp+FAT.createOption], 0
2177
        jnz     .doit
2288 clevermous 2178
; create directory
2179
        mov     byte [edi+11], 10h      ; attributes: folder
2643 clevermous 2180
        mov     esi, edi
2181
        mov     eax, [esp+36+20] ; extract saved cluster
2182
        mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
2288 clevermous 2183
        push    ecx
2643 clevermous 2184
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2185
        shl     ecx, 9
2643 clevermous 2186
        push    ecx
2187
        push    edi
2288 clevermous 2188
        jmp     .doit2
6468 pathoswith 2189
 
6917 pathoswith 2190
.copy:
2191
        lea     esi, [esp+72+11]
2192
        mov     cl, 21
2193
        rep movsb
2194
        sub     edi, 32
2195
        jmp     .doit
2196
 
6468 pathoswith 2197
.done1:
2198
        pop     edi
2199
        call    get_time_for_file
2200
        mov     [edi+22], ax
2201
        call    get_date_for_file
2202
        mov     [edi+24], ax
2203
        mov     [edi+18], ax
2204
        or      byte [edi+11], 20h      ; set 'archive' attribute
2288 clevermous 2205
.doit:
2643 clevermous 2206
        mov     esi, [esp+36+20]
2288 clevermous 2207
        lea     eax, [esp+8]
2208
        call    dword [eax+16]  ; flush directory
2209
        push    ecx
2643 clevermous 2210
        mov     ecx, [esp+4+36+24]
6917 pathoswith 2211
        xor     eax, eax
2288 clevermous 2212
        test    ecx, ecx
2213
        jz      .done
6917 pathoswith 2214
        push    ecx edi
2288 clevermous 2215
        call    get_free_FAT
2216
        jc      .diskfull
2643 clevermous 2217
.doit2:
2288 clevermous 2218
        push    eax
2219
        mov     [edi+26], ax
2220
        shr     eax, 16
2221
        mov     [edi+20], ax
2222
        lea     eax, [esp+16+8]
2223
        call    dword [eax+16]  ; flush directory
2224
        pop     eax
2643 clevermous 2225
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2226
        call    set_FAT
2227
.write_cluster:
2228
        push    eax
2229
        dec     eax
2230
        dec     eax
2643 clevermous 2231
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2232
        add     eax, [ebp+FAT.DATA_START]
2233
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2234
.write_sector:
6917 pathoswith 2235
        cmp     [ebp+FAT.createOption], 0
2236
        jz      .writedir
2288 clevermous 2237
        mov     ecx, 512
2643 clevermous 2238
        cmp     dword [esp+12], ecx
2288 clevermous 2239
        jb      .writeshort
2240
; we can write directly from given buffer
2241
        mov     ebx, esi
2242
        add     esi, ecx
2243
        jmp     .writecommon
6468 pathoswith 2244
 
6867 pathoswith 2245
.writedir:
2246
        push    512
2247
        lea     edi, [ebp+FAT.buffer]
2248
        mov     ebx, edi
2249
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2250
        shl     ecx, 9
2251
        cmp     ecx, [esp+16]
2252
        jnz     .writedircont
2253
        dec     dword [esp+20]
2254
        push    esi
2255
        mov     ecx, 32/4
2256
        rep movsd
2257
        pop     esi
2258
        mov     dword [edi-32], '.   '
2259
        mov     dword [edi-32+4], '    '
2260
        mov     dword [edi-32+8], '    '
2261
        mov     byte [edi-32+11], 10h
2262
        push    esi
2263
        mov     ecx, 32/4
2264
        rep movsd
2265
        pop     esi
2266
        mov     dword [edi-32], '..  '
2267
        mov     dword [edi-32+4], '    '
2268
        mov     dword [edi-32+8], '    '
2269
        mov     byte [edi-32+11], 10h
2270
        mov     ecx, [esp+20+36]
2271
        cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
2272
        jnz     @f
2273
        xor     ecx, ecx
2274
@@:
2275
        mov     word [edi-32+26], cx
2276
        shr     ecx, 16
2277
        mov     [edi-32+20], cx
2278
        jmp     .writedircont
2279
 
2288 clevermous 2280
.writeshort:
2643 clevermous 2281
        mov     ecx, [esp+12]
2288 clevermous 2282
        push    ecx
2643 clevermous 2283
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 2284
        mov     ebx, edi
2285
        rep movsb
2286
.writedircont:
2643 clevermous 2287
        lea     ecx, [ebp+FAT.buffer+0x200]
2288 clevermous 2288
        sub     ecx, edi
2289
        push    eax
2290
        xor     eax, eax
2291
        rep stosb
2292
        pop     eax
2293
        pop     ecx
2294
.writecommon:
2643 clevermous 2295
        push    eax
2296
        call    fs_write32_app
2297
        test    eax, eax
2298
        pop     eax
2288 clevermous 2299
        jnz     .writeerr
2300
        inc     eax
2643 clevermous 2301
        sub     dword [esp+12], ecx
2288 clevermous 2302
        jz      .writedone
2643 clevermous 2303
        dec     dword [esp]
2288 clevermous 2304
        jnz     .write_sector
2643 clevermous 2305
        pop     eax
2288 clevermous 2306
; allocate new cluster
2307
        pop     eax
2308
        mov     ecx, eax
2309
        call    get_free_FAT
2310
        jc      .diskfull
2643 clevermous 2311
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2312
        call    set_FAT
2313
        xchg    eax, ecx
2314
        mov     edx, ecx
2315
        call    set_FAT
2316
        xchg    eax, ecx
2317
        jmp     .write_cluster
6468 pathoswith 2318
 
2288 clevermous 2319
.diskfull:
2320
        mov     eax, ERROR_DISK_FULL
2321
        jmp     .ret
6468 pathoswith 2322
 
2288 clevermous 2323
.writeerr:
2643 clevermous 2324
        pop     eax eax
2288 clevermous 2325
        sub     esi, ecx
2643 clevermous 2326
        mov     eax, ERROR_DEVICE
2288 clevermous 2327
        jmp     .ret
6468 pathoswith 2328
 
2288 clevermous 2329
.writedone:
2643 clevermous 2330
        pop     eax eax
2288 clevermous 2331
        xor     eax, eax
2332
.ret:
2333
        pop     edi ecx
6917 pathoswith 2334
        inc     ecx
2335
.done:
2643 clevermous 2336
        sub     esi, [esp+4+36+20]
2337
        mov     [esp+4+36+28], eax
2338
        mov     [esp+4+36+16], esi
6917 pathoswith 2339
        jecxz   @f
2643 clevermous 2340
        lea     eax, [esp+12]
2288 clevermous 2341
        call    dword [eax+8]
2643 clevermous 2342
        mov     [edi+28], esi
2288 clevermous 2343
        call    dword [eax+16]
6917 pathoswith 2344
@@:
2643 clevermous 2345
        lea     eax, [esi+511]
2288 clevermous 2346
        shr     eax, 9
2643 clevermous 2347
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2348
        lea     eax, [eax+ecx-1]
2349
        xor     edx, edx
2350
        div     ecx
2643 clevermous 2351
        pop     ecx
2288 clevermous 2352
        sub     ecx, eax
2353
        call    add_disk_free_space
2643 clevermous 2354
        add     esp, 36
6917 pathoswith 2355
        cmp     [ebp+FAT.createOption], 2
2356
        jz      @f
2288 clevermous 2357
        call    update_disk
2643 clevermous 2358
        call    fat_unlock
6917 pathoswith 2359
@@:
2288 clevermous 2360
        popad
2361
        ret
6468 pathoswith 2362
 
2288 clevermous 2363
@@:
6471 pathoswith 2364
        or      eax, -1
2365
        rep stosw
4273 clevermous 2366
        ret
2367
 
2368
fat_read_symbols:
6471 pathoswith 2369
        test    esi, esi
2370
        jz      @b
2371
        call    utf8to16
4273 clevermous 2372
        stosw
6471 pathoswith 2373
        test    ax, ax
2374
        jnz     @f
2375
        xor     esi, esi
2376
@@:
4273 clevermous 2377
        loop    fat_read_symbols
2378
        ret
2379
 
2643 clevermous 2380
;----------------------------------------------------------------
2381
fat_Write:
2382
        call    fat_lock
6468 pathoswith 2383
        call    hd_find_lfn
6845 pathoswith 2384
        jc      .error
2643 clevermous 2385
        cmp     dword [ebx+8], 0
6845 pathoswith 2386
        jnz     .eof    ; FAT does not support files larger than 4GB
2643 clevermous 2387
        mov     ecx, [ebx+12]
2388
        mov     edx, [ebx+16]
2389
        mov     ebx, [ebx+4]
2288 clevermous 2390
; now edi points to direntry, ebx=start byte to write,
2391
; ecx=number of bytes to write, edx=data pointer
2392
; extend file if needed
2393
        add     ecx, ebx
2394
        jc      .eof    ; FAT does not support files larger than 4GB
2643 clevermous 2395
        push    edx
2288 clevermous 2396
        push    eax     ; save directory sector
2397
        push    0       ; return value=0
2398
        call    get_time_for_file
2399
        mov     [edi+22], ax            ; last write time
2400
        call    get_date_for_file
2401
        mov     [edi+24], ax            ; last write date
2402
        mov     [edi+18], ax            ; last access date
2403
        push    dword [edi+28]          ; save current file size
2404
        cmp     ecx, [edi+28]
2405
        jbe     .length_ok
2406
        cmp     ecx, ebx
2407
        jz      .length_ok
2408
        call    hd_extend_file
2409
        jnc     .length_ok
2410
        mov     [esp+4], eax
2411
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
2412
; First two cases are fatal errors, in third case we may write some data
2413
        cmp     al, ERROR_DISK_FULL
6845 pathoswith 2414
        jnz     @f
2288 clevermous 2415
; correct number of bytes to write
2416
        mov     ecx, [edi+28]
2417
        cmp     ecx, ebx
2418
        ja      .length_ok
2643 clevermous 2419
        push    0
2288 clevermous 2420
.ret:
2643 clevermous 2421
        pop     eax
2422
        sub     edx, [esp+12]
2423
        mov     ebx, edx        ; ebx=number of written bytes
2288 clevermous 2424
        call    update_disk
2643 clevermous 2425
        test    eax, eax
2288 clevermous 2426
        jz      @f
2643 clevermous 2427
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 2428
@@:
6845 pathoswith 2429
        pop     eax eax ecx edx
2430
.error:
2431
        push    eax
2432
@@:
2643 clevermous 2433
        call    fat_unlock
6867 pathoswith 2434
        pop     eax
6845 pathoswith 2435
        ret
2436
 
2437
.eof:
2438
        push    ERROR_END_OF_FILE
6846 pathoswith 2439
        xor     ebx, ebx
6845 pathoswith 2440
        jmp     @b
2441
 
2442
.device_err2:
2643 clevermous 2443
        pop     ecx
6845 pathoswith 2444
.device_err:
2445
        mov     byte [esp+8], ERROR_DEVICE
2446
        jmp     .ret
2447
 
2448
.fat_err:
2449
        mov     byte [esp+8], ERROR_FS_FAIL
2450
        jmp     .ret
2451
 
2288 clevermous 2452
.length_ok:
2453
        mov     esi, [edi+28]
2454
        mov     eax, [edi+20-2]
2455
        mov     ax, [edi+26]
2456
        mov     edi, eax        ; edi=current cluster
2643 clevermous 2457
        push    0               ; current sector in cluster
2288 clevermous 2458
; save directory
2643 clevermous 2459
        mov     eax, [esp+12]
2288 clevermous 2460
        push    ebx
2643 clevermous 2461
        lea     ebx, [ebp+FAT.buffer]
2462
        call    fs_write32_sys
2288 clevermous 2463
        pop     ebx
2643 clevermous 2464
        test    eax, eax
6845 pathoswith 2465
        jnz     .device_err
2288 clevermous 2466
; now ebx=start pos, ecx=end pos, both lie inside file
2467
        sub     ecx, ebx
2468
        jz      .ret
2469
.write_loop:
2470
; skip unmodified sectors
2643 clevermous 2471
        cmp     dword [esp+4], 0x200
2288 clevermous 2472
        jb      .modify
2473
        sub     ebx, 0x200
2474
        jae     .skip
2475
        add     ebx, 0x200
2476
.modify:
2477
; get length of data in current sector
2478
        push    ecx
2479
        sub     ebx, 0x200
2480
        jb      .hasdata
2481
        neg     ebx
2482
        xor     ecx, ecx
2483
        jmp     @f
2484
.hasdata:
2485
        neg     ebx
2486
        cmp     ecx, ebx
2487
        jbe     @f
2488
        mov     ecx, ebx
2489
@@:
2490
; get current sector number
2491
        mov     eax, edi
2492
        dec     eax
2493
        dec     eax
2643 clevermous 2494
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2495
        add     eax, [ebp+FAT.DATA_START]
2496
        add     eax, [esp+4]
2288 clevermous 2497
; load sector if needed
2643 clevermous 2498
        cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
2288 clevermous 2499
        jz      .noread
2500
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
2501
        jz      .noread
2502
        cmp     ecx, esi        ; (same for the last sector)
2503
        jz      .noread
2643 clevermous 2504
        push    eax ebx
2505
        lea     ebx, [ebp+FAT.buffer]
2506
        call    fs_read32_app
2507
        test    eax, eax
2508
        pop     ebx eax
6845 pathoswith 2509
        jnz     .device_err2
2288 clevermous 2510
.noread:
2511
; zero uninitialized data if file was extended (because hd_extend_file does not this)
2512
        push    eax ecx edi
2513
        xor     eax, eax
2514
        mov     ecx, 0x200
2643 clevermous 2515
        sub     ecx, [esp+8+12]
2288 clevermous 2516
        jbe     @f
2643 clevermous 2517
        lea     edi, [ebp+FAT.buffer]
2518
        add     edi, [esp+8+12]
2288 clevermous 2519
        rep stosb
2520
@@:
2521
; zero uninitialized data in the last sector
2522
        mov     ecx, 0x200
2523
        sub     ecx, esi
2524
        jbe     @f
2643 clevermous 2525
        lea     edi, [ebp+FAT.buffer+esi]
2288 clevermous 2526
        rep stosb
2527
@@:
2528
        pop     edi ecx
2529
; copy new data
2530
        mov     eax, edx
2531
        neg     ebx
2532
        jecxz   @f
2643 clevermous 2533
        lea     ebx, [ebp+FAT.buffer+0x200+ebx]
2288 clevermous 2534
        call    memmove
2535
        xor     ebx, ebx
2536
@@:
2537
        pop     eax
2538
; save sector
2539
        push    ebx
2643 clevermous 2540
        lea     ebx, [ebp+FAT.buffer]
2541
        call    fs_write32_app
2288 clevermous 2542
        pop     ebx
2643 clevermous 2543
        test    eax, eax
2288 clevermous 2544
        jnz     .device_err2
2545
        add     edx, ecx
2546
        sub     [esp], ecx
2547
        pop     ecx
2548
        jz      .ret
2549
.skip:
2550
; next sector
2643 clevermous 2551
        pop     eax
2552
        inc     eax
2553
        push    eax
2554
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2555
        jb      @f
2643 clevermous 2556
        and     dword [esp], 0
2288 clevermous 2557
        mov     eax, edi
2558
        call    get_FAT
2559
        mov     edi, eax
2643 clevermous 2560
        jc      .device_err
2561
        cmp     edi, 2
2562
        jb      .fat_err
2563
        cmp     edi, [ebp+FAT.fatRESERVED]
2564
        jae     .fat_err
2288 clevermous 2565
@@:
2566
        sub     esi, 0x200
2567
        jae     @f
2568
        xor     esi, esi
2569
@@:
2643 clevermous 2570
        sub     dword [esp+4], 0x200
2288 clevermous 2571
        jae     @f
2643 clevermous 2572
        and     dword [esp+4], 0
2288 clevermous 2573
@@:
2574
        jmp     .write_loop
2575
 
2576
hd_extend_file.zero_size:
2577
        xor     eax, eax
2578
        jmp     hd_extend_file.start_extend
2579
 
2580
; extends file on hd to given size (new data area is undefined)
2581
; in: edi->direntry, ecx=new size
2582
; out: CF=0 => OK, eax=0
6468 pathoswith 2583
;      CF=1 => error, eax=code (ERROR_FS_FAIL or ERROR_DISK_FULL or ERROR_DEVICE)
2288 clevermous 2584
hd_extend_file:
2643 clevermous 2585
        push    esi
2586
        mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
2587
        imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
2288 clevermous 2588
        push    ecx
2589
; find the last cluster of file
2590
        mov     eax, [edi+20-2]
2591
        mov     ax, [edi+26]
2592
        mov     ecx, [edi+28]
2593
        jecxz   .zero_size
2594
.last_loop:
2643 clevermous 2595
        sub     ecx, esi
2288 clevermous 2596
        jbe     .last_found
2597
        call    get_FAT
2643 clevermous 2598
        jnc     @f
2288 clevermous 2599
.device_err:
2600
        pop     ecx
2601
.device_err2:
2643 clevermous 2602
        pop     esi
2603
        push    ERROR_DEVICE
2288 clevermous 2604
.ret_err:
2605
        pop     eax
2606
        stc
2607
        ret
2608
@@:
2609
        cmp     eax, 2
2610
        jb      .fat_err
2643 clevermous 2611
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2612
        jb      .last_loop
2613
.fat_err:
2643 clevermous 2614
        pop     ecx esi
6468 pathoswith 2615
        push    ERROR_FS_FAIL
2288 clevermous 2616
        jmp     .ret_err
2617
.last_found:
2618
        push    eax
2619
        call    get_FAT
2643 clevermous 2620
        jnc     @f
2288 clevermous 2621
        pop     eax
2622
        jmp     .device_err
2623
@@:
2643 clevermous 2624
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2625
        pop     eax
2626
        jb      .fat_err
2627
; set length to full number of clusters
2628
        sub     [edi+28], ecx
2629
.start_extend:
2630
        pop     ecx
2631
; now do extend
2632
        push    edx
2633
        mov     edx, 2          ; start scan from cluster 2
2634
.extend_loop:
2635
        cmp     [edi+28], ecx
2636
        jae     .extend_done
2637
; add new cluster
2638
        push    eax
2639
        call    get_free_FAT
2640
        jc      .disk_full
2643 clevermous 2641
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2642
        call    set_FAT
2643
        mov     edx, eax
2644
        pop     eax
2645
        test    eax, eax
2646
        jz      .first_cluster
2647
        push    edx
2648
        call    set_FAT
2649
        pop     edx
2650
        jmp     @f
2651
.first_cluster:
2652
        ror     edx, 16
2653
        mov     [edi+20], dx
2654
        ror     edx, 16
2655
        mov     [edi+26], dx
2656
@@:
2657
        push    ecx
2658
        mov     ecx, -1
2659
        call    add_disk_free_space
2660
        pop     ecx
2661
        mov     eax, edx
2643 clevermous 2662
        add     [edi+28], esi
2288 clevermous 2663
        jmp     .extend_loop
2664
.extend_done:
2665
        mov     [edi+28], ecx
2643 clevermous 2666
        pop     edx esi
2288 clevermous 2667
        xor     eax, eax        ; CF=0
2668
        ret
2669
.device_err3:
2670
        pop     edx
2671
        jmp     .device_err2
2672
.disk_full:
2643 clevermous 2673
        pop     eax edx esi
3598 clevermous 2674
        movi    eax, ERROR_DISK_FULL
2288 clevermous 2675
        stc
2676
        ret
2677
 
2678
;----------------------------------------------------------------
2643 clevermous 2679
fat_SetFileEnd:
2680
        call    fat_lock
6468 pathoswith 2681
        call    hd_find_lfn
6845 pathoswith 2682
        jc      .reteax
2288 clevermous 2683
; must not be directory
2684
        test    byte [edi+11], 10h
2643 clevermous 2685
        jnz     .access_denied
2288 clevermous 2686
; file size must not exceed 4 Gb
2643 clevermous 2687
        cmp     dword [ebx+8], 0
6845 pathoswith 2688
        jnz     .endOfFile
2288 clevermous 2689
        push    eax     ; save directory sector
2690
; set file modification date/time to current
6867 pathoswith 2691
        call    get_time_for_file
2692
        mov     [edi+22], ax    ; last write
2693
        call    get_date_for_file
2694
        mov     [edi+24], ax    ; last write
2695
        mov     [edi+18], ax    ; last access
2643 clevermous 2696
        mov     eax, [ebx+4]
2288 clevermous 2697
        cmp     eax, [edi+28]
2698
        jb      .truncate
2699
        ja      .expand
2700
        pop     eax
2643 clevermous 2701
        lea     ebx, [ebp+FAT.buffer]
2702
        call    fs_write32_sys
2703
        test    eax, eax
6845 pathoswith 2704
        jnz     .errorDevice
2705
        push    0
2706
        jmp     .ret
2707
 
2708
.access_denied:
2709
        push    ERROR_ACCESS_DENIED
2710
        jmp     .ret
2711
 
2712
.endOfFile:
2713
        push    ERROR_END_OF_FILE
2714
        jmp     .ret
2715
 
2716
.errorDevice:
2643 clevermous 2717
        push    ERROR_DEVICE
2718
        jmp     .ret
6845 pathoswith 2719
 
2288 clevermous 2720
.expand:
2721
        push    ebx ebp ecx
2722
        push    dword [edi+28]  ; save old size
2723
        mov     ecx, eax
2724
        call    hd_extend_file
2725
        push    eax             ; return code
2726
        jnc     .expand_ok
2727
        cmp     al, ERROR_DISK_FULL
6845 pathoswith 2728
        jnz     .pop_ret
2729
.expand_ok: ; save directory
2288 clevermous 2730
        mov     eax, [edi+28]
2731
        xchg    eax, [esp+20]
2643 clevermous 2732
        lea     ebx, [ebp+FAT.buffer]
2733
        call    fs_write32_sys
2734
        test    eax, eax
6850 pathoswith 2735
        jnz     .pop_ret11
2736
        mov     eax, [esp+20]
2737
        sub     eax, [esp+4]
2738
        cmp     eax, 1000001h
2739
        jnc     .pop_ret
2288 clevermous 2740
        mov     eax, [edi+20-2]
2741
        mov     ax, [edi+26]
2742
        mov     edi, eax
2643 clevermous 2743
        test    edi, edi
2744
        jz      .pop_ret
2288 clevermous 2745
; now zero new data
2643 clevermous 2746
        push    0
2747
; edi=current cluster, [esp]=sector in cluster
2748
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
2288 clevermous 2749
.zero_loop:
2643 clevermous 2750
        cmp     edi, 2
2751
        jb      .error_fat
2752
        cmp     edi, [ebp+FAT.fatRESERVED]
2753
        jae     .error_fat
2754
        sub     dword [esp+8], 0x200
2288 clevermous 2755
        jae     .next_cluster
2756
        lea     eax, [edi-2]
2643 clevermous 2757
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2758
        add     eax, [ebp+FAT.DATA_START]
2759
        add     eax, [esp]
2760
        cmp     dword [esp+8], -0x200
2288 clevermous 2761
        jz      .noread
2643 clevermous 2762
        push    eax
2763
        lea     ebx, [ebp+FAT.buffer]
2764
        call    fs_read32_app
2765
        test    eax, eax
2766
        pop     eax
2288 clevermous 2767
        jnz     .err_next
2768
.noread:
2643 clevermous 2769
        mov     ecx, [esp+8]
2288 clevermous 2770
        neg     ecx
2771
        push    edi
2643 clevermous 2772
        lea     edi, [ebp+FAT.buffer+0x200]
2773
        add     edi, [esp+12]
2288 clevermous 2774
        push    eax
2775
        xor     eax, eax
2643 clevermous 2776
        mov     [esp+16], eax
2288 clevermous 2777
        rep stosb
2778
        pop     eax
2779
        pop     edi
2643 clevermous 2780
        call    fs_write32_app
2781
        test    eax, eax
2288 clevermous 2782
        jz      .next_cluster
2783
.err_next:
2643 clevermous 2784
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 2785
.next_cluster:
2643 clevermous 2786
        pop     eax
2288 clevermous 2787
        sub     dword [esp+20], 0x200
2788
        jbe     .pop_ret
2643 clevermous 2789
        inc     eax
2790
        push    eax
2791
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2792
        jb      .zero_loop
2643 clevermous 2793
        and     dword [esp], 0
2288 clevermous 2794
        mov     eax, edi
2795
        call    get_FAT
2796
        mov     edi, eax
2643 clevermous 2797
        jnc     .zero_loop
2798
        pop     eax
6845 pathoswith 2799
.pop_ret11:
2800
        mov     byte [esp], ERROR_DEVICE
2801
.pop_ret:
2802
        call    update_disk
2803
        pop     eax ecx ecx ebp ebx ecx
2804
.reteax:
2805
        push    eax
2806
.ret:
2807
        call    fat_unlock
6867 pathoswith 2808
        pop     eax
6845 pathoswith 2809
        ret
2810
 
2811
.error_fat:
2812
        pop     eax
2813
        mov     byte [esp], ERROR_FS_FAIL
2814
        jmp     .pop_ret
2815
 
2816
.error_fat2:
2817
        pop     eax ecx eax
2818
        call    update_disk
2819
        push    ERROR_FS_FAIL
2820
        jmp     .ret
2821
 
2288 clevermous 2822
.truncate:
2823
        mov     [edi+28], eax
2824
        push    ecx
2825
        mov     ecx, [edi+20-2]
2826
        mov     cx, [edi+26]
2827
        push    eax
2828
        test    eax, eax
2829
        jz      .zero_size
6845 pathoswith 2830
@@: ; find new last cluster
2643 clevermous 2831
        cmp     ecx, 2
2832
        jb      .error_fat2
2833
        cmp     ecx, [ebp+FAT.fatRESERVED]
2834
        jae     .error_fat2
2835
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2836
        shl     eax, 9
2837
        sub     [esp], eax
2838
        jbe     @f
2839
        mov     eax, ecx
2840
        call    get_FAT
2841
        mov     ecx, eax
2643 clevermous 2842
        jnc     @b
2288 clevermous 2843
.device_err3:
6845 pathoswith 2844
        pop     eax ecx eax
2643 clevermous 2845
        call    update_disk
6845 pathoswith 2846
        push    ERROR_DEVICE
2847
        jmp     .ret
2848
 
2288 clevermous 2849
@@:
2850
; we will zero data at the end of last sector - remember it
2851
        push    ecx
2852
; terminate FAT chain
2853
        push    edx
2854
        mov     eax, ecx
2643 clevermous 2855
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2856
        call    set_FAT
2857
        mov     eax, edx
2858
        pop     edx
2643 clevermous 2859
        jnc     @f
2288 clevermous 2860
.device_err4:
2861
        pop     ecx
2862
        jmp     .device_err3
6845 pathoswith 2863
 
2288 clevermous 2864
.zero_size:
2865
        and     word [edi+20], 0
2866
        and     word [edi+26], 0
2867
        push    0
2868
        mov     eax, ecx
2869
@@:
2870
; delete FAT chain
2871
        call    clear_cluster_chain
2643 clevermous 2872
        jc      .device_err4
2288 clevermous 2873
; save directory
2874
        mov     eax, [esp+12]
2875
        push    ebx
2643 clevermous 2876
        lea     ebx, [ebp+FAT.buffer]
2877
        call    fs_write32_sys
2288 clevermous 2878
        pop     ebx
2643 clevermous 2879
        test    eax, eax
2288 clevermous 2880
        jnz     .device_err4
2881
; zero last sector, ignore errors
2882
        pop     ecx
2883
        pop     eax
2884
        dec     ecx
2643 clevermous 2885
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2886
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 2887
        push    eax
2888
        sar     eax, 9
2889
        add     ecx, eax
2890
        pop     eax
2891
        and     eax, 0x1FF
2892
        jz      .truncate_done
2893
        push    ebx eax
2894
        mov     eax, ecx
2643 clevermous 2895
        lea     ebx, [ebp+FAT.buffer]
2896
        call    fs_read32_app
2288 clevermous 2897
        pop     eax
2643 clevermous 2898
        lea     edi, [ebp+FAT.buffer+eax]
2288 clevermous 2899
        push    ecx
2900
        mov     ecx, 0x200
2901
        sub     ecx, eax
2902
        xor     eax, eax
2903
        rep stosb
2904
        pop     eax
2643 clevermous 2905
        call    fs_write32_app
2288 clevermous 2906
        pop     ebx
2907
.truncate_done:
6867 pathoswith 2908
        pop     ecx eax
2288 clevermous 2909
        call    update_disk
2643 clevermous 2910
        call    fat_unlock
2288 clevermous 2911
        xor     eax, eax
2912
        ret
2913
 
2643 clevermous 2914
;----------------------------------------------------------------
2915
fat_GetFileInfo:
2288 clevermous 2916
        cmp     byte [esi], 0
6868 pathoswith 2917
        jz      .volume
2643 clevermous 2918
        call    fat_lock
6468 pathoswith 2919
        call    hd_find_lfn
6867 pathoswith 2920
        jc      @f
2643 clevermous 2921
        push    ebp
2922
        xor     ebp, ebp
2923
        mov     esi, [ebx+16]
2924
        mov     dword [esi+4], ebp
2925
        call    fat_entry_to_bdfe2
2926
        pop     ebp
2927
        xor     eax, eax
6867 pathoswith 2928
@@:
2643 clevermous 2929
        push    eax
2930
        call    fat_unlock
2931
        pop     eax
6876 pathoswith 2932
@@:
2643 clevermous 2933
        ret
2288 clevermous 2934
 
6868 pathoswith 2935
.volume:
2936
        mov     eax, dword[ebp+FAT.Length]
2937
        mov     edx, dword[ebp+FAT.Length+4]
2938
        mov     edi, [ebx+16]
2939
        shld    edx, eax, 9
2940
        shl     eax, 9
2941
        mov     [edi+36], edx
2942
        mov     [edi+32], eax
2943
        mov     eax, [ebx+8]
2944
        mov     byte [edi], 8
2945
        mov     [edi+4], eax
6876 pathoswith 2946
        test    eax, eax
2947
        jz      @b
6868 pathoswith 2948
        lea     esi, [ebp+FAT.volumeLabel]
2949
        mov     ecx, 11
2950
@@:
2951
        mov     byte [esi+ecx], 0
2952
        dec     ecx
2953
        jz      @f
2954
        cmp     byte [esi+ecx], ' '
2955
        jz      @b
2956
@@:
2957
        mov     cl, 12
2958
        add     edi, 40
2959
        cmp     eax, 2
2960
        jz      @f
2961
        rep movsb
2962
        xor     eax, eax
2963
        ret
2964
 
2965
@@:
2966
        lodsb
2967
        stosw
2968
        loop    @b
2969
        ret
2970
 
2643 clevermous 2971
;----------------------------------------------------------------
2972
fat_SetFileInfo:
2973
        call    fat_lock
6468 pathoswith 2974
        call    hd_find_lfn
6867 pathoswith 2975
        jc      @f
2288 clevermous 2976
        push    eax
2643 clevermous 2977
        mov     edx, [ebx+16]
2288 clevermous 2978
        call    bdfe_to_fat_entry
2979
        pop     eax
2643 clevermous 2980
        lea     ebx, [ebp+FAT.buffer]
2981
        call    fs_write32_sys
2288 clevermous 2982
        call    update_disk
2983
        xor     eax, eax
6867 pathoswith 2984
@@:
2643 clevermous 2985
        push    eax
2986
        call    fat_unlock
2987
        pop     eax
2988
        ret
2288 clevermous 2989
 
2990
;----------------------------------------------------------------
2643 clevermous 2991
fat_Delete:
2992
        call    fat_lock
2993
        and     [ebp+FAT.longname_sec1], 0
2994
        and     [ebp+FAT.longname_sec2], 0
6468 pathoswith 2995
        call    hd_find_lfn
6845 pathoswith 2996
        jc      .notFound
2288 clevermous 2997
        cmp     dword [edi], '.   '
2998
        jz      .access_denied2
2999
        cmp     dword [edi], '..  '
3000
        jz      .access_denied2
3001
        test    byte [edi+11], 10h
3002
        jz      .dodel
3003
; we can delete only empty folders!
3004
        pushad
2643 clevermous 3005
        mov     esi, [edi+20-2]
3006
        mov     si, [edi+26]
2288 clevermous 3007
        xor     ecx, ecx
2643 clevermous 3008
        lea     eax, [esi-2]
3009
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3010
        add     eax, [ebp+FAT.DATA_START]
3011
        lea     ebx, [ebp+FAT.buffer]
3012
        call    fs_read32_sys
3013
        test    eax, eax
2288 clevermous 3014
        jnz     .err1
2643 clevermous 3015
        lea     eax, [ebx+0x200]
2288 clevermous 3016
        add     ebx, 2*0x20
3017
.checkempty:
3018
        cmp     byte [ebx], 0
3019
        jz      .empty
3020
        cmp     byte [ebx], 0xE5
3021
        jnz     .notempty
3022
        add     ebx, 0x20
2643 clevermous 3023
        cmp     ebx, eax
2288 clevermous 3024
        jb      .checkempty
3025
        inc     ecx
2643 clevermous 3026
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 3027
        jb      @f
2643 clevermous 3028
        mov     eax, esi
2288 clevermous 3029
        call    get_FAT
2643 clevermous 3030
        jc      .err1
3174 clevermous 3031
        cmp     eax, 2
3032
        jb      .error_fat
3033
        cmp     eax, [ebp+FAT.fatRESERVED]
3034
        jae     .empty
2643 clevermous 3035
        mov     esi, eax
2288 clevermous 3036
        xor     ecx, ecx
3037
@@:
2643 clevermous 3038
        lea     eax, [esi-2]
3039
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3040
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 3041
        add     eax, ecx
2643 clevermous 3042
        lea     ebx, [ebp+FAT.buffer]
3043
        call    fs_read32_sys
3044
        test    eax, eax
3045
        lea     eax, [ebx+0x200]
2288 clevermous 3046
        jz      .checkempty
3047
.err1:
3048
        popad
3049
.err2:
6845 pathoswith 3050
        push    ERROR_DEVICE
3051
.ret:
2643 clevermous 3052
        call    fat_unlock
6867 pathoswith 3053
        pop     eax
2288 clevermous 3054
        ret
6845 pathoswith 3055
 
3056
.notFound:
3057
        push    ERROR_FILE_NOT_FOUND
3058
        jmp     .ret
3059
 
3174 clevermous 3060
.error_fat:
3061
        popad
6845 pathoswith 3062
        push    ERROR_FS_FAIL
3063
        jmp     .ret
3064
 
2288 clevermous 3065
.notempty:
3066
        popad
3067
.access_denied2:
6845 pathoswith 3068
        push    ERROR_ACCESS_DENIED
3069
        jmp     .ret
3070
 
2288 clevermous 3071
.empty:
3072
        popad
2643 clevermous 3073
        push    eax ebx
3074
        lea     ebx, [ebp+FAT.buffer]
3075
        call    fs_read32_sys
3076
        test    eax, eax
3077
        pop     ebx eax
2288 clevermous 3078
        jnz     .err2
3079
.dodel:
3080
        push    eax
3081
        mov     eax, [edi+20-2]
3082
        mov     ax, [edi+26]
3083
        xchg    eax, [esp]
3084
; delete folder entry
3085
        mov     byte [edi], 0xE5
3086
; delete LFN (if present)
3087
.lfndel:
2643 clevermous 3088
        lea     edx, [ebp+FAT.buffer]
3089
        cmp     edi, edx
2288 clevermous 3090
        ja      @f
2643 clevermous 3091
        cmp     [ebp+FAT.longname_sec2], 0
2288 clevermous 3092
        jz      .lfndone
2643 clevermous 3093
        push    [ebp+FAT.longname_sec2]
3094
        push    [ebp+FAT.longname_sec1]
3095
        pop     [ebp+FAT.longname_sec2]
3096
        and     [ebp+FAT.longname_sec1], 0
2288 clevermous 3097
        push    ebx
2643 clevermous 3098
        mov     ebx, edx
3099
        call    fs_write32_sys
2288 clevermous 3100
        mov     eax, [esp+4]
2643 clevermous 3101
        call    fs_read32_sys
2288 clevermous 3102
        pop     ebx
3103
        pop     eax
2643 clevermous 3104
        lea     edi, [ebp+FAT.buffer+0x200]
2288 clevermous 3105
@@:
3106
        sub     edi, 0x20
3107
        cmp     byte [edi], 0xE5
3108
        jz      .lfndone
3109
        cmp     byte [edi+11], 0xF
3110
        jnz     .lfndone
3111
        mov     byte [edi], 0xE5
3112
        jmp     .lfndel
3113
.lfndone:
3114
        push    ebx
2643 clevermous 3115
        lea     ebx, [ebp+FAT.buffer]
3116
        call    fs_write32_sys
2288 clevermous 3117
        pop     ebx
3118
; delete FAT chain
3119
        pop     eax
3120
        call    clear_cluster_chain
3121
        call    update_disk
2643 clevermous 3122
        call    fat_unlock
2288 clevermous 3123
        xor     eax, eax
3124
        ret
6917 pathoswith 3125
 
3126
;----------------------------------------------------------------
3127
fat_Rename:
3128
; in: edi -> new path string in UTF-8
3129
        push    esi edi
3130
        call    fat_lock
3131
        call    hd_find_lfn
3132
        pop     ebx
3133
        jc      .error
3134
        sub     esp, 32
3135
        mov     esi, edi
3136
        mov     edi, esp
3137
        mov     ecx, 8
3138
        rep movsd
3139
        mov     [ebp+FAT.createOption], 2
3140
        mov     esi, ebx
3141
        call    fat_CreateFile.rename
3142
        add     esp, 32
3143
        pop     esi
3144
        test    eax, eax
3145
        jnz     .ret
3146
        push    eax
3147
        mov     [ebp+FAT.longname_sec1], eax
3148
        mov     [ebp+FAT.longname_sec2], eax
3149
        call    hd_find_lfn
3150
        jc      .error
3151
        mov     byte [edi], 0xE5
3152
        jmp     fat_Delete.lfndel
3153
 
3154
.error:
3155
        push    eax
3156
        call    fat_unlock
3157
        pop     eax ebx
3158
.ret:
3159
        ret