*/
#include <linux/smp_lock.h>
-#include "ntfs.h"
+#include <linux/buffer_head.h>
+
#include "dir.h"
+#include "aops.h"
+#include "attrib.h"
+#include "mft.h"
+#include "debug.h"
+#include "ntfs.h"
/**
* The little endian Unicode string $I30 as a global constant.
ntfs_error(sb, "No index allocation attribute but index entry "
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug.", dir_ni->mft_no);
- err = -EIO;
goto err_out;
}
/* Get the starting vcn of the index_block holding the child node. */
if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
"inode 0x%lx or driver bug.", dir_ni->mft_no);
- err = -EIO;
+ goto unm_err_out;
+ }
+ /* Catch multi sector transfer fixup errors. */
+ if (unlikely(!ntfs_is_indx_record(ia->magic))) {
+ ntfs_error(sb, "Directory index record with vcn 0x%llx is "
+ "corrupt. Corrupt inode 0x%lx. Run chkdsk.",
+ (unsigned long long)vcn, dir_ni->mft_no);
goto unm_err_out;
}
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
"bug.", (unsigned long long)
sle64_to_cpu(ia->index_block_vcn),
(unsigned long long)vcn, dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
(unsigned long long)vcn, dir_ni->mft_no,
le32_to_cpu(ia->index.allocated_size) + 0x18,
dir_ni->itype.index.block_size);
- err = -EIO;
goto unm_err_out;
}
index_end = (u8*)ia + dir_ni->itype.index.block_size;
"Cannot access! This is probably a bug in the "
"driver.", (unsigned long long)vcn,
dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory "
"inode 0x%lx exceeds maximum size.",
(unsigned long long)vcn, dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/* The first index entry. */
ntfs_error(sb, "Index entry out of bounds in "
"directory inode 0x%lx.",
dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/*
ntfs_error(sb, "Index entry with child node found in "
"a leaf node in directory inode 0x%lx.",
dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/* Child node present, descend into it. */
}
ntfs_error(sb, "Negative child node vcn in directory inode "
"0x%lx.", dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/*
unlock_page(page);
ntfs_unmap_page(page);
err_out:
+ if (!err)
+ err = -EIO;
if (ctx)
ntfs_attr_put_search_ctx(ctx);
if (m)
}
return ERR_MREF(err);
dir_err_out:
- ntfs_error(sb, "Corrupt directory. Aborting lookup.");
- err = -EIO;
+ ntfs_error(sb, "Corrupt directory. Aborting lookup.");
goto err_out;
}
ntfs_error(sb, "No index allocation attribute but index entry "
"requires one. Directory inode 0x%lx is "
"corrupt or driver bug.", dir_ni->mft_no);
- err = -EIO;
goto err_out;
}
/* Get the starting vcn of the index_block holding the child node. */
if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) {
ntfs_error(sb, "Out of bounds check failed. Corrupt directory "
"inode 0x%lx or driver bug.", dir_ni->mft_no);
- err = -EIO;
+ goto unm_err_out;
+ }
+ /* Catch multi sector transfer fixup errors. */
+ if (unlikely(!ntfs_is_indx_record(ia->magic))) {
+ ntfs_error(sb, "Directory index record with vcn 0x%llx is "
+ "corrupt. Corrupt inode 0x%lx. Run chkdsk.",
+ (unsigned long long)vcn, dir_ni->mft_no);
goto unm_err_out;
}
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
"bug.", (unsigned long long)
sle64_to_cpu(ia->index_block_vcn),
(unsigned long long)vcn, dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
if (le32_to_cpu(ia->index.allocated_size) + 0x18 !=
(unsigned long long)vcn, dir_ni->mft_no,
le32_to_cpu(ia->index.allocated_size) + 0x18,
dir_ni->itype.index.block_size);
- err = -EIO;
goto unm_err_out;
}
index_end = (u8*)ia + dir_ni->itype.index.block_size;
"Cannot access! This is probably a bug in the "
"driver.", (unsigned long long)vcn,
dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory "
"inode 0x%lx exceeds maximum size.",
(unsigned long long)vcn, dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/* The first index entry. */
ntfs_error(sb, "Index entry out of bounds in "
"directory inode 0x%lx.",
dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/*
ntfs_error(sb, "Index entry with child node found in "
"a leaf node in directory inode 0x%lx.",
dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/* Child node present, descend into it. */
}
ntfs_error(sb, "Negative child node vcn in directory inode "
"0x%lx.", dir_ni->mft_no);
- err = -EIO;
goto unm_err_out;
}
/* No child node, return -ENOENT. */
unlock_page(page);
ntfs_unmap_page(page);
err_out:
+ if (!err)
+ err = -EIO;
if (ctx)
ntfs_attr_put_search_ctx(ctx);
if (m)
return ERR_MREF(err);
dir_err_out:
ntfs_error(sb, "Corrupt directory. Aborting lookup.");
- err = -EIO;
goto err_out;
}
ntfs_debug("Reading bitmap with page index 0x%llx, bit ofs 0x%llx",
(unsigned long long)bmp_pos >> (3 + PAGE_CACHE_SHIFT),
(unsigned long long)bmp_pos &
- ((PAGE_CACHE_SIZE * 8) - 1));
+ (unsigned long long)((PAGE_CACHE_SIZE * 8) - 1));
bmp_page = ntfs_map_page(bmp_mapping,
bmp_pos >> (3 + PAGE_CACHE_SHIFT));
if (IS_ERR(bmp_page)) {
"inode 0x%lx or driver bug.", vdir->i_ino);
goto err_out;
}
+ /* Catch multi sector transfer fixup errors. */
+ if (unlikely(!ntfs_is_indx_record(ia->magic))) {
+ ntfs_error(sb, "Directory index record with vcn 0x%llx is "
+ "corrupt. Corrupt inode 0x%lx. Run chkdsk.",
+ (unsigned long long)ia_pos >>
+ ndir->itype.index.vcn_size_bits, vdir->i_ino);
+ goto err_out;
+ }
if (unlikely(sle64_to_cpu(ia->index_block_vcn) != (ia_pos &
~(s64)(ndir->itype.index.block_size - 1)) >>
ndir->itype.index.vcn_size_bits)) {
*/
for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) {
ntfs_debug("In index allocation, offset 0x%llx.",
- (unsigned long long)ia_start + ((u8*)ie -
- (u8*)ia));
+ (unsigned long long)ia_start +
+ (unsigned long long)((u8*)ie - (u8*)ia));
/* Bounds checks. */
if (unlikely((u8*)ie < (u8*)ia || (u8*)ie +
sizeof(INDEX_ENTRY_HEADER) > index_end ||