Subversion Repositories Kolibri OS

Rev

Rev 6846 | Rev 6867 | 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: 6850 $
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
6798 pathoswith 1413
        cmp     byte [ebp-4], 2
1414
        jz      .utf16
1415
        cmp     byte [ebp-4], 3
1416
        jz      .utf8
1417
@@:
6576 pathoswith 1418
        lodsw
6798 pathoswith 1419
        call    uni2ansi_char
1420
        stosb
1421
        test    al, al
1422
        jnz     @b
6576 pathoswith 1423
        pop     esi edi
6798 pathoswith 1424
        add     esi, 264
4273 clevermous 1425
.ret:
1426
        ret
6471 pathoswith 1427
 
6798 pathoswith 1428
.utf8:
1429
        push    ecx
1430
        mov     ecx, 519
1431
        call    UTF16to8_string
1432
        pop     ecx
1433
        jmp     @f
1434
 
1435
.utf16:
6471 pathoswith 1436
        lodsw
6798 pathoswith 1437
        stosw
1438
        test    eax, eax
1439
        jnz     .utf16
1440
@@:
6576 pathoswith 1441
        pop     esi edi
6798 pathoswith 1442
        add     esi, 520
6576 pathoswith 1443
        ret
4273 clevermous 1444
 
1445
bdfe_to_fat_entry:
1446
; convert BDFE at edx to FAT entry at edi
1447
; destroys eax
1448
; attributes byte
1449
        test    byte [edi+11], 8        ; volume label?
1450
        jnz     @f
1451
        mov     al, [edx]
1452
        and     al, 0x27
1453
        and     byte [edi+11], 0x10
1454
        or      byte [edi+11], al
1455
@@:
1456
        mov     eax, [edx+8]
1457
        call    bdfe_to_fat_time
1458
        mov     [edi+14], ax            ; creation time
1459
        mov     eax, [edx+12]
1460
        call    bdfe_to_fat_date
1461
        mov     [edi+16], ax            ; creation date
1462
        mov     eax, [edx+20]
1463
        call    bdfe_to_fat_date
1464
        mov     [edi+18], ax            ; last access date
1465
        mov     eax, [edx+24]
1466
        call    bdfe_to_fat_time
1467
        mov     [edi+22], ax            ; last write time
1468
        mov     eax, [edx+28]
1469
        call    bdfe_to_fat_date
1470
        mov     [edi+24], ax            ; last write date
1471
        ret
1472
 
2288 clevermous 1473
hd_find_lfn:
6471 pathoswith 1474
; in: esi -> path string in UTF-8
2643 clevermous 1475
; out: CF=1 - file not found, eax=error code
2288 clevermous 1476
;      else CF=0 and edi->direntry, eax=sector
1477
        push    esi edi
1478
        push    0
1479
        push    0
4273 clevermous 1480
        push    fat1x_root_first
1481
        push    fat1x_root_next
2643 clevermous 1482
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
1483
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1484
        jz      .fat32
1485
.loop:
4273 clevermous 1486
        and     [ebp+FAT.longname_sec1], 0
1487
        and     [ebp+FAT.longname_sec2], 0
2288 clevermous 1488
        call    fat_find_lfn
1489
        jc      .notfound
1490
        cmp     byte [esi], 0
1491
        jz      .found
1492
        test    byte [edi+11], 10h
1493
        jz      .notfound
1494
        and     dword [esp+12], 0
1495
        mov     eax, [edi+20-2]
1496
        mov     ax, [edi+26]    ; cluster
1497
.fat32:
1498
        mov     [esp+8], eax
1499
        mov     dword [esp+4], fat_notroot_first
1500
        mov     dword [esp], fat_notroot_next
1501
        jmp     .loop
6468 pathoswith 1502
 
2288 clevermous 1503
.notfound:
1504
        add     esp, 16
1505
        pop     edi esi
1506
        stc
6468 pathoswith 1507
        ret
1508
 
2288 clevermous 1509
.found:
1510
        lea     eax, [esp+8]
1511
        cmp     dword [eax], 0
1512
        jz      .root
1513
        call    fat_get_sector
1514
        jmp     .cmn
6468 pathoswith 1515
 
2288 clevermous 1516
.root:
1517
        mov     eax, [eax+4]
2643 clevermous 1518
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 1519
.cmn:
1520
        add     esp, 20         ; CF=0
1521
        pop     esi
6468 pathoswith 1522
        ret
2288 clevermous 1523
 
1524
;----------------------------------------------------------------
2643 clevermous 1525
fat_Read:
1526
        call    fat_lock
2288 clevermous 1527
        push    edi
6468 pathoswith 1528
        call    hd_find_lfn
6845 pathoswith 1529
        jc      .notFound
5578 Pathoswith 1530
        test    byte [edi+11], 0x10     ; do not allow read directories
2288 clevermous 1531
        jnz     .noaccess
2643 clevermous 1532
        cmp     dword [ebx+8], 0
6845 pathoswith 1533
        jnz     .endOfFile
5578 Pathoswith 1534
        mov     edx, [ebx+4]    ; file offset
2643 clevermous 1535
        mov     ecx, [ebx+12]   ; size
5578 Pathoswith 1536
        mov     ebx, [ebx+16]   ; buffer
1537
        push    ebx
2288 clevermous 1538
        push    0
6037 pathoswith 1539
        test    ecx, ecx
1540
        jz      .done
2288 clevermous 1541
        mov     eax, [edi+28]
5578 Pathoswith 1542
        sub     eax, edx
1543
        jb      .fileEnd
2288 clevermous 1544
        cmp     eax, ecx
1545
        jae     @f
1546
        mov     ecx, eax
1547
        mov     byte [esp], 6
1548
@@:
1549
        mov     eax, [edi+20-2]
1550
        mov     ax, [edi+26]
5578 Pathoswith 1551
; now eax=cluster, ebx=buffer for data, ecx=count, edx=position
1552
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1553
        shl     edi, 9
1554
@@:
2643 clevermous 1555
        cmp     eax, 2
5578 Pathoswith 1556
        jb      .fileEnd
2643 clevermous 1557
        cmp     eax, [ebp+FAT.fatRESERVED]
5578 Pathoswith 1558
        jae     .fileEnd
1559
        sub     edx, edi
1560
        jc      @f
1561
        call    get_FAT
1562
        jc      .noaccess2
1563
        jmp     @b
6845 pathoswith 1564
 
1565
.notFound:
1566
        push    eax
1567
        jmp     .ret
1568
 
1569
.noaccess:
1570
        push    ERROR_ACCESS_DENIED
1571
        jmp     .ret
1572
 
1573
.endOfFile:
1574
        push    ERROR_END_OF_FILE
1575
.ret:
1576
        call    fat_unlock
1577
        pop     eax edi
1578
        xor     ebx, ebx
1579
        ret
1580
 
5578 Pathoswith 1581
@@:
1582
        mov     esi, eax
2288 clevermous 1583
        dec     eax
1584
        dec     eax
5578 Pathoswith 1585
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2643 clevermous 1586
        add     eax, [ebp+FAT.DATA_START]
5578 Pathoswith 1587
        add     edx, edi
1588
        jz      .alignedCluster
1589
        mov     edi, edx
1590
        shr     edi, 9
1591
        add     eax, edi
1592
        and     edx, 511
5840 pathoswith 1593
        cmp     ecx, 512
1594
        jc      .sectorPiece
1595
        test    edx, edx
5578 Pathoswith 1596
        jz      .alignedSector
1597
.sectorPiece:
2643 clevermous 1598
        push    eax ebx
1599
        lea     ebx, [ebp+FAT.buffer]
1600
        call    fs_read32_app
1601
        test    eax, eax
2288 clevermous 1602
        mov     eax, ebx
1603
        pop     ebx
5578 Pathoswith 1604
        jne     .noaccess3
1605
        add     eax, edx
2288 clevermous 1606
        push    ecx
5578 Pathoswith 1607
        add     ecx, edx
2288 clevermous 1608
        cmp     ecx, 512
1609
        jbe     @f
1610
        mov     ecx, 512
1611
@@:
5578 Pathoswith 1612
        sub     ecx, edx
2288 clevermous 1613
        call    memmove
1614
        sub     [esp], ecx
5578 Pathoswith 1615
        add     ebx, ecx
1616
        pop     ecx eax
1617
        xor     edx, edx
1618
        inc     edi
2288 clevermous 1619
        inc     eax
5578 Pathoswith 1620
        test    ecx, ecx
1621
        jz      .done
1622
.alignedSector:
1623
        shl     edi, 9
1624
        add     ecx, edi
1625
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1626
        shl     edi, 9
1627
.alignedCluster:
1628
        cmp     ecx, 512
1629
        jc      .sectorPiece
1630
        mov     edx, eax
1631
        mov     eax, esi
1632
@@:
1633
        sub     ecx, edi
1634
        jbe     .readEnd
2288 clevermous 1635
        call    get_FAT
5578 Pathoswith 1636
        jc      .noaccess4
1637
        cmp     eax, 2
1638
        jb      .fileEnd2
1639
        cmp     eax, [ebp+FAT.fatRESERVED]
1640
        jae     .fileEnd2
1641
        inc     esi
1642
        cmp     eax, esi
1643
        jz      @b
1644
.fragmentEnd:
1645
        xchg    eax, esi
1646
        dec     eax
1647
        dec     eax
1648
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1649
        add     eax, [ebp+FAT.DATA_START]
1650
        push    ecx
1651
        mov     ecx, eax
5840 pathoswith 1652
        mov     eax, esi
1653
        dec     eax
1654
        dec     eax
1655
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1656
        add     eax, [ebp+FAT.DATA_START]
1657
        push    eax
