Subversion Repositories Kolibri OS

Rev

Rev 3598 | 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: 3631 $
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
2444
        test    eax, eax
2288 clevermous 2445
        jz      @f
2643 clevermous 2446
        push    ERROR_DEVICE
2447
        jmp     .ret
2288 clevermous 2448
@@:
2643 clevermous 2449
        push    0
2450
        jmp     .ret
2288 clevermous 2451
.expand:
2452
        push    ebx ebp ecx
2453
        push    dword [edi+28]  ; save old size
2454
        mov     ecx, eax
2455
        call    hd_extend_file
2456
        push    eax             ; return code
2457
        jnc     .expand_ok
2458
        cmp     al, ERROR_DISK_FULL
2459
        jz      .disk_full
2460
.pop_ret:
2461
        call    update_disk
2643 clevermous 2462
        pop     eax ecx ecx ebp ebx ecx
2463
        jmp     .reteax
2288 clevermous 2464
.expand_ok:
2465
.disk_full:
2466
; save directory
2467
        mov     eax, [edi+28]
2468
        xchg    eax, [esp+20]
2643 clevermous 2469
        lea     ebx, [ebp+FAT.buffer]
2470
        call    fs_write32_sys
2471
        test    eax, eax
2288 clevermous 2472
        mov     eax, [edi+20-2]
2473
        mov     ax, [edi+26]
2474
        mov     edi, eax
2475
        jz      @f
2476
.pop_ret11:
2643 clevermous 2477
        mov     byte [esp], ERROR_DEVICE
2288 clevermous 2478
        jmp     .pop_ret
2479
@@:
2643 clevermous 2480
        test    edi, edi
2481
        jz      .pop_ret
2288 clevermous 2482
; now zero new data
2643 clevermous 2483
        push    0
2484
; edi=current cluster, [esp]=sector in cluster
2485
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
2288 clevermous 2486
.zero_loop:
2643 clevermous 2487
        cmp     edi, 2
2488
        jb      .error_fat
2489
        cmp     edi, [ebp+FAT.fatRESERVED]
2490
        jae     .error_fat
2491
        sub     dword [esp+8], 0x200
2288 clevermous 2492
        jae     .next_cluster
2493
        lea     eax, [edi-2]
2643 clevermous 2494
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2495
        add     eax, [ebp+FAT.DATA_START]
2496
        add     eax, [esp]
2497
        cmp     dword [esp+8], -0x200
2288 clevermous 2498
        jz      .noread
2643 clevermous 2499
        push    eax
2500
        lea     ebx, [ebp+FAT.buffer]
2501
        call    fs_read32_app
2502
        test    eax, eax
2503
        pop     eax
2288 clevermous 2504
        jnz     .err_next
2505
.noread:
2643 clevermous 2506
        mov     ecx, [esp+8]
2288 clevermous 2507
        neg     ecx
2508
        push    edi
2643 clevermous 2509
        lea     edi, [ebp+FAT.buffer+0x200]
2510
        add     edi, [esp+12]
2288 clevermous 2511
        push    eax
2512
        xor     eax, eax
2643 clevermous 2513
        mov     [esp+16], eax
2288 clevermous 2514
        rep stosb
2515
        pop     eax
2516
        pop     edi
2643 clevermous 2517
        call    fs_write32_app
2518
        test    eax, eax
2288 clevermous 2519
        jz      .next_cluster
2520
.err_next:
2643 clevermous 2521
        mov     byte [esp+4], ERROR_DEVICE
2288 clevermous 2522
.next_cluster:
2643 clevermous 2523
        pop     eax
2288 clevermous 2524
        sub     dword [esp+20], 0x200
2525
        jbe     .pop_ret
2643 clevermous 2526
        inc     eax
2527
        push    eax
2528
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2529
        jb      .zero_loop
2643 clevermous 2530
        and     dword [esp], 0
2288 clevermous 2531
        mov     eax, edi
2532
        call    get_FAT
2533
        mov     edi, eax
2643 clevermous 2534
        jnc     .zero_loop
2535
        pop     eax
2536
        jmp     .pop_ret11
