Subversion Repositories Kolibri OS

Rev

Rev 6917 | Rev 7136 | 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: 6939 $
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
@@:
598
        mov     [ebp+FAT.fat_in_cache], eax
2643 clevermous 599
        call    fs_read32_sys
600
        test    eax, eax
6867 pathoswith 601
        jne     .error
602
.inCache:
2643 clevermous 603
        cmp     [ebp+FAT.fs_type], 16
6867 pathoswith 604
        jne     .test32
2288 clevermous 605
        xchg    [ebx+esi], dx   ; save new value and get old value
6867 pathoswith 606
        jmp     .write
2288 clevermous 607
 
6867 pathoswith 608
.test32:
2643 clevermous 609
        mov     eax, [ebp+FAT.fatMASK]
2288 clevermous 610
        and     edx, eax
611
        xor     eax, -1         ; mask for high bits
612
        and     eax, [ebx+esi]  ; get high 4 bits
613
        or      eax, edx
614
        mov     edx, [ebx+esi]  ; get old value
615
        mov     [ebx+esi], eax  ; save new value
6867 pathoswith 616
.write:
617
        mov     [ebp+FAT.fat_change], 1
2643 clevermous 618
        and     edx, [ebp+FAT.fatMASK]
6867 pathoswith 619
.ret:
2288 clevermous 620
        pop     esi ebx eax
621
        ret
6867 pathoswith 622
 
623
.error:
2643 clevermous 624
        stc
6867 pathoswith 625
        jmp     .ret
2288 clevermous 626
 
6867 pathoswith 627
.FAT12:
4273 clevermous 628
        test    edx, 0xF000
6867 pathoswith 629
        jnz     .error
4273 clevermous 630
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
631
        xchg    [ebx+eax*2], dx
632
        mov     [ebp+FAT.fat_change], 1
6867 pathoswith 633
        jmp     .ret
2288 clevermous 634
 
635
get_FAT:
6867 pathoswith 636
; in: eax = cluster
637
; out: eax = next cluster, CF=1 -> error
2288 clevermous 638
        push    ebx esi
4273 clevermous 639
        cmp     [ebp+FAT.fs_type], 12
6867 pathoswith 640
        je      .FAT12
2643 clevermous 641
        cmp     [ebp+FAT.fs_type], 16
6867 pathoswith 642
        je      @f
2288 clevermous 643
        add     eax, eax
6867 pathoswith 644
@@:
2288 clevermous 645
        add     eax, eax
646
        mov     esi, 511
6867 pathoswith 647
        and     esi, eax
648
        shr     eax, 9
2643 clevermous 649
        add     eax, [ebp+FAT.FAT_START]
4273 clevermous 650
        mov     ebx, [ebp+FAT.fat_cache_ptr]
6867 pathoswith 651
        cmp     eax, [ebp+FAT.fat_in_cache]
652
        je      .inCache
653
        cmp     [ebp+FAT.fat_change], 0
654
        je      @f
655
        call    write_fat_sector
656
@@:
2643 clevermous 657
        mov     [ebp+FAT.fat_in_cache], eax
658
        call    fs_read32_sys
659
        test    eax, eax
6867 pathoswith 660
        jnz     .error
661
.inCache:
2288 clevermous 662
        mov     eax, [ebx+esi]
2643 clevermous 663
        and     eax, [ebp+FAT.fatMASK]
6867 pathoswith 664
.ret:
2288 clevermous 665
        pop     esi ebx
666
        ret
6867 pathoswith 667
 
668
.error:
2643 clevermous 669
        stc
6867 pathoswith 670
        jmp     .ret
2288 clevermous 671
 
6867 pathoswith 672
.FAT12:
4273 clevermous 673
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
674
        movzx   eax, word [ebx+eax*2]
6867 pathoswith 675
        jmp     .ret
2288 clevermous 676
 
677
get_free_FAT:
6867 pathoswith 678
; out: eax = number of first free cluster, CF=1 -> disk full
2288 clevermous 679
        push    ecx
6867 pathoswith 680
        mov     ecx, [ebp+FAT.LAST_CLUSTER]
2643 clevermous 681
        mov     eax, [ebp+FAT.fatStartScan]
4273 clevermous 682
        cmp     [ebp+FAT.fs_type], 12
683
        jz      get_free_FAT12
684
        dec     ecx
2288 clevermous 685
        cmp     eax, 2
6867 pathoswith 686
        jb      .reset
687
.test:
688
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
689
        jbe     .inRange
690
.reset:
2288 clevermous 691
        mov     eax, 2
6867 pathoswith 692
.inRange:
2288 clevermous 693
        push    eax
6867 pathoswith 694
        call    get_FAT
695
        jc      @f
696
        test    eax, eax
2288 clevermous 697
        pop     eax
6867 pathoswith 698
        je      .found
699
        inc     eax
700
        dec     ecx
701
        jnz     .test
702
.notFound:
703
        pop     ecx
2288 clevermous 704
        stc
705
        ret
706
 
6867 pathoswith 707
@@:
2643 clevermous 708
        pop     eax
6867 pathoswith 709
        jmp     .notFound
2643 clevermous 710
 
6867 pathoswith 711
.found:
2288 clevermous 712
        lea     ecx, [eax+1]
2643 clevermous 713
        mov     [ebp+FAT.fatStartScan], ecx
2288 clevermous 714
        pop     ecx
715
        clc
716
        ret
717
 
4273 clevermous 718
get_free_FAT12:
719
        push    edx edi
720
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
721
        cmp     eax, 2
722
        jb      .reset
723
        cmp     eax, ecx
724
        jbe     @f
725
.reset:
726
        mov     eax, 2
727
@@:
728
        mov     edx, eax
729
        lea     edi, [edi+eax*2]
730
        sub     ecx, eax
731
        inc     ecx
732
        xor     eax, eax
733
        repnz scasw
734
        jz      .found
735
        cmp     edx, 2
736
        jz      .notfound
737
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
738
        lea     ecx, [edx-2]
739
        repnz scasw
740
        jnz     .notfound
741
.found:
742
        sub     edi, [ebp+FAT.fat12_unpacked_ptr]
743
        shr     edi, 1
744
        mov     [ebp+FAT.fatStartScan], edi
745
        lea     eax, [edi-1]
6867 pathoswith 746
@@:
4273 clevermous 747
        pop     edi edx ecx
748
        ret
6867 pathoswith 749
 
4273 clevermous 750
.notfound:
751
        stc
6867 pathoswith 752
        jmp     @b
2288 clevermous 753
 
754
write_fat_sector:
755
        push    eax ebx ecx
2643 clevermous 756
        mov     [ebp+FAT.fat_change], 0
757
        mov     eax, [ebp+FAT.fat_in_cache]
2288 clevermous 758
        cmp     eax, -1
6867 pathoswith 759
        jz      @f
4273 clevermous 760
        mov     ebx, [ebp+FAT.fat_cache_ptr]
2643 clevermous 761
        mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
6867 pathoswith 762
.write_next_fat:
2643 clevermous 763
        push    eax
764
        call    fs_write32_sys
765
        pop     eax
766
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
2288 clevermous 767
        dec     ecx
6867 pathoswith 768
        jnz     .write_next_fat
769
@@:
2288 clevermous 770
        pop     ecx ebx eax
771
        ret
772
 
773
get_date_for_file:
6867 pathoswith 774
;   out in ax:
775
; bits 0-4 = day
776
; bits 5-8 = month
777
; bits 9-15 = count of years from 1980
778
        mov     al, 7
779
        call    fsReadCMOS
2288 clevermous 780
        ror     eax, 5
6867 pathoswith 781
        mov     al, 8
782
        call    fsReadCMOS
2288 clevermous 783
        ror     eax, 4
6867 pathoswith 784
        mov     al, 9
785
        call    fsReadCMOS
786
        add     ax, 20
787
        rol     eax, 9
2288 clevermous 788
        ret
789
 
790
get_time_for_file:
6867 pathoswith 791
;   out in ax:
792
; bits 0-4 = second (the low bit is lost)
793
; bits 5-10 = minute
794
; bits 11-15 = hour
795
        mov     al, 0
796
        call    fsReadCMOS
2288 clevermous 797
        ror     eax, 6
6867 pathoswith 798
        mov     al, 2
799
        call    fsReadCMOS
2288 clevermous 800
        ror     eax, 6
6867 pathoswith 801
        mov     al, 4
802
        call    fsReadCMOS
2288 clevermous 803
        rol     eax, 11
804
        ret
805
 
806
add_disk_free_space:
6867 pathoswith 807
; in: ecx = cluster count (signed)
808
        test    ecx, ecx
809
        je      .ret
810
        cmp     [ebp+FAT.fs_type], 32
811
        jne     .ret
2288 clevermous 812
        push    eax ebx
2643 clevermous 813
        mov     eax, [ebp+FAT.ADR_FSINFO]
814
        lea     ebx, [ebp+FAT.fsinfo_buffer]
815
        call    fs_read32_sys
816
        test    eax, eax
6867 pathoswith 817
        jnz     @f
818
        cmp     dword [ebx+0x1fc], 0xaa550000   ; check sector id
819
        jne     @f
2288 clevermous 820
        add     [ebx+0x1e8], ecx
2643 clevermous 821
        push    [ebp+FAT.fatStartScan]
2288 clevermous 822
        pop     dword [ebx+0x1ec]
2643 clevermous 823
        mov     eax, [ebp+FAT.ADR_FSINFO]
824
        call    fs_write32_sys
6867 pathoswith 825
@@:
2288 clevermous 826
        pop     ebx eax
6867 pathoswith 827
.ret:
2288 clevermous 828
        ret
829
 
830
clear_cluster_chain:
6867 pathoswith 831
; in: eax = first cluster
2288 clevermous 832
        push    eax ecx edx
833
        xor     ecx, ecx        ; cluster count
6867 pathoswith 834
@@:
835
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
836
        ja      @f
837
        cmp     eax, 2
838
        jb      @f
839
        cmp     eax, [ebp+FAT.ROOT_CLUSTER]
840
        jz      @f
2288 clevermous 841
        xor     edx, edx
6867 pathoswith 842
        call    set_FAT
843
        jc      .ret
844
        inc     ecx
845
        mov     eax, edx
846
        jmp     @b
2288 clevermous 847
 
6867 pathoswith 848
@@:
849
        call    add_disk_free_space
2643 clevermous 850
        clc
6867 pathoswith 851
.ret:
2288 clevermous 852
        pop     edx ecx eax
853
        ret
854
 
855
update_disk:
6867 pathoswith 856
        cmp     [ebp+FAT.fat_change], 0
857
        jz      .noChange
4273 clevermous 858
        cmp     [ebp+FAT.fs_type], 12
859
        jz      .fat12
2288 clevermous 860
        call    write_fat_sector
6867 pathoswith 861
.noChange:
2643 clevermous 862
        mov     esi, [ebp+PARTITION.Disk]
863
        call    disk_sync
2288 clevermous 864
        ret
865
 
6867 pathoswith 866
.fat12:
867
        mov     esi, [ebp+FAT.fat12_unpacked_ptr]
868
        mov     edi, [ebp+FAT.fat_cache_ptr]
869
        mov     edx, [ebp+FAT.LAST_CLUSTER]
870
        and     edx, not 7
871
        lea     edx, [esi+(edx+8)*2]
872
@@:
873
        mov     eax, dword [esi]
874
        mov     ebx, dword [esi+4]
875
        shl     ax, 4
876
        shl     eax, 4
877
        shl     bx, 4
878
        shr     ebx, 4
879
        shrd    eax, ebx, 8
880
        shr     ebx, 8
881
        mov     dword [edi], eax
882
        mov     word [edi+4], bx
883
        add     edi, 6
884
        add     esi, 8
885
        cmp     esi, edx
886
        jb      @b
887
        mov     esi, [ebp+FAT.NUMBER_OF_FATS]
888
        mov     edx, [ebp+FAT.LAST_CLUSTER]
889
        lea     edx, [(edx+1)*3 + 512*2-1]
890
        shr     edx, 10
891
        push    [ebp+FAT.FAT_START]
892
.write_fats:
893
        xor     eax, eax
894
        mov     ebx, [ebp+FAT.fat_cache_ptr]
895
.loop1:
896
        push    eax
897
        add     eax, [esp+4]
898
        call    fs_write32_sys
899
        test    eax, eax
900
        pop     eax
901
        jnz     @f
902
        add     ebx, 512
903
        inc     eax
904
        cmp     eax, edx
905
        jb      .loop1
906
        pop     eax
907
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
908
        push    eax
909
        dec     esi