1658
.readFragment:
1659
        sub     ecx, edx
5578 Pathoswith 1660
        mov     eax, edx
1661
        xor     edx, edx
1662
        call    fs_read64_app
1663
        shl     ecx, 9
1664
        add     ebx, ecx
1665
        test    eax, eax
2288 clevermous 1666
        pop     eax
5578 Pathoswith 1667
        jnz     .noaccess3
1668
        pop     ecx
1669
        xor     edx, edx
6036 pathoswith 1670
        jecxz   .done
5578 Pathoswith 1671
        jmp     .alignedCluster
6845 pathoswith 1672
 
5578 Pathoswith 1673
.readEnd:
1674
        add     ecx, edi
1675
        mov     edi, ecx
1676
        and     ecx, 511
1677
        shr     edi, 9
1678
        dec     eax
1679
        dec     eax
1680
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1681
        add     eax, [ebp+FAT.DATA_START]
1682
        add     eax, edi
5840 pathoswith 1683
        push    ecx
1684
        push    eax
1685
        mov     ecx, eax
5578 Pathoswith 1686
        jmp     .readFragment
6845 pathoswith 1687
 
5578 Pathoswith 1688
.noaccess3:
2288 clevermous 1689
        pop     eax
5578 Pathoswith 1690
.noaccess2:
1691
        mov     byte [esp], ERROR_DEVICE
2288 clevermous 1692
.done:
2643 clevermous 1693
        call    fat_unlock
1694
        pop     eax edx edi
2288 clevermous 1695
        sub     ebx, edx
1696
        ret
6845 pathoswith 1697
 
5578 Pathoswith 1698
.fileEnd:
1699
        mov     byte [esp], ERROR_END_OF_FILE
1700
        jmp     .done
6845 pathoswith 1701
 
5578 Pathoswith 1702
.noaccess4:
1703
        mov     byte [esp], ERROR_DEVICE
1704
        jmp     @f
6845 pathoswith 1705
 
5578 Pathoswith 1706
.fileEnd2:
1707
        mov     byte [esp], ERROR_END_OF_FILE
1708
@@:
1709
        inc     esi
1710
        xor     ecx, ecx
1711
        jmp     .fragmentEnd
2288 clevermous 1712
 
1713
;----------------------------------------------------------------
2643 clevermous 1714
fat_ReadFolder:
1715
        call    fat_lock
1716
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
2288 clevermous 1717
        push    edi
1718
        cmp     byte [esi], 0
1719
        jz      .doit
6468 pathoswith 1720
        call    hd_find_lfn
2288 clevermous 1721
        jnc     .found
1722
        pop     edi
2643 clevermous 1723
        push    eax
1724
        call    fat_unlock
1725
        pop     eax
2288 clevermous 1726
        or      ebx, -1
1727
        ret
1728
.found:
1729
        test    byte [edi+11], 0x10     ; do not allow read files
1730
        jnz     .found_dir
1731
        pop     edi
2643 clevermous 1732
        call    fat_unlock
2288 clevermous 1733
        or      ebx, -1
1734
        mov     eax, ERROR_ACCESS_DENIED
1735
        ret
1736
.found_dir:
1737
        mov     eax, [edi+20-2]
1738
        mov     ax, [edi+26]    ; eax=cluster
1739
.doit:
2643 clevermous 1740
        push    esi
2288 clevermous 1741
        sub     esp, 262*2      ; reserve space for LFN
6471 pathoswith 1742
        push    dword [ebx+8]   ; cp866/UNICODE name
2643 clevermous 1743
        mov     edx, [ebx+16]   ; pointer to buffer
2288 clevermous 1744
; init header
2643 clevermous 1745
        push    eax
2288 clevermous 1746
        mov     edi, edx
1747
        mov     ecx, 32/4
1748
        xor     eax, eax
1749
        rep stosd
2643 clevermous 1750
        pop     eax
2288 clevermous 1751
        mov     byte [edx], 1   ; version
1752
        mov     esi, edi        ; esi points to BDFE
2643 clevermous 1753
        mov     ecx, [ebx+12]   ; number of blocks to read
1754
        mov     ebx, [ebx+4]    ; index of the first block
2288 clevermous 1755
.new_cluster:
2643 clevermous 1756
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 1757
        test    eax, eax
1758
        jnz     @f
2643 clevermous 1759
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1760
        jz      .notfound
2643 clevermous 1761
        mov     eax, [ebp+FAT.ROOT_START]
1762
        push    [ebp+FAT.ROOT_SECTORS]
2288 clevermous 1763
        push    ebx
1764
        jmp     .new_sector
1765
@@:
1766
        dec     eax
1767
        dec     eax
2643 clevermous 1768
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1769
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
1770
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1771
        push    ebx
1772
.new_sector:
2643 clevermous 1773
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 1774
        mov     edi, ebx
2643 clevermous 1775
        push    eax
1776
        call    fs_read32_sys
1777
        test    eax, eax
1778
        pop     eax
2288 clevermous 1779
        jnz     .notfound2
1780
        add     ebx, 512
1781
        push    eax
1782
.l1:
2643 clevermous 1783
        push    ebp
1784
        lea     ebp, [esp+20]
2288 clevermous 1785
        call    fat_get_name
2643 clevermous 1786
        pop     ebp
2288 clevermous 1787
        jc      .l2
1788
        cmp     byte [edi+11], 0xF
1789
        jnz     .do_bdfe
1790
        add     edi, 0x20
1791
        cmp     edi, ebx
1792
        jb      .do_bdfe
1793
        pop     eax
1794
        inc     eax
1795
        dec     dword [esp+4]
1796
        jnz     @f
2643 clevermous 1797
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 1798
        test    eax, eax
1799
        jz      .done
1800
        call    get_FAT
2643 clevermous 1801
        jc      .notfound2
2288 clevermous 1802
        cmp     eax, 2
1803
        jb      .done
2643 clevermous 1804
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1805
        jae     .done
1806
        push    eax
2643 clevermous 1807
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1808
        mov     [esp+8], eax
1809
        pop     eax
2643 clevermous 1810
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 1811
        dec     eax
1812
        dec     eax
2643 clevermous 1813
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1814
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1815
@@:
2643 clevermous 1816
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 1817
        mov     edi, ebx
2643 clevermous 1818
        push    eax
1819
        call    fs_read32_sys
1820
        test    eax, eax
1821
        pop     eax
2288 clevermous 1822
        jnz     .notfound2
1823
        add     ebx, 512
1824
        push    eax
1825
.do_bdfe:
1826
        inc     dword [edx+8]   ; new file found
1827
        dec     dword [esp+4]
1828
        jns     .l2
1829
        dec     ecx
1830
        js      .l2
1831
        inc     dword [edx+4]   ; new file block copied
2643 clevermous 1832
        push    ebp
1833
        lea     ebp, [esp+20]
2288 clevermous 1834
        call    fat_entry_to_bdfe
2643 clevermous 1835
        pop     ebp
2288 clevermous 1836
.l2:
1837
        add     edi, 0x20
1838
        cmp     edi, ebx
1839
        jb      .l1
1840
        pop     eax
1841
        inc     eax
1842
        dec     dword [esp+4]
1843
        jnz     .new_sector
2643 clevermous 1844
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 1845
        test    eax, eax
1846
        jz      .done
1847
        call    get_FAT
2643 clevermous 1848
        jc      .notfound2
2288 clevermous 1849
        cmp     eax, 2
1850
        jb      .done
2643 clevermous 1851
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1852
        jae     .done
1853
        push    eax
2643 clevermous 1854
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1855
        mov     [esp+8], eax
1856
        pop     eax
1857
        pop     ebx
1858
        add     esp, 4
1859
        jmp     .new_cluster
1860
.notfound2:
1861
        add     esp, 8
1862
.notfound:
1863
        add     esp, 262*2+4
2643 clevermous 1864
        pop     esi edi
1865
        mov     ebx, [edx+4]
1866
        call    fat_unlock
1867
        mov     eax, ERROR_DEVICE
2288 clevermous 1868
        ret
1869
.done:
1870
        add     esp, 262*2+4+8
1871
        mov     ebx, [edx+4]
1872
        xor     eax, eax
1873
        dec     ecx
1874
        js      @f
1875
        mov     al, ERROR_END_OF_FILE
1876
@@:
2643 clevermous 1877
        push    eax
1878
        call    fat_unlock
1879
        pop     eax
1880
        pop     esi edi
2288 clevermous 1881
        ret
1882
 
4273 clevermous 1883
fat1x_root_next:
2643 clevermous 1884
        push    ecx
1885
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1886
        cmp     edi, ecx
4273 clevermous 1887
        jae     fat1x_root_next_sector
2643 clevermous 1888
        pop     ecx
2288 clevermous 1889
        add     edi, 0x20
1890
        ret     ; CF=0
4273 clevermous 1891
fat1x_root_next_sector:
2288 clevermous 1892
; read next sector
2643 clevermous 1893
        push    [ebp+FAT.longname_sec2]
1894
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1895
        mov     ecx, [eax+4]
1896
        push    ecx
2643 clevermous 1897
        add     ecx, [ebp+FAT.ROOT_START]
1898
        mov     [ebp+FAT.longname_sec2], ecx
2288 clevermous 1899
        pop     ecx
1900
        inc     ecx
1901
        mov     [eax+4], ecx
2643 clevermous 1902
        cmp     ecx, [ebp+FAT.ROOT_SECTORS]
2288 clevermous 1903
        pop     ecx
4273 clevermous 1904
        jb      fat1x_root_first
2643 clevermous 1905
        mov     eax, ERROR_FILE_NOT_FOUND
1906
        stc
1907
        ret
