Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
495 diamond 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
465 serge 2
;;                                                                 ;;
3908 Serge 3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
495 diamond 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
465 serge 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
;;                                                                 ;;
593 mikedld 45
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1 ha 46
 
593 mikedld 47
$Revision: 3908 $
48
 
49
 
1 ha 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
 
2987 Serge 60
; Internal data for every FAT partition.
3908 Serge 61
struct FAT PARTITION
2987 Serge 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
3908 Serge 67
                                ; can not be executed in parallel since the
68
                                ; legacy code is not ready; this mutex guards
69
                                ; all operations
2987 Serge 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
 
171 diamond 102
uglobal
103
align 4
1 ha 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
171 diamond 111
endg
1 ha 112
 
113
uglobal
171 diamond 114
align 4
1 ha 115
 Sector512:                      ; label for dev_hdcd.inc
2434 Serge 116
  buffer:
3908 Serge 117
                times 512 db 0
1 ha 118
endg
119
 
2987 Serge 120
iglobal
121
align 4
122
fat_user_functions:
3908 Serge 123
        dd      free
2987 Serge 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:
1 ha 136
endg
137
 
2987 Serge 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
3908 Serge 149
        cmp     dword [esp+4], 0
2987 Serge 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.
3626 Serge 167
        movi    eax, sizeof.FAT
2987 Serge 168
        call    malloc
169
        test    eax, eax
170
        jz      .return0
3908 Serge 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
2987 Serge 182
        or      [eax+FAT.fat_in_cache], -1
183
        mov     [eax+FAT.fat_change], 0
184
        push    ebp
185
        mov     ebp, eax
1 ha 186
 
2987 Serge 187
        lea     ecx, [ebp+FAT.Lock]
188
        call    mutex_init
1 ha 189
 
2987 Serge 190
        movzx   eax, word [ebx+0xe]     ; sectors reserved
191
        mov     [ebp+FAT.FAT_START], eax
1 ha 192
 
2987 Serge 193
        movzx   eax, byte [ebx+0xd]     ; sectors per cluster
194
        mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
1 ha 195
 
2987 Serge 196
        movzx   ecx, word [ebx+0xb]     ; bytes per sector
197
        mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
321 diamond 198
 
2987 Serge 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
321 diamond 207
 
2987 Serge 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
321 diamond 212
@@:
2987 Serge 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
@@:
3908 Serge 228
        mov     dword [ebp+FAT.Length], eax
229
        and     dword [ebp+FAT.Length+4], 0
2987 Serge 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
321 diamond 255
        jz      @f
2987 Serge 256
        mov     [ebp+FAT.fatStartScan], eax
321 diamond 257
@@:
2987 Serge 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
321 diamond 267
        ret
2987 Serge 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
2434 Serge 278
        ret
1 ha 279
 
280
set_FAT:
281
;--------------------------------
282
; input  : EAX = cluster
283
;          EDX = value to save
2987 Serge 284
;          EBP = pointer to FAT structure
1 ha 285
; output : EDX = old value
286
;--------------------------------
2987 Serge 287
; out: CF set <=> error
2434 Serge 288
        push    eax ebx esi
1 ha 289
 
2434 Serge 290
        cmp     eax, 2
291
        jb      sfc_error
2987 Serge 292
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
2434 Serge 293
        ja      sfc_error
2987 Serge 294
        cmp     [ebp+FAT.fs_type], 16
2434 Serge 295
        je      sfc_1
296
        add     eax, eax
1 ha 297
  sfc_1:
2434 Serge 298
        add     eax, eax
299
        mov     esi, 511
300
        and     esi, eax        ; esi = position in fat sector
301
        shr     eax, 9          ; eax = fat sector
2987 Serge 302
        add     eax, [ebp+FAT.FAT_START]
303
        lea     ebx, [ebp+FAT.fat_cache]
1 ha 304
 
2987 Serge 305
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
2434 Serge 306
        je      sfc_in_cache    ; yes
1 ha 307
 
2987 Serge 308
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
2434 Serge 309
        je      sfc_no_change   ; no
310
        call    write_fat_sector; yes. write it into disk
2987 Serge 311
        jc      sfc_error
1 ha 312
 
313
  sfc_no_change:
2987 Serge 314
        mov     [ebp+FAT.fat_in_cache], eax; save fat sector
315
        call    fs_read32_sys
316
        test    eax, eax
2434 Serge 317
        jne     sfc_error
1 ha 318
 
379 serge 319
 
1 ha 320
  sfc_in_cache:
2987 Serge 321
        cmp     [ebp+FAT.fs_type], 16
2434 Serge 322
        jne     sfc_test32
1 ha 323
 
324
  sfc_set16:
2434 Serge 325
        xchg    [ebx+esi], dx   ; save new value and get old value
326
        jmp     sfc_write
1 ha 327
 
328
  sfc_test32:
2987 Serge 329
        mov     eax, [ebp+FAT.fatMASK]
1 ha 330
 
331
  sfc_set32:
2434 Serge 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
1 ha 338
 
339
  sfc_write:
2987 Serge 340
        mov     [ebp+FAT.fat_change], 1; fat has changed
1 ha 341
 
342
  sfc_nonzero:
2987 Serge 343
        and     edx, [ebp+FAT.fatMASK]
1 ha 344
 
2987 Serge 345
  sfc_return:
2434 Serge 346
        pop     esi ebx eax
347
        ret
2987 Serge 348
  sfc_error:
349
        stc
350
        jmp     sfc_return
1 ha 351
 
352
 
353
get_FAT:
354
;--------------------------------
355
; input  : EAX = cluster
2987 Serge 356
;          EBP = pointer to FAT structure
1 ha 357
; output : EAX = next cluster
358
;--------------------------------
2987 Serge 359
; out: CF set <=> error
2434 Serge 360
        push    ebx esi
1 ha 361
 
2987 Serge 362
        cmp     [ebp+FAT.fs_type], 16
2434 Serge 363
        je      gfc_1
364
        add     eax, eax
1 ha 365
  gfc_1:
2434 Serge 366
        add     eax, eax
367
        mov     esi, 511
368
        and     esi, eax        ; esi = position in fat sector
369
        shr     eax, 9          ; eax = fat sector
2987 Serge 370
        add     eax, [ebp+FAT.FAT_START]
371
        lea     ebx, [ebp+FAT.fat_cache]
1 ha 372
 
2987 Serge 373
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
2434 Serge 374
        je      gfc_in_cache
1 ha 375
 
2987 Serge 376
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
2434 Serge 377
        je      gfc_no_change   ; no
378
        call    write_fat_sector; yes. write it into disk
2987 Serge 379
        jc      hd_error_01
1 ha 380
 
381
  gfc_no_change:
2987 Serge 382
        mov     [ebp+FAT.fat_in_cache], eax
383
        call    fs_read32_sys
384
        test    eax, eax
2434 Serge 385
        jne     hd_error_01
1 ha 386
 
387
  gfc_in_cache:
2434 Serge 388
        mov     eax, [ebx+esi]
2987 Serge 389
        and     eax, [ebp+FAT.fatMASK]
390
  gfc_return:
2434 Serge 391
        pop     esi ebx
392
        ret
2987 Serge 393
 hd_error_01:
394
        stc
395
        jmp     gfc_return
1 ha 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
;-----------------------------------------------------------
2434 Serge 404
        push    ecx
2987 Serge 405
        mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
2434 Serge 406
        sub     ecx, 2
2987 Serge 407
        mov     eax, [ebp+FAT.fatStartScan]
2434 Serge 408
        cmp     eax, 2
409
        jb      gff_reset
1 ha 410
 
411
  gff_test:
2987 Serge 412
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
2434 Serge 413
        jbe     gff_in_range
649 diamond 414
  gff_reset:
2434 Serge 415
        mov     eax, 2
1 ha 416
 
417
  gff_in_range:
2434 Serge 418
        push    eax
419
        call    get_FAT         ; get cluster state
2987 Serge 420
        jc      gff_not_found_1
74 mario79 421
 
2434 Serge 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
1 ha 428
 
429
  gff_not_found:
2434 Serge 430
        pop     ecx             ; yes. disk is full
431
        stc
432
        ret
1 ha 433
 
2987 Serge 434
  gff_not_found_1:
435
        pop     eax
436
        jmp     gff_not_found
437
 
1 ha 438
  gff_found:
