Subversion Repositories Kolibri OS

Rev

Rev 3681 | 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
;;                                                                 ;;
8
;;  FAT16/32 functions for KolibriOS                               ;;
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: 3742 $
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
 
97
fat_cache            rb 512
98
buffer               rb 512
99
fsinfo_buffer        rb 512
100
ends
101
 
2288 clevermous 102
uglobal
103
align 4
104
partition_count      dd 0       ; partitions found by set_FAT32_variables
105
 
106
hd_error             dd 0       ; set by wait_for_sector_buffer
107
hd_setup             dd 0
108
hd_wait_timeout      dd 0
109
 
110
cache_search_start   dd 0       ; used by find_empty_slot
111
endg
112
 
113
uglobal
114
align 4
115
 Sector512:                      ; label for dev_hdcd.inc
116
  buffer:
2643 clevermous 117
                times 512 db 0
2288 clevermous 118
endg
119
 
2643 clevermous 120
iglobal
121
align 4
122
fat_user_functions:
3742 clevermous 123
        dd      free
2643 clevermous 124
        dd      (fat_user_functions_end - fat_user_functions - 4) / 4
125
        dd      fat_Read
126
        dd      fat_ReadFolder
127
        dd      fat_Rewrite
128
        dd      fat_Write
129
        dd      fat_SetFileEnd
130
        dd      fat_GetFileInfo
131
        dd      fat_SetFileInfo
132
        dd      0
133
        dd      fat_Delete
134
        dd      fat_CreateFolder
135
fat_user_functions_end:
2288 clevermous 136
endg
137
 
2643 clevermous 138
; these labels are located before the main function to make
139
; most of jumps to these be short
140
fat_create_partition.free_return0:
141
        mov     eax, ebp
142
        call    free
143
        pop     ebp
144
fat_create_partition.return0:
145
        xor     eax, eax
146
        ret
147
fat_create_partition:
148
; bootsector must have been successfully read
3742 clevermous 149
        cmp     dword [esp+4], 0
2643 clevermous 150
        jnz     .return0
151
; bootsector signature must be correct
152
        cmp     word [ebx+0x1fe], 0xaa55
153
        jnz     .return0
154
; sectors per cluster must be nonzero
155
        cmp     byte [ebx+0xd], 0
156
        jz      .return0
157
; bytes per sector must be 0x200
158
        cmp     word [ebx+0xb], 0x200
159
        jnz     .return0
160
; number of fats must be nonzero
161
        cmp     byte [ebx+0x10], 0
162
        jz      .return0
163
; The only reason to be invalid partition now is FAT12. Since the test for
164
; FAT size requires knowledge of some calculated values, which are also used
165
; in the normal operation, let's hope for the best and allocate data now; if
166
; it will prove wrong, just deallocate it.
3598 clevermous 167
        movi    eax, sizeof.FAT
2643 clevermous 168
        call    malloc
169
        test    eax, eax
170
        jz      .return0
3742 clevermous 171
        mov     ecx, dword [ebp+PARTITION.FirstSector]
172
        mov     dword [eax+FAT.FirstSector], ecx
173
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
174
        mov     dword [eax+FAT.FirstSector+4], ecx
175
        mov     ecx, dword [ebp+PARTITION.Length]
176
        mov     dword [eax+FAT.Length], ecx
177
        mov     ecx, dword [ebp+PARTITION.Length+4]
178
        mov     dword [eax+FAT.Length+4], ecx
179
        mov     ecx, [ebp+PARTITION.Disk]
180
        mov     [eax+FAT.Disk], ecx
181
        mov     [eax+FAT.FSUserFunctions], fat_user_functions
2643 clevermous 182
        or      [eax+FAT.fat_in_cache], -1
183
        mov     [eax+FAT.fat_change], 0
184
        push    ebp
185
        mov     ebp, eax
2288 clevermous 186
 
2643 clevermous 187
        lea     ecx, [ebp+FAT.Lock]
188
        call    mutex_init
2288 clevermous 189
 
2643 clevermous 190
        movzx   eax, word [ebx+0xe]     ; sectors reserved
191
        mov     [ebp+FAT.FAT_START], eax
2288 clevermous 192
 
2643 clevermous 193
        movzx   eax, byte [ebx+0xd]     ; sectors per cluster
194
        mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
2288 clevermous 195
 
2643 clevermous 196
        movzx   ecx, word [ebx+0xb]     ; bytes per sector
197
        mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
2288 clevermous 198
 
2643 clevermous 199
        movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
200
        shl     eax, 5                  ; mul 32
201
        dec     ecx
202
        add     eax, ecx                ; round up if not equal count
203
        inc     ecx                     ; bytes per sector
204
        xor     edx, edx
205
        div     ecx
206
        mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
2288 clevermous 207
 
2643 clevermous 208
        movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
209
        test    eax, eax
210
        jnz     @f
211
        mov     eax, [ebx+0x24]         ; sectors per fat
2288 clevermous 212
@@:
2643 clevermous 213
        mov     [ebp+FAT.SECTORS_PER_FAT], eax
214
 
215
        movzx   eax, byte [ebx+0x10]    ; number of fats
216
        mov     [ebp+FAT.NUMBER_OF_FATS], eax
217
        imul    eax, [ebp+FAT.SECTORS_PER_FAT]
218
        add     eax, [ebp+FAT.FAT_START]
219
        mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
220
        add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
221
        mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
222
 
223
        movzx   eax, word [ebx+0x13]    ; total sector count <65536
224
        test    eax, eax
225
        jnz     @f
226
        mov     eax, [ebx+0x20]         ; total sector count
227
@@:
3742 clevermous 228
        mov     dword [ebp+FAT.Length], eax
229
        and     dword [ebp+FAT.Length+4], 0
2643 clevermous 230
        sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
231
        xor     edx, edx
232
        div     [ebp+FAT.SECTORS_PER_CLUSTER]
233
        inc     eax
234
        mov     [ebp+FAT.LAST_CLUSTER], eax
235
        dec     eax                     ; cluster count
236
        mov     [ebp+FAT.fatStartScan], 2
237
 
238
        ; limits by Microsoft Hardware White Paper v1.03
239
        cmp     eax, 4085               ; 0xff5
240
        jb      .free_return0           ; fat12 not supported
241
        cmp     eax, 65525              ; 0xfff5
242
        jb      .fat16
243
.fat32:
244
        mov     eax, [ebx+0x2c]         ; rootdir cluster
245
        mov     [ebp+FAT.ROOT_CLUSTER], eax
246
        movzx   eax, word [ebx+0x30]
247
        mov     [ebp+FAT.ADR_FSINFO], eax
248
        push    ebx
249
        add     ebx, 512
250
        call    fs_read32_sys
251
        test    eax, eax
252
        jnz     @f
253
        mov     eax, [ebx+0x1ec]
254
        cmp     eax, -1
2288 clevermous 255
        jz      @f
2643 clevermous 256
        mov     [ebp+FAT.fatStartScan], eax
2288 clevermous 257
@@:
2643 clevermous 258
        pop     ebx
259
        mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
260
        mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
261
        mov     [ebp+FAT.fatEND], 0x0FFFFFF8
262
        mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
263
        mov     al, 32
264
        mov     [ebp+FAT.fs_type], al
265
        mov     eax, ebp
266
        pop     ebp
2288 clevermous 267
        ret
2643 clevermous 268
.fat16:
269
        and     [ebp+FAT.ROOT_CLUSTER], 0
270
        mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
271
        mov     [ebp+FAT.fatBAD], 0x0000FFF7
272
        mov     [ebp+FAT.fatEND], 0x0000FFF8
273
        mov     [ebp+FAT.fatMASK], 0x0000FFFF
274
        mov     al, 16
275
        mov     [ebp+FAT.fs_type], al
276
        mov     eax, ebp
277
        pop     ebp
2288 clevermous 278
        ret
279
 
280
set_FAT:
281
;--------------------------------
282
; input  : EAX = cluster
283
;          EDX = value to save
2643 clevermous 284
;          EBP = pointer to FAT structure
2288 clevermous 285
; output : EDX = old value
286
;--------------------------------
2643 clevermous 287
; out: CF set <=> error
2288 clevermous 288
        push    eax ebx esi
289
 
290
        cmp     eax, 2
291
        jb      sfc_error
2643 clevermous 292
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
2288 clevermous 293
        ja      sfc_error
2643 clevermous 294
        cmp     [ebp+FAT.fs_type], 16
2288 clevermous 295
        je      sfc_1
296
        add     eax, eax
297
  sfc_1:
298
        add     eax, eax
299
        mov     esi, 511
300
        and     esi, eax        ; esi = position in fat sector
301
        shr     eax, 9          ; eax = fat sector
2643 clevermous 302
        add     eax, [ebp+FAT.FAT_START]
303
        lea     ebx, [ebp+FAT.fat_cache]
2288 clevermous 304
 
2643 clevermous 305
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
2288 clevermous 306
        je      sfc_in_cache    ; yes
307
 
2643 clevermous 308
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
2288 clevermous 309
        je      sfc_no_change   ; no
310
        call    write_fat_sector; yes. write it into disk
2643 clevermous 311
        jc      sfc_error
2288 clevermous 312
 
313
  sfc_no_change:
2643 clevermous 314
        mov     [ebp+FAT.fat_in_cache], eax; save fat sector
315
        call    fs_read32_sys
316
        test    eax, eax
2288 clevermous 317
        jne     sfc_error
318
 
319
 
320
  sfc_in_cache:
2643 clevermous 321
        cmp     [ebp+FAT.fs_type], 16
2288 clevermous 322
        jne     sfc_test32
323
 
324
  sfc_set16:
325
        xchg    [ebx+esi], dx   ; save new value and get old value
326
        jmp     sfc_write
327
 
328
  sfc_test32:
2643 clevermous 329
        mov     eax, [ebp+FAT.fatMASK]
2288 clevermous 330
 
331
  sfc_set32:
332
        and     edx, eax
333
        xor     eax, -1         ; mask for high bits
334
        and     eax, [ebx+esi]  ; get high 4 bits
335
        or      eax, edx
336
        mov     edx, [ebx+esi]  ; get old value
337
        mov     [ebx+esi], eax  ; save new value
338
 
339
  sfc_write:
2643 clevermous 340
        mov     [ebp+FAT.fat_change], 1; fat has changed
2288 clevermous 341
 
342
  sfc_nonzero:
2643 clevermous 343
        and     edx, [ebp+FAT.fatMASK]
2288 clevermous 344
 
2643 clevermous 345
  sfc_return:
2288 clevermous 346
        pop     esi ebx eax
347
        ret
2643 clevermous 348
  sfc_error:
349
        stc
350
        jmp     sfc_return
2288 clevermous 351
 
352
 
353
get_FAT:
354
;--------------------------------
355
; input  : EAX = cluster
2643 clevermous 356
;          EBP = pointer to FAT structure
2288 clevermous 357
; output : EAX = next cluster
358
;--------------------------------
2643 clevermous 359
; out: CF set <=> error
2288 clevermous 360
        push    ebx esi
361
 
2643 clevermous 362
        cmp     [ebp+FAT.fs_type], 16
2288 clevermous 363
        je      gfc_1
364
        add     eax, eax
365
  gfc_1:
366
        add     eax, eax
367
        mov     esi, 511
368
        and     esi, eax        ; esi = position in fat sector
369
        shr     eax, 9          ; eax = fat sector
2643 clevermous 370
        add     eax, [ebp+FAT.FAT_START]
371
        lea     ebx, [ebp+FAT.fat_cache]
2288 clevermous 372
 
2643 clevermous 373
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
2288 clevermous 374
        je      gfc_in_cache
375
 
2643 clevermous 376
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
2288 clevermous 377
        je      gfc_no_change   ; no
378
        call    write_fat_sector; yes. write it into disk
2643 clevermous 379
        jc      hd_error_01
2288 clevermous 380
 
381
  gfc_no_change:
2643 clevermous 382
        mov     [ebp+FAT.fat_in_cache], eax
383
        call    fs_read32_sys
384
        test    eax, eax
2288 clevermous 385
        jne     hd_error_01
386
 
387
  gfc_in_cache:
388
        mov     eax, [ebx+esi]
2643 clevermous 389
        and     eax, [ebp+FAT.fatMASK]