4273 clevermous 1908
fat1x_root_first:
2288 clevermous 1909
        mov     eax, [eax+4]
2643 clevermous 1910
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 1911
        push    ebx
2643 clevermous 1912
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1913
        mov     ebx, edi
2643 clevermous 1914
        call    fs_read32_sys
2288 clevermous 1915
        pop     ebx
2643 clevermous 1916
        test    eax, eax
2288 clevermous 1917
        jnz     .readerr
1918
        ret     ; CF=0
1919
.readerr:
2643 clevermous 1920
        mov     eax, ERROR_DEVICE
2288 clevermous 1921
        stc
1922
        ret
2643 clevermous 1923
.notfound:
1924
        mov     eax, ERROR_FILE_NOT_FOUND
1925
        stc
1926
        ret
4273 clevermous 1927
fat1x_root_begin_write:
2288 clevermous 1928
        push    edi eax
4273 clevermous 1929
        call    fat1x_root_first
2288 clevermous 1930
        pop     eax edi
1931
        ret
4273 clevermous 1932
fat1x_root_end_write:
2288 clevermous 1933
        pusha
1934
        mov     eax, [eax+4]
2643 clevermous 1935
        add     eax, [ebp+FAT.ROOT_START]
1936
        lea     ebx, [ebp+FAT.buffer]
1937
        call    fs_write32_sys
2288 clevermous 1938
        popa
1939
        ret
4273 clevermous 1940
fat1x_root_next_write:
2643 clevermous 1941
        push    ecx
1942
        lea     ecx, [ebp+FAT.buffer+0x200]
1943
        cmp     edi, ecx
2288 clevermous 1944
        jae     @f
2643 clevermous 1945
        pop     ecx
2288 clevermous 1946
        ret
1947
@@:
4273 clevermous 1948
        call    fat1x_root_end_write
1949
        jmp     fat1x_root_next_sector
1950
fat1x_root_extend_dir:
2288 clevermous 1951
        stc
1952
        ret
1953
 
1954
fat_notroot_next:
2643 clevermous 1955
        push    ecx
1956
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1957
        cmp     edi, ecx
2288 clevermous 1958
        jae     fat_notroot_next_sector
2643 clevermous 1959
        pop     ecx
2288 clevermous 1960
        add     edi, 0x20
1961
        ret     ; CF=0
1962
fat_notroot_next_sector:
2643 clevermous 1963
        push    [ebp+FAT.longname_sec2]
1964
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1965
        push    eax
1966
        call    fat_get_sector
2643 clevermous 1967
        mov     [ebp+FAT.longname_sec2], eax
2288 clevermous 1968
        pop     eax
1969
        mov     ecx, [eax+4]
1970
        inc     ecx
2643 clevermous 1971
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1972
        jae     fat_notroot_next_cluster
1973
        mov     [eax+4], ecx
1974
        jmp     @f
1975
fat_notroot_next_cluster:
1976
        push    eax
1977
        mov     eax, [eax]
1978
        call    get_FAT
1979
        mov     ecx, eax
1980
        pop     eax
2643 clevermous 1981
        jc      fat_notroot_first.deverr
1982
        cmp     ecx, 2
1983
        jb      fat_notroot_next_err
1984
        cmp     ecx, [ebp+FAT.fatRESERVED]
2288 clevermous 1985
        jae     fat_notroot_next_err
1986
        mov     [eax], ecx
1987
        and     dword [eax+4], 0
1988
@@:
1989
        pop     ecx
1990
fat_notroot_first:
1991
        call    fat_get_sector
1992
        push    ebx
2643 clevermous 1993
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1994
        mov     ebx, edi
2643 clevermous 1995
        call    fs_read32_sys
2288 clevermous 1996
        pop     ebx
2643 clevermous 1997
        test    eax, eax
1998
        jz      .ret ; CF=0
1999
        push    ecx
2000
.deverr:
2001
        pop     ecx
2002
        mov     eax, ERROR_DEVICE
2003
        stc
2004
.ret:
2005
        ret
2288 clevermous 2006
fat_notroot_next_err:
2007
        pop     ecx
2643 clevermous 2008
        mov     eax, ERROR_FILE_NOT_FOUND
2288 clevermous 2009
        stc
2010
        ret
2011
fat_notroot_begin_write:
2012
        push    eax edi
2013
        call    fat_notroot_first
2014
        pop     edi eax
2015
        ret
2016
fat_notroot_end_write:
2017
        call    fat_get_sector
2018
        push    ebx
2643 clevermous 2019
        lea     ebx, [ebp+FAT.buffer]
2020
        call    fs_write32_sys
2288 clevermous 2021
        pop     ebx
2022
        ret
2023
fat_notroot_next_write:
2643 clevermous 2024
        push    ecx
2025
        lea     ecx, [ebp+FAT.buffer+0x200]
2026
        cmp     edi, ecx
2288 clevermous 2027
        jae     @f
2643 clevermous 2028
        pop     ecx
2288 clevermous 2029
        ret
2030
@@:
2031
        push    eax
2032
        call    fat_notroot_end_write
2033
        pop     eax
2034
        jmp     fat_notroot_next_sector
2035
fat_notroot_extend_dir:
2036
        push    eax
2037
        call    get_free_FAT
2038
        jnc     .found
2039
        pop     eax
2040
        ret     ; CF=1
2041
.found:
2042
        push    edx
2643 clevermous 2043
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2044
        call    set_FAT
2643 clevermous 2045
        jc      .writeerr
2288 clevermous 2046
        mov     edx, eax
2047
        mov     eax, [esp+4]
2048
        mov     eax, [eax]
2049
        push    edx
2050
        call    set_FAT
2051
        pop     edx
2643 clevermous 2052
        jnc     @f
2053
.writeerr:
2288 clevermous 2054
        pop     edx
2055
        pop     eax
2056
        stc
2057
        ret
2058
@@:
2059
        push    ecx
2060
        or      ecx, -1
2061
        call    add_disk_free_space
2062
; zero new cluster
2063
        mov     ecx, 512/4
2643 clevermous 2064
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 2065
        push    edi
2066
        xor     eax, eax
2067
        rep stosd
2068
        pop     edi
2069
        pop     ecx
2070
        mov     eax, [esp+4]
2071
        mov     [eax], edx
2072
        and     dword [eax+4], 0
2073
        pop     edx
2074
        mov     eax, [eax]
2075
        dec     eax
2076
        dec     eax
2077
        push    ebx ecx
2643 clevermous 2078
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2079
        imul    eax, ecx
2643 clevermous 2080
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 2081
        mov     ebx, edi
2082
@@:
2643 clevermous 2083
        push    eax
2084
        call    fs_write32_sys
2085
        pop     eax
2288 clevermous 2086
        inc     eax
2087
        loop    @b
2088
        pop     ecx ebx eax
2089
        clc
2090
        ret
2091
 
2092
fat_get_sector:
2093
        push    ecx
2094
        mov     ecx, [eax]
2095
        dec     ecx
2096
        dec     ecx
2643 clevermous 2097
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2098
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 2099
        add     ecx, [eax+4]
2100
        mov     eax, ecx
2101
        pop     ecx
2102
        ret
2103
 
2643 clevermous 2104
;----------------------------------------------------------------
2105
fat_CreateFolder:
2106
        push    1
6468 pathoswith 2107
        jmp     @f
2643 clevermous 2108
 
6468 pathoswith 2109
fat_CreateFile:
2643 clevermous 2110
        push    0
6468 pathoswith 2111
@@:
2643 clevermous 2112
        call    fat_lock
2113
        pop     eax
2114
        mov     ecx, [ebx+12]
2115
        mov     edx, [ebx+16]
2288 clevermous 2116
        pushad
2117
        xor     edi, edi
2118
        push    esi
2119
@@:
2120
        lodsb
2121
        test    al, al
2122
        jz      @f
2123
        cmp     al, '/'
2124
        jnz     @b
2125
        lea     edi, [esi-1]
2126
        jmp     @b
6468 pathoswith 2127
 
2288 clevermous 2128
@@:
2129
        pop     esi
2130
        test    edi, edi
2131
        jnz     .noroot
2643 clevermous 2132
        mov     edx, [ebp+FAT.ROOT_CLUSTER]
2133
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 2134
        jz      .pushnotroot
2643 clevermous 2135
        xor     edx, edx
2136
        push    edx
4273 clevermous 2137
        push    fat1x_root_extend_dir
2138
        push    fat1x_root_end_write
2139
        push    fat1x_root_next_write
2140
        push    fat1x_root_begin_write
2643 clevermous 2141
        push    edx
2142
        push    edx
4273 clevermous 2143
        push    fat1x_root_first
2144
        push    fat1x_root_next
2288 clevermous 2145
        jmp     .common1
6468 pathoswith 2146
 
2288 clevermous 2147
.noroot:
2148
        mov     eax, ERROR_ACCESS_DENIED
2149
        cmp     byte [edi+1], 0
2150
        jz      .ret1
2151
; check existence
2152
        mov     byte [edi], 0
2153
        push    edi
6468 pathoswith 2154
        call    hd_find_lfn
2288 clevermous 2155
        pop     esi
2156
        mov     byte [esi], '/'
2157
        jnc     @f
2158
.notfound0:
2159
        mov     eax, ERROR_FILE_NOT_FOUND
2160
.ret1:
2161
        mov     [esp+28], eax
2643 clevermous 2162
        call    fat_unlock
2288 clevermous 2163
        popad
2164
        xor     ebx, ebx
2165
        ret
6468 pathoswith 2166
 
2288 clevermous 2167
@@:
2168
        inc     esi
2169
        test    byte [edi+11], 0x10     ; must be directory
2170
        mov     eax, ERROR_ACCESS_DENIED
