Subversion Repositories Kolibri OS

Rev

Rev 256 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ha 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;;  FAT32.INC                                                      ;;
4
;;                                                                 ;;
131 diamond 5
;;  FAT16/32 functions for KolibriOS                               ;;
1 ha 6
;;                                                                 ;;
7
;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
8
;;                                                                 ;;
9
;;  See file COPYING for details                                   ;;
321 diamond 10
;;  04.02.2007 LFN create folder - diamond                         ;;
171 diamond 11
;;  08.10.2006 LFN delete file/folder - diamond                    ;;
139 diamond 12
;;  20.08.2006 LFN set file size (truncate/extend) - diamond       ;;
131 diamond 13
;;  17.08.2006 LFN write/append to file - diamond                  ;;
91 diamond 14
;;  23.06.2006 LFN start application - diamond                     ;;
86 diamond 15
;;  15.06.2006 LFN get/set file/folder info - diamond              ;;
83 diamond 16
;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
75 diamond 17
;;  04.05.2006 LFN read folder - diamond                           ;;
74 mario79 18
;;  29.04.2006 Elimination of hangup after the                     ;;
19
;;             expiration hd_wait_timeout -  Mario79               ;;
75 diamond 20
;;  23.04.2006 LFN read file - diamond                             ;;
65 mario79 21
;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
22
;;             to MBR, see file part_set.inc - Mario79             ;;
1 ha 23
;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
24
;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
25
;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
26
;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
27
;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
28
;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
29
;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
30
;;  08.11.2004 rename - ATV                                        ;;
31
;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
32
;;  20.10.2004 Makedir/Removedir - ATV                             ;;
33
;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
34
;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
35
;;  24.5.2004  Write back buffer for File_write -VT                ;;
36
;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
37
;;  30.3.2004  Error parameters at function return - VT            ;;
38
;;  01.5.2002  Bugfix in device write - VT                         ;;
39
;;  20.5.2002  Hd status check - VT                                ;;
40
;;  29.6.2002  Improved fat32 verification - VT                    ;;
41
;;                                                                 ;;
42
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
43
 
44
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
45
 
52 mikedld 46
ERROR_SUCCESS        = 0
47
ERROR_DISK_BASE      = 1
48
ERROR_UNSUPPORTED_FS = 2
49
ERROR_UNKNOWN_FS     = 3
50
ERROR_PARTITION      = 4
51
ERROR_FILE_NOT_FOUND = 5
52
ERROR_END_OF_FILE    = 6
53
ERROR_MEMORY_POINTER = 7
54
ERROR_DISK_FULL      = 8
55
ERROR_FAT_TABLE      = 9
56
ERROR_ACCESS_DENIED  = 10
1 ha 57
 
58
PUSHAD_EAX equ [esp+28]
59
PUSHAD_ECX equ [esp+24]
60
PUSHAD_EDX equ [esp+20]
61
PUSHAD_EBX equ [esp+16]
62
PUSHAD_EBP equ [esp+8]
63
PUSHAD_ESI equ [esp+4]
64
PUSHAD_EDI equ [esp+0]
65
 
171 diamond 66
uglobal
67
align 4
1 ha 68
cluster              dd 0       ; used by file_write,makedir,append
69
partition_count      dd 0       ; partitions found by set_FAT32_variables
70
longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
71
longname_sec2        dd 0       ; directory sectors for delete long filename
72
 
73
hd_error             dd 0       ; set by wait_for_sector_buffer
74
hd_setup             dd 0
75
hd_wait_timeout      dd 0
76
 
77
cluster_tmp          dd 0       ; used by analyze_directory
78
                                ; and analyze_directory_to_write
79
 
80
file_size            dd 0       ; used by file_read
81
 
82
sector_tmp           dd 0       ; used by rename,append,file_write
83
entry_pos            dd 0       ; used by rename,append,file_write
84
 
85
old_filesize         dd 0       ; used by append
86
new_filepos          dd 0       ; used by append
87
bytes2write          dd 0       ; used by append
88
 
89
cache_search_start   dd 0       ; used by find_empty_slot
171 diamond 90
endg
1 ha 91
 
171 diamond 92
iglobal
1 ha 93
fat_in_cache         dd -1
171 diamond 94
endg
1 ha 95
 
96
uglobal
171 diamond 97
align 4
98
fat_cache:           times 512 db 0
1 ha 99
 Sector512:                      ; label for dev_hdcd.inc
100
  buffer:              times 512 db 0
101
  deltree_buffer:      times 512 db 0
133 diamond 102
  fsinfo_buffer:       times 512 db 0
1 ha 103
endg
104
 
105
uglobal
106
  dir_entry:           times 32 db 0
107
 
108
  startpath:           times 255 db 0
109
 
110
  fat16_root           db 0       ; flag for fat16 rootdir
111
  fat_change           db 0       ; 1=fat has changed
112
 
113
endg
114
 
115
reserve_hd1:
116
 
117
    cli
118
    cmp   [hd1_status],0
119
    je    reserve_ok1
120
 
121
    sti
122
    call  change_task
123
    jmp   reserve_hd1
124
 
125
  reserve_ok1:
126
 
127
    push  eax
128
    mov   eax,[0x3000]
129
    shl   eax,5
115 poddubny 130
    mov   eax,[eax+0x3000+TASKDATA.pid]
1 ha 131
    mov   [hd1_status],eax
132
    pop   eax
133
    sti
134
    ret
95 mario79 135
;********************************************
321 diamond 136
 
137
uglobal
138
hd_in_cache db ?
139
endg
140
 
95 mario79 141
reserve_hd_channel:
142
    cmp   [hdbase], 0x1F0
143
    jne   .IDE_Channel_2
144
.IDE_Channel_1:
145
    cli
146
    cmp   [IDE_Channel_1],0
147
    je    .reserve_ok_1
148
    sti
149
    call  change_task
150
    jmp   .IDE_Channel_1
151
.IDE_Channel_2:
152
    cli
153
    cmp   [IDE_Channel_2],0
154
    je    .reserve_ok_2
155
    sti
156
    call  change_task
321 diamond 157
    jmp   .IDE_Channel_2
95 mario79 158
.reserve_ok_1:
321 diamond 159
        mov     [IDE_Channel_1], 1
160
        push    eax
161
        mov     al, 1
162
        jmp     @f
95 mario79 163
.reserve_ok_2:
321 diamond 164
        mov     [IDE_Channel_2], 1
165
        push    eax
166
        mov     al, 3
167
@@:
168
        cmp     [hdid], 1
169
        sbb     al, -1
170
        cmp     al, [hd_in_cache]
171
        jz      @f
172
        mov     [hd_in_cache], al
173
        call    clear_hd_cache
174
@@:
175
	pop     eax
176
        ret
177
 
95 mario79 178
free_hd_channel:
179
    cmp   [hdbase], 0x1F0
180
    jne   .IDE_Channel_2
181
.IDE_Channel_1:
182
    mov [IDE_Channel_1],0
183
    ret
184
.IDE_Channel_2:
185
    mov [IDE_Channel_2],0
186
    ret
187
;********************************************
1 ha 188
problem_partition db 0  ; used for partitions search
189
 
65 mario79 190
include  'part_set.inc'
1 ha 191
 
192
set_FAT:
193
;--------------------------------
194
; input  : EAX = cluster
195
;          EDX = value to save
196
; output : EDX = old value
197
;--------------------------------
198
    push  eax ebx esi
199
 
200
    cmp   eax,2
201
    jb    sfc_error
202
    cmp   eax,[LAST_CLUSTER]
203
    ja    sfc_error
256 diamond 204
    cmp   [fs_type],16
1 ha 205
    je    sfc_1
206
    add   eax,eax
207
  sfc_1:
208
    add   eax,eax
209
    mov   esi,511
210
    and   esi,eax               ; esi = position in fat sector
211
    shr   eax,9                 ; eax = fat sector
212
    add   eax,[FAT_START]
213
    mov   ebx,fat_cache
214
 
215
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
216
    je    sfc_in_cache          ; yes
217
 
218
    cmp   [fat_change],0        ; is fat changed?
219
    je    sfc_no_change         ; no
220
    call  write_fat_sector      ; yes. write it into disk
74 mario79 221
    cmp   [hd_error],0
222
    jne   sfc_error
1 ha 223
 
224
  sfc_no_change:
225
    mov   [fat_in_cache],eax    ; save fat sector
226
    call  hd_read
74 mario79 227
    cmp  [hd_error],0
228
    jne  sfc_error
229
 
1 ha 230
 
231
  sfc_in_cache:
256 diamond 232
    cmp   [fs_type],16
1 ha 233
    jne   sfc_test32
234
 
235
  sfc_set16:
236
    xchg  [ebx+esi],dx          ; save new value and get old value
237
    jmp   sfc_write
238
 
239
  sfc_test32:
240
    mov   eax,[fatMASK]
241
 
242
  sfc_set32:
243
    and   edx,eax
244
    xor   eax,-1                ; mask for high bits
245
    and   eax,[ebx+esi]         ; get high 4 bits
246
    or    eax,edx
247
    mov   edx,[ebx+esi]         ; get old value
248
    mov   [ebx+esi],eax         ; save new value
249
 
250
  sfc_write:
251
    mov   [fat_change],1        ; fat has changed
252
 
253
  sfc_nonzero:
254
    and   edx,[fatMASK]
255
 
256
  sfc_error:
257
    pop   esi ebx eax
258
    ret
259
 
260
 
261
get_FAT:
262
;--------------------------------
263
; input  : EAX = cluster
264
; output : EAX = next cluster
265
;--------------------------------
266
    push  ebx esi
267
 
256 diamond 268
    cmp   [fs_type],16
1 ha 269
    je    gfc_1
270
    add   eax,eax
271
  gfc_1:
272
    add   eax,eax
273
    mov   esi,511
274
    and   esi,eax               ; esi = position in fat sector
275
    shr   eax,9                 ; eax = fat sector
276
    add   eax,[FAT_START]
277
    mov   ebx,fat_cache
278
 
279
    cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
280
    je    gfc_in_cache
281
 
282
    cmp   [fat_change],0        ; is fat changed?
283
    je    gfc_no_change         ; no
284
    call  write_fat_sector      ; yes. write it into disk
74 mario79 285
    cmp  [hd_error],0
286
    jne  hd_error_01
1 ha 287
 
288
  gfc_no_change:
289
    mov   [fat_in_cache],eax
290
    call  hd_read
74 mario79 291
    cmp  [hd_error],0
292
    jne  hd_error_01
1 ha 293
 
294
  gfc_in_cache:
295
    mov   eax,[ebx+esi]
296
    and   eax,[fatMASK]
74 mario79 297
 hd_error_01:
1 ha 298
    pop   esi ebx
299
    ret
300
 
301
 
302
get_free_FAT:
303
;-----------------------------------------------------------
304
; input  : EAX = # cluster for start the searching
305
; output : if CARRY=0 EAX = # first cluster found free
306
;          if CARRY=1 disk full
307
; Note   : for more speed need to use fat_cache directly
308
;-----------------------------------------------------------
309
    push  ecx
310
    mov   ecx,[LAST_CLUSTER]    ; counter for full disk
311
    sub   ecx,2
312
 
313
  gff_test:
314
    cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
315
    jbe   gff_in_range
316
    mov   eax,2
317
 
318
  gff_in_range:
319
    push  eax
320
    call  get_FAT               ; get cluster state
74 mario79 321
    cmp   [hd_error],0
322
    jne   gff_not_found_1
323
 
1 ha 324
    test  eax,eax               ; is it free?
325
    pop   eax
326
    je    gff_found             ; yes
327
    inc   eax                   ; next cluster
328
    dec   ecx                   ; is all checked?
329
    jns   gff_test              ; no
330
 
74 mario79 331
  gff_not_found_1:
332
    add   esp,4
1 ha 333
  gff_not_found:
334
    pop   ecx                   ; yes. disk is full
335
    stc
336
    ret
337
 
338
  gff_found:
339
    pop   ecx
340
    clc
341
    ret
342
 
343
 
344
write_fat_sector:
345
;-----------------------------------------------------------
346
; write changed fat to disk
347
;-----------------------------------------------------------
348
    push  eax ebx ecx
349
 
350
    mov   [fat_change],0
351
    mov   eax,[fat_in_cache]
352
    cmp   eax,-1
353
    jz    write_fat_not_used
354
    mov   ebx,fat_cache
355
    mov   ecx,[NUMBER_OF_FATS]
356
 
357
  write_next_fat:
358
    call  hd_write
74 mario79 359
    cmp   [hd_error],0
360
    jne   write_fat_not_used
361
 
1 ha 362
    add   eax,[SECTORS_PER_FAT]
363
    dec   ecx
364
    jnz   write_next_fat
365
 
366
  write_fat_not_used:
367
    pop   ecx ebx eax
368
    ret
369
 
370
 
371
analyze_directory:
372
;-----------------------------------------------------------
373
; input  : EAX = first cluster of the directory
374
;          EBX = pointer to filename
375
; output : IF CARRY=0 EAX = sector where th file is found
376
;                     EBX = pointer in buffer
377
;                     [buffer .. buffer+511]
378
;                     ECX,EDX,ESI,EDI not changed
379
;          IF CARRY=1 filename not found
380
; Note   : if cluster=0 it's changed to read rootdir
381
;          save 2 previous directory sectors in longname_sec
382
;-----------------------------------------------------------
383
    push  ecx edx esi edi ebx   ; ebx = [esp+0]
384
    mov   [longname_sec1],0
385
    mov   [longname_sec2],0
386
 
387
  adr_new_cluster:
388
    mov   [cluster_tmp],eax
389
    mov   [fat16_root],0
390
    cmp   eax,[LAST_CLUSTER]
391
    ja    adr_not_found         ; too big cluster number, something is wrong
392
    cmp   eax,2
393
    jnb   adr_data_cluster
394
 
395
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
256 diamond 396
    cmp   [fs_type],16
1 ha 397
    jne   adr_data_cluster
398
    mov   eax,[ROOT_START]
399
    mov   edx,[ROOT_SECTORS]
400
    mov   [fat16_root],1        ; flag for fat16 rootdir
401
    jmp   adr_new_sector
402
 
403
  adr_data_cluster:
404
    sub   eax,2
405
    mov   edx,[SECTORS_PER_CLUSTER]
406
    imul  eax,edx
407
    add   eax,[DATA_START]
408
 
409
  adr_new_sector:
410
    mov   ebx,buffer
411
    call  hd_read
74 mario79 412
    cmp  [hd_error],0
413
    jne  adr_not_found
414
 
1 ha 415
    mov   ecx,512/32            ; count of dir entrys per sector = 16
416
 
417
  adr_analyze:
418
    mov   edi,[ebx+11]          ; file attribute
419
    and   edi,0xf
420
    cmp   edi,0xf
421
    je    adr_long_filename
422
    test  edi,0x8               ; skip over volume label
423
    jne   adr_long_filename     ; Note: label can be same name as file/dir
424
 
425
    mov   esi,[esp+0]           ; filename need to be uppercase
426
    mov   edi,ebx
427
    push  ecx
428
    mov   ecx,11
429
    cld
430
    rep   cmpsb                 ; compare 8+3 filename
431
    pop   ecx
432
    je    adr_found
433
 
434
  adr_long_filename:
435
    add   ebx,32                ; position of next dir entry
436
    dec   ecx
437
    jnz   adr_analyze
438
 
439
    mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
440
    mov   [longname_sec1],eax   ; for delete long filename
441
    mov   [longname_sec2],ecx
442
    inc   eax                   ; next sector
443
    dec   edx
444
    jne   adr_new_sector
445
    cmp   [fat16_root],1        ; end of fat16 rootdir
446
    je    adr_not_found
447
 