910
        jnz     .write_fats
911
@@:
912
        pop     eax
913
        mov     [ebp+FAT.fat_change], 0
914
        jmp     .noChange
915
 
2643 clevermous 916
fat_lock:
917
        lea     ecx, [ebp+FAT.Lock]
918
        jmp     mutex_lock
6867 pathoswith 919
 
2643 clevermous 920
fat_unlock:
921
        lea     ecx, [ebp+FAT.Lock]
922
        jmp     mutex_unlock
2288 clevermous 923
 
4273 clevermous 924
fat_get_name:
6868 pathoswith 925
; in: edi -> FAT entry, esi -> buffer for UTF-16 name
926
; out: CF=1 -> no valid entry
4273 clevermous 927
        cmp     byte [edi], 0
928
        jz      .no
929
        cmp     byte [edi], 0xE5
6471 pathoswith 930
        jz      .no
4273 clevermous 931
        cmp     byte [edi+11], 0xF
932
        jz      .longname
6868 pathoswith 933
        push    edi
934
        xchg    esi, edi
935
        test    byte [esi+11], 8
936
        jnz     .label
937
        pushd   ecx 8
938
        pop     ecx
939
        xor     eax, eax
4273 clevermous 940
@@:
6471 pathoswith 941
        lodsb
942
        stosw
4273 clevermous 943
        loop    @b
6471 pathoswith 944
        mov     cl, 8
4273 clevermous 945
@@:
6471 pathoswith 946
        cmp     word [edi-2], ' '
4273 clevermous 947
        jnz     @f
6471 pathoswith 948
        sub     edi, 2
4273 clevermous 949
        loop    @b
950
@@:
6471 pathoswith 951
        mov     word [edi], '.'
952
        add     edi, 2
953
        mov     cl, 3
4273 clevermous 954
@@:
6471 pathoswith 955
        lodsb
956
        stosw
4273 clevermous 957
        loop    @b
6471 pathoswith 958
        mov     cl, 3
4273 clevermous 959
@@:
6471 pathoswith 960
        cmp     word [edi-2], ' '
4273 clevermous 961
        jnz     @f
6471 pathoswith 962
        sub     edi, 2
4273 clevermous 963
        loop    @b
6471 pathoswith 964
        sub     edi, 2
4273 clevermous 965
@@:
6471 pathoswith 966
        and     word [edi], 0   ; CF=0
6868 pathoswith 967
        pop     ecx edi
4273 clevermous 968
        ret
6471 pathoswith 969
 
6868 pathoswith 970
.label:
971
        lea     edi, [ebp+FAT.volumeLabel]
972
        movsd
973
        movsd
974
        movsd
975
        pop     edi
6471 pathoswith 976
.no:
977
        stc
978
        ret
979
 
4273 clevermous 980
.longname:
981
        mov     al, byte [edi]
982
        and     eax, 0x3F
983
        dec     eax
984
        cmp     al, 20
985
        jae     .no     ; ignore invalid entries
6868 pathoswith 986
        mov     word [esi+260*2], 0     ; force null-terminating for orphans
4273 clevermous 987
        imul    eax, 13*2
988
        test    byte [edi], 0x40
989
        jz      @f
6868 pathoswith 990
        mov     word [esi+eax+13*2], 0
6471 pathoswith 991
@@: ; copy name (13 chars in UTF-16)
6868 pathoswith 992
        push    edi
993
        inc     edi
994
        add     esi, eax
995
        xchg    esi, edi
6471 pathoswith 996
        movsd
997
        movsd
6868 pathoswith 998
        movsw
999
        add     esi, 3
6471 pathoswith 1000
        movsd
1001
        movsd
1002
        movsd
1003
        add     esi, 2
1004
        movsd
6868 pathoswith 1005
        pop     edi
6471 pathoswith 1006
        test    eax, eax
1007
        jnz     .no ; if this is not first entry, more processing required
4273 clevermous 1008
        ret
1009
 
6868 pathoswith 1010
fat_find_lfn:
1011
;   in:
1012
; esi -> path in UTF-8
1013
; parameters in the stack
6471 pathoswith 1014
;   out:
6868 pathoswith 1015
; esi -> next name in the path
1016
; edi -> direntry
1017
; CF=1 -> file not found, eax = error code
1018
        lea     eax, [esp+12]
1019
        call    dword [eax-4]
1020
        jc      .reterr
1021
        sub     esp, 262*2      ; reserve place for LFN
1022
.l1:
1023
        push    esi
1024
        lea     esi, [esp+4]
1025
        call    fat_get_name
1026
        pop     esi
1027
        jc      .no
1028
        push    edi esi
1029
        lea     edi, [esp+8]
6471 pathoswith 1030
@@:
1031
        call    utf8to16
1032
        call    utf16toUpper
1033
        mov     edx, eax
6868 pathoswith 1034
        mov     ax, [edi]
6471 pathoswith 1035
        call    utf16toUpper
1036
        cmp     ax, dx
4273 clevermous 1037
        jnz     .done
6868 pathoswith 1038
        add     edi, 2
6471 pathoswith 1039
        test    ax, ax
1040
        jnz     @b
4273 clevermous 1041
        dec     esi
6868 pathoswith 1042
        pop     eax edi
1043
.found:
1044
        add     esp, 262*2
1045
; if this is LFN entry, advance to true entry
1046
        cmp     byte [edi+11], 0xF
1047
        jnz     @f
1048
        lea     eax, [esp+12]
1049
        call    dword[eax-8]
1050
        jc      .reterr
1051
@@:
1052
        xor     eax, eax
4273 clevermous 1053
        ret
6471 pathoswith 1054
 
4273 clevermous 1055
.done:
6471 pathoswith 1056
        cmp     dx, '/'
4273 clevermous 1057
        jnz     @f
6471 pathoswith 1058
        test    ax, ax
4273 clevermous 1059
        jnz     @f
6471 pathoswith 1060
        mov     [esp], esi
4273 clevermous 1061
@@:
6868 pathoswith 1062
        pop     esi edi
4273 clevermous 1063
        jz      .found
6868 pathoswith 1064
.no:
1065
        lea     eax, [esp+262*2+12]
1066
        call    dword[eax-8]
4273 clevermous 1067
        jnc     .l1
6471 pathoswith 1068
        add     esp, 262*2
4273 clevermous 1069
.reterr:
1070
        stc
1071
        ret
6471 pathoswith 1072
 
4273 clevermous 1073
fat_time_to_bdfe:
1074
; in: eax=FAT time
1075
; out: eax=BDFE time
1076
        push    ecx edx
1077
        mov     ecx, eax
1078
        mov     edx, eax
1079
        shr     eax, 11
1080
        shl     eax, 16 ; hours
1081
        and     edx, 0x1F
1082
        add     edx, edx
1083
        mov     al, dl  ; seconds
1084
        shr     ecx, 5
1085
        and     ecx, 0x3F
1086
        mov     ah, cl  ; minutes
1087
        pop     edx ecx
1088
        ret
1089
 
1090
fat_date_to_bdfe:
1091
        push    ecx edx
1092
        mov     ecx, eax
1093
        mov     edx, eax
1094
        shr     eax, 9
1095
        add     ax, 1980
1096
        shl     eax, 16 ; year
1097
        and     edx, 0x1F
1098
        mov     al, dl  ; day
1099
        shr     ecx, 5
1100
        and     ecx, 0xF
1101
        mov     ah, cl  ; month
1102
        pop     edx ecx
1103
        ret
1104
 
1105
bdfe_to_fat_time:
1106
        push    edx
1107
        mov     edx, eax
1108
        shr     eax, 16
1109
        and     dh, 0x3F
1110
        shl     eax, 6
1111
        or      al, dh
1112
        shr     dl, 1
1113
        and     dl, 0x1F
1114
        shl     eax, 5
1115
        or      al, dl
1116
        pop     edx
1117
        ret
1118
 
1119
bdfe_to_fat_date:
1120
        push    edx
1121
        mov     edx, eax
1122
        shr     eax, 16
1123
        sub     ax, 1980
1124
        and     dh, 0xF
1125
        shl     eax, 4
1126
        or      al, dh
1127
        and     dl, 0x1F
1128
        shl     eax, 5
1129
        or      al, dl
1130
        pop     edx
1131
        ret
1132
 
1133
fat_entry_to_bdfe:
1134
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
1135
        mov     eax, [ebp-4]
6471 pathoswith 1136
        mov     [esi+4], eax    ; cp866/UNICODE name
4273 clevermous 1137
fat_entry_to_bdfe2:
1138
        movzx   eax, byte [edi+11]
1139
        mov     [esi], eax      ; attributes
1140
        movzx   eax, word [edi+14]
1141
        call    fat_time_to_bdfe
1142
        mov     [esi+8], eax    ; creation time
1143
        movzx   eax, word [edi+16]
1144
        call    fat_date_to_bdfe
1145
        mov     [esi+12], eax   ; creation date
1146
        and     dword [esi+16], 0       ; last access time is not supported on FAT
1147
        movzx   eax, word [edi+18]
1148
        call    fat_date_to_bdfe
1149
        mov     [esi+20], eax   ; last access date
1150
        movzx   eax, word [edi+22]
1151
        call    fat_time_to_bdfe
1152
        mov     [esi+24], eax   ; last write time
1153
        movzx   eax, word [edi+24]
1154
        call    fat_date_to_bdfe
1155
        mov     [esi+28], eax   ; last write date
1156
        mov     eax, [edi+28]
1157
        mov     [esi+32], eax   ; file size (low dword)
1158
        xor     eax, eax
1159
        mov     [esi+36], eax   ; file size (high dword)
1160
        test    ebp, ebp
1161
        jz      .ret
6576 pathoswith 1162
        add     esi, 40
1163
        push    edi esi
1164
        mov     edi, esi
4273 clevermous 1165
        mov     esi, ebp
6798 pathoswith 1166
        cmp     byte [ebp-4], 2
1167
        jz      .utf16
1168
        cmp     byte [ebp-4], 3
1169
        jz      .utf8
1170
@@:
6576 pathoswith 1171
        lodsw
6798 pathoswith 1172
        call    uni2ansi_char
1173
        stosb
1174
        test    al, al
1175
        jnz     @b
6576 pathoswith 1176
        pop     esi edi
6798 pathoswith 1177
        add     esi, 264
4273 clevermous 1178
.ret:
1179
        ret
6471 pathoswith 1180
 
6798 pathoswith 1181
.utf8:
1182
        push    ecx
1183
        mov     ecx, 519
1184
        call    UTF16to8_string
1185
        pop     ecx
1186
        jmp     @f
1187
 
1188
.utf16:
6471 pathoswith 1189
        lodsw
6798 pathoswith 1190
        stosw
1191
        test    eax, eax
1192
        jnz     .utf16
1193
@@:
6576 pathoswith 1194
        pop     esi edi
6798 pathoswith 1195
        add     esi, 520
6576 pathoswith 1196
        ret
4273 clevermous 1197
 
1198
bdfe_to_fat_entry:
1199
; convert BDFE at edx to FAT entry at edi
1200
; destroys eax
1201
; attributes byte
1202
        test    byte [edi+11], 8        ; volume label?
1203
        jnz     @f
1204
        mov     al, [edx]
1205
        and     al, 0x27
1206
        and     byte [edi+11], 0x10
1207
        or      byte [edi+11], al
1208
@@:
1209
        mov     eax, [edx+8]
1210
        call    bdfe_to_fat_time
1211
        mov     [edi+14], ax            ; creation time
1212
        mov     eax, [edx+12]
1213
        call    bdfe_to_fat_date
1214
        mov     [edi+16], ax            ; creation date
1215
        mov     eax, [edx+20]
1216
        call    bdfe_to_fat_date
1217
        mov     [edi+18], ax            ; last access date
1218
        mov     eax, [edx+24]
1219
        call    bdfe_to_fat_time
1220
        mov     [edi+22], ax            ; last write time
1221
        mov     eax, [edx+28]
1222
        call    bdfe_to_fat_date
1223
        mov     [edi+24], ax            ; last write date
1224
        ret
1225
 
2288 clevermous 1226
hd_find_lfn:
6471 pathoswith 1227
; in: esi -> path string in UTF-8
2643 clevermous 1228
; out: CF=1 - file not found, eax=error code
2288 clevermous 1229
;      else CF=0 and edi->direntry, eax=sector
1230
        push    esi edi
1231
        push    0
1232
        push    0
4273 clevermous 1233
        push    fat1x_root_first
1234
        push    fat1x_root_next
2643 clevermous 1235
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
1236
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1237
        jz      .fat32