2171
        jz      .ret1
2643 clevermous 2172
        mov     edx, [edi+20-2]
2173
        mov     dx, [edi+26]            ; ebp=cluster
6468 pathoswith 2174
        mov     eax, ERROR_FS_FAIL
2643 clevermous 2175
        cmp     edx, 2
2288 clevermous 2176
        jb      .ret1
2177
.pushnotroot:
2643 clevermous 2178
        push    edx
2288 clevermous 2179
        push    fat_notroot_extend_dir
2180
        push    fat_notroot_end_write
2181
        push    fat_notroot_next_write
2182
        push    fat_notroot_begin_write
2183
        push    0
2643 clevermous 2184
        push    edx
2288 clevermous 2185
        push    fat_notroot_first
2186
        push    fat_notroot_next
2187
.common1:
2188
        call    fat_find_lfn
2189
        jc      .notfound
2190
        test    byte [edi+11], 10h
2191
        jz      .exists_file
6468 pathoswith 2192
; found directory
2643 clevermous 2193
        add     esp, 36
2194
        call    fat_unlock
2288 clevermous 2195
        popad
2196
        test    al, al
2197
        mov     eax, ERROR_ACCESS_DENIED
2198
        jz      @f
2199
        mov     al, 0
2200
@@:
2201
        xor     ebx, ebx
2202
        ret
6468 pathoswith 2203
 
2288 clevermous 2204
.exists_file:
2643 clevermous 2205
        cmp     byte [esp+36+28], 0
2288 clevermous 2206
        jz      @f
2643 clevermous 2207
        add     esp, 36
2208
        call    fat_unlock
2288 clevermous 2209
        popad
2210
        mov     eax, ERROR_ACCESS_DENIED
2211
        xor     ebx, ebx
2212
        ret
6468 pathoswith 2213
 
2214
@@: ; delete FAT chain
2288 clevermous 2215
        push    edi
2216
        xor     eax, eax
2217
        mov     dword [edi+28], eax     ; zero size
2218
        xor     ecx, ecx
2219
        mov     eax, [edi+20-2]
2220
        mov     ax, [edi+26]
2221
        mov     word [edi+20], cx
2222
        mov     word [edi+26], cx
2223
        test    eax, eax
2224
        jz      .done1
2225
@@:
2643 clevermous 2226
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2227
        jae     .done1
2228
        push    edx
2229
        xor     edx, edx
2230
        call    set_FAT
2231
        mov     eax, edx
2232
        pop     edx
2643 clevermous 2233
        jc      .done1
2288 clevermous 2234
        inc     ecx
2235
        jmp     @b
6468 pathoswith 2236
 
2237
.short_name_found:
2238
        pop     ecx edi esi
2239
        call    fat_next_short_name
2240
        jnc     .test_short_name_loop
2241
.disk_full:
2242
        add     esp, 12+36
2243
        call    fat_unlock
2244
        popa
2245
        mov     eax, ERROR_DISK_FULL
2246
        xor     ebx, ebx
2247
        ret
2248
 
2249
.notfound:  ; generate short name
2288 clevermous 2250
        call    fat_name_is_legal
2251
        jc      @f
2643 clevermous 2252
        add     esp, 36
2253
        call    fat_unlock
2288 clevermous 2254
        popad
2255
        mov     eax, ERROR_FILE_NOT_FOUND
2256
        xor     ebx, ebx
2257
        ret
6468 pathoswith 2258
 
2288 clevermous 2259
@@:
2260
        sub     esp, 12
2261
        mov     edi, esp
2262
        call    fat_gen_short_name
2263
.test_short_name_loop:
2264
        push    esi edi ecx
2265
        mov     esi, edi
2266
        lea     eax, [esp+12+12+8]
2643 clevermous 2267
        mov     edx, [eax+24]
2268
        mov     [eax], edx
2288 clevermous 2269
        and     dword [eax+4], 0
2270
        call    dword [eax-4]
2271
        jc      .found
2272
.test_short_name_entry:
2273
        cmp     byte [edi+11], 0xF
2274
        jz      .test_short_name_cont
2275
        mov     ecx, 11
2276
        push    esi edi
2277
        repz cmpsb
2278
        pop     edi esi
2279
        jz      .short_name_found
2280
.test_short_name_cont:
2281
        lea     eax, [esp+12+12+8]
2282
        call    dword [eax-8]
2283
        jnc     .test_short_name_entry
2284
.found:
2285
        pop     ecx edi esi
2286
; now find space in directory
2287
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
2288
        mov     al, '~'
2289
        push    ecx edi
2290
        mov     ecx, 8
2291
        repnz scasb
3598 clevermous 2292
        movi    eax, 1     ; 1 entry
2288 clevermous 2293
        jnz     .notilde
2294
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
6471 pathoswith 2295
        xor     ecx, ecx
2296
        push    esi
2288 clevermous 2297
@@:
6471 pathoswith 2298
        call    utf8to16
2299
        inc     ecx
2300
        test    ax, ax
2301
        jnz     @b
2302
        pop     esi
2303
        mov     eax, ecx
2304
        add     eax, 12+13-1
2288 clevermous 2305
        mov     ecx, 13
2306
        cdq
2307
        div     ecx
2308
.notilde:
2309
        push    -1
2310
        push    -1
2311
        push    -1
2312
; find  successive entries in directory
2313
        xor     ecx, ecx
2314
        push    eax
2315
        lea     eax, [esp+16+8+12+8]
2643 clevermous 2316
        mov     edx, [eax+24]
2317
        mov     [eax], edx
2288 clevermous 2318
        and     dword [eax+4], 0
2319
        call    dword [eax-4]
2320
        pop     eax
2321
        jnc     .scan_dir
2322
.fsfrfe3:
2643 clevermous 2323
        add     esp, 12+8+12+36
2324
        call    fat_unlock
2288 clevermous 2325
        popad
2643 clevermous 2326
        mov     eax, ERROR_DEVICE
2288 clevermous 2327
        xor     ebx, ebx
2328
        ret
6468 pathoswith 2329
 
2288 clevermous 2330
.scan_dir:
2331
        cmp     byte [edi], 0
2332
        jz      .free
2333
        cmp     byte [edi], 0xE5
2334
        jz      .free
2335
        xor     ecx, ecx
2336
.scan_cont:
2337
        push    eax
2338
        lea     eax, [esp+16+8+12+8]
2339
        call    dword [eax-8]
2643 clevermous 2340
        mov     edx, eax
2288 clevermous 2341
        pop     eax
2342
        jnc     .scan_dir
2643 clevermous 2343
        cmp     edx, ERROR_DEVICE
2344
        jz      .fsfrfe3
2288 clevermous 2345
        push    eax
2346
        lea     eax, [esp+16+8+12+8]
2347
        call    dword [eax+20]          ; extend directory
2348
        pop     eax
2349
        jnc     .scan_dir
2643 clevermous 2350
        add     esp, 12+8+12+36
2351
        call    fat_unlock
2288 clevermous 2352
        popad
2353
        mov     eax, ERROR_DISK_FULL
2354
        xor     ebx, ebx
2355
        ret
6468 pathoswith 2356
 
2288 clevermous 2357
.free:
2358
        test    ecx, ecx
2359
        jnz     @f
2360
        mov     [esp], edi
2361
        mov     ecx, [esp+12+8+12+8]
2362
        mov     [esp+4], ecx
2363
        mov     ecx, [esp+12+8+12+12]
2364
        mov     [esp+8], ecx
2365
        xor     ecx, ecx
2366
@@:
2367
        inc     ecx
2368
        cmp     ecx, eax
2369
        jb      .scan_cont
2370
; found!
2643 clevermous 2371
        push    esi ecx
2372
; If creating a directory, allocate one data cluster now and fail immediately
2373
; if this is impossible. This prevents from creating an invalid directory entry
2374
; on a full disk.
2375
; yup, the argument is quite non-intuitive... but what should I do if
2376
; the entire function uses such arguments? BTW, it refers to al from pushad,
6468 pathoswith 2377
; which in turn is filled with 0 in fat_CreateFile and 1 in fat_CreateFolder.
2643 clevermous 2378
        cmp     byte [esp+8+12+8+12+36+28], 0
2379
        jz      .no.preallocate.folder.data
2380
        call    get_free_FAT
2381
        jnc     @f
2382
        add     esp, 8+12+8
2383
        jmp     .disk_full
6468 pathoswith 2384
 
2643 clevermous 2385
@@:
6471 pathoswith 2386
        mov     [esp+8+12+8+12+36+20], eax  ; store the cluster somewhere
6468 pathoswith 2387
.no.preallocate.folder.data:    ; calculate name checksum
2288 clevermous 2388
        mov     esi, [esp+8+12]
2389
        mov     ecx, 11
2390
        xor     eax, eax
2391
@@:
2392
        ror     al, 1
2393
        add     al, [esi]
2394
        inc     esi
2395
        loop    @b
6471 pathoswith 2396
        pop     ecx esi edi
2288 clevermous 2397
        pop     dword [esp+8+12+12]
2398
        pop     dword [esp+8+12+12]
2399
; edi points to first entry in free chunk
2400
        dec     ecx
2401
        jz      .nolfn
6471 pathoswith 2402
        push    esi eax
2288 clevermous 2403
        lea     eax, [esp+8+8+12+8]
6471 pathoswith 2404
        call    dword [eax+8]   ; begin write
2288 clevermous 2405
        mov     al, 40h
2406
.writelfn:
2407
        or      al, cl
6471 pathoswith 2408
        stosb
2288 clevermous 2409
        mov     esi, [esp+4]
2410
        push    ecx
2411
        dec     ecx
