From 54422f2f5adb1556ec393ed5c19120fa07915cbc Mon Sep 17 00:00:00 2001 From: pathoswithin Date: Thu, 21 Apr 2016 17:41:56 +0000 Subject: [PATCH] NTFS: cleaning and fixing git-svn-id: svn://kolibrios.org@6405 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/fs/ntfs.inc | 390 +++++++++++++++++---------------------- 1 file changed, 167 insertions(+), 223 deletions(-) diff --git a/kernel/trunk/fs/ntfs.inc b/kernel/trunk/fs/ntfs.inc index 6d183c38fd..c1acdf312c 100644 --- a/kernel/trunk/fs/ntfs.inc +++ b/kernel/trunk/fs/ntfs.inc @@ -102,10 +102,8 @@ mft_cluster dd ? ; location mftmirr_cluster dd ? ; location frs_size dd ? ; in bytes frs_buffer dd ? ; MFT fileRecord buffer -mft_retrieval dd ? -mft_retrieval_size dd ? -mft_retrieval_alloc dd ? mft_retrieval_end dd ? +mftSize dd ? ; in sectors cur_index_size dd ? ; in sectors cur_index_buf dd ? ; index node buffer secondIndexBuffer dd ? @@ -118,39 +116,39 @@ mftBitmapBuffer dd ? ; one cluster mftBitmapSize dd ? ; bytes readen 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 cur_offs dd ? ; attribute VCN in sectors cur_size dd ? ; max sectors to read cur_buf dd ? cur_read dd ? ; bytes readen +cur_tail dd ? +cur_subnode_size dd ? LastRead dd ? ; last readen block of sectors rootLastRead dd ? nodeLastRead dd ? indexRoot dd ? -pointingIndex dd ? +indexPointer dd ? newRecord dd ? fileDataStart dd ? ; starting cluster fileDataSize dd ? ; in clusters fileDataBuffer dd ? fileRealSize dd ? ; in bytes -indexOffset dd ? fragmentCount db ? bCanContinue db ? bFolder db ? bWriteAttr db ? ; Warning: Don't forget to turn off!!! -cur_subnode_size dd ? -attr_iRecord dd ? -attr_iBaseRecord dd ? -attr_offs dd ? -attr_list dd ? -attr_size dq ? -cur_tail dd ? - -attrlist_buf rb 0x400 -attrlist_mft_buf rb 0x400 -bitmap_buf rb 0x400 +align 256 +mft_retrieval rb 768 +attrlist_buf rb 1024 +attrlist_mft_buf rb 1024 +bitmap_buf rb 1024 ends ; NTFS external functions @@ -286,10 +284,8 @@ ntfs_create_partition: xor eax, eax jmp .exit -; By given bootsector, initialize some NTFS variables -.ntfs_setup: - movi eax, sizeof.NTFS - call malloc +.ntfs_setup: ; By given bootsector, initialize some NTFS variables + stdcall kernel_alloc, 1000h test eax, eax jz .exit mov ecx, dword [ebp+PARTITION.FirstSector] @@ -335,7 +331,10 @@ ntfs_create_partition: ; read $MFT disposition mov eax, [ebp+NTFS.mft_cluster] mul [ebp+NTFS.sectors_per_cluster] - call ntfs_read_frs_sector + mov ecx, [ebp+NTFS.frs_size] + shr ecx, 9 + mov ebx, [ebp+NTFS.frs_buffer] + call fs_read64_sys test eax, eax jnz .usemirr cmp dword [ebx], 'FILE' @@ -345,66 +344,65 @@ ntfs_create_partition: .usemirr: mov eax, [ebp+NTFS.mftmirr_cluster] mul [ebp+NTFS.sectors_per_cluster] - call ntfs_read_frs_sector + mov ecx, [ebp+NTFS.frs_size] + shr ecx, 9 + mov ebx, [ebp+NTFS.frs_buffer] + call fs_read64_sys test eax, eax jnz .fail_free_frs cmp dword [ebx], 'FILE' jnz .fail_free_frs call ntfs_restore_usa_frs jc .fail_free_frs -.mftok: -; read $MFT table retrieval information -; start with one page, increase if not enough (when MFT too fragmented) - push ebx - stdcall kernel_alloc, 0x1000 - pop ebx - test eax, eax - jz .fail_free_frs - mov [ebp+NTFS.mft_retrieval], eax - and [ebp+NTFS.mft_retrieval_size], 0 - mov [ebp+NTFS.mft_retrieval_alloc], 0x1000/8 -; $MFT base record must contain unnamed non-resident $DATA attribute - movzx eax, word [ebx+14h] +.mftok: ; prepare $MFT retrieval information +; search for unnamed non-resident $DATA attribute + movzx eax, word [ebx+attributeOffset] add eax, ebx .scandata: cmp dword [eax], -1 - jz .fail_free_mft + jz .fail_free_frs cmp dword [eax], 0x80 jnz @f - cmp byte [eax+9], 0 + cmp byte [eax+nameLength], 0 jz .founddata @@: - add eax, [eax+4] + add eax, [eax+sizeWithHeader] jmp .scandata .founddata: - cmp byte [eax+8], 0 - jz .fail_free_mft -; load first portion of $DATA attribute retrieval information - mov edx, [eax+0x18] - mov [ebp+NTFS.mft_retrieval_end], edx - mov esi, eax - movzx eax, word [eax+0x20] + cmp byte [eax+nonResidentFlag], 0 + jz .fail_free_frs + movzx esi, word [eax+dataRunsOffset] add esi, eax + mov edx, [eax+attributeAllocatedSize+4] + mov eax, [eax+attributeAllocatedSize] + shrd eax, edx, 9 + mov [ebp+NTFS.mftSize], eax sub esp, 10h -.scanmcb: + lea ecx, [ebp+NTFS.mft_retrieval] + xor edx, edx +.scanmcb: ; load descriptions of fragments call ntfs_decode_mcb_entry jnc .scanmcbend - call .get_mft_retrieval_ptr - mov edx, [esp] ; block length - mov [eax], edx - mov edx, [esp+8] ; block addr (relative) - mov [eax+4], edx - inc [ebp+NTFS.mft_retrieval_size] + mov eax, [esp] ; block length + mov [ecx], eax + add edx, [esp+8] ; block addr + mov [ecx+4], edx + add ecx, 8 jmp .scanmcb .scanmcbend: add esp, 10h -; there may be other portions of $DATA attribute in auxiliary records; -; if they will be needed, they will be loaded later + lea eax, [ebp+NTFS.attrlist_buf] + cmp eax, ecx + jc @f + mov eax, ecx +@@: + mov [ebp+NTFS.mft_retrieval_end], eax +; allocate index buffers stdcall kernel_alloc, 2000h test eax, eax - jz .fail_free_mft + jz .fail_free_frs mov [ebp+NTFS.cur_index_buf], eax add eax, 1000h mov [ebp+NTFS.secondIndexBuffer], eax @@ -485,66 +483,38 @@ ntfs_create_partition: ret .failFreeBitmapMFT: - stdcall kernel_free, [ebx+NTFS.mftBitmapBuffer] + stdcall kernel_free, [ebp+NTFS.mftBitmapBuffer] .failFreeBitmap: - stdcall kernel_free, [ebx+NTFS.BitmapBuffer] + stdcall kernel_free, [ebp+NTFS.BitmapBuffer] .failFreeIndex: - stdcall kernel_free, [ebp+NTFS.cur_index_buf] - stdcall kernel_free, [ebp+NTFS.secondIndexBuffer] -.fail_free_mft: - stdcall kernel_free, [ebp+NTFS.mft_retrieval] + mov eax, [ebp+NTFS.cur_index_buf] + cmp eax, [ebp+NTFS.secondIndexBuffer] + jc @f + mov eax, [ebp+NTFS.secondIndexBuffer] +@@: + stdcall kernel_free, eax .fail_free_frs: stdcall kernel_free, [ebp+NTFS.frs_buffer] .fail_free: - mov eax, ebp - call free + stdcall kernel_free, ebp xor eax, eax jmp .pop_exit -.get_mft_retrieval_ptr: - pushad - mov eax, [ebp+NTFS.mft_retrieval_size] - cmp eax, [ebp+NTFS.mft_retrieval_alloc] - jnz .ok - add eax, 0x1000/8 - mov [ebp+NTFS.mft_retrieval_alloc], eax - shl eax, 3 - stdcall kernel_alloc, eax - test eax, eax - jnz @f - popad - add esp, 14h - jmp .fail_free_mft - -@@: - mov esi, [ebp+NTFS.mft_retrieval] - mov edi, eax - mov ecx, [ebp+NTFS.mft_retrieval_size] - add ecx, ecx - rep movsd - push [ebp+NTFS.mft_retrieval] - mov [ebp+NTFS.mft_retrieval], eax - call kernel_free - mov eax, [ebp+NTFS.mft_retrieval_size] -.ok: - shl eax, 3 - add eax, [ebp+NTFS.mft_retrieval] - mov [esp+28], eax - popad - ret - ntfs_free: push ebx mov ebx, eax stdcall kernel_free, [ebx+NTFS.frs_buffer] - stdcall kernel_free, [ebx+NTFS.mft_retrieval] - stdcall kernel_free, [ebx+NTFS.cur_index_buf] - stdcall kernel_free, [ebp+NTFS.secondIndexBuffer] stdcall kernel_free, [ebx+NTFS.mftBitmapBuffer] stdcall kernel_free, [ebx+NTFS.BitmapBuffer] - mov eax, ebx + mov eax, [ebx+NTFS.cur_index_buf] + cmp eax, [ebx+NTFS.secondIndexBuffer] + jc @f + mov eax, [ebx+NTFS.secondIndexBuffer] +@@: + stdcall kernel_free, eax + stdcall kernel_free, ebx pop ebx - jmp free + ret ntfs_lock: lea ecx, [ebp+NTFS.Lock] @@ -554,29 +524,6 @@ ntfs_unlock: lea ecx, [ebp+NTFS.Lock] jmp mutex_unlock -ntfs_read_frs_sector: - push ecx - mov ebx, [ebp+NTFS.frs_buffer] - push ebx - mov ecx, [ebp+NTFS.frs_size] - shr ecx, 9 - push ecx - mov ecx, eax -@@: - mov eax, ecx - call fs_read32_sys - test eax, eax - jnz .fail - add ebx, 0x200 - inc ecx - dec dword [esp] - jnz @b - pop eax -.fail: - pop ebx - pop ecx - ret - ntfs_read_attr: ; [ebp+NTFS.bWriteAttr]=1 -> write attribute ; in: @@ -595,86 +542,54 @@ ntfs_read_attr: jnz .nomft cmp [ebp+NTFS.cur_attr], 0x80 jnz .nomft - mov eax, [ebp+NTFS.mft_retrieval_end] - inc eax - mul [ebp+NTFS.sectors_per_cluster] - cmp eax, [ebp+NTFS.cur_offs] - jbe .nomft ; precalculated part of $Mft $DATA - mov esi, [ebp+NTFS.mft_retrieval] mov eax, [ebp+NTFS.cur_offs] xor edx, edx div [ebp+NTFS.sectors_per_cluster] -; eax = VCN, edx = offset in sectors from beginning of cluster - xor ecx, ecx ; ecx will contain LCN + mov ebx, edx +; eax = VCN, ebx = offset in sectors from beginning of cluster + lea esi, [ebp+NTFS.mft_retrieval] + sub esi, 8 .mftscan: - add ecx, [esi+4] - sub eax, [esi] - jb @f add esi, 8 - push eax - mov eax, [ebp+NTFS.mft_retrieval_end] - shl eax, 3 - add eax, [ebp+NTFS.mft_retrieval] - cmp eax, esi - pop eax - jnz .mftscan - jmp .nomft - -@@: - push ecx + cmp esi, [ebp+NTFS.mft_retrieval_end] + jz .nomft + mov ecx, [esi+4] + sub eax, [esi] + jnc .mftscan add ecx, eax add ecx, [esi] - push eax - push edx - mov eax, [ebp+NTFS.sectors_per_cluster] - mul ecx -; eax = sector on partition - pop edx - add eax, edx + neg eax + mul [ebp+NTFS.sectors_per_cluster] + xchg eax, ecx + mul [ebp+NTFS.sectors_per_cluster] + sub ecx, ebx + add eax, ebx mov ebx, [ebp+NTFS.cur_buf] - pop ecx - neg ecx - imul ecx, [ebp+NTFS.sectors_per_cluster] - sub ecx, edx - mov [ebp+NTFS.LastRead], eax cmp ecx, [ebp+NTFS.cur_size] jb @f mov ecx, [ebp+NTFS.cur_size] @@: -; ecx = number of sequential sectors to read - push eax - call fs_read32_sys - pop edx + mov [ebp+NTFS.LastRead], eax + mov edi, ecx + call fs_read64_sys test eax, eax - jnz .errread - add [ebp+NTFS.cur_read], 0x200 - dec [ebp+NTFS.cur_size] - inc [ebp+NTFS.cur_offs] - add ebx, 0x200 - mov [ebp+NTFS.cur_buf], ebx - lea eax, [edx+1] - loop @b - pop ecx + jnz .errret + sub [ebp+NTFS.cur_size], edi + add [ebp+NTFS.cur_offs], edi + shl edi, 9 + add [ebp+NTFS.cur_read], edi + add [ebp+NTFS.cur_buf], edi xor eax, eax - xor edx, edx + xor ebx, ebx cmp [ebp+NTFS.cur_size], eax jz @f - add esi, 8 - push eax - mov eax, [ebp+NTFS.mft_retrieval_end] - shl eax, 3 - add eax, [ebp+NTFS.mft_retrieval] - cmp eax, esi - pop eax - jz .nomft jmp .mftscan .errret2_pop: xor eax, eax .errret_pop: pop ecx -.errread: pop ecx .errret: mov [esp+28], eax @@ -769,7 +684,6 @@ ntfs_read_attr: mov ecx, [ebp+NTFS.attr_list] test ecx, ecx jnz .lookattr -.ret_is_attr: and dword [esp+28], 0 cmp [ebp+NTFS.attr_offs], 1 ; define CF .ret: @@ -1024,14 +938,13 @@ ntfs_read_attr: and eax, 0x1FF mov [ebp+NTFS.cur_tail], eax @@: - cmp [ebp+NTFS.cur_size], 0 - jz .okret mov eax, [ebp+NTFS.cur_offs] xor edx, edx div [ebp+NTFS.sectors_per_cluster] sub eax, [ecx+firstVCN] jb .okret -; eax = cluster, edx = starting sector + mov ebx, edx +; eax = starting cluster, ebx = sector in the cluster cmp [ebp+NTFS.cur_attr], 0x80 jnz .sys cmp [ebp+NTFS.cur_iRecord], 0 @@ -1056,25 +969,23 @@ ntfs_read_attr: add edi, [esp+8] sub eax, [esp] jae .readloop - push ecx - push eax - add eax, [esp+8] - add eax, edi - imul eax, [ebp+NTFS.sectors_per_cluster] - add eax, edx - pop ecx - neg ecx - imul ecx, [ebp+NTFS.sectors_per_cluster] - sub ecx, edx + mov ecx, edi + add ecx, eax + add ecx, [esp] + neg eax + mul [ebp+NTFS.sectors_per_cluster] + xchg eax, ecx + mul [ebp+NTFS.sectors_per_cluster] + sub ecx, ebx + add eax, ebx + mov ebx, [ebp+NTFS.cur_buf] cmp ecx, [ebp+NTFS.cur_size] jb @f mov ecx, [ebp+NTFS.cur_size] @@: - mov ebx, [ebp+NTFS.cur_buf] mov [ebp+NTFS.LastRead], eax push ecx - xor edx, edx - call dword[esp+18h] + call dword[esp+14h] pop ecx test eax, eax jnz .errread2 @@ -1084,9 +995,8 @@ ntfs_read_attr: add [ebp+NTFS.cur_read], ecx add [ebp+NTFS.cur_buf], ecx inc [ebp+NTFS.fragmentCount] - pop ecx xor eax, eax - xor edx, edx + xor ebx, ebx cmp [ebp+NTFS.cur_size], 0 jnz .readloop add esp, 14h @@ -1100,7 +1010,6 @@ ntfs_read_attr: ret .errread2: - pop ecx add esp, 14h stc ret @@ -1270,8 +1179,13 @@ unichar_toupper: ntfs_find_lfn: ; in: [esi]+[esp+4] = name ; out: -; [ebp+NTFS.cur_iRecord] = number of MFT fileRecord -; eax -> index in the parent index node +; [ebp+NTFS.cur_iRecord] = target fileRecord +; eax -> index in the target node +; [ebp+NTFS.indexPointer] -> index, that points the target subnode +; [ebp+NTFS.indexRoot] -> attribute +; [ebp+NTFS.cur_size] = index record size in sectors +; [ebp+NTFS.cur_subnode_size] = index record size in clusters or sectors +; [ebp+NTFS.rootLastRead] = directory fileRecord sector ; CF=1 -> file not found, eax=0 -> error mov [ebp+NTFS.cur_iRecord], 5 ; start from root directory .doit2: @@ -1344,14 +1258,16 @@ ntfs_find_lfn: stdcall kernel_alloc, eax test eax, eax jz .err - push [ebp+NTFS.secondIndexBuffer] - push [ebp+NTFS.cur_index_buf] + mov edx, [ebp+NTFS.cur_index_buf] + cmp edx, [ebp+NTFS.secondIndexBuffer] + jc @f + mov edx, [ebp+NTFS.secondIndexBuffer] +@@: mov [ebp+NTFS.cur_index_buf], eax add eax, [esi+indexRecordSize] mov [ebp+NTFS.secondIndexBuffer], eax mov [ebp+NTFS.cur_index_size], edi - call kernel_free - call kernel_free + stdcall kernel_free, edx popad jmp .doit2 @@ -1378,7 +1294,7 @@ ntfs_find_lfn: jz @f mul [ebp+NTFS.sectors_per_cluster] @@: - mov [ebp+NTFS.pointingIndex], esi + mov [ebp+NTFS.indexPointer], esi mov esi, [ebp+NTFS.cur_index_buf] xchg [ebp+NTFS.secondIndexBuffer], esi mov [ebp+NTFS.cur_index_buf], esi @@ -1645,14 +1561,16 @@ ntfs_ReadFolder: stdcall kernel_alloc, eax test eax, eax jz .err - push [ebp+NTFS.secondIndexBuffer] - push [ebp+NTFS.cur_index_buf] + mov edx, [ebp+NTFS.cur_index_buf] + cmp edx, [ebp+NTFS.secondIndexBuffer] + jc @f + mov edx, [ebp+NTFS.secondIndexBuffer] +@@: mov [ebp+NTFS.cur_index_buf], eax add eax, [esi+indexRecordSize] mov [ebp+NTFS.secondIndexBuffer], eax mov [ebp+NTFS.cur_index_size], edi - call kernel_free - call kernel_free + stdcall kernel_free, edx popad jmp .doit @@ -2283,7 +2201,7 @@ ntfs_CreateFile: add ecx, edi add [ecx+rootNode+nodeRealSize], eax add [ecx+rootNode+nodeAllocatedSize], eax - add ecx, [ebp+NTFS.pointingIndex] + add ecx, [ebp+NTFS.indexPointer] sub ecx, [ebp+NTFS.secondIndexBuffer] mov edi, esi sub esi, eax @@ -2427,7 +2345,7 @@ ntfs_CreateFile: mul ecx mov [edi+fileAllocatedSize], eax pop ecx - mov [ebp+NTFS.indexOffset], edi + mov [ebp+NTFS.indexPointer], edi mov [edi+fileNameLength], cl add edi, fileName @@: ; record filename @@ -2440,7 +2358,7 @@ ntfs_CreateFile: mov [ebp+NTFS.nodeLastRead], eax cmp [ebp+NTFS.bFolder], 0 jz @f - mov edi, [ebp+NTFS.indexOffset] + mov edi, [ebp+NTFS.indexPointer] bts dword [edi+fileFlags], 28 jmp .mftBitmap @@ -2484,22 +2402,25 @@ ntfs_CreateFile: mov [ebp+NTFS.cur_iRecord], 0 mov [ebp+NTFS.cur_attr], 0x80 mov [ebp+NTFS.cur_offs], eax - mov [ebp+NTFS.cur_size], 1 + push eax + mov [ebp+NTFS.cur_size], 0 mov eax, [ebp+NTFS.frs_buffer] mov [ebp+NTFS.cur_buf], eax call ntfs_read_attr - cmp [ebp+NTFS.cur_read], 0 - jz .extendMFT + pop eax + jc ntfsFail + cmp eax, [ebp+NTFS.mftSize] + jnc .extendMFT jmp .mftRecord .extendBitmapMFT: mov eax, [ebp+NTFS.sectors_per_cluster] + mov [ebp+NTFS.cur_offs], eax shl eax, 9 cmp [ebp+NTFS.mftBitmapSize], eax jnc ntfsUnsupported mov [ebp+NTFS.cur_iRecord], 0 mov [ebp+NTFS.cur_attr], 0xB0 - mov [ebp+NTFS.cur_offs], 0 mov [ebp+NTFS.cur_size], 0 call ntfs_read_attr jc ntfsFail @@ -2520,6 +2441,7 @@ ntfs_CreateFile: mov dword [edi], 1 mov dword [edi+4], 0 mov [ebp+NTFS.cur_attr], 0x80 + mov [ebp+NTFS.cur_offs], 0 call ntfs_read_attr.newAttribute jc ntfsFail mov [ebp+NTFS.mftBitmapSize], ecx @@ -2547,6 +2469,27 @@ ntfs_CreateFile: movzx ecx, word [ebx+updateSequenceSize] dec ecx call fs_write64_sys ; $MFTMirr +; update $MFT retrieval information + mov edi, [ebp+NTFS.mft_retrieval_end] + mov eax, [edi-4] + add eax, [edi-8] + mov edx, [ebp+NTFS.fileDataSize] + cmp eax, [ebp+NTFS.fileDataStart] + jnz .newFragment + add [edi-8], edx + jmp @f +.newFragment: + lea eax, [ebp+NTFS.attrlist_buf] + cmp eax, edi + jz @f + mov [edi], edx + mov eax, [ebp+NTFS.fileDataStart] + mov [edi+4], eax + add [ebp+NTFS.mft_retrieval_end], 8 +@@: + mov eax, [ebp+NTFS.fileDataSize] + mul [ebp+NTFS.sectors_per_cluster] + add [ebp+NTFS.mftSize], eax call ntfsSpaceClean pop [ebp+NTFS.fileDataSize] pop [ebp+NTFS.fileDataStart] @@ -2581,7 +2524,7 @@ ntfs_CreateFile: mov byte [edi+attributeOffset], 18h add edi, 48h ; $FileName - mov esi, [ebp+NTFS.indexOffset] + mov esi, [ebp+NTFS.indexPointer] mov byte [edi+attributeType], 30h mov byte [edi+attributeID], 1 mov byte [edi+attributeOffset], 18h @@ -2605,7 +2548,7 @@ ntfs_CreateFile: mov eax, [ebp+NTFS.fileDataSize] test eax, eax jz .resident - mov esi, [ebp+NTFS.indexOffset] + mov esi, [ebp+NTFS.indexPointer] dec eax mov [edi+lastVCN], eax mov byte [edi+nonResidentFlag], 1 @@ -2689,7 +2632,7 @@ ntfs_CreateFile: mov ecx, 1 xor edx, edx call fs_write64_sys - mov edi, [ebp+NTFS.indexOffset] + mov edi, [ebp+NTFS.indexPointer] mov eax, [ebp+NTFS.newRecord] mov [edi+fileRecordReference], eax ; 5. Write directory node @@ -3901,6 +3844,7 @@ ntfs_SetFileEnd: stdcall kernel_alloc, ecx pop ecx pop edi + mov esi, eax sub ecx, edi add edi, eax mov [ebp+NTFS.cur_buf], eax @@ -3911,14 +3855,14 @@ ntfs_SetFileEnd: rep stosb push ebx mov eax, [ebp+NTFS.LastRead] - mov ebx, [ebp+NTFS.cur_buf] + mov ebx, esi mov ecx, [ebp+NTFS.sectors_per_cluster] xor edx, edx call fs_write64_app pop ebx @@: pop [ebp+NTFS.LastRead] - stdcall kernel_free, [ebp+NTFS.cur_buf] + stdcall kernel_free, esi .aligned: mov eax, [ebx+4] mov edx, [ebx+8]