1238
.loop:
4273 clevermous 1239
        and     [ebp+FAT.longname_sec1], 0
1240
        and     [ebp+FAT.longname_sec2], 0
2288 clevermous 1241
        call    fat_find_lfn
1242
        jc      .notfound
1243
        cmp     byte [esi], 0
1244
        jz      .found
1245
        test    byte [edi+11], 10h
1246
        jz      .notfound
1247
        and     dword [esp+12], 0
1248
        mov     eax, [edi+20-2]
1249
        mov     ax, [edi+26]    ; cluster
1250
.fat32:
1251
        mov     [esp+8], eax
1252
        mov     dword [esp+4], fat_notroot_first
1253
        mov     dword [esp], fat_notroot_next
1254
        jmp     .loop
6468 pathoswith 1255
 
2288 clevermous 1256
.notfound:
1257
        add     esp, 16
1258
        pop     edi esi
1259
        stc
6468 pathoswith 1260
        ret
1261
 
2288 clevermous 1262
.found:
1263
        lea     eax, [esp+8]
1264
        cmp     dword [eax], 0
1265
        jz      .root
1266
        call    fat_get_sector
1267
        jmp     .cmn
6468 pathoswith 1268
 
2288 clevermous 1269
.root:
1270
        mov     eax, [eax+4]
2643 clevermous 1271
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 1272
.cmn:
1273
        add     esp, 20         ; CF=0
1274
        pop     esi
6468 pathoswith 1275
        ret
2288 clevermous 1276
 
1277
;----------------------------------------------------------------
2643 clevermous 1278
fat_Read:
1279
        call    fat_lock
6468 pathoswith 1280
        call    hd_find_lfn
6845 pathoswith 1281
        jc      .notFound
5578 Pathoswith 1282
        test    byte [edi+11], 0x10     ; do not allow read directories
2288 clevermous 1283
        jnz     .noaccess
2643 clevermous 1284
        cmp     dword [ebx+8], 0
6845 pathoswith 1285
        jnz     .endOfFile
5578 Pathoswith 1286
        mov     edx, [ebx+4]    ; file offset
2643 clevermous 1287
        mov     ecx, [ebx+12]   ; size
5578 Pathoswith 1288
        mov     ebx, [ebx+16]   ; buffer
1289
        push    ebx
2288 clevermous 1290
        push    0
6037 pathoswith 1291
        test    ecx, ecx
1292
        jz      .done
2288 clevermous 1293
        mov     eax, [edi+28]
5578 Pathoswith 1294
        sub     eax, edx
1295
        jb      .fileEnd
2288 clevermous 1296
        cmp     eax, ecx
1297
        jae     @f
1298
        mov     ecx, eax
1299
        mov     byte [esp], 6
1300
@@:
1301
        mov     eax, [edi+20-2]
1302
        mov     ax, [edi+26]
5578 Pathoswith 1303
; now eax=cluster, ebx=buffer for data, ecx=count, edx=position
1304
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1305
        shl     edi, 9
1306
@@:
2643 clevermous 1307
        cmp     eax, 2
5578 Pathoswith 1308
        jb      .fileEnd
2643 clevermous 1309
        cmp     eax, [ebp+FAT.fatRESERVED]
5578 Pathoswith 1310
        jae     .fileEnd
1311
        sub     edx, edi
1312
        jc      @f
1313
        call    get_FAT
1314
        jc      .noaccess2
1315
        jmp     @b
6845 pathoswith 1316
 
1317
.notFound:
1318
        push    eax
1319
        jmp     .ret
1320
 
1321
.noaccess:
1322
        push    ERROR_ACCESS_DENIED
1323
        jmp     .ret
1324
 
1325
.endOfFile:
1326
        push    ERROR_END_OF_FILE
1327
.ret:
1328
        call    fat_unlock
6867 pathoswith 1329
        pop     eax
6845 pathoswith 1330
        xor     ebx, ebx
1331
        ret
1332
 
5578 Pathoswith 1333
@@:
1334
        mov     esi, eax
2288 clevermous 1335
        dec     eax
1336
        dec     eax
5578 Pathoswith 1337
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2643 clevermous 1338
        add     eax, [ebp+FAT.DATA_START]
5578 Pathoswith 1339
        add     edx, edi
1340
        jz      .alignedCluster
1341
        mov     edi, edx
1342
        shr     edi, 9
1343
        add     eax, edi
1344
        and     edx, 511
5840 pathoswith 1345
        cmp     ecx, 512
1346
        jc      .sectorPiece
1347
        test    edx, edx
5578 Pathoswith 1348
        jz      .alignedSector
1349
.sectorPiece:
2643 clevermous 1350
        push    eax ebx
1351
        lea     ebx, [ebp+FAT.buffer]
1352
        call    fs_read32_app
1353
        test    eax, eax
2288 clevermous 1354
        mov     eax, ebx
1355
        pop     ebx
5578 Pathoswith 1356
        jne     .noaccess3
1357
        add     eax, edx
2288 clevermous 1358
        push    ecx
5578 Pathoswith 1359
        add     ecx, edx
2288 clevermous 1360
        cmp     ecx, 512
1361
        jbe     @f
1362
        mov     ecx, 512
1363
@@:
5578 Pathoswith 1364
        sub     ecx, edx
2288 clevermous 1365
        call    memmove
1366
        sub     [esp], ecx
5578 Pathoswith 1367
        add     ebx, ecx
1368
        pop     ecx eax
1369
        xor     edx, edx
1370
        inc     edi
2288 clevermous 1371
        inc     eax
5578 Pathoswith 1372
        test    ecx, ecx
1373
        jz      .done
1374
.alignedSector:
1375
        shl     edi, 9
1376
        add     ecx, edi
1377
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1378
        shl     edi, 9
1379
.alignedCluster:
1380
        cmp     ecx, 512
1381
        jc      .sectorPiece
1382
        mov     edx, eax
1383
        mov     eax, esi
1384
@@:
1385
        sub     ecx, edi
1386
        jbe     .readEnd
2288 clevermous 1387
        call    get_FAT
5578 Pathoswith 1388
        jc      .noaccess4
1389
        cmp     eax, 2
1390
        jb      .fileEnd2
1391
        cmp     eax, [ebp+FAT.fatRESERVED]
1392
        jae     .fileEnd2
1393
        inc     esi
1394
        cmp     eax, esi
1395
        jz      @b
1396
.fragmentEnd:
1397
        xchg    eax, esi
1398
        dec     eax
1399
        dec     eax
1400
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1401
        add     eax, [ebp+FAT.DATA_START]
1402
        push    ecx
1403
        mov     ecx, eax
5840 pathoswith 1404
        mov     eax, esi
1405
        dec     eax
1406
        dec     eax
1407
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1408
        add     eax, [ebp+FAT.DATA_START]
1409
        push    eax
1410
.readFragment:
1411
        sub     ecx, edx
5578 Pathoswith 1412
        mov     eax, edx
1413
        xor     edx, edx
1414
        call    fs_read64_app
1415
        shl     ecx, 9
1416
        add     ebx, ecx
1417
        test    eax, eax
2288 clevermous 1418
        pop     eax
5578 Pathoswith 1419
        jnz     .noaccess3
1420
        pop     ecx
1421
        xor     edx, edx
6036 pathoswith 1422
        jecxz   .done
5578 Pathoswith 1423
        jmp     .alignedCluster
6845 pathoswith 1424
 
5578 Pathoswith 1425
.readEnd:
1426
        add     ecx, edi
1427
        mov     edi, ecx
1428
        and     ecx, 511
1429
        shr     edi, 9
1430
        dec     eax
1431
        dec     eax
1432
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1433
        add     eax, [ebp+FAT.DATA_START]
1434
        add     eax, edi
5840 pathoswith 1435
        push    ecx
1436
        push    eax
1437
        mov     ecx, eax
5578 Pathoswith 1438
        jmp     .readFragment
6845 pathoswith 1439
 
5578 Pathoswith 1440
.noaccess3:
2288 clevermous 1441
        pop     eax
5578 Pathoswith 1442
.noaccess2:
1443
        mov     byte [esp], ERROR_DEVICE
2288 clevermous 1444
.done:
2643 clevermous 1445
        call    fat_unlock
6867 pathoswith 1446
        pop     eax edx
2288 clevermous 1447
        sub     ebx, edx
1448
        ret
6845 pathoswith 1449
 
5578 Pathoswith 1450
.fileEnd:
1451
        mov     byte [esp], ERROR_END_OF_FILE
1452
        jmp     .done
6845 pathoswith 1453
 
5578 Pathoswith 1454
.noaccess4:
1455
        mov     byte [esp], ERROR_DEVICE
1456
        jmp     @f
6845 pathoswith 1457
 
5578 Pathoswith 1458
.fileEnd2:
1459
        mov     byte [esp], ERROR_END_OF_FILE
1460
@@:
1461
        inc     esi
1462
        xor     ecx, ecx
1463
        jmp     .fragmentEnd
2288 clevermous 1464
 
1465
;----------------------------------------------------------------
2643 clevermous 1466
fat_ReadFolder:
1467
        call    fat_lock
1468
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
2288 clevermous 1469
        cmp     byte [esi], 0
1470
        jz      .doit
6468 pathoswith 1471
        call    hd_find_lfn
6867 pathoswith 1472
        jc      .error
2288 clevermous 1473
        test    byte [edi+11], 0x10     ; do not allow read files
6867 pathoswith 1474
        jz      .accessDenied
2288 clevermous 1475
        mov     eax, [edi+20-2]
1476
        mov     ax, [edi+26]    ; eax=cluster
1477
.doit:
1478
        sub     esp, 262*2      ; reserve space for LFN
6471 pathoswith 1479
        push    dword [ebx+8]   ; cp866/UNICODE name
2643 clevermous 1480
        mov     edx, [ebx+16]   ; pointer to buffer
2288 clevermous 1481
; init header
2643 clevermous 1482
        push    eax
2288 clevermous 1483
        mov     edi, edx
1484
        mov     ecx, 32/4
1485
        xor     eax, eax
1486
        rep stosd
2643 clevermous 1487
        pop     eax
2288 clevermous 1488
        mov     byte [edx], 1   ; version
1489
        mov     esi, edi        ; esi points to BDFE
2643 clevermous 1490
        mov     ecx, [ebx+12]   ; number of blocks to read
1491
        mov     ebx, [ebx+4]    ; index of the first block
2288 clevermous 1492
.new_cluster:
2643 clevermous 1493
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 1494
        test    eax, eax
1495
        jnz     @f
2643 clevermous 1496
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1497
        jz      .notfound
2643 clevermous 1498
        mov     eax, [ebp+FAT.ROOT_START]
1499
        push    [ebp+FAT.ROOT_SECTORS]
2288 clevermous 1500
        push    ebx
1501
        jmp     .new_sector
6867 pathoswith 1502
 
2288 clevermous 1503
@@:
1504
        dec     eax
1505
        dec     eax
2643 clevermous 1506
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1507
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
1508
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1509
        push    ebx
1510
.new_sector:
2643 clevermous 1511
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 1512
        mov     edi, ebx
2643 clevermous 1513
        push    eax
1514
        call    fs_read32_sys
1515
        test    eax, eax
1516
        pop     eax
2288 clevermous 1517
        jnz     .notfound2
1518
        add     ebx, 512
1519
        push    eax
1520
.l1:
6868 pathoswith 1521
        push    esi
1522
        lea     esi, [esp+20]
2288 clevermous 1523
        call    fat_get_name
6868 pathoswith 1524
        pop     esi
2288 clevermous 1525
        jc      .l2
1526
        cmp     byte [edi+11], 0xF
1527
        jnz     .do_bdfe
1528
        add     edi, 0x20
1529
        cmp     edi, ebx
1530
        jb      .do_bdfe
1531
        pop     eax
1532
        inc     eax
1533
        dec     dword [esp+4]
1534
        jnz     @f
2643 clevermous 1535
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 1536
        test    eax, eax
1537
        jz      .done
1538
        call    get_FAT
2643 clevermous 1539
        jc      .notfound2
2288 clevermous 1540
        cmp     eax, 2
1541
        jb      .done
2643 clevermous 1542
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1543
        jae     .done
1544
        push    eax
2643 clevermous 1545
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1546
        mov     [esp+8], eax
1547
        pop     eax
2643 clevermous 1548
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 1549
        dec     eax
1550
        dec     eax
2643 clevermous 1551
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1552
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1553
@@:
2643 clevermous 1554
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 1555
        mov     edi, ebx
2643 clevermous 1556
        push    eax
1557
        call    fs_read32_sys