6471 pathoswith 2412
        jz      @f
2288 clevermous 2413
        imul    ecx, 13
6471 pathoswith 2414
.scroll:
2415
        call    utf8to16
2416
        loop    .scroll
2417
@@:
2288 clevermous 2418
        mov     cl, 5
4273 clevermous 2419
        call    fat_read_symbols
2288 clevermous 2420
        mov     ax, 0xF
2421
        stosw
2422
        mov     al, [esp+4]
2423
        stosb
2424
        mov     cl, 6
4273 clevermous 2425
        call    fat_read_symbols
2288 clevermous 2426
        xor     eax, eax
2427
        stosw
2428
        mov     cl, 2
4273 clevermous 2429
        call    fat_read_symbols
2288 clevermous 2430
        pop     ecx
2431
        lea     eax, [esp+8+8+12+8]
6471 pathoswith 2432
        call    dword [eax+12]  ; next write
2288 clevermous 2433
        xor     eax, eax
2434
        loop    .writelfn
6471 pathoswith 2435
        pop     eax esi
2288 clevermous 2436
.nolfn:
2437
        xchg    esi, [esp]
2438
        mov     ecx, 11
2439
        rep movsb
2440
        mov     word [edi], 20h         ; attributes
2441
        sub     edi, 11
2442
        pop     esi ecx
2443
        add     esp, 12
2444
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
2445
        call    get_time_for_file
2446
        mov     [edi+14], ax            ; creation time
2447
        mov     [edi+22], ax            ; last write time
2448
        call    get_date_for_file
2449
        mov     [edi+16], ax            ; creation date
2450
        mov     [edi+24], ax            ; last write date
2451
        mov     [edi+18], ax            ; last access date
2452
        xor     ecx, ecx
2453
        mov     word [edi+20], cx       ; high word of cluster
2454
        mov     word [edi+26], cx       ; low word of cluster - to be filled
2455
        mov     dword [edi+28], ecx     ; file size - to be filled
2643 clevermous 2456
        cmp     byte [esp+36+28], cl
2288 clevermous 2457
        jz      .doit
2458
; create directory
2459
        mov     byte [edi+11], 10h      ; attributes: folder
2643 clevermous 2460
        mov     esi, edi
2288 clevermous 2461
        lea     eax, [esp+8]
2462
        call    dword [eax+16]  ; flush directory
2643 clevermous 2463
        mov     eax, [esp+36+20] ; extract saved cluster
2464
        mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
2288 clevermous 2465
        push    ecx
2643 clevermous 2466
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2467
        shl     ecx, 9
2643 clevermous 2468
        push    ecx
2469
        push    edi
2288 clevermous 2470
        jmp     .doit2
6468 pathoswith 2471
 
2472
.done1:
2473
        pop     edi
2474
        call    get_time_for_file
2475
        mov     [edi+22], ax
2476
        call    get_date_for_file
2477
        mov     [edi+24], ax
2478
        mov     [edi+18], ax
2479
        or      byte [edi+11], 20h      ; set 'archive' attribute
2288 clevermous 2480
.doit:
2643 clevermous 2481
        mov     esi, [esp+36+20]
2288 clevermous 2482
        lea     eax, [esp+8]
2483
        call    dword [eax+16]  ; flush directory
2484
        push    ecx
2643 clevermous 2485
        mov     ecx, [esp+4+36+24]
2288 clevermous 2486
        push    ecx
2487
        push    edi
2488
        test    ecx, ecx
2489
        jz      .done
2490
        call    get_free_FAT
2491
        jc      .diskfull
2643 clevermous 2492
.doit2:
2288 clevermous 2493
        push    eax
2494
        mov     [edi+26], ax
2495
        shr     eax, 16
2496
        mov     [edi+20], ax
2497
        lea     eax, [esp+16+8]
2498
        call    dword [eax+16]  ; flush directory
2499
        pop     eax
2500
        push    edx
2643 clevermous 2501
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2502
        call    set_FAT
2503
        pop     edx
2504
.write_cluster:
2505
        push    eax
2506
        dec     eax
2507
        dec     eax
2643 clevermous 2508
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2509
        add     eax, [ebp+FAT.DATA_START]
2510
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2511
.write_sector:
2643 clevermous 2512
        cmp     byte [esp+20+36+28], 0
2288 clevermous 2513
        jnz     .writedir
2514
        mov     ecx, 512
2643 clevermous 2515
        cmp     dword [esp+12], ecx
2288 clevermous 2516
        jb      .writeshort
2517
; we can write directly from given buffer
2518
        mov     ebx, esi
2519
        add     esi, ecx
2520
        jmp     .writecommon
6468 pathoswith 2521
 
2288 clevermous 2522
.writeshort:
2643 clevermous 2523
        mov     ecx, [esp+12]
2288 clevermous 2524
        push    ecx
2643 clevermous 2525
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 2526
        mov     ebx, edi
2527
        rep movsb
2528
.writedircont:
2643 clevermous 2529
        lea     ecx, [ebp+FAT.buffer+0x200]
2288 clevermous 2530
        sub     ecx, edi
2531
        push    eax
2532
        xor     eax, eax
2533
        rep stosb
2534
        pop     eax
2535
        pop     ecx
2536
.writecommon:
2643 clevermous 2537
        push    eax
2538
        call    fs_write32_app
2539
        test    eax, eax
2540
        pop     eax
2288 clevermous 2541
        jnz     .writeerr
2542
        inc     eax
2643 clevermous 2543
        sub     dword [esp+12], ecx
2288 clevermous 2544
        jz      .writedone
2643 clevermous 2545
        dec     dword [esp]
2288 clevermous 2546
        jnz     .write_sector
2643 clevermous 2547
        pop     eax
2288 clevermous 2548
; allocate new cluster
2549
        pop     eax
2550
        mov     ecx, eax
2551
        call    get_free_FAT
2552
        jc      .diskfull
2553
        push    edx
2643 clevermous 2554
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2555
        call    set_FAT
2556
        xchg    eax, ecx
2557
        mov     edx, ecx
2558
        call    set_FAT
2559
        pop     edx
2560
        xchg    eax, ecx
2561
        jmp     .write_cluster
6468 pathoswith 2562
 
2288 clevermous 2563
.diskfull:
2564
        mov     eax, ERROR_DISK_FULL
2565
        jmp     .ret
6468 pathoswith 2566
 
2288 clevermous 2567
.writeerr:
2643 clevermous 2568
        pop     eax eax
2288 clevermous 2569
        sub     esi, ecx
2643 clevermous 2570
        mov     eax, ERROR_DEVICE
2288 clevermous 2571
        jmp     .ret
6468 pathoswith 2572
 
2288 clevermous 2573
.writedone:
2643 clevermous 2574
        pop     eax eax
2288 clevermous 2575
.done:
2576
        xor     eax, eax
2577
.ret:
2578
        pop     edi ecx
2643 clevermous 2579
        sub     esi, [esp+4+36+20]
2580
        mov     [esp+4+36+28], eax
2581
        mov     [esp+4+36+16], esi
2582
        lea     eax, [esp+12]
2288 clevermous 2583
        call    dword [eax+8]
2643 clevermous 2584
        mov     [edi+28], esi
2288 clevermous 2585
        call    dword [eax+16]
2643 clevermous 2586
        mov     [esp+36+16], ebx
2587
        lea     eax, [esi+511]
2288 clevermous 2588
        shr     eax, 9
2643 clevermous 2589
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2590
        lea     eax, [eax+ecx-1]
2591
        xor     edx, edx
2592
        div     ecx
2643 clevermous 2593
        pop     ecx
2288 clevermous 2594
        sub     ecx, eax
2595
        call    add_disk_free_space
2643 clevermous 2596
        add     esp, 36
2288 clevermous 2597
        call    update_disk
2643 clevermous 2598
        call    fat_unlock
2288 clevermous 2599
        popad
2600
        ret
6468 pathoswith 2601
 
2288 clevermous 2602
.writedir:
2603
        push    512
2643 clevermous 2604
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 2605
        mov     ebx, edi
2643 clevermous 2606
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2607
        shl     ecx, 9
2643 clevermous 2608
        cmp     ecx, [esp+16]
2288 clevermous 2609
        jnz     .writedircont
2643 clevermous 2610
        dec     dword [esp+20]
2288 clevermous 2611
        push    esi
2612
        mov     ecx, 32/4
2613
        rep movsd
2614
        pop     esi
2615
        mov     dword [edi-32], '.   '
2616
        mov     dword [edi-32+4], '    '
2617
        mov     dword [edi-32+8], '    '
2618
        mov     byte [edi-32+11], 10h
2619
        push    esi
2620
        mov     ecx, 32/4
2621
        rep movsd
2622
        pop     esi
2623
        mov     dword [edi-32], '..  '
2624
        mov     dword [edi-32+4], '    '
2625
        mov     dword [edi-32+8], '    '
2626
        mov     byte [edi-32+11], 10h
2643 clevermous 2627
        mov     ecx, [esp+20+36]
2628
        cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
2288 clevermous 2629
        jnz     @f
2630
        xor     ecx, ecx
2631
@@:
2632
        mov     word [edi-32+26], cx
2633
        shr     ecx, 16
2634
        mov     [edi-32+20], cx
2635
        jmp     .writedircont
2636
 
6471 pathoswith 2637
@@:
2638
        or      eax, -1
2639
        rep stosw
4273 clevermous 2640
        ret
2641
 
2642
fat_read_symbols:
6471 pathoswith 2643
        test    esi, esi
2644
        jz      @b
2645
        call    utf8to16
4273 clevermous 2646
        stosw
6471 pathoswith 2647
        test    ax, ax
2648
        jnz     @f
2649
        xor     esi, esi
