Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 494 → Rev 495

/kernel/trunk/fs/fat32.inc
1,5 → 1,5
$Revision$
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
69,7 → 69,6
 
uglobal
align 4
cluster dd 0 ; used by file_write,makedir,append
partition_count dd 0 ; partitions found by set_FAT32_variables
longname_sec1 dd 0 ; used by analyze_directory to save 2 previous
longname_sec2 dd 0 ; directory sectors for delete long filename
83,13 → 82,6
 
file_size dd 0 ; used by file_read
 
sector_tmp dd 0 ; used by rename,append,file_write
entry_pos dd 0 ; used by rename,append,file_write
 
old_filesize dd 0 ; used by append
new_filepos dd 0 ; used by append
bytes2write dd 0 ; used by append
 
cache_search_start dd 0 ; used by find_empty_slot
endg
 
106,13 → 98,8
endg
 
uglobal
dir_entry: times 32 db 0
 
startpath: times 255 db 0
 
fat16_root db 0 ; flag for fat16 rootdir
fat_change db 0 ; 1=fat has changed
 
endg
 
reserve_hd1:
470,131 → 457,6
ret
 
 
analyze_directory_to_write:
;-----------------------------------------------------------
; input : EAX = first cluster of the directory
; output : IF CARRY=0 EAX = sector where the empty pos is found
; EBX = pointer in buffer
; [buffer .. buffer+511]
; ECX,EDX,ESI,EDI not changed
; IF CARRY=1 disk full or fat corrupted
; Note : if cluster=0 it's changed to read rootdir
;-----------------------------------------------------------
push ecx edx edi
 
adw_new_cluster:
mov [cluster_tmp],eax
mov [fat16_root],0
cmp eax,[LAST_CLUSTER]
ja adw_not_found ; too big cluster number, something is wrong
cmp eax,2
jnb adw_data_cluster
 
mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir
cmp [fs_type],16
jne adw_data_cluster
mov eax,[ROOT_START]
mov edx,[ROOT_SECTORS]
mov [fat16_root],1 ; flag for fat16 rootdir
jmp adw_new_sector
 
adw_data_cluster:
sub eax,2
mov edx,[SECTORS_PER_CLUSTER]
imul eax,edx
add eax,[DATA_START]
 
adw_new_sector:
mov ebx,buffer
call hd_read
cmp [hd_error],0
jne adw_not_found
 
mov ecx,512/32 ; count of dir entrys per sector = 16
 
adw_analyze:
cmp byte [ebx],0x00 ; is free entry?
je adw_found ; yes
cmp byte [ebx],0xe5 ; is deleted entry?
je adw_found ; yes
add ebx,32 ; position of next dir entry
dec ecx
jnz adw_analyze
 
inc eax ; next sector
dec edx
jne adw_new_sector
cmp [fat16_root],1 ; end of fat16 rootdir
je adw_not_found
 
mov eax,[cluster_tmp]
call get_FAT ; get next cluster
cmp [hd_error],0
jne adw_not_found
 
cmp eax,2 ; incorrect fat chain?
jb adw_not_found ; yes
cmp eax,[fatRESERVED] ; is it end of directory?
jb adw_new_cluster ; no. analyse it
 
mov eax,2 ; this block of code add a new cluster
call get_free_FAT ; for the directory because the directory
jc adw_not_found ; is full
 
mov edx,[fatEND] ; new end for directory
call set_FAT
cmp [hd_error],0
jne adw_not_found
 
push eax ; save new cluster
mov edx,eax
mov eax,[cluster_tmp] ; change last cluster to point new cluster
call set_FAT
cmp [hd_error],0
jne adw_not_found_1
 
mov ecx,-1 ; remove 1 cluster from free disk space
call add_disk_free_space
cmp [hd_error],0
jne adw_not_found_1
 
mov ecx,512/4
xor eax,eax
mov edi,buffer
cld
rep stosd ; clear new directory cluster
pop eax
 
sub eax,2
mov ecx,[SECTORS_PER_CLUSTER]
imul eax,ecx
add eax,[DATA_START]
mov ebx,buffer
push eax ; save sector number
 
adw_set_empty_directory:
call hd_write
cmp [hd_error],0
jne adw_not_found_1
 
inc eax ; next sector
dec ecx
jnz adw_set_empty_directory
 
pop eax
 
adw_found:
pop edi edx ecx
clc ; free space found
ret
adw_not_found_1:
add esp,4
adw_not_found:
pop edi edx ecx
stc ; free space not found
ret
 
 
get_data_cluster:
;-----------------------------------------------------------
; input : EAX = cluster
660,43 → 522,6
ret
 
 
set_data_cluster:
;-----------------------------------------------------------
; input : EAX = cluster
; EBX = pointer to buffer
; output : if CARRY=0 ok
; if CARRY=1 cluster out of range
;-----------------------------------------------------------
push eax ebx edx
 
cmp eax,[LAST_CLUSTER]
ja sdc_error ; too big cluster number, something is wrong
sub eax,2
jb sdc_error ; don't allow rootdir write
 