448
  adr_next_cluster:
449
    mov   eax,[cluster_tmp]
450
    call  get_FAT               ; get next cluster
74 mario79 451
    cmp  [hd_error],0
452
    jne  adr_not_found
453
 
1 ha 454
    cmp   eax,2                 ; incorrect fat chain?
455
    jb    adr_not_found         ; yes
456
    cmp   eax,[fatRESERVED]     ; is it end of directory?
457
    jb    adr_new_cluster       ; no. analyse it
458
 
459
  adr_not_found:
460
    pop   edi edi esi edx ecx   ; first edi will remove ebx
461
    stc                         ; file not found
462
    ret
463
 
464
  adr_found:
465
    pop   edi edi esi edx ecx   ; first edi will remove ebx
466
    clc                         ; file found
467
    ret
468
 
469
 
470
analyze_directory_to_write:
471
;-----------------------------------------------------------
472
; input  : EAX = first cluster of the directory
473
; output : IF CARRY=0 EAX = sector where the empty pos is found
474
;                     EBX = pointer in buffer
475
;                     [buffer .. buffer+511]
476
;                     ECX,EDX,ESI,EDI not changed
477
;          IF CARRY=1 disk full or fat corrupted
478
; Note   : if cluster=0 it's changed to read rootdir
479
;-----------------------------------------------------------
480
    push  ecx edx edi
481
 
482
  adw_new_cluster:
483
    mov   [cluster_tmp],eax
484
    mov   [fat16_root],0
485
    cmp   eax,[LAST_CLUSTER]
486
    ja    adw_not_found         ; too big cluster number, something is wrong
487
    cmp   eax,2
488
    jnb   adw_data_cluster
489
 
490
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
256 diamond 491
    cmp   [fs_type],16
1 ha 492
    jne   adw_data_cluster
493
    mov   eax,[ROOT_START]
494
    mov   edx,[ROOT_SECTORS]
495
    mov   [fat16_root],1        ; flag for fat16 rootdir
496
    jmp   adw_new_sector
497
 
498
  adw_data_cluster:
499
    sub   eax,2
500
    mov   edx,[SECTORS_PER_CLUSTER]
501
    imul  eax,edx
502
    add   eax,[DATA_START]
503
 
504
  adw_new_sector:
505
    mov   ebx,buffer
506
    call  hd_read
74 mario79 507
    cmp  [hd_error],0
508
    jne  adw_not_found
509
 
1 ha 510
    mov   ecx,512/32            ; count of dir entrys per sector = 16
511
 
512
  adw_analyze:
513
    cmp   byte [ebx],0x00       ; is free entry?
514
    je    adw_found             ; yes
515
    cmp   byte [ebx],0xe5       ; is deleted entry?
516
    je    adw_found             ; yes
517
    add   ebx,32                ; position of next dir entry
518
    dec   ecx
519
    jnz   adw_analyze
520
 
521
    inc   eax                   ; next sector
522
    dec   edx
523
    jne   adw_new_sector
524
    cmp   [fat16_root],1        ; end of fat16 rootdir
525
    je    adw_not_found
526
 
527
    mov   eax,[cluster_tmp]
528
    call  get_FAT               ; get next cluster
74 mario79 529
    cmp   [hd_error],0
530
    jne   adw_not_found
531
 
1 ha 532
    cmp   eax,2                 ; incorrect fat chain?
533
    jb    adw_not_found         ; yes
534
    cmp   eax,[fatRESERVED]     ; is it end of directory?
535
    jb    adw_new_cluster       ; no. analyse it
536
 
537
    mov   eax,2                 ; this block of code add a new cluster
538
    call  get_free_FAT          ; for the directory because the directory
539
    jc    adw_not_found         ; is full
540
 
541
    mov   edx,[fatEND]          ; new end for directory
542
    call  set_FAT
74 mario79 543
    cmp  [hd_error],0
544
    jne  adw_not_found
1 ha 545
 
546
    push  eax                   ; save new cluster
547
    mov   edx,eax
548
    mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
549
    call  set_FAT
74 mario79 550
    cmp  [hd_error],0
551
    jne  adw_not_found_1
552
 
1 ha 553
    mov   ecx,-1                ; remove 1 cluster from free disk space
554
    call  add_disk_free_space
74 mario79 555
    cmp  [hd_error],0
556
    jne    adw_not_found_1
1 ha 557
 
558
    mov   ecx,512/4
559
    xor   eax,eax
560
    mov   edi,buffer
561
    cld
562
    rep   stosd                 ; clear new directory cluster
563
    pop   eax
564
 
565
    sub   eax,2
566
    mov   ecx,[SECTORS_PER_CLUSTER]
567
    imul  eax,ecx
568
    add   eax,[DATA_START]
569
    mov   ebx,buffer
570
    push  eax                   ; save sector number
571
 
572
  adw_set_empty_directory:
573
    call  hd_write
74 mario79 574
    cmp   [hd_error],0
575
    jne   adw_not_found_1
576
 
1 ha 577
    inc   eax                   ; next sector
578
    dec   ecx
579
    jnz   adw_set_empty_directory
580
 
581
    pop   eax
582
 
583
  adw_found:
584
    pop   edi edx ecx
585
    clc                         ; free space found
586
    ret
74 mario79 587
  adw_not_found_1:
588
    add  esp,4
1 ha 589
  adw_not_found:
590
    pop   edi edx ecx
591
    stc                         ; free space not found
592
    ret
593
 
594
 
595
get_data_cluster:
596
;-----------------------------------------------------------
597
; input  : EAX = cluster
598
;          EBX = pointer to buffer
599
;          EDX = # blocks to read in buffer
600
;          ESI = # blocks to skip over
601
; output : if CARRY=0 ok EBX/EDX/ESI updated
602
;          if CARRY=1 cluster out of range
603
; Note   : if cluster=0 it's changed to read rootdir
604
;-----------------------------------------------------------
605
    push  eax ecx
606
 
607
    mov   [fat16_root],0
608
    cmp   eax,[LAST_CLUSTER]
609
    ja    gdc_error             ; too big cluster number, something is wrong
610
    cmp   eax,2
611
    jnb   gdc_cluster
612
 
613
    mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
256 diamond 614
    cmp   [fs_type],16
1 ha 615
    jne   gdc_cluster
616
    mov   eax,[ROOT_START]
617
    mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
618
    mov   [fat16_root],1        ; flag for fat16 rootdir
619
    jmp   gdc_read
620
 
621
  gdc_cluster:
622
    sub   eax,2
623
    mov   ecx,[SECTORS_PER_CLUSTER]
624
    imul  eax,ecx
625
    add   eax,[DATA_START]
626
 
627
  gdc_read:
628
    test  esi,esi               ; first wanted block
629
    je    gdcl1                 ; yes, skip count is 0
630
    dec   esi
631
    jmp   gdcl2
632
 
633
  gdcl1:
634
    call  hd_read
74 mario79 635
    cmp  [hd_error],0
636
    jne  gdc_error
637
 
1 ha 638
    add   ebx,512               ; update pointer
639
    dec   edx
640
 
641
  gdcl2:
642
    test  edx,edx               ; is all read?
643
    je    out_of_read
644
 
645
    inc   eax                   ; next sector
646
    dec   ecx
647
    jnz   gdc_read
648
 
649
  out_of_read:
650
    pop   ecx eax
651
    clc
652
    ret
653
 
654
  gdc_error:
655
    pop   ecx eax
656
    stc
657
    ret
658
 
659
 
660
set_data_cluster:
661
;-----------------------------------------------------------
662
; input  : EAX = cluster
663
;          EBX = pointer to buffer
664
; output : if CARRY=0 ok
665
;          if CARRY=1 cluster out of range
666
;-----------------------------------------------------------
667
    push  eax ebx edx
668
 
669
    cmp   eax,[LAST_CLUSTER]
670
    ja    sdc_error             ; too big cluster number, something is wrong
671
    sub   eax,2
672
    jb    sdc_error             ; don't allow rootdir write
673
 
674
    mov   edx,[SECTORS_PER_CLUSTER]
675
    imul  eax,edx
676
    add   eax,[DATA_START]
677
 
678
  sdc_write:
679
    call  hd_write
74 mario79 680
    cmp   [hd_error],0
681
    jne   sdc_error
682
 
1 ha 683
    add   ebx,512               ; update pointer
684
    inc   eax
685
    dec   edx
686
    jnz   sdc_write
687
    pop   edx ebx eax
688
    clc
689
    ret
690
 
691
  sdc_error:
692
    pop   edx ebx eax
693
    stc
694
    ret
695
 
696
 
697
get_cluster_of_a_path:
698
;---------------------------------------------------------
699
; input  : EBX = pointer to a path string
700
;          (example: the path "/files/data/document" become
701
;                             "files......data.......document...0"
702
;          '.' = space char
703
;          '0' = char(0) (ASCII=0) !!! )
704
; output : if (CARRY=1) -> ERROR in the PATH
705
;          if (CARRY=0) -> EAX=cluster
706
;---------------------------------------------------------
707
    push  ebx edx
708
 
709
    mov   eax,[ROOT_CLUSTER]
710
    mov   edx,ebx
711
 
712
search_end_of_path:
713
    cmp   byte [edx],0
714
    je    found_end_of_path
715
 
716
    inc   edx ; '/'
717
    mov   ebx,edx
718
    call  analyze_directory
719
    jc    directory_not_found
720
 
721
    mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
722
    mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
723
    and   eax,[fatMASK]
724
    add   edx,11                ; 8+3 (name+extension)
725
    jmp   search_end_of_path
726
 
727
found_end_of_path:
728
    pop   edx ebx
729
    clc                         ; no errors
730
    ret
731
 
732
directory_not_found:
733
    pop   edx ebx
734
    stc                         ; errors occour
735
    ret
736
 
737
 
738
bcd2bin:
739
;----------------------------------
740
; input  : AL=BCD number (eg. 0x11)
741
; output : AH=0
742
;          AL=decimal number (eg. 11)
743
;----------------------------------
744
    xor   ah,ah
745
    shl   ax,4
746
    shr   al,4
747
    aad
748
    ret
749
 
750
 
751
get_date_for_file:
752
;-----------------------------------------------------
753
; Get date from CMOS and pack day,month,year in AX
754
; DATE   bits  0..4   : day of month 0..31
755
;              5..8   : month of year 1..12
756
;              9..15  : count of years from 1980
757
;-----------------------------------------------------
758
    mov   al,0x7        ;day
759
    out   0x70,al
760
    in    al,0x71
761
    call  bcd2bin
762
    ror   eax,5
763
 
764
    mov   al,0x8        ;month
765
    out   0x70,al
766
    in    al,0x71
767
    call  bcd2bin
768
    ror   eax,4
769
 
770
    mov   al,0x9        ;year
771
    out   0x70,al
772
    in    al,0x71
773
    call  bcd2bin
774
    add   ax,20         ;because CMOS return only the two last
775
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
776
    rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
777
    ret
778
 
779
 
780
get_time_for_file:
781
;-----------------------------------------------------
782
; Get time from CMOS and pack hour,minute,second in AX
783
; TIME   bits  0..4   : second (the low bit is lost)
784
;              5..10  : minute 0..59
785
;              11..15 : hour 0..23
786
;-----------------------------------------------------
787
    mov   al,0x0        ;second
788
    out   0x70,al
789
    in    al,0x71
790
    call  bcd2bin
791
    ror   eax,6
792
 
793
    mov   al,0x2        ;minute
794
    out   0x70,al
795
    in    al,0x71
796
    call  bcd2bin
797
    ror   eax,6
798
 
799
    mov   al,0x4        ;hour
800
    out   0x70,al
801
    in    al,0x71
802
    call  bcd2bin
803
    rol   eax,11
804
    ret
805
 
806
 
807
set_current_time_for_entry:
808
;-----------------------------------------------------
809
; Set current time/date for file entry
810
; input  : ebx = file entry pointer
811
;-----------------------------------------------------
812
    push  eax
813
    call  get_time_for_file     ; update files date/time
814
    mov   [ebx+22],ax
815
    call  get_date_for_file
816
    mov   [ebx+24],ax
817
    pop   eax
818
    ret
819
 
820
 
821
 
822
add_disk_free_space:
823
;-----------------------------------------------------
824
; input  : ecx = cluster count
825
; Note   : negative = remove clusters from free space
826
;          positive = add clusters to free space
827
;-----------------------------------------------------
828
    test  ecx,ecx               ; no change
829
    je    add_dfs_no
256 diamond 830
    cmp   [fs_type],32         ; free disk space only used by fat32
1 ha 831
    jne   add_dfs_no
832
 
833
    push  eax ebx
834
    mov   eax,[ADR_FSINFO]
133 diamond 835
    mov   ebx,fsinfo_buffer
1 ha 836
    call  hd_read
74 mario79 837
    cmp  [hd_error],0
838
    jne  add_not_fs
839
 
1 ha 840
    cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
841
    jne   add_not_fs
842
 
843
    add   [ebx+0x1e8],ecx
844
    call  hd_write
133 diamond 845
;    cmp   [hd_error],0
846
;    jne   add_not_fs
1 ha 847
 
848
  add_not_fs:
849
    pop   ebx eax
850
 
851
  add_dfs_no:
852
    ret
853
 
854
 
855
file_write:
856
;--------------------------------------------------------------------------
857
;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
858
;
859
;            EAX        EDI            system call to write    /
860
;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
861
;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
862
;            ECX        EBX   (PAR2)   file size               PAR2
863
;            ESI        EDX   (PAR3)   pointer to path         PAR3
864
;
865
; output : eax = 0 - ok
866
;                3 - unknown FS
867
;                5 - file not found
868
;                8 - disk full
869
;               10 - access denied
870
;--------------------------------------------------------------------------
256 diamond 871
        cmp     [fs_type], 16
872
        jz      fat_ok_for_writing
873
        cmp     [fs_type], 32
874
        jz      fat_ok_for_writing
875
        push    ERROR_UNKNOWN_FS
876
        pop     eax
877
        ret
1 ha 878
 
879
  fat_ok_for_writing:
880
;    call  reserve_hd1
881
 
882
    pushad
883
 
884
    xor   edi,edi               ; don't allow directory remove
885
    call  file_delete           ; try to delete the file first
74 mario79 886
    cmp   [hd_error],0
887
    jne   exit_write_access_1
888
 
1 ha 889
    test  eax,eax
890
    jz    old_deleted           ; deleted ok
891
    cmp   eax,ERROR_FILE_NOT_FOUND
892
    jnz   exit_write_access     ; it exist but can't delete
893
 
894
  old_deleted:
895
    mov   ebx,PUSHAD_EDX
896
    call  get_cluster_of_a_path
897
    jnc   found_directory_for_writing
74 mario79 898
    cmp   [hd_error],0
899
    jne   exit_write_access
1 ha 900
 
901
  exit_writing_with_error:
902
    popad
903
    call  update_disk           ; write all of cache and fat to hd
74 mario79 904
    cmp   [hd_error],0
905
    jne   exit_write_access_2
906
 
1 ha 907
    mov   [hd1_status],0
908
    mov   eax,ERROR_FILE_NOT_FOUND
909
    ret
910
 
911
  exit_writing_disk_full_clear:
74 mario79 912
    cmp  [hd_error],0
913
    jne  exit_write_access_1
1 ha 914
    mov   eax,[sector_tmp]
915
    mov   ebx,buffer
916
    call  hd_read               ; read directory sector
74 mario79 917
    cmp  [hd_error],0
918
    jne  exit_write_access_1
919
 
1 ha 920
    mov   edx,[entry_pos]
921
    mov   byte [edx],0xe5       ; mark as deleted
922
    call  hd_write
74 mario79 923
    cmp   [hd_error],0
924
    jne   exit_write_access_1
