Subversion Repositories Kolibri OS

Rev

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