Subversion Repositories Kolibri OS

Rev

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

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