2288 clevermous 2537
.truncate:
2538
        mov     [edi+28], eax
2539
        push    ecx
2540
        mov     ecx, [edi+20-2]
2541
        mov     cx, [edi+26]
2542
        push    eax
2543
        test    eax, eax
2544
        jz      .zero_size
2545
; find new last cluster
2546
@@:
2643 clevermous 2547
        cmp     ecx, 2
2548
        jb      .error_fat2
2549
        cmp     ecx, [ebp+FAT.fatRESERVED]
2550
        jae     .error_fat2
2551
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2552
        shl     eax, 9
2553
        sub     [esp], eax
2554
        jbe     @f
2555
        mov     eax, ecx
2556
        call    get_FAT
2557
        mov     ecx, eax
2643 clevermous 2558
        jnc     @b
2288 clevermous 2559
.device_err3:
2560
        pop     eax ecx eax edi
2643 clevermous 2561
        call    update_disk
2562
        call    fat_unlock
3598 clevermous 2563
        movi    eax, ERROR_DEVICE
2288 clevermous 2564
        ret
2565
@@:
2566
; we will zero data at the end of last sector - remember it
2567
        push    ecx
2568
; terminate FAT chain
2569
        push    edx
2570
        mov     eax, ecx
2643 clevermous 2571
        mov     edx, [ebp+FAT.fatEND]
2288 clevermous 2572
        call    set_FAT
2573
        mov     eax, edx
2574
        pop     edx
2643 clevermous 2575
        jnc     @f
2288 clevermous 2576
.device_err4:
2577
        pop     ecx
2578
        jmp     .device_err3
2579
.zero_size:
2580
        and     word [edi+20], 0
2581
        and     word [edi+26], 0
2582
        push    0
2583
        mov     eax, ecx
2584
@@:
2585
; delete FAT chain
2586
        call    clear_cluster_chain
2643 clevermous 2587
        jc      .device_err4
2288 clevermous 2588
; save directory
2589
        mov     eax, [esp+12]
2590
        push    ebx
2643 clevermous 2591
        lea     ebx, [ebp+FAT.buffer]
2592
        call    fs_write32_sys
2288 clevermous 2593
        pop     ebx
2643 clevermous 2594
        test    eax, eax
2288 clevermous 2595
        jnz     .device_err4
2596
; zero last sector, ignore errors
2597
        pop     ecx
2598
        pop     eax
2599
        dec     ecx
2643 clevermous 2600
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2601
        add     ecx, [ebp+FAT.DATA_START]
2288 clevermous 2602
        push    eax
2603
        sar     eax, 9
2604
        add     ecx, eax
2605
        pop     eax
2606
        and     eax, 0x1FF
2607
        jz      .truncate_done
2608
        push    ebx eax
2609
        mov     eax, ecx
2643 clevermous 2610
        lea     ebx, [ebp+FAT.buffer]
2611
        call    fs_read32_app
2288 clevermous 2612
        pop     eax
2643 clevermous 2613
        lea     edi, [ebp+FAT.buffer+eax]
2288 clevermous 2614
        push    ecx
2615
        mov     ecx, 0x200
2616
        sub     ecx, eax
2617
        xor     eax, eax
2618
        rep stosb
2619
        pop     eax
2643 clevermous 2620
        call    fs_write32_app
2288 clevermous 2621
        pop     ebx
2622
.truncate_done:
2623
        pop     ecx eax edi
2624
        call    update_disk
2643 clevermous 2625
        call    fat_unlock
2288 clevermous 2626
        xor     eax, eax
2627
        ret
2643 clevermous 2628
.error_fat:
2629
        pop     eax
2630
        mov     byte [esp], ERROR_FAT_TABLE
2631
        jmp     .pop_ret
2632
.error_fat2:
2633
        pop     eax ecx eax edi
2634
        call    update_disk
2635
        call    fat_unlock
3598 clevermous 2636
        movi    eax, ERROR_FAT_TABLE
2643 clevermous 2637
        ret
2288 clevermous 2638
 