1558
        test    eax, eax
1559
        pop     eax
2288 clevermous 1560
        jnz     .notfound2
1561
        add     ebx, 512
1562
        push    eax
1563
.do_bdfe:
1564
        inc     dword [edx+8]   ; new file found
1565
        dec     dword [esp+4]
1566
        jns     .l2
1567
        dec     ecx
1568
        js      .l2
1569
        inc     dword [edx+4]   ; new file block copied
2643 clevermous 1570
        push    ebp
1571
        lea     ebp, [esp+20]
2288 clevermous 1572
        call    fat_entry_to_bdfe
2643 clevermous 1573
        pop     ebp
2288 clevermous 1574
.l2:
1575
        add     edi, 0x20
1576
        cmp     edi, ebx
1577
        jb      .l1
1578
        pop     eax
1579
        inc     eax
1580
        dec     dword [esp+4]
1581
        jnz     .new_sector
2643 clevermous 1582
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 1583
        test    eax, eax
1584
        jz      .done
1585
        call    get_FAT
2643 clevermous 1586
        jc      .notfound2
2288 clevermous 1587
        cmp     eax, 2
1588
        jb      .done
2643 clevermous 1589
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1590
        jae     .done
1591
        push    eax
2643 clevermous 1592
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1593
        mov     [esp+8], eax
1594
        pop     eax
1595
        pop     ebx
1596
        add     esp, 4
1597
        jmp     .new_cluster
6867 pathoswith 1598
 
2288 clevermous 1599
.notfound2:
1600
        add     esp, 8
1601
.notfound:
6868 pathoswith 1602
        add     esp, 262*2+4
6867 pathoswith 1603
        push    ERROR_DEVICE
1604
        jmp     @f
1605
 
2288 clevermous 1606
.done:
6868 pathoswith 1607
        add     esp, 262*2+12
6867 pathoswith 1608
        pushd   0
2288 clevermous 1609
        dec     ecx
1610
        js      @f
6867 pathoswith 1611
        mov     byte [esp], ERROR_END_OF_FILE
2288 clevermous 1612
@@:
6867 pathoswith 1613
        mov     ebx, [edx+4]
1614
.ret:
2643 clevermous 1615
        call    fat_unlock
1616
        pop     eax
2288 clevermous 1617
        ret
1618
 
6867 pathoswith 1619
.error:
1620
        push    eax
1621
        xor     ebx, ebx
1622
        jmp     .ret
1623
 
1624
.accessDenied:
1625
        push    ERROR_ACCESS_DENIED
1626
        xor     ebx, ebx
1627
        jmp     .ret
1628
 
4273 clevermous 1629
fat1x_root_next:
2643 clevermous 1630
        push    ecx
1631
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1632
        cmp     edi, ecx
4273 clevermous 1633
        jae     fat1x_root_next_sector
6867 pathoswith 1634
        add     edi, 0x20
1635
@@:
2643 clevermous 1636
        pop     ecx
6867 pathoswith 1637
        ret
1638
 
1639
fat1x_root_next_write:
1640
        push    ecx
1641
        lea     ecx, [ebp+FAT.buffer+0x200]
1642
        cmp     edi, ecx
1643
        jc      @b
1644
        call    fat1x_root_end_write
4273 clevermous 1645
fat1x_root_next_sector:
2643 clevermous 1646
        push    [ebp+FAT.longname_sec2]
1647
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1648
        mov     ecx, [eax+4]
1649
        push    ecx
2643 clevermous 1650
        add     ecx, [ebp+FAT.ROOT_START]
1651
        mov     [ebp+FAT.longname_sec2], ecx
2288 clevermous 1652
        pop     ecx
1653
        inc     ecx
1654
        mov     [eax+4], ecx
2643 clevermous 1655
        cmp     ecx, [ebp+FAT.ROOT_SECTORS]
6867 pathoswith 1656
        jnc     fat_notroot_next_err
2288 clevermous 1657
        pop     ecx
4273 clevermous 1658
fat1x_root_first:
2288 clevermous 1659
        mov     eax, [eax+4]
2643 clevermous 1660
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 1661
        push    ebx
2643 clevermous 1662
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1663
        mov     ebx, edi
2643 clevermous 1664
        call    fs_read32_sys
2288 clevermous 1665
        pop     ebx
2643 clevermous 1666
        test    eax, eax
6867 pathoswith 1667
        jz      @f
1668
        movi    eax, ERROR_DEVICE
2288 clevermous 1669
        stc
6867 pathoswith 1670
@@:
2288 clevermous 1671
        ret
6867 pathoswith 1672
 
4273 clevermous 1673
fat1x_root_begin_write:
2288 clevermous 1674
        push    edi eax
4273 clevermous 1675
        call    fat1x_root_first
2288 clevermous 1676
        pop     eax edi
1677
        ret
6867 pathoswith 1678
 
4273 clevermous 1679
fat1x_root_end_write:
2288 clevermous 1680
        pusha
1681
        mov     eax, [eax+4]
2643 clevermous 1682
        add     eax, [ebp+FAT.ROOT_START]
1683
        lea     ebx, [ebp+FAT.buffer]
1684
        call    fs_write32_sys
2288 clevermous 1685
        popa
1686
        ret
6867 pathoswith 1687
 
1688
fat_notroot_next:
2643 clevermous 1689
        push    ecx
6867 pathoswith 1690
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
2643 clevermous 1691
        cmp     edi, ecx
6867 pathoswith 1692
        jae     fat_notroot_next_sector
1693
        add     edi, 0x20
1694
@@:
2643 clevermous 1695
        pop     ecx
2288 clevermous 1696
        ret
1697
 
6867 pathoswith 1698
fat_notroot_next_write:
2643 clevermous 1699
        push    ecx
6867 pathoswith 1700
        lea     ecx, [ebp+FAT.buffer+0x200]
2643 clevermous 1701
        cmp     edi, ecx
6867 pathoswith 1702
        jc      @b
1703
        push    eax
1704
        call    fat_notroot_end_write
1705
        pop     eax
2288 clevermous 1706
fat_notroot_next_sector:
2643 clevermous 1707
        push    [ebp+FAT.longname_sec2]
1708
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1709
        push    eax
1710
        call    fat_get_sector
2643 clevermous 1711
        mov     [ebp+FAT.longname_sec2], eax
2288 clevermous 1712
        pop     eax
1713
        mov     ecx, [eax+4]
1714
        inc     ecx
2643 clevermous 1715
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1716
        jae     fat_notroot_next_cluster
1717
        mov     [eax+4], ecx
1718
        jmp     @f
6867 pathoswith 1719
 
1720
fat_notroot_next_err:
1721
        pop     ecx
1722
        movi    eax, ERROR_FILE_NOT_FOUND
1723
fat1x_root_extend_dir:
1724
        stc
1725
        ret
1726
 
2288 clevermous 1727
fat_notroot_next_cluster:
1728
        push    eax
1729
        mov     eax, [eax]
1730
        call    get_FAT
1731
        mov     ecx, eax
1732
        pop     eax
2643 clevermous 1733
        jc      fat_notroot_first.deverr
1734
        cmp     ecx, 2
1735
        jb      fat_notroot_next_err
1736
        cmp     ecx, [ebp+FAT.fatRESERVED]
2288 clevermous 1737
        jae     fat_notroot_next_err
1738
        mov     [eax], ecx
1739
        and     dword [eax+4], 0
1740
@@:
1741
        pop     ecx
1742
fat_notroot_first:
1743
        call    fat_get_sector
1744
        push    ebx
2643 clevermous 1745
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1746
        mov     ebx, edi
2643 clevermous 1747
        call    fs_read32_sys
2288 clevermous 1748
        pop     ebx
2643 clevermous 1749
        test    eax, eax
1750
        jz      .ret ; CF=0
1751
        push    ecx
1752
.deverr:
1753
        pop     ecx
1754
        mov     eax, ERROR_DEVICE
1755
        stc
1756
.ret:
1757
        ret
6867 pathoswith 1758
 
2288 clevermous 1759
fat_notroot_begin_write:
1760
        push    eax edi
1761
        call    fat_notroot_first
1762
        pop     edi eax
1763
        ret
6867 pathoswith 1764
 
2288 clevermous 1765
fat_notroot_end_write:
1766
        call    fat_get_sector
1767
        push    ebx
2643 clevermous 1768
        lea     ebx, [ebp+FAT.buffer]
1769
        call    fs_write32_sys
2288 clevermous 1770
        pop     ebx
1771
        ret
6867 pathoswith 1772
 
1773
fat_notroot_extend_dir.writeerr:
1774
        pop     edx
2288 clevermous 1775
@@:
1776
        pop     eax
6867 pathoswith 1777
        ret
1778
 
2288 clevermous 1779
fat_notroot_extend_dir:
1780
        push    eax
1781
        call    get_free_FAT
6867 pathoswith 1782
        jc      @b
2288 clevermous 1783
        push    edx
2643 clevermous 1784
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 1785
        call    set_FAT
2643 clevermous 1786
        jc      .writeerr
2288 clevermous 1787
        mov     edx, eax
1788
        mov     eax, [esp+4]
1789
        mov     eax, [eax]
1790
        push    edx
1791
        call    set_FAT
1792
        pop     edx
6867 pathoswith 1793
        jc      .writeerr
2288 clevermous 1794
        push    ecx
1795
        or      ecx, -1
1796
        call    add_disk_free_space
1797
        mov     ecx, 512/4
2643 clevermous 1798
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1799
        push    edi
1800
        xor     eax, eax
1801
        rep stosd
1802
        pop     edi
1803
        pop     ecx
1804
        mov     eax, [esp+4]
1805
        mov     [eax], edx
1806
        and     dword [eax+4], 0
1807
        pop     edx
1808
        mov     eax, [eax]
1809
        dec     eax
1810
        dec     eax
1811
        push    ebx ecx
2643 clevermous 1812
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1813
        imul    eax, ecx
2643 clevermous 1814
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1815
        mov     ebx, edi
1816
@@:
2643 clevermous 1817
        push    eax
1818
        call    fs_write32_sys
1819
        pop     eax
2288 clevermous 1820
        inc     eax
1821
        loop    @b
1822
        pop     ecx ebx eax
1823
        clc
1824
        ret
1825
 
1826
fat_get_sector:
1827
        push    ecx
1828
        mov     ecx, [eax]
1829
        dec     ecx
1830
        dec     ecx
2643 clevermous 1831
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
1832
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 1833
        add     ecx, [eax+4]
1834
        mov     eax, ecx
1835
        pop     ecx
1836
        ret
1837
 
2643 clevermous 1838
;----------------------------------------------------------------
1839
fat_CreateFolder:
6917 pathoswith 1840
        mov     [ebp+FAT.createOption], 0
6468 pathoswith 1841
        jmp     @f
2643 clevermous 1842
 
6468 pathoswith 1843
fat_CreateFile:
6917 pathoswith 1844
        mov     [ebp+FAT.createOption], 1
6468 pathoswith 1845
@@:
2643 clevermous 1846
        call    fat_lock
1847
        mov     ecx, [ebx+12]
1848
        mov     edx, [ebx+16]
6917 pathoswith 1849
.rename:
2288 clevermous 1850
        pushad
1851
        xor     edi, edi
1852
        push    esi
1853
@@:
1854
        lodsb
1855
        test    al, al
1856
        jz      @f
1857
        cmp     al, '/'
1858
        jnz     @b
1859
        lea     edi, [esi-1]
1860
        jmp     @b
6468 pathoswith 1861
 
2288 clevermous 1862
@@:
1863
        pop     esi
1864
        test    edi, edi
1865
        jnz     .noroot
2643 clevermous 1866
        mov     edx, [ebp+FAT.ROOT_CLUSTER]
1867
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1868
        jz      .pushnotroot
2643 clevermous 1869
        xor     edx, edx
1870
        push    edx
4273 clevermous 1871
        push    fat1x_root_extend_dir
1872
        push    fat1x_root_end_write
1873
        push    fat1x_root_next_write
1874
        push    fat1x_root_begin_write
2643 clevermous 1875
        push    edx
1876
        push    edx
4273 clevermous 1877
        push    fat1x_root_first
1878
        push    fat1x_root_next
2288 clevermous 1879
        jmp     .common1
6468 pathoswith 1880
 
6867 pathoswith 1881
.retNotFound:
1882
        movi    eax, ERROR_FILE_NOT_FOUND
1883
        jmp     .ret1
1884
 
1885
.noAccess:
1886
        movi    eax, ERROR_ACCESS_DENIED
1887
.ret1:
1888
        mov     [esp+28], eax