2434 Serge 439
        lea     ecx, [eax+1]
2987 Serge 440
        mov     [ebp+FAT.fatStartScan], ecx
2434 Serge 441
        pop     ecx
442
        clc
443
        ret
1 ha 444
 
445
 
446
write_fat_sector:
447
;-----------------------------------------------------------
448
; write changed fat to disk
449
;-----------------------------------------------------------
2434 Serge 450
        push    eax ebx ecx
1 ha 451
 
2987 Serge 452
        mov     [ebp+FAT.fat_change], 0
453
        mov     eax, [ebp+FAT.fat_in_cache]
2434 Serge 454
        cmp     eax, -1
455
        jz      write_fat_not_used
2987 Serge 456
        lea     ebx, [ebp+FAT.fat_cache]
457
        mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
1 ha 458
 
459
  write_next_fat:
2987 Serge 460
        push    eax
461
        call    fs_write32_sys
462
        test    eax, eax
463
        pop     eax
464
        jnz     write_fat_not_used
74 mario79 465
 
2987 Serge 466
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
2434 Serge 467
        dec     ecx
468
        jnz     write_next_fat
1 ha 469
 
470
  write_fat_not_used:
2434 Serge 471
        pop     ecx ebx eax
472
        ret
1 ha 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
;----------------------------------
2434 Serge 484
        xor     ah, ah
485
        shl     ax, 4
486
        shr     al, 4
487
        aad
488
        ret
1 ha 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
;-----------------------------------------------------
2434 Serge 498
        mov     al, 0x7 ;day
499
        out     0x70, al
500
        in      al, 0x71
501
        call    bcd2bin
502
        ror     eax, 5
1 ha 503
 
2434 Serge 504
        mov     al, 0x8 ;month
505
        out     0x70, al
506
        in      al, 0x71
507
        call    bcd2bin
508
        ror     eax, 4
1 ha 509
 
2434 Serge 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
1 ha 515
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
2434 Serge 516
        rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
517
        ret
1 ha 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
;-----------------------------------------------------
2434 Serge 527
        mov     al, 0x0 ;second
528
        out     0x70, al
529
        in      al, 0x71
530
        call    bcd2bin
531
        ror     eax, 6
1 ha 532
 
2434 Serge 533
        mov     al, 0x2 ;minute
534
        out     0x70, al
535
        in      al, 0x71
536
        call    bcd2bin
537
        ror     eax, 6
1 ha 538
 
2434 Serge 539
        mov     al, 0x4 ;hour
540
        out     0x70, al
541
        in      al, 0x71
542
        call    bcd2bin
543
        rol     eax, 11
544
        ret
1 ha 545
 
546
 
547
set_current_time_for_entry:
548
;-----------------------------------------------------
549
; Set current time/date for file entry
550
; input  : ebx = file entry pointer
551
;-----------------------------------------------------
2434 Serge 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
1 ha 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
;-----------------------------------------------------
2434 Serge 568
        test    ecx, ecx        ; no change
569
        je      add_dfs_no
2987 Serge 570
        cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
2434 Serge 571
        jne     add_dfs_no
1 ha 572
 
2434 Serge 573
        push    eax ebx
2987 Serge 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
74 mario79 579
 
2434 Serge 580
        cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
581
        jne     add_not_fs
1 ha 582
 
2434 Serge 583
        add     [ebx+0x1e8], ecx
2987 Serge 584
        push    [ebp+FAT.fatStartScan]
2434 Serge 585
        pop     dword [ebx+0x1ec]
2987 Serge 586
        mov     eax, [ebp+FAT.ADR_FSINFO]
587
        call    fs_write32_sys
588
;    jc    add_not_fs
1 ha 589
 
590
  add_not_fs:
2434 Serge 591
        pop     ebx eax
1 ha 592
 
593
  add_dfs_no:
2434 Serge 594
        ret
1 ha 595
 
596
 
597
 
598
clear_cluster_chain:
599
;-----------------------------------------------------
600
; input  : eax = first cluster
601
;-----------------------------------------------------
2434 Serge 602
        push    eax ecx edx
603
        xor     ecx, ecx        ; cluster count
1 ha 604
 
605
  clean_new_chain:
2987 Serge 606
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
2434 Serge 607
        ja      delete_OK
608
        cmp     eax, 2          ; unfinished fat chain or zero length file
609
        jb      delete_OK
2987 Serge 610
        cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
2434 Serge 611
        jz      delete_OK
1 ha 612
 
2434 Serge 613
        xor     edx, edx
614
        call    set_FAT         ; clear fat entry
2987 Serge 615
        jc      access_denied_01
74 mario79 616
 
2434 Serge 617
        inc     ecx             ; update cluster count
618
        mov     eax, edx        ; old cluster
619
        jmp     clean_new_chain
1 ha 620
 
621
  delete_OK:
2434 Serge 622
        call    add_disk_free_space; add clusters to free disk space
2987 Serge 623
        clc
74 mario79 624
  access_denied_01:
2434 Serge 625
        pop     edx ecx eax
626
        ret
1 ha 627
 
628
 
2987 Serge 629
if 0
1 ha 630
get_hd_info:
631
;-----------------------------------------------------------
632
; output : eax = 0 - ok
633
;                3 - unknown FS
74 mario79 634
;               10 - access denied
1 ha 635
;          edx = cluster size in bytes
636
;          ebx = total clusters on disk
637
;          ecx = free clusters on disk
638
;-----------------------------------------------------------
2987 Serge 639
        cmp     [ebp+FAT.fs_type], 16
256 diamond 640
        jz      info_fat_ok
2987 Serge 641
        cmp     [ebp+FAT.fs_type], 32
256 diamond 642
        jz      info_fat_ok
2434 Serge 643
        xor     edx, edx
644
        xor     ebx, ebx
645
        xor     ecx, ecx
646
        mov     eax, ERROR_UNKNOWN_FS
647
        ret
1 ha 648
 
649
  info_fat_ok:
650
;    call  reserve_hd1
651
 
2434 Serge 652
        xor     ecx, ecx        ; count of free clusters
653
        mov     eax, 2
2987 Serge 654
        mov     ebx, [ebp+FAT.LAST_CLUSTER]
1 ha 655
 
656
  info_cluster:
2434 Serge 657
        push    eax
658
        call    get_FAT         ; get cluster info
2987 Serge 659
        jc      info_access_denied
74 mario79 660
 
2434 Serge 661
        test    eax, eax        ; is it free?
662
        jnz     info_used       ; no
663
        inc     ecx
1 ha 664
 
665
  info_used:
2434 Serge 666
        pop     eax
667
        inc     eax
668
        cmp     eax, ebx        ; is above last cluster?
669
        jbe     info_cluster    ; no. test next cluster
1 ha 670
 
2434 Serge 671
        dec     ebx             ; cluster count
2987 Serge 672
        imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
2434 Serge 673
        xor     eax, eax
674
        ret
1 ha 675
 
74 mario79 676
  info_access_denied:
2434 Serge 677
        add     esp, 4
678
        xor     edx, edx
679
        xor     ebx, ebx
680
        xor     ecx, ecx
681
        mov     eax, ERROR_ACCESS_DENIED
682
        ret
2987 Serge 683
end if
1 ha 684
 
685
update_disk:
686
;-----------------------------------------------------------
687
; write changed fat and cache to disk
688
;-----------------------------------------------------------
2987 Serge 689
        cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
2434 Serge 690
        je      upd_no_change
1 ha 691
 
2434 Serge 692
        call    write_fat_sector
2987 Serge 693
        jc      update_disk_acces_denied
1 ha 694
 
695
  upd_no_change:
696
 
2987 Serge 697
        push    esi
698
        mov     esi, [ebp+PARTITION.Disk]
699
        call    disk_sync
700
        pop     esi
74 mario79 701
  update_disk_acces_denied:
2434 Serge 702
        ret
1 ha 703
 
2987 Serge 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
1 ha 710
 
71 diamond 711
; \begin{diamond}
712
hd_find_lfn:
2987 Serge 713
; in: ebp -> FAT structure
714
; in: esi+[esp+4] -> name
715
; out: CF=1 - file not found, eax=error code
86 diamond 716
;      else CF=0 and edi->direntry, eax=sector
83 diamond 717
; destroys eax
718
        push    esi edi
719
        push    0
720
        push    0
