Subversion Repositories Kolibri OS

Rev

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