Subversion Repositories Kolibri OS

Rev

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