NTFS: set file end, extend bitmap MFT

git-svn-id: svn://kolibrios.org@6107 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
pathoswithin 2016-01-27 23:48:14 +00:00
parent f9f301e7a1
commit 81924b284f

View File

@ -442,6 +442,9 @@ ntfs_create_partition:
mov eax, [ebp+NTFS.ntfs_cur_read] mov eax, [ebp+NTFS.ntfs_cur_read]
cmp eax, 4 cmp eax, 4
jc .failFreeBitmapMFT jc .failFreeBitmapMFT
mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1
jnz .failFreeBitmapMFT
mov [ebp+NTFS.mftBitmapSize], eax mov [ebp+NTFS.mftBitmapSize], eax
mov eax, [ebp+NTFS.ntfsLastRead] mov eax, [ebp+NTFS.ntfsLastRead]
mov [ebp+NTFS.mftBitmapLocation], eax mov [ebp+NTFS.mftBitmapLocation], eax
@ -660,18 +663,19 @@ ntfs_read_attr:
jc .errret jc .errret
; 2. Find required attribute. ; 2. Find required attribute.
mov eax, [ebp+NTFS.frs_buffer] mov eax, [ebp+NTFS.frs_buffer]
; a) For auxiliary records, read base record ; a) For auxiliary records, read base record.
; N.B. If base record is present, ; If base record is present, base iRecord may be 0 (for $Mft),
; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero ; but SequenceNumber is nonzero.
cmp dword [eax+24h], 0 cmp dword [eax+24h], 0
jz @f jz @f
mov eax, [eax+20h] mov eax, [eax+20h]
; test eax, eax
; jz @f
.beginfindattr: .beginfindattr:
mov [ebp+NTFS.ntfs_attr_iRecord], eax mov [ebp+NTFS.ntfs_attr_iRecord], eax
call ntfs_read_file_record call ntfs_read_file_record
jc .errret jc .errret
jmp @f
.newAttribute:
pushad
@@: @@:
; b) Scan for required attribute and for $ATTR_LIST ; b) Scan for required attribute and for $ATTR_LIST
mov eax, [ebp+NTFS.frs_buffer] mov eax, [ebp+NTFS.frs_buffer]
@ -2050,8 +2054,6 @@ ntfs_CreateFile:
xor edx, edx xor edx, edx
cmp word [ecx+baseRecordReuse], 0 cmp word [ecx+baseRecordReuse], 0
jnz ntfsUnsupported ; auxiliary record jnz ntfsUnsupported ; auxiliary record
cmp byte [ecx+hardLinkCounter], 1
jnz ntfsUnsupported ; file copying required
mov ecx, [ebp+NTFS.ntfs_attr_offs] mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1 cmp byte [ecx+nonResidentFlag], 1
jnz ntfsUnsupported ; resident $DATA jnz ntfsUnsupported ; resident $DATA
@ -2215,7 +2217,7 @@ ntfs_CreateFile:
movzx eax, byte [edi] movzx eax, byte [edi]
not al not al
bsf ecx, eax bsf ecx, eax
jz ntfsUnsupported ; no free records jz .extendBitmapMFT ; no free records
bts [edi], ecx bts [edi], ecx
; get record location ; get record location
sub edi, [ebp+NTFS.mftBitmapBuffer] sub edi, [ebp+NTFS.mftBitmapBuffer]
@ -2233,99 +2235,67 @@ ntfs_CreateFile:
mov [ebp+NTFS.ntfs_cur_buf], eax mov [ebp+NTFS.ntfs_cur_buf], eax
call ntfs_read_attr call ntfs_read_attr
cmp [ebp+NTFS.ntfs_cur_read], 0 cmp [ebp+NTFS.ntfs_cur_read], 0
jnz .mftRecord jz .extendMFT
; extend MFT $DATA jmp .mftRecord
.extendBitmapMFT:
mov eax, [ebp+NTFS.sectors_per_cluster]
shl eax, 9
cmp [ebp+NTFS.mftBitmapSize], eax
jnc ntfsUnsupported
mov [ebp+NTFS.ntfs_cur_iRecord], 0
mov [ebp+NTFS.ntfs_cur_attr], 0xB0
mov [ebp+NTFS.ntfs_cur_offs], 0
mov [ebp+NTFS.ntfs_cur_size], 0
call ntfs_read_attr
jc ntfsFail
mov eax, [ebp+NTFS.mft_cluster] mov eax, [ebp+NTFS.mft_cluster]
mul [ebp+NTFS.sectors_per_cluster] mul [ebp+NTFS.sectors_per_cluster]
cmp eax, [ebp+NTFS.ntfsLastRead] cmp eax, [ebp+NTFS.ntfsLastRead]
jnz ntfsUnsupported ; auxiliary record jnz ntfsUnsupported ; auxiliary record
mov edi, [ebp+NTFS.ntfs_attr_offs] mov edi, [ebp+NTFS.mftBitmapBuffer]
mov ebx, [ebp+NTFS.sectors_per_cluster] mov ecx, [ebp+NTFS.mftBitmapSize]
shl ebx, 9+3 add edi, ecx
add dword [edi+lastVCN], 8 mov eax, ecx
add [edi+attributeAllocatedSize], ebx mov edx, [ebp+NTFS.ntfs_attr_offs]
adc byte [edi+attributeAllocatedSize+4], 0 add ecx, 8
add [edi+attributeRealSize], ebx mov [edx+attributeRealSize], ecx
adc byte [edi+attributeRealSize+4], 0 mov [edx+initialDataSize], ecx
add [edi+initialDataSize], ebx shl eax, 3
adc byte [edi+initialDataSize+4], 0 mov [ebp+NTFS.newMftRecord], eax
movzx eax, byte [edi+dataRunsOffset] mov dword [edi], 1
add edi, eax mov dword [edi+4], 0
mov al, [edi] mov [ebp+NTFS.ntfs_cur_attr], 0x80
inc edi call ntfs_read_attr.newAttribute
shl eax, 4 jc ntfsFail
shr al, 4 mov [ebp+NTFS.mftBitmapSize], ecx
mov cl, 4 .extendMFT:
sub cl, al mov eax, [ebp+NTFS.mft_cluster]
shl cl, 3
add ah, al
shr eax, 8
cmp byte [edi+eax], 0
jnz ntfsUnsupported ; $MFT fragmented
mov al, 8
mov edx, [edi]
rol eax, cl
rol edx, cl
add eax, edx
jc ntfsUnsupported
ror eax, cl
shr edx, cl
mov [edi], eax
add edx, [ebp+NTFS.mft_cluster]
mov esi, edx
mov ecx, edx
and ecx, 7
shr edx, 3
add edx, [ebp+NTFS.BitmapBuffer]
mov ax, [edx]
shr ax, cl
test al, al
jnz ntfsUnsupported
dec al
xchg [edx], al
mov [edx+1], al
stdcall kernel_alloc, ebx
test eax, eax
jz ntfsNoMemory
mov ecx, ebx
shr ecx, 2
mov edi, eax
push ebx
mov ebx, eax
xor eax, eax
rep stosd
mov eax, esi
mul [ebp+NTFS.sectors_per_cluster] mul [ebp+NTFS.sectors_per_cluster]
pop ecx cmp eax, [ebp+NTFS.ntfsLastRead]
shr ecx, 9 jnz ntfsUnsupported ; auxiliary record
call fs_write64_sys ; clear new records mov ecx, [ebp+NTFS.ntfs_attr_offs]
stdcall kernel_free, ebx mov eax, [ecx+attributeRealSize]
mov eax, esi mov edx, [ecx+attributeRealSize+4]
shr eax, 3+9 xor ax, ax
mov ebx, eax add eax, 10000h
shl ebx, 9 adc edx, 0
add ebx, [ebp+NTFS.BitmapBuffer] push [ebp+NTFS.fileDataStart]
add eax, [ebp+NTFS.BitmapLocation] push [ebp+NTFS.fileDataSize]
mov ecx, 1 call resizeAttribute
xor edx, edx jc ntfsErrorPop2
call fs_write64_app ; partition bitmap
test eax, eax
jnz ntfsDevice
mov eax, [ebp+NTFS.frs_buffer] mov eax, [ebp+NTFS.frs_buffer]
mov [ebp+NTFS.ntfs_cur_buf], eax mov [ebp+NTFS.ntfs_cur_buf], eax
call writeRecord ; $MFT call writeRecord ; $MFT
test eax, eax
jnz ntfsDevice
mov eax, [ebp+NTFS.mftmirr_cluster] mov eax, [ebp+NTFS.mftmirr_cluster]
mul [ebp+NTFS.sectors_per_cluster] mul [ebp+NTFS.sectors_per_cluster]
mov ebx, [ebp+NTFS.frs_buffer] mov ebx, [ebp+NTFS.frs_buffer]
movzx ecx, word [ebx+updateSequenceSize] movzx ecx, word [ebx+updateSequenceSize]
dec ecx dec ecx
call fs_write64_sys ; $MFTMirr call fs_write64_sys ; $MFTMirr
test eax, eax call ntfsSpaceClean
jnz ntfsDevice pop [ebp+NTFS.fileDataSize]
mov eax, [ebp+NTFS.ntfs_cur_offs] pop [ebp+NTFS.fileDataStart]
add [ebp+NTFS.ntfsLastRead], eax
.mftRecord: .mftRecord:
mov esi, [ebp+NTFS.indexOffset] mov esi, [ebp+NTFS.indexOffset]
mov edi, [ebp+NTFS.frs_buffer] mov edi, [ebp+NTFS.frs_buffer]
@ -2570,6 +2540,8 @@ resizeAttribute:
; [ebp+NTFS.ntfs_attr_offs] -> attribute ; [ebp+NTFS.ntfs_attr_offs] -> attribute
; edx:eax = new size ; edx:eax = new size
; out: ; out:
; [ebp+NTFS.fileDataSize] = clusters added (positive)
; [ebp+NTFS.fileDataStart] = added block
; CF=1 -> eax = error code ; CF=1 -> eax = error code
mov esi, [ebp+NTFS.ntfs_attr_offs] mov esi, [ebp+NTFS.ntfs_attr_offs]
mov ecx, [ebp+NTFS.sectors_per_cluster] mov ecx, [ebp+NTFS.sectors_per_cluster]
@ -2592,10 +2564,10 @@ resizeAttribute:
mov [esi+lastVCN], edi mov [esi+lastVCN], edi
movzx eax, byte [esi+dataRunsOffset] movzx eax, byte [esi+dataRunsOffset]
sub edi, ecx sub edi, ecx
mov [ebp+NTFS.fileDataSize], edi
jz .done jz .done
jc .shrinkAttribute jc .shrinkAttribute
; extend attribute ; extend attribute
mov [ebp+NTFS.fileDataSize], edi
xor edi, edi xor edi, edi
add esi, eax add esi, eax
push edi edi edi edi push edi edi edi edi
@ -2612,8 +2584,11 @@ resizeAttribute:
shr edi, 5 shr edi, 5
shl edi, 2 shl edi, 2
push eax push eax
cmp [ebp+NTFS.ntfs_cur_iRecord], 0
jz @f
cmp edi, [ebp+NTFS.BitmapStart] cmp edi, [ebp+NTFS.BitmapStart]
jc .err1 jc .err1
@@:
call ntfsSpaceAlloc call ntfsSpaceAlloc
jc .err1 jc .err1
pop edi pop edi
@ -2642,6 +2617,8 @@ resizeAttribute:
pop eax pop eax
jc .err2 jc .err2
mov byte [edi], 0 mov byte [edi], 0
mov [ebp+NTFS.fileDataSize], ecx
mov [ebp+NTFS.fileDataStart], eax
add ecx, eax add ecx, eax
add ecx, 4095 add ecx, 4095
shr ecx, 3+9 shr ecx, 3+9
@ -2710,6 +2687,7 @@ resizeAttribute:
jz @f jz @f
mov esi, [ebp+NTFS.ntfs_attr_offs] mov esi, [ebp+NTFS.ntfs_attr_offs]
call createMcbEntry call createMcbEntry
mov [ebp+NTFS.fileDataSize], 0
@@: @@:
mov byte [edi], 0 mov byte [edi], 0
ret ret
@ -2720,6 +2698,38 @@ resizeAttribute:
stc stc
ret ret
ntfsSpaceClean:
; clean up to 16 Mb of disk space
; in:
; [ebp+NTFS.fileDataStart] = block to clean
; [ebp+NTFS.fileDataSize] = block size
mov eax, [ebp+NTFS.fileDataSize]
test eax, eax
jz @f
mul [ebp+NTFS.sectors_per_cluster]
cmp eax, 8001h
jnc @f
push eax
shl eax, 9
stdcall kernel_alloc, eax
pop ecx
test eax, eax
jz @f
push ecx
shl ecx, 7
mov edi, eax
mov ebx, eax
xor eax, eax
rep stosd
mov eax, [ebp+NTFS.fileDataStart]
mul [ebp+NTFS.sectors_per_cluster]
mov [ebp+NTFS.ntfsLastRead], eax
pop ecx
call fs_write64_app
stdcall kernel_free, ebx
@@:
ret
ntfsSpaceAlloc: ntfsSpaceAlloc:
; find and mark block of free space in bitmap buffer ; find and mark block of free space in bitmap buffer
; in: ; in:
@ -3058,8 +3068,6 @@ ntfs_WriteFile:
mov ecx, [ebp+NTFS.frs_buffer] mov ecx, [ebp+NTFS.frs_buffer]
cmp word [ecx+baseRecordReuse], 0 cmp word [ecx+baseRecordReuse], 0
jnz ntfsUnsupported ; auxiliary record jnz ntfsUnsupported ; auxiliary record
cmp byte [ecx+hardLinkCounter], 1
jnz ntfsUnsupported ; file copying required
mov ecx, [ebp+NTFS.ntfs_attr_offs] mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1 cmp byte [ecx+nonResidentFlag], 1
jnz ntfsUnsupported ; resident $DATA jnz ntfsUnsupported ; resident $DATA
@ -3071,7 +3079,7 @@ ntfs_WriteFile:
.resizeAttribute: .resizeAttribute:
push ebx push ebx
call resizeAttribute call resizeAttribute
jc ntfsError jc ntfsErrorPop
mov eax, [ebp+NTFS.frs_buffer] mov eax, [ebp+NTFS.frs_buffer]
mov [ebp+NTFS.ntfs_cur_buf], eax mov [ebp+NTFS.ntfs_cur_buf], eax
call writeRecord ; file call writeRecord ; file
@ -3185,6 +3193,11 @@ ntfs_Delete:
jnc ntfsUnsupported jnc ntfsUnsupported
; delete index from the node ; delete index from the node
movzx edx, word [eax+indexAllocatedSize] movzx edx, word [eax+indexAllocatedSize]
mov ecx, [eax+fileRecordReference]
cmp [eax+edx+fileRecordReference], ecx
jnz @f
add dx, [eax+edx+indexAllocatedSize]
@@:
mov edi, [ebp+NTFS.cur_index_buf] mov edi, [ebp+NTFS.cur_index_buf]
cmp dword [edi], 'INDX' cmp dword [edi], 'INDX'
jz .indexRecord jz .indexRecord
@ -3231,8 +3244,6 @@ ntfs_Delete:
mov esi, [ebp+NTFS.frs_buffer] mov esi, [ebp+NTFS.frs_buffer]
cmp word [esi+baseRecordReuse], 0 cmp word [esi+baseRecordReuse], 0
jnz ntfsUnsupported ; auxiliary record jnz ntfsUnsupported ; auxiliary record
cmp byte [esi+hardLinkCounter], 2
jnc .writeFileRecord ; delete hard link
mov esi, [ebp+NTFS.ntfs_attr_offs] mov esi, [ebp+NTFS.ntfs_attr_offs]
cmp byte [esi+nonResidentFlag], 0 cmp byte [esi+nonResidentFlag], 0
jz .writeBitmapMFT jz .writeBitmapMFT
@ -3280,10 +3291,8 @@ ntfs_Delete:
xor edx, edx xor edx, edx
call fs_write64_sys call fs_write64_sys
mov esi, [ebp+NTFS.frs_buffer] mov esi, [ebp+NTFS.frs_buffer]
mov byte [esi+recordFlags], 0
.writeFileRecord:
dec byte [esi+hardLinkCounter]
mov [ebp+NTFS.ntfs_cur_buf], esi mov [ebp+NTFS.ntfs_cur_buf], esi
mov byte [esi+recordFlags], 0
call writeRecord call writeRecord
; write directory node ; write directory node
mov eax, [ebp+NTFS.nodeLastRead] mov eax, [ebp+NTFS.nodeLastRead]
@ -3295,6 +3304,107 @@ ntfs_Delete:
;---------------------------------------------------------------- ;----------------------------------------------------------------
ntfs_SetFileEnd: ntfs_SetFileEnd:
cmp byte [esi], 0
jnz @f
xor ebx, ebx
movi eax, ERROR_ACCESS_DENIED
ret
@@:
call ntfs_lock
stdcall ntfs_find_lfn, [esp+4]
jc ntfsNotFound
cmp [ebp+NTFS.ntfs_cur_iRecord], 16
jc ntfsDenied
bt dword [eax+fileFlags], 28
jc ntfsDenied
cmp [ebp+NTFS.ntfsFragmentCount], 1
jnz ntfsUnsupported ; record fragmented
; set file size in the directory
mov edi, [ebp+NTFS.cur_index_buf]
cmp dword [edi], 'INDX'
jz @f
mov esi, [ebp+NTFS.frs_buffer]
mov ecx, [esi+recordRealSize]
shr ecx, 2
rep movsd
mov esi, [ebp+NTFS.ntfs_attr_offs]
mov cl, [esi+attributeOffset]
sub esi, [ebp+NTFS.frs_buffer]
add eax, ecx
add eax, esi
@@:
mov ecx, [ebx+4]
mov edx, [ebx+8]
mov [eax+fileRealSize], ecx
mov [eax+fileRealSize+4], edx
mov eax, [ebp+NTFS.ntfsLastRead]
mov [ebp+NTFS.nodeLastRead], eax
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
jc ntfsFail
mov eax, ecx
mov ecx, [ebp+NTFS.frs_buffer]
cmp word [ecx+baseRecordReuse], 0
jnz ntfsUnsupported ; auxiliary record
mov ecx, [ebp+NTFS.ntfs_attr_offs]
cmp byte [ecx+nonResidentFlag], 1
jnz ntfsUnsupported ; resident $DATA
cmp [ecx+attributeRealSize+4], edx
jnz .resizeAttribute
cmp [ecx+attributeRealSize], eax
jnc .resizeAttribute
mov eax, [ecx+attributeRealSize]
mov ecx, [ebp+NTFS.sectors_per_cluster]
mov [ebp+NTFS.ntfs_cur_size], ecx
shl ecx, 9
div ecx
test edx, edx
jz .aligned
push edx
push ecx
mul [ebp+NTFS.sectors_per_cluster]
mov [ebp+NTFS.ntfs_cur_offs], eax
stdcall kernel_alloc, ecx
pop ecx
pop edi
sub ecx, edi
add edi, eax
mov [ebp+NTFS.ntfs_cur_buf], eax
push [ebp+NTFS.ntfsLastRead]
call ntfs_read_attr.continue
jc @f
xor eax, eax
rep stosb
push ebx
mov eax, [ebp+NTFS.ntfsLastRead]
mov ebx, [ebp+NTFS.ntfs_cur_buf]
mov ecx, [ebp+NTFS.sectors_per_cluster]
xor edx, edx
call fs_write64_app
pop ebx
@@:
pop [ebp+NTFS.ntfsLastRead]
stdcall kernel_free, [ebp+NTFS.ntfs_cur_buf]
.aligned:
mov eax, [ebx+4]
mov edx, [ebx+8]
.resizeAttribute:
call resizeAttribute
jc ntfsError
mov eax, [ebp+NTFS.frs_buffer]
mov [ebp+NTFS.ntfs_cur_buf], eax
call writeRecord ; file
mov eax, [ebp+NTFS.nodeLastRead]
mov [ebp+NTFS.ntfsLastRead], eax
mov eax, [ebp+NTFS.cur_index_buf]
mov [ebp+NTFS.ntfs_cur_buf], eax
call writeRecord ; directory
call ntfsSpaceClean
jmp ntfsDone
;----------------------------------------------------------------
ntfs_SetFileInfo: ntfs_SetFileInfo:
movi eax, ERROR_UNSUPPORTED_FS movi eax, ERROR_UNSUPPORTED_FS
ret ret
@ -3338,14 +3448,14 @@ ntfsDenied:
ntfsFail: ntfsFail:
push ERROR_FS_FAIL push ERROR_FS_FAIL
jmp ntfsOut jmp ntfsOut
ntfsNoMemory:
push ERROR_OUT_OF_MEMORY
jmp ntfsOut
ntfsDiskFull: ntfsDiskFull:
push ERROR_DISK_FULL push ERROR_DISK_FULL
jmp ntfsOut jmp ntfsOut
ntfsError: ntfsErrorPop2:
pop ebx pop ebx
ntfsErrorPop:
pop ebx
ntfsError:
push eax push eax
ntfsOut: ntfsOut:
call ntfs_unlock call ntfs_unlock