mov edx,[SECTORS_PER_CLUSTER]
imul eax,edx
add eax,[DATA_START]
 
sdc_write:
call hd_write
cmp [hd_error],0
jne sdc_error
 
add ebx,512 ; update pointer
inc eax
dec edx
jnz sdc_write
pop edx ebx eax
clc
ret
 
sdc_error:
pop edx ebx eax
stc
ret
 
 
get_cluster_of_a_path:
;---------------------------------------------------------
; input : EBX = pointer to a path string
855,191 → 680,6
ret
 
 
file_write:
;--------------------------------------------------------------------------
; INPUT : user-reg register-in-this meaning symbol-in-this-routine
;
; EAX EDI system call to write /
; EBX EAX (PAR0) pointer to file-name PAR0
; EDX ECX (PAR1) pointer to buffer PAR1
; ECX EBX (PAR2) file size PAR2
; ESI EDX (PAR3) pointer to path PAR3
;
; output : eax = 0 - ok
; 3 - unknown FS
; 5 - file not found
; 8 - disk full
; 10 - access denied
;--------------------------------------------------------------------------
cmp [fs_type], 16
jz fat_ok_for_writing
cmp [fs_type], 32
jz fat_ok_for_writing
push ERROR_UNKNOWN_FS
pop eax
ret
 
fat_ok_for_writing:
; call reserve_hd1
 
pushad
 
xor edi,edi ; don't allow directory remove
call file_delete ; try to delete the file first
cmp [hd_error],0
jne exit_write_access_1
 
test eax,eax
jz old_deleted ; deleted ok
cmp eax,ERROR_FILE_NOT_FOUND
jnz exit_write_access ; it exist but can't delete
 
old_deleted:
mov ebx,PUSHAD_EDX
call get_cluster_of_a_path
jnc found_directory_for_writing
cmp [hd_error],0
jne exit_write_access
 
exit_writing_with_error:
popad
call update_disk ; write all of cache and fat to hd
cmp [hd_error],0
jne exit_write_access_2
 
mov [hd1_status],0
mov eax,ERROR_FILE_NOT_FOUND
ret
 
exit_writing_disk_full_clear:
cmp [hd_error],0
jne exit_write_access_1
mov eax,[sector_tmp]
mov ebx,buffer
call hd_read ; read directory sector
cmp [hd_error],0
jne exit_write_access_1
 
mov edx,[entry_pos]
mov byte [edx],0xe5 ; mark as deleted
call hd_write
cmp [hd_error],0
jne exit_write_access_1
 
mov eax,[edx+20-2] ; FAT entry
mov ax,[edx+26]
and eax,[fatMASK]
call clear_cluster_chain
 
exit_writing_disk_full:
cmp [hd_error],0
jne exit_write_access_1
popad
call update_disk ; write all of cache and fat to hd
cmp [hd_error],0
jne exit_write_access_2
mov [hd1_status],0
mov eax,ERROR_DISK_FULL
ret
 
exit_write_access:
popad
call update_disk ; write all of cache and fat to hd
mov [hd1_status],0
mov eax,ERROR_ACCESS_DENIED
ret
 
exit_write_access_1:
popad
exit_write_access_2:
mov [hd1_status],0
mov eax,ERROR_ACCESS_DENIED
ret
 
found_directory_for_writing:
call analyze_directory_to_write
jc exit_writing_disk_full
 
mov [sector_tmp],eax
mov [entry_pos],ebx
push eax ; save directory sector
mov eax,2
call get_free_FAT
mov [cluster],eax ; first free cluster
pop eax
jc exit_writing_disk_full
 
mov esi,PUSHAD_EAX ; file name
mov edi,ebx ; pointer in buffer
mov ecx,11
cld
rep movsb
 
mov esi,PUSHAD_EBX ; file size (bytes left)
mov [ebx+28],esi ; file size
mov ecx,[cluster]
mov [ebx+26],cx ; 16 bits low of cluster
shr ecx,16
mov [ebx+20],cx ; 16 bits high of cluster (=0 fat16)
mov byte [ebx+11],0x20 ; attribute = archive
 
call set_current_time_for_entry
 
mov ebx,buffer ; save the directory name,length,cluster
call hd_write
cmp [hd_error],0
jne exit_write_access_1
 
imul edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
xor ecx,ecx ; cluster count
mov ebx,PUSHAD_ECX ; ebx = buffer
 
hd_new_block_write:
 
mov eax,[cluster] ; eax = block
call set_data_cluster
cmp [hd_error],0
jne exit_write_access_1
 
sub esi,edi ; sub wrote bytes
jbe file_saved_OK ; end if all done
add ebx,edi ; update buffer position
 
inc eax
call get_free_FAT ; next free in FAT
jc exit_writing_disk_full_clear
 
mov edx,eax
xchg eax,[cluster] ; get old cluster and save new cluster
call set_FAT ; add it in cluster chain
cmp [hd_error],0
jne exit_write_access_1
 