925
 
1 ha 926
    mov   eax,[edx+20-2]        ; FAT entry
927
    mov   ax,[edx+26]
928
    and   eax,[fatMASK]
929
    call  clear_cluster_chain
930
 
931
  exit_writing_disk_full:
74 mario79 932
    cmp  [hd_error],0
933
    jne  exit_write_access_1
1 ha 934
    popad
935
    call  update_disk           ; write all of cache and fat to hd
74 mario79 936
    cmp   [hd_error],0
937
    jne   exit_write_access_2
1 ha 938
    mov   [hd1_status],0
939
    mov   eax,ERROR_DISK_FULL
940
    ret
941
 
942
  exit_write_access:
943
    popad
944
    call  update_disk           ; write all of cache and fat to hd
945
    mov   [hd1_status],0
946
    mov   eax,ERROR_ACCESS_DENIED
947
    ret
948
 
74 mario79 949
  exit_write_access_1:
950
    popad
951
  exit_write_access_2:
952
    mov   [hd1_status],0
953
    mov   eax,ERROR_ACCESS_DENIED
954
    ret
955
 
1 ha 956
found_directory_for_writing:
957
    call  analyze_directory_to_write
958
    jc    exit_writing_disk_full
959
 
960
    mov   [sector_tmp],eax
961
    mov   [entry_pos],ebx
962
    push  eax                   ; save directory sector
963
    mov   eax,2
964
    call  get_free_FAT
965
    mov   [cluster],eax         ; first free cluster
966
    pop   eax
967
    jc    exit_writing_disk_full
968
 
969
    mov   esi,PUSHAD_EAX        ; file name
970
    mov   edi,ebx               ; pointer in buffer
971
    mov   ecx,11
972
    cld
973
    rep   movsb
974
 
975
    mov   esi,PUSHAD_EBX        ; file size (bytes left)
976
    mov   [ebx+28],esi          ; file size
977
    mov   ecx,[cluster]
978
    mov   [ebx+26],cx           ; 16 bits low of cluster
979
    shr   ecx,16
980
    mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
981
    mov   byte [ebx+11],0x20    ; attribute = archive
982
 
983
    call  set_current_time_for_entry
984
 
985
    mov   ebx,buffer            ; save the directory name,length,cluster
986
    call  hd_write
74 mario79 987
    cmp   [hd_error],0
988
    jne   exit_write_access_1
1 ha 989
 
990
    imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
991
    xor   ecx,ecx               ; cluster count
992
    mov   ebx,PUSHAD_ECX        ; ebx = buffer
993
 
994
hd_new_block_write:
995
 
996
    mov   eax,[cluster]         ; eax = block
997
    call  set_data_cluster
74 mario79 998
    cmp   [hd_error],0
999
    jne   exit_write_access_1
1 ha 1000
 
1001
    sub   esi,edi               ; sub wrote bytes
1002
    jbe   file_saved_OK         ; end if all done
1003
    add   ebx,edi               ; update buffer position
1004
 
1005
    inc   eax
1006
    call  get_free_FAT          ; next free in FAT
1007
    jc    exit_writing_disk_full_clear
1008
 
1009
    mov   edx,eax
1010
    xchg  eax,[cluster]         ; get old cluster and save new cluster
1011
    call  set_FAT               ; add it in cluster chain
74 mario79 1012
    cmp  [hd_error],0
1013
    jne   exit_write_access_1
1014
 
1 ha 1015
    dec   ecx                   ; update cluster count
1016
    jmp   hd_new_block_write
1017
 
1018
file_saved_OK:
1019
 
1020
    mov   edx,[fatEND]          ; new end for cluster chain
1021
    call  set_FAT
74 mario79 1022
    cmp  [hd_error],0
1023
    jne   exit_write_access_1
1024
 
1 ha 1025
    dec   ecx                   ; update cluster count
1026
 
1027
    call  add_disk_free_space   ; remove clusters from free disk space
74 mario79 1028
    cmp  [hd_error],0
1029
    jne   exit_write_access_1
1 ha 1030
 
1031
    popad
1032
    call  update_disk           ; write all of cache and fat to hd
74 mario79 1033
    cmp   [hd_error],0
1034
    jne   exit_write_access_2
1 ha 1035
    mov   [hd1_status],0
1036
    xor   eax,eax
1037
    ret
1038
 
1039
 
1040
file_read:
1041
;--------------------------------------------------------------------------
1042
;   INPUT :  user-register register-in-this  meaning         symbol-in-this
1043
;
1044
;            EAX           EDI               system call to write   /
1045
;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
1046
;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
1047
;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
1048
;            ESI           EDX   (PAR3)      pointer to path        PAR3
1049
;            EDI           ESI            vt first 512 block to read
1050
;                          EDI               if 0 - read root
1051
;
1052
; output : eax = 0 - ok
1053
;                3 - unknown FS
1054
;                5 - file not found
1055
;                6 - end of file
1056
;                9 - fat table corrupted
74 mario79 1057
;               10 - access denied
1 ha 1058
;          ebx = size of file/directory
1059
;--------------------------------------------------------------------------
256 diamond 1060
        cmp     [fs_type], 16
1061
        jz      fat_ok_for_reading
1062
        cmp     [fs_type], 32
1063
        jz      fat_ok_for_reading
1 ha 1064
    xor   ebx,ebx
1065
    mov   eax,ERROR_UNKNOWN_FS
63 halyavin 1066
    mov   [hd1_status], ebx
1 ha 1067
    ret
1068
 
1069
  fat_ok_for_reading:
1070
;    call  reserve_hd1
1071
 
1072
    pushad
1073
 
1074
    mov   ebx,edx
1075
    call  get_cluster_of_a_path
1076
    jc    file_to_read_not_found
1077
 
1078
    test  edi,edi               ; read rootdir
1079
    jne   no_read_root
1080
 
1081
    xor   eax,eax
1082
    call  get_dir_size          ; return rootdir size
74 mario79 1083
    cmp   [hd_error],0
1084
    jne   file_access_denied
1085
 
1 ha 1086
    mov   [file_size],eax
1087
    mov   eax,[ROOT_CLUSTER]
1088
    jmp   file_read_start
1089
 
1090
  no_read_root:
1091
    mov   ebx,PUSHAD_EAX        ; file name
1092
    call  analyze_directory
1093
    jc    file_to_read_not_found
1094
 
1095
    mov   eax,[ebx+28]          ; file size
1096
    test  byte [ebx+11],0x10    ; is it directory?
1097
    jz    read_set_size         ; no
1098
 
1099
    mov   eax,[ebx+20-2]        ; FAT entry
1100
    mov   ax,[ebx+26]
1101
    and   eax,[fatMASK]
1102
    call  get_dir_size
74 mario79 1103
    cmp   [hd_error],0
1104
    jne   file_access_denied
1 ha 1105
 
1106
  read_set_size:
1107
    mov   [file_size],eax
1108
 
1109
    mov   eax,[ebx+20-2]        ; FAT entry
1110
    mov   ax,[ebx+26]
1111
    and   eax,[fatMASK]
1112
 
1113
  file_read_start:
1114
    mov   ebx,PUSHAD_ECX        ; pointer to buffer
1115
    mov   edx,PUSHAD_EBX        ; file blocks to read
1116
    mov   esi,PUSHAD_ESI        ; first 512 block to read
1117
 
1118
  file_read_new_cluster:
1119
    call  get_data_cluster
1120
    jc    file_read_eof         ; end of file or cluster out of range
1121
 
1122
    test  edx,edx               ; is all read?
1123
    je    file_read_OK          ; yes
1124
 
1125
    call  get_FAT               ; get next cluster
74 mario79 1126
    cmp   [hd_error],0
1127
    jne   file_access_denied
1128
 
1 ha 1129
    cmp   eax,[fatRESERVED]     ; end of file
1130
    jnb   file_read_eof
1131
    cmp   eax,2                 ; incorrect fat chain
1132
    jnb   file_read_new_cluster
1133
 
1134
    popad
1135
    mov   [hd1_status],0
1136
    mov   ebx,[file_size]
1137
    mov   eax,ERROR_FAT_TABLE
1138
    ret
1139
 
1140
  file_read_eof:
74 mario79 1141
    cmp   [hd_error],0
1142
    jne   file_access_denied
1 ha 1143
    popad
1144
    mov   [hd1_status],0
1145
    mov   ebx,[file_size]
1146
    mov   eax,ERROR_END_OF_FILE
1147
    ret
1148
 
1149
  file_read_OK:
1150
    popad
1151
    mov   [hd1_status],0
1152
    mov   ebx,[file_size]
1153
    xor   eax,eax
1154
    ret
1155
 
1156
  file_to_read_not_found:
74 mario79 1157
    cmp   [hd_error],0
1158
    jne   file_access_denied
1 ha 1159
    popad
1160
    mov   [hd1_status],0
1161
    xor   ebx,ebx
1162
    mov   eax,ERROR_FILE_NOT_FOUND
1163
    ret
1164
 
74 mario79 1165
  file_access_denied:
1166
    popad
1167
    mov   [hd1_status],0
1168
    xor   ebx,ebx
1169
    mov   eax,ERROR_ACCESS_DENIED
1170
    ret
1 ha 1171
 
1172
get_dir_size:
1173
;-----------------------------------------------------
1174
; input  : eax = first cluster (0=rootdir)
1175
; output : eax = directory size in bytes
1176
;-----------------------------------------------------
1177
    push  edx
1178
    xor   edx,edx               ; count of directory clusters
1179
    test  eax,eax
1180
    jnz   dir_size_next
1181
 
1182
    mov   eax,[ROOT_SECTORS]
1183
    shl   eax,9                 ; fat16 rootdir size in bytes
256 diamond 1184
    cmp   [fs_type],16
1 ha 1185
    je    dir_size_ret
1186
    mov   eax,[ROOT_CLUSTER]
1187
 
1188
  dir_size_next:
1189
    cmp   eax,2                 ; incorrect fat chain
1190
    jb    dir_size_end
1191
    cmp   eax,[fatRESERVED]     ; end of directory
1192
    ja    dir_size_end
1193
    call  get_FAT               ; get next cluster
74 mario79 1194
    cmp   [hd_error],0
1195
    jne   dir_size_ret
1196
 
1 ha 1197
    inc   edx
1198
    jmp   dir_size_next
1199
 
1200
  dir_size_end:
1201
    imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
1202
    imul  eax,edx
1203
 
1204
  dir_size_ret:
1205
    pop   edx
1206
    ret
1207
 
1208
 
1209
file_delete:
1210
;-----------------------------------------------------
1211
; input  : eax = file/directory name
1212
;          edx = path
1213
;          edi = 1 - allow directory remove else don't remove directory
1214
; output : eax = 0 - ok
1215
;                3 - unknown FS
1216
;                5 - file not found
1217
;               10 - access denied
1218
;-----------------------------------------------------
256 diamond 1219
        cmp     [fs_type], 16
1220
        jz      file_del_fat_ok
1221
        cmp     [fs_type], 32
1222
        jz      file_del_fat_ok
1223
        push    ERROR_UNKNOWN_FS
1224
        pop     eax
1225
        ret
1 ha 1226
 
1227
  file_del_fat_ok:
1228
    pushad
1229
 
1230
    mov   ebx,edx
1231
    call  get_cluster_of_a_path
1232
    jc    file_to_delete_not_found
1233
 
1234
    mov   ebx,PUSHAD_EAX        ; file/directory name
1235
    call  analyze_directory
1236
    jc    file_to_delete_not_found
1237
 
1238
    test  byte [ebx+11],0x10    ; is it directory?
1239
    jz    delete_notdir         ; no. it's file
1240
    cmp   edi,1                 ; allow directory remove
1241
    jnz   delete_no_access      ; no
1242
 
1243
    push  eax                   ; save directory sector
1244
    mov   eax,[ebx+20-2]        ; first cluster of file
1245
    mov   ax,[ebx+26]           ; 0 length files start cluster = 0
1246
    and   eax,[fatMASK]
1247
    xor   ebp,ebp               ; counter for directory deepnes
1248
    call  clear_directory
1249
    pop   eax
1250
    jc    delete_no_access
1251
 
1252
    push  ebx                   ; save directory pointer in buffer
1253
    mov   ebx,buffer
1254
    call  hd_read               ; read directory sector
74 mario79 1255
    cmp  [hd_error],0
1256
    jne  delete_no_access_1
1 ha 1257
    pop   ebx
1258
 
1259
  delete_notdir:
1260
    call  delete_entry_name
74 mario79 1261
    cmp   [hd_error],0
1262
    jne   delete_no_access
1263
 
1 ha 1264
    mov   eax,ecx               ; first cluster of file
1265
    call  clear_cluster_chain
74 mario79 1266
    cmp   [hd_error],0
1267
    jne   delete_no_access
1268
 
1 ha 1269
    popad
1270
    xor   eax,eax
1271
    ret
1272
 
74 mario79 1273
  delete_no_access_1:
1274
     add esp,4
1 ha 1275
  delete_no_access:
1276
    popad
1277
    mov   eax,ERROR_ACCESS_DENIED
1278
    ret
1279
 
1280
  file_to_delete_not_found:
74 mario79 1281
    cmp  [hd_error],0
1282
    jne  delete_no_access
1 ha 1283
    popad
1284
    mov   eax,ERROR_FILE_NOT_FOUND
1285
    ret
1286
 
1287
 
1288
clear_cluster_chain:
1289
;-----------------------------------------------------
1290
; input  : eax = first cluster
1291
;-----------------------------------------------------
1292
    push  eax ecx edx
1293
    xor   ecx,ecx               ; cluster count
1294
 
1295
  clean_new_chain:
1296
    cmp   eax,[LAST_CLUSTER]    ; end of file
1297
    ja    delete_OK
1298
    cmp   eax,2                 ; unfinished fat chain or zero length file
1299
    jb    delete_OK
1300
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1301
    jz    delete_OK
1302
 
1303
    xor   edx,edx
1304
    call  set_FAT               ; clear fat entry
74 mario79 1305
    cmp  [hd_error],0
1306
    jne  access_denied_01
1307
 
1 ha 1308
    inc   ecx                   ; update cluster count
1309
    mov   eax,edx               ; old cluster
1310
    jmp   clean_new_chain
1311
 
1312
  delete_OK:
1313
    call  add_disk_free_space   ; add clusters to free disk space
74 mario79 1314
  access_denied_01:
1 ha 1315
    pop   edx ecx eax
1316
    ret
1317
 
1318
 
1319
clear_directory:
1320
;-----------------------------------------------------
1321
; input  : eax = directory cluster
1322
;          ebp = directory deepnes
1323
; Note   : use recursive call
1324
;-----------------------------------------------------
1325
    pushad
1326
    inc   ebp
1327
    cmp   ebp,64                ; if over 63 directory deep
1328
    jnb   clear_error           ; something must be wrong
1329
 
1330
  clear_new_cluster:
1331
    cmp   eax,[LAST_CLUSTER]
1332
    ja    clear_end
1333
    cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
1334
    jz    clear_end
1335
    mov   esi,eax               ; esi = current directory cluster
1336
    sub   eax,2
1337
    jb    clear_end
1338
    mov   ecx,[SECTORS_PER_CLUSTER]
1339
    imul  eax,ecx
1340
    add   eax,[DATA_START]
1341
 
1342
  clear_new_sector:
1343
    mov   edi,eax               ; edi = current directory sector
1344
    mov   ebx,deltree_buffer
1345
    call  hd_read
74 mario79 1346
    cmp  [hd_error],0
1347
    jne  clear_error
1348
 
1 ha 1349
    mov   edx,512/32            ; count of dir entrys per sector = 16
1350
 
1351
  clear_analyze:
1352
    mov   al,[ebx+11]           ; file attribute