2639
fs_HdGetFileInfo:
2643 clevermous 2640
        cmp     [fs_type], 16
2641
        jz      @f
2642
        cmp     [fs_type], 32
2643
        jz      @f
2288 clevermous 2644
        cmp     [fs_type], 1
2645
        jz      ntfs_HdGetFileInfo
2646
        cmp     [fs_type], 2
2647
        jz      ext2_HdGetFileInfo
2648
        mov     eax, ERROR_UNKNOWN_FS
2649
        ret
2650
@@:
2643 clevermous 2651
        sub     ebx, 4
2652
        push    ebp
2653
        mov     ebp, [fs_dependent_data_start.partition]
2654
        call    fat_GetFileInfo
2655
        pop     ebp
2656
        ret
2657
 
2658
;----------------------------------------------------------------
2659
; fat_GetFileInfo - FAT16/32 implementation of getting file info
2660
; in:  ebp = pointer to FAT structure
2661
; in:  esi+[esp+4] = name
2662
; in:  ebx = pointer to parameters from sysfunc 70
2663
; out: eax, ebx = return values for sysfunc 70
2664
;----------------------------------------------------------------
2665
fat_GetFileInfo:
2288 clevermous 2666
        cmp     byte [esi], 0
2667
        jnz     @f
2668
        mov     eax, 2
2669
        ret
2670
@@:
2671
        push    edi
2643 clevermous 2672
        call    fat_lock
2673
        stdcall hd_find_lfn, [esp+4+4]
2674
        jc      .error
2675
        push    ebp
2676
        xor     ebp, ebp
2677
        mov     esi, [ebx+16]
2678
        mov     dword [esi+4], ebp
2679
        call    fat_entry_to_bdfe2
2680
        pop     ebp
2681
        call    fat_unlock
2682
        xor     eax, eax
2288 clevermous 2683
        pop     edi
2684
        ret
2643 clevermous 2685
.error:
2686
        push    eax
2687
        call    fat_unlock
2688
        pop     eax
2689
        pop     edi
2690
        ret
2288 clevermous 2691
 
2692
fs_HdSetFileInfo:
2643 clevermous 2693
        cmp     [fs_type], 16
2694
        jz      @f
2695
        cmp     [fs_type], 32
2696
        jz      @f
2288 clevermous 2697
        cmp     [fs_type], 1
2698
        jz      ntfs_HdSetFileInfo
2699
        cmp     [fs_type], 2
2700
        jz      ext2_HdSetFileInfo
2701
        mov     eax, ERROR_UNKNOWN_FS
2702
        ret
2703
@@:
2643 clevermous 2704
        sub     ebx, 4
2705
        push    ebp
2706
        mov     ebp, [fs_dependent_data_start.partition]
2707
        call    fat_SetFileInfo
2708
        pop     ebp
2709
        ret
2710
 
2711
;----------------------------------------------------------------
2712
; fat_SetFileInfo - FAT16/32 implementation of setting file info
2713
; in:  ebp = pointer to FAT structure
2714
; in:  esi+[esp+4] = name
2715
; in:  ebx = pointer to parameters from sysfunc 70
2716
; out: eax, ebx = return values for sysfunc 70
2717
;----------------------------------------------------------------
2718
fat_SetFileInfo:
2288 clevermous 2719
        cmp     byte [esi], 0
2720
        jnz     @f
2721
        mov     eax, 2
2722
        ret
2723
@@:
2724
        push    edi
2643 clevermous 2725
        call    fat_lock
2726
        stdcall hd_find_lfn, [esp+4+4]
2727
        jc      .error
2288 clevermous 2728
        push    eax
2643 clevermous 2729
        mov     edx, [ebx+16]
2288 clevermous 2730
        call    bdfe_to_fat_entry
2731
        pop     eax
2643 clevermous 2732
        lea     ebx, [ebp+FAT.buffer]
2733
        call    fs_write32_sys
2288 clevermous 2734
        call    update_disk
2643 clevermous 2735
        call    fat_unlock
2288 clevermous 2736
        pop     edi
2737
        xor     eax, eax
2738
        ret
