Subversion Repositories Kolibri OS

Rev

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