1353
    and   al,0xf
1354
    cmp   al,0xf
1355
    je    clear_long_filename
1356
 
1357
    cmp   byte [ebx],'.'        ; parent or current directory
1358
    je    clear_next_entry
1359
    cmp   byte [ebx],0xe5       ; deleted
1360
    je    clear_next_entry
1361
    cmp   byte [ebx],0          ; empty
1362
    je    clear_write_last
1363
    ;je    clear_next_entry
1364
 
1365
    mov   eax,[ebx+20-2]        ; first cluster of entry
1366
    mov   ax,[ebx+26]
1367
    and   eax,[fatMASK]
1368
 
1369
    test  byte [ebx+11],0x10    ; is it directory?
1370
    jz    clear_file            ; no
1371
 
1372
    push  eax ebx
1373
    mov   eax,edi
1374
    mov   ebx,deltree_buffer    ; save buffer over recursive call
1375
    call  hd_write              ; write directory sector to disk
74 mario79 1376
    cmp   [hd_error],0
1377
    jne   clear_error
1378
 
1 ha 1379
    pop   ebx eax
1380
 
1381
    call  clear_directory       ; recursive call !!!
1382
    jc    clear_error           ; exit if error found
1383
 
1384
    push  eax ebx
1385
    mov   eax,edi
1386
    mov   ebx,deltree_buffer
1387
    call  hd_read               ; read directory sector again
74 mario79 1388
    cmp  [hd_error],0
1389
    jne   clear_error_1
1390
 
1 ha 1391
    pop   ebx eax
1392
 
1393
  clear_file:
1394
    call  clear_cluster_chain
74 mario79 1395
    cmp  [hd_error],0
1396
    jne   clear_error
1 ha 1397
 
1398
  clear_long_filename:
1399
    mov   byte [ebx],0xe5
1400
 
1401
  clear_next_entry:
1402
    add   ebx,32                ; position of next dir entry
1403
    dec   edx
1404
    jnz   clear_analyze
1405
 
1406
    mov   eax,edi
1407
    mov   ebx,deltree_buffer
1408
    call  hd_write              ; write directory sector to disk
74 mario79 1409
    cmp   [hd_error],0
1410
    jne   clear_error
1 ha 1411
 
1412
    inc   eax                   ; next sector
1413
    dec   ecx
1414
    jnz   clear_new_sector
1415
 
1416
    mov   eax,esi
1417
    call  get_FAT               ; get next cluster
74 mario79 1418
    cmp   [hd_error],0
1419
    jne   clear_error
1420
 
1 ha 1421
    jmp   clear_new_cluster     ; clear it
1422
 
1423
  clear_write_last:
1424
    mov   eax,edi
1425
    mov   ebx,deltree_buffer
1426
    call  hd_write              ; write directory sector to disk
74 mario79 1427
    cmp   [hd_error],0
1428
    jne   clear_error
1 ha 1429
 
1430
  clear_end:
1431
    popad
1432
    clc
1433
    ret
74 mario79 1434
clear_error_1:
1435
    add  esp,8
1 ha 1436
  clear_error:
1437
    popad
1438
    stc
1439
    ret
1440
 
1441
 
1442
delete_entry_name:
1443
;-----------------------------------------------------
1444
; input  : eax = directory sector
1445
;          ebx = directory pointer in buffer
1446
;          longname_sec = 2 previous directory sectors
1447
; output : ecx = first cluster
1448
; change : eax,ebx,edx
1449
;-----------------------------------------------------
1450
    mov   byte [ebx],0xe5
1451
    mov   ecx,[ebx+20-2]        ; first cluster of file
1452
    mov   cx,[ebx+26]           ; 0 length files start cluster = 0
1453
    and   ecx,[fatMASK]
1454
 
1455
  delete_empty:
1456
    sub   ebx,32
1457
    cmp   ebx,buffer
1458
    jnb   delete_test_long
1459
 
1460
    mov   ebx,buffer
1461
    call  hd_write              ; write directory sector back
74 mario79 1462
    cmp   [hd_error],0
1463
    jne   delete_name_end
1464
 
1 ha 1465
    xor   eax,eax
1466
    xchg  eax,[longname_sec2]
1467
    xchg  eax,[longname_sec1]
1468
    test  eax,eax               ; is there previous directory sector?
1469
    jz    delete_name_end       ; no
1470
 
1471
    mov   ebx,buffer
1472
    call  hd_read               ; read previous sector
74 mario79 1473
    cmp  [hd_error],0
1474
    jne  delete_name_end
1475
 
1 ha 1476
    mov   ebx,buffer+0x1e0      ; start from last entry
1477
 
1478
  delete_test_long:
1479
    mov   dh,[ebx+11]           ; file attribute
1480
    and   dh,0xf
1481
    cmp   dh,0xf
1482
    jne   delete_write_buffer
1483
 
1484
    cmp   byte [ebx],0x40       ; end of long dir entry?
1485
    mov   byte [ebx],0xe5
1486
    jb    delete_empty
1487
 
1488
  delete_write_buffer:
1489
    mov   ebx,buffer
1490
    call  hd_write              ; write directory sector back
1491
 
1492
  delete_name_end:
1493
    ret
1494
 
1495
 
1496
get_hd_info:
1497
;-----------------------------------------------------------
1498
; output : eax = 0 - ok
1499
;                3 - unknown FS
74 mario79 1500
;               10 - access denied
1 ha 1501
;          edx = cluster size in bytes
1502
;          ebx = total clusters on disk
1503
;          ecx = free clusters on disk
1504
;-----------------------------------------------------------
256 diamond 1505
        cmp     [fs_type], 16
1506
        jz      info_fat_ok
1507
        cmp     [fs_type], 32
1508
        jz      info_fat_ok
1 ha 1509
    xor   edx,edx
1510
    xor   ebx,ebx
1511
    xor   ecx,ecx
1512
    mov   eax,ERROR_UNKNOWN_FS
1513
    ret
1514
 
1515
  info_fat_ok:
1516
;    call  reserve_hd1
1517
 
1518
    xor   ecx,ecx               ; count of free clusters
1519
    mov   eax,2
1520
    mov   ebx,[LAST_CLUSTER]
1521
 
1522
  info_cluster:
1523
    push  eax
1524
    call  get_FAT               ; get cluster info
74 mario79 1525
    cmp   [hd_error],0
1526
    jne   info_access_denied
1527
 
1 ha 1528
    test  eax,eax               ; is it free?
1529
    jnz   info_used             ; no
1530
    inc   ecx
1531
 
1532
  info_used:
1533
    pop   eax
1534
    inc   eax
1535
    cmp   eax,ebx               ; is above last cluster?
1536
    jbe   info_cluster          ; no. test next cluster
1537
 
1538
    dec   ebx                   ; cluster count
1539
    imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
1540
    mov   [hd1_status],0
1541
    xor   eax,eax
1542
    ret
1543
 
74 mario79 1544
  info_access_denied:
1545
    add   esp,4
1546
    xor   edx,edx
1547
    xor   ebx,ebx
1548
    xor   ecx,ecx
1549
    mov   eax,ERROR_ACCESS_DENIED
1550
    ret
1 ha 1551
 
1552
update_disk:
1553
;-----------------------------------------------------------
1554
; write changed fat and cache to disk
1555
;-----------------------------------------------------------
1556
    cmp   [fat_change],0        ; is fat changed?
1557
    je    upd_no_change
1558
 
1559
    call  write_fat_sector
74 mario79 1560
    cmp   [hd_error],0
1561
    jne   update_disk_acces_denied
1 ha 1562
 
1563
  upd_no_change:
1564
 
1565
    call  write_cache
74 mario79 1566
  update_disk_acces_denied:
1 ha 1567
    ret
1568
 
1569
read_hd_file:
1570
;-----------------------------------------------------------------
1571
;
1572
; Converting old reading function for hd-application start.
1573
;
1574
; IN:
1575
;
1576
; eax - pointer to file (0 = read only first sector of drive: eg 'label')
1577
; ebx - file lenght
1578
; ecx - start 512 byte block number
1579
; edx - number of blocks to read
1580
; esi - pointer to return/work area (atleast 20 000 bytes)
1581
;
1582
; For new read function
1583
;
1584
; EAX   (PAR0)      pointer to file-name
1585
; ECX   (PAR1)      pointer to buffer
1586
; EBX   (PAR2)   vt file blocks to read
1587
; EDX   (PAR3)      pointer to path
1588
; ESI            vt first 512 block to read
1589
; EDI               if 0 - return root
1590
;--------------------------------------------------------------------------
1591
 
1592
    push  ecx esi edi
1593
    mov   esi,eax
1594
    mov   edi,startpath
1595
    mov   ecx,250
1596
    cld
1597
    rep   movsb
1598
    pop   edi esi ecx
1599
 
1600
    mov   eax,startpath
1601
    mov   [eax+ebx-12],byte 0
1602
 
1603
    push  eax ebx ecx edx esi
1604
 
1605
    pop   ecx ; pointer to buffer
1606
    add   ecx,1024
1607
    pop   ebx ; number of blocks to read
1608
    pop   esi ; first block to read
1609
    dec   esi
1610
    pop   eax ; file length
1611
    pop   edx ; pointer to path
1612
 
1613
    mov   edi,12
1614
    lea   eax,[eax+edx-12+1]
1615
    call  file_read
1616
 
1617
    ret
1618
 
71 diamond 1619
; \begin{diamond}
1620
hd_find_lfn:
1621
; in: esi->name
1622
; out: CF=1 - file not found
86 diamond 1623
;      else CF=0 and edi->direntry, eax=sector
83 diamond 1624
; destroys eax
1625
        push    esi edi
1626
        push    0
1627
        push    0
1628
        push    fat16_root_first
1629
        push    fat16_root_next
1630
        mov     eax, [ROOT_CLUSTER]
256 diamond 1631
        cmp     [fs_type], 32
83 diamond 1632
        jz      .fat32
1633
.loop:
1634
        call    fat_find_lfn
1635
        jc      .notfound
1636
        cmp     byte [esi], 0
1637
        jz      .found
1638
        test    byte [edi+11], 10h
1639
        jz      .notfound
1640
        and     dword [esp+12], 0
88 diamond 1641
        mov     eax, [edi+20-2]
1642
        mov     ax, [edi+26]    ; cluster
83 diamond 1643
.fat32:
1644
        mov     [esp+8], eax
1645
        mov     dword [esp+4], fat_notroot_first
1646
        mov     dword [esp], fat_notroot_next
1647
        jmp     .loop
71 diamond 1648
.notfound:
83 diamond 1649
        add     esp, 16
1650
        pop     edi esi
1651
        stc
1652
        ret
71 diamond 1653
.found:
86 diamond 1654
        lea     eax, [esp+8]
1655
        cmp     dword [eax], 0
1656
        jz      .root
1657
        call    fat_get_sector
1658
        jmp     .cmn
1659
.root:
1660
        mov     eax, [eax+4]
1661
        add     eax, [ROOT_START]
1662
.cmn:
83 diamond 1663
        add     esp, 20         ; CF=0
1664
        pop     esi
1665
        ret
74 mario79 1666
 
71 diamond 1667
;----------------------------------------------------------------
1668
;
1669
;  fs_HdRead - LFN variant for reading hard disk
1670
;
1671
;  esi  points to filename
1672
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1673
;       may be ebx=0 - start from first byte
1674
;  ecx  number of bytes to read, 0+
1675
;  edx  mem location to return data
1676
;
77 diamond 1677
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 1678
;      eax = 0 ok read or other = errormsg
1679
;
1680
;--------------------------------------------------------------
1681
fs_HdRead:
256 diamond 1682
        cmp     [fs_type], 16
1683
        jz      @f
1684
        cmp     [fs_type], 32
1685
        jz      @f
1686
        cmp     [fs_type], 1
1687
        jz      ntfs_HdRead
1688
        or      ebx, -1
1689
        mov     eax, ERROR_UNKNOWN_FS
1690
        ret
71 diamond 1691
@@:
74 mario79 1692
    push    edi
1693
    cmp    byte [esi], 0
1694
    jnz    @f
71 diamond 1695
.noaccess:
74 mario79 1696
    pop    edi
1697
.noaccess_2:
1698
    or    ebx, -1
1699
    mov    eax, ERROR_ACCESS_DENIED
1700
    ret
1701
 
1702
.noaccess_3:
1703
    add esp,4
1704
.noaccess_1:
1705
    add esp,4
1706
.noaccess_4:
1707
    add esp,4*5
1708
    jmp  .noaccess_2
1709
 
71 diamond 1710
@@:
74 mario79 1711
    call    hd_find_lfn
1712
    jnc    .found
1713
    pop    edi
1714
    cmp   [hd_error],0
1715
    jne   .noaccess_2
1716
    or    ebx, -1
1717
    mov    eax, ERROR_FILE_NOT_FOUND
1718
    ret
1719
 
71 diamond 1720
.found:
74 mario79 1721
    test    byte [edi+11], 0x10    ; do not allow read directories
1722
    jnz    .noaccess
1723
    test    ebx, ebx
1724
    jz    .l1
1725
    cmp    dword [ebx+4], 0
1726
    jz    @f
77 diamond 1727
        xor     ebx, ebx
71 diamond 1728
.reteof:
74 mario79 1729
    mov    eax, 6
1730
    pop    edi
1731
    ret
71 diamond 1732
@@:
74 mario79 1733
    mov    ebx, [ebx]
71 diamond 1734
.l1:
77 diamond 1735
        push    ecx edx
1736
        push    0
1737
        mov     eax, [edi+28]
1738
        sub     eax, ebx
1739
        jb      .eof
1740
        cmp     eax, ecx
1741
        jae     @f
1742
        mov     ecx, eax
1743
        mov     byte [esp], 6
1744
@@:
74 mario79 1745
    mov    eax, [edi+20-2]
1746
    mov    ax, [edi+26]
71 diamond 1747
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
1748
.new_cluster:
74 mario79 1749
    jecxz    .new_sector
1750
    test    eax, eax
1751
    jz    .eof
1752
    cmp    eax, [fatRESERVED]
1753
    jae    .eof
1754
    mov    [cluster_tmp], eax
1755
    dec    eax
1756
    dec    eax
1757
    mov    edi, [SECTORS_PER_CLUSTER]
1758
    imul    eax, edi
1759
    add    eax, [DATA_START]
71 diamond 1760
.new_sector:
74 mario79 1761
    test    ecx, ecx
1762
    jz    .done
1763
    sub    ebx, 512
1764
    jae    .skip
1765
    add    ebx, 512
1766
    jnz    .force_buf
1767
    cmp    ecx, 512
1768
    jb    .force_buf
71 diamond 1769
; we may read directly to given buffer
74 mario79 1770
    push    ebx
1771
    mov    ebx, edx
1772
    call    hd_read
1773
    cmp  [hd_error],0
1774
    jne  .noaccess_1
1775
    pop    ebx
1776
    add    edx, 512
1777
    sub    ecx, 512
1778
    jmp    .skip
71 diamond 1779
.force_buf:
1780
; we must read sector to temporary buffer and then copy it to destination
74 mario79 1781
    push    eax ebx
1782
    mov    ebx, buffer
1783
    call    hd_read
1784
    cmp  [hd_error],0
1785
    jne  .noaccess_3
1786
 
1787
    mov    eax, ebx
1788
    pop    ebx
1789
    add    eax, ebx
1790
    push    ecx
1791
    add    ecx, ebx
1792
    cmp    ecx, 512
1793
    jbe    @f
1794
    mov    ecx, 512
71 diamond 1795
@@:
74 mario79 1796
    sub    ecx, ebx
1797
    mov    ebx, edx
1798
    call    memmove
1799
    add    edx, ecx
1800
    sub    [esp], ecx