721
        push    fat16_root_first
722
        push    fat16_root_next
2987 Serge 723
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
724
        cmp     [ebp+FAT.fs_type], 32
83 diamond 725
        jz      .fat32
726
.loop:
727
        call    fat_find_lfn
728
        jc      .notfound
729
        cmp     byte [esi], 0
730
        jz      .found
521 diamond 731
.continue:
83 diamond 732
        test    byte [edi+11], 10h
733
        jz      .notfound
734
        and     dword [esp+12], 0
88 diamond 735
        mov     eax, [edi+20-2]
736
        mov     ax, [edi+26]    ; cluster
83 diamond 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
71 diamond 742
.notfound:
83 diamond 743
        add     esp, 16
744
        pop     edi esi
745
        stc
2987 Serge 746
        ret     4
71 diamond 747
.found:
2987 Serge 748
        lea     eax, [esp+4+24]
749
        cmp     dword [eax], 0
521 diamond 750
        jz      @f
2987 Serge 751
        mov     esi, [eax]
752
        and     dword [eax], 0
521 diamond 753
        jmp     .continue
754
@@:
86 diamond 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]
2987 Serge 762
        add     eax, [ebp+FAT.ROOT_START]
86 diamond 763
.cmn:
83 diamond 764
        add     esp, 20         ; CF=0
765
        pop     esi
2987 Serge 766
        ret     4
74 mario79 767
 
71 diamond 768
;----------------------------------------------------------------
2987 Serge 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
2434 Serge 777
        push    edi
778
        cmp     byte [esi], 0
779
        jnz     @f
71 diamond 780
.noaccess:
2434 Serge 781
        pop     edi
74 mario79 782
.noaccess_2:
2987 Serge 783
        call    fat_unlock
2434 Serge 784
        or      ebx, -1
785
        mov     eax, ERROR_ACCESS_DENIED
786
        ret
379 serge 787
 
71 diamond 788
@@:
2987 Serge 789
        stdcall hd_find_lfn, [esp+4+4]
2434 Serge 790
        jnc     .found
791
        pop     edi
2987 Serge 792
        push    eax
793
        call    fat_unlock
794
        pop     eax
2434 Serge 795
        or      ebx, -1
796
        ret
74 mario79 797
 
71 diamond 798
.found:
2434 Serge 799
        test    byte [edi+11], 0x10; do not allow read directories
800
        jnz     .noaccess
2987 Serge 801
        cmp     dword [ebx+8], 0
2434 Serge 802
        jz      @f
77 diamond 803
        xor     ebx, ebx
71 diamond 804
.reteof:
2987 Serge 805
        call    fat_unlock
806
        mov     eax, ERROR_END_OF_FILE
2434 Serge 807
        pop     edi
808
        ret
71 diamond 809
@@:
2987 Serge 810
        mov     ecx, [ebx+12]   ; size
811
        mov     edx, [ebx+16]   ; pointer
812
        mov     ebx, [ebx+4]    ; file offset
813
        push    edx
77 diamond 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
@@:
2434 Serge 823
        mov     eax, [edi+20-2]
824
        mov     ax, [edi+26]
71 diamond 825
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
826
.new_cluster:
2434 Serge 827
        jecxz   .new_sector
2987 Serge 828
        cmp     eax, 2
829
        jb      .eof
830
        cmp     eax, [ebp+FAT.fatRESERVED]
2434 Serge 831
        jae     .eof
2987 Serge 832
        mov     [ebp+FAT.cluster_tmp], eax
2434 Serge 833
        dec     eax
834
        dec     eax
2987 Serge 835
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
2434 Serge 836
        imul    eax, edi
2987 Serge 837
        add     eax, [ebp+FAT.DATA_START]
71 diamond 838
.new_sector:
2434 Serge 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
71 diamond 847
; we may read directly to given buffer
2987 Serge 848
        push    eax ebx
2434 Serge 849
        mov     ebx, edx
2987 Serge 850
        call    fs_read32_app
851
        test    eax, eax
852
        pop     ebx eax
2434 Serge 853
        jne     .noaccess_1
854
        add     edx, 512
855
        sub     ecx, 512
856
        jmp     .skip
71 diamond 857
.force_buf:
858
; we must read sector to temporary buffer and then copy it to destination
2434 Serge 859
        push    eax ebx
2987 Serge 860
        lea     ebx, [ebp+FAT.buffer]
861
        call    fs_read32_app
862
        test    eax, eax
2434 Serge 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
71 diamond 872
@@:
2434 Serge 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
71 diamond 881
.skip:
2434 Serge 882
        inc     eax
883
        dec     edi
884
        jnz     .new_sector
2987 Serge 885
        mov     eax, [ebp+FAT.cluster_tmp]
2434 Serge 886
        call    get_FAT
2987 Serge 887
        jc      .noaccess_1
74 mario79 888
 
2434 Serge 889
        jmp     .new_cluster
1124 diamond 890
.noaccess_3:
891
        pop     eax
892
.noaccess_1:
893
        pop     eax
2987 Serge 894
        push    ERROR_DEVICE
71 diamond 895
.done:
77 diamond 896
        mov     ebx, edx
2987 Serge 897
        call    fat_unlock
898
        pop     eax edx edi
77 diamond 899
        sub     ebx, edx
900
        ret
71 diamond 901
.eof:
77 diamond 902
        mov     ebx, edx
2987 Serge 903
        pop     eax edx
77 diamond 904
        sub     ebx, edx
905
        jmp     .reteof
75 diamond 906
 
907
;----------------------------------------------------------------
2987 Serge 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]
75 diamond 917
        push    edi
918
        cmp     byte [esi], 0
919
        jz      .doit
2987 Serge 920
        stdcall hd_find_lfn, [esp+4+4]
75 diamond 921
        jnc     .found
922
        pop     edi
2987 Serge 923
        push    eax
924
        call    fat_unlock
925
        pop     eax
75 diamond 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
2987 Serge 932
        call    fat_unlock
75 diamond 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:
2987 Serge 940
        push    esi
75 diamond 941
        sub     esp, 262*2      ; reserve space for LFN
2987 Serge 942
        push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
943
        mov     edx, [ebx+16]   ; pointer to buffer
75 diamond 944
; init header
2987 Serge 945
        push    eax
75 diamond 946
        mov     edi, edx
947
        mov     ecx, 32/4
948
        xor     eax, eax
2434 Serge 949
        rep stosd
2987 Serge 950
        pop     eax
75 diamond 951
        mov     byte [edx], 1   ; version
952
        mov     esi, edi        ; esi points to BDFE
2987 Serge 953
        mov     ecx, [ebx+12]   ; number of blocks to read
954
        mov     ebx, [ebx+4]    ; index of the first block
75 diamond 955
.new_cluster:
2987 Serge 956
        mov     [ebp+FAT.cluster_tmp], eax
75 diamond 957
        test    eax, eax
958
        jnz     @f
2987 Serge 959
        cmp     [ebp+FAT.fs_type], 32
75 diamond 960
        jz      .notfound
2987 Serge 961
        mov     eax, [ebp+FAT.ROOT_START]
962
        push    [ebp+FAT.ROOT_SECTORS]
75 diamond 963
        push    ebx
964
        jmp     .new_sector
965
@@:
966
        dec     eax
967
        dec     eax
2987 Serge 968
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
969
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
970
        add     eax, [ebp+FAT.DATA_START]
75 diamond 971
        push    ebx
972
.new_sector:
2987 Serge 973
        lea     ebx, [ebp+FAT.buffer]
75 diamond 974
        mov     edi, ebx
2987 Serge 975
        push    eax
976
        call    fs_read32_sys
977
        test    eax, eax
978
        pop     eax
75 diamond 979
        jnz     .notfound2
980
        add     ebx, 512
981
        push    eax
982
.l1:
2987 Serge 983
        push    ebp
984
        lea     ebp, [esp+20]
75 diamond 985
        call    fat_get_name
2987 Serge 986
        pop     ebp
75 diamond 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
2987 Serge 997
        mov     eax, [ebp+FAT.cluster_tmp]
75 diamond 998
        test    eax, eax
999
        jz      .done
1000
        call    get_FAT
2987 Serge 1001
        jc      .notfound2
75 diamond 1002
        cmp     eax, 2
1003
        jb      .done
2987 Serge 1004
        cmp     eax, [ebp+FAT.fatRESERVED]
