Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
425 victor 1
$Revision: 521 $
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:
521 diamond 959
; in: esi+ebp -> name
71 diamond 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
521 diamond 976
.continue:
83 diamond 977
        test    byte [edi+11], 10h
978
        jz      .notfound
979
        and     dword [esp+12], 0
88 diamond 980
        mov     eax, [edi+20-2]
981
        mov     ax, [edi+26]    ; cluster
83 diamond 982
.fat32:
983
        mov     [esp+8], eax
984
        mov     dword [esp+4], fat_notroot_first
985
        mov     dword [esp], fat_notroot_next
986
        jmp     .loop
71 diamond 987
.notfound:
83 diamond 988
        add     esp, 16
989
        pop     edi esi
990
        stc
991
        ret
71 diamond 992
.found:
521 diamond 993
        test    ebp, ebp
994
        jz      @f
995
        mov     esi, ebp
996
        xor     ebp, ebp
997
        jmp     .continue
998
@@:
86 diamond 999
        lea     eax, [esp+8]
1000
        cmp     dword [eax], 0
1001
        jz      .root
1002
        call    fat_get_sector
1003
        jmp     .cmn
1004
.root:
1005
        mov     eax, [eax+4]
1006
        add     eax, [ROOT_START]
1007
.cmn:
83 diamond 1008
        add     esp, 20         ; CF=0
1009
        pop     esi
1010
        ret
74 mario79 1011
 
71 diamond 1012
;----------------------------------------------------------------
1013
;
1014
;  fs_HdRead - LFN variant for reading hard disk
1015
;
1016
;  esi  points to filename
1017
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1018
;       may be ebx=0 - start from first byte
1019
;  ecx  number of bytes to read, 0+
1020
;  edx  mem location to return data
1021
;
77 diamond 1022
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 1023
;      eax = 0 ok read or other = errormsg
1024
;
1025
;--------------------------------------------------------------
1026
fs_HdRead:
256 diamond 1027
        cmp     [fs_type], 16
1028
        jz      @f
1029
        cmp     [fs_type], 32
1030
        jz      @f
1031
        cmp     [fs_type], 1
1032
        jz      ntfs_HdRead
1033
        or      ebx, -1
1034
        mov     eax, ERROR_UNKNOWN_FS
1035
        ret
71 diamond 1036
@@:
74 mario79 1037
    push    edi
1038
    cmp    byte [esi], 0
1039
    jnz    @f
71 diamond 1040
.noaccess:
74 mario79 1041
    pop    edi
1042
.noaccess_2:
1043
    or    ebx, -1
1044
    mov    eax, ERROR_ACCESS_DENIED
1045
    ret
379 serge 1046
 
74 mario79 1047
.noaccess_3:
1048
    add esp,4
1049
.noaccess_1:
1050
    add esp,4
1051
.noaccess_4:
1052
    add esp,4*5
1053
    jmp  .noaccess_2
1054
 
71 diamond 1055
@@:
74 mario79 1056
    call    hd_find_lfn
1057
    jnc    .found
1058
    pop    edi
1059
    cmp   [hd_error],0
1060
    jne   .noaccess_2
1061
    or    ebx, -1
1062
    mov    eax, ERROR_FILE_NOT_FOUND
1063
    ret
1064
 
71 diamond 1065
.found:
74 mario79 1066
    test    byte [edi+11], 0x10    ; do not allow read directories
1067
    jnz    .noaccess
1068
    test    ebx, ebx
1069
    jz    .l1
1070
    cmp    dword [ebx+4], 0
1071
    jz    @f
77 diamond 1072
        xor     ebx, ebx
71 diamond 1073
.reteof:
74 mario79 1074
    mov    eax, 6
1075
    pop    edi
1076
    ret
71 diamond 1077
@@:
74 mario79 1078
    mov    ebx, [ebx]
71 diamond 1079
.l1:
77 diamond 1080
        push    ecx edx
1081
        push    0
1082
        mov     eax, [edi+28]
1083
        sub     eax, ebx
1084
        jb      .eof
1085
        cmp     eax, ecx
1086
        jae     @f
1087
        mov     ecx, eax
1088
        mov     byte [esp], 6
1089
@@:
74 mario79 1090
    mov    eax, [edi+20-2]
1091
    mov    ax, [edi+26]
71 diamond 1092
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
1093
.new_cluster:
74 mario79 1094
    jecxz    .new_sector
1095
    test    eax, eax
1096
    jz    .eof
1097
    cmp    eax, [fatRESERVED]
1098
    jae    .eof
1099
    mov    [cluster_tmp], eax
1100
    dec    eax
1101
    dec    eax
1102
    mov    edi, [SECTORS_PER_CLUSTER]
1103
    imul    eax, edi
1104
    add    eax, [DATA_START]
71 diamond 1105
.new_sector:
74 mario79 1106
    test    ecx, ecx
1107
    jz    .done
1108
    sub    ebx, 512
1109
    jae    .skip
1110
    add    ebx, 512
1111
    jnz    .force_buf
1112
    cmp    ecx, 512
1113
    jb    .force_buf
71 diamond 1114
; we may read directly to given buffer
74 mario79 1115
    push    ebx
1116
    mov    ebx, edx
1117
    call    hd_read
1118
    cmp  [hd_error],0
379 serge 1119
    jne  .noaccess_1
74 mario79 1120
    pop    ebx
1121
    add    edx, 512
1122
    sub    ecx, 512
1123
    jmp    .skip
71 diamond 1124
.force_buf:
1125
; we must read sector to temporary buffer and then copy it to destination
74 mario79 1126
    push    eax ebx
1127
    mov    ebx, buffer
1128
    call    hd_read
1129
    cmp  [hd_error],0
1130
    jne  .noaccess_3
1131
 
1132
    mov    eax, ebx
1133
    pop    ebx
1134
    add    eax, ebx
1135
    push    ecx
1136
    add    ecx, ebx
1137
    cmp    ecx, 512
1138
    jbe    @f
1139
    mov    ecx, 512
71 diamond 1140
@@:
74 mario79 1141
    sub    ecx, ebx
1142
    mov    ebx, edx
1143
    call    memmove
1144
    add    edx, ecx
1145
    sub    [esp], ecx
1146
    pop    ecx
1147
    pop    eax
1148
    xor    ebx, ebx
71 diamond 1149
.skip:
74 mario79 1150
    inc    eax
1151
    dec    edi
1152
    jnz    .new_sector
1153
    mov    eax, [cluster_tmp]
1154
    call    get_FAT
1155
    cmp   [hd_error],0
1156
    jne   .noaccess_4
1157
 
1158
    jmp    .new_cluster
71 diamond 1159
.done:
77 diamond 1160
        mov     ebx, edx
1161
        pop     eax edx ecx edi
1162
        sub     ebx, edx
1163
        ret
71 diamond 1164
.eof:
77 diamond 1165
        mov     ebx, edx
1166
        pop     eax edx ecx
1167
        sub     ebx, edx
1168
        jmp     .reteof
75 diamond 1169
 
1170
;----------------------------------------------------------------
1171
;
1172
;  fs_HdReadFolder - LFN variant for reading hard disk folder
1173
;
1174
;  esi  points to filename
78 diamond 1175
;  ebx  pointer to structure 32-bit number = first wanted block, 0+
1176
;                          & flags (bitfields)
1177
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 1178
;  ecx  number of blocks to read, 0+
1179
;  edx  mem location to return data
1180
;
77 diamond 1181
;  ret ebx = blocks read or 0xffffffff folder not found
75 diamond 1182
;      eax = 0 ok read or other = errormsg
1183
;
1184
;--------------------------------------------------------------
1185
fs_HdReadFolder:
256 diamond 1186
        cmp     [fs_type], 1
1187
        jz      ntfs_HdReadFolder
1188
        cmp     [fs_type], 16
1189
        jz      @f
1190
        cmp     [fs_type], 32
1191
        jz      @f
1192
        push    ERROR_UNSUPPORTED_FS
1193
        pop     eax
1194
        or      ebx, -1
1195
        ret
1196
@@:
75 diamond 1197
        mov     eax, [ROOT_CLUSTER]
1198
        push    edi
1199
        cmp     byte [esi], 0
1200
        jz      .doit
1201
        call    hd_find_lfn
1202
        jnc     .found
1203
        pop     edi
1204
        or      ebx, -1