1801
    pop    ecx
1802
    pop    eax
1803
    xor    ebx, ebx
71 diamond 1804
.skip:
74 mario79 1805
    inc    eax
1806
    dec    edi
1807
    jnz    .new_sector
1808
    mov    eax, [cluster_tmp]
1809
    call    get_FAT
1810
    cmp   [hd_error],0
1811
    jne   .noaccess_4
1812
 
1813
    jmp    .new_cluster
71 diamond 1814
.done:
77 diamond 1815
        mov     ebx, edx
1816
        pop     eax edx ecx edi
1817
        sub     ebx, edx
1818
        ret
71 diamond 1819
.eof:
77 diamond 1820
        mov     ebx, edx
1821
        pop     eax edx ecx
1822
        sub     ebx, edx
1823
        jmp     .reteof
75 diamond 1824
 
1825
;----------------------------------------------------------------
1826
;
1827
;  fs_HdReadFolder - LFN variant for reading hard disk folder
1828
;
1829
;  esi  points to filename
78 diamond 1830
;  ebx  pointer to structure 32-bit number = first wanted block, 0+
1831
;                          & flags (bitfields)
1832
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 1833
;  ecx  number of blocks to read, 0+
1834
;  edx  mem location to return data
1835
;
77 diamond 1836
;  ret ebx = blocks read or 0xffffffff folder not found
75 diamond 1837
;      eax = 0 ok read or other = errormsg
1838
;
1839
;--------------------------------------------------------------
1840
fs_HdReadFolder:
256 diamond 1841
        cmp     [fs_type], 1
1842
        jz      ntfs_HdReadFolder
1843
        cmp     [fs_type], 16
1844
        jz      @f
1845
        cmp     [fs_type], 32
1846
        jz      @f
1847
        push    ERROR_UNSUPPORTED_FS
1848
        pop     eax
1849
        or      ebx, -1
1850
        ret
1851
@@:
75 diamond 1852
        mov     eax, [ROOT_CLUSTER]
1853
        push    edi
1854
        cmp     byte [esi], 0
1855
        jz      .doit
1856
        call    hd_find_lfn
1857
        jnc     .found
1858
        pop     edi
1859
        or      ebx, -1
1860
        mov     eax, ERROR_FILE_NOT_FOUND
1861
        ret
1862
.found:
1863
        test    byte [edi+11], 0x10     ; do not allow read files
1864
        jnz     .found_dir
1865
        pop     edi
1866
        or      ebx, -1
1867
        mov     eax, ERROR_ACCESS_DENIED
1868
        ret
1869
.found_dir:
1870
        mov     eax, [edi+20-2]
1871
        mov     ax, [edi+26]    ; eax=cluster
1872
.doit:
1873
        push    esi ecx
1874
        push    ebp
1875
        sub     esp, 262*2      ; reserve space for LFN
1876
        mov     ebp, esp
78 diamond 1877
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
1878
        mov     ebx, [ebx]
75 diamond 1879
; init header
1880
        push    eax ecx
1881
        mov     edi, edx
1882
        mov     ecx, 32/4
1883
        xor     eax, eax
1884
        rep     stosd
1885
        pop     ecx eax
1886
        mov     byte [edx], 1   ; version
1887
        mov     esi, edi        ; esi points to BDFE
1888
.new_cluster:
1889
        mov     [cluster_tmp], eax
1890
        test    eax, eax
1891
        jnz     @f
256 diamond 1892
        cmp     [fs_type], 32
75 diamond 1893
        jz      .notfound
1894
        mov     eax, [ROOT_START]
1895
        push    [ROOT_SECTORS]
1896
        push    ebx
1897
        jmp     .new_sector
1898
@@:
1899
        dec     eax
1900
        dec     eax
1901
        imul    eax, [SECTORS_PER_CLUSTER]
1902
        push    [SECTORS_PER_CLUSTER]
1903
        add     eax, [DATA_START]
1904
        push    ebx
1905
.new_sector:
1906
        mov     ebx, buffer
1907
        mov     edi, ebx
1908
        call    hd_read
1909
        cmp     [hd_error], 0
1910
        jnz     .notfound2
1911
        add     ebx, 512
1912
        push    eax
1913
.l1:
1914
        call    fat_get_name
1915
        jc      .l2
1916
        cmp     byte [edi+11], 0xF
1917
        jnz     .do_bdfe
1918
        add     edi, 0x20
1919
        cmp     edi, ebx
1920
        jb      .do_bdfe
1921
        pop     eax
1922
        inc     eax
1923
        dec     dword [esp+4]
1924
        jnz     @f
1925
        mov     eax, [cluster_tmp]
1926
        test    eax, eax
1927
        jz      .done
1928
        call    get_FAT
1929
        cmp     [hd_error], 0
1930
        jnz     .notfound2
1931
        cmp     eax, 2
1932
        jb      .done
1933
        cmp     eax, [fatRESERVED]
1934
        jae     .done
1935
        push    eax
1936
        mov     eax, [SECTORS_PER_CLUSTER]
1937
        mov     [esp+8], eax
1938
        pop     eax
1939
        mov     [cluster_tmp], eax
1940
        dec     eax
1941
        dec     eax
1942
        imul    eax, [SECTORS_PER_CLUSTER]
1943
        add     eax, [DATA_START]
1944
@@:
1945
        mov     ebx, buffer
1946
        mov     edi, ebx
1947
        call    hd_read
1948
        cmp     [hd_error], 0
1949
        jnz     .notfound2
1950
        add     ebx, 512
1951
        push    eax
1952
.do_bdfe:
1953
        inc     dword [edx+8]   ; new file found
1954
        dec     dword [esp+4]
1955
        jns     .l2
1956
        dec     ecx
1957
        js      .l2
1958
        inc     dword [edx+4]   ; new file block copied
1959
        call    fat_entry_to_bdfe
1960
.l2:
1961
        add     edi, 0x20
1962
        cmp     edi, ebx
1963
        jb      .l1
1964
        pop     eax
1965
        inc     eax
1966
        dec     dword [esp+4]
1967
        jnz     .new_sector
1968
        mov     eax, [cluster_tmp]
1969
        test    eax, eax
1970
        jz      .done
1971
        call    get_FAT
1972
        cmp     [hd_error], 0
1973
        jnz     .notfound2
1974
        cmp     eax, 2
1975
        jb      .done
1976
        cmp     eax, [fatRESERVED]
1977
        jae     .done
1978
        push    eax
1979
        mov     eax, [SECTORS_PER_CLUSTER]
1980
        mov     [esp+8], eax
1981
        pop     eax
1982
        pop     ebx
1983
        add     esp, 4
1984
        jmp     .new_cluster
1985
.notfound2:
1986
        add     esp, 8
1987
.notfound:
1988
        add     esp, 262*2+4
1989
        pop     ebp ecx esi edi
1990
        mov     eax, ERROR_FILE_NOT_FOUND
1991
        or      ebx, -1
1992
        ret
1993
.done:
1994
        add     esp, 262*2+4+8
1995
        pop     ebp
77 diamond 1996
        mov     ebx, [edx+4]
75 diamond 1997
        xor     eax, eax
1998
        dec     ecx
1999
        js      @f
2000
        mov     al, ERROR_END_OF_FILE
2001
@@:
2002
        pop     ecx esi edi
2003
        ret
2004
 
83 diamond 2005
fat16_root_next:
2006
        cmp     edi, buffer+0x200-0x20
2007
        jae     fat16_root_next_sector
2008
        add     edi, 0x20
2009
        ret     ; CF=0
2010
fat16_root_next_sector:
2011
; read next sector
171 diamond 2012
        push    [longname_sec2]
2013
        pop     [longname_sec1]
83 diamond 2014
        push    ecx
2015
        mov     ecx, [eax+4]
171 diamond 2016
        push    ecx
2017
        add     ecx, [ROOT_START]
2018
        mov     [longname_sec2], ecx
2019
        pop     ecx
83 diamond 2020
        inc     ecx
2021
        mov     [eax+4], ecx
2022
        cmp     ecx, [ROOT_SECTORS]
2023
        pop     ecx
2024
        jae     fat16_root_first.readerr
2025
fat16_root_first:
2026
        mov     eax, [eax+4]
2027
        add     eax, [ROOT_START]
2028
        push    ebx
2029
        mov     edi, buffer
2030
        mov     ebx, edi
2031
        call    hd_read
2032
        pop     ebx
2033
        cmp     [hd_error], 0
2034
        jnz     .readerr
2035
        ret     ; CF=0
2036
.readerr:
2037
        stc
2038
        ret
2039
fat16_root_begin_write:
2040
        push    edi eax
2041
        call    fat16_root_first
2042
        pop     eax edi
2043
        ret
2044
fat16_root_end_write:
2045
        pusha
2046
        mov     eax, [eax+4]
2047
        add     eax, [ROOT_START]
2048
        mov     ebx, buffer
2049
        call    hd_write
2050
        popa
2051
        ret
2052
fat16_root_next_write:
2053
        cmp     edi, buffer+0x200
2054
        jae     @f
2055
        ret
2056
@@:
2057
        call    fat16_root_end_write
2058
        jmp     fat16_root_next_sector
2059
fat16_root_extend_dir:
2060
        stc
2061
        ret
2062
 
2063
fat_notroot_next:
2064
        cmp     edi, buffer+0x200-0x20
2065
        jae     fat_notroot_next_sector
2066
        add     edi, 0x20
2067
        ret     ; CF=0
2068
fat_notroot_next_sector:
171 diamond 2069
        push    [longname_sec2]
2070
        pop     [longname_sec1]
2071
        push    eax
2072
        call    fat_get_sector
2073
        mov     [longname_sec2], eax
2074
        pop     eax
83 diamond 2075
        push    ecx
2076
        mov     ecx, [eax+4]
2077
        inc     ecx
2078
        cmp     ecx, [SECTORS_PER_CLUSTER]
2079
        jae     fat_notroot_next_cluster
2080
        mov     [eax+4], ecx
2081
        jmp     @f
2082
fat_notroot_next_cluster:
2083
        push    eax
2084
        mov     eax, [eax]
2085
        call    get_FAT
2086
        mov     ecx, eax
2087
        pop     eax
2088
        cmp     [hd_error], 0
2089
        jnz     fat_notroot_next_err
2090
        cmp     ecx, [fatRESERVED]
2091
        jae     fat_notroot_next_err
2092
        mov     [eax], ecx
2093
        and     dword [eax+4], 0
2094
@@:
2095
        pop     ecx
2096
fat_notroot_first:
2097
        call    fat_get_sector
2098
        push    ebx
2099
        mov     edi, buffer
2100
        mov     ebx, edi
2101
        call    hd_read
2102
        pop     ebx
2103
        cmp     [hd_error], 0
2104
        jnz     @f
2105
        ret     ; CF=0
2106
fat_notroot_next_err:
2107
        pop     ecx
2108
@@:
2109
        stc
2110
        ret
2111
fat_notroot_begin_write:
2112
        push    eax edi
2113
        call    fat_notroot_first
2114
        pop     edi eax
2115
        ret
2116
fat_notroot_end_write:
2117
        call    fat_get_sector
2118
        push    ebx
2119
        mov     ebx, buffer
2120
        call    hd_write
2121
        pop     ebx
2122
        ret
2123
fat_notroot_next_write:
2124
        cmp     edi, buffer+0x200
2125
        jae     @f
2126
        ret
2127
@@:
2128
        push    eax
2129
        call    fat_notroot_end_write
2130
        pop     eax
2131
        jmp     fat_notroot_next_sector
2132
fat_notroot_extend_dir:
2133
        push    eax
2134
        mov     eax, [eax]
2135
        call    get_free_FAT
2136
        jnc     .found
2137
        pop     eax
2138
        ret     ; CF=1
2139
.found:
2140
        push    edx
2141
        mov     edx, [fatEND]
2142
        call    set_FAT
2143
        mov     edx, eax
2144
        mov     eax, [esp+4]
2145
        mov     eax, [eax]
2146
        push    edx
2147
        call    set_FAT
2148
        pop     edx
2149
        cmp     [hd_error], 0
2150
        jz      @f
2151
        pop     edx
2152
        pop     eax
2153
        stc
2154
        ret
2155
@@:
2156
        push    ecx
2157
        or      ecx, -1
2158
        call    add_disk_free_space
2159
; zero new cluster
2160
        mov     ecx, 512/4
2161
        mov     edi, buffer
2162
        push    edi
2163
        xor     eax, eax
2164
        rep     stosd
2165
        pop     edi
2166
        pop     ecx
2167
        mov     eax, [esp+4]
2168
        mov     [eax], edx
2169
        and     dword [eax+4], 0
2170
        pop     edx
2171
        mov     eax, [eax]
2172
        dec     eax
2173
        dec     eax
2174
        push    ebx ecx
2175
        mov     ecx, [SECTORS_PER_CLUSTER]
2176
        imul    eax, ecx
2177
        add     eax, [DATA_START]
2178
        mov     ebx, edi
2179
@@:
2180
        call    hd_write
2181
        inc     eax
2182
        loop    @b
2183
        pop     ecx ebx eax
2184
        clc
2185
        ret
2186
 
2187
fat_get_sector:
2188
        push    ecx
2189
        mov     ecx, [eax]
2190
        dec     ecx
2191
        dec     ecx
2192
        imul    ecx, [SECTORS_PER_CLUSTER]
2193
        add     ecx, [DATA_START]
2194
        add     ecx, [eax+4]
2195
        mov     eax, ecx
2196
        pop     ecx
2197
        ret
2198
 
2199
;----------------------------------------------------------------
2200
;
2201
;  fs_HdRewrite - LFN variant for writing hard disk
2202
;
2203
;  esi  points to filename
2204
;  ebx  ignored (reserved)
2205
;  ecx  number of bytes to write, 0+
2206
;  edx  mem location to data
2207
;
2208
;  ret ebx = number of written bytes
2209
;      eax = 0 ok read or other = errormsg
2210
;
2211
;--------------------------------------------------------------
2212
fshrad:
2213
        mov     eax, ERROR_ACCESS_DENIED
2214
        xor     ebx, ebx
2215
        ret
2216
fshrfs:
2217
        mov     eax, ERROR_UNKNOWN_FS
2218
        xor     ebx, ebx
2219
        ret
2220
 
321 diamond 2221
fs_HdCreateFolder:
2222
        mov     al, 1
2223
        jmp     fs_HdRewrite.common
2224
 
83 diamond 2225
fs_HdRewrite:
321 diamond 2226
        xor     eax, eax
2227
.common:
256 diamond 2228
        cmp     [fs_type], 1
2229
        jz      ntfs_HdRewrite
2230
        cmp     [fs_type], 16
2231
        jz      @f
2232
        cmp     [fs_type], 32
2233
        jnz     fshrfs
2234
@@:
83 diamond 2235
        cmp     byte [esi], 0
2236
        jz      fshrad
2237
        pushad
2238
        xor     ebp, ebp
2239
        push    esi
2240
@@:
2241
        lodsb
2242
        test    al, al
2243
        jz      @f
2244
        cmp     al, '/'
2245
        jnz     @b
2246
        lea     ebp, [esi-1]
2247
        jmp     @b
2248
@@:
2249
        pop     esi
2250
        test    ebp, ebp
2251
        jnz     .noroot
2252
        mov     ebp, [ROOT_CLUSTER]
256 diamond 2253
        cmp     [fs_type], 32
83 diamond 2254
        jz      .pushnotroot
2255
        push    fat16_root_extend_dir
2256
        push    fat16_root_end_write
2257
        push    fat16_root_next_write
2258
        push    fat16_root_begin_write
2259
        xor     ebp, ebp
2260
        push    ebp
2261
        push    ebp
2262
        push    fat16_root_first
