Subversion Repositories Kolibri OS

Rev

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

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