2643 clevermous 2739
.error:
2740
        push    eax
2741
        call    fat_unlock
2742
        pop     eax
2743
        pop     edi
2744
        ret
2288 clevermous 2745
 
2746
;----------------------------------------------------------------
2747
;
2748
;  fs_HdDelete - delete file or empty folder from hard disk
2749
;
2643 clevermous 2750
;  Obsolete, will be replaced with filesystem-specific functions.
2751
;
2288 clevermous 2752
;  esi  points to filename
2753
;
2754
;  ret  eax = 0 ok or other = errormsg
2755
;
2756
;--------------------------------------------------------------
2757
fs_HdDelete:
2643 clevermous 2758
        cmp     [fs_type], 16
2759
        jz      @f
2760
        cmp     [fs_type], 32
2761
        jz      @f
2288 clevermous 2762
        cmp     [fs_type], 1
2763
        jz      ntfs_HdDelete
2764
        cmp     [fs_type], 2
2765
        jz      ext2_HdDelete
3598 clevermous 2766
        movi    eax, ERROR_UNKNOWN_FS
2288 clevermous 2767
        ret
2768
@@:
2643 clevermous 2769
        sub     ebx, 4
2770
        push    ebp
2771
        mov     ebp, [fs_dependent_data_start.partition]
2772
        call    fat_Delete
2773
        pop     ebp
2774
        ret
2775
 
2776
;----------------------------------------------------------------
2777
; fat_Delete - FAT16/32 implementation of deleting a file/folder
2778
; in:  ebp = pointer to FAT structure
2779
; in:  esi+[esp+4] = name
2780
; in:  ebx = pointer to parameters from sysfunc 70
2781
; out: eax, ebx = return values for sysfunc 70
2782
;----------------------------------------------------------------
2783
fat_Delete:
2784
        call    fat_lock
2288 clevermous 2785
        cmp     byte [esi], 0
2786
        jnz     @f
2787
; cannot delete root!
2788
.access_denied:
2789
        push    ERROR_ACCESS_DENIED
2643 clevermous 2790
.pop_ret:
2791
        call    fat_unlock
2792
        pop     eax
2793
        xor     ebx, ebx
2794
        ret
2288 clevermous 2795
@@:
2643 clevermous 2796
        and     [ebp+FAT.longname_sec1], 0
2797
        and     [ebp+FAT.longname_sec2], 0
2288 clevermous 2798
        push    edi
2643 clevermous 2799
        stdcall hd_find_lfn, [esp+4+4]
2288 clevermous 2800
        jnc     .found
2801
        pop     edi
2802
        push    ERROR_FILE_NOT_FOUND
2803
        jmp     .pop_ret
2804
.found:
2805
        cmp     dword [edi], '.   '
2806
        jz      .access_denied2
2807
        cmp     dword [edi], '..  '
2808
        jz      .access_denied2
2809
        test    byte [edi+11], 10h
2810
        jz      .dodel
2811
; we can delete only empty folders!
2812
        pushad
2643 clevermous 2813
        mov     esi, [edi+20-2]
2814
        mov     si, [edi+26]
2288 clevermous 2815
        xor     ecx, ecx
2643 clevermous 2816
        lea     eax, [esi-2]
2817
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2818
        add     eax, [ebp+FAT.DATA_START]
2819
        lea     ebx, [ebp+FAT.buffer]
2820
        call    fs_read32_sys
2821
        test    eax, eax
2288 clevermous 2822
        jnz     .err1
2643 clevermous 2823
        lea     eax, [ebx+0x200]
2288 clevermous 2824
        add     ebx, 2*0x20
2825
.checkempty:
2826
        cmp     byte [ebx], 0
2827
        jz      .empty
2828
        cmp     byte [ebx], 0xE5
2829
        jnz     .notempty
2830
        add     ebx, 0x20
2643 clevermous 2831
        cmp     ebx, eax
2288 clevermous 2832
        jb      .checkempty
2833
        inc     ecx
2643 clevermous 2834
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2288 clevermous 2835
        jb      @f
2643 clevermous 2836
        mov     eax, esi