2263
        push    fat16_root_next
2264
        jmp     .common1
2265
.noroot:
2266
; check existence
2267
        mov     byte [ebp], 0
2268
        call    hd_find_lfn
2269
        mov     byte [ebp], '/'
2270
        lea     esi, [ebp+1]
2271
        jnc     @f
2272
        mov     eax, ERROR_FILE_NOT_FOUND
2273
.ret1:
2274
        mov     [esp+28], eax
2275
        popad
2276
        xor     ebx, ebx
2277
        ret
2278
@@:
2279
        test    byte [edi+11], 0x10     ; must be directory
2280
        mov     eax, ERROR_ACCESS_DENIED
2281
        jz      .ret1
2282
        mov     ebp, [edi+20-2]
2283
        mov     bp, [edi+26]            ; ebp=cluster
2284
        mov     eax, ERROR_FAT_TABLE
2285
        cmp     ebp, 2
2286
        jb      .ret1
2287
.pushnotroot:
2288
        push    fat_notroot_extend_dir
2289
        push    fat_notroot_end_write
2290
        push    fat_notroot_next_write
2291
        push    fat_notroot_begin_write
2292
        push    0
2293
        push    ebp
2294
        push    fat_notroot_first
2295
        push    fat_notroot_next
2296
.common1:
2297
        call    fat_find_lfn
2298
        jc      .notfound
321 diamond 2299
; found
91 diamond 2300
        test    byte [edi+11], 10h
321 diamond 2301
        jz      .exists_file
2302
; found directory; if we are creating directory, return OK,
2303
;                  if we are creating file, say "access denied"
2304
        add     esp, 32
2305
        popad
2306
        test    al, al
2307
        mov     eax, ERROR_ACCESS_DENIED
91 diamond 2308
        jz      @f
321 diamond 2309
        mov     al, 0
2310
@@:
2311
        xor     ebx, ebx
2312
        ret
2313
.exists_file:
2314
; found file; if we are creating directory, return "access denied",
2315
;             if we are creating file, delete existing file and continue
2316
        cmp     byte [esp+32+28], 0
2317
        jz      @f
91 diamond 2318
        add     esp, 32
2319
        popad
2320
        mov     eax, ERROR_ACCESS_DENIED
2321
        xor     ebx, ebx
2322
        ret
2323
@@:
2324
; delete FAT chain
83 diamond 2325
        push    edi
2326
        xor     eax, eax
2327
        mov     dword [edi+28], eax     ; zero size
2328
        xor     ecx, ecx
2329
        mov     eax, [edi+20-2]
2330
        mov     ax, [edi+26]
2331
        mov     word [edi+20], cx
2332
        mov     word [edi+26], cx
2333
        test    eax, eax
2334
        jz      .done1
2335
@@:
2336
        cmp     eax, [fatRESERVED]
2337
        jae     .done1
2338
        push    edx
2339
        xor     edx, edx
2340
        call    set_FAT
2341
        mov     eax, edx
2342
        pop     edx
2343
        inc     ecx
2344
        jmp     @b
2345
.done1:
2346
        pop     edi
2347
        call    get_time_for_file
2348
        mov     [edi+22], ax
2349
        call    get_date_for_file
2350
        mov     [edi+24], ax
2351
        mov     [edi+18], ax
2352
        or      byte [edi+11], 20h      ; set 'archive' attribute
2353
        jmp     .doit
2354
.notfound:
2355
; file is not found; generate short name
2356
        call    fat_name_is_legal
2357
        jc      @f
2358
        add     esp, 32
2359
        popad
2360
        mov     eax, ERROR_FILE_NOT_FOUND
2361
        xor     ebx, ebx
2362
        ret
2363
@@:
2364
        sub     esp, 12
2365
        mov     edi, esp
2366
        call    fat_gen_short_name
2367
.test_short_name_loop:
2368
        push    esi edi ecx
2369
        mov     esi, edi
2370
        lea     eax, [esp+12+12+8]
2371
        mov     [eax], ebp
2372
        and     dword [eax+4], 0
2373
        call    dword [eax-4]
2374
        jc      .found
2375
.test_short_name_entry:
2376
        cmp     byte [edi+11], 0xF
2377
        jz      .test_short_name_cont
2378
        mov     ecx, 11
2379
        push    esi edi
2380
        repz    cmpsb
2381
        pop     edi esi
2382
        jz      .short_name_found
2383
.test_short_name_cont:
2384
        lea     eax, [esp+12+12+8]
2385
        call    dword [eax-8]
2386
        jnc     .test_short_name_entry
2387
        jmp     .found
2388
.short_name_found:
2389
        pop     ecx edi esi
2390
        call    fat_next_short_name
2391
        jnc     .test_short_name_loop
2392
.disk_full:
2393
        add     esp, 12+32
2394
        popa
2395
        mov     eax, ERROR_DISK_FULL
2396
        xor     ebx, ebx
2397
        ret
2398
.found:
2399
        pop     ecx edi esi
2400
; now find space in directory
2401
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
2402
        mov     al, '~'
2403
        push    ecx edi
2404
        mov     ecx, 8
2405
        repnz   scasb
2406
        push    1
2407
        pop     eax     ; 1 entry
2408
        jnz     .notilde
2409
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
2410
        xor     eax, eax
2411
@@:
2412
        cmp     byte [esi], 0
2413
        jz      @f
2414
        inc     esi
2415
        inc     eax
2416
        jmp     @b
2417
@@:
2418
        sub     esi, eax
2419
        add     eax, 12+13
2420
        mov     ecx, 13
2421
        push    edx
2422
        cdq
2423
        div     ecx
2424
        pop     edx
2425
.notilde:
2426
        push    -1
2427
        push    -1
2428
        push    -1
2429
; find  successive entries in directory
2430
        xor     ecx, ecx
2431
        push    eax
2432
        lea     eax, [esp+16+8+12+8]
2433
        mov     [eax], ebp
2434
        and     dword [eax+4], 0
2435
        call    dword [eax-4]
2436
        pop     eax
2437
        jnc     .scan_dir
2438
.fsfrfe3:
2439
        add     esp, 12+8+12+32
2440
        popad
2441
        mov     eax, 11
2442
        xor     ebx, ebx
2443
        ret
2444
.scan_dir:
2445
        cmp     byte [edi], 0
2446
        jz      .free
2447
        cmp     byte [edi], 0xE5
2448
        jz      .free
2449
        xor     ecx, ecx
2450
.scan_cont:
2451
        push    eax
2452
        lea     eax, [esp+16+8+12+8]
2453
        call    dword [eax-8]
2454
        pop     eax
2455
        jnc     .scan_dir
2456
        cmp     [hd_error], 0
2457
        jnz     .fsfrfe3
2458
        push    eax
2459
        lea     eax, [esp+16+8+12+8]
2460
        call    dword [eax+20]          ; extend directory
2461
        pop     eax
2462
        jnc     .scan_dir
2463
        add     esp, 12+8+12+32
2464
        popad
2465
        mov     eax, ERROR_DISK_FULL
2466
        xor     ebx, ebx
2467
        ret
2468
.free:
2469
        test    ecx, ecx
2470
        jnz     @f
2471
        mov     [esp], edi
2472
        mov     ecx, [esp+12+8+12+8]
2473
        mov     [esp+4], ecx
2474
        mov     ecx, [esp+12+8+12+12]
2475
        mov     [esp+8], ecx
2476
        xor     ecx, ecx
2477
@@:
2478
        inc     ecx
2479
        cmp     ecx, eax
2480
        jb      .scan_cont
2481
; found!
2482
; calculate name checksum
2483
        push    esi ecx
2484
        mov     esi, [esp+8+12]
2485
        mov     ecx, 11
2486
        xor     eax, eax
2487
@@:
2488
        ror     al, 1
2489
        add     al, [esi]
2490
        inc     esi
2491
        loop    @b
2492
        pop     ecx esi
2493
        pop     edi
2494
        pop     dword [esp+8+12+12]
2495
        pop     dword [esp+8+12+12]
2496
; edi points to first entry in free chunk
2497
        dec     ecx
2498
        jz      .nolfn
2499
        push    esi
2500
        push    eax
2501
        lea     eax, [esp+8+8+12+8]
2502
        call    dword [eax+8]         ; begin write
2503
        mov     al, 40h
2504
.writelfn:
2505
        or      al, cl
2506
        mov     esi, [esp+4]
2507
        push    ecx
2508
        dec     ecx
2509
        imul    ecx, 13
2510
        add     esi, ecx
2511
        stosb
2512
        mov     cl, 5
2513
        call    fs_RamdiskRewrite.read_symbols
2514
        mov     ax, 0xF
2515
        stosw
2516
        mov     al, [esp+4]
2517
        stosb
2518
        mov     cl, 6
2519
        call    fs_RamdiskRewrite.read_symbols
2520
        xor     eax, eax
2521
        stosw
2522
        mov     cl, 2
2523
        call    fs_RamdiskRewrite.read_symbols
2524
        pop     ecx
2525
        lea     eax, [esp+8+8+12+8]
2526
        call    dword [eax+12]         ; next write
2527
        xor     eax, eax
2528
        loop    .writelfn
2529
        pop     eax
2530
        pop     esi
2531
;        lea     eax, [esp+8+12+8]
2532
;        call    dword [eax+16]          ; end write
2533
.nolfn:
2534
        xchg    esi, [esp]
2535
        mov     ecx, 11
2536
        rep     movsb
2537
        mov     word [edi], 20h         ; attributes
2538
        sub     edi, 11
2539
        pop     esi ecx
2540
        add     esp, 12
2541
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
2542
        call    get_time_for_file
2543
        mov     [edi+14], ax            ; creation time
2544
        mov     [edi+22], ax            ; last write time
2545
        call    get_date_for_file
2546
        mov     [edi+16], ax            ; creation date
2547
        mov     [edi+24], ax            ; last write date
2548
        mov     [edi+18], ax            ; last access date
2549
        xor     ecx, ecx
2550
        mov     word [edi+20], cx       ; high word of cluster
2551
        mov     word [edi+26], cx       ; low word of cluster - to be filled
2552
        mov     dword [edi+28], ecx     ; file size - to be filled
321 diamond 2553
        cmp     byte [esp+32+28], cl
2554
        jz      .doit
2555
; create directory
2556
        mov     byte [edi+11], 10h      ; attributes: folder
2557
        mov     edx, edi
2558
        lea     eax, [esp+8]
2559
        call    dword [eax+16]  ; flush directory
2560
        push    ecx
2561
        mov     ecx, [SECTORS_PER_CLUSTER]
2562
        shl     ecx, 9
2563
        jmp     .doit2
83 diamond 2564
.doit:
2565
        lea     eax, [esp+8]
2566
        call    dword [eax+16]  ; flush directory
2567
        push    ecx
2568
        mov     ecx, [esp+4+32+24]
321 diamond 2569
.doit2:
83 diamond 2570
        push    ecx
2571
        push    edi
2572
        mov     esi, edx
2573
        test    ecx, ecx
2574
        jz      .done
2575
        mov     eax, 2
2576
        call    get_free_FAT
2577
        jc      .diskfull
2578
        push    eax
2579
        mov     [edi+26], ax
2580
        shr     eax, 16
2581
        mov     [edi+20], ax
2582
        lea     eax, [esp+16+8]
2583
        call    dword [eax+16]  ; flush directory
2584
        pop     eax
2585
        push    edx
2586
        mov     edx, [fatEND]
2587
        call    set_FAT
2588
        pop     edx
2589
.write_cluster:
2590
        push    eax
2591
        dec     eax
2592
        dec     eax
2593
        mov     ebp, [SECTORS_PER_CLUSTER]
2594
        imul    eax, ebp
2595
        add     eax, [DATA_START]
2596
; write data
2597
.write_sector:
321 diamond 2598
        cmp     byte [esp+16+32+28], 0
2599
        jnz     .writedir
83 diamond 2600
        mov     ecx, 512
2601
        cmp     dword [esp+8], ecx
2602
        jb      .writeshort
2603
; we can write directly from given buffer
2604
        mov     ebx, esi
2605
        add     esi, ecx
2606
        jmp     .writecommon
2607
.writeshort:
2608
        mov     ecx, [esp+8]
2609
        push    ecx
2610
        mov     edi, buffer
2611
        mov     ebx, edi
2612
        rep     movsb
321 diamond 2613
.writedircont:
83 diamond 2614
        mov     ecx, buffer+0x200
2615
        sub     ecx, edi
2616
        push    eax
2617
        xor     eax, eax
2618
        rep     stosb
2619
        pop     eax
2620
        pop     ecx
2621
.writecommon:
2622
        call    hd_write
2623
        cmp     [hd_error], 0
2624
        jnz     .writeerr
2625
        inc     eax
2626
        sub     dword [esp+8], ecx
2627
        jz      .writedone
2628
        dec     ebp
2629
        jnz     .write_sector
2630
; allocate new cluster
2631
        pop     eax
2632
        mov     ecx, eax
2633
        call    get_free_FAT
2634
        jc      .diskfull
2635
        push    edx
2636
        mov     edx, [fatEND]
2637
        call    set_FAT
2638
        xchg    eax, ecx
2639
        mov     edx, ecx
2640
        call    set_FAT
2641
        pop     edx
2642
        xchg    eax, ecx
2643
        jmp     .write_cluster
2644
.diskfull:
2645
        mov     eax, ERROR_DISK_FULL
2646
        jmp     .ret
2647
.writeerr:
2648
        pop     eax
2649
        sub     esi, ecx
2650
        mov     eax, 11
2651
        jmp     .ret
2652
.writedone:
2653
        pop     eax
2654
.done:
2655
        xor     eax, eax
2656
.ret:
2657
        pop     edi ecx
2658
        mov     ebx, esi
2659
        sub     ebx, edx
2660
        pop     ebp
2661
        mov     [esp+32+28], eax
2662
        lea     eax, [esp+8]
2663
        call    dword [eax+8]
2664
        mov     [edi+28], ebx
2665
        call    dword [eax+16]
2666
        mov     [esp+32+16], ebx
2667
        lea     eax, [ebx+511]
2668
        shr     eax, 9
2669
        mov     ecx, [SECTORS_PER_CLUSTER]
2670
        lea     eax, [eax+ecx-1]
2671
        xor     edx, edx
2672
        div     ecx
2673
        mov     ecx, ebp
2674
        sub     ecx, eax
2675
        call    add_disk_free_space
2676
        add     esp, 32
2677
        call    update_disk
2678
        popad
2679
        ret
321 diamond 2680
.writedir:
2681
        push    512
2682
        mov     edi, buffer
2683
        mov     ebx, edi
2684
        mov     ecx, [SECTORS_PER_CLUSTER]
2685
        shl     ecx, 9
2686
        cmp     ecx, [esp+12]
2687
        jnz     .writedircont
2688
        dec     dword [esp+16]
2689
        push    esi
2690
        mov     ecx, 32/4
2691
        rep     movsd
2692
        pop     esi
2693
        mov     dword [edi-32], '.   '
2694
        mov     dword [edi-32+4], '    '
2695
        mov     dword [edi-32+8], '    '
2696
        mov     byte [edi-32+11], 10h
2697
        push    esi
2698
        mov     ecx, 32/4
2699
        rep     movsd
2700
        pop     esi
2701
        mov     dword [edi-32], '..  '
2702
        mov     dword [edi-32+4], '    '
2703
        mov     dword [edi-32+8], '    '
2704
        mov     byte [edi-32+11], 10h
2705
        mov     ecx, [esp+20+8]
2706
        cmp     ecx, [ROOT_CLUSTER]
2707
        jnz     @f
2708
        xor     ecx, ecx
2709
@@:
2710
        mov     word [edi-32+26], cx
2711
        shr     ecx, 16
