Subversion Repositories Kolibri OS

Rev

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