390
  gfc_return:
2288 clevermous 391
        pop     esi ebx
392
        ret
2643 clevermous 393
 hd_error_01:
394
        stc
395
        jmp     gfc_return
2288 clevermous 396
 
397
 
398
get_free_FAT:
399
;-----------------------------------------------------------
400
; output : if CARRY=0 EAX = # first cluster found free
401
;          if CARRY=1 disk full
402
; Note   : for more speed need to use fat_cache directly
403
;-----------------------------------------------------------
404
        push    ecx
2643 clevermous 405
        mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
2288 clevermous 406
        sub     ecx, 2
2643 clevermous 407
        mov     eax, [ebp+FAT.fatStartScan]
2288 clevermous 408
        cmp     eax, 2
409
        jb      gff_reset
410
 
411
  gff_test:
2643 clevermous 412
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
2288 clevermous 413
        jbe     gff_in_range
414
  gff_reset:
415
        mov     eax, 2
416
 
417
  gff_in_range:
418
        push    eax
419
        call    get_FAT         ; get cluster state
2643 clevermous 420
        jc      gff_not_found_1
2288 clevermous 421
 
422
        test    eax, eax        ; is it free?
423
        pop     eax
424
        je      gff_found       ; yes
425
        inc     eax             ; next cluster
426
        dec     ecx             ; is all checked?
427
        jns     gff_test        ; no
428
 
429
  gff_not_found:
430
        pop     ecx             ; yes. disk is full
431
        stc
432
        ret
433
 
2643 clevermous 434
  gff_not_found_1:
435
        pop     eax
436
        jmp     gff_not_found
437
 
2288 clevermous 438
  gff_found:
439
        lea     ecx, [eax+1]
2643 clevermous 440
        mov     [ebp+FAT.fatStartScan], ecx
2288 clevermous 441
        pop     ecx
442
        clc
443
        ret
444
 
445
 
446
write_fat_sector:
447
;-----------------------------------------------------------
448
; write changed fat to disk
449
;-----------------------------------------------------------
450
        push    eax ebx ecx
451
 
2643 clevermous 452
        mov     [ebp+FAT.fat_change], 0
453
        mov     eax, [ebp+FAT.fat_in_cache]
2288 clevermous 454
        cmp     eax, -1
455
        jz      write_fat_not_used
2643 clevermous 456
        lea     ebx, [ebp+FAT.fat_cache]
457
        mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
2288 clevermous 458
 
459
  write_next_fat:
2643 clevermous 460
        push    eax
461
        call    fs_write32_sys
462
        test    eax, eax
463
        pop     eax
464
        jnz     write_fat_not_used
2288 clevermous 465
 
2643 clevermous 466
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
2288 clevermous 467
        dec     ecx
468
        jnz     write_next_fat
469
 
470
  write_fat_not_used:
471
        pop     ecx ebx eax
472
        ret
473
 
474
 
475
 
476
 
477
 
478
bcd2bin:
479
;----------------------------------
480
; input  : AL=BCD number (eg. 0x11)
481
; output : AH=0
482
;          AL=decimal number (eg. 11)
483
;----------------------------------
484
        xor     ah, ah
485
        shl     ax, 4
486
        shr     al, 4
487
        aad
488
        ret
489
 
490
 
491
get_date_for_file:
492
;-----------------------------------------------------
493
; Get date from CMOS and pack day,month,year in AX
494
; DATE   bits  0..4   : day of month 0..31
495
;              5..8   : month of year 1..12
496
;              9..15  : count of years from 1980
497
;-----------------------------------------------------
498
        mov     al, 0x7 ;day
499
        out     0x70, al
500
        in      al, 0x71
501
        call    bcd2bin
502
        ror     eax, 5
503
 
504
        mov     al, 0x8 ;month
505
        out     0x70, al
506
        in      al, 0x71
507
        call    bcd2bin
508
        ror     eax, 4
509
 
510
        mov     al, 0x9 ;year
511
        out     0x70, al
512
        in      al, 0x71
513
        call    bcd2bin
514
        add     ax, 20  ;because CMOS return only the two last
515
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
516
        rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
517
        ret
518
 
519
 
520
get_time_for_file:
521
;-----------------------------------------------------
522
; Get time from CMOS and pack hour,minute,second in AX
523
; TIME   bits  0..4   : second (the low bit is lost)
524
;              5..10  : minute 0..59
525
;              11..15 : hour 0..23
526
;-----------------------------------------------------
527
        mov     al, 0x0 ;second
528
        out     0x70, al
529
        in      al, 0x71
530
        call    bcd2bin
531
        ror     eax, 6
532
 
533
        mov     al, 0x2 ;minute
534
        out     0x70, al
535
        in      al, 0x71
536
        call    bcd2bin
537
        ror     eax, 6
538
 
539
        mov     al, 0x4 ;hour
540
        out     0x70, al
541
        in      al, 0x71
542
        call    bcd2bin
543
        rol     eax, 11
544
        ret
545
 
546
 
547
set_current_time_for_entry:
548
;-----------------------------------------------------
549
; Set current time/date for file entry
550
; input  : ebx = file entry pointer
551
;-----------------------------------------------------
552
        push    eax
553
        call    get_time_for_file; update files date/time
554
        mov     [ebx+22], ax
555
        call    get_date_for_file
556
        mov     [ebx+24], ax
557
        pop     eax
558
        ret
559
 
560
 
561
 
562
add_disk_free_space:
563
;-----------------------------------------------------
564
; input  : ecx = cluster count
565
; Note   : negative = remove clusters from free space
566
;          positive = add clusters to free space
567
;-----------------------------------------------------
568
        test    ecx, ecx        ; no change
569
        je      add_dfs_no
2643 clevermous 570
        cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
2288 clevermous 571
        jne     add_dfs_no
572
 
573
        push    eax ebx
2643 clevermous 574
        mov     eax, [ebp+FAT.ADR_FSINFO]
575
        lea     ebx, [ebp+FAT.fsinfo_buffer]
576
        call    fs_read32_sys
577
        test    eax, eax
578
        jnz     add_not_fs
2288 clevermous 579
 
580
        cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
581
        jne     add_not_fs
582
 
583
        add     [ebx+0x1e8], ecx
2643 clevermous 584
        push    [ebp+FAT.fatStartScan]
2288 clevermous 585
        pop     dword [ebx+0x1ec]
2643 clevermous 586
        mov     eax, [ebp+FAT.ADR_FSINFO]
587
        call    fs_write32_sys
588
;    jc    add_not_fs
2288 clevermous 589
 
590
  add_not_fs:
591
        pop     ebx eax
592
 
593
  add_dfs_no:
594
        ret
595
 
596
 
597
 
598
clear_cluster_chain:
599
;-----------------------------------------------------
600
; input  : eax = first cluster
601
;-----------------------------------------------------
602
        push    eax ecx edx
603
        xor     ecx, ecx        ; cluster count
604
 
605
  clean_new_chain:
2643 clevermous 606
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
2288 clevermous 607
        ja      delete_OK
608
        cmp     eax, 2          ; unfinished fat chain or zero length file
609
        jb      delete_OK
2643 clevermous 610
        cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
2288 clevermous 611
        jz      delete_OK
612
 
613
        xor     edx, edx
614
        call    set_FAT         ; clear fat entry
2643 clevermous 615
        jc      access_denied_01
2288 clevermous 616
 
617
        inc     ecx             ; update cluster count
618
        mov     eax, edx        ; old cluster
619
        jmp     clean_new_chain
620
 
621
  delete_OK:
622
        call    add_disk_free_space; add clusters to free disk space
2643 clevermous 623
        clc
2288 clevermous 624
  access_denied_01:
625
        pop     edx ecx eax
626
        ret
627
 
628
 
2643 clevermous 629
if 0
2288 clevermous 630
get_hd_info:
631
;-----------------------------------------------------------
632
; output : eax = 0 - ok
633
;                3 - unknown FS
634
;               10 - access denied
635
;          edx = cluster size in bytes
636
;          ebx = total clusters on disk
637
;          ecx = free clusters on disk
638
;-----------------------------------------------------------
2643 clevermous 639
        cmp     [ebp+FAT.fs_type], 16
2288 clevermous 640
        jz      info_fat_ok
2643 clevermous 641
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 642
        jz      info_fat_ok
643
        xor     edx, edx
644
        xor     ebx, ebx
645
        xor     ecx, ecx
646
        mov     eax, ERROR_UNKNOWN_FS
647
        ret
648
 
649
  info_fat_ok:
650
;    call  reserve_hd1
651
 
652
        xor     ecx, ecx        ; count of free clusters
653
        mov     eax, 2
2643 clevermous 654
        mov     ebx, [ebp+FAT.LAST_CLUSTER]
2288 clevermous 655
 
656
  info_cluster:
657
        push    eax
658
        call    get_FAT         ; get cluster info
2643 clevermous 659
        jc      info_access_denied
2288 clevermous 660
 
661
        test    eax, eax        ; is it free?
662
        jnz     info_used       ; no
663
        inc     ecx
664
 
665
  info_used:
666
        pop     eax
667
        inc     eax
668
        cmp     eax, ebx        ; is above last cluster?
669
        jbe     info_cluster    ; no. test next cluster
670
 
671
        dec     ebx             ; cluster count
2643 clevermous 672
        imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
2288 clevermous 673
        xor     eax, eax
674
        ret
675
 
676
  info_access_denied:
677
        add     esp, 4
678
        xor     edx, edx
679
        xor     ebx, ebx
680
        xor     ecx, ecx
681
        mov     eax, ERROR_ACCESS_DENIED
682
        ret
2643 clevermous 683
end if
2288 clevermous 684
 
685
update_disk:
686
;-----------------------------------------------------------
687
; write changed fat and cache to disk
688
;-----------------------------------------------------------
2643 clevermous 689
        cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
2288 clevermous 690
        je      upd_no_change
691
 
692
        call    write_fat_sector
2643 clevermous 693
        jc      update_disk_acces_denied
2288 clevermous 694
 
695
  upd_no_change:
696
 
2643 clevermous 697
        push    esi
698
        mov     esi, [ebp+PARTITION.Disk]
699
        call    disk_sync
700
        pop     esi
2288 clevermous 701
  update_disk_acces_denied:
702
        ret
703
 
2643 clevermous 704
fat_lock:
705
        lea     ecx, [ebp+FAT.Lock]
706
        jmp     mutex_lock
707
fat_unlock:
708
        lea     ecx, [ebp+FAT.Lock]
709
        jmp     mutex_unlock
2288 clevermous 710
 
711
; \begin{diamond}
712
hd_find_lfn:
2643 clevermous 713
; in: ebp -> FAT structure
714
; in: esi+[esp+4] -> name
715
; out: CF=1 - file not found, eax=error code
2288 clevermous 716
;      else CF=0 and edi->direntry, eax=sector
717
; destroys eax
718
        push    esi edi
719
        push    0
720
        push    0
721
        push    fat16_root_first
722
        push    fat16_root_next
2643 clevermous 723
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
724
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 725
        jz      .fat32
726
.loop:
727
        call    fat_find_lfn
728
        jc      .notfound
729
        cmp     byte [esi], 0
730
        jz      .found
731
.continue:
732
        test    byte [edi+11], 10h
733
        jz      .notfound
734
        and     dword [esp+12], 0
735
        mov     eax, [edi+20-2]
736
        mov     ax, [edi+26]    ; cluster
737
.fat32:
738
        mov     [esp+8], eax
739
        mov     dword [esp+4], fat_notroot_first
740
        mov     dword [esp], fat_notroot_next
741
        jmp     .loop
742
.notfound:
743
        add     esp, 16
744
        pop     edi esi
745
        stc
2643 clevermous 746
        ret     4
2288 clevermous 747
.found:
2643 clevermous 748
        lea     eax, [esp+4+24]
749
        cmp     dword [eax], 0
2288 clevermous 750
        jz      @f
2643 clevermous 751
        mov     esi, [eax]
752
        and     dword [eax], 0
2288 clevermous 753
        jmp     .continue
754
@@:
755
        lea     eax, [esp+8]
756
        cmp     dword [eax], 0
757
        jz      .root
758
        call    fat_get_sector
759
        jmp     .cmn
760
.root:
761
        mov     eax, [eax+4]