dec ecx ; update cluster count
jmp hd_new_block_write
 
file_saved_OK:
 
mov edx,[fatEND] ; new end for cluster chain
call set_FAT
cmp [hd_error],0
jne exit_write_access_1
 
dec ecx ; update cluster count
 
call add_disk_free_space ; remove clusters from free disk space
cmp [hd_error],0
jne exit_write_access_1
 
popad
call update_disk ; write all of cache and fat to hd
cmp [hd_error],0
jne exit_write_access_2
mov [hd1_status],0
xor eax,eax
ret
 
 
file_read:
;--------------------------------------------------------------------------
; INPUT : user-register register-in-this meaning symbol-in-this
1209,67 → 849,6
ret
 
 
file_delete:
;-----------------------------------------------------
; input : eax = file/directory name
; edx = path
; edi = 1 - allow directory remove else don't remove directory
; output : eax = 0 - ok
; 3 - unknown FS
; 5 - file not found
; 10 - access denied
;-----------------------------------------------------
cmp [fs_type], 16
jz file_del_fat_ok
cmp [fs_type], 32
jz file_del_fat_ok
push ERROR_UNKNOWN_FS
pop eax
ret
 
file_del_fat_ok:
pushad
 
mov ebx,edx
call get_cluster_of_a_path
jc file_to_delete_not_found
 
mov ebx,PUSHAD_EAX ; file/directory name
call analyze_directory
jc file_to_delete_not_found
 
test byte [ebx+11],0x10 ; is it directory?
jnz delete_no_access
 
delete_notdir:
call delete_entry_name
cmp [hd_error],0
jne delete_no_access
 
mov eax,ecx ; first cluster of file
call clear_cluster_chain
cmp [hd_error],0
jne delete_no_access
 
popad
xor eax,eax
ret
 
delete_no_access_1:
add esp,4
delete_no_access:
popad
mov eax,ERROR_ACCESS_DENIED
ret
 
file_to_delete_not_found:
cmp [hd_error],0
jne delete_no_access
popad
mov eax,ERROR_FILE_NOT_FOUND
ret
 
 
clear_cluster_chain:
;-----------------------------------------------------
; input : eax = first cluster
1301,60 → 880,6
ret
 
 
delete_entry_name:
;-----------------------------------------------------
; input : eax = directory sector
; ebx = directory pointer in buffer
; longname_sec = 2 previous directory sectors
; output : ecx = first cluster
; change : eax,ebx,edx
;-----------------------------------------------------
mov byte [ebx],0xe5
mov ecx,[ebx+20-2] ; first cluster of file
mov cx,[ebx+26] ; 0 length files start cluster = 0
and ecx,[fatMASK]
 
delete_empty:
sub ebx,32
cmp ebx,buffer
jnb delete_test_long
 
mov ebx,buffer
call hd_write ; write directory sector back
cmp [hd_error],0
jne delete_name_end
 
xor eax,eax
xchg eax,[longname_sec2]
xchg eax,[longname_sec1]
test eax,eax ; is there previous directory sector?
jz delete_name_end ; no
 
mov ebx,buffer
call hd_read ; read previous sector
cmp [hd_error],0
jne delete_name_end
 
mov ebx,buffer+0x1e0 ; start from last entry
 
delete_test_long:
mov dh,[ebx+11] ; file attribute
and dh,0xf
cmp dh,0xf
jne delete_write_buffer
 
cmp byte [ebx],0x40 ; end of long dir entry?
mov byte [ebx],0xe5
jb delete_empty
 
delete_write_buffer:
mov ebx,buffer
call hd_write ; write directory sector back
 
delete_name_end:
ret
 
 
get_hd_info:
;-----------------------------------------------------------
; output : eax = 0 - ok
1428,56 → 953,7
update_disk_acces_denied:
ret
 
read_hd_file:
;-----------------------------------------------------------------
;
; Converting old reading function for hd-application start.
;
; IN:
;
; eax - pointer to file (0 = read only first sector of drive: eg 'label')
; ebx - file lenght
; ecx - start 512 byte block number
; edx - number of blocks to read
; esi - pointer to return/work area (atleast 20 000 bytes)
;
; For new read function
;
; EAX (PAR0) pointer to file-name
; ECX (PAR1) pointer to buffer
; EBX (PAR2) vt file blocks to read
; EDX (PAR3) pointer to path
; ESI vt first 512 block to read
; EDI if 0 - return root
;--------------------------------------------------------------------------
 
push ecx esi edi
mov esi,eax
mov edi,startpath
mov ecx,250
cld
rep movsb
pop edi esi ecx
 
mov eax,startpath
mov [eax+ebx-12],byte 0
 
push eax ebx ecx edx esi
 
pop ecx ; pointer to buffer
add ecx,1024
pop ebx ; number of blocks to read
pop esi ; first block to read
dec esi
pop eax ; file length
pop edx ; pointer to path
 
mov edi,12
lea eax,[eax+edx-12+1]
call file_read
 
ret
 
; \begin{diamond}
hd_find_lfn:
; in: esi->name