75 diamond 1005
        jae     .done
1006
        push    eax
2987 Serge 1007
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
75 diamond 1008
        mov     [esp+8], eax
1009
        pop     eax
2987 Serge 1010
        mov     [ebp+FAT.cluster_tmp], eax
75 diamond 1011
        dec     eax
1012
        dec     eax
2987 Serge 1013
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1014
        add     eax, [ebp+FAT.DATA_START]
75 diamond 1015
@@:
2987 Serge 1016
        lea     ebx, [ebp+FAT.buffer]
75 diamond 1017
        mov     edi, ebx
2987 Serge 1018
        push    eax
1019
        call    fs_read32_sys
1020
        test    eax, eax
1021
        pop     eax
75 diamond 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
2987 Serge 1032
        push    ebp
1033
        lea     ebp, [esp+20]
75 diamond 1034
        call    fat_entry_to_bdfe
2987 Serge 1035
        pop     ebp
75 diamond 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
2987 Serge 1044
        mov     eax, [ebp+FAT.cluster_tmp]
75 diamond 1045
        test    eax, eax
1046
        jz      .done
1047
        call    get_FAT
2987 Serge 1048
        jc      .notfound2
75 diamond 1049
        cmp     eax, 2
1050
        jb      .done
2987 Serge 1051
        cmp     eax, [ebp+FAT.fatRESERVED]
75 diamond 1052
        jae     .done
1053
        push    eax
2987 Serge 1054
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
75 diamond 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
2987 Serge 1064
        pop     esi edi
1065
        mov     ebx, [edx+4]
1066
        call    fat_unlock
1067
        mov     eax, ERROR_DEVICE
75 diamond 1068
        ret
1069
.done:
1070
        add     esp, 262*2+4+8
77 diamond 1071
        mov     ebx, [edx+4]
75 diamond 1072
        xor     eax, eax
1073
        dec     ecx
1074
        js      @f
1075
        mov     al, ERROR_END_OF_FILE
1076
@@:
2987 Serge 1077
        push    eax
1078
        call    fat_unlock
1079
        pop     eax
1080
        pop     esi edi
75 diamond 1081
        ret
1082
 
83 diamond 1083
fat16_root_next:
2987 Serge 1084
        push    ecx
1085
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1086
        cmp     edi, ecx
83 diamond 1087
        jae     fat16_root_next_sector
2987 Serge 1088
        pop     ecx
83 diamond 1089
        add     edi, 0x20
1090
        ret     ; CF=0
1091
fat16_root_next_sector:
1092
; read next sector
2987 Serge 1093
        push    [ebp+FAT.longname_sec2]
1094
        pop     [ebp+FAT.longname_sec1]
83 diamond 1095
        mov     ecx, [eax+4]
171 diamond 1096
        push    ecx
2987 Serge 1097
        add     ecx, [ebp+FAT.ROOT_START]
1098
        mov     [ebp+FAT.longname_sec2], ecx
171 diamond 1099
        pop     ecx
83 diamond 1100
        inc     ecx
1101
        mov     [eax+4], ecx
2987 Serge 1102
        cmp     ecx, [ebp+FAT.ROOT_SECTORS]
83 diamond 1103
        pop     ecx
2987 Serge 1104
        jb      fat16_root_first
1105
        mov     eax, ERROR_FILE_NOT_FOUND
1106
        stc
1107
        ret
83 diamond 1108
fat16_root_first:
1109
        mov     eax, [eax+4]
2987 Serge 1110
        add     eax, [ebp+FAT.ROOT_START]
83 diamond 1111
        push    ebx
2987 Serge 1112
        lea     edi, [ebp+FAT.buffer]
83 diamond 1113
        mov     ebx, edi
2987 Serge 1114
        call    fs_read32_sys
83 diamond 1115
        pop     ebx
2987 Serge 1116
        test    eax, eax
83 diamond 1117
        jnz     .readerr
1118
        ret     ; CF=0
1119
.readerr:
2987 Serge 1120
        mov     eax, ERROR_DEVICE
83 diamond 1121
        stc
1122
        ret
2987 Serge 1123
.notfound:
1124
        mov     eax, ERROR_FILE_NOT_FOUND
1125
        stc
1126
        ret
83 diamond 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]
2987 Serge 1135
        add     eax, [ebp+FAT.ROOT_START]
1136
        lea     ebx, [ebp+FAT.buffer]
1137
        call    fs_write32_sys
83 diamond 1138
        popa
1139
        ret
1140
fat16_root_next_write:
2987 Serge 1141
        push    ecx
1142
        lea     ecx, [ebp+FAT.buffer+0x200]
1143
        cmp     edi, ecx
83 diamond 1144
        jae     @f
2987 Serge 1145
        pop     ecx
83 diamond 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:
2987 Serge 1155
        push    ecx
1156
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
1157
        cmp     edi, ecx
83 diamond 1158
        jae     fat_notroot_next_sector
2987 Serge 1159
        pop     ecx
83 diamond 1160
        add     edi, 0x20
1161
        ret     ; CF=0
1162
fat_notroot_next_sector:
2987 Serge 1163
        push    [ebp+FAT.longname_sec2]
1164
        pop     [ebp+FAT.longname_sec1]
171 diamond 1165
        push    eax
1166
        call    fat_get_sector
2987 Serge 1167
        mov     [ebp+FAT.longname_sec2], eax
171 diamond 1168
        pop     eax
83 diamond 1169
        mov     ecx, [eax+4]
1170
        inc     ecx
2987 Serge 1171
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
83 diamond 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
2987 Serge 1181
        jc      fat_notroot_first.deverr
1182
        cmp     ecx, 2
1183
        jb      fat_notroot_next_err
1184
        cmp     ecx, [ebp+FAT.fatRESERVED]
83 diamond 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
2987 Serge 1193
        lea     edi, [ebp+FAT.buffer]
83 diamond 1194
        mov     ebx, edi
2987 Serge 1195
        call    fs_read32_sys
83 diamond 1196
        pop     ebx
2987 Serge 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
83 diamond 1206
fat_notroot_next_err:
1207
        pop     ecx
2987 Serge 1208
        mov     eax, ERROR_FILE_NOT_FOUND
83 diamond 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
2987 Serge 1219
        lea     ebx, [ebp+FAT.buffer]
1220
        call    fs_write32_sys
83 diamond 1221
        pop     ebx
1222
        ret
1223
fat_notroot_next_write:
2987 Serge 1224
        push    ecx
1225
        lea     ecx, [ebp+FAT.buffer+0x200]
1226
        cmp     edi, ecx
83 diamond 1227
        jae     @f
2987 Serge 1228
        pop     ecx
83 diamond 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
2987 Serge 1243
        mov     edx, [ebp+FAT.fatEND]
83 diamond 1244
        call    set_FAT
2987 Serge 1245
        jc      .writeerr
83 diamond 1246
        mov     edx, eax
1247
        mov     eax, [esp+4]
1248
        mov     eax, [eax]
1249
        push    edx
1250
        call    set_FAT
1251
        pop     edx
2987 Serge 1252
        jnc     @f
1253
.writeerr:
83 diamond 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
2987 Serge 1264
        lea     edi, [ebp+FAT.buffer]
83 diamond 1265
        push    edi
1266
        xor     eax, eax
2434 Serge 1267
        rep stosd
83 diamond 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
2987 Serge 1278
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
83 diamond 1279
        imul    eax, ecx
2987 Serge 1280
        add     eax, [ebp+FAT.DATA_START]
83 diamond 1281
        mov     ebx, edi
1282
@@:
2987 Serge 1283
        push    eax
1284
        call    fs_write32_sys
1285
        pop     eax
83 diamond 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
2987 Serge 1297
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
1298
        add     ecx, [ebp+FAT.DATA_START]
83 diamond 1299
        add     ecx, [eax+4]
1300
        mov     eax, ecx
1301
        pop     ecx
1302
        ret
1303
 
2987 Serge 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
;----------------------------------------------------------------
3908 Serge 1322
; fat_Rewrite - FAT16/32 implementation of creating a new file
2987 Serge 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
83 diamond 1333
        cmp     byte [esi], 0
1334
        jz      fshrad
2987 Serge 1335
        mov     ecx, [ebx+12]
1336
        mov     edx, [ebx+16]
83 diamond 1337
        pushad
