193 files changed, 80411 insertions, 44563 deletions
diff --git a/libntfs-3g/inode.c b/libntfs-3g/inode.c index 6f3fa06..a4a0134 100755 --- a/libntfs-3g/inode.c +++ b/libntfs-3g/inode.c @@ -437,13 +437,12 @@ static int idata_cache_compare(const struct CACHED_GENERIC *cached, void ntfs_inode_invalidate(ntfs_volume *vol, const MFT_REF mref) { struct CACHED_NIDATA item; - int count; item.inum = MREF(mref); item.ni = (ntfs_inode*)NULL; item.pathname = (const char*)NULL; item.varsize = 0; - count = ntfs_invalidate_cache(vol->nidata_cache, + ntfs_invalidate_cache(vol->nidata_cache, GENERIC(&item),idata_cache_compare,CACHE_FREE); } @@ -481,6 +480,9 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) } else { ni = ntfs_inode_real_open(vol, mref); } + if (!ni) { + debug_double_inode(item.inum, 0); + } #else ni = ntfs_inode_real_open(vol, mref); #endif @@ -571,6 +573,9 @@ int ntfs_inode_close(ntfs_inode *ni) ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref) { u64 mft_no = MREF_LE(mref); + VCN extent_vcn; + runlist_element *rl; + ntfs_volume *vol; ntfs_inode *ni = NULL; ntfs_inode **extent_nis; int i; @@ -585,6 +590,37 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref) (unsigned long long)mft_no, (unsigned long long)base_ni->mft_no); + if (!base_ni->mft_no) { + /* + * When getting extents of MFT, we must be sure + * they are in the MFT part which has already + * been mapped, otherwise we fall into an endless + * recursion. + * Situations have been met where extents locations + * are described in themselves. + * This is a severe error which chkdsk cannot fix. + */ + vol = base_ni->vol; + extent_vcn = mft_no << vol->mft_record_size_bits + >> vol->cluster_size_bits; + rl = vol->mft_na->rl; + if (rl) { + while (rl->length + && ((rl->vcn + rl->length) <= extent_vcn)) + rl++; + } + if (!rl || (rl->lcn < 0)) { + ntfs_log_error("MFT is corrupt, cannot read" + " its unmapped extent record %lld\n", + (long long)mft_no); + ntfs_log_error("Note : chkdsk cannot fix this," + " try ntfsfix\n"); + errno = EIO; + ni = (ntfs_inode*)NULL; + goto out; + } + } + /* Is the extent inode already open and attached to the base inode? */ if (base_ni->nr_extents > 0) { extent_nis = base_ni->extent_nis; @@ -842,6 +878,12 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni) else { fnx->allocated_size = cpu_to_sle64(ni->allocated_size); fnx->data_size = cpu_to_sle64(ni->data_size); + /* + * The file name record has also to be fixed if some + * attribute update implied the unnamed data to be + * made non-resident + */ + fn->allocated_size = fnx->allocated_size; } /* update or clear the reparse tag in the index */ fnx->reparse_point_tag = reparse_tag; |