Subversion Repositories Kolibri OS

Rev

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