From 7abeb6e7e31670497bdafdacc84d287b10451c49 Mon Sep 17 00:00:00 2001 From: pathoswithin Date: Wed, 4 May 2016 17:36:09 +0000 Subject: [PATCH] NTFS: deletion remake git-svn-id: svn://kolibrios.org@6418 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/fs/ntfs.inc | 447 +++++++++++++++++++++------------------ 1 file changed, 247 insertions(+), 200 deletions(-) diff --git a/kernel/trunk/fs/ntfs.inc b/kernel/trunk/fs/ntfs.inc index 07a29d7a9..012f09733 100644 --- a/kernel/trunk/fs/ntfs.inc +++ b/kernel/trunk/fs/ntfs.inc @@ -119,7 +119,6 @@ mftBitmapLocation dd ? ; starting sector attr_size dq ? attr_offs dd ? attr_list dd ? -attr_iRecord dd ? attr_iBaseRecord dd ? cur_attr dd ? ; attribute type cur_iRecord dd ? ; number of fileRecord in MFT @@ -548,6 +547,7 @@ ntfs_read_attr: xor edx, edx div [ebp+NTFS.sectors_per_cluster] mov ebx, edx + mov [ebp+NTFS.fragmentCount], 0 ; eax = VCN, ebx = offset in sectors from beginning of cluster lea esi, [ebp+NTFS.mft_retrieval] sub esi, 8 @@ -581,6 +581,7 @@ ntfs_read_attr: shl edi, 9 add [ebp+NTFS.cur_read], edi add [ebp+NTFS.cur_buf], edi + inc [ebp+NTFS.fragmentCount] xor eax, eax xor ebx, ebx cmp [ebp+NTFS.cur_size], eax @@ -603,7 +604,6 @@ ntfs_read_attr: ; 1. Read file record. ; N.B. This will do recursive call of read_attr for $MFT::$Data. mov eax, [ebp+NTFS.cur_iRecord] - mov [ebp+NTFS.attr_iRecord], eax and [ebp+NTFS.attr_list], 0 or dword [ebp+NTFS.attr_size+4], -1 or [ebp+NTFS.attr_iBaseRecord], -1 @@ -618,7 +618,6 @@ ntfs_read_attr: jz @f mov eax, [eax+baseRecordReference] .beginfindattr: - mov [ebp+NTFS.attr_iRecord], eax call ntfs_read_file_record jc .errret jmp @f @@ -1023,7 +1022,6 @@ ntfs_read_file_record: shrd eax, edx, 9 shr edx, 9 jnz .errret - push [ebp+NTFS.attr_iRecord] push [ebp+NTFS.attr_iBaseRecord] push [ebp+NTFS.attr_offs] push [ebp+NTFS.attr_list] @@ -1055,7 +1053,6 @@ ntfs_read_file_record: pop [ebp+NTFS.attr_list] pop [ebp+NTFS.attr_offs] pop [ebp+NTFS.attr_iBaseRecord] - pop [ebp+NTFS.attr_iRecord] jc .ret cmp edx, [ebp+NTFS.frs_size] jnz .errret @@ -1197,6 +1194,7 @@ ntfs_find_lfn: jc .ret cmp [ebp+NTFS.cur_read], 0x20 jc .ret + push esi pushad mov esi, [ebp+NTFS.cur_index_buf] mov eax, [esi+indexRecordSize] @@ -1266,6 +1264,7 @@ ntfs_find_lfn: mov [ebp+NTFS.cur_index_size], edi stdcall kernel_free, edx popad + pop eax jmp .doit2 .notfound: @@ -1273,6 +1272,8 @@ ntfs_find_lfn: .err: popad stc +.ret2: + pop esi .ret: ret 4 @@ -1316,15 +1317,14 @@ ntfs_find_lfn: .found: cmp byte [edi], 0 - jz .done + jz @f cmp byte [edi], '/' - jz .next + jz @f pop edi pop esi jmp .scanloopcont -.done: -.next: +@@: pop esi pop esi mov eax, [esi] @@ -1334,11 +1334,13 @@ ntfs_find_lfn: popad inc esi cmp byte [esi-1], 0 - jnz .doit2 - cmp dword [esp+4], 0 - jz .ret - mov esi, [esp+4] - mov dword [esp+4], 0 + jnz @f + cmp dword [esp+8], 0 + jz .ret2 + mov esi, [esp+8] + mov dword [esp+8], 0 +@@: + pop eax jmp .doit2 ;---------------------------------------------------------------- @@ -2431,7 +2433,7 @@ ntfs_CreateFile: shl eax, 1 add eax, 42h mov [edi+indexRawSize], ax - mov eax, [ebp+NTFS.attr_iRecord] + mov eax, [ebp+NTFS.cur_iRecord] mov [edi+directoryRecordReference], eax mov eax, [ebp+NTFS.frs_buffer] mov eax, [eax+reuseCounter] @@ -2610,9 +2612,14 @@ ntfs_CreateFile: mov edi, [ebp+NTFS.frs_buffer] xor eax, eax rep stosd + mov esi, [ebp+NTFS.indexPointer] + mov eax, [ebp+NTFS.newRecord] + mov [esi+fileRecordReference], eax + rdtsc + mov [esi+fileReferenceReuse], ax mov edi, [ebp+NTFS.frs_buffer] ; record header - rdtsc + mov [edi+reuseCounter], ax mov [edi+2ah], ax mov eax, [ebp+NTFS.frs_size] mov [edi+recordAllocatedSize], eax @@ -2635,7 +2642,6 @@ ntfs_CreateFile: mov byte [edi+attributeOffset], 18h add edi, 48h ; $FileName - mov esi, [ebp+NTFS.indexPointer] mov byte [edi+attributeType], 30h mov byte [edi+attributeID], 1 mov byte [edi+attributeOffset], 18h @@ -2743,9 +2749,6 @@ ntfs_CreateFile: mov ecx, 1 xor edx, edx call fs_write64_sys - mov edi, [ebp+NTFS.indexPointer] - mov eax, [ebp+NTFS.newRecord] - mov [edi+fileRecordReference], eax ; 5. Write directory node mov ebx, [ebp+NTFS.cur_index_buf] mov edx, [ebp+NTFS.nodeLastRead] @@ -3630,9 +3633,9 @@ ntfs_WriteFile: ;---------------------------------------------------------------- ntfs_Delete: - xor ebx, ebx cmp byte [esi], 0 jnz @f + xor ebx, ebx movi eax, ERROR_ACCESS_DENIED ret @@ -3644,86 +3647,111 @@ ntfs_Delete: jc ntfsDenied cmp [ebp+NTFS.fragmentCount], 1 jnz ntfsUnsupported ; record fragmented - mov edx, [ebp+NTFS.cur_iRecord] - shr edx, 3 - cmp edx, [ebp+NTFS.mftBitmapSize] + mov ebx, [eax+directoryRecordReference] + mov [ebp+NTFS.newRecord], ebx + mov bx, [eax+fileReferenceReuse] + mov [ebp+NTFS.indexPointer], esi + mov eax, [ebp+NTFS.cur_iRecord] + shr eax, 3 + cmp eax, [ebp+NTFS.mftBitmapSize] jnc ntfsUnsupported - mov edx, [ebp+NTFS.secondIndexBuffer] - mov byte [edx], 0 - mov edx, [ebp+NTFS.LastRead] - mov [ebp+NTFS.nodeLastRead], edx +; examine file record + mov [ebp+NTFS.cur_attr], 0x80 ; file? + mov [ebp+NTFS.cur_offs], 0 + mov [ebp+NTFS.cur_size], 0 + call ntfs_read_attr + jnc @f + xor eax, eax + push ebx eax eax eax eax + mov [esp+12], esp + push eax + mov ebx, esp + mov [ebp+NTFS.cur_attr], 0x90 ; folder? + call ntfs_ReadFolder.doit + mov edx, [esp+12] + add esp, 20 + pop ebx + test eax, eax + jnz .ret + cmp edx, 2 + jnz ntfsDenied ; folder is not empty + mov [ebp+NTFS.cur_attr], 0xA0 + mov [ebp+NTFS.cur_offs], 0 + mov [ebp+NTFS.cur_size], 0 + call ntfs_read_attr.newAttribute + jc .deleteFileRecord +@@: + mov esi, [ebp+NTFS.frs_buffer] + cmp word [esi+baseRecordReuse], 0 + jnz ntfsUnsupported ; auxiliary record + cmp word [esi+reuseCounter], bx + jnz .backToIndex ; broken index + cmp byte [esi+recordFlags], 0 + jz .writeBitmapMFT ; record deleted + cmp byte [esi+hardLinkCounter], 3 + jnc ntfsUnsupported + mov esi, [ebp+NTFS.attr_offs] + cmp byte [esi+nonResidentFlag], 0 + jz .deleteFileRecord + movzx eax, byte [esi+dataRunsOffset] + add esi, eax + xor edi, edi + sub esp, 16 +@@: + call ntfs_decode_mcb_entry + jnc @f + cmp dword[esp+8], 0 + jz @b + add edi, [esp+8] + mov ebx, [esp] + call ntfsSpaceFree + jnc @b +@@: + add esp, 16 +.deleteFileRecord: + mov ebx, [ebp+NTFS.frs_buffer] + mov byte [ebx+recordFlags], 0 + mov edx, [ebp+NTFS.mftLastRead] + call writeRecord +.writeBitmapMFT: + mov eax, [ebp+NTFS.cur_iRecord] + mov ecx, eax + shr eax, 3 + and ecx, 7 + mov edi, [ebp+NTFS.mftBitmapBuffer] + btr [edi+eax], ecx + shr eax, 9 + mov ebx, eax + shl ebx, 9 + add eax, [ebp+NTFS.mftBitmapLocation] + add ebx, edi + mov ecx, 1 + xor edx, edx + call fs_write64_sys +.backToIndex: + mov eax, [ebp+NTFS.newRecord] + mov [ebp+NTFS.cur_iRecord], eax + mov esi, [ebp+NTFS.indexPointer] + stdcall ntfs_find_lfn.doit2, 0 + jc ntfsFail + mov ebx, [ebp+NTFS.secondIndexBuffer] + mov byte [ebx], 0 + mov ebx, [ebp+NTFS.LastRead] + mov [ebp+NTFS.nodeLastRead], ebx + xor ebx, ebx test byte [eax+indexFlags], 1 jz .deleteIndex ; no subnode - movzx edx, word [eax+indexAllocatedSize] mov edi, eax - mov eax, [eax+edx-8] - mov edx, [ebp+NTFS.cur_size] - push edx - cmp edx, [ebp+NTFS.cur_subnode_size] - jz @f - mul [ebp+NTFS.sectors_per_cluster] -@@: - mov [ebp+NTFS.cur_attr], 0xA0 - mov [ebp+NTFS.cur_offs], eax - push eax - mov ebx, [ebp+NTFS.secondIndexBuffer] - mov esi, ebx - mov [ebp+NTFS.cur_buf], ebx - call ntfs_read_attr.newAttribute - pop [ebp+NTFS.cur_offs] - pop eax + call .findSubindex jc ntfsFail - cmp dword [esi], 'INDX' - jnz ntfsFail - mov [ebp+NTFS.cur_size], eax - shl eax, 9 - call ntfs_restore_usa - jc ntfsFail - add esi, recordNode - cmp byte [esi+nonLeafFlag], 0 - jnz ntfsUnsupported ; non leaf node - add esi, [esi+indexOffset] - test byte [esi+indexFlags], 2 - jnz .deleteSubnode ; empty node - xor eax, eax -@@: - add esi, eax - mov ax, [esi+indexAllocatedSize] - test byte [esi+eax+indexFlags], 2 - jz @b movzx edx, word [edi+indexAllocatedSize] + test esi, esi + jz @f sub edx, eax sub edx, 8 +@@: + mov eax, edi mov ebx, esi - mov eax, edi - jmp @f - -.deleteSubnode: - mov esi, [ebp+NTFS.attr_offs] - add esi, [esi+sizeWithHeader] - cmp byte [esi], 0xB0 - jnz ntfsFail - movzx eax, byte [esi+attributeOffset] - add esi, eax - mov eax, [ebp+NTFS.cur_offs] - xor edx, edx - div [ebp+NTFS.cur_size] - mov edx, eax - shr eax, 3 - and edx, 7 - btr [esi+eax], edx - mov dx, [edi+indexAllocatedSize] - mov eax, edi - mov edi, [ebp+NTFS.secondIndexBuffer] - mov byte [edi], 0 - xor ebx, ebx - mov esi, [ebp+NTFS.cur_index_buf] - cmp dword [esi], 'INDX' - jnz @f - mov esi, [ebp+NTFS.frs_buffer] - mov ecx, [esi+recordRealSize] - shr ecx, 2 - rep movsd jmp @f .deleteIndex: @@ -3736,26 +3764,19 @@ ntfs_Delete: mov edi, [ebp+NTFS.cur_index_buf] cmp dword [edi], 'INDX' jz .indexRecord - mov esi, [ebp+NTFS.frs_buffer] ; indexRoot - mov ecx, [esi+recordRealSize] - shr ecx, 2 - rep movsd - mov esi, [ebp+NTFS.cur_index_buf] + sub eax, edi mov edi, [ebp+NTFS.indexRoot] - sub edi, [ebp+NTFS.frs_buffer] - add edi, esi sub [edi+sizeWithHeader], edx sub [edi+sizeWithoutHeader], edx - mov cl, [edi+attributeOffset] + movzx ecx, byte [edi+attributeOffset] add edi, ecx + add eax, edi sub [edi+rootNode+nodeRealSize], edx sub [edi+rootNode+nodeAllocatedSize], edx - sub eax, esi - add eax, edi - sub [esi+recordRealSize], edx - mov ecx, [esi+recordRealSize] - cmp [esi+recordAllocatedSize], ecx - jc ntfsUnsupported + mov edi, [ebp+NTFS.frs_buffer] + sub [edi+recordRealSize], edx + mov ecx, [edi+recordRealSize] + cmp [edi+recordAllocatedSize], ecx jmp @f .indexRecord: @@ -3763,10 +3784,9 @@ ntfs_Delete: sub [edi+nodeRealSize], edx mov ecx, [edi+nodeRealSize] cmp [edi+nodeAllocatedSize], ecx - jc ntfsUnsupported - add ecx, recordNode @@: - add ecx, [ebp+NTFS.cur_index_buf] + jc ntfsUnsupported + add ecx, edi sub ecx, eax mov esi, eax add esi, edx @@ -3786,121 +3806,148 @@ ntfs_Delete: cld @@: test ebx, ebx - jz @f + jz .done ; copy index from the subnode to replace deleted pointing index movzx ecx, word [ebx+indexAllocatedSize] mov edx, ecx + test byte [ebx+indexFlags], 1 + jz @f + sub ecx, 8 + movzx edi, word [ebx+edx+indexAllocatedSize] + add edi, edx + mov esi, [ebx+ecx] + mov [ebx+edi-8], esi + mov [ebx+indexAllocatedSize], cx +@@: shr ecx, 2 mov esi, ebx mov edi, eax rep movsd - mov edi, [ebp+NTFS.cur_index_buf] - xchg [ebp+NTFS.secondIndexBuffer], edi - mov [ebp+NTFS.cur_index_buf], edi add word [eax+indexAllocatedSize], 8 mov byte [eax+indexFlags], 1 - mov eax, [ebp+NTFS.LastRead] - xchg [ebp+NTFS.nodeLastRead], eax - mov [ebp+NTFS.rootLastRead], eax + mov edi, [ebp+NTFS.secondIndexBuffer] mov eax, ebx xor ebx, ebx jmp .indexRecord -.ret: - ret - -@@: ; examine file record - mov [ebp+NTFS.cur_attr], 0x80 ; file? - mov [ebp+NTFS.cur_offs], 0 - mov [ebp+NTFS.cur_size], 0 - call ntfs_read_attr - jnc @f - mov eax, [ebp+NTFS.cur_index_size] - shl eax, 9 - stdcall kernel_alloc, eax - test eax, eax - jz ntfsFail - push [ebp+NTFS.cur_index_buf] - push [ebp+NTFS.secondIndexBuffer] - push [ebp+NTFS.cur_index_size] - mov [ebp+NTFS.cur_index_buf], eax - mov [ebp+NTFS.secondIndexBuffer], eax - xor eax, eax - push eax eax eax eax - mov [esp+12], esp - push eax - mov ebx, esp - mov [ebp+NTFS.cur_attr], 0x90 ; folder? - call ntfs_ReadFolder.doit - push eax - stdcall kernel_free, [ebp+NTFS.cur_index_buf] - pop eax - mov edx, [esp+12] - add esp, 20 - pop [ebp+NTFS.cur_index_size] - pop [ebp+NTFS.secondIndexBuffer] - pop [ebp+NTFS.cur_index_buf] - test eax, eax - jnz .ret - cmp edx, 2 - jnz ntfsDenied ; folder is not empty - mov [ebp+NTFS.cur_attr], 0xA0 - mov [ebp+NTFS.cur_offs], 0 - mov [ebp+NTFS.cur_size], 0 - call ntfs_read_attr.newAttribute - jc .writeBitmapMFT -@@: - mov esi, [ebp+NTFS.frs_buffer] - cmp word [esi+baseRecordReuse], 0 - jnz ntfsUnsupported ; auxiliary record - mov esi, [ebp+NTFS.attr_offs] - cmp byte [esi+nonResidentFlag], 0 - jz .writeBitmapMFT - movzx eax, byte [esi+dataRunsOffset] - add esi, eax - xor edi, edi - sub esp, 16 -@@: - call ntfs_decode_mcb_entry - jnc @f - cmp dword[esp+8], 0 - jz @b - add edi, [esp+8] - mov ebx, [esp] - call ntfsSpaceFree - jnc @b -@@: - add esp, 16 -.writeBitmapMFT: ; "delete" file record - mov eax, [ebp+NTFS.cur_iRecord] - mov ecx, eax - shr eax, 3 - and ecx, 7 - mov edi, [ebp+NTFS.mftBitmapBuffer] - btr [edi+eax], ecx - shr eax, 9 - mov ebx, eax - shl ebx, 9 - add eax, [ebp+NTFS.mftBitmapLocation] - add ebx, edi - mov ecx, 1 - xor edx, edx - call fs_write64_sys +.done: mov ebx, [ebp+NTFS.frs_buffer] - mov byte [ebx+recordFlags], 0 - mov edx, [ebp+NTFS.mftLastRead] + mov edx, [ebp+NTFS.rootLastRead] call writeRecord -; write directory node mov ebx, [ebp+NTFS.cur_index_buf] + cmp dword [ebx], 'INDX' + jnz @f mov edx, [ebp+NTFS.nodeLastRead] call writeRecord +@@: mov ebx, [ebp+NTFS.secondIndexBuffer] cmp byte [ebx], 0 jz ntfsDone - mov edx, [ebp+NTFS.rootLastRead] + mov edx, [ebp+NTFS.LastRead] call writeRecord jmp ntfsDone +.findSubindex: +; in: eax -> index +; out: +; CF=1 -> error +; esi=0 -> subnode deleted +; esi -> replacement index +; eax = index effective size + movzx edx, word [eax+indexAllocatedSize] + mov eax, [eax+edx-8] + mov edx, [ebp+NTFS.cur_size] + push edx + cmp edx, [ebp+NTFS.cur_subnode_size] + jz @f + mul [ebp+NTFS.sectors_per_cluster] +@@: + mov [ebp+NTFS.cur_attr], 0xA0 + mov [ebp+NTFS.cur_offs], eax + push eax + mov ebx, [ebp+NTFS.secondIndexBuffer] + mov esi, ebx + mov [ebp+NTFS.cur_buf], ebx + call ntfs_read_attr.newAttribute + pop [ebp+NTFS.cur_offs] + pop eax + jc .ret + cmp dword [esi], 'INDX' + stc + jnz .ret + mov [ebp+NTFS.cur_size], eax + shl eax, 9 + call ntfs_restore_usa + jc .ret + add esi, recordNode + add esi, [esi+indexOffset] + test byte [esi+indexFlags], 2 + jnz .emptyNode + cmp [ebp+NTFS.fragmentCount], 1 + stc + jnz .ret ; record fragmented + xor eax, eax +@@: + add esi, eax + mov ax, [esi+indexAllocatedSize] + test byte [esi+eax+indexFlags], 2 + jz @b + test byte [esi+indexFlags], 1 + jz .ret + add eax, esi + push esi + push [ebp+NTFS.cur_offs] + call .findSubindex + pop [ebp+NTFS.cur_offs] + pop edx + jc .ret + test esi, esi + jnz .ret + mov esi, edx + mov ebx, [ebp+NTFS.secondIndexBuffer] + mov [ebp+NTFS.cur_buf], ebx + push [ebp+NTFS.cur_size] + call ntfs_read_attr.continue + pop eax + jc .ret + shl eax, 9 + call ntfs_restore_usa + jc .ret + movzx eax, word [esi+indexAllocatedSize] + sub eax, 8 +.ret: + ret + +.emptyNode: + test byte [esi+indexFlags], 1 + jz @f + mov eax, esi + push [ebp+NTFS.cur_offs] + call .findSubindex + pop [ebp+NTFS.cur_offs] + jc .ret + test esi, esi + jnz .ret +@@: ; delete node + mov esi, [ebp+NTFS.attr_offs] + add esi, [esi+sizeWithHeader] + cmp byte [esi], 0xB0 + stc + jnz .ret + movzx eax, byte [esi+attributeOffset] + add esi, eax + mov eax, [ebp+NTFS.cur_offs] + xor edx, edx + div [ebp+NTFS.cur_size] + mov edx, eax + shr eax, 3 + and edx, 7 + btr [esi+eax], edx + mov esi, [ebp+NTFS.secondIndexBuffer] + mov byte [esi], 0 + xor esi, esi + ret + ;---------------------------------------------------------------- ntfs_SetFileEnd: cmp byte [esi], 0