Subversion Repositories Kolibri OS

Rev

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