1205
        mov     eax, ERROR_FILE_NOT_FOUND
1206
        ret
1207
.found:
1208
        test    byte [edi+11], 0x10     ; do not allow read files
1209
        jnz     .found_dir
1210
        pop     edi
1211
        or      ebx, -1
1212
        mov     eax, ERROR_ACCESS_DENIED
1213
        ret
1214
.found_dir:
1215
        mov     eax, [edi+20-2]
1216
        mov     ax, [edi+26]    ; eax=cluster
1217
.doit:
1218
        push    esi ecx
1219
        push    ebp
1220
        sub     esp, 262*2      ; reserve space for LFN
1221
        mov     ebp, esp
78 diamond 1222
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
1223
        mov     ebx, [ebx]
75 diamond 1224
; init header
1225
        push    eax ecx
1226
        mov     edi, edx
1227
        mov     ecx, 32/4
1228
        xor     eax, eax
1229
        rep     stosd
1230
        pop     ecx eax
1231
        mov     byte [edx], 1   ; version
1232
        mov     esi, edi        ; esi points to BDFE
1233
.new_cluster:
1234
        mov     [cluster_tmp], eax
1235
        test    eax, eax
1236
        jnz     @f
256 diamond 1237
        cmp     [fs_type], 32
75 diamond 1238
        jz      .notfound
1239
        mov     eax, [ROOT_START]
1240
        push    [ROOT_SECTORS]
1241
        push    ebx
1242
        jmp     .new_sector
1243
@@:
1244
        dec     eax
1245
        dec     eax
1246
        imul    eax, [SECTORS_PER_CLUSTER]
1247
        push    [SECTORS_PER_CLUSTER]
1248
        add     eax, [DATA_START]
1249
        push    ebx
1250
.new_sector:
1251
        mov     ebx, buffer
1252
        mov     edi, ebx
1253
        call    hd_read
1254
        cmp     [hd_error], 0
1255
        jnz     .notfound2
1256
        add     ebx, 512
1257
        push    eax
1258
.l1:
1259
        call    fat_get_name
1260
        jc      .l2
1261
        cmp     byte [edi+11], 0xF
1262
        jnz     .do_bdfe
1263
        add     edi, 0x20
1264
        cmp     edi, ebx
1265
        jb      .do_bdfe
1266
        pop     eax
1267
        inc     eax
1268
        dec     dword [esp+4]
1269
        jnz     @f
1270
        mov     eax, [cluster_tmp]
1271
        test    eax, eax
1272
        jz      .done
1273
        call    get_FAT
1274
        cmp     [hd_error], 0
1275
        jnz     .notfound2
1276
        cmp     eax, 2
1277
        jb      .done
1278
        cmp     eax, [fatRESERVED]
1279
        jae     .done
1280
        push    eax
1281
        mov     eax, [SECTORS_PER_CLUSTER]
1282
        mov     [esp+8], eax
1283
        pop     eax
1284
        mov     [cluster_tmp], eax
1285
        dec     eax
1286
        dec     eax
1287
        imul    eax, [SECTORS_PER_CLUSTER]
1288
        add     eax, [DATA_START]
1289
@@:
1290
        mov     ebx, buffer
1291
        mov     edi, ebx
1292
        call    hd_read
1293
        cmp     [hd_error], 0
1294
        jnz     .notfound2
1295
        add     ebx, 512
1296
        push    eax
1297
.do_bdfe:
1298
        inc     dword [edx+8]   ; new file found
1299
        dec     dword [esp+4]
1300
        jns     .l2
1301
        dec     ecx
1302
        js      .l2
1303
        inc     dword [edx+4]   ; new file block copied
1304
        call    fat_entry_to_bdfe
1305
.l2:
1306
        add     edi, 0x20
1307
        cmp     edi, ebx
1308
        jb      .l1
1309
        pop     eax
1310
        inc     eax
1311
        dec     dword [esp+4]
1312
        jnz     .new_sector
1313
        mov     eax, [cluster_tmp]
1314
        test    eax, eax
1315
        jz      .done
1316
        call    get_FAT
1317
        cmp     [hd_error], 0
1318
        jnz     .notfound2
1319
        cmp     eax, 2
1320
        jb      .done
1321
        cmp     eax, [fatRESERVED]
1322
        jae     .done
1323
        push    eax
1324
        mov     eax, [SECTORS_PER_CLUSTER]
1325
        mov     [esp+8], eax
1326
        pop     eax
1327
        pop     ebx
1328
        add     esp, 4
1329
        jmp     .new_cluster
1330
.notfound2:
1331
        add     esp, 8
1332
.notfound:
1333
        add     esp, 262*2+4
1334
        pop     ebp ecx esi edi
1335
        mov     eax, ERROR_FILE_NOT_FOUND
1336
        or      ebx, -1
1337
        ret
1338
.done:
1339
        add     esp, 262*2+4+8
1340
        pop     ebp
77 diamond 1341
        mov     ebx, [edx+4]
75 diamond 1342
        xor     eax, eax
1343
        dec     ecx
1344
        js      @f
1345
        mov     al, ERROR_END_OF_FILE
1346
@@:
1347
        pop     ecx esi edi
1348
        ret
1349
 
83 diamond 1350
fat16_root_next:
1351
        cmp     edi, buffer+0x200-0x20
1352
        jae     fat16_root_next_sector
1353
        add     edi, 0x20
1354
        ret     ; CF=0
1355
fat16_root_next_sector:
1356
; read next sector
171 diamond 1357
        push    [longname_sec2]
1358
        pop     [longname_sec1]
83 diamond 1359
        push    ecx
1360
        mov     ecx, [eax+4]
171 diamond 1361
        push    ecx
1362
        add     ecx, [ROOT_START]
1363
        mov     [longname_sec2], ecx
1364
        pop     ecx
83 diamond 1365
        inc     ecx
1366
        mov     [eax+4], ecx
1367
        cmp     ecx, [ROOT_SECTORS]
1368
        pop     ecx
1369
        jae     fat16_root_first.readerr
1370
fat16_root_first:
1371
        mov     eax, [eax+4]
1372
        add     eax, [ROOT_START]
1373
        push    ebx
1374
        mov     edi, buffer
1375
        mov     ebx, edi
1376
        call    hd_read
1377
        pop     ebx
1378
        cmp     [hd_error], 0
1379
        jnz     .readerr
1380
        ret     ; CF=0
1381
.readerr:
1382
        stc
1383
        ret
1384
fat16_root_begin_write:
1385
        push    edi eax
1386
        call    fat16_root_first
1387
        pop     eax edi
1388
        ret
1389
fat16_root_end_write:
1390
        pusha
1391
        mov     eax, [eax+4]
1392
        add     eax, [ROOT_START]
1393
        mov     ebx, buffer
1394
        call    hd_write
1395
        popa
1396
        ret
1397
fat16_root_next_write:
1398
        cmp     edi, buffer+0x200
1399
        jae     @f
1400
        ret
1401
@@:
1402
        call    fat16_root_end_write
1403
        jmp     fat16_root_next_sector
1404
fat16_root_extend_dir:
1405
        stc
1406
        ret
1407
 
1408
fat_notroot_next:
1409
        cmp     edi, buffer+0x200-0x20
1410
        jae     fat_notroot_next_sector
1411
        add     edi, 0x20
1412
        ret     ; CF=0
1413
fat_notroot_next_sector:
171 diamond 1414
        push    [longname_sec2]
1415
        pop     [longname_sec1]
1416
        push    eax
1417
        call    fat_get_sector
1418
        mov     [longname_sec2], eax
1419
        pop     eax
83 diamond 1420
        push    ecx
1421
        mov     ecx, [eax+4]
1422
        inc     ecx
1423
        cmp     ecx, [SECTORS_PER_CLUSTER]
1424
        jae     fat_notroot_next_cluster
1425
        mov     [eax+4], ecx
1426
        jmp     @f
1427
fat_notroot_next_cluster:
1428
        push    eax
1429
        mov     eax, [eax]
1430
        call    get_FAT
1431
        mov     ecx, eax
1432
        pop     eax
1433
        cmp     [hd_error], 0
1434
        jnz     fat_notroot_next_err
1435
        cmp     ecx, [fatRESERVED]
1436
        jae     fat_notroot_next_err
1437
        mov     [eax], ecx
1438
        and     dword [eax+4], 0
1439
@@:
1440
        pop     ecx