1889
        call    fat_unlock
1890
        popad
1891
        xor     ebx, ebx
1892
        ret
1893
 
1894
.full:
1895
        movi    eax, ERROR_DISK_FULL
1896
        jmp     .ret1
1897
 
2288 clevermous 1898
.noroot:
1899
        cmp     byte [edi+1], 0
6867 pathoswith 1900
        jz      .noAccess
2288 clevermous 1901
; check existence
1902
        mov     byte [edi], 0
1903
        push    edi
6468 pathoswith 1904
        call    hd_find_lfn
2288 clevermous 1905
        pop     esi
1906
        mov     byte [esi], '/'
6867 pathoswith 1907
        jc      .retNotFound
2288 clevermous 1908
        inc     esi
6867 pathoswith 1909
        test    byte [edi+11], 0x10
1910
        jz      .noAccess   ; file
2643 clevermous 1911
        mov     edx, [edi+20-2]
6867 pathoswith 1912
        mov     dx, [edi+26]
1913
        movi    eax, ERROR_FS_FAIL
2643 clevermous 1914
        cmp     edx, 2
2288 clevermous 1915
        jb      .ret1
1916
.pushnotroot:
2643 clevermous 1917
        push    edx
2288 clevermous 1918
        push    fat_notroot_extend_dir
1919
        push    fat_notroot_end_write
1920
        push    fat_notroot_next_write
1921
        push    fat_notroot_begin_write
1922
        push    0
2643 clevermous 1923
        push    edx
2288 clevermous 1924
        push    fat_notroot_first
1925
        push    fat_notroot_next
1926
.common1:
1927
        call    fat_find_lfn
1928
        jc      .notfound
1929
        test    byte [edi+11], 10h
1930
        jz      .exists_file
6468 pathoswith 1931
; found directory
2643 clevermous 1932
        add     esp, 36
1933
        call    fat_unlock
2288 clevermous 1934
        popad
6917 pathoswith 1935
        xor     eax, eax
1936
        cmp     [ebp+FAT.createOption], 0
2288 clevermous 1937
        jz      @f
6917 pathoswith 1938
        mov     al, ERROR_ACCESS_DENIED
2288 clevermous 1939
@@:
1940
        xor     ebx, ebx
1941
        ret
6468 pathoswith 1942
 
2288 clevermous 1943
.exists_file:
6917 pathoswith 1944
        cmp     [ebp+FAT.createOption], 1
2288 clevermous 1945
        jz      @f
2643 clevermous 1946
        add     esp, 36
6867 pathoswith 1947
        jmp     .noAccess
6468 pathoswith 1948
 
1949
@@: ; delete FAT chain
2288 clevermous 1950
        push    edi
1951
        xor     eax, eax
1952
        mov     dword [edi+28], eax     ; zero size
1953
        xor     ecx, ecx
1954
        mov     eax, [edi+20-2]
1955
        mov     ax, [edi+26]
1956
        mov     word [edi+20], cx
1957
        mov     word [edi+26], cx
1958
        test    eax, eax
1959
        jz      .done1
1960
@@:
2643 clevermous 1961
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1962
        jae     .done1
1963
        xor     edx, edx
1964
        call    set_FAT
1965
        mov     eax, edx
2643 clevermous 1966
        jc      .done1
2288 clevermous 1967
        inc     ecx
1968
        jmp     @b
6468 pathoswith 1969
 
1970
.short_name_found:
1971
        pop     ecx edi esi
1972
        call    fat_next_short_name
1973
        jnc     .test_short_name_loop
1974
.disk_full:
1975
        add     esp, 12+36
6867 pathoswith 1976
        jmp     .full
6468 pathoswith 1977
 
1978
.notfound:  ; generate short name
2288 clevermous 1979
        call    fat_name_is_legal
1980
        jc      @f
2643 clevermous 1981
        add     esp, 36
6867 pathoswith 1982
        jmp     .retNotFound
6468 pathoswith 1983
 
2288 clevermous 1984
@@:
1985
        sub     esp, 12
1986
        mov     edi, esp
1987
        call    fat_gen_short_name
1988
.test_short_name_loop:
1989
        push    esi edi ecx
1990
        mov     esi, edi
1991
        lea     eax, [esp+12+12+8]
2643 clevermous 1992
        mov     edx, [eax+24]
1993
        mov     [eax], edx
2288 clevermous 1994
        and     dword [eax+4], 0
1995
        call    dword [eax-4]
1996
        jc      .found
1997
.test_short_name_entry:
1998
        cmp     byte [edi+11], 0xF
1999
        jz      .test_short_name_cont
2000
        mov     ecx, 11
2001
        push    esi edi
2002
        repz cmpsb
2003
        pop     edi esi
2004
        jz      .short_name_found
2005
.test_short_name_cont:
2006
        lea     eax, [esp+12+12+8]
2007
        call    dword [eax-8]
2008
        jnc     .test_short_name_entry
2009
.found:
2010
        pop     ecx edi esi
2011
; now find space in directory
2012
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
2013
        mov     al, '~'
2014
        push    ecx edi
2015
        mov     ecx, 8
2016
        repnz scasb
3598 clevermous 2017
        movi    eax, 1     ; 1 entry
2288 clevermous 2018
        jnz     .notilde
2019
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
6471 pathoswith 2020
        xor     ecx, ecx
2021
        push    esi
2288 clevermous 2022
@@:
6471 pathoswith 2023
        call    utf8to16
2024
        inc     ecx
2025
        test    ax, ax
2026
        jnz     @b
2027
        pop     esi
2028
        mov     eax, ecx
2029
        add     eax, 12+13-1
2288 clevermous 2030
        mov     ecx, 13
2031
        cdq
2032
        div     ecx
2033
.notilde:
2034
        push    -1
2035
        push    -1
2036
        push    -1
2037
; find  successive entries in directory
2038
        xor     ecx, ecx
2039
        push    eax
2040
        lea     eax, [esp+16+8+12+8]
2643 clevermous 2041
        mov     edx, [eax+24]
2042
        mov     [eax], edx
2288 clevermous 2043
        and     dword [eax+4], 0
2044
        call    dword [eax-4]
2045
        pop     eax
2046
        jnc     .scan_dir
2047
.fsfrfe3:
2643 clevermous 2048
        add     esp, 12+8+12+36
6867 pathoswith 2049
        movi    eax, ERROR_DEVICE
2050
        jmp     .ret1
6468 pathoswith 2051
 
2288 clevermous 2052
.scan_dir:
2053
        cmp     byte [edi], 0
2054
        jz      .free
2055
        cmp     byte [edi], 0xE5
2056
        jz      .free
2057
        xor     ecx, ecx
2058
.scan_cont:
2059
        push    eax
2060
        lea     eax, [esp+16+8+12+8]
2061
        call    dword [eax-8]
2643 clevermous 2062
        mov     edx, eax
2288 clevermous 2063
        pop     eax
2064
        jnc     .scan_dir
2643 clevermous 2065
        cmp     edx, ERROR_DEVICE
2066
        jz      .fsfrfe3
2288 clevermous 2067
        push    eax
2068
        lea     eax, [esp+16+8+12+8]
2069
        call    dword [eax+20]          ; extend directory
2070
        pop     eax
2071
        jnc     .scan_dir
2643 clevermous 2072
        add     esp, 12+8+12+36
6867 pathoswith 2073
        jmp     .full
6468 pathoswith 2074
 
2288 clevermous 2075
.free:
2076
        test    ecx, ecx
2077
        jnz     @f
2078
        mov     [esp], edi
2079
        mov     ecx, [esp+12+8+12+8]
2080
        mov     [esp+4], ecx
2081
        mov     ecx, [esp+12+8+12+12]
2082
        mov     [esp+8], ecx
2083
        xor     ecx, ecx
2084
@@:
2085
        inc     ecx
2086
        cmp     ecx, eax
2087
        jb      .scan_cont
2088
; found!
2643 clevermous 2089
        push    esi ecx
6917 pathoswith 2090
; If creating a directory, allocate one data cluster or fail immediately if this is impossible.
2091
; This prevents from creating an invalid directory entry on a full disk.
2092
        cmp     [ebp+FAT.createOption], 0
2093
        jnz     .notFolder
2643 clevermous 2094
        call    get_free_FAT
2095
        jnc     @f
2096
        add     esp, 8+12+8
2097
        jmp     .disk_full
6468 pathoswith 2098
 
2643 clevermous 2099
@@:
6471 pathoswith 2100
        mov     [esp+8+12+8+12+36+20], eax  ; store the cluster somewhere
6917 pathoswith 2101
.notFolder: ; calculate name checksum
2288 clevermous 2102
        mov     esi, [esp+8+12]
2103
        mov     ecx, 11
2104
        xor     eax, eax
2105
@@:
2106
        ror     al, 1
2107
        add     al, [esi]
2108
        inc     esi
2109
        loop    @b
6471 pathoswith 2110
        pop     ecx esi edi
2288 clevermous 2111
        pop     dword [esp+8+12+12]
2112
        pop     dword [esp+8+12+12]
2113
; edi points to first entry in free chunk
2114
        dec     ecx
2115
        jz      .nolfn
6471 pathoswith 2116
        push    esi eax
2288 clevermous 2117
        lea     eax, [esp+8+8+12+8]
6471 pathoswith 2118
        call    dword [eax+8]   ; begin write
2288 clevermous 2119
        mov     al, 40h
2120
.writelfn:
2121
        or      al, cl
6471 pathoswith 2122
        stosb
2288 clevermous 2123
        mov     esi, [esp+4]
2124
        push    ecx
2125
        dec     ecx
6471 pathoswith 2126
        jz      @f
2288 clevermous 2127
        imul    ecx, 13
6471 pathoswith 2128
.scroll:
2129
        call    utf8to16
2130
        loop    .scroll
2131
@@:
2288 clevermous 2132
        mov     cl, 5
4273 clevermous 2133
        call    fat_read_symbols
2288 clevermous 2134
        mov     ax, 0xF
2135
        stosw
2136
        mov     al, [esp+4]
2137
        stosb
2138
        mov     cl, 6
4273 clevermous 2139
        call    fat_read_symbols
2288 clevermous 2140
        xor     eax, eax
2141
        stosw
2142
        mov     cl, 2
4273 clevermous 2143
        call    fat_read_symbols
2288 clevermous 2144
        pop     ecx
2145
        lea     eax, [esp+8+8+12+8]
6471 pathoswith 2146
        call    dword [eax+12]  ; next write
2288 clevermous 2147
        xor     eax, eax
2148
        loop    .writelfn
6471 pathoswith 2149
        pop     eax esi
2288 clevermous 2150
.nolfn:
6917 pathoswith 2151
        pop     esi
2152
        add     esp, 16
2288 clevermous 2153
        mov     ecx, 11
2154
        rep movsb
6917 pathoswith 2155
        cmp     [ebp+FAT.createOption], 2
2156
        jz      .copy
2288 clevermous 2157
        mov     word [edi], 20h         ; attributes
2158
        sub     edi, 11
2159
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
2160
        call    get_time_for_file
2161
        mov     [edi+14], ax            ; creation time
2162
        mov     [edi+22], ax            ; last write time
2163
        call    get_date_for_file
2164
        mov     [edi+16], ax            ; creation date
2165
        mov     [edi+24], ax            ; last write date
2166
        mov     [edi+18], ax            ; last access date
2167
        mov     word [edi+20], cx       ; high word of cluster
2168
        mov     word [edi+26], cx       ; low word of cluster - to be filled
2169
        mov     dword [edi+28], ecx     ; file size - to be filled
6917 pathoswith 2170
        cmp     [ebp+FAT.createOption], 0
2171
        jnz     .doit
2288 clevermous 2172
; create directory
2173
        mov     byte [edi+11], 10h      ; attributes: folder
2643 clevermous 2174
        mov     esi, edi
2175
        mov     eax, [esp+36+20] ; extract saved cluster
2176
        mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
2288 clevermous 2177
        push    ecx
2643 clevermous 2178
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2179
        shl     ecx, 9
2643 clevermous 2180
        push    ecx
2181
        push    edi
2288 clevermous 2182
        jmp     .doit2
6468 pathoswith 2183
 
6917 pathoswith 2184
.copy:
2185
        lea     esi, [esp+72+11]
2186
        mov     cl, 21
2187
        rep movsb
2188
        sub     edi, 32
2189
        jmp     .doit
2190
 
6468 pathoswith 2191
.done1:
2192
        pop     edi
2193
        call    get_time_for_file
2194
        mov     [edi+22], ax
2195
        call    get_date_for_file
2196
        mov     [edi+24], ax
