Subversion Repositories Kolibri OS

Rev

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