1441
fat_notroot_first:
1442
        call    fat_get_sector
1443
        push    ebx
1444
        mov     edi, buffer
1445
        mov     ebx, edi
1446
        call    hd_read
1447
        pop     ebx
1448
        cmp     [hd_error], 0
1449
        jnz     @f
1450
        ret     ; CF=0
1451
fat_notroot_next_err:
1452
        pop     ecx
1453
@@:
1454
        stc
1455
        ret
1456
fat_notroot_begin_write:
1457
        push    eax edi
1458
        call    fat_notroot_first
1459
        pop     edi eax
1460
        ret
1461
fat_notroot_end_write:
1462
        call    fat_get_sector
1463
        push    ebx
1464
        mov     ebx, buffer
1465
        call    hd_write
1466
        pop     ebx
1467
        ret
1468
fat_notroot_next_write:
1469
        cmp     edi, buffer+0x200
1470
        jae     @f
1471
        ret
1472
@@:
1473
        push    eax
1474
        call    fat_notroot_end_write
1475
        pop     eax
1476
        jmp     fat_notroot_next_sector
1477
fat_notroot_extend_dir:
1478
        push    eax
1479
        mov     eax, [eax]
1480
        call    get_free_FAT
1481
        jnc     .found
1482
        pop     eax
1483
        ret     ; CF=1
1484
.found:
1485
        push    edx
1486
        mov     edx, [fatEND]
1487
        call    set_FAT
1488
        mov     edx, eax
1489
        mov     eax, [esp+4]
1490
        mov     eax, [eax]
1491
        push    edx
1492
        call    set_FAT
1493
        pop     edx
1494
        cmp     [hd_error], 0
1495
        jz      @f
1496
        pop     edx
1497
        pop     eax
1498
        stc
1499
        ret
1500
@@:
1501
        push    ecx
1502
        or      ecx, -1
1503
        call    add_disk_free_space
1504
; zero new cluster
1505
        mov     ecx, 512/4
1506
        mov     edi, buffer
1507
        push    edi
1508
        xor     eax, eax
1509
        rep     stosd
1510
        pop     edi
1511
        pop     ecx
1512
        mov     eax, [esp+4]
1513
        mov     [eax], edx
1514
        and     dword [eax+4], 0
1515
        pop     edx
1516
        mov     eax, [eax]
1517
        dec     eax
1518
        dec     eax
1519
        push    ebx ecx
1520
        mov     ecx, [SECTORS_PER_CLUSTER]
1521
        imul    eax, ecx
1522
        add     eax, [DATA_START]
1523
        mov     ebx, edi
1524
@@:
1525
        call    hd_write
1526
        inc     eax
1527
        loop    @b
1528
        pop     ecx ebx eax
1529
        clc
1530
        ret
1531
 
1532
fat_get_sector:
1533
        push    ecx
1534
        mov     ecx, [eax]
1535
        dec     ecx
1536
        dec     ecx
1537
        imul    ecx, [SECTORS_PER_CLUSTER]
1538
        add     ecx, [DATA_START]
1539
        add     ecx, [eax+4]
1540
        mov     eax, ecx
1541
        pop     ecx
1542
        ret
1543
 
1544
;----------------------------------------------------------------
1545
;
1546
;  fs_HdRewrite - LFN variant for writing hard disk
1547
;
1548
;  esi  points to filename
1549
;  ebx  ignored (reserved)
1550
;  ecx  number of bytes to write, 0+
1551
;  edx  mem location to data
1552
;
1553
;  ret ebx = number of written bytes
1554
;      eax = 0 ok read or other = errormsg
1555
;
1556
;--------------------------------------------------------------
1557
fshrad:
1558
        mov     eax, ERROR_ACCESS_DENIED
1559
        xor     ebx, ebx
1560
        ret
1561
fshrfs:
1562
        mov     eax, ERROR_UNKNOWN_FS
1563
        xor     ebx, ebx
1564
        ret
1565
 
321 diamond 1566
fs_HdCreateFolder:
1567
        mov     al, 1
1568
        jmp     fs_HdRewrite.common
1569
 
83 diamond 1570
fs_HdRewrite:
321 diamond 1571
        xor     eax, eax
1572
.common:
256 diamond 1573
        cmp     [fs_type], 1
1574
        jz      ntfs_HdRewrite
1575
        cmp     [fs_type], 16
1576
        jz      @f
1577
        cmp     [fs_type], 32
1578
        jnz     fshrfs
1579
@@:
83 diamond 1580
        cmp     byte [esi], 0
1581
        jz      fshrad
1582
        pushad
521 diamond 1583
        xor     edi, edi
83 diamond 1584
        push    esi
521 diamond 1585
        test    ebp, ebp
1586
        jz      @f
1587
        mov     esi, ebp
83 diamond 1588
@@:
1589
        lodsb
1590
        test    al, al
1591
        jz      @f
1592
        cmp     al, '/'
1593
        jnz     @b
521 diamond 1594
        lea     edi, [esi-1]
83 diamond 1595
        jmp     @b
1596
@@:
1597
        pop     esi
521 diamond 1598
        test    edi, edi
1599
        jnz     .noroot
83 diamond 1600
        test    ebp, ebp
521 diamond 1601
        jnz     .hasebp
83 diamond 1602
        mov     ebp, [ROOT_CLUSTER]
256 diamond 1603
        cmp     [fs_type], 32
83 diamond 1604
        jz      .pushnotroot
1605
        push    fat16_root_extend_dir
1606
        push    fat16_root_end_write
1607
        push    fat16_root_next_write
1608
        push    fat16_root_begin_write
1609
        xor     ebp, ebp
1610
        push    ebp
1611
        push    ebp
1612
        push    fat16_root_first
1613
        push    fat16_root_next
1614
        jmp     .common1
521 diamond 1615
.hasebp:
1616
        mov     eax, ERROR_ACCESS_DENIED
1617
        cmp     byte [ebp], 0
1618
        jz      .ret1
1619
        push    ebp
1620
        xor     ebp, ebp
1621
        call    hd_find_lfn
1622
        pop     esi
1623
        jc      .notfound0
1624
        jmp     .common0
83 diamond 1625
.noroot:
335 diamond 1626
        mov     eax, ERROR_ACCESS_DENIED
521 diamond 1627
        cmp     byte [edi+1], 0
335 diamond 1628
        jz      .ret1
83 diamond 1629
; check existence
521 diamond 1630
        mov     byte [edi], 0
1631
        push    edi
83 diamond 1632
        call    hd_find_lfn
521 diamond 1633
        pop     esi
1634
        mov     byte [esi], '/'
83 diamond 1635
        jnc     @f
521 diamond 1636
.notfound0:
83 diamond 1637
        mov     eax, ERROR_FILE_NOT_FOUND
1638
.ret1:
1639
        mov     [esp+28], eax
1640
        popad
1641
        xor     ebx, ebx
1642
        ret
1643
@@:
521 diamond 1644
        inc     esi
1645
.common0:
83 diamond 1646
        test    byte [edi+11], 0x10     ; must be directory
1647
        mov     eax, ERROR_ACCESS_DENIED
1648
        jz      .ret1
1649
        mov     ebp, [edi+20-2]
1650
        mov     bp, [edi+26]            ; ebp=cluster
1651
        mov     eax, ERROR_FAT_TABLE
1652
        cmp     ebp, 2
1653
        jb      .ret1
1654
.pushnotroot:
1655
        push    fat_notroot_extend_dir
1656
        push    fat_notroot_end_write
1657
        push    fat_notroot_next_write
1658
        push    fat_notroot_begin_write
1659
        push    0
1660
        push    ebp
1661
        push    fat_notroot_first
1662
        push    fat_notroot_next
1663
.common1:
1664
        call    fat_find_lfn
1665
        jc      .notfound
321 diamond 1666
; found
91 diamond 1667
        test    byte [edi+11], 10h
321 diamond 1668
        jz      .exists_file
1669
; found directory; if we are creating directory, return OK,
1670
;                  if we are creating file, say "access denied"
1671
        add     esp, 32
1672
        popad
1673
        test    al, al
1674
        mov     eax, ERROR_ACCESS_DENIED
91 diamond 1675
        jz      @f
321 diamond 1676
        mov     al, 0
1677
@@:
1678
        xor     ebx, ebx
1679
        ret