2197
        mov     [edi+18], ax
2198
        or      byte [edi+11], 20h      ; set 'archive' attribute
2288 clevermous 2199
.doit:
2643 clevermous 2200
        mov     esi, [esp+36+20]
2288 clevermous 2201
        lea     eax, [esp+8]
2202
        call    dword [eax+16]  ; flush directory
2203
        push    ecx
2643 clevermous 2204
        mov     ecx, [esp+4+36+24]
6917 pathoswith 2205
        xor     eax, eax
2288 clevermous 2206
        test    ecx, ecx
2207
        jz      .done
6917 pathoswith 2208
        push    ecx edi
2288 clevermous 2209
        call    get_free_FAT
2210
        jc      .diskfull
2643 clevermous 2211
.doit2:
2288 clevermous 2212
        push    eax
2213
        mov     [edi+26], ax
2214
        shr     eax, 16
2215
        mov     [edi+20], ax
2216
        lea     eax, [esp+16+8]
2217
        call    dword [eax+16]  ; flush directory
2218
        pop     eax
2643 clevermous 2219
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2220
        call    set_FAT
2221
.write_cluster:
2222
        push    eax
2223
        dec     eax
2224
        dec     eax
2643 clevermous 2225
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2226
        add     eax, [ebp+FAT.DATA_START]
2227
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2228
.write_sector:
6917 pathoswith 2229
        cmp     [ebp+FAT.createOption], 0
2230
        jz      .writedir
2288 clevermous 2231
        mov     ecx, 512
2643 clevermous 2232
        cmp     dword [esp+12], ecx
2288 clevermous 2233
        jb      .writeshort
2234
; we can write directly from given buffer
2235
        mov     ebx, esi
2236
        add     esi, ecx
2237
        jmp     .writecommon
6468 pathoswith 2238
 
6867 pathoswith 2239
.writedir:
2240
        push    512
2241
        lea     edi, [ebp+FAT.buffer]
2242
        mov     ebx, edi
2243
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2244
        shl     ecx, 9
2245
        cmp     ecx, [esp+16]
2246
        jnz     .writedircont
2247
        dec     dword [esp+20]
2248
        push    esi
2249
        mov     ecx, 32/4
2250
        rep movsd
2251
        pop     esi
2252
        mov     dword [edi-32], '.   '
2253
        mov     dword [edi-32+4], '    '
2254
        mov     dword [edi-32+8], '    '
2255
        mov     byte [edi-32+11], 10h
2256
        push    esi
2257
        mov     ecx, 32/4
2258
        rep movsd
2259
        pop     esi
2260
        mov     dword [edi-32], '..  '
2261
        mov     dword [edi-32+4], '    '
2262
        mov     dword [edi-32+8], '    '
2263
        mov     byte [edi-32+11], 10h
2264
        mov     ecx, [esp+20+36]
2265
        cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
2266
        jnz     @f
2267
        xor     ecx, ecx
2268
@@:
2269
        mov     word [edi-32+26], cx
2270
        shr     ecx, 16
2271
        mov     [edi-32+20], cx
2272
        jmp     .writedircont
2273
 
2288 clevermous 2274
.writeshort:
2643 clevermous 2275
        mov     ecx, [esp+12]
2288 clevermous 2276
        push    ecx
2643 clevermous 2277
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 2278
        mov     ebx, edi
2279
        rep movsb
2280
.writedircont:
2643 clevermous 2281
        lea     ecx, [ebp+FAT.buffer+0x200]
2288 clevermous 2282
        sub     ecx, edi
2283
        push    eax
2284
        xor     eax, eax
2285
        rep stosb
2286
        pop     eax
2287
        pop     ecx
2288
.writecommon:
2643 clevermous 2289
        push    eax
2290
        call    fs_write32_app
2291
        test    eax, eax
2292
        pop     eax
2288 clevermous 2293
        jnz     .writeerr
2294
        inc     eax
2643 clevermous 2295
        sub     dword [esp+12], ecx
2288 clevermous 2296
        jz      .writedone
2643 clevermous 2297
        dec     dword [esp]
2288 clevermous 2298
        jnz     .write_sector
2643 clevermous 2299
        pop     eax
2288 clevermous 2300
; allocate new cluster
2301
        pop     eax
2302
        mov     ecx, eax
2303
        call    get_free_FAT
2304
        jc      .diskfull
2643 clevermous 2305
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2306
        call    set_FAT
2307
        xchg    eax, ecx
2308
        mov     edx, ecx
2309
        call    set_FAT
2310
        xchg    eax, ecx
2311
        jmp     .write_cluster
6468 pathoswith 2312
 
2288 clevermous 2313
.diskfull:
2314
        mov     eax, ERROR_DISK_FULL
2315
        jmp     .ret
6468 pathoswith 2316
 
2288 clevermous 2317
.writeerr:
2643 clevermous 2318
        pop     eax eax
2288 clevermous 2319
        sub     esi, ecx
2643 clevermous 2320
        mov     eax, ERROR_DEVICE
2288 clevermous 2321
        jmp     .ret
6468 pathoswith 2322
 
2288 clevermous 2323
.writedone:
2643 clevermous 2324
        pop     eax eax
2288 clevermous 2325
        xor     eax, eax
2326
.ret:
2327
        pop     edi ecx
6917 pathoswith 2328
        inc     ecx
2329
.done:
2643 clevermous 2330
        sub     esi, [esp+4+36+20]
2331
        mov     [esp+4+36+28], eax
2332
        mov     [esp+4+36+16], esi
6917 pathoswith 2333
        jecxz   @f
2643 clevermous 2334
        lea     eax, [esp+12]
2288 clevermous 2335
        call    dword [eax+8]
2643 clevermous 2336
        mov     [edi+28], esi
2288 clevermous 2337
        call    dword [eax+16]
6917 pathoswith 2338
@@:
2643 clevermous 2339
        lea     eax, [esi+511]
2288 clevermous 2340
        shr     eax, 9
2643 clevermous 2341
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2342
        lea     eax, [eax+ecx-1]
2343
        xor     edx, edx
2344
        div     ecx
2643 clevermous 2345
        pop     ecx
2288 clevermous 2346
        sub     ecx, eax
2347
        call    add_disk_free_space
2643 clevermous 2348
        add     esp, 36
6917 pathoswith 2349
        cmp     [ebp+FAT.createOption], 2
2350
        jz      @f
2288 clevermous 2351
        call    update_disk
2643 clevermous 2352
        call    fat_unlock
6917 pathoswith 2353
@@:
2288 clevermous 2354
        popad
2355
        ret
6468 pathoswith 2356
 
2288 clevermous 2357
@@:
6471 pathoswith 2358
        or      eax, -1
2359
        rep stosw
4273 clevermous 2360
        ret
2361
 
2362
fat_read_symbols:
6471 pathoswith 2363
        test    esi, esi
2364
        jz      @b
2365
        call    utf8to16
4273 clevermous 2366
        stosw
6471 pathoswith 2367
        test    ax, ax
2368
        jnz     @f
2369
        xor     esi, esi
2370
@@:
4273 clevermous 2371
        loop    fat_read_symbols
2372
        ret
2373
 
2643 clevermous 2374
;----------------------------------------------------------------
2375
fat_Write:
2376
        call    fat_lock
6468 pathoswith 2377
        call    hd_find_lfn
6845 pathoswith 2378
        jc      .error
2643 clevermous 2379
        cmp     dword [ebx+8], 0
6845 pathoswith 2380
        jnz     .eof    ; FAT does not support files larger than 4GB
2643 clevermous 2381
        mov     ecx, [ebx+12]
2382
        mov     edx, [ebx+16]
2383
        mov     ebx, [ebx+4]
2288 clevermous 2384
; now edi points to direntry, ebx=start byte to write,
2385
; ecx=number of bytes to write, edx=data pointer
2386
; extend file if needed
2387
        add     ecx, ebx
2388
        jc      .eof    ; FAT does not support files larger than 4GB
2643 clevermous 2389
        push    edx
2288 clevermous 2390
        push    eax     ; save directory sector
2391
        push    0       ; return value=0
2392
        call    get_time_for_file
2393
        mov     [edi+22], ax            ; last write time
2394
        call    get_date_for_file
2395
        mov     [edi+24], ax            ; last write date
2396
        mov     [edi+18], ax            ; last access date
2397
        push    dword [edi+28]          ; save current file size
2398
        cmp     ecx, [edi+28]
2399
        jbe     .length_ok
2400
        cmp     ecx, ebx
2401
        jz      .length_ok
2402
        call    hd_extend_file
2403
        jnc     .length_ok
2404
        mov     [esp+4], eax
2405
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
2406
; First two cases are fatal errors, in third case we may write some data
2407
        cmp     al, ERROR_DISK_FULL
6845 pathoswith 2408
        jnz     @f
2288 clevermous 2409
; correct number of bytes to write
2410
        mov     ecx, [edi+28]
2411
        cmp     ecx, ebx
2412
        ja      .length_ok
2643 clevermous 2413
        push    0
2288 clevermous 2414
.ret:
6939 pathoswith 2415
        pop     eax eax eax ecx ecx
2416
        sub     edx, ecx
2417
        push    eax edx
2288 clevermous 2418
        call    update_disk
6939 pathoswith 2419
        pop     ebx
2288 clevermous 2420
@@:
2643 clevermous 2421
        call    fat_unlock
6867 pathoswith 2422
        pop     eax
6845 pathoswith 2423
        ret
2424
 
6939 pathoswith 2425
.error:
2426
        push    eax
2427
        jmp     @b
2428
 
6845 pathoswith 2429
.eof:
2430
        push    ERROR_END_OF_FILE
6846 pathoswith 2431
        xor     ebx, ebx
6845 pathoswith 2432
        jmp     @b
2433
 
2434
.device_err2:
2643 clevermous 2435
        pop     ecx
6845 pathoswith 2436
.device_err:
2437
        mov     byte [esp+8], ERROR_DEVICE
2438
        jmp     .ret
2439
 
2440
.fat_err:
2441
        mov     byte [esp+8], ERROR_FS_FAIL
2442
        jmp     .ret
2443
 
2288 clevermous 2444
.length_ok:
2445
        mov     esi, [edi+28]
2446
        mov     eax, [edi+20-2]
2447
        mov     ax, [edi+26]
2448
        mov     edi, eax        ; edi=current cluster
2643 clevermous 2449
        push    0               ; current sector in cluster
2288 clevermous 2450
; save directory
2643 clevermous 2451
        mov     eax, [esp+12]
2288 clevermous 2452
        push    ebx
2643 clevermous 2453
        lea     ebx, [ebp+FAT.buffer]
2454
        call    fs_write32_sys
2288 clevermous 2455
        pop     ebx
2643 clevermous 2456
        test    eax, eax
6845 pathoswith 2457
        jnz     .device_err
2288 clevermous 2458
; now ebx=start pos, ecx=end pos, both lie inside file
2459
        sub     ecx, ebx
2460
        jz      .ret
2461
.write_loop:
2462
; skip unmodified sectors
2643 clevermous 2463
        cmp     dword [esp+4], 0x200
2288 clevermous 2464
        jb      .modify
2465
        sub     ebx, 0x200
2466
        jae     .skip
2467
        add     ebx, 0x200
2468
.modify:
2469
; get length of data in current sector
2470
        push    ecx
2471
        sub     ebx, 0x200
2472
        jb      .hasdata
2473
        neg     ebx
2474
        xor     ecx, ecx
2475
        jmp     @f
2476
.hasdata:
2477
        neg     ebx
2478
        cmp     ecx, ebx
2479
        jbe     @f
2480
        mov     ecx, ebx
2481
@@:
2482
; get current sector number
2483
        mov     eax, edi
2484
        dec     eax
2485
        dec     eax
2643 clevermous 2486
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2487
        add     eax, [ebp+FAT.DATA_START]
2488
        add     eax, [esp+4]
2288 clevermous 2489
; load sector if needed
2643 clevermous 2490
        cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
2288 clevermous 2491
        jz      .noread
2492
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
2493
        jz      .noread
2494
        cmp     ecx, esi        ; (same for the last sector)
2495
        jz      .noread
2643 clevermous 2496
        push    eax ebx
2497
        lea     ebx, [ebp+FAT.buffer]
2498
        call    fs_read32_app
2499
        test    eax, eax
2500
        pop     ebx eax
6845 pathoswith 2501
        jnz     .device_err2
2288 clevermous 2502
.noread:
2503
; zero uninitialized data if file was extended (because hd_extend_file does not this)
2504
        push    eax ecx edi
2505
        xor     eax, eax
