Subversion Repositories Kolibri OS

Rev

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