Subversion Repositories Kolibri OS

Rev

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

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