2712
        mov     [edi-32+20], cx
2713
        jmp     .writedircont
83 diamond 2714
 
131 diamond 2715
;----------------------------------------------------------------
2716
;
256 diamond 2717
;  fs_HdWrite - LFN variant for writing to hard disk
131 diamond 2718
;
2719
;  esi  points to filename
2720
;  ebx  pointer to 64-bit number = first wanted byte, 0+
2721
;       may be ebx=0 - start from first byte
2722
;  ecx  number of bytes to write, 0+
2723
;  edx  mem location to data
2724
;
2725
;  ret ebx = bytes written (maybe 0)
2726
;      eax = 0 ok write or other = errormsg
2727
;
2728
;--------------------------------------------------------------
2729
fs_HdWrite.access_denied:
2730
        push    ERROR_ACCESS_DENIED
2731
fs_HdWrite.ret0:
2732
        pop     eax
2733
        xor     ebx, ebx
2734
        ret
2735
 
2736
fs_HdWrite.ret11:
2737
        push    11
2738
        jmp     fs_HdWrite.ret0
2739
 
2740
fs_HdWrite:
256 diamond 2741
        cmp     [fs_type], 1
2742
        jz      ntfs_HdWrite
2743
        cmp     [fs_type], 16
2744
        jz      @f
2745
        cmp     [fs_type], 32
2746
        jz      @f
131 diamond 2747
        push    ERROR_UNKNOWN_FS
2748
        jmp     .ret0
2749
@@:
2750
        cmp     byte [esi], 0
2751
        jz      .access_denied
2752
        pushad
2753
        call    hd_find_lfn
2754
        pushfd
2755
        cmp     [hd_error], 0
2756
        jz      @f
2757
        popfd
2758
        popad
2759
        push    11
2760
        jmp     .ret0
2761
@@:
2762
        popfd
2763
        jnc     .found
2764
        popad
2765
        push    ERROR_FILE_NOT_FOUND
2766
        jmp     .ret0
2767
.found:
2768
; FAT does not support files larger than 4GB
2769
        test    ebx, ebx
2770
        jz      .l1
2771
        cmp     dword [ebx+4], 0
2772
        jz      @f
2773
.eof:
2774
        popad
2775
        push    ERROR_END_OF_FILE
2776
        jmp     .ret0
2777
@@:
2778
        mov     ebx, [ebx]
2779
.l1:
2780
; now edi points to direntry, ebx=start byte to write,
2781
; ecx=number of bytes to write, edx=data pointer
2782
 
2783
; extend file if needed
2784
        add     ecx, ebx
2785
        jc      .eof    ; FAT does not support files larger than 4GB
2786
        push    eax     ; save directory sector
2787
        push    0       ; return value=0
2788
 
2789
        call    get_time_for_file
2790
        mov     [edi+22], ax            ; last write time
2791
        call    get_date_for_file
2792
        mov     [edi+24], ax            ; last write date
2793
        mov     [edi+18], ax            ; last access date
2794
 
2795
        push    dword [edi+28]          ; save current file size
2796
        cmp     ecx, [edi+28]
2797
        jbe     .length_ok
2798
        cmp     ecx, ebx
2799
        jz      .length_ok
2800
        call    hd_extend_file
2801
        jnc     .length_ok
2802
        mov     [esp+4], eax
2803
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
2804
; First two cases are fatal errors, in third case we may write some data
2805
        cmp     al, ERROR_DISK_FULL
2806
        jz      .disk_full
2807
        pop     eax
2808
        pop     eax
2809
        mov     [esp+4+28], eax
2810
        pop     eax
2811
        popad
2812
        xor     ebx, ebx
2813
        ret
2814
.disk_full:
2815
; correct number of bytes to write
2816
        mov     ecx, [edi+28]
2817
        cmp     ecx, ebx
2818
        ja      .length_ok
2819
.ret:
2820
        call    update_disk
2821
        cmp     [hd_error], 0
2822
        jz      @f
2823
        mov     byte [esp+4], 11
2824
@@:
2825
        pop     eax
2826
        pop     eax
2827
        mov     [esp+4+28], eax ; eax=return value
2828
        pop     eax
2829
        sub     edx, [esp+20]
2830
        mov     [esp+16], edx   ; ebx=number of written bytes
2831
        popad
2832
        ret
2833
.length_ok:
2834
        mov     esi, [edi+28]
2835
        mov     eax, [edi+20-2]
2836
        mov     ax, [edi+26]
2837
        mov     edi, eax        ; edi=current cluster
2838
        xor     ebp, ebp        ; ebp=current sector in cluster
2839
; save directory
2840
        mov     eax, [esp+8]
2841
        push    ebx
2842
        mov     ebx, buffer
2843
        call    hd_write
2844
        pop     ebx
2845
        cmp     [hd_error], 0
2846
        jz      @f
2847
.device_err:
2848
        mov     byte [esp+4], 11
2849
        jmp     .ret
2850
@@:
2851
 
2852
; now ebx=start pos, ecx=end pos, both lie inside file
2853
        sub     ecx, ebx
2854
        jz      .ret
2855
.write_loop:
321 diamond 2856
; skip unmodified sectors
2857
        cmp     dword [esp], 0x200
2858
        jb      .modify
2859
        sub     ebx, 0x200
2860
        jae     .skip
2861
        add     ebx, 0x200
2862
.modify:
131 diamond 2863
; get length of data in current sector
2864
        push    ecx
2865
        sub     ebx, 0x200
2866
        jb      .hasdata
2867
        neg     ebx
2868
        xor     ecx, ecx
2869
        jmp     @f
2870
.hasdata:
2871
        neg     ebx
2872
        cmp     ecx, ebx
2873
        jbe     @f
2874
        mov     ecx, ebx
2875
@@:
2876
; get current sector number
2877
        mov     eax, edi
2878
        dec     eax
2879
        dec     eax
2880
        imul    eax, [SECTORS_PER_CLUSTER]
2881
        add     eax, [DATA_START]
2882
        add     eax, ebp
2883
; load sector if needed
2884
        cmp     dword [esp+4], 0        ; we don't need to read uninitialized data
2885
        jz      .noread
2886
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
2887
        jz      .noread
2888
        cmp     ecx, esi        ; (same for the last sector)
2889
        jz      .noread
2890
        push    ebx
2891
        mov     ebx, buffer
2892
        call    hd_read
2893
        pop     ebx
2894
        cmp     [hd_error], 0
2895
        jz      @f
2896
.device_err2:
2897
        pop     ecx
2898
        jmp     .device_err
2899
@@:
2900
.noread:
2901
; zero uninitialized data if file was extended (because hd_extend_file does not this)
2902
        push    eax ecx edi
2903
        xor     eax, eax
2904
        mov     ecx, 0x200
2905
        sub     ecx, [esp+4+12]
2906
        jbe     @f
2907
        mov     edi, buffer
2908
        add     edi, [esp+4+12]
2909
        rep     stosb
2910
@@:
2911
; zero uninitialized data in the last sector
2912
        mov     ecx, 0x200
2913
        sub     ecx, esi
2914
        jbe     @f
2915
        mov     edi, buffer
2916
        add     edi, esi
2917
        rep     stosb
2918
@@:
321 diamond 2919
        pop     edi ecx
131 diamond 2920
; copy new data
2921
        mov     eax, edx
2922
        neg     ebx
2923
        jecxz   @f
2924
        add     ebx, buffer+0x200
2925
        call    memmove
2926
        xor     ebx, ebx
2927
@@:
2928
        pop     eax
2929
; save sector
2930
        push    ebx
2931
        mov     ebx, buffer
2932
        call    hd_write
2933
        pop     ebx
2934
        cmp     [hd_error], 0
2935
        jnz     .device_err2
2936
        add     edx, ecx
2937
        sub     [esp], ecx
2938
        pop     ecx
2939
        jz      .ret
321 diamond 2940
.skip:
131 diamond 2941
; next sector
2942
        inc     ebp
2943
        cmp     ebp, [SECTORS_PER_CLUSTER]
2944
        jb      @f
2945
        xor     ebp, ebp
2946
        mov     eax, edi
2947
        call    get_FAT
2948
        mov     edi, eax
2949
        cmp     [hd_error], 0
2950
        jnz     .device_err
2951
@@:
2952
        sub     esi, 0x200
2953
        jae     @f
2954
        xor     esi, esi
2955
@@:
2956
        sub     dword [esp], 0x200
2957
        jae     @f
2958
        and     dword [esp], 0
2959
@@:     jmp     .write_loop
2960
 
2961
hd_extend_file.zero_size:
2962
        xor     eax, eax
2963
        jmp     hd_extend_file.start_extend
2964
 
2965
; extends file on hd to given size (new data area is undefined)
2966
; in: edi->direntry, ecx=new size
133 diamond 2967
; out: CF=0 => OK, eax=0
131 diamond 2968
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11)
2969
hd_extend_file:
2970
        push    ebp
2971
        mov     ebp, [SECTORS_PER_CLUSTER]
2972
        imul    ebp, [BYTES_PER_SECTOR]
2973
        push    ecx
2974
; find the last cluster of file
2975
        mov     eax, [edi+20-2]
2976
        mov     ax, [edi+26]
2977
        mov     ecx, [edi+28]
2978
        jecxz   .zero_size
2979
.last_loop:
2980
        sub     ecx, ebp
2981
        jbe     .last_found
2982
        call    get_FAT
2983
        cmp     [hd_error], 0
2984
        jz      @f
2985
.device_err:
2986
        pop     ecx
2987
.device_err2:
2988
        pop     ebp
2989
        push    11
2990
.ret_err:
2991
        pop     eax
2992
        stc
2993
        ret
2994
@@:
2995
        cmp     eax, 2
2996
        jb      .fat_err
2997
        cmp     eax, [fatRESERVED]
2998
        jb      .last_loop
2999
.fat_err:
3000
        pop     ecx ebp
3001
        push    ERROR_FAT_TABLE
3002
        jmp     .ret_err
3003
.last_found:
3004
        push    eax
3005
        call    get_FAT
3006
        cmp     [hd_error], 0
3007
        jz      @f
3008
        pop     eax
3009
        jmp     .device_err
3010
@@:
3011
        cmp     eax, [fatRESERVED]
3012
        pop     eax
3013
        jb      .fat_err
3014
; set length to full number of clusters
3015
        sub     [edi+28], ecx
3016
.start_extend:
3017
        pop     ecx
3018
; now do extend
3019
        push    edx
3020
        mov     edx, 2          ; start scan from cluster 2
3021
.extend_loop:
3022
        cmp     [edi+28], ecx
3023
        jae     .extend_done
3024
; add new cluster
3025
        push    eax
3026
        mov     eax, edx
3027
        call    get_free_FAT
3028
        jc      .disk_full
3029
        mov     edx, [fatEND]
3030
        call    set_FAT
3031
        mov     edx, eax
3032
        pop     eax
3033
        test    eax, eax
3034
        jz      .first_cluster
3035
        push    edx
3036
        call    set_FAT
3037
        pop     edx
3038
        jmp     @f
3039
.first_cluster:
3040
        ror     edx, 16
3041
        mov     [edi+20], dx
3042
        ror     edx, 16
3043
        mov     [edi+26], dx
3044
@@:
133 diamond 3045
        push    ecx
3046
        mov     ecx, -1
3047
        call    add_disk_free_space
3048
        pop     ecx
131 diamond 3049
        mov     eax, edx
3050
        cmp     [hd_error], 0
3051
        jnz     .device_err3
3052
        add     [edi+28], ebp
3053
        jmp     .extend_loop
3054
.extend_done:
3055
        mov     [edi+28], ecx
3056
        pop     edx ebp
133 diamond 3057
        xor     eax, eax        ; CF=0
131 diamond 3058
        ret
3059
.device_err3:
3060
        pop     edx
3061
        jmp     .device_err2
3062
.disk_full:
3063
        pop     eax edx ebp
3064
        push    ERROR_DISK_FULL
3065
        pop     eax
3066
        cmp     [hd_error], 0
3067
        jz      @f
3068
        mov     al, 11
3069
@@:     stc
3070
        ret
3071
 
133 diamond 3072
;----------------------------------------------------------------
3073
;
3074
;  fs_HdSetFileEnd - set end of file on hard disk
3075
;
3076
;  esi  points to filename
3077
;  ebx  points to 64-bit number = new file size
3078
;  ecx  ignored (reserved)
3079
;  edx  ignored (reserved)
3080
;
3081
;  ret eax = 0 ok or other = errormsg
3082
;
3083
;--------------------------------------------------------------
3084
fs_HdSetFileEnd:
256 diamond 3085
        cmp     [fs_type], 1
3086
        jz      ntfs_HdSetFileEnd
3087
        cmp     [fs_type], 16
3088
        jz      @f
3089
        cmp     [fs_type], 32
3090
        jz      @f
133 diamond 3091
        push    ERROR_UNKNOWN_FS
3092
.ret:
3093
        pop     eax
3094
        ret
3095
@@:
3096
        cmp     byte [esi], 0
3097
        jnz     @f
3098
.access_denied:
3099
        push    ERROR_ACCESS_DENIED
3100
        jmp     .ret
3101
@@:
3102
        push    edi
3103
        call    hd_find_lfn
3104
        pushfd
3105
        cmp     [hd_error], 0
3106
        jz      @f
3107
        popfd
3108
        push    11
3109
        jmp     .ret
3110
@@:
3111
        popfd
3112
        jnc     @f
3113
        pop     edi
3114
        push    ERROR_FILE_NOT_FOUND
3115
        jmp     .ret
3116
@@:
3117
; must not be directory
3118
        test    byte [edi+11], 10h
3119
        jz      @f
3120
        pop     edi
3121
        jmp     .access_denied
3122
@@:
3123
; file size must not exceed 4 Gb
3124
        cmp     dword [ebx+4], 0
3125
        jz      @f
3126
        pop     edi
3127
        push    ERROR_END_OF_FILE
3128
        jmp     .ret
3129
@@:
3130
        push    eax     ; save directory sector
3131
; set file modification date/time to current
3132
        call    fat_update_datetime
3133
        mov     eax, [ebx]
3134
        cmp     eax, [edi+28]
3135
        jb      .truncate
3136
        ja      .expand
3137
        pop     eax
3138
        mov     ebx, buffer
3139
        call    hd_write
3140
        pop     edi
3141
        xor     eax, eax
3142
        cmp     [hd_error], 0
3143
        jz      @f
3144
        mov     al, 11
3145
@@:
3146
        ret
3147
.expand:
3148
        push    ebx ebp ecx
3149
        push    dword [edi+28]  ; save old size
3150
        mov     ecx, eax
3151
        call    hd_extend_file
3152
        push    eax             ; return code
3153
        jnc     .expand_ok
3154
        cmp     al, ERROR_DISK_FULL
3155
        jz      .disk_full
3156
.pop_ret:
3157
        call    update_disk
3158
        pop     eax ecx ebp ebx ecx edi edi
3159
        ret
3160
.expand_ok:
3161
.disk_full:
3162
; save directory
3163
        mov     eax, [edi+28]
3164
        xchg    eax, [esp+20]
3165
        mov     ebx, buffer
3166
        call    hd_write
3167
        mov     eax, [edi+20-2]
3168
        mov     ax, [edi+26]
3169
        mov     edi, eax
3170
        cmp     [hd_error], 0
3171
        jz      @f
3172
.pop_ret11:
3173
        mov     byte [esp], 11
3174
        jmp     .pop_ret
3175
@@:
3176
; now zero new data
3177
        xor     ebp, ebp
3178
; edi=current cluster, ebp=sector in cluster
3179
; [esp+20]=new size, [esp+4]=old size, [esp]=return code
3180
.zero_loop:
3181
        sub     dword [esp+4], 0x200
