Subversion Repositories Kolibri OS

Rev

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

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