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