521 diamond 1338
        xor     edi, edi
2987 Serge 1339
        mov     edx, [esp+4+20h]
83 diamond 1340
        push    esi
2987 Serge 1341
        test    edx, edx
521 diamond 1342
        jz      @f
2987 Serge 1343
        mov     esi, edx
83 diamond 1344
@@:
1345
        lodsb
1346
        test    al, al
1347
        jz      @f
1348
        cmp     al, '/'
1349
        jnz     @b
521 diamond 1350
        lea     edi, [esi-1]
83 diamond 1351
        jmp     @b
1352
@@:
1353
        pop     esi
521 diamond 1354
        test    edi, edi
1355
        jnz     .noroot
2987 Serge 1356
        test    edx, edx
521 diamond 1357
        jnz     .hasebp
2987 Serge 1358
        mov     edx, [ebp+FAT.ROOT_CLUSTER]
1359
        cmp     [ebp+FAT.fs_type], 32
83 diamond 1360
        jz      .pushnotroot
2987 Serge 1361
        xor     edx, edx
1362
        push    edx
83 diamond 1363
        push    fat16_root_extend_dir
1364
        push    fat16_root_end_write
1365
        push    fat16_root_next_write
1366
        push    fat16_root_begin_write
2987 Serge 1367
        push    edx
1368
        push    edx
83 diamond 1369
        push    fat16_root_first
1370
        push    fat16_root_next
1371
        jmp     .common1
521 diamond 1372
.hasebp:
1373
        mov     eax, ERROR_ACCESS_DENIED
2987 Serge 1374
        cmp     byte [edx], 0
521 diamond 1375
        jz      .ret1
2987 Serge 1376
        stdcall hd_find_lfn, 0
1377
        mov     esi, [esp+4+20h]
1378
        jc      .ret1
521 diamond 1379
        jmp     .common0
83 diamond 1380
.noroot:
335 diamond 1381
        mov     eax, ERROR_ACCESS_DENIED
521 diamond 1382
        cmp     byte [edi+1], 0
335 diamond 1383
        jz      .ret1
83 diamond 1384
; check existence
521 diamond 1385
        mov     byte [edi], 0
1386
        push    edi
2987 Serge 1387
        stdcall hd_find_lfn, [esp+4+24h]
521 diamond 1388
        pop     esi
1389
        mov     byte [esi], '/'
83 diamond 1390
        jnc     @f
521 diamond 1391
.notfound0:
83 diamond 1392
        mov     eax, ERROR_FILE_NOT_FOUND
1393
.ret1:
1394
        mov     [esp+28], eax
2987 Serge 1395
        call    fat_unlock
83 diamond 1396
        popad
1397
        xor     ebx, ebx
1398
        ret
1399
@@:
521 diamond 1400
        inc     esi
1401
.common0:
83 diamond 1402
        test    byte [edi+11], 0x10     ; must be directory
1403
        mov     eax, ERROR_ACCESS_DENIED
1404
        jz      .ret1
2987 Serge 1405
        mov     edx, [edi+20-2]
1406
        mov     dx, [edi+26]            ; ebp=cluster
83 diamond 1407
        mov     eax, ERROR_FAT_TABLE
2987 Serge 1408
        cmp     edx, 2
83 diamond 1409
        jb      .ret1
1410
.pushnotroot:
2987 Serge 1411
        push    edx
83 diamond 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
2987 Serge 1417
        push    edx
83 diamond 1418
        push    fat_notroot_first
1419
        push    fat_notroot_next
1420
.common1:
1421
        call    fat_find_lfn
1422
        jc      .notfound
321 diamond 1423
; found
91 diamond 1424
        test    byte [edi+11], 10h
321 diamond 1425
        jz      .exists_file
1426
; found directory; if we are creating directory, return OK,
1427
;                  if we are creating file, say "access denied"
2987 Serge 1428
        add     esp, 36
1429
        call    fat_unlock
321 diamond 1430
        popad
1431
        test    al, al
1432
        mov     eax, ERROR_ACCESS_DENIED
91 diamond 1433
        jz      @f
321 diamond 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
2987 Serge 1441
        cmp     byte [esp+36+28], 0
321 diamond 1442
        jz      @f
2987 Serge 1443
        add     esp, 36
1444
        call    fat_unlock
91 diamond 1445
        popad
1446
        mov     eax, ERROR_ACCESS_DENIED
1447
        xor     ebx, ebx
1448
        ret
1449
@@:
1450
; delete FAT chain
83 diamond 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
@@:
2987 Serge 1462
        cmp     eax, [ebp+FAT.fatRESERVED]
83 diamond 1463
        jae     .done1
1464
        push    edx
1465
        xor     edx, edx
1466
        call    set_FAT
1467
        mov     eax, edx
1468
        pop     edx
2987 Serge 1469
        jc      .done1
83 diamond 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
2987 Serge 1485
        add     esp, 36
1486
        call    fat_unlock
83 diamond 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]
2987 Serge 1499
        mov     edx, [eax+24]
1500
        mov     [eax], edx
83 diamond 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
2434 Serge 1509
        repz cmpsb
83 diamond 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:
2987 Serge 1522
        add     esp, 12+36
1523
        call    fat_unlock
83 diamond 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
2434 Serge 1535
        repnz scasb
3626 Serge 1536
        movi    eax, 1     ; 1 entry
83 diamond 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]
2987 Serge 1562
        mov     edx, [eax+24]
1563
        mov     [eax], edx
83 diamond 1564
        and     dword [eax+4], 0
1565
        call    dword [eax-4]
1566
        pop     eax
1567
        jnc     .scan_dir
1568
.fsfrfe3:
2987 Serge 1569
        add     esp, 12+8+12+36
1570
        call    fat_unlock
83 diamond 1571
        popad
2987 Serge 1572
        mov     eax, ERROR_DEVICE
83 diamond 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]
2987 Serge 1585
        mov     edx, eax
83 diamond 1586
        pop     eax
1587
        jnc     .scan_dir
2987 Serge 1588
        cmp     edx, ERROR_DEVICE
1589
        jz      .fsfrfe3
83 diamond 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
2987 Serge 1595
        add     esp, 12+8+12+36
1596
        call    fat_unlock
83 diamond 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!
2987 Serge 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:
83 diamond 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
2434 Serge 1684
        rep movsb
83 diamond 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
2987 Serge 1701
        cmp     byte [esp+36+28], cl
321 diamond 1702
        jz      .doit
1703
; create directory
1704
        mov     byte [edi+11], 10h      ; attributes: folder
2987 Serge 1705
        mov     esi, edi
321 diamond 1706
        lea     eax, [esp+8]
1707
        call    dword [eax+16]  ; flush directory
2987 Serge 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!
321 diamond 1710
        push    ecx
2987 Serge 1711
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
321 diamond 1712
        shl     ecx, 9
2987 Serge 1713
        push    ecx
1714
        push    edi
321 diamond 1715
        jmp     .doit2
83 diamond 1716
.doit:
2987 Serge 1717
        mov     esi, [esp+36+20]
83 diamond 1718
        lea     eax, [esp+8]
1719
        call    dword [eax+16]  ; flush directory
1720
        push    ecx
2987 Serge 1721
        mov     ecx, [esp+4+36+24]
83 diamond 1722
        push    ecx
1723
        push    edi
1724
        test    ecx, ecx
1725
        jz      .done
1726
        call    get_free_FAT
1727
        jc      .diskfull
2987 Serge 1728
.doit2:
83 diamond 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
2987 Serge 1737
        mov     edx, [ebp+FAT.fatEND]
83 diamond 1738
        call    set_FAT
1739
        pop     edx
1740
.write_cluster:
1741
        push    eax
1742
        dec     eax
1743
        dec     eax
2987 Serge 1744
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1745
        add     eax, [ebp+FAT.DATA_START]
1746
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
83 diamond 1747
; write data
1748
.write_sector:
2987 Serge 1749
        cmp     byte [esp+20+36+28], 0
321 diamond 1750
        jnz     .writedir
83 diamond 1751
        mov     ecx, 512
2987 Serge 1752
        cmp     dword [esp+12], ecx
83 diamond 1753
        jb      .writeshort
1754
; we can write directly from given buffer
1755
        mov     ebx, esi
1756
        add     esi, ecx
1757
        jmp     .writecommon