2643 clevermous 762
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 763
.cmn:
764
        add     esp, 20         ; CF=0
765
        pop     esi
2643 clevermous 766
        ret     4
2288 clevermous 767
 
768
;----------------------------------------------------------------
2643 clevermous 769
; fat_Read - FAT16/32 implementation of reading a file
770
; in:  ebp = pointer to FAT structure
771
; in:  esi+[esp+4] = name
772
; in:  ebx = pointer to parameters from sysfunc 70
773
; out: eax, ebx = return values for sysfunc 70
774
;----------------------------------------------------------------
775
fat_Read:
776
        call    fat_lock
2288 clevermous 777
        push    edi
778
        cmp     byte [esi], 0
779
        jnz     @f
780
.noaccess:
781
        pop     edi
782
.noaccess_2:
2643 clevermous 783
        call    fat_unlock
2288 clevermous 784
        or      ebx, -1
785
        mov     eax, ERROR_ACCESS_DENIED
786
        ret
787
 
788
@@:
2643 clevermous 789
        stdcall hd_find_lfn, [esp+4+4]
2288 clevermous 790
        jnc     .found
791
        pop     edi
2643 clevermous 792
        push    eax
793
        call    fat_unlock
794
        pop     eax
2288 clevermous 795
        or      ebx, -1
796
        ret
797
 
798
.found:
799
        test    byte [edi+11], 0x10; do not allow read directories
800
        jnz     .noaccess
2643 clevermous 801
        cmp     dword [ebx+8], 0
2288 clevermous 802
        jz      @f
803
        xor     ebx, ebx
804
.reteof:
2643 clevermous 805
        call    fat_unlock
806
        mov     eax, ERROR_END_OF_FILE
2288 clevermous 807
        pop     edi
808
        ret
809
@@:
2643 clevermous 810
        mov     ecx, [ebx+12]   ; size
811
        mov     edx, [ebx+16]   ; pointer
812
        mov     ebx, [ebx+4]    ; file offset
813
        push    edx
2288 clevermous 814
        push    0
815
        mov     eax, [edi+28]
816
        sub     eax, ebx
817
        jb      .eof
818
        cmp     eax, ecx
819
        jae     @f
820
        mov     ecx, eax
821
        mov     byte [esp], 6
822
@@:
823
        mov     eax, [edi+20-2]
824
        mov     ax, [edi+26]
825
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
826
.new_cluster:
827
        jecxz   .new_sector
2643 clevermous 828
        cmp     eax, 2
829
        jb      .eof
830
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 831
        jae     .eof
2643 clevermous 832
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 833
        dec     eax
834
        dec     eax
2643 clevermous 835
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 836
        imul    eax, edi
2643 clevermous 837
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 838
.new_sector:
839
        test    ecx, ecx
840
        jz      .done
841
        sub     ebx, 512
842
        jae     .skip
843
        add     ebx, 512
844
        jnz     .force_buf
845
        cmp     ecx, 512
846
        jb      .force_buf
847
; we may read directly to given buffer
2643 clevermous 848
        push    eax ebx
2288 clevermous 849
        mov     ebx, edx
2643 clevermous 850
        call    fs_read32_app
851
        test    eax, eax
852
        pop     ebx eax
2288 clevermous 853
        jne     .noaccess_1
854
        add     edx, 512
855
        sub     ecx, 512
856
        jmp     .skip
857
.force_buf:
858
; we must read sector to temporary buffer and then copy it to destination
859
        push    eax ebx
2643 clevermous 860
        lea     ebx, [ebp+FAT.buffer]
861
        call    fs_read32_app
862
        test    eax, eax
2288 clevermous 863
        mov     eax, ebx
864
        pop     ebx
865
        jne     .noaccess_3
866
        add     eax, ebx
867
        push    ecx
868
        add     ecx, ebx
869
        cmp     ecx, 512
870
        jbe     @f
871
        mov     ecx, 512
872
@@:
873
        sub     ecx, ebx
874
        mov     ebx, edx
875
        call    memmove
876
        add     edx, ecx
877
        sub     [esp], ecx
878
        pop     ecx
879
        pop     eax
880
        xor     ebx, ebx
881
.skip:
882
        inc     eax
883
        dec     edi
884
        jnz     .new_sector
2643 clevermous 885
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 886
        call    get_FAT
2643 clevermous 887
        jc      .noaccess_1
2288 clevermous 888
 
889
        jmp     .new_cluster
890
.noaccess_3:
891
        pop     eax
892
.noaccess_1:
893
        pop     eax
2643 clevermous 894
        push    ERROR_DEVICE
2288 clevermous 895
.done:
896
        mov     ebx, edx
2643 clevermous 897
        call    fat_unlock
898
        pop     eax edx edi
2288 clevermous 899
        sub     ebx, edx
900
        ret
901
.eof:
902
        mov     ebx, edx
2643 clevermous 903
        pop     eax edx
2288 clevermous 904
        sub     ebx, edx
905
        jmp     .reteof
906
 
907
;----------------------------------------------------------------
2643 clevermous 908
; fat_ReadFolder - FAT16/32 implementation of reading a folder
909
; in:  ebp = pointer to FAT structure
910
; in:  esi+[esp+4] = name
911
; in:  ebx = pointer to parameters from sysfunc 70
912
; out: eax, ebx = return values for sysfunc 70
913
;----------------------------------------------------------------
914
fat_ReadFolder:
915
        call    fat_lock
916
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
2288 clevermous 917
        push    edi
918
        cmp     byte [esi], 0
919
        jz      .doit
2643 clevermous 920
        stdcall hd_find_lfn, [esp+4+4]
2288 clevermous 921
        jnc     .found
922
        pop     edi
2643 clevermous 923
        push    eax
924
        call    fat_unlock
925
        pop     eax
2288 clevermous 926
        or      ebx, -1
927
        ret
928
.found:
929
        test    byte [edi+11], 0x10     ; do not allow read files
930
        jnz     .found_dir
931
        pop     edi
2643 clevermous 932
        call    fat_unlock
2288 clevermous 933
        or      ebx, -1
934
        mov     eax, ERROR_ACCESS_DENIED
935
        ret
936
.found_dir:
937
        mov     eax, [edi+20-2]
938
        mov     ax, [edi+26]    ; eax=cluster
939
.doit:
2643 clevermous 940
        push    esi
2288 clevermous 941
        sub     esp, 262*2      ; reserve space for LFN
2643 clevermous 942
        push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
943
        mov     edx, [ebx+16]   ; pointer to buffer
2288 clevermous 944
; init header
2643 clevermous 945
        push    eax
2288 clevermous 946
        mov     edi, edx
947
        mov     ecx, 32/4
948
        xor     eax, eax
949
        rep stosd
2643 clevermous 950
        pop     eax
2288 clevermous 951
        mov     byte [edx], 1   ; version
952
        mov     esi, edi        ; esi points to BDFE
2643 clevermous 953
        mov     ecx, [ebx+12]   ; number of blocks to read
954
        mov     ebx, [ebx+4]    ; index of the first block
2288 clevermous 955
.new_cluster:
2643 clevermous 956
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 957
        test    eax, eax
958
        jnz     @f
2643 clevermous 959
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 960
        jz      .notfound
2643 clevermous 961
        mov     eax, [ebp+FAT.ROOT_START]
962
        push    [ebp+FAT.ROOT_SECTORS]
2288 clevermous 963
        push    ebx
964
        jmp     .new_sector
965
@@:
966
        dec     eax
967
        dec     eax
2643 clevermous 968
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
969
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
970
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 971
        push    ebx
972
.new_sector:
2643 clevermous 973
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 974
        mov     edi, ebx
2643 clevermous 975
        push    eax
976
        call    fs_read32_sys
977
        test    eax, eax
978
        pop     eax
2288 clevermous 979
        jnz     .notfound2
980
        add     ebx, 512
981
        push    eax
982
.l1:
2643 clevermous 983
        push    ebp
984
        lea     ebp, [esp+20]
2288 clevermous 985
        call    fat_get_name
2643 clevermous 986
        pop     ebp
2288 clevermous 987
        jc      .l2
988
        cmp     byte [edi+11], 0xF
989
        jnz     .do_bdfe
990
        add     edi, 0x20
991
        cmp     edi, ebx
992
        jb      .do_bdfe
993
        pop     eax
994
        inc     eax
995
        dec     dword [esp+4]
996
        jnz     @f
2643 clevermous 997
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 998
        test    eax, eax
999
        jz      .done
1000
        call    get_FAT
2643 clevermous 1001
        jc      .notfound2
2288 clevermous 1002
        cmp     eax, 2
1003
        jb      .done
2643 clevermous 1004
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1005
        jae     .done
1006
        push    eax
2643 clevermous 1007
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1008
        mov     [esp+8], eax
1009
        pop     eax
2643 clevermous 1010
        mov     [ebp+FAT.cluster_tmp], eax
2288 clevermous 1011
        dec     eax
1012
        dec     eax
2643 clevermous 1013
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1014
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1015
@@:
2643 clevermous 1016
        lea     ebx, [ebp+FAT.buffer]
2288 clevermous 1017
        mov     edi, ebx
2643 clevermous 1018
        push    eax
1019
        call    fs_read32_sys
1020
        test    eax, eax
1021
        pop     eax
2288 clevermous 1022
        jnz     .notfound2
1023
        add     ebx, 512
1024
        push    eax
1025
.do_bdfe:
1026
        inc     dword [edx+8]   ; new file found
1027
        dec     dword [esp+4]
1028
        jns     .l2
1029
        dec     ecx
1030
        js      .l2
1031
        inc     dword [edx+4]   ; new file block copied
2643 clevermous 1032
        push    ebp
1033
        lea     ebp, [esp+20]
2288 clevermous 1034
        call    fat_entry_to_bdfe
2643 clevermous 1035
        pop     ebp
2288 clevermous 1036
.l2:
1037
        add     edi, 0x20
1038
        cmp     edi, ebx
1039
        jb      .l1
1040
        pop     eax
1041
        inc     eax
1042
        dec     dword [esp+4]
1043
        jnz     .new_sector
2643 clevermous 1044
        mov     eax, [ebp+FAT.cluster_tmp]
2288 clevermous 1045
        test    eax, eax
1046
        jz      .done
1047
        call    get_FAT
2643 clevermous 1048
        jc      .notfound2
2288 clevermous 1049
        cmp     eax, 2
1050
        jb      .done
2643 clevermous 1051
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1052
        jae     .done
1053
        push    eax
2643 clevermous 1054
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1055
        mov     [esp+8], eax
1056
        pop     eax
1057
        pop     ebx
1058
        add     esp, 4
1059
        jmp     .new_cluster
1060
.notfound2:
1061
        add     esp, 8
1062
.notfound:
1063
        add     esp, 262*2+4
2643 clevermous 1064
        pop     esi edi
1065
        mov     ebx, [edx+4]
1066
        call    fat_unlock
1067
        mov     eax, ERROR_DEVICE
2288 clevermous 1068
        ret
1069
.done:
1070
        add     esp, 262*2+4+8
1071
        mov     ebx, [edx+4]
1072
        xor     eax, eax
1073
        dec     ecx
1074
        js      @f
1075
        mov     al, ERROR_END_OF_FILE
1076
@@:
2643 clevermous 1077
        push    eax
1078
        call    fat_unlock
1079
        pop     eax
1080
        pop     esi edi
2288 clevermous 1081
        ret
1082
 
1083
fat16_root_next:
2643 clevermous 1084
        push    ecx
1085
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1086
        cmp     edi, ecx
2288 clevermous 1087
        jae     fat16_root_next_sector
2643 clevermous 1088
        pop     ecx
2288 clevermous 1089
        add     edi, 0x20
1090
        ret     ; CF=0
1091
fat16_root_next_sector:
1092
; read next sector
2643 clevermous 1093
        push    [ebp+FAT.longname_sec2]
1094
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1095
        mov     ecx, [eax+4]
1096
        push    ecx
2643 clevermous 1097
        add     ecx, [ebp+FAT.ROOT_START]
1098
        mov     [ebp+FAT.longname_sec2], ecx
2288 clevermous 1099
        pop     ecx
1100
        inc     ecx
1101
        mov     [eax+4], ecx
2643 clevermous 1102
        cmp     ecx, [ebp+FAT.ROOT_SECTORS]
