Subversion Repositories Kolibri OS

Rev

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

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