1758
.writeshort:
2987 Serge 1759
        mov     ecx, [esp+12]
83 diamond 1760
        push    ecx
2987 Serge 1761
        lea     edi, [ebp+FAT.buffer]
83 diamond 1762
        mov     ebx, edi
2434 Serge 1763
        rep movsb
321 diamond 1764
.writedircont:
2987 Serge 1765
        lea     ecx, [ebp+FAT.buffer+0x200]
83 diamond 1766
        sub     ecx, edi
1767
        push    eax
1768
        xor     eax, eax
2434 Serge 1769
        rep stosb
83 diamond 1770
        pop     eax
1771
        pop     ecx
1772
.writecommon:
2987 Serge 1773
        push    eax
1774
        call    fs_write32_app
1775
        test    eax, eax
1776
        pop     eax
83 diamond 1777
        jnz     .writeerr
1778
        inc     eax
2987 Serge 1779
        sub     dword [esp+12], ecx
83 diamond 1780
        jz      .writedone
2987 Serge 1781
        dec     dword [esp]
83 diamond 1782
        jnz     .write_sector
2987 Serge 1783
        pop     eax
83 diamond 1784
; allocate new cluster
1785
        pop     eax
1786
        mov     ecx, eax
1787
        call    get_free_FAT
1788
        jc      .diskfull
1789
        push    edx
2987 Serge 1790
        mov     edx, [ebp+FAT.fatEND]
83 diamond 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:
2987 Serge 1802
        pop     eax eax
83 diamond 1803
        sub     esi, ecx
2987 Serge 1804
        mov     eax, ERROR_DEVICE
83 diamond 1805
        jmp     .ret
1806
.writedone:
2987 Serge 1807
        pop     eax eax
83 diamond 1808
.done:
1809
        xor     eax, eax
1810
.ret:
1811
        pop     edi ecx
2987 Serge 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]
83 diamond 1816
        call    dword [eax+8]
2987 Serge 1817
        mov     [edi+28], esi
83 diamond 1818
        call    dword [eax+16]
2987 Serge 1819
        mov     [esp+36+16], ebx
1820
        lea     eax, [esi+511]
83 diamond 1821
        shr     eax, 9
2987 Serge 1822
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
83 diamond 1823
        lea     eax, [eax+ecx-1]
1824
        xor     edx, edx
1825
        div     ecx
2987 Serge 1826
        pop     ecx
83 diamond 1827
        sub     ecx, eax
1828
        call    add_disk_free_space
2987 Serge 1829
        add     esp, 36
83 diamond 1830
        call    update_disk
2987 Serge 1831
        call    fat_unlock
83 diamond 1832
        popad
1833
        ret
321 diamond 1834
.writedir:
1835
        push    512
2987 Serge 1836
        lea     edi, [ebp+FAT.buffer]
321 diamond 1837
        mov     ebx, edi
2987 Serge 1838
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
321 diamond 1839
        shl     ecx, 9
2987 Serge 1840
        cmp     ecx, [esp+16]
321 diamond 1841
        jnz     .writedircont
2987 Serge 1842
        dec     dword [esp+20]
321 diamond 1843
        push    esi
1844
        mov     ecx, 32/4
2434 Serge 1845
        rep movsd
321 diamond 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
2434 Serge 1853
        rep movsd
321 diamond 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
2987 Serge 1859
        mov     ecx, [esp+20+36]
1860
        cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
321 diamond 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
83 diamond 1868
 
2987 Serge 1869
fat_Write.access_denied:
131 diamond 1870
        push    ERROR_ACCESS_DENIED
3908 Serge 1871
fat_Write.ret0:
131 diamond 1872
        pop     eax
1873
        xor     ebx, ebx
1874
        ret
1875
 
3908 Serge 1876
fat_Write.ret11:
2987 Serge 1877
        push    ERROR_DEVICE
3908 Serge 1878
        jmp     fat_Write.ret0
131 diamond 1879
 
2987 Serge 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:
131 diamond 1888
        cmp     byte [esi], 0
1889
        jz      .access_denied
2987 Serge 1890
        call    fat_lock
1891
        push    edi
1892
        stdcall hd_find_lfn, [esp+4+4]
131 diamond 1893
        jnc     .found
2987 Serge 1894
        pop     edi
1895
        push    eax
1896
        call    fat_unlock
3908 Serge 1897
        jmp     .ret0
131 diamond 1898
.found:
1899
; FAT does not support files larger than 4GB
2987 Serge 1900
        cmp     dword [ebx+8], 0
131 diamond 1901
        jz      @f
1902
.eof:
2987 Serge 1903
        pop     edi
131 diamond 1904
        push    ERROR_END_OF_FILE
2987 Serge 1905
        call    fat_unlock
3908 Serge 1906
        jmp     .ret0
131 diamond 1907
@@:
2987 Serge 1908
        mov     ecx, [ebx+12]
1909
        mov     edx, [ebx+16]
1910
        mov     ebx, [ebx+4]
131 diamond 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
2987 Serge 1917
        push    edx
131 diamond 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
2987 Serge 1939
        call    fat_unlock
131 diamond 1940
        pop     eax
1941
        pop     eax
2987 Serge 1942
        pop     ecx
1943
        pop     edx
1944
        pop     edi
131 diamond 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
2987 Serge 1952
        push    0
131 diamond 1953
.ret:
2987 Serge 1954
        pop     eax
1955
        sub     edx, [esp+12]
1956
        mov     ebx, edx        ; ebx=number of written bytes
131 diamond 1957
        call    update_disk
2987 Serge 1958
        test    eax, eax
131 diamond 1959
        jz      @f
2987 Serge 1960
        mov     byte [esp+4], ERROR_DEVICE
131 diamond 1961
@@:
2987 Serge 1962
        call    fat_unlock
131 diamond 1963
        pop     eax
1964
        pop     eax
2987 Serge 1965
        pop     ecx
1966
        pop     edx
1967
        pop     edi
131 diamond 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
2987 Serge 1974
        push    0               ; current sector in cluster
131 diamond 1975
; save directory
2987 Serge 1976
        mov     eax, [esp+12]
131 diamond 1977
        push    ebx
2987 Serge 1978
        lea     ebx, [ebp+FAT.buffer]
1979
        call    fs_write32_sys
131 diamond 1980
        pop     ebx
2987 Serge 1981
        test    eax, eax
131 diamond 1982
        jz      @f
1983
.device_err:
2987 Serge 1984
        mov     byte [esp+8], ERROR_DEVICE
131 diamond 1985
        jmp     .ret
2987 Serge 1986
.fat_err:
1987
        mov     byte [esp+8], ERROR_FAT_TABLE
1988
        jmp     .ret
131 diamond 1989
@@:
1990
 
1991
; now ebx=start pos, ecx=end pos, both lie inside file
1992
        sub     ecx, ebx
1993
        jz      .ret
1994
.write_loop:
321 diamond 1995
; skip unmodified sectors
2987 Serge 1996
        cmp     dword [esp+4], 0x200
321 diamond 1997
        jb      .modify
1998
        sub     ebx, 0x200
1999
        jae     .skip
2000
        add     ebx, 0x200
2001
.modify:
131 diamond 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
2987 Serge 2019
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2020
        add     eax, [ebp+FAT.DATA_START]
2021
        add     eax, [esp+4]
131 diamond 2022
; load sector if needed
2987 Serge 2023
        cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
131 diamond 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
2987 Serge 2029
        push    eax ebx
2030
        lea     ebx, [ebp+FAT.buffer]
2031
        call    fs_read32_app
2032
        test    eax, eax
2033
        pop     ebx eax
131 diamond 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
2987 Serge 2044
        sub     ecx, [esp+8+12]
131 diamond 2045
        jbe     @f
2987 Serge 2046
        lea     edi, [ebp+FAT.buffer]
2047
        add     edi, [esp+8+12]
2434 Serge 2048
        rep stosb
131 diamond 2049
@@:
2050
; zero uninitialized data in the last sector
2051
        mov     ecx, 0x200
2052
        sub     ecx, esi
2053
        jbe     @f
2987 Serge 2054
        lea     edi, [ebp+FAT.buffer+esi]
2434 Serge 2055
        rep stosb
131 diamond 2056
@@:
321 diamond 2057
        pop     edi ecx
131 diamond 2058
; copy new data
2059
        mov     eax, edx
2060
        neg     ebx