2288 clevermous 1103
        pop     ecx
2643 clevermous 1104
        jb      fat16_root_first
1105
        mov     eax, ERROR_FILE_NOT_FOUND
1106
        stc
1107
        ret
2288 clevermous 1108
fat16_root_first:
1109
        mov     eax, [eax+4]
2643 clevermous 1110
        add     eax, [ebp+FAT.ROOT_START]
2288 clevermous 1111
        push    ebx
2643 clevermous 1112
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1113
        mov     ebx, edi
2643 clevermous 1114
        call    fs_read32_sys
2288 clevermous 1115
        pop     ebx
2643 clevermous 1116
        test    eax, eax
2288 clevermous 1117
        jnz     .readerr
1118
        ret     ; CF=0
1119
.readerr:
2643 clevermous 1120
        mov     eax, ERROR_DEVICE
2288 clevermous 1121
        stc
1122
        ret
2643 clevermous 1123
.notfound:
1124
        mov     eax, ERROR_FILE_NOT_FOUND
1125
        stc
1126
        ret
2288 clevermous 1127
fat16_root_begin_write:
1128
        push    edi eax
1129
        call    fat16_root_first
1130
        pop     eax edi
1131
        ret
1132
fat16_root_end_write:
1133
        pusha
1134
        mov     eax, [eax+4]
2643 clevermous 1135
        add     eax, [ebp+FAT.ROOT_START]
1136
        lea     ebx, [ebp+FAT.buffer]
1137
        call    fs_write32_sys
2288 clevermous 1138
        popa
1139
        ret
1140
fat16_root_next_write:
2643 clevermous 1141
        push    ecx
1142
        lea     ecx, [ebp+FAT.buffer+0x200]
1143
        cmp     edi, ecx
2288 clevermous 1144
        jae     @f
2643 clevermous 1145
        pop     ecx
2288 clevermous 1146
        ret
1147
@@:
1148
        call    fat16_root_end_write
1149
        jmp     fat16_root_next_sector
1150
fat16_root_extend_dir:
1151
        stc
1152
        ret
1153
 
1154
fat_notroot_next:
2643 clevermous 1155
        push    ecx
1156
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1157
        cmp     edi, ecx
2288 clevermous 1158
        jae     fat_notroot_next_sector
2643 clevermous 1159
        pop     ecx
2288 clevermous 1160
        add     edi, 0x20
1161
        ret     ; CF=0
1162
fat_notroot_next_sector:
2643 clevermous 1163
        push    [ebp+FAT.longname_sec2]
1164
        pop     [ebp+FAT.longname_sec1]
2288 clevermous 1165
        push    eax
1166
        call    fat_get_sector
2643 clevermous 1167
        mov     [ebp+FAT.longname_sec2], eax
2288 clevermous 1168
        pop     eax
1169
        mov     ecx, [eax+4]
1170
        inc     ecx
2643 clevermous 1171
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1172
        jae     fat_notroot_next_cluster
1173
        mov     [eax+4], ecx
1174
        jmp     @f
1175
fat_notroot_next_cluster:
1176
        push    eax
1177
        mov     eax, [eax]
1178
        call    get_FAT
1179
        mov     ecx, eax
1180
        pop     eax
2643 clevermous 1181
        jc      fat_notroot_first.deverr
1182
        cmp     ecx, 2
1183
        jb      fat_notroot_next_err
1184
        cmp     ecx, [ebp+FAT.fatRESERVED]
2288 clevermous 1185
        jae     fat_notroot_next_err
1186
        mov     [eax], ecx
1187
        and     dword [eax+4], 0
1188
@@:
1189
        pop     ecx
1190
fat_notroot_first:
1191
        call    fat_get_sector
1192
        push    ebx
2643 clevermous 1193
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1194
        mov     ebx, edi
2643 clevermous 1195
        call    fs_read32_sys
2288 clevermous 1196
        pop     ebx
2643 clevermous 1197
        test    eax, eax
1198
        jz      .ret ; CF=0
1199
        push    ecx
1200
.deverr:
1201
        pop     ecx
1202
        mov     eax, ERROR_DEVICE
1203
        stc
1204
.ret:
1205
        ret
2288 clevermous 1206
fat_notroot_next_err:
1207
        pop     ecx
2643 clevermous 1208
        mov     eax, ERROR_FILE_NOT_FOUND
2288 clevermous 1209
        stc
1210
        ret
1211
fat_notroot_begin_write:
1212
        push    eax edi
1213
        call    fat_notroot_first
1214
        pop     edi eax
1215
        ret
1216
fat_notroot_end_write:
1217
        call    fat_get_sector
1218
        push    ebx
2643 clevermous 1219
        lea     ebx, [ebp+FAT.buffer]
1220
        call    fs_write32_sys
2288 clevermous 1221
        pop     ebx
1222
        ret
1223
fat_notroot_next_write:
2643 clevermous 1224
        push    ecx
1225
        lea     ecx, [ebp+FAT.buffer+0x200]
1226
        cmp     edi, ecx
2288 clevermous 1227
        jae     @f
2643 clevermous 1228
        pop     ecx
2288 clevermous 1229
        ret
1230
@@:
1231
        push    eax
1232
        call    fat_notroot_end_write
1233
        pop     eax
1234
        jmp     fat_notroot_next_sector
1235
fat_notroot_extend_dir:
1236
        push    eax
1237
        call    get_free_FAT
1238
        jnc     .found
1239
        pop     eax
1240
        ret     ; CF=1
1241
.found:
1242
        push    edx
2643 clevermous 1243
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 1244
        call    set_FAT
2643 clevermous 1245
        jc      .writeerr
2288 clevermous 1246
        mov     edx, eax
1247
        mov     eax, [esp+4]
1248
        mov     eax, [eax]
1249
        push    edx
1250
        call    set_FAT
1251
        pop     edx
2643 clevermous 1252
        jnc     @f
1253
.writeerr:
2288 clevermous 1254
        pop     edx
1255
        pop     eax
1256
        stc
1257
        ret
1258
@@:
1259
        push    ecx
1260
        or      ecx, -1
1261
        call    add_disk_free_space
1262
; zero new cluster
1263
        mov     ecx, 512/4
2643 clevermous 1264
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1265
        push    edi
1266
        xor     eax, eax
1267
        rep stosd
1268
        pop     edi
1269
        pop     ecx
1270
        mov     eax, [esp+4]
1271
        mov     [eax], edx
1272
        and     dword [eax+4], 0
1273
        pop     edx
1274
        mov     eax, [eax]
1275
        dec     eax
1276
        dec     eax
1277
        push    ebx ecx
2643 clevermous 1278
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1279
        imul    eax, ecx
2643 clevermous 1280
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 1281
        mov     ebx, edi
1282
@@:
2643 clevermous 1283
        push    eax
1284
        call    fs_write32_sys
1285
        pop     eax
2288 clevermous 1286
        inc     eax
1287
        loop    @b
1288
        pop     ecx ebx eax
1289
        clc
1290
        ret
1291
 
1292
fat_get_sector:
1293
        push    ecx
1294
        mov     ecx, [eax]
1295
        dec     ecx
1296
        dec     ecx
2643 clevermous 1297
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
1298
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 1299
        add     ecx, [eax+4]
1300
        mov     eax, ecx
1301
        pop     ecx
1302
        ret
1303
 
2643 clevermous 1304
fshrad:
1305
        call    fat_unlock
1306
        mov     eax, ERROR_ACCESS_DENIED
1307
        xor     ebx, ebx
1308
        ret
1309
 
1310
;----------------------------------------------------------------
1311
; fat_CreateFolder - FAT16/32 implementation of creating a folder
1312
; in:  ebp = pointer to FAT structure
1313
; in:  esi+[esp+4] = name
1314
; in:  ebx = pointer to parameters from sysfunc 70
1315
; out: eax, ebx = return values for sysfunc 70
1316
;----------------------------------------------------------------
1317
fat_CreateFolder:
1318
        push    1
1319
        jmp     fat_Rewrite.common
1320
 
1321
;----------------------------------------------------------------
3742 clevermous 1322
; fat_Rewrite - FAT16/32 implementation of creating a new file
2643 clevermous 1323
; in:  ebp = pointer to FAT structure
1324
; in:  esi+[esp+4] = name
1325
; in:  ebx = pointer to parameters from sysfunc 70
1326
; out: eax, ebx = return values for sysfunc 70
1327
;----------------------------------------------------------------
1328
fat_Rewrite:
1329
        push    0
1330
.common:
1331
        call    fat_lock
1332
        pop     eax
2288 clevermous 1333
        cmp     byte [esi], 0
1334
        jz      fshrad
2643 clevermous 1335
        mov     ecx, [ebx+12]
1336
        mov     edx, [ebx+16]
2288 clevermous 1337
        pushad
1338
        xor     edi, edi
2643 clevermous 1339
        mov     edx, [esp+4+20h]
2288 clevermous 1340
        push    esi
2643 clevermous 1341
        test    edx, edx
2288 clevermous 1342
        jz      @f
2643 clevermous 1343
        mov     esi, edx
2288 clevermous 1344
@@:
1345
        lodsb
1346
        test    al, al
1347
        jz      @f
1348
        cmp     al, '/'
1349
        jnz     @b
1350
        lea     edi, [esi-1]
1351
        jmp     @b
1352
@@:
1353
        pop     esi
1354
        test    edi, edi
1355
        jnz     .noroot
2643 clevermous 1356
        test    edx, edx
2288 clevermous 1357
        jnz     .hasebp
2643 clevermous 1358
        mov     edx, [ebp+FAT.ROOT_CLUSTER]
1359
        cmp     [ebp+FAT.fs_type], 32
2288 clevermous 1360
        jz      .pushnotroot
2643 clevermous 1361
        xor     edx, edx
1362
        push    edx
2288 clevermous 1363
        push    fat16_root_extend_dir
1364
        push    fat16_root_end_write
1365
        push    fat16_root_next_write
1366
        push    fat16_root_begin_write
2643 clevermous 1367
        push    edx
1368
        push    edx
2288 clevermous 1369
        push    fat16_root_first
1370
        push    fat16_root_next
1371
        jmp     .common1
1372
.hasebp:
1373
        mov     eax, ERROR_ACCESS_DENIED
2643 clevermous 1374
        cmp     byte [edx], 0
2288 clevermous 1375
        jz      .ret1
2643 clevermous 1376
        stdcall hd_find_lfn, 0
1377
        mov     esi, [esp+4+20h]
1378
        jc      .ret1
2288 clevermous 1379
        jmp     .common0
1380
.noroot:
1381
        mov     eax, ERROR_ACCESS_DENIED
1382
        cmp     byte [edi+1], 0
1383
        jz      .ret1
1384
; check existence
1385
        mov     byte [edi], 0
1386
        push    edi
2643 clevermous 1387
        stdcall hd_find_lfn, [esp+4+24h]
2288 clevermous 1388
        pop     esi
1389
        mov     byte [esi], '/'
1390
        jnc     @f
1391
.notfound0:
1392
        mov     eax, ERROR_FILE_NOT_FOUND
1393
.ret1:
1394
        mov     [esp+28], eax
2643 clevermous 1395
        call    fat_unlock
2288 clevermous 1396
        popad
1397
        xor     ebx, ebx
1398
        ret
1399
@@:
1400
        inc     esi
1401
.common0:
1402
        test    byte [edi+11], 0x10     ; must be directory
1403
        mov     eax, ERROR_ACCESS_DENIED
1404
        jz      .ret1
2643 clevermous 1405
        mov     edx, [edi+20-2]
1406
        mov     dx, [edi+26]            ; ebp=cluster
2288 clevermous 1407
        mov     eax, ERROR_FAT_TABLE
2643 clevermous 1408
        cmp     edx, 2
2288 clevermous 1409
        jb      .ret1
1410
.pushnotroot:
2643 clevermous 1411
        push    edx
2288 clevermous 1412
        push    fat_notroot_extend_dir
1413
        push    fat_notroot_end_write
1414
        push    fat_notroot_next_write
1415
        push    fat_notroot_begin_write
1416
        push    0
2643 clevermous 1417
        push    edx
2288 clevermous 1418
        push    fat_notroot_first
1419
        push    fat_notroot_next