2506
        mov     ecx, 0x200
2643 clevermous 2507
        sub     ecx, [esp+8+12]
2288 clevermous 2508
        jbe     @f
2643 clevermous 2509
        lea     edi, [ebp+FAT.buffer]
2510
        add     edi, [esp+8+12]
2288 clevermous 2511
        rep stosb
2512
@@:
2513
; zero uninitialized data in the last sector
2514
        mov     ecx, 0x200
2515
        sub     ecx, esi
2516
        jbe     @f
2643 clevermous 2517
        lea     edi, [ebp+FAT.buffer+esi]
2288 clevermous 2518
        rep stosb
2519
@@:
2520
        pop     edi ecx
2521
; copy new data
2522
        mov     eax, edx
2523
        neg     ebx
2524
        jecxz   @f
2643 clevermous 2525
        lea     ebx, [ebp+FAT.buffer+0x200+ebx]
2288 clevermous 2526
        call    memmove
2527
        xor     ebx, ebx
2528
@@:
2529
        pop     eax
2530
; save sector
2531
        push    ebx
2643 clevermous 2532
        lea     ebx, [ebp+FAT.buffer]
2533
        call    fs_write32_app
2288 clevermous 2534
        pop     ebx
2643 clevermous 2535
        test    eax, eax
2288 clevermous 2536
        jnz     .device_err2
2537
        add     edx, ecx
2538
        sub     [esp], ecx
2539
        pop     ecx
2540
        jz      .ret
2541
.skip:
2542
; next sector
2643 clevermous 2543
        pop     eax
2544
        inc     eax
2545
        push    eax
2546
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2547
        jb      @f
2643 clevermous 2548
        and     dword [esp], 0
2288 clevermous 2549
        mov     eax, edi
2550
        call    get_FAT
2551
        mov     edi, eax
2643 clevermous 2552
        jc      .device_err
2553
        cmp     edi, 2
2554
        jb      .fat_err
2555
        cmp     edi, [ebp+FAT.fatRESERVED]
2556
        jae     .fat_err
2288 clevermous 2557
@@:
2558
        sub     esi, 0x200
2559
        jae     @f
2560
        xor     esi, esi
2561
@@:
2643 clevermous 2562
        sub     dword [esp+4], 0x200
2288 clevermous 2563
        jae     @f
2643 clevermous 2564
        and     dword [esp+4], 0
2288 clevermous 2565
@@:
2566
        jmp     .write_loop
2567
 
2568
hd_extend_file.zero_size:
2569
        xor     eax, eax
2570
        jmp     hd_extend_file.start_extend
2571
 
2572
; extends file on hd to given size (new data area is undefined)
2573
; in: edi->direntry, ecx=new size
2574
; out: CF=0 => OK, eax=0
6468 pathoswith 2575
;      CF=1 => error, eax=code (ERROR_FS_FAIL or ERROR_DISK_FULL or ERROR_DEVICE)
2288 clevermous 2576
hd_extend_file:
2643 clevermous 2577
        push    esi
2578
        mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
2579
        imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
2288 clevermous 2580
        push    ecx
2581
; find the last cluster of file
2582
        mov     eax, [edi+20-2]
2583
        mov     ax, [edi+26]
2584
        mov     ecx, [edi+28]
2585
        jecxz   .zero_size
2586
.last_loop:
2643 clevermous 2587
        sub     ecx, esi
2288 clevermous 2588
        jbe     .last_found
2589
        call    get_FAT
2643 clevermous 2590
        jnc     @f
2288 clevermous 2591
.device_err:
2592
        pop     ecx
2593
.device_err2:
2643 clevermous 2594
        pop     esi
2595
        push    ERROR_DEVICE
2288 clevermous 2596
.ret_err:
2597
        pop     eax
2598
        stc
2599
        ret
2600
@@:
2601
        cmp     eax, 2
2602
        jb      .fat_err
2643 clevermous 2603
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2604
        jb      .last_loop
2605
.fat_err:
2643 clevermous 2606
        pop     ecx esi
6468 pathoswith 2607
        push    ERROR_FS_FAIL
2288 clevermous 2608
        jmp     .ret_err
2609
.last_found:
2610
        push    eax
2611
        call    get_FAT
2643 clevermous 2612
        jnc     @f
2288 clevermous 2613
        pop     eax
2614
        jmp     .device_err
2615
@@:
2643 clevermous 2616
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2617
        pop     eax
2618
        jb      .fat_err
2619
; set length to full number of clusters
2620
        sub     [edi+28], ecx
2621
.start_extend:
2622
        pop     ecx
2623
; now do extend
2624
        push    edx
2625
        mov     edx, 2          ; start scan from cluster 2
2626
.extend_loop:
2627
        cmp     [edi+28], ecx
2628
        jae     .extend_done
2629
; add new cluster
2630
        push    eax
2631
        call    get_free_FAT
2632
        jc      .disk_full
2643 clevermous 2633
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2634
        call    set_FAT
2635
        mov     edx, eax
2636
        pop     eax
2637
        test    eax, eax
2638
        jz      .first_cluster
2639
        push    edx
2640
        call    set_FAT
2641
        pop     edx
2642
        jmp     @f
2643
.first_cluster:
2644
        ror     edx, 16
2645
        mov     [edi+20], dx
2646
        ror     edx, 16
2647
        mov     [edi+26], dx
2648
@@:
2649
        push    ecx
2650
        mov     ecx, -1
2651
        call    add_disk_free_space
2652
        pop     ecx
2653
        mov     eax, edx
2643 clevermous 2654
        add     [edi+28], esi
2288 clevermous 2655
        jmp     .extend_loop
2656
.extend_done:
2657
        mov     [edi+28], ecx
2643 clevermous 2658
        pop     edx esi
2288 clevermous 2659
        xor     eax, eax        ; CF=0
2660
        ret
2661
.device_err3:
2662
        pop     edx
2663
        jmp     .device_err2
2664
.disk_full:
2643 clevermous 2665
        pop     eax edx esi
3598 clevermous 2666
        movi    eax, ERROR_DISK_FULL
2288 clevermous 2667
        stc
2668
        ret
2669
 
2670
;----------------------------------------------------------------
2643 clevermous 2671
fat_SetFileEnd:
2672
        call    fat_lock
6468 pathoswith 2673
        call    hd_find_lfn
6845 pathoswith 2674
        jc      .reteax
2288 clevermous 2675
; must not be directory
2676
        test    byte [edi+11], 10h
2643 clevermous 2677
        jnz     .access_denied
2288 clevermous 2678
; file size must not exceed 4 Gb
2643 clevermous 2679
        cmp     dword [ebx+8], 0
6845 pathoswith 2680
        jnz     .endOfFile
2288 clevermous 2681
        push    eax     ; save directory sector
2682
; set file modification date/time to current
6867 pathoswith 2683
        call    get_time_for_file
2684
        mov     [edi+22], ax    ; last write
2685
        call    get_date_for_file
2686
        mov     [edi+24], ax    ; last write
2687
        mov     [edi+18], ax    ; last access
2643 clevermous 2688
        mov     eax, [ebx+4]
2288 clevermous 2689
        cmp     eax, [edi+28]
2690
        jb      .truncate
2691
        ja      .expand
2692
        pop     eax
2643 clevermous 2693
        lea     ebx, [ebp+FAT.buffer]
2694
        call    fs_write32_sys
2695
        test    eax, eax
6845 pathoswith 2696
        jnz     .errorDevice
2697
        push    0
2698
        jmp     .ret
2699
 
2700
.access_denied:
2701
        push    ERROR_ACCESS_DENIED
2702
        jmp     .ret
2703
 
2704
.endOfFile:
2705
        push    ERROR_END_OF_FILE
2706
        jmp     .ret
2707
 
2708
.errorDevice:
2643 clevermous 2709
        push    ERROR_DEVICE
2710
        jmp     .ret
6845 pathoswith 2711
 
2288 clevermous 2712
.expand:
2713
        push    ebx ebp ecx
2714
        push    dword [edi+28]  ; save old size
2715
        mov     ecx, eax
2716
        call    hd_extend_file
2717
        push    eax             ; return code
2718
        jnc     .expand_ok
2719
        cmp     al, ERROR_DISK_FULL
6845 pathoswith 2720
        jnz     .pop_ret
2721
.expand_ok: ; save directory
2288 clevermous 2722
        mov     eax, [edi+28]
2723
        xchg    eax, [esp+20]
2643 clevermous 2724
        lea     ebx, [ebp+FAT.buffer]
2725
        call    fs_write32_sys
2726
        test    eax, eax
6850 pathoswith 2727
        jnz     .pop_ret11
2728
        mov     eax, [esp+20]
2729
        sub     eax, [esp+4]
2730
        cmp     eax, 1000001h
2731
        jnc     .pop_ret
2288 clevermous 2732
        mov     eax, [edi+20-2]
2733
        mov     ax, [edi+26]
2734
        mov     edi, eax
2643 clevermous 2735
        test    edi, edi
2736
        jz      .pop_ret
2288 clevermous 2737
; now zero new data
2643 clevermous 2738
        push    0
2739
; edi=current cluster, [esp]=sector in cluster
2740
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
2288 clevermous 2741
.zero_loop:
2643 clevermous 2742
        cmp     edi, 2
2743
        jb      .error_fat
2744
        cmp     edi, [ebp+FAT.fatRESERVED]
2745
        jae     .error_fat
2746
        sub     dword [esp+8], 0x200
2288 clevermous 2747
        jae     .next_cluster
2748
        lea     eax, [edi-2]
2643 clevermous 2749
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2750
        add     eax, [ebp+FAT.DATA_START]
2751
        add     eax, [esp]
2752
        cmp     dword [esp+8], -0x200
2288 clevermous 2753
        jz      .noread
2643 clevermous 2754
        push    eax
2755
        lea     ebx, [ebp+FAT.buffer]
2756
        call    fs_read32_app
2757
        test    eax, eax
2758
        pop     eax
2288 clevermous 2759
        jnz     .err_next
2760
.noread:
2643 clevermous 2761
        mov     ecx, [esp+8]
2288 clevermous 2762
        neg     ecx
2763
        push    edi
2643 clevermous 2764
        lea     edi, [ebp+FAT.buffer+0x200]
2765
        add     edi, [esp+12]
2288 clevermous 2766
        push    eax
2767
        xor     eax, eax
2643 clevermous 2768
        mov     [esp+16], eax
2288 clevermous 2769
        rep stosb
2770
        pop     eax
2771
        pop     edi
2643 clevermous 2772
        call    fs_write32_app
2773
        test    eax, eax
2288 clevermous 2774
        jz      .next_cluster
2775
.err_next:
2643 clevermous 2776
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 2777
.next_cluster:
2643 clevermous 2778
        pop     eax
2288 clevermous 2779
        sub     dword [esp+20], 0x200
2780
        jbe     .pop_ret
2643 clevermous 2781
        inc     eax
2782
        push    eax
2783
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2784
        jb      .zero_loop
2643 clevermous 2785
        and     dword [esp], 0
2288 clevermous 2786
        mov     eax, edi
2787
        call    get_FAT
2788
        mov     edi, eax
2643 clevermous 2789
        jnc     .zero_loop
2790
        pop     eax
6845 pathoswith 2791
.pop_ret11:
2792
        mov     byte [esp], ERROR_DEVICE
2793
.pop_ret:
2794
        call    update_disk
2795
        pop     eax ecx ecx ebp ebx ecx
2796
.reteax:
2797
        push    eax
2798
.ret:
2799
        call    fat_unlock
6867 pathoswith 2800
        pop     eax
6845 pathoswith 2801
        ret
2802
 
2803
.error_fat:
2804
        pop     eax
2805
        mov     byte [esp], ERROR_FS_FAIL
2806
        jmp     .pop_ret
2807
 
2808
.error_fat2:
2809
        pop     eax ecx eax
2810
        call    update_disk
2811
        push    ERROR_FS_FAIL
2812
        jmp     .ret
2813
 
2288 clevermous 2814
.truncate:
2815
        mov     [edi+28], eax
2816
        push    ecx
2817
        mov     ecx, [edi+20-2]
2818
        mov     cx, [edi+26]
2819
        push    eax
2820
        test    eax, eax
2821
        jz      .zero_size
6845 pathoswith 2822
@@: ; find new last cluster
2643 clevermous 2823
        cmp     ecx, 2
2824
        jb      .error_fat2
2825
        cmp     ecx, [ebp+FAT.fatRESERVED]
2826
        jae     .error_fat2
2827
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2828
        shl     eax, 9
2829
        sub     [esp], eax
