NTFS: write/rewrite file without size change.

git-svn-id: svn://kolibrios.org@5994 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
pathoswithin 2015-12-21 11:47:21 +00:00
parent 03116eedba
commit 662164c87f
2 changed files with 199 additions and 42 deletions

View File

@ -20,6 +20,7 @@ ERROR_FAT_TABLE = 9 ;deprecated
ERROR_FS_FAIL = 9
ERROR_ACCESS_DENIED = 10
ERROR_DEVICE = 11
ERROR_OUT_OF_MEMORY = 12
image_of_eax EQU esp+32
image_of_ebx EQU esp+20

View File

@ -37,6 +37,8 @@ attributeOffset = 14h
recordFlags = 16h
recordRealSize = 18h
recordAllocatedSize = 1ch
baseRecordReference = 20h ; for auxiliary records
baseRecordReuse = 26h
newAttributeID = 28h
; attribute header
attributeType = 0
@ -111,8 +113,8 @@ fileRealSize dd ? ; in bytes
indexOffset dd ?
nodeLastRead dd ?
ntfs_bCanContinue db ?
ntfsNotFound db ?
ntfsFolder db ?
ntfsWriteAttr db ? ; Warning: Don't forget to turn off!!!
ntfsFragmentCount db ?
cur_subnode_size dd ?
@ -143,7 +145,7 @@ ntfs_user_functions:
dd ntfs_ReadFile
dd ntfs_ReadFolder
dd ntfs_CreateFile
dd ntfs_Write
dd ntfs_WriteFile
dd ntfs_SetFileEnd
dd ntfs_GetFileInfo
dd ntfs_SetFileInfo
@ -277,6 +279,7 @@ ntfs_create_partition:
mov ecx, [ebp+PARTITION.Disk]
mov [eax+NTFS.Disk], ecx
mov [eax+NTFS.FSUserFunctions], ntfs_user_functions
mov [eax+NTFS.ntfsWriteAttr], 0
push ebx ebp esi
mov ebp, eax
@ -544,6 +547,7 @@ ntfs_read_frs_sector:
ret
ntfs_read_attr:
; [ebp+NTFS.ntfsWriteAttr]=1 -> write attribute
; in:
; [ebp+NTFS.ntfs_cur_iRecord] = number of fileRecord
; [ebp+NTFS.ntfs_cur_attr] = attribute type
@ -992,6 +996,18 @@ ntfs_read_attr:
sub eax, [ecx+10h] ; first_vbo
jb .okret
; eax = cluster, edx = starting sector
cmp [ebp+NTFS.ntfs_cur_attr], 0x80
jnz .sys
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jz .sys
push fs_read64_app
cmp [ebp+NTFS.ntfsWriteAttr], 1
jnz @f
mov dword[esp], fs_write64_app
jmp @f
.sys:
push fs_read64_sys
@@:
sub esp, 10h
movzx esi, word [ecx+20h] ; mcb_info_ofs
add esi, ecx
@ -1021,15 +1037,7 @@ ntfs_read_attr:
mov [ebp+NTFS.ntfsLastRead], eax
push ecx
xor edx, edx
cmp [ebp+NTFS.ntfs_cur_attr], 0x80
jnz .sys
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jz .sys
call fs_read64_app
jmp .appsys
.sys:
call fs_read64_sys
.appsys:
call dword[esp+18h]
pop ecx
test eax, eax
jnz .errread2
@ -1044,7 +1052,7 @@ ntfs_read_attr:
xor edx, edx
cmp [ebp+NTFS.ntfs_cur_size], 0
jnz .readloop
add esp, 10h
add esp, 14h
mov eax, [ebp+NTFS.ntfs_cur_tail]
test eax, eax
jz @f
@ -1055,11 +1063,11 @@ ntfs_read_attr:
ret
.errread2:
pop ecx
add esp, 10h
add esp, 14h
stc
ret
.break:
add esp, 10h ; CF=0
add esp, 14h ; CF=0
mov [ebp+NTFS.ntfs_bCanContinue], 1
ret
@ -1211,8 +1219,8 @@ ntfs_find_lfn:
; in: [esi]+[esp+4] = name
; out:
; [ebp+NTFS.ntfs_cur_iRecord] = number of MFT fileRecord
; eax = pointer in parent index node
; CF=1 -> file not found (or just error)
; eax -> index in the parent index node
; CF=1 -> file not found, eax=0 -> error
mov [ebp+NTFS.ntfs_cur_iRecord], 5 ; start parse from root cluster
.doit2:
mov [ebp+NTFS.ntfs_cur_attr], 0x90 ; $INDEX_ROOT
@ -1222,11 +1230,11 @@ ntfs_find_lfn:
mov eax, [ebp+NTFS.cur_index_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr
mov eax, 0
jnc @f
.ret:
ret 4
@@:
xor eax, eax
cmp [ebp+NTFS.ntfs_cur_read], 0x20
jc .ret
pushad
@ -1345,7 +1353,6 @@ ntfs_find_lfn:
add esi, 0x18
jmp .scanloop
.notfound:
mov [ebp+NTFS.ntfsNotFound], 1
mov [esp+1Ch], esi
.err:
popad
@ -1470,7 +1477,6 @@ ntfs_ReadFile:
adc edx, 0
shrd eax, edx, 9
pop edx
.zero1:
mov [ebp+NTFS.ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_buf], edx
mov eax, ecx
@ -1550,7 +1556,7 @@ ntfs_ReadFolder:
test eax, eax
jz .notfound
or ebx, -1
push 11
push ERROR_DEVICE
jmp .pop_ret
.ok:
cmp [ebp+NTFS.ntfs_cur_read], 0x20
@ -1587,7 +1593,7 @@ ntfs_ReadFolder:
call ntfs_unlock
popad
or ebx, -1
movi eax, 12
movi eax, ERROR_OUT_OF_MEMORY
ret
@@:
mov [ebp+NTFS.cur_index_buf], eax
@ -1976,6 +1982,7 @@ ntfs_datetime_to_bdfe:
ntfs_CreateFolder:
mov [ebp+NTFS.ntfsFolder], 1
jmp @f
ntfs_CreateFile:
mov [ebp+NTFS.ntfsFolder], 0
@@:
@ -1986,18 +1993,46 @@ ntfs_CreateFile:
ret
@@: ; 1. Search file
call ntfs_lock
mov [ebp+NTFS.ntfsNotFound], 0
stdcall ntfs_find_lfn, [esp+4]
jnc @f ; found; rewrite
jnc .found
cmp [ebp+NTFS.ntfsFragmentCount], 1
jnz @f ; record fragmented
cmp [ebp+NTFS.ntfsNotFound], 1
jz .notFound
test eax, eax
jnz .notFound
push ERROR_FS_FAIL
jmp ntfsError
@@:
push ERROR_UNSUPPORTED_FS
jmp ntfsError
.found: ; rewrite
mov [ebp+NTFS.ntfs_cur_attr], 0x80
mov [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 0
call ntfs_read_attr
jnc @f
push ERROR_ACCESS_DENIED
jmp ntfsError
@@:
push ERROR_UNSUPPORTED_FS
mov eax, [ebp+NTFS.frs_buffer]
cmp word [eax+baseRecordReuse], 0
jnz ntfsError ; auxiliary record
cmp byte [eax+hardLinkCounter], 1
jnz ntfsError ; file copying required
mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1
jnz ntfsError ; resident $DATA
mov eax, [ebx+4]
mov edx, [ebx+8]
add eax, [ebx+12]
adc edx, 0
cmp edx, [ecx+attributeRealSize+4]
jnz ntfsError
cmp [ecx+attributeRealSize], eax
jnz ntfsError
jmp ntfs_WriteFile.write
.notFound: ; create; check name
cmp dword [esp+4], 0
jnz .bad
@ -2285,7 +2320,7 @@ ntfs_CreateFile:
call fs_write64_app
test eax, eax
jz .mftBitmap
push 11
push ERROR_DEVICE
jmp ntfsError
; 4. MFT record
@ -2335,8 +2370,11 @@ ntfs_CreateFile:
shl ebx, 9+3
add dword [edi+lastVCN], 8
add [edi+attributeAllocatedSize], ebx
adc byte [edi+attributeAllocatedSize+4], 0
add [edi+attributeRealSize], ebx
adc byte [edi+attributeRealSize+4], 0
add [edi+initialDataSize], ebx
adc byte [edi+initialDataSize+4], 0
add edi, [edi+dataRunsOffset]
movzx eax, byte [edi]
inc edi
@ -2364,14 +2402,15 @@ ntfs_CreateFile:
and ecx, 7
shr edx, 3
add edx, [ebp+NTFS.BitmapBuffer]
movzx eax, word [edx]
shr eax, cl
mov ax, [edx]
shr ax, cl
test al, al
jnz ntfsError
mov al, -1
dec al
xchg [edx], al
mov [edx+1], al
pop eax
push 12
push ERROR_OUT_OF_MEMORY
stdcall kernel_alloc, ebx
test eax, eax
jz ntfsError
@ -2389,7 +2428,7 @@ ntfs_CreateFile:
call fs_write64_sys ; clear new records
stdcall kernel_free, ebx
pop eax
push 11
push ERROR_DEVICE
mov eax, esi
shr eax, 3+9
mov ebx, eax
@ -2521,7 +2560,7 @@ ntfs_CreateFile:
call writeRecord
test eax, eax
jz @f
push 11
push ERROR_DEVICE
jmp ntfsError
@@:
mov esi, [ebp+PARTITION.Disk]
@ -2538,7 +2577,7 @@ ntfs_CreateFile:
call fs_write64_sys
test eax, eax
jz @f
push 11
push ERROR_DEVICE
jmp ntfsError
@@: ; 5. Write partition bitmap
cmp [ebp+NTFS.ntfsFolder], 0
@ -2560,7 +2599,7 @@ ntfs_CreateFile:
call fs_write64_app
test eax, eax
jz @f
push 11
push ERROR_DEVICE
jmp ntfsError
@@:
mov esi, [ebp+PARTITION.Disk]
@ -2659,9 +2698,126 @@ bitmapBuffering:
jmp ntfsError
;----------------------------------------------------------------
ntfs_Write:
ntfs_WriteFile:
cmp byte [esi], 0
jnz @f
xor ebx, ebx
mov eax, ERROR_UNSUPPORTED_FS
movi eax, ERROR_ACCESS_DENIED
ret
@@:
call ntfs_lock
stdcall ntfs_find_lfn, [esp+4]
jnc .found
push ERROR_FILE_NOT_FOUND
jmp ntfsError
.found:
mov [ebp+NTFS.ntfs_cur_attr], 0x80
mov [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 0
call ntfs_read_attr
jnc @f
push ERROR_ACCESS_DENIED
jmp ntfsError
@@:
push ERROR_UNSUPPORTED_FS
mov eax, [ebp+NTFS.frs_buffer]
cmp word [eax+baseRecordReuse], 0
jnz ntfsError ; auxiliary record
cmp byte [eax+hardLinkCounter], 1
jnz ntfsError ; file copying required
mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1
jnz ntfsError ; resident $DATA
mov eax, [ebx+4]
mov edx, [ebx+8]
add eax, [ebx+12]
adc edx, 0
cmp edx, [ecx+attributeRealSize+4]
jc .write
jnz ntfsError ; end of file
cmp [ecx+attributeRealSize], eax
jc ntfsError
.write:
pop eax
push ERROR_DEVICE
mov eax, [ebx+4]
mov edx, [ebx+8]
mov ecx, [ebx+12]
mov esi, [ebx+16]
shrd eax, edx, 9
test dword[ebx+4], 1FFh
jz .aligned
mov [ebp+NTFS.ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_size], 1
lea edi, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], edi
call ntfs_read_attr.continue
jc ntfsError
mov eax, [ebx+4]
and eax, 1FFh
add edi, eax
sub eax, [ebp+NTFS.ntfs_cur_read]
neg eax
push ecx
cmp ecx, eax
jb @f
mov ecx, eax
@@:
sub [esp], ecx
rep movsb
push ebx
mov eax, [ebp+NTFS.ntfsLastRead]
lea ebx, [ebp+NTFS.ntfs_bitmap_buf]
mov ecx, 1
xor edx, edx
call fs_write64_app
pop ebx
pop ecx
test eax, eax
jnz ntfsError
test ecx, ecx
jz @f
mov eax, [ebx+4]
mov edx, [ebx+8]
shrd eax, edx, 9
inc eax
.aligned:
push ecx
shr ecx, 9
mov [ebp+NTFS.ntfs_cur_offs], eax
mov [ebp+NTFS.ntfs_cur_size], ecx
mov [ebp+NTFS.ntfs_cur_buf], esi
add eax, ecx
push eax
mov [ebp+NTFS.ntfsWriteAttr], 1
call ntfs_read_attr.continue
mov [ebp+NTFS.ntfsWriteAttr], 0
pop [ebp+NTFS.ntfs_cur_offs]
pop ecx
jc ntfsError
and ecx, 1FFh
jz @f
add esi, [ebp+NTFS.ntfs_cur_read]
mov [ebp+NTFS.ntfs_cur_size], 1
lea edi, [ebp+NTFS.ntfs_bitmap_buf]
mov [ebp+NTFS.ntfs_cur_buf], edi
call ntfs_read_attr.continue
jc ntfsError
rep movsb
push ebx
mov eax, [ebp+NTFS.ntfsLastRead]
lea ebx, [ebp+NTFS.ntfs_bitmap_buf]
mov ecx, 1
xor edx, edx
call fs_write64_app
pop ebx
@@:
mov esi, [ebp+PARTITION.Disk]
call disk_sync
call ntfs_unlock
pop eax
xor eax, eax
mov ebx, [ebx+12]
ret
;----------------------------------------------------------------
@ -2675,19 +2831,19 @@ ntfs_Delete:
ntfs_GetFileInfo:
cmp byte [esi], 0
jnz @f
movi eax, 2
movi eax, ERROR_UNSUPPORTED_FS
ret
@@:
call ntfs_lock
stdcall ntfs_find_lfn, [esp+4]
jnc .doit
test eax, eax
jnc .found
push ERROR_FILE_NOT_FOUND
jz ntfsError
test eax, eax
jnz ntfsError
pop eax
push 11
push ERROR_FS_FAIL
jmp ntfsError
.doit:
.found:
push esi edi
mov esi, eax
mov edi, [ebx+16]