1420
.common1:
1421
        call    fat_find_lfn
1422
        jc      .notfound
1423
; found
1424
        test    byte [edi+11], 10h
1425
        jz      .exists_file
1426
; found directory; if we are creating directory, return OK,
1427
;                  if we are creating file, say "access denied"
2643 clevermous 1428
        add     esp, 36
1429
        call    fat_unlock
2288 clevermous 1430
        popad
1431
        test    al, al
1432
        mov     eax, ERROR_ACCESS_DENIED
1433
        jz      @f
1434
        mov     al, 0
1435
@@:
1436
        xor     ebx, ebx
1437
        ret
1438
.exists_file:
1439
; found file; if we are creating directory, return "access denied",
1440
;             if we are creating file, delete existing file and continue
2643 clevermous 1441
        cmp     byte [esp+36+28], 0
2288 clevermous 1442
        jz      @f
2643 clevermous 1443
        add     esp, 36
1444
        call    fat_unlock
2288 clevermous 1445
        popad
1446
        mov     eax, ERROR_ACCESS_DENIED
1447
        xor     ebx, ebx
1448
        ret
1449
@@:
1450
; delete FAT chain
1451
        push    edi
1452
        xor     eax, eax
1453
        mov     dword [edi+28], eax     ; zero size
1454
        xor     ecx, ecx
1455
        mov     eax, [edi+20-2]
1456
        mov     ax, [edi+26]
1457
        mov     word [edi+20], cx
1458
        mov     word [edi+26], cx
1459
        test    eax, eax
1460
        jz      .done1
1461
@@:
2643 clevermous 1462
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 1463
        jae     .done1
1464
        push    edx
1465
        xor     edx, edx
1466
        call    set_FAT
1467
        mov     eax, edx
1468
        pop     edx
2643 clevermous 1469
        jc      .done1
2288 clevermous 1470
        inc     ecx
1471
        jmp     @b
1472
.done1:
1473
        pop     edi
1474
        call    get_time_for_file
1475
        mov     [edi+22], ax
1476
        call    get_date_for_file
1477
        mov     [edi+24], ax
1478
        mov     [edi+18], ax
1479
        or      byte [edi+11], 20h      ; set 'archive' attribute
1480
        jmp     .doit
1481
.notfound:
1482
; file is not found; generate short name
1483
        call    fat_name_is_legal
1484
        jc      @f
2643 clevermous 1485
        add     esp, 36
1486
        call    fat_unlock
2288 clevermous 1487
        popad
1488
        mov     eax, ERROR_FILE_NOT_FOUND
1489
        xor     ebx, ebx
1490
        ret
1491
@@:
1492
        sub     esp, 12
1493
        mov     edi, esp
1494
        call    fat_gen_short_name
1495
.test_short_name_loop:
1496
        push    esi edi ecx
1497
        mov     esi, edi
1498
        lea     eax, [esp+12+12+8]
2643 clevermous 1499
        mov     edx, [eax+24]
1500
        mov     [eax], edx
2288 clevermous 1501
        and     dword [eax+4], 0
1502
        call    dword [eax-4]
1503
        jc      .found
1504
.test_short_name_entry:
1505
        cmp     byte [edi+11], 0xF
1506
        jz      .test_short_name_cont
1507
        mov     ecx, 11
1508
        push    esi edi
1509
        repz cmpsb
1510
        pop     edi esi
1511
        jz      .short_name_found
1512
.test_short_name_cont:
1513
        lea     eax, [esp+12+12+8]
1514
        call    dword [eax-8]
1515
        jnc     .test_short_name_entry
1516
        jmp     .found
1517
.short_name_found:
1518
        pop     ecx edi esi
1519
        call    fat_next_short_name
1520
        jnc     .test_short_name_loop
1521
.disk_full:
2643 clevermous 1522
        add     esp, 12+36
1523
        call    fat_unlock
2288 clevermous 1524
        popa
1525
        mov     eax, ERROR_DISK_FULL
1526
        xor     ebx, ebx
1527
        ret
1528
.found:
1529
        pop     ecx edi esi
1530
; now find space in directory
1531
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
1532
        mov     al, '~'
1533
        push    ecx edi
1534
        mov     ecx, 8
1535
        repnz scasb
3598 clevermous 1536
        movi    eax, 1     ; 1 entry
2288 clevermous 1537
        jnz     .notilde
1538
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
1539
        xor     eax, eax
1540
@@:
1541
        cmp     byte [esi], 0
1542
        jz      @f
1543
        inc     esi
1544
        inc     eax
1545
        jmp     @b
1546
@@:
1547
        sub     esi, eax
1548
        add     eax, 12+13
1549
        mov     ecx, 13
1550
        push    edx
1551
        cdq
1552
        div     ecx
1553
        pop     edx
1554
.notilde:
1555
        push    -1
1556
        push    -1
1557
        push    -1
1558
; find  successive entries in directory
1559
        xor     ecx, ecx
1560
        push    eax
1561
        lea     eax, [esp+16+8+12+8]
2643 clevermous 1562
        mov     edx, [eax+24]
1563
        mov     [eax], edx
2288 clevermous 1564
        and     dword [eax+4], 0
1565
        call    dword [eax-4]
1566
        pop     eax
1567
        jnc     .scan_dir
1568
.fsfrfe3:
2643 clevermous 1569
        add     esp, 12+8+12+36
1570
        call    fat_unlock
2288 clevermous 1571
        popad
2643 clevermous 1572
        mov     eax, ERROR_DEVICE
2288 clevermous 1573
        xor     ebx, ebx
1574
        ret
1575
.scan_dir:
1576
        cmp     byte [edi], 0
1577
        jz      .free
1578
        cmp     byte [edi], 0xE5
1579
        jz      .free
1580
        xor     ecx, ecx
1581
.scan_cont:
1582
        push    eax
1583
        lea     eax, [esp+16+8+12+8]
1584
        call    dword [eax-8]
2643 clevermous 1585
        mov     edx, eax
2288 clevermous 1586
        pop     eax
1587
        jnc     .scan_dir
2643 clevermous 1588
        cmp     edx, ERROR_DEVICE
1589
        jz      .fsfrfe3
2288 clevermous 1590
        push    eax
1591
        lea     eax, [esp+16+8+12+8]
1592
        call    dword [eax+20]          ; extend directory
1593
        pop     eax
1594
        jnc     .scan_dir
2643 clevermous 1595
        add     esp, 12+8+12+36
1596
        call    fat_unlock
2288 clevermous 1597
        popad
1598
        mov     eax, ERROR_DISK_FULL
1599
        xor     ebx, ebx
1600
        ret
1601
.free:
1602
        test    ecx, ecx
1603
        jnz     @f
1604
        mov     [esp], edi
1605
        mov     ecx, [esp+12+8+12+8]
1606
        mov     [esp+4], ecx
1607
        mov     ecx, [esp+12+8+12+12]
1608
        mov     [esp+8], ecx
1609
        xor     ecx, ecx
1610
@@:
1611
        inc     ecx
1612
        cmp     ecx, eax
1613
        jb      .scan_cont
1614
; found!
2643 clevermous 1615
        push    esi ecx
1616
; If creating a directory, allocate one data cluster now and fail immediately
1617
; if this is impossible. This prevents from creating an invalid directory entry
1618
; on a full disk.
1619
; yup, the argument is quite non-intuitive... but what should I do if
1620
; the entire function uses such arguments? BTW, it refers to al from pushad,
1621
; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
1622
        cmp     byte [esp+8+12+8+12+36+28], 0
1623
        jz      .no.preallocate.folder.data
1624
        call    get_free_FAT
1625
        jnc     @f
1626
        add     esp, 8+12+8
1627
        jmp     .disk_full