1680
.exists_file:
1681
; found file; if we are creating directory, return "access denied",
1682
;             if we are creating file, delete existing file and continue
1683
        cmp     byte [esp+32+28], 0
1684
        jz      @f
91 diamond 1685
        add     esp, 32
1686
        popad
1687
        mov     eax, ERROR_ACCESS_DENIED
1688
        xor     ebx, ebx
1689
        ret
1690
@@:
1691
; delete FAT chain
83 diamond 1692
        push    edi
1693
        xor     eax, eax
1694
        mov     dword [edi+28], eax     ; zero size
1695
        xor     ecx, ecx
1696
        mov     eax, [edi+20-2]
1697
        mov     ax, [edi+26]
1698
        mov     word [edi+20], cx
1699
        mov     word [edi+26], cx
1700
        test    eax, eax
1701
        jz      .done1
1702
@@:
1703
        cmp     eax, [fatRESERVED]
1704
        jae     .done1
1705
        push    edx
1706
        xor     edx, edx
1707
        call    set_FAT
1708
        mov     eax, edx
1709
        pop     edx
1710
        inc     ecx
1711
        jmp     @b
1712
.done1:
1713
        pop     edi
1714
        call    get_time_for_file
1715
        mov     [edi+22], ax
1716
        call    get_date_for_file
1717
        mov     [edi+24], ax
1718
        mov     [edi+18], ax
1719
        or      byte [edi+11], 20h      ; set 'archive' attribute
1720
        jmp     .doit
1721
.notfound:
1722
; file is not found; generate short name
1723
        call    fat_name_is_legal
1724
        jc      @f
1725
        add     esp, 32
1726
        popad
1727
        mov     eax, ERROR_FILE_NOT_FOUND
1728
        xor     ebx, ebx
1729
        ret
1730
@@:
1731
        sub     esp, 12
1732
        mov     edi, esp
1733
        call    fat_gen_short_name
1734
.test_short_name_loop:
1735
        push    esi edi ecx
1736
        mov     esi, edi
1737
        lea     eax, [esp+12+12+8]
1738
        mov     [eax], ebp
1739
        and     dword [eax+4], 0
1740
        call    dword [eax-4]
1741
        jc      .found
1742
.test_short_name_entry:
1743
        cmp     byte [edi+11], 0xF
1744
        jz      .test_short_name_cont
1745
        mov     ecx, 11
1746
        push    esi edi
1747
        repz    cmpsb
1748
        pop     edi esi
1749
        jz      .short_name_found
1750
.test_short_name_cont:
1751
        lea     eax, [esp+12+12+8]
1752
        call    dword [eax-8]
1753
        jnc     .test_short_name_entry
1754
        jmp     .found
1755
.short_name_found:
1756
        pop     ecx edi esi
1757
        call    fat_next_short_name
1758
        jnc     .test_short_name_loop
1759
.disk_full:
1760
        add     esp, 12+32
1761
        popa
1762
        mov     eax, ERROR_DISK_FULL
1763
        xor     ebx, ebx
1764
        ret
1765
.found:
1766
        pop     ecx edi esi
1767
; now find space in directory
1768
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
1769
        mov     al, '~'
1770
        push    ecx edi
1771
        mov     ecx, 8
1772
        repnz   scasb
1773
        push    1
1774
        pop     eax     ; 1 entry
1775
        jnz     .notilde
1776
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
1777
        xor     eax, eax
1778
@@:
1779
        cmp     byte [esi], 0
1780
        jz      @f
1781
        inc     esi
1782
        inc     eax
1783
        jmp     @b
1784
@@:
1785
        sub     esi, eax
1786
        add     eax, 12+13
1787
        mov     ecx, 13
1788
        push    edx
1789
        cdq
1790
        div     ecx
1791
        pop     edx
1792
.notilde:
1793
        push    -1
1794
        push    -1
1795
        push    -1
1796
; find  successive entries in directory
1797
        xor     ecx, ecx
1798
        push    eax
1799
        lea     eax, [esp+16+8+12+8]
1800
        mov     [eax], ebp
1801
        and     dword [eax+4], 0
1802
        call    dword [eax-4]
1803
        pop     eax
1804
        jnc     .scan_dir
1805
.fsfrfe3:
1806
        add     esp, 12+8+12+32
1807
        popad
1808
        mov     eax, 11
1809
        xor     ebx, ebx
1810
        ret
1811
.scan_dir:
1812
        cmp     byte [edi], 0
1813
        jz      .free
1814
        cmp     byte [edi], 0xE5
1815
        jz      .free
1816
        xor     ecx, ecx
1817
.scan_cont:
1818
        push    eax
1819
        lea     eax, [esp+16+8+12+8]
1820
        call    dword [eax-8]
1821
        pop     eax
1822
        jnc     .scan_dir
1823
        cmp     [hd_error], 0
1824
        jnz     .fsfrfe3
1825
        push    eax
1826
        lea     eax, [esp+16+8+12+8]
1827
        call    dword [eax+20]          ; extend directory
1828
        pop     eax
1829
        jnc     .scan_dir
1830
        add     esp, 12+8+12+32
1831
        popad
1832
        mov     eax, ERROR_DISK_FULL
1833
        xor     ebx, ebx
1834
        ret
1835
.free:
1836
        test    ecx, ecx
1837
        jnz     @f
1838
        mov     [esp], edi
1839
        mov     ecx, [esp+12+8+12+8]
1840
        mov     [esp+4], ecx
1841
        mov     ecx, [esp+12+8+12+12]
1842
        mov     [esp+8], ecx
1843
        xor     ecx, ecx
1844
@@:
1845
        inc     ecx
1846
        cmp     ecx, eax
1847
        jb      .scan_cont
1848
; found!
1849
; calculate name checksum
1850
        push    esi ecx
1851
        mov     esi, [esp+8+12]
1852
        mov     ecx, 11
1853
        xor     eax, eax
1854
@@:
1855
        ror     al, 1
1856
        add     al, [esi]
1857
        inc     esi
1858
        loop    @b
1859
        pop     ecx esi
1860
        pop     edi
1861
        pop     dword [esp+8+12+12]
1862
        pop     dword [esp+8+12+12]
1863
; edi points to first entry in free chunk
1864
        dec     ecx
1865
        jz      .nolfn
1866
        push    esi
1867
        push    eax
1868
        lea     eax, [esp+8+8+12+8]
1869
        call    dword [eax+8]         ; begin write
1870
        mov     al, 40h
1871
.writelfn:
1872
        or      al, cl
1873
        mov     esi, [esp+4]
1874
        push    ecx
1875
        dec     ecx
1876
        imul    ecx, 13
1877
        add     esi, ecx
1878
        stosb
1879
        mov     cl, 5
1880
        call    fs_RamdiskRewrite.read_symbols
1881
        mov     ax, 0xF
1882
        stosw
1883
        mov     al, [esp+4]
1884
        stosb
1885
        mov     cl, 6
1886
        call    fs_RamdiskRewrite.read_symbols
1887
        xor     eax, eax
1888
        stosw
1889
        mov     cl, 2
1890
        call    fs_RamdiskRewrite.read_symbols
1891
        pop     ecx
1892
        lea     eax, [esp+8+8+12+8]
1893
        call    dword [eax+12]         ; next write
1894
        xor     eax, eax
1895
        loop    .writelfn
1896
        pop     eax
1897
        pop     esi
1898
;        lea     eax, [esp+8+12+8]
1899
;        call    dword [eax+16]          ; end write
1900
.nolfn:
1901
        xchg    esi, [esp]
1902
        mov     ecx, 11
1903
        rep     movsb
1904
        mov     word [edi], 20h         ; attributes
1905
        sub     edi, 11
1906
        pop     esi ecx
1907
        add     esp, 12
1908
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1909
        call    get_time_for_file
1910
        mov     [edi+14], ax            ; creation time
1911
        mov     [edi+22], ax            ; last write time
1912
        call    get_date_for_file
1913
        mov     [edi+16], ax            ; creation date
1914
        mov     [edi+24], ax            ; last write date
1915
        mov     [edi+18], ax            ; last access date
1916
        xor     ecx, ecx
1917
        mov     word [edi+20], cx       ; high word of cluster
1918
        mov     word [edi+26], cx       ; low word of cluster - to be filled
1919
        mov     dword [edi+28], ecx     ; file size - to be filled
321 diamond 1920
        cmp     byte [esp+32+28], cl