3182
        jae     .next_cluster
3183
        lea     eax, [edi-2]
3184
        imul    eax, [SECTORS_PER_CLUSTER]
3185
        add     eax, [DATA_START]
3186
        add     eax, ebp
3187
        cmp     dword [esp+4], -0x200
3188
        jz      .noread
3189
        mov     ebx, buffer
3190
        call    hd_read
3191
        cmp     [hd_error], 0
3192
        jnz     .err_next
3193
.noread:
3194
        mov     ecx, [esp+4]
3195
        neg     ecx
3196
        push    edi
3197
        mov     edi, buffer+0x200
3198
        add     edi, [esp+8]
3199
        push    eax
3200
        xor     eax, eax
3201
        mov     [esp+12], eax
3202
        rep     stosb
3203
        pop     eax
3204
        pop     edi
3205
        call    hd_write
3206
        cmp     [hd_error], 0
3207
        jz      .next_cluster
3208
.err_next:
3209
        mov     byte [esp], 11
3210
.next_cluster:
3211
        sub     dword [esp+20], 0x200
3212
        jbe     .pop_ret
3213
        inc     ebp
3214
        cmp     ebp, [SECTORS_PER_CLUSTER]
3215
        jb      .zero_loop
3216
        xor     ebp, ebp
3217
        mov     eax, edi
3218
        call    get_FAT
3219
        mov     edi, eax
3220
        cmp     [hd_error], 0
3221
        jnz     .pop_ret11
3222
        jmp     .zero_loop
3223
.truncate:
3224
        mov     [edi+28], eax
3225
        push    ecx
3226
        mov     ecx, [edi+20-2]
3227
        mov     cx, [edi+26]
3228
        push    eax
3229
        test    eax, eax
3230
        jz      .zero_size
3231
; find new last cluster
3232
@@:
3233
        mov     eax, [SECTORS_PER_CLUSTER]
3234
        shl     eax, 9
3235
        sub     [esp], eax
3236
        jbe     @f
3237
        mov     eax, ecx
3238
        call    get_FAT
3239
        mov     ecx, eax
3240
        cmp     [hd_error], 0
3241
        jz      @b
3242
.device_err3:
3243
        pop     eax ecx eax edi
3244
        push    11
3245
        pop     eax
3246
        ret
3247
@@:
3248
; we will zero data at the end of last sector - remember it
3249
        push    ecx
3250
; terminate FAT chain
3251
        push    edx
3252
        mov     eax, ecx
3253
        mov     edx, [fatEND]
3254
        call    set_FAT
3255
        mov     eax, edx
3256
        pop     edx
3257
        cmp     [hd_error], 0
3258
        jz      @f
3259
.device_err4:
3260
        pop     ecx
3261
        jmp     .device_err3
3262
.zero_size:
3263
        and     word [edi+20], 0
3264
        and     word [edi+26], 0
3265
        push    0
3266
        mov     eax, ecx
3267
@@:
3268
; delete FAT chain
3269
        call    clear_cluster_chain
3270
        cmp     [hd_error], 0
3271
        jnz     .device_err4
3272
; save directory
3273
        mov     eax, [esp+12]
3274
        push    ebx
3275
        mov     ebx, buffer
3276
        call    hd_write
3277
        pop     ebx
3278
        cmp     [hd_error], 0
3279
        jnz     .device_err4
3280
; zero last sector, ignore errors
3281
        pop     ecx
3282
        pop     eax
3283
        dec     ecx
3284
        imul    ecx, [SECTORS_PER_CLUSTER]
3285
        add     ecx, [DATA_START]
3286
        push    eax
3287
        sar     eax, 9
3288
        add     ecx, eax
3289
        pop     eax
3290
        and     eax, 0x1FF
3291
        jz      .truncate_done
3292
        push    ebx eax
3293
        mov     eax, ecx
3294
        mov     ebx, buffer
3295
        call    hd_read
3296
        pop     eax
3297
        lea     edi, [buffer+eax]
3298
        push    ecx
3299
        mov     ecx, 0x200
3300
        sub     ecx, eax
3301
        xor     eax, eax
3302
        rep     stosb
3303
        pop     eax
3304
        call    hd_write
3305
        pop     ebx
3306
.truncate_done:
3307
        pop     ecx eax edi
3308
        call    update_disk
3309
        xor     eax, eax
3310
        cmp     [hd_error], 0
3311
        jz      @f
3312
        mov     al, 11
3313
@@:
3314
        ret
3315
 
86 diamond 3316
fs_HdGetFileInfo:
256 diamond 3317
        cmp     [fs_type], 1
3318
        jz      ntfs_HdGetFileInfo
3319
        cmp     [fs_type], 16
3320
        jz      @f
3321
        cmp     [fs_type], 32
3322
        jz      @f
86 diamond 3323
        mov     eax, ERROR_UNKNOWN_FS
3324
        ret
3325
@@:
3326
        cmp     byte [esi], 0
3327
        jnz     @f
3328
        mov     eax, 2
3329
        ret
3330
@@:
3331
        push    edi
3332
        call    hd_find_lfn
3333
        pushfd
3334
        cmp     [hd_error], 0
3335
        jz      @f
3336
        popfd
3337
        pop     edi
3338
        mov     eax, 11
3339
        ret
3340
@@:
3341
        popfd
3342
        jmp     fs_GetFileInfo_finish
3343
 
3344
fs_HdSetFileInfo:
256 diamond 3345
        cmp     [fs_type], 1
3346
        jz      ntfs_HdSetFileInfo
3347
        cmp     [fs_type], 16
3348
        jz      @f
3349
        cmp     [fs_type], 32
3350
        jz      @f
86 diamond 3351
        mov     eax, ERROR_UNKNOWN_FS
3352
        ret
3353
@@:
3354
        cmp     byte [esi], 0
3355
        jnz     @f
3356
        mov     eax, 2
3357
        ret
3358
@@:
3359
        push    edi
3360
        call    hd_find_lfn
3361
        pushfd
3362
        cmp     [hd_error], 0
3363
        jz      @f
3364
        popfd
3365
        pop     edi
3366
        mov     eax, 11
3367
        ret
3368
@@:
3369
        popfd
3370
        jnc     @f
3371
        pop     edi
3372
        mov     eax, ERROR_FILE_NOT_FOUND
3373
        ret
3374
@@:
3375
        push    eax
3376
        call    bdfe_to_fat_entry
3377
        pop     eax
3378
        mov     ebx, buffer
3379
        call    hd_write
3380
        call    update_disk
3381
        pop     edi
3382
        xor     eax, eax
3383
        ret
3384
 
256 diamond 3385
if 0    ; starting from revision 237 execute is implemented in taskman.inc
3386
        ; through fs_XxxGetFileInfo and fs_XxxRead
91 diamond 3387
;----------------------------------------------------------------
3388
;
3389
;  fs_HdExecute - LFN variant for executing from harddisk
3390
;
3391
;  esi  points to hd filename (e.g. 'dir1/name')
3392
;  ebp  points to full filename (e.g. '/hd0/1/dir1/name')
3393
;  dword [ebx] = flags
3394
;  dword [ebx+4] = cmdline
3395
;
3396
;  ret ebx,edx destroyed
3397
;      eax > 0 - PID, < 0 - error
3398
;
3399
;--------------------------------------------------------------
3400
fs_HdExecute:
3401
        mov     edx, [ebx]
3402
        mov     ebx, [ebx+4]
3403
        test    ebx, ebx
3404
        jz      @f
3405
        add     ebx, std_application_base_address
3406
@@:
3407
 
3408
;----------------------------------------------------------------
3409
;
3410
; fs_HdExecute.flags - second entry
3411
;
3412
;  esi  points to floppy filename (kernel address)
3413
;  ebp  points to full filename
3414
;  edx  flags
3415
;  ebx  cmdline (kernel address)
3416
;
3417
;  ret  eax > 0 - PID, < 0 - error
3418
;
3419
;--------------------------------------------------------------
3420
 
3421
.flags:
3422
        cmp     [fat_type], 0
3423
        jnz     @f
171 diamond 3424
        mov     eax, -ERROR_UNKNOWN_FS
91 diamond 3425
        ret
3426
@@:
3427
        cmp     byte [esi], 0
3428
        jnz     @f
3429
; cannot execute root!
3430
        mov     eax, -ERROR_ACCESS_DENIED
3431
        ret
3432
@@:
3433
        push    edi
3434
        call    hd_find_lfn
3435
        jnc     .found
3436
        pop     edi
3437
        mov     eax, -ERROR_FILE_NOT_FOUND
3438
        cmp     [hd_error], 0
3439
        jz      @f
3440
        mov     al, -11
3441
@@:
3442
        ret
3443
.found:
3444
        mov     eax, [edi+20-2]
3445
        mov     ax, [edi+26]
3446
        push    0
3447
        push    eax
3448
        push    dword [edi+28]          ; size
3449
        push    .DoRead
3450
        call    fs_execute
3451
        add     esp, 16
3452
        pop     edi
3453
        ret
3454
 
3455
.DoRead:
3456
; read next block
3457
; in: eax->parameters, edi->buffer
3458
; out: eax = error code
3459
        pushad
3460
        cmp     dword [eax], 0  ; file size
3461
        jz      .eof
3462
        add     eax, 4
3463
        call    fat_get_sector
3464
        mov     ebx, edi
3465
        call    hd_read
3466
        cmp     [hd_error], 0
3467
        jnz     .err
3468
        mov     eax, [esp+28]
3469
        mov     ecx, [eax]
3470
        sub     ecx, 512
3471
        jae     @f
3472
        lea     edi, [edi+ecx+512]
3473
        neg     ecx
3474
        push    eax
3475
        xor     eax, eax
3476
        rep     stosb
3477
        pop     eax
3478
@@:
3479
        mov     [eax], ecx
3480
        mov     edx, [eax+8]
3481
        inc     edx
3482
        cmp     edx, [SECTORS_PER_CLUSTER]
3483
        jb      @f
3484
        push    eax
3485
        mov     eax, [eax+4]
3486
        call    get_FAT
3487
        cmp     [hd_error], 0
3488
        jnz     .err
3489
        mov     ecx, eax
3490
        pop     eax
3491
        mov     [eax+4], ecx
3492
        xor     edx, edx
3493
@@:
3494
        mov     [eax+8], edx
3495
        popad
3496
        xor     eax, eax
3497
        ret
3498
.eof:
3499
        popad
3500
        mov     eax, 6
3501
        ret
3502
.err:
3503
        popad
3504
        mov     eax, 11
3505
        ret
256 diamond 3506
end if
91 diamond 3507
 
171 diamond 3508
;----------------------------------------------------------------
3509
;
3510
;  fs_HdDelete - delete file or empty folder from hard disk
3511
;
3512
;  esi  points to filename
3513
;
3514
;  ret  eax = 0 ok or other = errormsg
3515
;
3516
;--------------------------------------------------------------
3517
fs_HdDelete:
256 diamond 3518
        cmp     [fs_type], 1
3519
        jz      ntfs_HdDelete
3520
        cmp     [fs_type], 16
3521
        jz      @f
3522
        cmp     [fs_type], 32
3523
        jz      @f
171 diamond 3524
        push    ERROR_UNKNOWN_FS
3525
.pop_ret:
3526
        pop     eax
3527
        ret
3528
@@:
3529
        cmp     byte [esi], 0
3530
        jnz     @f
3531
; cannot delete root!
3532
.access_denied:
3533
        push    ERROR_ACCESS_DENIED
3534
        jmp     .pop_ret
3535
@@:
3536
        and     [longname_sec1], 0
3537
        and     [longname_sec2], 0
3538
        push    edi
3539
        call    hd_find_lfn
3540
        jnc     .found
3541
        pop     edi
3542
        push    ERROR_FILE_NOT_FOUND
3543
        jmp     .pop_ret
3544
.found:
3545
        cmp     dword [edi], '.   '
3546
        jz      .access_denied2
3547
        cmp     dword [edi], '..  '
3548
        jz      .access_denied2
3549
        test    byte [edi+11], 10h
3550
        jz      .dodel
3551
; we can delete only empty folders!
3552
        pushad
3553
        mov     ebp, [edi+20-2]
3554
        mov     bp, [edi+26]
3555
        xor     ecx, ecx
3556
        lea     eax, [ebp-2]
3557
        imul    eax, [SECTORS_PER_CLUSTER]
3558
        add     eax, [DATA_START]
3559
        mov     ebx, buffer
3560
        call    hd_read
3561
        cmp     [hd_error], 0
3562
        jnz     .err1
3563
        add     ebx, 2*0x20
3564
.checkempty:
3565
        cmp     byte [ebx], 0
3566
        jz      .empty
3567
        cmp     byte [ebx], 0xE5
3568
        jnz     .notempty
3569
        add     ebx, 0x20
3570
        cmp     ebx, buffer+0x200
3571
        jb      .checkempty
3572
        inc     ecx
3573
        cmp     ecx, [SECTORS_PER_CLUSTER]
3574
        jb      @f
3575
        mov     eax, ebp
3576
        call    get_FAT
3577
        cmp     [hd_error], 0
3578
        jnz     .err1
3579
        mov     ebp, eax
3580
        xor     ecx, ecx
3581
@@:
3582
        lea     eax, [ebp-2]
3583
        imul    eax, [SECTORS_PER_CLUSTER]
3584
        add     eax, [DATA_START]
3585
        add     eax, ecx
3586
        mov     ebx, buffer
3587
        call    hd_read
3588
        cmp     [hd_error], 0
3589
        jz      .checkempty
3590
.err1:
3591
        popad
3592
.err2:
3593
        pop     edi
3594
        push    11
3595
        pop     eax
3596
        ret
3597
.notempty:
3598
        popad
3599
.access_denied2:
3600
        pop     edi
3601
        push    ERROR_ACCESS_DENIED
3602
        pop     eax
3603
        ret
3604
.empty:
3605
        popad
3606
        push    ebx
3607
        mov     ebx, buffer
3608
        call    hd_read
3609
        pop     ebx
3610
        cmp     [hd_error], 0
3611
        jnz     .err2
3612
.dodel:
3613
        push    eax
3614
        mov     eax, [edi+20-2]
3615
        mov     ax, [edi+26]
3616
        xchg    eax, [esp]
3617
; delete folder entry
3618
        mov     byte [edi], 0xE5
3619
; delete LFN (if present)
3620
.lfndel:
3621
        cmp     edi, buffer
3622
        ja      @f
3623
        cmp     [longname_sec2], 0
3624
        jz      .lfndone
3625
        push    [longname_sec2]
3626
        push    [longname_sec1]
3627
        pop     [longname_sec2]
3628
        and     [longname_sec1], 0
3629
        push    ebx
3630
        mov     ebx, buffer
3631
        call    hd_write
3632
        mov     eax, [esp+4]
3633
        call    hd_read
3634
        pop     ebx
3635
        pop     eax
3636
        mov     edi, buffer+0x200
3637
@@:
3638
        sub     edi, 0x20
3639
        cmp     byte [edi], 0xE5
3640
        jz      .lfndone
3641
        cmp     byte [edi+11], 0xF
3642
        jnz     .lfndone
3643
        mov     byte [edi], 0xE5
3644
        jmp     .lfndel
3645
.lfndone:
3646
        push    ebx
3647
        mov     ebx, buffer
3648
        call    hd_write
3649
        pop     ebx
3650
; delete FAT chain
3651
        pop     eax
3652
        call    clear_cluster_chain
3653
        call    update_disk
3654
        pop     edi
3655
        xor     eax, eax
3656
        cmp     [hd_error], 0
3657
        jz      @f
3658
        mov     al, 11
3659
@@:
3660
        ret
3661
 
74 mario79 3662
; \end{diamond}