Subversion Repositories Kolibri OS

Rev

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