1921
        jz      .doit
1922
; create directory
1923
        mov     byte [edi+11], 10h      ; attributes: folder
1924
        mov     edx, edi
1925
        lea     eax, [esp+8]
1926
        call    dword [eax+16]  ; flush directory
1927
        push    ecx
1928
        mov     ecx, [SECTORS_PER_CLUSTER]
1929
        shl     ecx, 9
1930
        jmp     .doit2
83 diamond 1931
.doit:
1932
        lea     eax, [esp+8]
1933
        call    dword [eax+16]  ; flush directory
1934
        push    ecx
1935
        mov     ecx, [esp+4+32+24]
321 diamond 1936
.doit2:
83 diamond 1937
        push    ecx
1938
        push    edi
1939
        mov     esi, edx
1940
        test    ecx, ecx
1941
        jz      .done
1942
        mov     eax, 2
1943
        call    get_free_FAT
1944
        jc      .diskfull
1945
        push    eax
1946
        mov     [edi+26], ax
1947
        shr     eax, 16
1948
        mov     [edi+20], ax
1949
        lea     eax, [esp+16+8]
1950
        call    dword [eax+16]  ; flush directory
1951
        pop     eax
1952
        push    edx
1953
        mov     edx, [fatEND]
1954
        call    set_FAT
1955
        pop     edx
1956
.write_cluster:
1957
        push    eax
1958
        dec     eax
1959
        dec     eax
1960
        mov     ebp, [SECTORS_PER_CLUSTER]
1961
        imul    eax, ebp
1962
        add     eax, [DATA_START]
1963
; write data
1964
.write_sector:
321 diamond 1965
        cmp     byte [esp+16+32+28], 0
1966
        jnz     .writedir
83 diamond 1967
        mov     ecx, 512
1968
        cmp     dword [esp+8], ecx
1969
        jb      .writeshort
1970
; we can write directly from given buffer
1971
        mov     ebx, esi
1972
        add     esi, ecx
1973
        jmp     .writecommon
1974
.writeshort:
1975
        mov     ecx, [esp+8]
1976
        push    ecx
1977
        mov     edi, buffer
1978
        mov     ebx, edi
1979
        rep     movsb
321 diamond 1980
.writedircont:
83 diamond 1981
        mov     ecx, buffer+0x200
1982
        sub     ecx, edi
1983
        push    eax
1984
        xor     eax, eax
1985
        rep     stosb
1986
        pop     eax
1987
        pop     ecx
1988
.writecommon:
1989
        call    hd_write
1990
        cmp     [hd_error], 0
1991
        jnz     .writeerr
1992
        inc     eax
1993
        sub     dword [esp+8], ecx
1994
        jz      .writedone
1995
        dec     ebp
1996
        jnz     .write_sector
1997
; allocate new cluster
1998
        pop     eax
1999
        mov     ecx, eax
2000
        call    get_free_FAT
2001
        jc      .diskfull
2002
        push    edx
2003
        mov     edx, [fatEND]
2004
        call    set_FAT
2005
        xchg    eax, ecx
2006
        mov     edx, ecx
2007
        call    set_FAT
2008
        pop     edx
2009
        xchg    eax, ecx
2010
        jmp     .write_cluster
2011
.diskfull:
2012
        mov     eax, ERROR_DISK_FULL
2013
        jmp     .ret
2014
.writeerr:
2015
        pop     eax
2016
        sub     esi, ecx
2017
        mov     eax, 11
2018
        jmp     .ret
2019
.writedone:
2020
        pop     eax
2021
.done:
2022
        xor     eax, eax
2023
.ret:
2024
        pop     edi ecx
2025
        mov     ebx, esi
2026
        sub     ebx, edx
2027
        pop     ebp
2028
        mov     [esp+32+28], eax
2029
        lea     eax, [esp+8]
2030
        call    dword [eax+8]
2031
        mov     [edi+28], ebx
2032
        call    dword [eax+16]
2033
        mov     [esp+32+16], ebx
2034
        lea     eax, [ebx+511]
2035
        shr     eax, 9
2036
        mov     ecx, [SECTORS_PER_CLUSTER]
2037
        lea     eax, [eax+ecx-1]
2038
        xor     edx, edx
2039
        div     ecx
2040
        mov     ecx, ebp
2041
        sub     ecx, eax
2042
        call    add_disk_free_space
2043
        add     esp, 32
2044
        call    update_disk
2045
        popad
2046
        ret
321 diamond 2047
.writedir:
2048
        push    512
2049
        mov     edi, buffer
2050
        mov     ebx, edi
2051
        mov     ecx, [SECTORS_PER_CLUSTER]
2052
        shl     ecx, 9
2053
        cmp     ecx, [esp+12]
2054
        jnz     .writedircont
2055
        dec     dword [esp+16]
2056
        push    esi
2057
        mov     ecx, 32/4
2058
        rep     movsd
2059
        pop     esi
2060
        mov     dword [edi-32], '.   '
2061
        mov     dword [edi-32+4], '    '
2062
        mov     dword [edi-32+8], '    '
2063
        mov     byte [edi-32+11], 10h
2064
        push    esi
2065
        mov     ecx, 32/4
2066
        rep     movsd
2067
        pop     esi
2068
        mov     dword [edi-32], '..  '
2069
        mov     dword [edi-32+4], '    '
2070
        mov     dword [edi-32+8], '    '
2071
        mov     byte [edi-32+11], 10h
2072
        mov     ecx, [esp+20+8]
2073
        cmp     ecx, [ROOT_CLUSTER]
2074
        jnz     @f
2075
        xor     ecx, ecx
2076
@@:
2077
        mov     word [edi-32+26], cx
2078
        shr     ecx, 16
2079
        mov     [edi-32+20], cx
2080
        jmp     .writedircont
83 diamond 2081
 
131 diamond 2082
;----------------------------------------------------------------
2083
;
256 diamond 2084
;  fs_HdWrite - LFN variant for writing to hard disk
131 diamond 2085
;
2086
;  esi  points to filename
2087
;  ebx  pointer to 64-bit number = first wanted byte, 0+
2088
;       may be ebx=0 - start from first byte
2089
;  ecx  number of bytes to write, 0+
2090
;  edx  mem location to data
2091
;
2092
;  ret ebx = bytes written (maybe 0)
2093
;      eax = 0 ok write or other = errormsg
2094
;
2095
;--------------------------------------------------------------
2096
fs_HdWrite.access_denied:
2097
        push    ERROR_ACCESS_DENIED
2098
fs_HdWrite.ret0:
2099
        pop     eax
2100
        xor     ebx, ebx
2101
        ret
2102
 
2103
fs_HdWrite.ret11:
2104
        push    11
2105
        jmp     fs_HdWrite.ret0
2106
 
2107
fs_HdWrite:
256 diamond 2108
        cmp     [fs_type], 1
2109
        jz      ntfs_HdWrite
2110
        cmp     [fs_type], 16
2111
        jz      @f
2112
        cmp     [fs_type], 32
2113
        jz      @f
131 diamond 2114
        push    ERROR_UNKNOWN_FS
2115
        jmp     .ret0
2116
@@:
2117
        cmp     byte [esi], 0
2118
        jz      .access_denied
2119
        pushad
2120
        call    hd_find_lfn
2121
        pushfd
2122
        cmp     [hd_error], 0
2123
        jz      @f
2124
        popfd
2125
        popad
2126
        push    11
2127
        jmp     .ret0
2128
@@:
2129
        popfd
2130
        jnc     .found
2131
        popad
2132
        push    ERROR_FILE_NOT_FOUND
2133
        jmp     .ret0
2134
.found:
2135
; FAT does not support files larger than 4GB
2136
        test    ebx, ebx
2137
        jz      .l1
2138
        cmp     dword [ebx+4], 0
2139
        jz      @f
2140
.eof:
2141
        popad
2142
        push    ERROR_END_OF_FILE
2143
        jmp     .ret0
2144
@@:
2145
        mov     ebx, [ebx]
2146
.l1:
2147
; now edi points to direntry, ebx=start byte to write,
2148
; ecx=number of bytes to write, edx=data pointer
2149
 
2150
; extend file if needed
2151
        add     ecx, ebx
2152
        jc      .eof    ; FAT does not support files larger than 4GB
2153
        push    eax     ; save directory sector
2154
        push    0       ; return value=0
2155
 