2061
        jecxz   @f
2987 Serge 2062
        lea     ebx, [ebp+FAT.buffer+0x200+ebx]
131 diamond 2063
        call    memmove
2064
        xor     ebx, ebx
2065
@@:
2066
        pop     eax
2067
; save sector
2068
        push    ebx
2987 Serge 2069
        lea     ebx, [ebp+FAT.buffer]
2070
        call    fs_write32_app
131 diamond 2071
        pop     ebx
2987 Serge 2072
        test    eax, eax
131 diamond 2073
        jnz     .device_err2
2074
        add     edx, ecx
2075
        sub     [esp], ecx
2076
        pop     ecx
2077
        jz      .ret
321 diamond 2078
.skip:
131 diamond 2079
; next sector
2987 Serge 2080
        pop     eax
2081
        inc     eax
2082
        push    eax
2083
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
131 diamond 2084
        jb      @f
2987 Serge 2085
        and     dword [esp], 0
131 diamond 2086
        mov     eax, edi
2087
        call    get_FAT
2088
        mov     edi, eax
2987 Serge 2089
        jc      .device_err
2090
        cmp     edi, 2
2091
        jb      .fat_err
2092
        cmp     edi, [ebp+FAT.fatRESERVED]
2093
        jae     .fat_err
131 diamond 2094
@@:
2095
        sub     esi, 0x200
2096
        jae     @f
2097
        xor     esi, esi
2098
@@:
2987 Serge 2099
        sub     dword [esp+4], 0x200
131 diamond 2100
        jae     @f
2987 Serge 2101
        and     dword [esp+4], 0
2434 Serge 2102
@@:
2103
        jmp     .write_loop
131 diamond 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
133 diamond 2111
; out: CF=0 => OK, eax=0
2987 Serge 2112
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
131 diamond 2113
hd_extend_file:
2987 Serge 2114
        push    esi
2115
        mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
2116
        imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
131 diamond 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:
2987 Serge 2124
        sub     ecx, esi
131 diamond 2125
        jbe     .last_found
2126
        call    get_FAT
2987 Serge 2127
        jnc     @f
131 diamond 2128
.device_err:
2129
        pop     ecx
2130
.device_err2:
2987 Serge 2131
        pop     esi
2132
        push    ERROR_DEVICE
131 diamond 2133
.ret_err:
2134
        pop     eax
2135
        stc
2136
        ret
2137
@@:
2138
        cmp     eax, 2
2139
        jb      .fat_err
2987 Serge 2140
        cmp     eax, [ebp+FAT.fatRESERVED]
131 diamond 2141
        jb      .last_loop
2142
.fat_err:
2987 Serge 2143
        pop     ecx esi
131 diamond 2144
        push    ERROR_FAT_TABLE
2145
        jmp     .ret_err
2146
.last_found:
2147
        push    eax
2148
        call    get_FAT
2987 Serge 2149
        jnc     @f
131 diamond 2150
        pop     eax
2151
        jmp     .device_err
2152
@@:
2987 Serge 2153
        cmp     eax, [ebp+FAT.fatRESERVED]
131 diamond 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
2987 Serge 2170
        mov     edx, [ebp+FAT.fatEND]
131 diamond 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
@@:
133 diamond 2186
        push    ecx
2187
        mov     ecx, -1
2188
        call    add_disk_free_space
2189
        pop     ecx
131 diamond 2190
        mov     eax, edx
2987 Serge 2191
        add     [edi+28], esi
131 diamond 2192
        jmp     .extend_loop
2193
.extend_done:
2194
        mov     [edi+28], ecx
2987 Serge 2195
        pop     edx esi
133 diamond 2196
        xor     eax, eax        ; CF=0
131 diamond 2197
        ret
2198
.device_err3:
2199
        pop     edx
2200
        jmp     .device_err2
2201
.disk_full:
2987 Serge 2202
        pop     eax edx esi
3626 Serge 2203
        movi    eax, ERROR_DISK_FULL
2434 Serge 2204
        stc
131 diamond 2205
        ret
2206
 
133 diamond 2207
;----------------------------------------------------------------
2987 Serge 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
133 diamond 2217
        cmp     byte [esi], 0
2218
        jnz     @f
2219
.access_denied:
2220
        push    ERROR_ACCESS_DENIED
2987 Serge 2221
.ret:
2222
        call    fat_unlock
2223
        pop     eax
2224
        pop     edi
2225
        ret
133 diamond 2226
@@:
2987 Serge 2227
        stdcall hd_find_lfn, [esp+4+4]
133 diamond 2228
        jnc     @f
2987 Serge 2229
.reteax:
2230
        push    eax
133 diamond 2231
        jmp     .ret
2232
@@:
2233
; must not be directory
2234
        test    byte [edi+11], 10h
2987 Serge 2235
        jnz     .access_denied
133 diamond 2236
; file size must not exceed 4 Gb
2987 Serge 2237
        cmp     dword [ebx+8], 0
133 diamond 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
2987 Serge 2245
        mov     eax, [ebx+4]
133 diamond 2246
        cmp     eax, [edi+28]
2247
        jb      .truncate
2248
        ja      .expand
2249
        pop     eax
2987 Serge 2250
        lea     ebx, [ebp+FAT.buffer]
2251
        call    fs_write32_sys
2252
        test    eax, eax
133 diamond 2253
        jz      @f
2987 Serge 2254
        push    ERROR_DEVICE
2255
        jmp     .ret
133 diamond 2256
@@:
2987 Serge 2257
        push    0
2258
        jmp     .ret
133 diamond 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
2987 Serge 2270
        pop     eax ecx ecx ebp ebx ecx
2271
        jmp     .reteax
133 diamond 2272
.expand_ok:
2273
.disk_full:
2274
; save directory
2275
        mov     eax, [edi+28]
2276
        xchg    eax, [esp+20]
2987 Serge 2277
        lea     ebx, [ebp+FAT.buffer]
2278
        call    fs_write32_sys
2279
        test    eax, eax
133 diamond 2280
        mov     eax, [edi+20-2]
2281
        mov     ax, [edi+26]
2282
        mov     edi, eax
2283
        jz      @f
2284
.pop_ret11:
2987 Serge 2285
        mov     byte [esp], ERROR_DEVICE
133 diamond 2286
        jmp     .pop_ret
2287
@@:
2987 Serge 2288
        test    edi, edi
2289
        jz      .pop_ret
133 diamond 2290
; now zero new data
2987 Serge 2291
        push    0
2292
; edi=current cluster, [esp]=sector in cluster
2293
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
133 diamond 2294
.zero_loop:
2987 Serge 2295
        cmp     edi, 2
2296
        jb      .error_fat
2297
        cmp     edi, [ebp+FAT.fatRESERVED]
2298
        jae     .error_fat
2299
        sub     dword [esp+8], 0x200
133 diamond 2300
        jae     .next_cluster
2301
        lea     eax, [edi-2]
2987 Serge 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
133 diamond 2306
        jz      .noread
2987 Serge 2307
        push    eax
2308
        lea     ebx, [ebp+FAT.buffer]
2309
        call    fs_read32_app
2310
        test    eax, eax
2311
        pop     eax
133 diamond 2312
        jnz     .err_next
2313
.noread:
2987 Serge 2314
        mov     ecx, [esp+8]
133 diamond 2315
        neg     ecx
2316
        push    edi
2987 Serge 2317
        lea     edi, [ebp+FAT.buffer+0x200]
2318
        add     edi, [esp+12]
133 diamond 2319
        push    eax
2320
        xor     eax, eax
2987 Serge 2321
        mov     [esp+16], eax
2434 Serge 2322
        rep stosb
133 diamond 2323
        pop     eax
2324
        pop     edi
2987 Serge 2325
        call    fs_write32_app
2326
        test    eax, eax
133 diamond 2327
        jz      .next_cluster
2328
.err_next:
2987 Serge 2329
        mov     byte [esp+4], ERROR_DEVICE
133 diamond 2330
.next_cluster:
2987 Serge 2331
        pop     eax
133 diamond 2332
        sub     dword [esp+20], 0x200
2333
        jbe     .pop_ret
2987 Serge 2334
        inc     eax
2335
        push    eax
2336
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
133 diamond 2337
        jb      .zero_loop
2987 Serge 2338
        and     dword [esp], 0
133 diamond 2339
        mov     eax, edi