2288 clevermous 2837
        call    get_FAT
2643 clevermous 2838
        jc      .err1
3174 clevermous 2839
        cmp     eax, 2
2840
        jb      .error_fat
2841
        cmp     eax, [ebp+FAT.fatRESERVED]
2842
        jae     .empty
2643 clevermous 2843
        mov     esi, eax
2288 clevermous 2844
        xor     ecx, ecx
2845
@@:
2643 clevermous 2846
        lea     eax, [esi-2]
2847
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2848
        add     eax, [ebp+FAT.DATA_START]
2288 clevermous 2849
        add     eax, ecx
2643 clevermous 2850
        lea     ebx, [ebp+FAT.buffer]
2851
        call    fs_read32_sys
2852
        test    eax, eax
2853
        lea     eax, [ebx+0x200]
2288 clevermous 2854
        jz      .checkempty
2855
.err1:
2856
        popad
2857
.err2:
2858
        pop     edi
2643 clevermous 2859
        call    fat_unlock
3598 clevermous 2860
        movi    eax, ERROR_DEVICE
2288 clevermous 2861
        ret
3174 clevermous 2862
.error_fat:
2863
        popad
2864
        pop     edi
2865
        call    fat_unlock
3598 clevermous 2866
        movi    eax, ERROR_FAT_TABLE
3174 clevermous 2867
        ret
2288 clevermous 2868
.notempty:
2869
        popad
2870
.access_denied2:
2871
        pop     edi
2643 clevermous 2872
        call    fat_unlock
3598 clevermous 2873
        movi    eax, ERROR_ACCESS_DENIED
2288 clevermous 2874
        ret
2875
.empty:
2876
        popad
2643 clevermous 2877
        push    eax ebx
2878
        lea     ebx, [ebp+FAT.buffer]
2879
        call    fs_read32_sys
2880
        test    eax, eax
2881
        pop     ebx eax
2288 clevermous 2882
        jnz     .err2
2883
.dodel:
2884
        push    eax
2885
        mov     eax, [edi+20-2]
2886
        mov     ax, [edi+26]
2887
        xchg    eax, [esp]
2888
; delete folder entry
2889
        mov     byte [edi], 0xE5
2890
; delete LFN (if present)
2891
.lfndel:
2643 clevermous 2892
        lea     edx, [ebp+FAT.buffer]
2893
        cmp     edi, edx
2288 clevermous 2894
        ja      @f
2643 clevermous 2895
        cmp     [ebp+FAT.longname_sec2], 0
2288 clevermous 2896
        jz      .lfndone
2643 clevermous 2897
        push    [ebp+FAT.longname_sec2]
2898
        push    [ebp+FAT.longname_sec1]
2899
        pop     [ebp+FAT.longname_sec2]
2900
        and     [ebp+FAT.longname_sec1], 0
2288 clevermous 2901
        push    ebx
2643 clevermous 2902
        mov     ebx, edx
2903
        call    fs_write32_sys
2288 clevermous 2904
        mov     eax, [esp+4]
2643 clevermous 2905
        call    fs_read32_sys
2288 clevermous 2906
        pop     ebx
2907
        pop     eax
2643 clevermous 2908
        lea     edi, [ebp+FAT.buffer+0x200]
2288 clevermous 2909
@@:
2910
        sub     edi, 0x20
2911
        cmp     byte [edi], 0xE5
2912
        jz      .lfndone
2913
        cmp     byte [edi+11], 0xF
2914
        jnz     .lfndone
2915
        mov     byte [edi], 0xE5
2916
        jmp     .lfndel
2917
.lfndone:
2918
        push    ebx
2643 clevermous 2919
        lea     ebx, [ebp+FAT.buffer]
2920
        call    fs_write32_sys
2288 clevermous 2921
        pop     ebx
2922
; delete FAT chain
2923
        pop     eax
2924
        call    clear_cluster_chain
2925
        call    update_disk
2643 clevermous 2926
        call    fat_unlock
2288 clevermous 2927
        pop     edi
2928
        xor     eax, eax
2929
        ret
2930
 
2931
; \end{diamond}