2156
        call    get_time_for_file
2157
        mov     [edi+22], ax            ; last write time
2158
        call    get_date_for_file
2159
        mov     [edi+24], ax            ; last write date
2160
        mov     [edi+18], ax            ; last access date
2161
 
2162
        push    dword [edi+28]          ; save current file size
2163
        cmp     ecx, [edi+28]
2164
        jbe     .length_ok
2165
        cmp     ecx, ebx
2166
        jz      .length_ok
2167
        call    hd_extend_file
2168
        jnc     .length_ok
2169
        mov     [esp+4], eax
2170
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
2171
; First two cases are fatal errors, in third case we may write some data
2172
        cmp     al, ERROR_DISK_FULL
2173
        jz      .disk_full
2174
        pop     eax
2175
        pop     eax
2176
        mov     [esp+4+28], eax
2177
        pop     eax
2178
        popad
2179
        xor     ebx, ebx
2180
        ret
2181
.disk_full:
2182
; correct number of bytes to write
2183
        mov     ecx, [edi+28]
2184
        cmp     ecx, ebx
2185
        ja      .length_ok
2186
.ret:
2187
        call    update_disk
2188
        cmp     [hd_error], 0
2189
        jz      @f
2190
        mov     byte [esp+4], 11
2191
@@:
2192
        pop     eax
2193
        pop     eax
2194
        mov     [esp+4+28], eax ; eax=return value
2195
        pop     eax
2196
        sub     edx, [esp+20]
2197
        mov     [esp+16], edx   ; ebx=number of written bytes
2198
        popad
2199
        ret
2200
.length_ok:
2201
        mov     esi, [edi+28]
2202
        mov     eax, [edi+20-2]
2203
        mov     ax, [edi+26]
2204
        mov     edi, eax        ; edi=current cluster
2205
        xor     ebp, ebp        ; ebp=current sector in cluster
2206
; save directory
2207
        mov     eax, [esp+8]
2208
        push    ebx
2209
        mov     ebx, buffer
2210
        call    hd_write
2211
        pop     ebx
2212
        cmp     [hd_error], 0
2213
        jz      @f
2214
.device_err:
2215
        mov     byte [esp+4], 11
2216
        jmp     .ret
2217
@@:
2218
 
2219
; now ebx=start pos, ecx=end pos, both lie inside file
2220
        sub     ecx, ebx
2221
        jz      .ret
2222
.write_loop:
321 diamond 2223
; skip unmodified sectors
2224
        cmp     dword [esp], 0x200
2225
        jb      .modify
2226
        sub     ebx, 0x200
2227
        jae     .skip
2228
        add     ebx, 0x200
2229
.modify:
131 diamond 2230
; get length of data in current sector
2231
        push    ecx
2232
        sub     ebx, 0x200
2233
        jb      .hasdata
2234
        neg     ebx
2235
        xor     ecx, ecx
2236
        jmp     @f
2237
.hasdata:
2238
        neg     ebx
2239
        cmp     ecx, ebx
2240
        jbe     @f
2241
        mov     ecx, ebx
2242
@@:
2243
; get current sector number
2244
        mov     eax, edi
2245
        dec     eax
2246
        dec     eax
2247
        imul    eax, [SECTORS_PER_CLUSTER]
2248
        add     eax, [DATA_START]
2249
        add     eax, ebp
2250
; load sector if needed
2251
        cmp     dword [esp+4], 0        ; we don't need to read uninitialized data
2252
        jz      .noread
2253
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
2254
        jz      .noread
2255
        cmp     ecx, esi        ; (same for the last sector)
2256
        jz      .noread
2257
        push    ebx
2258
        mov     ebx, buffer
2259
        call    hd_read
2260
        pop     ebx
2261
        cmp     [hd_error], 0
2262
        jz      @f
2263
.device_err2:
2264
        pop     ecx
2265
        jmp     .device_err
2266
@@:
2267
.noread:
2268
; zero uninitialized data if file was extended (because hd_extend_file does not this)
2269
        push    eax ecx edi
2270
        xor     eax, eax
2271
        mov     ecx, 0x200
2272
        sub     ecx, [esp+4+12]
2273
        jbe     @f
2274
        mov     edi, buffer
2275
        add     edi, [esp+4+12]
2276
        rep     stosb
2277
@@:
2278
; zero uninitialized data in the last sector
2279
        mov     ecx, 0x200
2280
        sub     ecx, esi
2281
        jbe     @f
2282
        mov     edi, buffer
2283
        add     edi, esi
2284
        rep     stosb
2285
@@:
321 diamond 2286
        pop     edi ecx
131 diamond 2287
; copy new data
2288
        mov     eax, edx
2289
        neg     ebx
2290
        jecxz   @f
2291
        add     ebx, buffer+0x200
2292
        call    memmove
2293
        xor     ebx, ebx
2294
@@:
2295
        pop     eax
2296
; save sector
2297
        push    ebx
2298
        mov     ebx, buffer
2299
        call    hd_write
2300
        pop     ebx
2301
        cmp     [hd_error], 0
2302
        jnz     .device_err2
2303
        add     edx, ecx
2304
        sub     [esp], ecx
2305
        pop     ecx
2306
        jz      .ret
321 diamond 2307
.skip:
131 diamond 2308
; next sector
2309
        inc     ebp
2310
        cmp     ebp, [SECTORS_PER_CLUSTER]
2311
        jb      @f
2312
        xor     ebp, ebp
2313
        mov     eax, edi
2314
        call    get_FAT
2315
        mov     edi, eax
2316
        cmp     [hd_error], 0
2317
        jnz     .device_err
2318
@@:
2319
        sub     esi, 0x200
2320
        jae     @f
2321
        xor     esi, esi
2322
@@:
2323
        sub     dword [esp], 0x200
2324
        jae     @f
2325
        and     dword [esp], 0
2326
@@:     jmp     .write_loop
2327
 
2328
hd_extend_file.zero_size:
2329
        xor     eax, eax
2330
        jmp     hd_extend_file.start_extend
2331
 
2332
; extends file on hd to given size (new data area is undefined)
2333
; in: edi->direntry, ecx=new size
133 diamond 2334
; out: CF=0 => OK, eax=0
131 diamond 2335
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11)
2336
hd_extend_file:
2337
        push    ebp
2338
        mov     ebp, [SECTORS_PER_CLUSTER]
2339
        imul    ebp, [BYTES_PER_SECTOR]
2340
        push    ecx
2341
; find the last cluster of file
2342
        mov     eax, [edi+20-2]
2343
        mov     ax, [edi+26]
2344
        mov     ecx, [edi+28]
2345
        jecxz   .zero_size
2346
.last_loop:
2347
        sub     ecx, ebp
2348
        jbe     .last_found
2349
        call    get_FAT
2350
        cmp     [hd_error], 0
2351
        jz      @f
2352
.device_err:
2353
        pop     ecx
2354
.device_err2:
2355
        pop     ebp
2356
        push    11
2357
.ret_err:
2358
        pop     eax
2359
        stc
2360
        ret
2361
@@:
2362
        cmp     eax, 2
2363
        jb      .fat_err
2364
        cmp     eax, [fatRESERVED]
2365
        jb      .last_loop
2366
.fat_err:
2367
        pop     ecx ebp
2368
        push    ERROR_FAT_TABLE
2369
        jmp     .ret_err
2370
.last_found:
2371
        push    eax
2372
        call    get_FAT
2373
        cmp     [hd_error], 0
2374
        jz      @f
2375
        pop     eax
2376
        jmp     .device_err
2377
@@:
2378
        cmp     eax, [fatRESERVED]
2379
        pop     eax
2380
        jb      .fat_err
2381
; set length to full number of clusters
2382
        sub     [edi+28], ecx
2383
.start_extend:
2384
        pop     ecx
2385
; now do extend
2386
        push    edx
2387
        mov     edx, 2          ; start scan from cluster 2
2388
.extend_loop:
2389
        cmp     [edi+28], ecx
2390
        jae     .extend_done
2391
; add new cluster
2392
        push    eax
2393
        mov     eax, edx
2394
        call    get_free_FAT
2395
        jc      .disk_full
2396
        mov     edx, [fatEND]
2397
        call    set_FAT
2398
        mov     edx, eax
2399
        pop     eax
2400
        test    eax, eax
2401
        jz      .first_cluster
2402
        push    edx
