2,11 → 2,12 |
;; ;; |
;; FAT32.INC ;; |
;; ;; |
;; FAT16/32 functions for MenuetOS ;; |
;; FAT16/32 functions for KolibriOS ;; |
;; ;; |
;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; |
;; ;; |
;; See file COPYING for details ;; |
;; 17.08.2006 LFN write/append to file - diamond ;; |
;; 23.06.2006 LFN start application - diamond ;; |
;; 15.06.2006 LFN get/set file/folder info - diamond ;; |
;; 27.05.2006 LFN create/rewrite file - diamond ;; |
104,7 → 105,6 |
startpath: times 255 db 0 |
|
fat16_root db 0 ; flag for fat16 rootdir |
f_del db 0 ; 1=overwrite fat entry |
fat_change db 0 ; 1=fat has changed |
|
endg |
225,14 → 225,6 |
cmp [fat_type],16 |
jne sfc_test32 |
|
cmp [f_del],1 ; overwrite previous value? |
je sfc_set16 ; yes |
cmp word [ebx+esi],0 ; is cluster free? |
je sfc_set16 ; yes |
mov dword [8*0x100000],0xffffff |
mov edx,[ebx+esi] ; get old value |
jmp sfc_nonzero |
|
sfc_set16: |
xchg [ebx+esi],dx ; save new value and get old value |
jmp sfc_write |
239,13 → 231,6 |
|
sfc_test32: |
mov eax,[fatMASK] |
cmp [f_del],1 ; overwrite previous value? |
je sfc_set32 ; yes |
test eax,[ebx+esi] ; is cluster free? |
je sfc_set32 ; yes |
mov dword [8*0x100000],0xffffff |
mov edx,[ebx+esi] ; get old value |
jmp sfc_nonzero |
|
sfc_set32: |
and edx,eax |
554,13 → 539,10 |
push eax ; save new cluster |
mov edx,eax |
mov eax,[cluster_tmp] ; change last cluster to point new cluster |
mov [f_del],1 |
call set_FAT |
cmp [hd_error],0 |
jne adw_not_found_1 |
|
mov [f_del],0 |
|
mov ecx,-1 ; remove 1 cluster from free disk space |
call add_disk_free_space |
cmp [hd_error],0 |
883,13 → 865,10 |
jne make_dir_error_1 |
mov eax,[cluster] ; directory cluster |
xor edx,edx ; free |
mov [f_del],1 |
call set_FAT |
cmp [hd_error],0 |
jne make_dir_error_1 |
|
mov [f_del],0 |
|
popad |
call update_disk ; write all of cache and fat to hd |
make_dir_error_2: |
1238,12 → 1217,10 |
|
mov edx,eax |
mov eax,[cluster] |
mov [f_del],1 |
call set_FAT ; update previous cluster |
cmp [hd_error],0 |
jne append_access_1 |
|
mov [f_del],0 |
pop eax |
jmp append_remove_free |
|
1362,12 → 1339,10 |
|
truncate_pos_found: |
mov edx,[fatEND] ; new end for cluster chain |
mov [f_del],1 |
call set_FAT |
cmp [hd_error],0 |
jne append_access |
|
mov [f_del],0 |
mov eax,edx ; clear rest of chain |
|
truncate_clear_chain: |
1875,7 → 1850,6 |
;----------------------------------------------------- |
push eax ecx edx |
xor ecx,ecx ; cluster count |
mov [f_del],1 ; delete on |
|
clean_new_chain: |
cmp eax,[LAST_CLUSTER] ; end of file |
1897,7 → 1871,6 |
delete_OK: |
call add_disk_free_space ; add clusters to free disk space |
access_denied_01: |
mov [f_del],0 |
pop edx ecx eax |
ret |
|
3288,7 → 3261,6 |
mov eax, [esp+4] |
mov eax, [eax] |
push edx |
mov [f_del], 1 |
call set_FAT |
pop edx |
cmp [hd_error], 0 |
3450,7 → 3422,6 |
mov word [edi+26], cx |
test eax, eax |
jz .done1 |
mov [f_del], 1 |
@@: |
cmp eax, [fatRESERVED] |
jae .done1 |
3736,7 → 3707,6 |
mov ecx, eax |
call get_free_FAT |
jc .diskfull |
mov [f_del], 1 |
push edx |
mov edx, [fatEND] |
call set_FAT |
3783,6 → 3753,348 |
popad |
ret |
|
;---------------------------------------------------------------- |
; |
; fs_HdWrite - LFN variant for writing to floppy |
; |
; esi points to filename |
; ebx pointer to 64-bit number = first wanted byte, 0+ |
; may be ebx=0 - start from first byte |
; ecx number of bytes to write, 0+ |
; edx mem location to data |
; |
; ret ebx = bytes written (maybe 0) |
; eax = 0 ok write or other = errormsg |
; |
;-------------------------------------------------------------- |
fs_HdWrite.access_denied: |
push ERROR_ACCESS_DENIED |
fs_HdWrite.ret0: |
pop eax |
xor ebx, ebx |
ret |
|
fs_HdWrite.ret11: |
push 11 |
jmp fs_HdWrite.ret0 |
|
fs_HdWrite: |
cmp [fat_type], 0 |
jnz @f |
push ERROR_UNKNOWN_FS |
jmp .ret0 |
@@: |
cmp byte [esi], 0 |
jz .access_denied |
pushad |
call hd_find_lfn |
pushfd |
cmp [hd_error], 0 |
jz @f |
popfd |
popad |
push 11 |
jmp .ret0 |
@@: |
popfd |
jnc .found |
popad |
push ERROR_FILE_NOT_FOUND |
jmp .ret0 |
.found: |
; FAT does not support files larger than 4GB |
test ebx, ebx |
jz .l1 |
cmp dword [ebx+4], 0 |
jz @f |
.eof: |
popad |
push ERROR_END_OF_FILE |
jmp .ret0 |
@@: |
mov ebx, [ebx] |
.l1: |
; now edi points to direntry, ebx=start byte to write, |
; ecx=number of bytes to write, edx=data pointer |
|
; extend file if needed |
add ecx, ebx |
jc .eof ; FAT does not support files larger than 4GB |
push eax ; save directory sector |
push 0 ; return value=0 |
|
call get_time_for_file |
mov [edi+22], ax ; last write time |
call get_date_for_file |
mov [edi+24], ax ; last write date |
mov [edi+18], ax ; last access date |
|
push dword [edi+28] ; save current file size |
cmp ecx, [edi+28] |
jbe .length_ok |
cmp ecx, ebx |
jz .length_ok |
call hd_extend_file |
jnc .length_ok |
mov [esp+4], eax |
; hd_extend_file can return three error codes: FAT table error, device error or disk full. |
; First two cases are fatal errors, in third case we may write some data |
cmp al, ERROR_DISK_FULL |
jz .disk_full |
pop eax |
pop eax |
mov [esp+4+28], eax |
pop eax |
popad |
xor ebx, ebx |
ret |
.disk_full: |
; correct number of bytes to write |
mov ecx, [edi+28] |
cmp ecx, ebx |
ja .length_ok |
.ret: |
call update_disk |
cmp [hd_error], 0 |
jz @f |
mov byte [esp+4], 11 |
@@: |
pop eax |
pop eax |
mov [esp+4+28], eax ; eax=return value |
pop eax |
sub edx, [esp+20] |
mov [esp+16], edx ; ebx=number of written bytes |
popad |
ret |
.length_ok: |
mov esi, [edi+28] |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov edi, eax ; edi=current cluster |
xor ebp, ebp ; ebp=current sector in cluster |
; save directory |
mov eax, [esp+8] |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err: |
mov byte [esp+4], 11 |
jmp .ret |
@@: |
|
; now ebx=start pos, ecx=end pos, both lie inside file |
sub ecx, ebx |
jz .ret |
.write_loop: |
; get length of data in current sector |
push ecx |
sub ebx, 0x200 |
jb .hasdata |
neg ebx |
xor ecx, ecx |
jmp @f |
.hasdata: |
neg ebx |
cmp ecx, ebx |
jbe @f |
mov ecx, ebx |
@@: |
; get current sector number |
mov eax, edi |
dec eax |
dec eax |
imul eax, [SECTORS_PER_CLUSTER] |
add eax, [DATA_START] |
add eax, ebp |
; load sector if needed |
cmp dword [esp+4], 0 ; we don't need to read uninitialized data |
jz .noread |
cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten |
jz .noread |
cmp ecx, esi ; (same for the last sector) |
jz .noread |
push ebx |
mov ebx, buffer |
call hd_read |
pop ebx |
cmp [hd_error], 0 |
jz @f |
.device_err2: |
pop ecx |
jmp .device_err |
@@: |
.noread: |
; zero uninitialized data if file was extended (because hd_extend_file does not this) |
push eax ecx edi |
xor eax, eax |
mov ecx, 0x200 |
sub ecx, [esp+4+12] |
jbe @f |
mov edi, buffer |
add edi, [esp+4+12] |
rep stosb |
@@: |
; zero uninitialized data in the last sector |
mov ecx, 0x200 |
sub ecx, esi |
jbe @f |
mov edi, buffer |
add edi, esi |
rep stosb |
@@: |
pop edi ecx eax |
; copy new data |
push eax |
mov eax, edx |
neg ebx |
jecxz @f |
add ebx, buffer+0x200 |
call memmove |
xor ebx, ebx |
@@: |
pop eax |
; save sector |
push ebx |
mov ebx, buffer |
call hd_write |
pop ebx |
cmp [hd_error], 0 |
jnz .device_err2 |
add edx, ecx |
sub [esp], ecx |
pop ecx |
jz .ret |
; next sector |
inc ebp |
cmp ebp, [SECTORS_PER_CLUSTER] |
jb @f |
xor ebp, ebp |
mov eax, edi |
call get_FAT |
mov edi, eax |
cmp [hd_error], 0 |
jnz .device_err |
@@: |
sub esi, 0x200 |
jae @f |
xor esi, esi |
@@: |
sub dword [esp], 0x200 |
jae @f |
and dword [esp], 0 |
@@: jmp .write_loop |
|
hd_extend_file.zero_size: |
xor eax, eax |
jmp hd_extend_file.start_extend |
|
; extends file on hd to given size (new data area is undefined) |
; in: edi->direntry, ecx=new size |
; out: CF=0 => OK, eax destroyed |
; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11) |
hd_extend_file: |
push ebp |
mov ebp, [SECTORS_PER_CLUSTER] |
imul ebp, [BYTES_PER_SECTOR] |
push ecx |
; find the last cluster of file |
mov eax, [edi+20-2] |
mov ax, [edi+26] |
mov ecx, [edi+28] |
jecxz .zero_size |
.last_loop: |
sub ecx, ebp |
jbe .last_found |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
.device_err: |
pop ecx |
.device_err2: |
pop ebp |
push 11 |
.ret_err: |
pop eax |
stc |
ret |
@@: |
cmp eax, 2 |
jb .fat_err |
cmp eax, [fatRESERVED] |
jb .last_loop |
.fat_err: |
pop ecx ebp |
push ERROR_FAT_TABLE |
jmp .ret_err |
.last_found: |
push eax |
call get_FAT |
cmp [hd_error], 0 |
jz @f |
pop eax |
jmp .device_err |
@@: |
cmp eax, [fatRESERVED] |
pop eax |
jb .fat_err |
; set length to full number of clusters |
sub [edi+28], ecx |
.start_extend: |
pop ecx |
; now do extend |
push edx |
mov edx, 2 ; start scan from cluster 2 |
.extend_loop: |
cmp [edi+28], ecx |
jae .extend_done |
; add new cluster |
push eax |
mov eax, edx |
call get_free_FAT |
jc .disk_full |
mov edx, [fatEND] |
call set_FAT |
mov edx, eax |
pop eax |
test eax, eax |
jz .first_cluster |
push edx |
call set_FAT |
pop edx |
jmp @f |
.first_cluster: |
ror edx, 16 |
mov [edi+20], dx |
ror edx, 16 |
mov [edi+26], dx |
@@: |
mov eax, edx |
cmp [hd_error], 0 |
jnz .device_err3 |
add [edi+28], ebp |
jmp .extend_loop |
.extend_done: |
mov [edi+28], ecx |
pop edx ebp |
clc |
ret |
.device_err3: |
pop edx |
jmp .device_err2 |
.disk_full: |
pop eax edx ebp |
push ERROR_DISK_FULL |
pop eax |
cmp [hd_error], 0 |
jz @f |
mov al, 11 |
@@: stc |
ret |
|
fs_HdGetFileInfo: |
cmp [fat_type], 0 |
jnz @f |