Subversion Repositories Kolibri OS

Rev

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

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