Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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