Subversion Repositories Kolibri OS

Rev

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

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