Subversion Repositories Kolibri OS

Rev

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