1628
@@:
1629
        mov     [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
1630
.no.preallocate.folder.data:
2288 clevermous 1631
; calculate name checksum
1632
        mov     esi, [esp+8+12]
1633
        mov     ecx, 11
1634
        xor     eax, eax
1635
@@:
1636
        ror     al, 1
1637
        add     al, [esi]
1638
        inc     esi
1639
        loop    @b
1640
        pop     ecx esi
1641
        pop     edi
1642
        pop     dword [esp+8+12+12]
1643
        pop     dword [esp+8+12+12]
1644
; edi points to first entry in free chunk
1645
        dec     ecx
1646
        jz      .nolfn
1647
        push    esi
1648
        push    eax
1649
        lea     eax, [esp+8+8+12+8]
1650
        call    dword [eax+8]         ; begin write
1651
        mov     al, 40h
1652
.writelfn:
1653
        or      al, cl
1654
        mov     esi, [esp+4]
1655
        push    ecx
1656
        dec     ecx
1657
        imul    ecx, 13
1658
        add     esi, ecx
1659
        stosb
1660
        mov     cl, 5
1661
        call    fs_RamdiskRewrite.read_symbols
1662
        mov     ax, 0xF
1663
        stosw
1664
        mov     al, [esp+4]
1665
        stosb
1666
        mov     cl, 6
1667
        call    fs_RamdiskRewrite.read_symbols
1668
        xor     eax, eax
1669
        stosw
1670
        mov     cl, 2
1671
        call    fs_RamdiskRewrite.read_symbols
1672
        pop     ecx
1673
        lea     eax, [esp+8+8+12+8]
1674
        call    dword [eax+12]         ; next write
1675
        xor     eax, eax
1676
        loop    .writelfn
1677
        pop     eax
1678
        pop     esi
1679
;        lea     eax, [esp+8+12+8]
1680
;        call    dword [eax+16]          ; end write
1681
.nolfn:
1682
        xchg    esi, [esp]
1683
        mov     ecx, 11
1684
        rep movsb
1685
        mov     word [edi], 20h         ; attributes
1686
        sub     edi, 11
1687
        pop     esi ecx
1688
        add     esp, 12
1689
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1690
        call    get_time_for_file
1691
        mov     [edi+14], ax            ; creation time
1692
        mov     [edi+22], ax            ; last write time
1693
        call    get_date_for_file
1694
        mov     [edi+16], ax            ; creation date
1695
        mov     [edi+24], ax            ; last write date
1696
        mov     [edi+18], ax            ; last access date
1697
        xor     ecx, ecx
1698
        mov     word [edi+20], cx       ; high word of cluster
1699
        mov     word [edi+26], cx       ; low word of cluster - to be filled
1700
        mov     dword [edi+28], ecx     ; file size - to be filled
2643 clevermous 1701
        cmp     byte [esp+36+28], cl
2288 clevermous 1702
        jz      .doit
1703
; create directory
1704
        mov     byte [edi+11], 10h      ; attributes: folder
2643 clevermous 1705
        mov     esi, edi
2288 clevermous 1706
        lea     eax, [esp+8]
1707
        call    dword [eax+16]  ; flush directory
2643 clevermous 1708
        mov     eax, [esp+36+20] ; extract saved cluster
1709
        mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
2288 clevermous 1710
        push    ecx
2643 clevermous 1711
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1712
        shl     ecx, 9
2643 clevermous 1713
        push    ecx
1714
        push    edi
2288 clevermous 1715
        jmp     .doit2
1716
.doit:
2643 clevermous 1717
        mov     esi, [esp+36+20]
2288 clevermous 1718
        lea     eax, [esp+8]
1719
        call    dword [eax+16]  ; flush directory
1720
        push    ecx
2643 clevermous 1721
        mov     ecx, [esp+4+36+24]
2288 clevermous 1722
        push    ecx
1723
        push    edi
1724
        test    ecx, ecx
1725
        jz      .done
1726
        call    get_free_FAT
1727
        jc      .diskfull
2643 clevermous 1728
.doit2:
2288 clevermous 1729
        push    eax
1730
        mov     [edi+26], ax
1731
        shr     eax, 16
1732
        mov     [edi+20], ax
1733
        lea     eax, [esp+16+8]
1734
        call    dword [eax+16]  ; flush directory
1735
        pop     eax
1736
        push    edx
2643 clevermous 1737
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 1738
        call    set_FAT
1739
        pop     edx
1740
.write_cluster:
1741
        push    eax
1742
        dec     eax
1743
        dec     eax
2643 clevermous 1744
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1745
        add     eax, [ebp+FAT.DATA_START]
1746
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1747
; write data
1748
.write_sector:
2643 clevermous 1749
        cmp     byte [esp+20+36+28], 0
2288 clevermous 1750
        jnz     .writedir
1751
        mov     ecx, 512
2643 clevermous 1752
        cmp     dword [esp+12], ecx
2288 clevermous 1753
        jb      .writeshort
1754
; we can write directly from given buffer
1755
        mov     ebx, esi
1756
        add     esi, ecx
1757
        jmp     .writecommon
1758
.writeshort:
2643 clevermous 1759
        mov     ecx, [esp+12]
2288 clevermous 1760
        push    ecx
2643 clevermous 1761
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1762
        mov     ebx, edi
1763
        rep movsb
1764
.writedircont:
2643 clevermous 1765
        lea     ecx, [ebp+FAT.buffer+0x200]
2288 clevermous 1766
        sub     ecx, edi
1767
        push    eax
1768
        xor     eax, eax
1769
        rep stosb
1770
        pop     eax
1771
        pop     ecx
1772
.writecommon:
2643 clevermous 1773
        push    eax
1774
        call    fs_write32_app
1775
        test    eax, eax
1776
        pop     eax
2288 clevermous 1777
        jnz     .writeerr
1778
        inc     eax
2643 clevermous 1779
        sub     dword [esp+12], ecx
2288 clevermous 1780
        jz      .writedone
2643 clevermous 1781
        dec     dword [esp]
2288 clevermous 1782
        jnz     .write_sector
2643 clevermous 1783
        pop     eax
2288 clevermous 1784
; allocate new cluster
1785
        pop     eax
1786
        mov     ecx, eax
1787
        call    get_free_FAT
1788
        jc      .diskfull
1789
        push    edx
2643 clevermous 1790
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 1791
        call    set_FAT
1792
        xchg    eax, ecx
1793
        mov     edx, ecx
1794
        call    set_FAT
1795
        pop     edx
1796
        xchg    eax, ecx
1797
        jmp     .write_cluster
1798
.diskfull:
1799
        mov     eax, ERROR_DISK_FULL
1800
        jmp     .ret
1801
.writeerr:
2643 clevermous 1802
        pop     eax eax
2288 clevermous 1803
        sub     esi, ecx
2643 clevermous 1804
        mov     eax, ERROR_DEVICE
2288 clevermous 1805
        jmp     .ret
1806
.writedone:
2643 clevermous 1807
        pop     eax eax
2288 clevermous 1808
.done:
1809
        xor     eax, eax
1810
.ret:
1811
        pop     edi ecx
2643 clevermous 1812
        sub     esi, [esp+4+36+20]
1813
        mov     [esp+4+36+28], eax
1814
        mov     [esp+4+36+16], esi
1815
        lea     eax, [esp+12]
2288 clevermous 1816
        call    dword [eax+8]
2643 clevermous 1817
        mov     [edi+28], esi
2288 clevermous 1818
        call    dword [eax+16]
2643 clevermous 1819
        mov     [esp+36+16], ebx
1820
        lea     eax, [esi+511]
2288 clevermous 1821
        shr     eax, 9
2643 clevermous 1822
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1823
        lea     eax, [eax+ecx-1]
1824
        xor     edx, edx
1825
        div     ecx
2643 clevermous 1826
        pop     ecx
2288 clevermous 1827
        sub     ecx, eax
1828
        call    add_disk_free_space
2643 clevermous 1829
        add     esp, 36
2288 clevermous 1830
        call    update_disk
2643 clevermous 1831
        call    fat_unlock
2288 clevermous 1832
        popad
1833
        ret
1834
.writedir:
1835
        push    512
2643 clevermous 1836
        lea     edi, [ebp+FAT.buffer]
2288 clevermous 1837
        mov     ebx, edi
2643 clevermous 1838
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 1839
        shl     ecx, 9
2643 clevermous 1840
        cmp     ecx, [esp+16]
2288 clevermous 1841
        jnz     .writedircont
2643 clevermous 1842
        dec     dword [esp+20]
2288 clevermous 1843
        push    esi
1844
        mov     ecx, 32/4
1845
        rep movsd
1846
        pop     esi
1847
        mov     dword [edi-32], '.   '
1848
        mov     dword [edi-32+4], '    '
1849
        mov     dword [edi-32+8], '    '
1850
        mov     byte [edi-32+11], 10h
1851
        push    esi
1852
        mov     ecx, 32/4
1853
        rep movsd
1854
        pop     esi
1855
        mov     dword [edi-32], '..  '
1856
        mov     dword [edi-32+4], '    '
1857
        mov     dword [edi-32+8], '    '
1858
        mov     byte [edi-32+11], 10h
2643 clevermous 1859
        mov     ecx, [esp+20+36]
1860
        cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
2288 clevermous 1861
        jnz     @f
1862
        xor     ecx, ecx
1863
@@:
1864
        mov     word [edi-32+26], cx
1865
        shr     ecx, 16
1866
        mov     [edi-32+20], cx
1867
        jmp     .writedircont
1868
 
2643 clevermous 1869
fat_Write.access_denied:
2288 clevermous 1870
        push    ERROR_ACCESS_DENIED
3742 clevermous 1871
fat_Write.ret0:
2288 clevermous 1872
        pop     eax
1873
        xor     ebx, ebx
1874
        ret
1875
 
3742 clevermous 1876
fat_Write.ret11:
2643 clevermous 1877
        push    ERROR_DEVICE
3742 clevermous 1878
        jmp     fat_Write.ret0
2288 clevermous 1879
 
2643 clevermous 1880
;----------------------------------------------------------------
1881
; fat_Write - FAT16/32 implementation of writing to file
1882
; in:  ebp = pointer to FAT structure
1883
; in:  esi+[esp+4] = name
1884
; in:  ebx = pointer to parameters from sysfunc 70
1885
; out: eax, ebx = return values for sysfunc 70
1886
;----------------------------------------------------------------
1887
fat_Write:
2288 clevermous 1888
        cmp     byte [esi], 0
1889
        jz      .access_denied
2643 clevermous 1890
        call    fat_lock
1891
        push    edi
1892
        stdcall hd_find_lfn, [esp+4+4]
2288 clevermous 1893
        jnc     .found
2643 clevermous 1894
        pop     edi
1895
        push    eax
1896
        call    fat_unlock
3742 clevermous 1897
        jmp     .ret0
2288 clevermous 1898
.found:
1899
; FAT does not support files larger than 4GB
2643 clevermous 1900
        cmp     dword [ebx+8], 0
2288 clevermous 1901
        jz      @f
1902
.eof:
2643 clevermous 1903
        pop     edi
2288 clevermous 1904
        push    ERROR_END_OF_FILE
2643 clevermous 1905
        call    fat_unlock
3742 clevermous 1906
        jmp     .ret0
2288 clevermous 1907
@@:
2643 clevermous 1908
        mov     ecx, [ebx+12]
1909
        mov     edx, [ebx+16]
1910
        mov     ebx, [ebx+4]
2288 clevermous 1911
; now edi points to direntry, ebx=start byte to write,
1912
; ecx=number of bytes to write, edx=data pointer
1913
 
1914
; extend file if needed
1915
        add     ecx, ebx
1916
        jc      .eof    ; FAT does not support files larger than 4GB
2643 clevermous 1917
        push    edx
2288 clevermous 1918
        push    eax     ; save directory sector
1919
        push    0       ; return value=0
1920
 
1921
        call    get_time_for_file
1922
        mov     [edi+22], ax            ; last write time
1923
        call    get_date_for_file
1924
        mov     [edi+24], ax            ; last write date
1925
        mov     [edi+18], ax            ; last access date
1926
 
1927
        push    dword [edi+28]          ; save current file size
1928
        cmp     ecx, [edi+28]
1929
        jbe     .length_ok
1930
        cmp     ecx, ebx
1931
        jz      .length_ok
1932
        call    hd_extend_file
1933
        jnc     .length_ok
1934
        mov     [esp+4], eax
1935
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
1936
; First two cases are fatal errors, in third case we may write some data
1937
        cmp     al, ERROR_DISK_FULL
1938
        jz      .disk_full
2643 clevermous 1939
        call    fat_unlock
2288 clevermous 1940
        pop     eax
1941
        pop     eax
2643 clevermous 1942
        pop     ecx
1943
        pop     edx
1944
        pop     edi
2288 clevermous 1945
        xor     ebx, ebx
1946
        ret
1947
.disk_full:
1948
; correct number of bytes to write
1949
        mov     ecx, [edi+28]
1950
        cmp     ecx, ebx
1951
        ja      .length_ok
2643 clevermous 1952
        push    0
2288 clevermous 1953
.ret:
2643 clevermous 1954
        pop     eax
1955
        sub     edx, [esp+12]
1956
        mov     ebx, edx        ; ebx=number of written bytes
2288 clevermous 1957
        call    update_disk
2643 clevermous 1958
        test    eax, eax
2288 clevermous 1959
        jz      @f
2643 clevermous 1960
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 1961
@@:
2643 clevermous 1962
        call    fat_unlock
2288 clevermous 1963
        pop     eax
1964
        pop     eax
2643 clevermous 1965
        pop     ecx
1966
        pop     edx
1967
        pop     edi
2288 clevermous 1968
        ret
1969
.length_ok:
1970
        mov     esi, [edi+28]
1971
        mov     eax, [edi+20-2]
1972
        mov     ax, [edi+26]
1973
        mov     edi, eax        ; edi=current cluster
2643 clevermous 1974
        push    0               ; current sector in cluster
2288 clevermous 1975
; save directory
2643 clevermous 1976
        mov     eax, [esp+12]
2288 clevermous 1977
        push    ebx
2643 clevermous 1978
        lea     ebx, [ebp+FAT.buffer]
1979
        call    fs_write32_sys
2288 clevermous 1980
        pop     ebx
2643 clevermous 1981
        test    eax, eax
2288 clevermous 1982
        jz      @f
1983
.device_err:
2643 clevermous 1984
        mov     byte [esp+8], ERROR_DEVICE
2288 clevermous 1985
        jmp     .ret
2643 clevermous 1986
.fat_err:
1987
        mov     byte [esp+8], ERROR_FAT_TABLE
1988
        jmp     .ret
2288 clevermous 1989
@@:
1990
 
1991
; now ebx=start pos, ecx=end pos, both lie inside file
1992
        sub     ecx, ebx
1993
        jz      .ret
1994
.write_loop:
1995
; skip unmodified sectors
2643 clevermous 1996
        cmp     dword [esp+4], 0x200
2288 clevermous 1997
        jb      .modify
1998
        sub     ebx, 0x200
1999
        jae     .skip
2000
        add     ebx, 0x200
2001
.modify:
2002
; get length of data in current sector
2003
        push    ecx
2004
        sub     ebx, 0x200
2005
        jb      .hasdata
2006
        neg     ebx
2007
        xor     ecx, ecx
2008
        jmp     @f
2009
.hasdata:
2010
        neg     ebx
2011
        cmp     ecx, ebx
2012
        jbe     @f
2013
        mov     ecx, ebx
2014
@@:
2015
; get current sector number
2016
        mov     eax, edi
2017
        dec     eax
2018
        dec     eax
2643 clevermous 2019
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2020
        add     eax, [ebp+FAT.DATA_START]
2021
        add     eax, [esp+4]
2288 clevermous 2022
; load sector if needed
2643 clevermous 2023
        cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
2288 clevermous 2024
        jz      .noread
2025
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
2026
        jz      .noread
2027
        cmp     ecx, esi        ; (same for the last sector)
2028
        jz      .noread
2643 clevermous 2029
        push    eax ebx
2030
        lea     ebx, [ebp+FAT.buffer]
2031
        call    fs_read32_app
2032
        test    eax, eax
2033
        pop     ebx eax
2288 clevermous 2034
        jz      @f
2035
.device_err2:
2036
        pop     ecx
2037
        jmp     .device_err
2038
@@:
2039
.noread:
2040
; zero uninitialized data if file was extended (because hd_extend_file does not this)
2041
        push    eax ecx edi
2042
        xor     eax, eax
2043
        mov     ecx, 0x200
2643 clevermous 2044
        sub     ecx, [esp+8+12]
2288 clevermous 2045
        jbe     @f
2643 clevermous 2046
        lea     edi, [ebp+FAT.buffer]
2047
        add     edi, [esp+8+12]
2288 clevermous 2048
        rep stosb
2049
@@:
2050
; zero uninitialized data in the last sector
2051
        mov     ecx, 0x200
2052
        sub     ecx, esi
2053
        jbe     @f
2643 clevermous 2054
        lea     edi, [ebp+FAT.buffer+esi]
2288 clevermous 2055
        rep stosb
2056
@@:
2057
        pop     edi ecx
2058
; copy new data
2059
        mov     eax, edx
2060
        neg     ebx
2061
        jecxz   @f
2643 clevermous 2062
        lea     ebx, [ebp+FAT.buffer+0x200+ebx]
2288 clevermous 2063
        call    memmove
2064
        xor     ebx, ebx
2065
@@:
2066
        pop     eax
2067
; save sector
2068
        push    ebx
2643 clevermous 2069
        lea     ebx, [ebp+FAT.buffer]
2070
        call    fs_write32_app
2288 clevermous 2071
        pop     ebx
2643 clevermous 2072
        test    eax, eax
2288 clevermous 2073
        jnz     .device_err2
2074
        add     edx, ecx
2075
        sub     [esp], ecx
2076
        pop     ecx
2077
        jz      .ret
2078
.skip:
2079
; next sector
2643 clevermous 2080
        pop     eax
2081
        inc     eax
2082
        push    eax
2083
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2084
        jb      @f
2643 clevermous 2085
        and     dword [esp], 0
2288 clevermous 2086
        mov     eax, edi
2087
        call    get_FAT
2088
        mov     edi, eax
2643 clevermous 2089
        jc      .device_err
2090
        cmp     edi, 2
2091
        jb      .fat_err
2092
        cmp     edi, [ebp+FAT.fatRESERVED]
2093
        jae     .fat_err
2288 clevermous 2094
@@:
2095
        sub     esi, 0x200
2096
        jae     @f
2097
        xor     esi, esi
2098
@@:
2643 clevermous 2099
        sub     dword [esp+4], 0x200
2288 clevermous 2100
        jae     @f
2643 clevermous 2101
        and     dword [esp+4], 0
2288 clevermous 2102
@@:
2103
        jmp     .write_loop
2104
 
2105
hd_extend_file.zero_size:
2106
        xor     eax, eax
2107
        jmp     hd_extend_file.start_extend
2108
 
2109
; extends file on hd to given size (new data area is undefined)
2110
; in: edi->direntry, ecx=new size
2111
; out: CF=0 => OK, eax=0
2643 clevermous 2112
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
2288 clevermous 2113
hd_extend_file:
2643 clevermous 2114
        push    esi
2115
        mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
2116
        imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
2288 clevermous 2117
        push    ecx
2118
; find the last cluster of file
2119
        mov     eax, [edi+20-2]
2120
        mov     ax, [edi+26]
2121
        mov     ecx, [edi+28]
2122
        jecxz   .zero_size
2123
.last_loop:
2643 clevermous 2124
        sub     ecx, esi
2288 clevermous 2125
        jbe     .last_found
2126
        call    get_FAT
2643 clevermous 2127
        jnc     @f
2288 clevermous 2128
.device_err:
2129
        pop     ecx
2130
.device_err2:
2643 clevermous 2131
        pop     esi
2132
        push    ERROR_DEVICE
2288 clevermous 2133
.ret_err:
2134
        pop     eax
2135
        stc
2136
        ret
2137
@@:
2138
        cmp     eax, 2
2139
        jb      .fat_err
2643 clevermous 2140
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2141
        jb      .last_loop
2142
.fat_err:
2643 clevermous 2143
        pop     ecx esi
2288 clevermous 2144
        push    ERROR_FAT_TABLE
2145
        jmp     .ret_err
2146
.last_found:
2147
        push    eax
2148
        call    get_FAT
2643 clevermous 2149
        jnc     @f
2288 clevermous 2150
        pop     eax
2151
        jmp     .device_err
2152
@@:
2643 clevermous 2153
        cmp     eax, [ebp+FAT.fatRESERVED]
2288 clevermous 2154
        pop     eax
2155
        jb      .fat_err
2156
; set length to full number of clusters
2157
        sub     [edi+28], ecx
2158
.start_extend:
2159
        pop     ecx
2160
; now do extend
2161
        push    edx
2162
        mov     edx, 2          ; start scan from cluster 2
2163
.extend_loop:
2164
        cmp     [edi+28], ecx
2165
        jae     .extend_done
2166
; add new cluster
2167
        push    eax
2168
        call    get_free_FAT
2169
        jc      .disk_full
2643 clevermous 2170
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2171
        call    set_FAT
2172
        mov     edx, eax
2173
        pop     eax
2174
        test    eax, eax
2175
        jz      .first_cluster
2176
        push    edx
2177
        call    set_FAT
2178
        pop     edx
2179
        jmp     @f
2180
.first_cluster:
2181
        ror     edx, 16
2182
        mov     [edi+20], dx
2183
        ror     edx, 16
2184
        mov     [edi+26], dx
2185
@@:
2186
        push    ecx
2187
        mov     ecx, -1
2188
        call    add_disk_free_space
2189
        pop     ecx
2190
        mov     eax, edx
2643 clevermous 2191
        add     [edi+28], esi
2288 clevermous 2192
        jmp     .extend_loop
2193
.extend_done:
2194
        mov     [edi+28], ecx
2643 clevermous 2195
        pop     edx esi
2288 clevermous 2196
        xor     eax, eax        ; CF=0
2197
        ret
2198
.device_err3:
2199
        pop     edx
2200
        jmp     .device_err2
2201
.disk_full:
2643 clevermous 2202
        pop     eax edx esi
3598 clevermous 2203
        movi    eax, ERROR_DISK_FULL
2288 clevermous 2204
        stc
2205
        ret
2206
 
2207
;----------------------------------------------------------------
2643 clevermous 2208
; fat_SetFileEnd - FAT16/32 implementation of setting end-of-file
2209
; in:  ebp = pointer to FAT structure
2210
; in:  esi+[esp+4] = name
2211
; in:  ebx = pointer to parameters from sysfunc 70
2212
; out: eax, ebx = return values for sysfunc 70
2213
;----------------------------------------------------------------
2214
fat_SetFileEnd:
2215
        call    fat_lock
2216
        push    edi
2288 clevermous 2217
        cmp     byte [esi], 0
2218
        jnz     @f
2219
.access_denied:
2220
        push    ERROR_ACCESS_DENIED
2643 clevermous 2221
.ret:
2222
        call    fat_unlock
2223
        pop     eax
2224
        pop     edi
2225
        ret
2288 clevermous 2226
@@:
2643 clevermous 2227
        stdcall hd_find_lfn, [esp+4+4]
2288 clevermous 2228
        jnc     @f
2643 clevermous 2229
.reteax:
2230
        push    eax
2288 clevermous 2231
        jmp     .ret
2232
@@:
2233
; must not be directory
2234
        test    byte [edi+11], 10h
2643 clevermous 2235
        jnz     .access_denied
2288 clevermous 2236
; file size must not exceed 4 Gb
2643 clevermous 2237
        cmp     dword [ebx+8], 0
2288 clevermous 2238
        jz      @f
2239
        push    ERROR_END_OF_FILE
2240
        jmp     .ret
2241
@@:
2242
        push    eax     ; save directory sector
2243
; set file modification date/time to current
2244
        call    fat_update_datetime
2643 clevermous 2245
        mov     eax, [ebx+4]
2288 clevermous 2246
        cmp     eax, [edi+28]
2247
        jb      .truncate
2248
        ja      .expand
2249
        pop     eax
2643 clevermous 2250
        lea     ebx, [ebp+FAT.buffer]
2251
        call    fs_write32_sys
2252
        test    eax, eax
2288 clevermous 2253
        jz      @f
2643 clevermous 2254
        push    ERROR_DEVICE
2255
        jmp     .ret
2288 clevermous 2256
@@:
2643 clevermous 2257
        push    0
2258
        jmp     .ret
2288 clevermous 2259
.expand:
2260
        push    ebx ebp ecx
2261
        push    dword [edi+28]  ; save old size
2262
        mov     ecx, eax
2263
        call    hd_extend_file
2264
        push    eax             ; return code
2265
        jnc     .expand_ok
2266
        cmp     al, ERROR_DISK_FULL
2267
        jz      .disk_full
2268
.pop_ret:
2269
        call    update_disk
2643 clevermous 2270
        pop     eax ecx ecx ebp ebx ecx
2271
        jmp     .reteax
2288 clevermous 2272
.expand_ok:
2273
.disk_full:
2274
; save directory
2275
        mov     eax, [edi+28]
2276
        xchg    eax, [esp+20]
2643 clevermous 2277
        lea     ebx, [ebp+FAT.buffer]
2278
        call    fs_write32_sys
2279
        test    eax, eax
2288 clevermous 2280
        mov     eax, [edi+20-2]
2281
        mov     ax, [edi+26]
2282
        mov     edi, eax
2283
        jz      @f
2284
.pop_ret11:
2643 clevermous 2285
        mov     byte [esp], ERROR_DEVICE
2288 clevermous 2286
        jmp     .pop_ret
2287
@@:
2643 clevermous 2288
        test    edi, edi
2289
        jz      .pop_ret
2288 clevermous 2290
; now zero new data
2643 clevermous 2291
        push    0
2292
; edi=current cluster, [esp]=sector in cluster
2293
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
2288 clevermous 2294
.zero_loop:
2643 clevermous 2295
        cmp     edi, 2
2296
        jb      .error_fat
2297
        cmp     edi, [ebp+FAT.fatRESERVED]
2298
        jae     .error_fat
2299
        sub     dword [esp+8], 0x200
2288 clevermous 2300
        jae     .next_cluster
2301
        lea     eax, [edi-2]
2643 clevermous 2302
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2303
        add     eax, [ebp+FAT.DATA_START]
2304
        add     eax, [esp]
2305
        cmp     dword [esp+8], -0x200
2288 clevermous 2306
        jz      .noread
2643 clevermous 2307
        push    eax
2308
        lea     ebx, [ebp+FAT.buffer]
2309
        call    fs_read32_app
2310
        test    eax, eax
2311
        pop     eax
2288 clevermous 2312
        jnz     .err_next
2313
.noread:
2643 clevermous 2314
        mov     ecx, [esp+8]
2288 clevermous 2315
        neg     ecx
2316
        push    edi
2643 clevermous 2317
        lea     edi, [ebp+FAT.buffer+0x200]
2318
        add     edi, [esp+12]
2288 clevermous 2319
        push    eax
2320
        xor     eax, eax
2643 clevermous 2321
        mov     [esp+16], eax
2288 clevermous 2322
        rep stosb
2323
        pop     eax
2324
        pop     edi
2643 clevermous 2325
        call    fs_write32_app
2326
        test    eax, eax
2288 clevermous 2327
        jz      .next_cluster
2328
.err_next:
2643 clevermous 2329
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 2330
.next_cluster:
2643 clevermous 2331
        pop     eax
2288 clevermous 2332
        sub     dword [esp+20], 0x200
2333
        jbe     .pop_ret
2643 clevermous 2334
        inc     eax
2335
        push    eax
2336
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2337
        jb      .zero_loop
2643 clevermous 2338
        and     dword [esp], 0
2288 clevermous 2339
        mov     eax, edi
2340
        call    get_FAT
2341
        mov     edi, eax
2643 clevermous 2342
        jnc     .zero_loop
2343
        pop     eax
2344
        jmp     .pop_ret11
2288 clevermous 2345
.truncate:
2346
        mov     [edi+28], eax
2347
        push    ecx
2348
        mov     ecx, [edi+20-2]
2349
        mov     cx, [edi+26]
2350
        push    eax
2351
        test    eax, eax
2352
        jz      .zero_size
2353
; find new last cluster
2354
@@:
2643 clevermous 2355
        cmp     ecx, 2
2356
        jb      .error_fat2
2357
        cmp     ecx, [ebp+FAT.fatRESERVED]
2358
        jae     .error_fat2
2359
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2360
        shl     eax, 9
2361
        sub     [esp], eax
2362
        jbe     @f
2363
        mov     eax, ecx
2364
        call    get_FAT
2365
        mov     ecx, eax
2643 clevermous 2366
        jnc     @b
2288 clevermous 2367
.device_err3:
2368
        pop     eax ecx eax edi
2643 clevermous 2369
        call    update_disk
2370
        call    fat_unlock
3598 clevermous 2371
        movi    eax, ERROR_DEVICE
2288 clevermous 2372
        ret
2373
@@:
2374
; we will zero data at the end of last sector - remember it
2375
        push    ecx
2376
; terminate FAT chain
2377
        push    edx
2378
        mov     eax, ecx
2643 clevermous 2379
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2380
        call    set_FAT
2381
        mov     eax, edx
2382
        pop     edx
2643 clevermous 2383
        jnc     @f
2288 clevermous 2384
.device_err4:
2385
        pop     ecx
2386
        jmp     .device_err3
2387
.zero_size:
2388
        and     word [edi+20], 0
2389
        and     word [edi+26], 0
2390
        push    0
2391
        mov     eax, ecx
2392
@@:
2393
; delete FAT chain
2394
        call    clear_cluster_chain
2643 clevermous 2395
        jc      .device_err4
2288 clevermous 2396
; save directory
2397
        mov     eax, [esp+12]
2398
        push    ebx
2643 clevermous 2399
        lea     ebx, [ebp+FAT.buffer]
2400
        call    fs_write32_sys
2288 clevermous 2401
        pop     ebx
2643 clevermous 2402
        test    eax, eax
2288 clevermous 2403
        jnz     .device_err4
2404
; zero last sector, ignore errors
2405
        pop     ecx
2406
        pop     eax
2407
        dec     ecx
2643 clevermous 2408
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2409
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 2410
        push    eax
2411
        sar     eax, 9
2412
        add     ecx, eax
2413
        pop     eax
2414
        and     eax, 0x1FF
2415
        jz      .truncate_done
2416
        push    ebx eax
2417
        mov     eax, ecx
2643 clevermous 2418
        lea     ebx, [ebp+FAT.buffer]
2419
        call    fs_read32_app
2288 clevermous 2420
        pop     eax
2643 clevermous 2421
        lea     edi, [ebp+FAT.buffer+eax]
2288 clevermous 2422
        push    ecx
2423
        mov     ecx, 0x200
2424
        sub     ecx, eax
2425
        xor     eax, eax
2426
        rep stosb
2427
        pop     eax
2643 clevermous 2428
        call    fs_write32_app
2288 clevermous 2429
        pop     ebx
2430
.truncate_done:
2431
        pop     ecx eax edi
2432
        call    update_disk
2643 clevermous 2433
        call    fat_unlock
2288 clevermous 2434
        xor     eax, eax
2435
        ret
2643 clevermous 2436
.error_fat:
2437
        pop     eax
2438
        mov     byte [esp], ERROR_FAT_TABLE
2439
        jmp     .pop_ret
2440
.error_fat2:
2441
        pop     eax ecx eax edi
2442
        call    update_disk
2443
        call    fat_unlock
3598 clevermous 2444
        movi    eax, ERROR_FAT_TABLE
2643 clevermous 2445
        ret
2288 clevermous 2446
 
2643 clevermous 2447
;----------------------------------------------------------------
2448
; fat_GetFileInfo - FAT16/32 implementation of getting file info
2449
; in:  ebp = pointer to FAT structure
2450
; in:  esi+[esp+4] = name
2451
; in:  ebx = pointer to parameters from sysfunc 70
2452
; out: eax, ebx = return values for sysfunc 70
2453
;----------------------------------------------------------------
2454
fat_GetFileInfo:
2288 clevermous 2455
        cmp     byte [esi], 0
2456
        jnz     @f
2457
        mov     eax, 2
2458
        ret
2459
@@:
2460
        push    edi
2643 clevermous 2461
        call    fat_lock
2462
        stdcall hd_find_lfn, [esp+4+4]
2463
        jc      .error
2464
        push    ebp
2465
        xor     ebp, ebp
2466
        mov     esi, [ebx+16]
2467
        mov     dword [esi+4], ebp
2468
        call    fat_entry_to_bdfe2
2469
        pop     ebp
2470
        call    fat_unlock
2471
        xor     eax, eax
2288 clevermous 2472
        pop     edi
2473
        ret
2643 clevermous 2474
.error:
2475
        push    eax
2476
        call    fat_unlock
2477
        pop     eax
2478
        pop     edi
2479
        ret
2288 clevermous 2480
 
2643 clevermous 2481
;----------------------------------------------------------------
2482
; fat_SetFileInfo - FAT16/32 implementation of setting file info
2483
; in:  ebp = pointer to FAT structure
2484
; in:  esi+[esp+4] = name
2485
; in:  ebx = pointer to parameters from sysfunc 70
2486
; out: eax, ebx = return values for sysfunc 70
2487
;----------------------------------------------------------------
2488
fat_SetFileInfo:
2288 clevermous 2489
        cmp     byte [esi], 0
2490
        jnz     @f
2491
        mov     eax, 2
2492
        ret
2493
@@:
2494
        push    edi
2643 clevermous 2495
        call    fat_lock
2496
        stdcall hd_find_lfn, [esp+4+4]
2497
        jc      .error
2288 clevermous 2498
        push    eax
2643 clevermous 2499
        mov     edx, [ebx+16]
2288 clevermous 2500
        call    bdfe_to_fat_entry
2501
        pop     eax
2643 clevermous 2502
        lea     ebx, [ebp+FAT.buffer]
2503
        call    fs_write32_sys
2288 clevermous 2504
        call    update_disk
2643 clevermous 2505
        call    fat_unlock
2288 clevermous 2506
        pop     edi
2507
        xor     eax, eax
2508
        ret
2643 clevermous 2509
.error:
2510
        push    eax
2511
        call    fat_unlock
2512
        pop     eax
2513
        pop     edi
2514
        ret
2288 clevermous 2515
 
2516
;----------------------------------------------------------------
2643 clevermous 2517
; fat_Delete - FAT16/32 implementation of deleting a file/folder
2518
; in:  ebp = pointer to FAT structure
2519
; in:  esi+[esp+4] = name
2520
; in:  ebx = pointer to parameters from sysfunc 70
2521
; out: eax, ebx = return values for sysfunc 70
2522
;----------------------------------------------------------------
2523
fat_Delete:
2524
        call    fat_lock
2288 clevermous 2525
        cmp     byte [esi], 0
2526
        jnz     @f
2527
; cannot delete root!
2528
.access_denied:
2529
        push    ERROR_ACCESS_DENIED
2643 clevermous 2530
.pop_ret:
2531
        call    fat_unlock
2532
        pop     eax
2533
        xor     ebx, ebx
2534
        ret
2288 clevermous 2535
@@:
2643 clevermous 2536
        and     [ebp+FAT.longname_sec1], 0
2537
        and     [ebp+FAT.longname_sec2], 0
2288 clevermous 2538
        push    edi
2643 clevermous 2539
        stdcall hd_find_lfn, [esp+4+4]
2288 clevermous 2540
        jnc     .found
2541
        pop     edi
2542
        push    ERROR_FILE_NOT_FOUND
2543
        jmp     .pop_ret
2544
.found:
2545
        cmp     dword [edi], '.   '
2546
        jz      .access_denied2
2547
        cmp     dword [edi], '..  '
2548
        jz      .access_denied2
2549
        test    byte [edi+11], 10h
2550
        jz      .dodel
2551
; we can delete only empty folders!
2552
        pushad
2643 clevermous 2553
        mov     esi, [edi+20-2]
2554
        mov     si, [edi+26]
2288 clevermous 2555
        xor     ecx, ecx
2643 clevermous 2556
        lea     eax, [esi-2]
2557
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2558
        add     eax, [ebp+FAT.DATA_START]
2559
        lea     ebx, [ebp+FAT.buffer]
2560
        call    fs_read32_sys
2561
        test    eax, eax
2288 clevermous 2562
        jnz     .err1
2643 clevermous 2563
        lea     eax, [ebx+0x200]
2288 clevermous 2564
        add     ebx, 2*0x20
2565
.checkempty:
2566
        cmp     byte [ebx], 0
2567
        jz      .empty
2568
        cmp     byte [ebx], 0xE5
2569
        jnz     .notempty
2570
        add     ebx, 0x20
2643 clevermous 2571
        cmp     ebx, eax
2288 clevermous 2572
        jb      .checkempty
2573
        inc     ecx
2643 clevermous 2574
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2575
        jb      @f
2643 clevermous 2576
        mov     eax, esi
2288 clevermous 2577
        call    get_FAT
2643 clevermous 2578
        jc      .err1
3174 clevermous 2579
        cmp     eax, 2
2580
        jb      .error_fat
2581
        cmp     eax, [ebp+FAT.fatRESERVED]
2582
        jae     .empty
2643 clevermous 2583
        mov     esi, eax
2288 clevermous 2584
        xor     ecx, ecx
2585
@@:
2643 clevermous 2586
        lea     eax, [esi-2]
2587
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2588
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 2589
        add     eax, ecx
2643 clevermous 2590
        lea     ebx, [ebp+FAT.buffer]
2591
        call    fs_read32_sys
2592
        test    eax, eax
2593
        lea     eax, [ebx+0x200]
2288 clevermous 2594
        jz      .checkempty
2595
.err1:
2596
        popad
2597
.err2:
2598
        pop     edi
2643 clevermous 2599
        call    fat_unlock
3598 clevermous 2600
        movi    eax, ERROR_DEVICE
2288 clevermous 2601
        ret
3174 clevermous 2602
.error_fat:
2603
        popad
2604
        pop     edi
2605
        call    fat_unlock
3598 clevermous 2606
        movi    eax, ERROR_FAT_TABLE
3174 clevermous 2607
        ret
2288 clevermous 2608
.notempty:
2609
        popad
2610
.access_denied2:
2611
        pop     edi
2643 clevermous 2612
        call    fat_unlock
3598 clevermous 2613
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 2614
        ret
2615
.empty:
2616
        popad
2643 clevermous 2617
        push    eax ebx
2618
        lea     ebx, [ebp+FAT.buffer]
2619
        call    fs_read32_sys
2620
        test    eax, eax
2621
        pop     ebx eax
2288 clevermous 2622
        jnz     .err2
2623
.dodel:
2624
        push    eax
2625
        mov     eax, [edi+20-2]
2626
        mov     ax, [edi+26]
2627
        xchg    eax, [esp]
2628
; delete folder entry
2629
        mov     byte [edi], 0xE5
2630
; delete LFN (if present)
2631
.lfndel:
2643 clevermous 2632
        lea     edx, [ebp+FAT.buffer]
2633
        cmp     edi, edx
2288 clevermous 2634
        ja      @f
2643 clevermous 2635
        cmp     [ebp+FAT.longname_sec2], 0
2288 clevermous 2636
        jz      .lfndone
2643 clevermous 2637
        push    [ebp+FAT.longname_sec2]
2638
        push    [ebp+FAT.longname_sec1]
2639
        pop     [ebp+FAT.longname_sec2]
2640
        and     [ebp+FAT.longname_sec1], 0
2288 clevermous 2641
        push    ebx
2643 clevermous 2642
        mov     ebx, edx
2643
        call    fs_write32_sys
2288 clevermous 2644
        mov     eax, [esp+4]
2643 clevermous 2645
        call    fs_read32_sys
2288 clevermous 2646
        pop     ebx
2647
        pop     eax
2643 clevermous 2648
        lea     edi, [ebp+FAT.buffer+0x200]
2288 clevermous 2649
@@:
2650
        sub     edi, 0x20
2651
        cmp     byte [edi], 0xE5
2652
        jz      .lfndone
2653
        cmp     byte [edi+11], 0xF
2654
        jnz     .lfndone
2655
        mov     byte [edi], 0xE5
2656
        jmp     .lfndel
2657
.lfndone:
2658
        push    ebx
2643 clevermous 2659
        lea     ebx, [ebp+FAT.buffer]
2660
        call    fs_write32_sys
2288 clevermous 2661
        pop     ebx
2662
; delete FAT chain
2663
        pop     eax
2664
        call    clear_cluster_chain
2665
        call    update_disk
2643 clevermous 2666
        call    fat_unlock
2288 clevermous 2667
        pop     edi
2668
        xor     eax, eax
2669
        ret
2670
 
2671
; \end{diamond}