Subversion Repositories Kolibri OS

Rev

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