2650
@@:
4273 clevermous 2651
        loop    fat_read_symbols
2652
        ret
2653
 
2643 clevermous 2654
;----------------------------------------------------------------
2655
fat_Write:
2656
        call    fat_lock
2657
        push    edi
6468 pathoswith 2658
        call    hd_find_lfn
6845 pathoswith 2659
        jc      .error
2643 clevermous 2660
        cmp     dword [ebx+8], 0
6845 pathoswith 2661
        jnz     .eof    ; FAT does not support files larger than 4GB
2643 clevermous 2662
        mov     ecx, [ebx+12]
2663
        mov     edx, [ebx+16]
2664
        mov     ebx, [ebx+4]
2288 clevermous 2665
; now edi points to direntry, ebx=start byte to write,
2666
; ecx=number of bytes to write, edx=data pointer
2667
; extend file if needed
2668
        add     ecx, ebx
2669
        jc      .eof    ; FAT does not support files larger than 4GB
2643 clevermous 2670
        push    edx
2288 clevermous 2671
        push    eax     ; save directory sector
2672
        push    0       ; return value=0
2673
        call    get_time_for_file
2674
        mov     [edi+22], ax            ; last write time
2675
        call    get_date_for_file
2676
        mov     [edi+24], ax            ; last write date
2677
        mov     [edi+18], ax            ; last access date
2678
        push    dword [edi+28]          ; save current file size
2679
        cmp     ecx, [edi+28]
2680
        jbe     .length_ok
2681
        cmp     ecx, ebx
2682
        jz      .length_ok
2683
        call    hd_extend_file
2684
        jnc     .length_ok
2685
        mov     [esp+4], eax
2686
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
2687
; First two cases are fatal errors, in third case we may write some data
2688
        cmp     al, ERROR_DISK_FULL
6845 pathoswith 2689
        jnz     @f
2288 clevermous 2690
; correct number of bytes to write
2691
        mov     ecx, [edi+28]
2692
        cmp     ecx, ebx
2693
        ja      .length_ok
2643 clevermous 2694
        push    0
2288 clevermous 2695
.ret:
2643 clevermous 2696
        pop     eax
2697
        sub     edx, [esp+12]
2698
        mov     ebx, edx        ; ebx=number of written bytes
2288 clevermous 2699
        call    update_disk
2643 clevermous 2700
        test    eax, eax
2288 clevermous 2701
        jz      @f
2643 clevermous 2702
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 2703
@@:
6845 pathoswith 2704
        pop     eax eax ecx edx
2705
.error:
2706
        push    eax
2707
@@:
2643 clevermous 2708
        call    fat_unlock
6845 pathoswith 2709
        pop     eax edi
2710
        ret
2711
 
2712
.eof:
2713
        push    ERROR_END_OF_FILE
6846 pathoswith 2714
        xor     ebx, ebx
6845 pathoswith 2715
        jmp     @b
2716
 
2717
.device_err2:
2643 clevermous 2718
        pop     ecx
6845 pathoswith 2719
.device_err:
2720
        mov     byte [esp+8], ERROR_DEVICE
2721
        jmp     .ret
2722
 
2723
.fat_err:
2724
        mov     byte [esp+8], ERROR_FS_FAIL
2725
        jmp     .ret
2726
 
2288 clevermous 2727
.length_ok:
2728
        mov     esi, [edi+28]
2729
        mov     eax, [edi+20-2]
2730
        mov     ax, [edi+26]
2731
        mov     edi, eax        ; edi=current cluster
2643 clevermous 2732
        push    0               ; current sector in cluster
2288 clevermous 2733
; save directory
2643 clevermous 2734
        mov     eax, [esp+12]
2288 clevermous 2735
        push    ebx
2643 clevermous 2736
        lea     ebx, [ebp+FAT.buffer]
2737
        call    fs_write32_sys
2288 clevermous 2738
        pop     ebx
2643 clevermous 2739
        test    eax, eax
6845 pathoswith 2740
        jnz     .device_err
2288 clevermous 2741
; now ebx=start pos, ecx=end pos, both lie inside file
2742
        sub     ecx, ebx
2743
        jz      .ret
2744
.write_loop:
2745
; skip unmodified sectors
2643 clevermous 2746
        cmp     dword [esp+4], 0x200
2288 clevermous 2747
        jb      .modify
2748
        sub     ebx, 0x200
2749
        jae     .skip
2750
        add     ebx, 0x200
2751
.modify:
2752
; get length of data in current sector
2753
        push    ecx
2754
        sub     ebx, 0x200
2755
        jb      .hasdata
2756
        neg     ebx
2757
        xor     ecx, ecx
2758
        jmp     @f
2759
.hasdata:
2760
        neg     ebx
2761
        cmp     ecx, ebx
2762
        jbe     @f
2763
        mov     ecx, ebx
2764
@@:
2765
; get current sector number
2766
        mov     eax, edi
2767
        dec     eax
2768
        dec     eax
2643 clevermous 2769
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2770
        add     eax, [ebp+FAT.DATA_START]
2771
        add     eax, [esp+4]
2288 clevermous 2772
; load sector if needed
2643 clevermous 2773
        cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
2288 clevermous 2774
        jz      .noread
2775
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
2776
        jz      .noread
2777
        cmp     ecx, esi        ; (same for the last sector)
2778
        jz      .noread
2643 clevermous 2779
        push    eax ebx
2780
        lea     ebx, [ebp+FAT.buffer]
2781
        call    fs_read32_app
2782
        test    eax, eax
2783
        pop     ebx eax
6845 pathoswith 2784
        jnz     .device_err2
2288 clevermous 2785
.noread:
2786
; zero uninitialized data if file was extended (because hd_extend_file does not this)
2787
        push    eax ecx edi
2788
        xor     eax, eax
2789
        mov     ecx, 0x200
2643 clevermous 2790
        sub     ecx, [esp+8+12]
2288 clevermous 2791
        jbe     @f
2643 clevermous 2792
        lea     edi, [ebp+FAT.buffer]
2793
        add     edi, [esp+8+12]
2288 clevermous 2794
        rep stosb
2795
@@:
2796
; zero uninitialized data in the last sector
2797
        mov     ecx, 0x200
2798
        sub     ecx, esi
2799
        jbe     @f
2643 clevermous 2800
        lea     edi, [ebp+FAT.buffer+esi]
2288 clevermous 2801
        rep stosb
2802
@@:
2803
        pop     edi ecx
2804
; copy new data
2805
        mov     eax, edx
2806
        neg     ebx
2807
        jecxz   @f
2643 clevermous 2808
        lea     ebx, [ebp+FAT.buffer+0x200+ebx]
2288 clevermous 2809
        call    memmove
2810
        xor     ebx, ebx
2811
@@:
2812
        pop     eax
2813
; save sector
2814
        push    ebx
2643 clevermous 2815
        lea     ebx, [ebp+FAT.buffer]
2816
        call    fs_write32_app
2288 clevermous 2817
        pop     ebx
2643 clevermous 2818
        test    eax, eax
2288 clevermous 2819
        jnz     .device_err2
2820
        add     edx, ecx
2821
        sub     [esp], ecx
2822
        pop     ecx
2823
        jz      .ret
2824
.skip:
2825
; next sector
2643 clevermous 2826
        pop     eax
2827
        inc     eax
2828
        push    eax
2829
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2830
        jb      @f
2643 clevermous 2831
        and     dword [esp], 0
2288 clevermous 2832
        mov     eax, edi
2833
        call    get_FAT
2834
        mov     edi, eax
2643 clevermous 2835
        jc      .device_err
2836
        cmp     edi, 2
2837
        jb      .fat_err
2838
        cmp     edi, [ebp+FAT.fatRESERVED]
2839
        jae     .fat_err
2288 clevermous 2840
@@:
2841
        sub     esi, 0x200
2842
        jae     @f
2843
        xor     esi, esi
2844
@@:
2643 clevermous 2845
        sub     dword [esp+4], 0x200
2288 clevermous 2846
        jae     @f
2643 clevermous 2847
        and     dword [esp+4], 0
2288 clevermous 2848
@@:
2849
        jmp     .write_loop
2850
 
2851
hd_extend_file.zero_size:
2852
        xor     eax, eax
2853
        jmp     hd_extend_file.start_extend
2854
 
2855
; extends file on hd to given size (new data area is undefined)
2856
; in: edi->direntry, ecx=new size
2857
; out: CF=0 => OK, eax=0
6468 pathoswith 2858
;      CF=1 => error, eax=code (ERROR_FS_FAIL or ERROR_DISK_FULL or ERROR_DEVICE)
2288 clevermous 2859
hd_extend_file:
2643 clevermous 2860
        push    esi
2861
        mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
2862
        imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
2288 clevermous 2863
        push    ecx
2864
; find the last cluster of file
2865
        mov     eax, [edi+20-2]
2866
        mov     ax, [edi+26]
2867
        mov     ecx, [edi+28]
2868
        jecxz   .zero_size
2869
.last_loop:
2643 clevermous 2870
        sub     ecx, esi
2288 clevermous 2871
        jbe     .last_found
2872
        call    get_FAT
2643 clevermous 2873
        jnc     @f
2288 clevermous 2874
.device_err:
2875
        pop     ecx
2876
.device_err2:
2643 clevermous 2877
        pop     esi
2878
        push    ERROR_DEVICE
2288 clevermous 2879
.ret_err:
2880
        pop     eax
2881
        stc
2882
        ret
2883
@@:
2884
        cmp     eax, 2
2885
        jb      .fat_err
2643 clevermous 2886
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2887
        jb      .last_loop
2888
.fat_err:
2643 clevermous 2889
        pop     ecx esi