2340
        call    get_FAT
2341
        mov     edi, eax
2987 Serge 2342
        jnc     .zero_loop
2343
        pop     eax
2344
        jmp     .pop_ret11
133 diamond 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
@@:
2987 Serge 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]
133 diamond 2360
        shl     eax, 9
2361
        sub     [esp], eax
2362
        jbe     @f
2363
        mov     eax, ecx
2364
        call    get_FAT
2365
        mov     ecx, eax
2987 Serge 2366
        jnc     @b
133 diamond 2367
.device_err3:
2368
        pop     eax ecx eax edi
2987 Serge 2369
        call    update_disk
2370
        call    fat_unlock
3626 Serge 2371
        movi    eax, ERROR_DEVICE
133 diamond 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
2987 Serge 2379
        mov     edx, [ebp+FAT.fatEND]
133 diamond 2380
        call    set_FAT
2381
        mov     eax, edx
2382
        pop     edx
2987 Serge 2383
        jnc     @f
133 diamond 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
2987 Serge 2395
        jc      .device_err4
133 diamond 2396
; save directory
2397
        mov     eax, [esp+12]
2398
        push    ebx
2987 Serge 2399
        lea     ebx, [ebp+FAT.buffer]
2400
        call    fs_write32_sys
133 diamond 2401
        pop     ebx
2987 Serge 2402
        test    eax, eax
133 diamond 2403
        jnz     .device_err4
2404
; zero last sector, ignore errors
2405
        pop     ecx
2406
        pop     eax
2407
        dec     ecx
2987 Serge 2408
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2409
        add     ecx, [ebp+FAT.DATA_START]
133 diamond 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
2987 Serge 2418
        lea     ebx, [ebp+FAT.buffer]
2419
        call    fs_read32_app
133 diamond 2420
        pop     eax
2987 Serge 2421
        lea     edi, [ebp+FAT.buffer+eax]
133 diamond 2422
        push    ecx
2423
        mov     ecx, 0x200
2424
        sub     ecx, eax
2425
        xor     eax, eax
2434 Serge 2426
        rep stosb
133 diamond 2427
        pop     eax
2987 Serge 2428
        call    fs_write32_app
133 diamond 2429
        pop     ebx
2430
.truncate_done:
2431
        pop     ecx eax edi
2432
        call    update_disk
2987 Serge 2433
        call    fat_unlock
133 diamond 2434
        xor     eax, eax
2435
        ret
2987 Serge 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
3626 Serge 2444
        movi    eax, ERROR_FAT_TABLE
2987 Serge 2445
        ret
133 diamond 2446
 
2987 Serge 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:
86 diamond 2455
        cmp     byte [esi], 0
2456
        jnz     @f
2457
        mov     eax, 2
2458
        ret
2459
@@:
2460
        push    edi
2987 Serge 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
86 diamond 2472
        pop     edi
2473
        ret
2987 Serge 2474
.error:
2475
        push    eax
2476
        call    fat_unlock
2477
        pop     eax
2478
        pop     edi
2479
        ret
86 diamond 2480
 
2987 Serge 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:
86 diamond 2489
        cmp     byte [esi], 0
2490
        jnz     @f
2491
        mov     eax, 2
2492
        ret
2493
@@:
2494
        push    edi
2987 Serge 2495
        call    fat_lock
2496
        stdcall hd_find_lfn, [esp+4+4]
2497
        jc      .error
86 diamond 2498
        push    eax
2987 Serge 2499
        mov     edx, [ebx+16]
86 diamond 2500
        call    bdfe_to_fat_entry
2501
        pop     eax
2987 Serge 2502
        lea     ebx, [ebp+FAT.buffer]
2503
        call    fs_write32_sys
86 diamond 2504
        call    update_disk
2987 Serge 2505
        call    fat_unlock
86 diamond 2506
        pop     edi
2507
        xor     eax, eax
2508
        ret
2987 Serge 2509
.error:
2510
        push    eax
2511
        call    fat_unlock
2512
        pop     eax
2513
        pop     edi
2514
        ret
86 diamond 2515
 
91 diamond 2516
;----------------------------------------------------------------
2987 Serge 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
171 diamond 2525
        cmp     byte [esi], 0
2526
        jnz     @f
2527
; cannot delete root!
2528
.access_denied:
2529
        push    ERROR_ACCESS_DENIED
2987 Serge 2530
.pop_ret:
2531
        call    fat_unlock
2532
        pop     eax
2533
        xor     ebx, ebx
2534
        ret
171 diamond 2535
@@:
2987 Serge 2536
        and     [ebp+FAT.longname_sec1], 0
2537
        and     [ebp+FAT.longname_sec2], 0
171 diamond 2538
        push    edi
2987 Serge 2539
        stdcall hd_find_lfn, [esp+4+4]
171 diamond 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
2987 Serge 2553
        mov     esi, [edi+20-2]
2554
        mov     si, [edi+26]
171 diamond 2555
        xor     ecx, ecx
2987 Serge 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
171 diamond 2562
        jnz     .err1
2987 Serge 2563
        lea     eax, [ebx+0x200]
171 diamond 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
2987 Serge 2571
        cmp     ebx, eax
171 diamond 2572
        jb      .checkempty
2573
        inc     ecx
2987 Serge 2574
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
171 diamond 2575
        jb      @f
2987 Serge 2576
        mov     eax, esi
171 diamond 2577
        call    get_FAT
2987 Serge 2578
        jc      .err1
3232 Serge 2579
        cmp     eax, 2
2580
        jb      .error_fat
2581
        cmp     eax, [ebp+FAT.fatRESERVED]
2582
        jae     .empty
2987 Serge 2583
        mov     esi, eax
171 diamond 2584
        xor     ecx, ecx
2585
@@:
2987 Serge 2586
        lea     eax, [esi-2]
2587
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2588
        add     eax, [ebp+FAT.DATA_START]
171 diamond 2589
        add     eax, ecx
2987 Serge 2590
        lea     ebx, [ebp+FAT.buffer]
2591
        call    fs_read32_sys
2592
        test    eax, eax
2593
        lea     eax, [ebx+0x200]
171 diamond 2594
        jz      .checkempty
2595
.err1:
2596
        popad
2597
.err2:
2598
        pop     edi
2987 Serge 2599
        call    fat_unlock
3626 Serge 2600
        movi    eax, ERROR_DEVICE
171 diamond 2601
        ret
3232 Serge 2602
.error_fat:
2603
        popad
2604
        pop     edi
2605
        call    fat_unlock
3626 Serge 2606
        movi    eax, ERROR_FAT_TABLE
3232 Serge 2607
        ret
171 diamond 2608
.notempty:
2609
        popad
2610
.access_denied2:
2611
        pop     edi
2987 Serge 2612
        call    fat_unlock
3626 Serge 2613
        movi    eax, ERROR_ACCESS_DENIED
171 diamond 2614
        ret
2615
.empty:
2616
        popad
2987 Serge 2617
        push    eax ebx
2618
        lea     ebx, [ebp+FAT.buffer]
2619
        call    fs_read32_sys
2620
        test    eax, eax
2621
        pop     ebx eax
171 diamond 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:
2987 Serge 2632
        lea     edx, [ebp+FAT.buffer]
2633
        cmp     edi, edx
171 diamond 2634
        ja      @f
2987 Serge 2635
        cmp     [ebp+FAT.longname_sec2], 0
171 diamond 2636
        jz      .lfndone
2987 Serge 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
171 diamond 2641
        push    ebx
2987 Serge 2642
        mov     ebx, edx
2643
        call    fs_write32_sys
171 diamond 2644
        mov     eax, [esp+4]
2987 Serge 2645
        call    fs_read32_sys
171 diamond 2646
        pop     ebx
2647
        pop     eax
2987 Serge 2648
        lea     edi, [ebp+FAT.buffer+0x200]
171 diamond 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
2987 Serge 2659
        lea     ebx, [ebp+FAT.buffer]
2660
        call    fs_write32_sys
171 diamond 2661
        pop     ebx
2662
; delete FAT chain
2663
        pop     eax
2664
        call    clear_cluster_chain
2665
        call    update_disk
2987 Serge 2666
        call    fat_unlock
171 diamond 2667
        pop     edi
2668
        xor     eax, eax
2669
        ret
2670
 
1379 turbanoff 2671
; \end{diamond}