2403
        call    set_FAT
2404
        pop     edx
2405
        jmp     @f
2406
.first_cluster:
2407
        ror     edx, 16
2408
        mov     [edi+20], dx
2409
        ror     edx, 16
2410
        mov     [edi+26], dx
2411
@@:
133 diamond 2412
        push    ecx
2413
        mov     ecx, -1
2414
        call    add_disk_free_space
2415
        pop     ecx
131 diamond 2416
        mov     eax, edx
2417
        cmp     [hd_error], 0
2418
        jnz     .device_err3
2419
        add     [edi+28], ebp
2420
        jmp     .extend_loop
2421
.extend_done:
2422
        mov     [edi+28], ecx
2423
        pop     edx ebp
133 diamond 2424
        xor     eax, eax        ; CF=0
131 diamond 2425
        ret
2426
.device_err3:
2427
        pop     edx
2428
        jmp     .device_err2
2429
.disk_full:
2430
        pop     eax edx ebp
2431
        push    ERROR_DISK_FULL
2432
        pop     eax
2433
        cmp     [hd_error], 0
2434
        jz      @f
2435
        mov     al, 11
2436
@@:     stc
2437
        ret
2438
 
133 diamond 2439
;----------------------------------------------------------------
2440
;
2441
;  fs_HdSetFileEnd - set end of file on hard disk
2442
;
2443
;  esi  points to filename
2444
;  ebx  points to 64-bit number = new file size
2445
;  ecx  ignored (reserved)
2446
;  edx  ignored (reserved)
2447
;
2448
;  ret eax = 0 ok or other = errormsg
2449
;
2450
;--------------------------------------------------------------
2451
fs_HdSetFileEnd:
256 diamond 2452
        cmp     [fs_type], 1
2453
        jz      ntfs_HdSetFileEnd
2454
        cmp     [fs_type], 16
2455
        jz      @f
2456
        cmp     [fs_type], 32
2457
        jz      @f
133 diamond 2458
        push    ERROR_UNKNOWN_FS
2459
.ret:
2460
        pop     eax
2461
        ret
2462
@@:
2463
        cmp     byte [esi], 0
2464
        jnz     @f
2465
.access_denied:
2466
        push    ERROR_ACCESS_DENIED
2467
        jmp     .ret
2468
@@:
2469
        push    edi
2470
        call    hd_find_lfn
2471
        pushfd
2472
        cmp     [hd_error], 0
2473
        jz      @f
2474
        popfd
2475
        push    11
2476
        jmp     .ret
2477
@@:
2478
        popfd
2479
        jnc     @f
2480
        pop     edi
2481
        push    ERROR_FILE_NOT_FOUND
2482
        jmp     .ret
2483
@@:
2484
; must not be directory
2485
        test    byte [edi+11], 10h
2486
        jz      @f
2487
        pop     edi
2488
        jmp     .access_denied
2489
@@:
2490
; file size must not exceed 4 Gb
2491
        cmp     dword [ebx+4], 0
2492
        jz      @f
2493
        pop     edi
2494
        push    ERROR_END_OF_FILE
2495
        jmp     .ret
2496
@@:
2497
        push    eax     ; save directory sector
2498
; set file modification date/time to current
2499
        call    fat_update_datetime
2500
        mov     eax, [ebx]
2501
        cmp     eax, [edi+28]
2502
        jb      .truncate
2503
        ja      .expand
2504
        pop     eax
2505
        mov     ebx, buffer
2506
        call    hd_write
2507
        pop     edi
2508
        xor     eax, eax
2509
        cmp     [hd_error], 0
2510
        jz      @f
2511
        mov     al, 11
2512
@@:
2513
        ret
2514
.expand:
2515
        push    ebx ebp ecx
2516
        push    dword [edi+28]  ; save old size
2517
        mov     ecx, eax
2518
        call    hd_extend_file
2519
        push    eax             ; return code
2520
        jnc     .expand_ok
2521
        cmp     al, ERROR_DISK_FULL
2522
        jz      .disk_full
2523
.pop_ret:
2524
        call    update_disk
2525
        pop     eax ecx ebp ebx ecx edi edi
2526
        ret
2527
.expand_ok:
2528
.disk_full:
2529
; save directory
2530
        mov     eax, [edi+28]
2531
        xchg    eax, [esp+20]
2532
        mov     ebx, buffer
2533
        call    hd_write
2534
        mov     eax, [edi+20-2]
2535
        mov     ax, [edi+26]
2536
        mov     edi, eax
2537
        cmp     [hd_error], 0
2538
        jz      @f
2539
.pop_ret11:
2540
        mov     byte [esp], 11
2541
        jmp     .pop_ret
2542
@@:
2543
; now zero new data
2544
        xor     ebp, ebp
2545
; edi=current cluster, ebp=sector in cluster
2546
; [esp+20]=new size, [esp+4]=old size, [esp]=return code
2547
.zero_loop:
2548
        sub     dword [esp+4], 0x200
2549
        jae     .next_cluster
2550
        lea     eax, [edi-2]
2551
        imul    eax, [SECTORS_PER_CLUSTER]
2552
        add     eax, [DATA_START]
2553
        add     eax, ebp
2554
        cmp     dword [esp+4], -0x200
2555
        jz      .noread
2556
        mov     ebx, buffer
2557
        call    hd_read
2558
        cmp     [hd_error], 0
2559
        jnz     .err_next
2560
.noread:
2561
        mov     ecx, [esp+4]
2562
        neg     ecx
2563
        push    edi
2564
        mov     edi, buffer+0x200
2565
        add     edi, [esp+8]
2566
        push    eax
2567
        xor     eax, eax
2568
        mov     [esp+12], eax
2569
        rep     stosb
2570
        pop     eax
2571
        pop     edi
2572
        call    hd_write
2573
        cmp     [hd_error], 0
2574
        jz      .next_cluster
2575
.err_next:
2576
        mov     byte [esp], 11
2577
.next_cluster:
2578
        sub     dword [esp+20], 0x200
2579
        jbe     .pop_ret
2580
        inc     ebp
2581
        cmp     ebp, [SECTORS_PER_CLUSTER]
2582
        jb      .zero_loop
2583
        xor     ebp, ebp
2584
        mov     eax, edi
2585
        call    get_FAT
2586
        mov     edi, eax
2587
        cmp     [hd_error], 0
2588
        jnz     .pop_ret11
2589
        jmp     .zero_loop
2590
.truncate:
2591
        mov     [edi+28], eax
2592
        push    ecx
2593
        mov     ecx, [edi+20-2]
2594
        mov     cx, [edi+26]
2595
        push    eax
2596
        test    eax, eax
2597
        jz      .zero_size
2598
; find new last cluster
2599
@@:
2600
        mov     eax, [SECTORS_PER_CLUSTER]
2601
        shl     eax, 9
2602
        sub     [esp], eax
2603
        jbe     @f
2604
        mov     eax, ecx
2605
        call    get_FAT
2606
        mov     ecx, eax
2607
        cmp     [hd_error], 0
2608
        jz      @b
2609
.device_err3:
2610
        pop     eax ecx eax edi
2611
        push    11
2612
        pop     eax
2613
        ret
2614
@@:
2615
; we will zero data at the end of last sector - remember it
2616
        push    ecx
2617
; terminate FAT chain
2618
        push    edx
2619
        mov     eax, ecx
2620
        mov     edx, [fatEND]
2621
        call    set_FAT
2622
        mov     eax, edx
2623
        pop     edx
2624
        cmp     [hd_error], 0
2625
        jz      @f
2626
.device_err4:
2627
        pop     ecx
2628
        jmp     .device_err3
2629
.zero_size:
2630
        and     word [edi+20], 0
2631
        and     word [edi+26], 0
2632
        push    0
2633
        mov     eax, ecx
2634
@@:
2635
; delete FAT chain
2636
        call    clear_cluster_chain
2637
        cmp     [hd_error], 0
2638
        jnz     .device_err4
2639
; save directory
2640
        mov     eax, [esp+12]
2641
        push    ebx
2642
        mov     ebx, buffer
2643
        call    hd_write
2644
        pop     ebx
2645
        cmp     [hd_error], 0
2646
        jnz     .device_err4
2647
; zero last sector, ignore errors
2648
        pop     ecx
2649
        pop     eax
2650
        dec     ecx
2651
        imul    ecx, [SECTORS_PER_CLUSTER]
