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_FS_FAIL = 9
ERROR_ACCESS_DENIED = 10 ERROR_ACCESS_DENIED = 10
ERROR_DEVICE = 11 ERROR_DEVICE = 11
ERROR_OUT_OF_MEMORY = 12
image_of_eax EQU esp+32 image_of_eax EQU esp+32
image_of_ebx EQU esp+20 image_of_ebx EQU esp+20

View File

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