Subversion Repositories Kolibri OS

Rev

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