Subversion Repositories Kolibri OS

Rev

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