Subversion Repositories Kolibri OS

Rev

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