Subversion Repositories Kolibri OS

Rev

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