6468 pathoswith 2890
        push    ERROR_FS_FAIL
2288 clevermous 2891
        jmp     .ret_err
2892
.last_found:
2893
        push    eax
2894
        call    get_FAT
2643 clevermous 2895
        jnc     @f
2288 clevermous 2896
        pop     eax
2897
        jmp     .device_err
2898
@@:
2643 clevermous 2899
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2900
        pop     eax
2901
        jb      .fat_err
2902
; set length to full number of clusters
2903
        sub     [edi+28], ecx
2904
.start_extend:
2905
        pop     ecx
2906
; now do extend
2907
        push    edx
2908
        mov     edx, 2          ; start scan from cluster 2
2909
.extend_loop:
2910
        cmp     [edi+28], ecx
2911
        jae     .extend_done
2912
; add new cluster
2913
        push    eax
2914
        call    get_free_FAT
2915
        jc      .disk_full
2643 clevermous 2916
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2917
        call    set_FAT
2918
        mov     edx, eax
2919
        pop     eax
2920
        test    eax, eax
2921
        jz      .first_cluster
2922
        push    edx
2923
        call    set_FAT
2924
        pop     edx
2925
        jmp     @f
2926
.first_cluster:
2927
        ror     edx, 16
2928
        mov     [edi+20], dx
2929
        ror     edx, 16
2930
        mov     [edi+26], dx
2931
@@:
2932
        push    ecx
2933
        mov     ecx, -1
2934
        call    add_disk_free_space
2935
        pop     ecx
2936
        mov     eax, edx
2643 clevermous 2937
        add     [edi+28], esi
2288 clevermous 2938
        jmp     .extend_loop
2939
.extend_done:
2940
        mov     [edi+28], ecx
2643 clevermous 2941
        pop     edx esi
2288 clevermous 2942
        xor     eax, eax        ; CF=0
2943
        ret
2944
.device_err3:
2945
        pop     edx
2946
        jmp     .device_err2
2947
.disk_full:
2643 clevermous 2948
        pop     eax edx esi
3598 clevermous 2949
        movi    eax, ERROR_DISK_FULL
2288 clevermous 2950
        stc
2951
        ret
2952
 
4273 clevermous 2953
fat_update_datetime:
2954
        call    get_time_for_file
2955
        mov     [edi+22], ax            ; last write time
2956
        call    get_date_for_file
2957
        mov     [edi+24], ax            ; last write date
2958
        mov     [edi+18], ax            ; last access date
2959
        ret
2960
 
2288 clevermous 2961
;----------------------------------------------------------------
2643 clevermous 2962
fat_SetFileEnd:
2963
        call    fat_lock
2964
        push    edi
6468 pathoswith 2965
        call    hd_find_lfn
6845 pathoswith 2966
        jc      .reteax
2288 clevermous 2967
; must not be directory
2968
        test    byte [edi+11], 10h
2643 clevermous 2969
        jnz     .access_denied
2288 clevermous 2970
; file size must not exceed 4 Gb
2643 clevermous 2971
        cmp     dword [ebx+8], 0
6845 pathoswith 2972
        jnz     .endOfFile
2288 clevermous 2973
        push    eax     ; save directory sector
2974
; set file modification date/time to current
2975
        call    fat_update_datetime
2643 clevermous 2976
        mov     eax, [ebx+4]
2288 clevermous 2977
        cmp     eax, [edi+28]
2978
        jb      .truncate
2979
        ja      .expand
2980
        pop     eax
2643 clevermous 2981
        lea     ebx, [ebp+FAT.buffer]
2982
        call    fs_write32_sys
2983
        test    eax, eax
6845 pathoswith 2984
        jnz     .errorDevice
2985
        push    0
2986
        jmp     .ret
2987
 
2988
.access_denied:
2989
        push    ERROR_ACCESS_DENIED
2990
        jmp     .ret
2991
 
2992
.endOfFile:
2993
        push    ERROR_END_OF_FILE
2994
        jmp     .ret
2995
 
2996
.errorDevice:
2643 clevermous 2997
        push    ERROR_DEVICE
2998
        jmp     .ret
6845 pathoswith 2999
 
2288 clevermous 3000
.expand:
3001
        push    ebx ebp ecx
3002
        push    dword [edi+28]  ; save old size
3003
        mov     ecx, eax
3004
        call    hd_extend_file
3005
        push    eax             ; return code
3006
        jnc     .expand_ok
3007
        cmp     al, ERROR_DISK_FULL
6845 pathoswith 3008
        jnz     .pop_ret
3009
.expand_ok: ; save directory
2288 clevermous 3010
        mov     eax, [edi+28]
3011
        xchg    eax, [esp+20]
2643 clevermous 3012
        lea     ebx, [ebp+FAT.buffer]
3013
        call    fs_write32_sys
3014
        test    eax, eax
6850 pathoswith 3015
        jnz     .pop_ret11
3016
        mov     eax, [esp+20]
3017
        sub     eax, [esp+4]
3018
        cmp     eax, 1000001h
3019
        jnc     .pop_ret
2288 clevermous 3020
        mov     eax, [edi+20-2]
3021
        mov     ax, [edi+26]
3022
        mov     edi, eax
2643 clevermous 3023
        test    edi, edi
3024
        jz      .pop_ret
2288 clevermous 3025
; now zero new data
2643 clevermous 3026
        push    0
3027
; edi=current cluster, [esp]=sector in cluster
3028
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
2288 clevermous 3029
.zero_loop:
2643 clevermous 3030
        cmp     edi, 2
3031
        jb      .error_fat
3032
        cmp     edi, [ebp+FAT.fatRESERVED]
3033
        jae     .error_fat
3034
        sub     dword [esp+8], 0x200
2288 clevermous 3035
        jae     .next_cluster
3036
        lea     eax, [edi-2]
2643 clevermous 3037
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3038
        add     eax, [ebp+FAT.DATA_START]
3039
        add     eax, [esp]
3040
        cmp     dword [esp+8], -0x200
2288 clevermous 3041
        jz      .noread
2643 clevermous 3042
        push    eax
3043
        lea     ebx, [ebp+FAT.buffer]
3044
        call    fs_read32_app
3045
        test    eax, eax
3046
        pop     eax
2288 clevermous 3047
        jnz     .err_next
3048
.noread:
2643 clevermous 3049
        mov     ecx, [esp+8]
2288 clevermous 3050
        neg     ecx
3051
        push    edi
2643 clevermous 3052
        lea     edi, [ebp+FAT.buffer+0x200]
3053
        add     edi, [esp+12]
2288 clevermous 3054
        push    eax
3055
        xor     eax, eax
2643 clevermous 3056
        mov     [esp+16], eax
2288 clevermous 3057
        rep stosb
3058
        pop     eax
3059
        pop     edi
2643 clevermous 3060
        call    fs_write32_app
3061
        test    eax, eax
2288 clevermous 3062
        jz      .next_cluster
3063
.err_next:
2643 clevermous 3064
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 3065
.next_cluster:
2643 clevermous 3066
        pop     eax
2288 clevermous 3067
        sub     dword [esp+20], 0x200
3068
        jbe     .pop_ret
2643 clevermous 3069
        inc     eax
3070
        push    eax
3071
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 3072
        jb      .zero_loop
2643 clevermous 3073
        and     dword [esp], 0
2288 clevermous 3074
        mov     eax, edi
3075
        call    get_FAT
3076
        mov     edi, eax
2643 clevermous 3077
        jnc     .zero_loop
3078
        pop     eax
6845 pathoswith 3079
.pop_ret11:
3080
        mov     byte [esp], ERROR_DEVICE
3081
.pop_ret:
3082
        call    update_disk
3083
        pop     eax ecx ecx ebp ebx ecx
3084
.reteax:
3085
        push    eax
3086
.ret:
3087
        call    fat_unlock
3088
        pop     eax edi
3089
        ret
3090
 
3091
.error_fat:
3092
        pop     eax
3093
        mov     byte [esp], ERROR_FS_FAIL
3094
        jmp     .pop_ret
3095
 
3096
.error_fat2:
3097
        pop     eax ecx eax
3098
        call    update_disk
3099
        push    ERROR_FS_FAIL
3100
        jmp     .ret
3101
 
2288 clevermous 3102
.truncate:
3103
        mov     [edi+28], eax
3104
        push    ecx
3105
        mov     ecx, [edi+20-2]
3106
        mov     cx, [edi+26]
3107
        push    eax
3108
        test    eax, eax
3109
        jz      .zero_size
6845 pathoswith 3110
@@: ; find new last cluster
2643 clevermous 3111
        cmp     ecx, 2
3112
        jb      .error_fat2
3113
        cmp     ecx, [ebp+FAT.fatRESERVED]
3114
        jae     .error_fat2
3115
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 3116
        shl     eax, 9
3117
        sub     [esp], eax
3118
        jbe     @f
3119
        mov     eax, ecx
3120
        call    get_FAT
3121
        mov     ecx, eax
2643 clevermous 3122
        jnc     @b
2288 clevermous 3123
.device_err3:
6845 pathoswith 3124
        pop     eax ecx eax
2643 clevermous 3125
        call    update_disk
6845 pathoswith 3126
        push    ERROR_DEVICE
3127
        jmp     .ret
3128
 
2288 clevermous 3129
@@:
3130
; we will zero data at the end of last sector - remember it
3131
        push    ecx
3132
; terminate FAT chain
3133
        push    edx
3134
        mov     eax, ecx
2643 clevermous 3135
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 3136
        call    set_FAT
3137
        mov     eax, edx
3138
        pop     edx
2643 clevermous 3139
        jnc     @f
2288 clevermous 3140
.device_err4:
3141
        pop     ecx