2652
        add     ecx, [DATA_START]
2653
        push    eax
2654
        sar     eax, 9
2655
        add     ecx, eax
2656
        pop     eax
2657
        and     eax, 0x1FF
2658
        jz      .truncate_done
2659
        push    ebx eax
2660
        mov     eax, ecx
2661
        mov     ebx, buffer
2662
        call    hd_read
2663
        pop     eax
2664
        lea     edi, [buffer+eax]
2665
        push    ecx
2666
        mov     ecx, 0x200
2667
        sub     ecx, eax
2668
        xor     eax, eax
2669
        rep     stosb
2670
        pop     eax
2671
        call    hd_write
2672
        pop     ebx
2673
.truncate_done:
2674
        pop     ecx eax edi
2675
        call    update_disk
2676
        xor     eax, eax
2677
        cmp     [hd_error], 0
2678
        jz      @f
2679
        mov     al, 11
2680
@@:
2681
        ret
2682
 
86 diamond 2683
fs_HdGetFileInfo:
256 diamond 2684
        cmp     [fs_type], 1
2685
        jz      ntfs_HdGetFileInfo
2686
        cmp     [fs_type], 16
2687
        jz      @f
2688
        cmp     [fs_type], 32
2689
        jz      @f
86 diamond 2690
        mov     eax, ERROR_UNKNOWN_FS
2691
        ret
2692
@@:
2693
        cmp     byte [esi], 0
2694
        jnz     @f
2695
        mov     eax, 2
2696
        ret
2697
@@:
2698
        push    edi
2699
        call    hd_find_lfn
2700
        pushfd
2701
        cmp     [hd_error], 0
2702
        jz      @f
2703
        popfd
2704
        pop     edi
2705
        mov     eax, 11
2706
        ret
2707
@@:
2708
        popfd
2709
        jmp     fs_GetFileInfo_finish
2710
 
2711
fs_HdSetFileInfo:
256 diamond 2712
        cmp     [fs_type], 1
2713
        jz      ntfs_HdSetFileInfo
2714
        cmp     [fs_type], 16
2715
        jz      @f
2716
        cmp     [fs_type], 32
2717
        jz      @f
86 diamond 2718
        mov     eax, ERROR_UNKNOWN_FS
2719
        ret
2720
@@:
2721
        cmp     byte [esi], 0
2722
        jnz     @f
2723
        mov     eax, 2
2724
        ret
2725
@@:
2726
        push    edi
2727
        call    hd_find_lfn
2728
        pushfd
2729
        cmp     [hd_error], 0
2730
        jz      @f
2731
        popfd
2732
        pop     edi
2733
        mov     eax, 11
2734
        ret
2735
@@:
2736
        popfd
2737
        jnc     @f
2738
        pop     edi
2739
        mov     eax, ERROR_FILE_NOT_FOUND
2740
        ret
2741
@@:
2742
        push    eax
2743
        call    bdfe_to_fat_entry
2744
        pop     eax
2745
        mov     ebx, buffer
2746
        call    hd_write
2747
        call    update_disk
2748
        pop     edi
2749
        xor     eax, eax
2750
        ret
2751
 
91 diamond 2752
;----------------------------------------------------------------
2753
;
171 diamond 2754
;  fs_HdDelete - delete file or empty folder from hard disk
2755
;
2756
;  esi  points to filename
2757
;
2758
;  ret  eax = 0 ok or other = errormsg
2759
;
2760
;--------------------------------------------------------------
2761
fs_HdDelete:
256 diamond 2762
        cmp     [fs_type], 1
2763
        jz      ntfs_HdDelete
2764
        cmp     [fs_type], 16
2765
        jz      @f
2766
        cmp     [fs_type], 32
2767
        jz      @f
171 diamond 2768
        push    ERROR_UNKNOWN_FS
2769
.pop_ret:
2770
        pop     eax
2771
        ret
2772
@@:
2773
        cmp     byte [esi], 0
2774
        jnz     @f
2775
; cannot delete root!
2776
.access_denied:
2777
        push    ERROR_ACCESS_DENIED
2778
        jmp     .pop_ret
2779
@@:
2780
        and     [longname_sec1], 0
2781
        and     [longname_sec2], 0
2782
        push    edi
2783
        call    hd_find_lfn
2784
        jnc     .found
2785
        pop     edi
2786
        push    ERROR_FILE_NOT_FOUND
2787
        jmp     .pop_ret
2788
.found:
2789
        cmp     dword [edi], '.   '
2790
        jz      .access_denied2
2791
        cmp     dword [edi], '..  '
2792
        jz      .access_denied2
2793
        test    byte [edi+11], 10h
2794
        jz      .dodel
2795
; we can delete only empty folders!
2796
        pushad
2797
        mov     ebp, [edi+20-2]
2798
        mov     bp, [edi+26]
2799
        xor     ecx, ecx
2800
        lea     eax, [ebp-2]
2801
        imul    eax, [SECTORS_PER_CLUSTER]
2802
        add     eax, [DATA_START]
2803
        mov     ebx, buffer
2804
        call    hd_read
2805
        cmp     [hd_error], 0
2806
        jnz     .err1
2807
        add     ebx, 2*0x20
2808
.checkempty:
2809
        cmp     byte [ebx], 0
2810
        jz      .empty
2811
        cmp     byte [ebx], 0xE5
2812
        jnz     .notempty
2813
        add     ebx, 0x20
2814
        cmp     ebx, buffer+0x200
2815
        jb      .checkempty
2816
        inc     ecx
2817
        cmp     ecx, [SECTORS_PER_CLUSTER]
2818
        jb      @f
2819
        mov     eax, ebp
2820
        call    get_FAT
2821
        cmp     [hd_error], 0
2822
        jnz     .err1
2823
        mov     ebp, eax
2824
        xor     ecx, ecx
2825
@@:
2826
        lea     eax, [ebp-2]
2827
        imul    eax, [SECTORS_PER_CLUSTER]
2828
        add     eax, [DATA_START]
2829
        add     eax, ecx
2830
        mov     ebx, buffer
2831
        call    hd_read
2832
        cmp     [hd_error], 0
2833
        jz      .checkempty
2834
.err1:
2835
        popad
2836
.err2:
2837
        pop     edi
2838
        push    11
2839
        pop     eax
2840
        ret
2841
.notempty:
2842
        popad
2843
.access_denied2:
2844
        pop     edi
2845
        push    ERROR_ACCESS_DENIED
2846
        pop     eax
2847
        ret
2848
.empty:
2849
        popad
2850
        push    ebx
2851
        mov     ebx, buffer
2852
        call    hd_read
2853
        pop     ebx
2854
        cmp     [hd_error], 0
2855
        jnz     .err2
2856
.dodel:
2857
        push    eax
2858
        mov     eax, [edi+20-2]
2859
        mov     ax, [edi+26]
2860
        xchg    eax, [esp]
2861
; delete folder entry
2862
        mov     byte [edi], 0xE5
2863
; delete LFN (if present)
2864
.lfndel:
2865
        cmp     edi, buffer
2866
        ja      @f
2867
        cmp     [longname_sec2], 0
2868
        jz      .lfndone
2869
        push    [longname_sec2]
2870
        push    [longname_sec1]
2871
        pop     [longname_sec2]
2872
        and     [longname_sec1], 0
2873
        push    ebx
2874
        mov     ebx, buffer
2875
        call    hd_write
2876
        mov     eax, [esp+4]
2877
        call    hd_read
2878
        pop     ebx
2879
        pop     eax
2880
        mov     edi, buffer+0x200
2881
@@:
2882
        sub     edi, 0x20
2883
        cmp     byte [edi], 0xE5
2884
        jz      .lfndone
2885
        cmp     byte [edi+11], 0xF
2886
        jnz     .lfndone
2887
        mov     byte [edi], 0xE5
2888
        jmp     .lfndel
2889
.lfndone:
2890
        push    ebx
2891
        mov     ebx, buffer
2892
        call    hd_write
2893
        pop     ebx
2894
; delete FAT chain
2895
        pop     eax
2896
        call    clear_cluster_chain
2897
        call    update_disk
2898
        pop     edi
2899
        xor     eax, eax
2900
        cmp     [hd_error], 0
2901
        jz      @f
2902
        mov     al, 11
2903
@@:
2904
        ret
2905
 
74 mario79 2906
; \end{diamond}