2830
        jbe     @f
2831
        mov     eax, ecx
2832
        call    get_FAT
2833
        mov     ecx, eax
2643 clevermous 2834
        jnc     @b
2288 clevermous 2835
.device_err3:
6845 pathoswith 2836
        pop     eax ecx eax
2643 clevermous 2837
        call    update_disk
6845 pathoswith 2838
        push    ERROR_DEVICE
2839
        jmp     .ret
2840
 
2288 clevermous 2841
@@:
2842
; we will zero data at the end of last sector - remember it
2843
        push    ecx
2844
; terminate FAT chain
2845
        push    edx
2846
        mov     eax, ecx
2643 clevermous 2847
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2848
        call    set_FAT
2849
        mov     eax, edx
2850
        pop     edx
2643 clevermous 2851
        jnc     @f
2288 clevermous 2852
.device_err4:
2853
        pop     ecx
2854
        jmp     .device_err3
6845 pathoswith 2855
 
2288 clevermous 2856
.zero_size:
2857
        and     word [edi+20], 0
2858
        and     word [edi+26], 0
2859
        push    0
2860
        mov     eax, ecx
2861
@@:
2862
; delete FAT chain
2863
        call    clear_cluster_chain
2643 clevermous 2864
        jc      .device_err4
2288 clevermous 2865
; save directory
2866
        mov     eax, [esp+12]
2867
        push    ebx
2643 clevermous 2868
        lea     ebx, [ebp+FAT.buffer]
2869
        call    fs_write32_sys
2288 clevermous 2870
        pop     ebx
2643 clevermous 2871
        test    eax, eax
2288 clevermous 2872
        jnz     .device_err4
2873
; zero last sector, ignore errors
2874
        pop     ecx
2875
        pop     eax
2876
        dec     ecx
2643 clevermous 2877
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2878
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 2879
        push    eax
2880
        sar     eax, 9
2881
        add     ecx, eax
2882
        pop     eax
2883
        and     eax, 0x1FF
2884
        jz      .truncate_done
2885
        push    ebx eax
2886
        mov     eax, ecx
2643 clevermous 2887
        lea     ebx, [ebp+FAT.buffer]
2888
        call    fs_read32_app
2288 clevermous 2889
        pop     eax
2643 clevermous 2890
        lea     edi, [ebp+FAT.buffer+eax]
2288 clevermous 2891
        push    ecx
2892
        mov     ecx, 0x200
2893
        sub     ecx, eax
2894
        xor     eax, eax
2895
        rep stosb
2896
        pop     eax
2643 clevermous 2897
        call    fs_write32_app
2288 clevermous 2898
        pop     ebx
2899
.truncate_done:
6867 pathoswith 2900
        pop     ecx eax
2288 clevermous 2901
        call    update_disk
2643 clevermous 2902
        call    fat_unlock
2288 clevermous 2903
        xor     eax, eax
2904
        ret
2905
 
2643 clevermous 2906
;----------------------------------------------------------------
2907
fat_GetFileInfo:
2288 clevermous 2908
        cmp     byte [esi], 0
6868 pathoswith 2909
        jz      .volume
2643 clevermous 2910
        call    fat_lock
6468 pathoswith 2911
        call    hd_find_lfn
6867 pathoswith 2912
        jc      @f
2643 clevermous 2913
        push    ebp
2914
        xor     ebp, ebp
2915
        mov     esi, [ebx+16]
2916
        mov     dword [esi+4], ebp
2917
        call    fat_entry_to_bdfe2
2918
        pop     ebp
2919
        xor     eax, eax
6867 pathoswith 2920
@@:
2643 clevermous 2921
        push    eax
2922
        call    fat_unlock
2923
        pop     eax
6876 pathoswith 2924
@@:
2643 clevermous 2925
        ret
2288 clevermous 2926
 
6868 pathoswith 2927
.volume:
2928
        mov     eax, dword[ebp+FAT.Length]
2929
        mov     edx, dword[ebp+FAT.Length+4]
2930
        mov     edi, [ebx+16]
2931
        shld    edx, eax, 9
2932
        shl     eax, 9
2933
        mov     [edi+36], edx
2934
        mov     [edi+32], eax
2935
        mov     eax, [ebx+8]
2936
        mov     byte [edi], 8
2937
        mov     [edi+4], eax
6876 pathoswith 2938
        test    eax, eax
2939
        jz      @b
6868 pathoswith 2940
        lea     esi, [ebp+FAT.volumeLabel]
2941
        mov     ecx, 11
2942
@@:
2943
        mov     byte [esi+ecx], 0
2944
        dec     ecx
2945
        jz      @f
2946
        cmp     byte [esi+ecx], ' '
2947
        jz      @b
2948
@@:
2949
        mov     cl, 12
2950
        add     edi, 40
2951
        cmp     eax, 2
2952
        jz      @f
2953
        rep movsb
2954
        xor     eax, eax
2955
        ret
2956
 
2957
@@:
2958
        lodsb
2959
        stosw
2960
        loop    @b
2961
        ret
2962
 
2643 clevermous 2963
;----------------------------------------------------------------
2964
fat_SetFileInfo:
2965
        call    fat_lock
6468 pathoswith 2966
        call    hd_find_lfn
6867 pathoswith 2967
        jc      @f
2288 clevermous 2968
        push    eax
2643 clevermous 2969
        mov     edx, [ebx+16]
2288 clevermous 2970
        call    bdfe_to_fat_entry
2971
        pop     eax
2643 clevermous 2972
        lea     ebx, [ebp+FAT.buffer]
2973
        call    fs_write32_sys
2288 clevermous 2974
        call    update_disk
2975
        xor     eax, eax
6867 pathoswith 2976
@@:
2643 clevermous 2977
        push    eax
2978
        call    fat_unlock
2979
        pop     eax
2980
        ret
2288 clevermous 2981
 
2982
;----------------------------------------------------------------
2643 clevermous 2983
fat_Delete:
2984
        call    fat_lock
2985
        and     [ebp+FAT.longname_sec1], 0
2986
        and     [ebp+FAT.longname_sec2], 0
6468 pathoswith 2987
        call    hd_find_lfn
6845 pathoswith 2988
        jc      .notFound
2288 clevermous 2989
        cmp     dword [edi], '.   '
2990
        jz      .access_denied2
2991
        cmp     dword [edi], '..  '
2992
        jz      .access_denied2
2993
        test    byte [edi+11], 10h
2994
        jz      .dodel
2995
; we can delete only empty folders!
2996
        pushad
2643 clevermous 2997
        mov     esi, [edi+20-2]
2998
        mov     si, [edi+26]
2288 clevermous 2999
        xor     ecx, ecx
2643 clevermous 3000
        lea     eax, [esi-2]
3001
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3002
        add     eax, [ebp+FAT.DATA_START]
3003
        lea     ebx, [ebp+FAT.buffer]
3004
        call    fs_read32_sys
3005
        test    eax, eax
2288 clevermous 3006
        jnz     .err1
2643 clevermous 3007
        lea     eax, [ebx+0x200]
2288 clevermous 3008
        add     ebx, 2*0x20
3009
.checkempty:
3010
        cmp     byte [ebx], 0
3011
        jz      .empty
3012
        cmp     byte [ebx], 0xE5
3013
        jnz     .notempty
3014
        add     ebx, 0x20
2643 clevermous 3015
        cmp     ebx, eax
2288 clevermous 3016
        jb      .checkempty
3017
        inc     ecx
2643 clevermous 3018
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 3019
        jb      @f
2643 clevermous 3020
        mov     eax, esi
2288 clevermous 3021
        call    get_FAT
2643 clevermous 3022
        jc      .err1
3174 clevermous 3023
        cmp     eax, 2
3024
        jb      .error_fat
3025
        cmp     eax, [ebp+FAT.fatRESERVED]
3026
        jae     .empty
2643 clevermous 3027
        mov     esi, eax
2288 clevermous 3028
        xor     ecx, ecx
3029
@@:
2643 clevermous 3030
        lea     eax, [esi-2]
3031
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3032
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 3033
        add     eax, ecx
2643 clevermous 3034
        lea     ebx, [ebp+FAT.buffer]
3035
        call    fs_read32_sys
3036
        test    eax, eax
3037
        lea     eax, [ebx+0x200]
2288 clevermous 3038
        jz      .checkempty
3039
.err1:
3040
        popad
3041
.err2:
6845 pathoswith 3042
        push    ERROR_DEVICE
3043
.ret:
2643 clevermous 3044
        call    fat_unlock
6867 pathoswith 3045
        pop     eax
2288 clevermous 3046
        ret
6845 pathoswith 3047
 
3048
.notFound:
3049
        push    ERROR_FILE_NOT_FOUND
3050
        jmp     .ret
3051
 
3174 clevermous 3052
.error_fat:
3053
        popad
6845 pathoswith 3054
        push    ERROR_FS_FAIL
3055
        jmp     .ret
3056
 
2288 clevermous 3057
.notempty:
3058
        popad
3059
.access_denied2:
6845 pathoswith 3060
        push    ERROR_ACCESS_DENIED
3061
        jmp     .ret
3062
 
2288 clevermous 3063
.empty:
3064
        popad
2643 clevermous 3065
        push    eax ebx
3066
        lea     ebx, [ebp+FAT.buffer]
3067
        call    fs_read32_sys
3068
        test    eax, eax
3069
        pop     ebx eax
2288 clevermous 3070
        jnz     .err2
3071
.dodel:
3072
        push    eax
3073
        mov     eax, [edi+20-2]
3074
        mov     ax, [edi+26]
3075
        xchg    eax, [esp]
3076
; delete folder entry
3077
        mov     byte [edi], 0xE5
3078
; delete LFN (if present)
3079
.lfndel:
2643 clevermous 3080
        lea     edx, [ebp+FAT.buffer]
3081
        cmp     edi, edx
2288 clevermous 3082
        ja      @f
2643 clevermous 3083
        cmp     [ebp+FAT.longname_sec2], 0
2288 clevermous 3084
        jz      .lfndone
2643 clevermous 3085
        push    [ebp+FAT.longname_sec2]
3086
        push    [ebp+FAT.longname_sec1]
3087
        pop     [ebp+FAT.longname_sec2]
3088
        and     [ebp+FAT.longname_sec1], 0
2288 clevermous 3089
        push    ebx
2643 clevermous 3090
        mov     ebx, edx
3091
        call    fs_write32_sys
2288 clevermous 3092
        mov     eax, [esp+4]
2643 clevermous 3093
        call    fs_read32_sys
2288 clevermous 3094
        pop     ebx
3095
        pop     eax
2643 clevermous 3096
        lea     edi, [ebp+FAT.buffer+0x200]
2288 clevermous 3097
@@:
3098
        sub     edi, 0x20
3099
        cmp     byte [edi], 0xE5
3100
        jz      .lfndone
3101
        cmp     byte [edi+11], 0xF
3102
        jnz     .lfndone
3103
        mov     byte [edi], 0xE5
3104
        jmp     .lfndel
3105
.lfndone:
3106
        push    ebx
2643 clevermous 3107
        lea     ebx, [ebp+FAT.buffer]
3108
        call    fs_write32_sys
2288 clevermous 3109
        pop     ebx
3110
; delete FAT chain
3111
        pop     eax
3112
        call    clear_cluster_chain
3113
        call    update_disk
2643 clevermous 3114
        call    fat_unlock
2288 clevermous 3115
        xor     eax, eax
3116
        ret
6917 pathoswith 3117
 
3118
;----------------------------------------------------------------
3119
fat_Rename:
3120
; in: edi -> new path string in UTF-8
3121
        push    esi edi
3122
        call    fat_lock
3123
        call    hd_find_lfn
3124
        pop     ebx
3125
        jc      .error
3126
        sub     esp, 32
3127
        mov     esi, edi
3128
        mov     edi, esp
3129
        mov     ecx, 8
3130
        rep movsd
3131
        mov     [ebp+FAT.createOption], 2
3132
        mov     esi, ebx
3133
        call    fat_CreateFile.rename
3134
        add     esp, 32
3135
        pop     esi
3136
        test    eax, eax
3137
        jnz     .ret
3138
        push    eax
3139
        mov     [ebp+FAT.longname_sec1], eax
3140
        mov     [ebp+FAT.longname_sec2], eax
3141
        call    hd_find_lfn
3142
        jc      .error
3143
        mov     byte [edi], 0xE5
3144
        jmp     fat_Delete.lfndel
3145
 
3146
.error:
3147
        push    eax
3148
        call    fat_unlock
3149
        pop     eax ebx
3150
.ret:
3151
        ret