3142
        jmp     .device_err3
6845 pathoswith 3143
 
2288 clevermous 3144
.zero_size:
3145
        and     word [edi+20], 0
3146
        and     word [edi+26], 0
3147
        push    0
3148
        mov     eax, ecx
3149
@@:
3150
; delete FAT chain
3151
        call    clear_cluster_chain
2643 clevermous 3152
        jc      .device_err4
2288 clevermous 3153
; save directory
3154
        mov     eax, [esp+12]
3155
        push    ebx
2643 clevermous 3156
        lea     ebx, [ebp+FAT.buffer]
3157
        call    fs_write32_sys
2288 clevermous 3158
        pop     ebx
2643 clevermous 3159
        test    eax, eax
2288 clevermous 3160
        jnz     .device_err4
3161
; zero last sector, ignore errors
3162
        pop     ecx
3163
        pop     eax
3164
        dec     ecx
2643 clevermous 3165
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
3166
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 3167
        push    eax
3168
        sar     eax, 9
3169
        add     ecx, eax
3170
        pop     eax
3171
        and     eax, 0x1FF
3172
        jz      .truncate_done
3173
        push    ebx eax
3174
        mov     eax, ecx
2643 clevermous 3175
        lea     ebx, [ebp+FAT.buffer]
3176
        call    fs_read32_app
2288 clevermous 3177
        pop     eax
2643 clevermous 3178
        lea     edi, [ebp+FAT.buffer+eax]
2288 clevermous 3179
        push    ecx
3180
        mov     ecx, 0x200
3181
        sub     ecx, eax
3182
        xor     eax, eax
3183
        rep stosb
3184
        pop     eax
2643 clevermous 3185
        call    fs_write32_app
2288 clevermous 3186
        pop     ebx
3187
.truncate_done:
3188
        pop     ecx eax edi
3189
        call    update_disk
2643 clevermous 3190
        call    fat_unlock
2288 clevermous 3191
        xor     eax, eax
3192
        ret
3193
 
2643 clevermous 3194
;----------------------------------------------------------------
3195
fat_GetFileInfo:
2288 clevermous 3196
        cmp     byte [esi], 0
3197
        jnz     @f
3198
        mov     eax, 2
3199
        ret
3200
@@:
3201
        push    edi
2643 clevermous 3202
        call    fat_lock
6468 pathoswith 3203
        call    hd_find_lfn
2643 clevermous 3204
        jc      .error
3205
        push    ebp
3206
        xor     ebp, ebp
3207
        mov     esi, [ebx+16]
3208
        mov     dword [esi+4], ebp
3209
        call    fat_entry_to_bdfe2
3210
        pop     ebp
3211
        call    fat_unlock
3212
        xor     eax, eax
2288 clevermous 3213
        pop     edi
3214
        ret
2643 clevermous 3215
.error:
3216
        push    eax
3217
        call    fat_unlock
3218
        pop     eax
3219
        pop     edi
3220
        ret
2288 clevermous 3221
 
2643 clevermous 3222
;----------------------------------------------------------------
3223
fat_SetFileInfo:
2288 clevermous 3224
        push    edi
2643 clevermous 3225
        call    fat_lock
6468 pathoswith 3226
        call    hd_find_lfn
2643 clevermous 3227
        jc      .error
2288 clevermous 3228
        push    eax
2643 clevermous 3229
        mov     edx, [ebx+16]
2288 clevermous 3230
        call    bdfe_to_fat_entry
3231
        pop     eax
2643 clevermous 3232
        lea     ebx, [ebp+FAT.buffer]
3233
        call    fs_write32_sys
2288 clevermous 3234
        call    update_disk
2643 clevermous 3235
        call    fat_unlock
2288 clevermous 3236
        pop     edi
3237
        xor     eax, eax
3238
        ret
2643 clevermous 3239
.error:
3240
        push    eax
3241
        call    fat_unlock
3242
        pop     eax
3243
        pop     edi
3244
        ret
2288 clevermous 3245
 
3246
;----------------------------------------------------------------
2643 clevermous 3247
fat_Delete:
3248
        call    fat_lock
3249
        and     [ebp+FAT.longname_sec1], 0
3250
        and     [ebp+FAT.longname_sec2], 0
2288 clevermous 3251
        push    edi
6468 pathoswith 3252
        call    hd_find_lfn
6845 pathoswith 3253
        jc      .notFound
2288 clevermous 3254
        cmp     dword [edi], '.   '
3255
        jz      .access_denied2
3256
        cmp     dword [edi], '..  '
3257
        jz      .access_denied2
3258
        test    byte [edi+11], 10h
3259
        jz      .dodel
3260
; we can delete only empty folders!
3261
        pushad
2643 clevermous 3262
        mov     esi, [edi+20-2]
3263
        mov     si, [edi+26]
2288 clevermous 3264
        xor     ecx, ecx
2643 clevermous 3265
        lea     eax, [esi-2]
3266
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3267
        add     eax, [ebp+FAT.DATA_START]
3268
        lea     ebx, [ebp+FAT.buffer]
3269
        call    fs_read32_sys
3270
        test    eax, eax
2288 clevermous 3271
        jnz     .err1
2643 clevermous 3272
        lea     eax, [ebx+0x200]
2288 clevermous 3273
        add     ebx, 2*0x20
3274
.checkempty:
3275
        cmp     byte [ebx], 0
3276
        jz      .empty
3277
        cmp     byte [ebx], 0xE5
3278
        jnz     .notempty
3279
        add     ebx, 0x20
2643 clevermous 3280
        cmp     ebx, eax
2288 clevermous 3281
        jb      .checkempty
3282
        inc     ecx
2643 clevermous 3283
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 3284
        jb      @f
2643 clevermous 3285
        mov     eax, esi
2288 clevermous 3286
        call    get_FAT
2643 clevermous 3287
        jc      .err1
3174 clevermous 3288
        cmp     eax, 2
3289
        jb      .error_fat
3290
        cmp     eax, [ebp+FAT.fatRESERVED]
3291
        jae     .empty
2643 clevermous 3292
        mov     esi, eax
2288 clevermous 3293
        xor     ecx, ecx
3294
@@:
2643 clevermous 3295
        lea     eax, [esi-2]
3296
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3297
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 3298
        add     eax, ecx
2643 clevermous 3299
        lea     ebx, [ebp+FAT.buffer]
3300
        call    fs_read32_sys
3301
        test    eax, eax
3302
        lea     eax, [ebx+0x200]
2288 clevermous 3303
        jz      .checkempty
3304
.err1:
3305
        popad
3306
.err2:
6845 pathoswith 3307
        push    ERROR_DEVICE
3308
.ret:
2643 clevermous 3309
        call    fat_unlock
6845 pathoswith 3310
        pop     eax edi
2288 clevermous 3311
        ret
6845 pathoswith 3312
 
3313
.notFound:
3314
        push    ERROR_FILE_NOT_FOUND
3315
        jmp     .ret
3316
 
3174 clevermous 3317
.error_fat:
3318
        popad
6845 pathoswith 3319
        push    ERROR_FS_FAIL
3320
        jmp     .ret
3321
 
2288 clevermous 3322
.notempty:
3323
        popad
3324
.access_denied2:
6845 pathoswith 3325
        push    ERROR_ACCESS_DENIED
3326
        jmp     .ret
3327
 
2288 clevermous 3328
.empty:
3329
        popad
2643 clevermous 3330
        push    eax ebx
3331
        lea     ebx, [ebp+FAT.buffer]
3332
        call    fs_read32_sys
3333
        test    eax, eax
3334
        pop     ebx eax
2288 clevermous 3335
        jnz     .err2
3336
.dodel:
3337
        push    eax
3338
        mov     eax, [edi+20-2]
3339
        mov     ax, [edi+26]
3340
        xchg    eax, [esp]
3341
; delete folder entry
3342
        mov     byte [edi], 0xE5
3343
; delete LFN (if present)
3344
.lfndel:
2643 clevermous 3345
        lea     edx, [ebp+FAT.buffer]
3346
        cmp     edi, edx
2288 clevermous 3347
        ja      @f
2643 clevermous 3348
        cmp     [ebp+FAT.longname_sec2], 0
2288 clevermous 3349
        jz      .lfndone
2643 clevermous 3350
        push    [ebp+FAT.longname_sec2]
3351
        push    [ebp+FAT.longname_sec1]
3352
        pop     [ebp+FAT.longname_sec2]
3353
        and     [ebp+FAT.longname_sec1], 0
2288 clevermous 3354
        push    ebx
2643 clevermous 3355
        mov     ebx, edx
3356
        call    fs_write32_sys
2288 clevermous 3357
        mov     eax, [esp+4]
2643 clevermous 3358
        call    fs_read32_sys
2288 clevermous 3359
        pop     ebx
3360
        pop     eax
2643 clevermous 3361
        lea     edi, [ebp+FAT.buffer+0x200]
2288 clevermous 3362
@@:
3363
        sub     edi, 0x20
3364
        cmp     byte [edi], 0xE5
3365
        jz      .lfndone
3366
        cmp     byte [edi+11], 0xF
3367
        jnz     .lfndone
3368
        mov     byte [edi], 0xE5
3369
        jmp     .lfndel
3370
.lfndone:
3371
        push    ebx
2643 clevermous 3372
        lea     ebx, [ebp+FAT.buffer]
3373
        call    fs_write32_sys
2288 clevermous 3374
        pop     ebx
3375
; delete FAT chain
3376
        pop     eax
3377
        call    clear_cluster_chain
3378
        call    update_disk
2643 clevermous 3379
        call    fat_unlock
2288 clevermous 3380
        pop     edi
3381
        xor     eax, eax
3382
        ret