Subversion Repositories Kolibri OS

Rev

Rev 5565 | Rev 5596 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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