Adapted to ntfs-3g-1.2531
parent
5e1c95de2c
commit
7c05f13884
|
@ -52,6 +52,9 @@ static __inline__ int ntfs_mft_record_read(const ntfs_volume *vol,
|
|||
return ntfs_mft_records_read(vol, mref, 1, b);
|
||||
}
|
||||
|
||||
extern int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
|
||||
MFT_RECORD *m);
|
||||
|
||||
extern int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
|
||||
MFT_RECORD **mrec, ATTR_RECORD **attr);
|
||||
|
||||
|
|
|
@ -381,10 +381,9 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
ntfs_attr_search_ctx *ctx;
|
||||
ntfs_attr *na;
|
||||
ATTR_RECORD *a;
|
||||
int err;
|
||||
BOOL cs;
|
||||
|
||||
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
|
||||
ntfs_log_trace("Entering for inode %lld, attr 0x%x.\n",
|
||||
(unsigned long long)ni->mft_no, type);
|
||||
if (!ni || !ni->vol || !ni->mrec) {
|
||||
errno = EINVAL;
|
||||
|
@ -402,16 +401,29 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
}
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx(ni, NULL);
|
||||
if (!ctx) {
|
||||
err = errno;
|
||||
if (!ctx)
|
||||
goto err_out;
|
||||
}
|
||||
if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx)) {
|
||||
err = errno;
|
||||
|
||||
if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx))
|
||||
goto put_err_out;
|
||||
}
|
||||
|
||||
a = ctx->attr;
|
||||
|
||||
if (!name) {
|
||||
if (a->name_length) {
|
||||
name = ntfs_ucsndup((ntfschar*)((u8*)a + le16_to_cpu(
|
||||
a->name_offset)), a->name_length);
|
||||
if (!name)
|
||||
goto put_err_out;
|
||||
name_len = a->name_length;
|
||||
} else {
|
||||
name = AT_UNNAMED;
|
||||
name_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
__ntfs_attr_init(na, ni, type, name, name_len);
|
||||
|
||||
/*
|
||||
* Wipe the flags in case they are not zero for an attribute list
|
||||
* attribute. Windows does not complain about invalid flags and chkdsk
|
||||
|
@ -419,23 +431,28 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
|
|||
*/
|
||||
if (type == AT_ATTRIBUTE_LIST)
|
||||
a->flags = 0;
|
||||
|
||||
cs = a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
|
||||
if (!name) {
|
||||
if (a->name_length) {
|
||||
name = ntfs_ucsndup((ntfschar*)((u8*)a + le16_to_cpu(
|
||||
a->name_offset)), a->name_length);
|
||||
if (!name) {
|
||||
err = errno;
|
||||
goto put_err_out;
|
||||
}
|
||||
name_len = a->name_length;
|
||||
} else {
|
||||
name = AT_UNNAMED;
|
||||
name_len = 0;
|
||||
}
|
||||
|
||||
if (na->type == AT_DATA && na->name == AT_UNNAMED &&
|
||||
((!(a->flags & ATTR_IS_COMPRESSED) != !NAttrCompressed(na)) ||
|
||||
(!(a->flags & ATTR_IS_SPARSE) != !NAttrSparse(na)) ||
|
||||
(!(a->flags & ATTR_IS_ENCRYPTED) != !NAttrEncrypted(na)))) {
|
||||
errno = EIO;
|
||||
ntfs_log_perror("Inode %lld has corrupt attribute flags "
|
||||
"(0x%x <> 0x%x)",(unsigned long long)ni->mft_no,
|
||||
a->flags, na->ni->flags);
|
||||
goto put_err_out;
|
||||
}
|
||||
__ntfs_attr_init(na, ni, type, name, name_len);
|
||||
|
||||
if (a->non_resident) {
|
||||
if ((a->flags & ATTR_IS_COMPRESSED) && !a->compression_unit) {
|
||||
errno = EIO;
|
||||
ntfs_log_perror("Compressed inode %lld attr 0x%x has "
|
||||
"no compression unit",
|
||||
(unsigned long long)ni->mft_no, type);
|
||||
goto put_err_out;
|
||||
}
|
||||
ntfs_attr_init(na, TRUE, a->flags & ATTR_IS_COMPRESSED,
|
||||
a->flags & ATTR_IS_ENCRYPTED,
|
||||
a->flags & ATTR_IS_SPARSE,
|
||||
|
@ -457,7 +474,6 @@ put_err_out:
|
|||
ntfs_attr_put_search_ctx(ctx);
|
||||
err_out:
|
||||
free(na);
|
||||
errno = err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -797,8 +813,8 @@ s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
|
|||
}
|
||||
|
||||
ntfs_log_trace("Entering for inode %lld attr 0x%x pos %lld count "
|
||||
"%lld\n", (unsigned long long)na->ni->mft_no,
|
||||
na->type, (long long)pos, (long long)count);
|
||||
"%lld flags: 0x%x\n", (unsigned long long)na->ni->mft_no,
|
||||
na->type, (long long)pos, (long long)count, na->ni->flags);
|
||||
|
||||
/*
|
||||
* If this is a compressed attribute it needs special treatment, but
|
||||
|
|
|
@ -221,7 +221,7 @@ static u8 *ntfs_ie_get_end(INDEX_HEADER *ih)
|
|||
|
||||
static int ntfs_ie_end(INDEX_ENTRY *ie)
|
||||
{
|
||||
return ie->ie_flags & INDEX_ENTRY_END;
|
||||
return ie->ie_flags & INDEX_ENTRY_END || !ie->length;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -302,11 +302,13 @@ static int ntfs_ih_numof_entries(INDEX_HEADER *ih)
|
|||
{
|
||||
int n;
|
||||
INDEX_ENTRY *ie;
|
||||
u8 *end;
|
||||
|
||||
ntfs_log_trace("Entering\n");
|
||||
|
||||
end = ntfs_ie_get_end(ih);
|
||||
ie = ntfs_ie_get_first(ih);
|
||||
for (n = 0; !ntfs_ie_end(ie); n++)
|
||||
for (n = 0; !ntfs_ie_end(ie) && (u8 *)ie < end; n++)
|
||||
ie = ntfs_ie_get_next(ie);
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -209,6 +209,40 @@ int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
|
|||
return -1;
|
||||
}
|
||||
|
||||
int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
|
||||
MFT_RECORD *m)
|
||||
{
|
||||
ATTR_RECORD *a;
|
||||
int ret = -1;
|
||||
|
||||
if (!ntfs_is_file_record(m->magic)) {
|
||||
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
|
||||
(unsigned long long)MREF(mref), *(le32 *)m);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) {
|
||||
ntfs_log_error("Record %llu has corrupt allocation size "
|
||||
"(%u <> %u)\n", (unsigned long long)MREF(mref),
|
||||
vol->mft_record_size,
|
||||
le32_to_cpu(m->bytes_allocated));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset));
|
||||
if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) {
|
||||
ntfs_log_error("Record %llu is corrupt\n",
|
||||
(unsigned long long)MREF(mref));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
err_out:
|
||||
if (ret)
|
||||
errno = EIO;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_file_record_read - read a FILE record from the mft from disk
|
||||
* @vol: volume to read from
|
||||
|
@ -244,14 +278,13 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
|
|||
MFT_RECORD **mrec, ATTR_RECORD **attr)
|
||||
{
|
||||
MFT_RECORD *m;
|
||||
ATTR_RECORD *a;
|
||||
int err;
|
||||
|
||||
if (!vol || !mrec) {
|
||||
errno = EINVAL;
|
||||
ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m = *mrec;
|
||||
if (!m) {
|
||||
m = ntfs_malloc(vol->mft_record_size);
|
||||
|
@ -259,36 +292,26 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
|
|||
return -1;
|
||||
}
|
||||
if (ntfs_mft_record_read(vol, mref, m)) {
|
||||
err = errno;
|
||||
ntfs_log_perror("ntfs_mft_record_read failed");
|
||||
goto err_out;
|
||||
}
|
||||
err = EIO;
|
||||
if (!ntfs_is_file_record(m->magic)) {
|
||||
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
|
||||
(unsigned long long)MREF(mref), *(le32 *)m);
|
||||
if (ntfs_mft_record_check(vol, mref, m))
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) {
|
||||
ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n",
|
||||
(unsigned long long)MREF(mref), MSEQNO(mref),
|
||||
le16_to_cpu(m->sequence_number));
|
||||
goto err_out;
|
||||
}
|
||||
a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
|
||||
if (p2n(a) < p2n(m) || (char*)a > (char*)m + vol->mft_record_size) {
|
||||
ntfs_log_error("Record %llu is corrupt\n",
|
||||
(unsigned long long)MREF(mref));
|
||||
errno = EIO;
|
||||
goto err_out;
|
||||
}
|
||||
*mrec = m;
|
||||
if (attr)
|
||||
*attr = a;
|
||||
*attr = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
|
||||
return 0;
|
||||
err_out:
|
||||
if (m != *mrec)
|
||||
free(m);
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -210,24 +210,14 @@ static int ntfs_mft_load(ntfs_volume *vol)
|
|||
ntfs_log_perror("Error reading $MFT");
|
||||
goto error_exit;
|
||||
}
|
||||
if (ntfs_is_baad_record(mb->magic)) {
|
||||
ntfs_log_error("Incomplete multi sector transfer detected in "
|
||||
"$MFT.\n");
|
||||
goto io_error_exit;
|
||||
}
|
||||
if (!ntfs_is_mft_record(mb->magic)) {
|
||||
ntfs_log_error("$MFT has invalid magic.\n");
|
||||
goto io_error_exit;
|
||||
}
|
||||
|
||||
if (ntfs_mft_record_check(vol, 0, mb))
|
||||
goto error_exit;
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
|
||||
if (!ctx)
|
||||
goto error_exit;
|
||||
|
||||
if (p2n(ctx->attr) < p2n(mb) ||
|
||||
(char*)ctx->attr > (char*)mb + vol->mft_record_size) {
|
||||
ntfs_log_error("$MFT is corrupt.\n");
|
||||
goto io_error_exit;
|
||||
}
|
||||
/* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */
|
||||
if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
|
||||
ctx)) {
|
||||
|
@ -855,13 +845,19 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
|
|||
ntfs_log_perror("Failed to open inode FILE_Bitmap");
|
||||
goto error_exit;
|
||||
}
|
||||
/* Get an ntfs attribute for $Bitmap/$DATA. */
|
||||
|
||||
vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
|
||||
if (!vol->lcnbmp_na) {
|
||||
ntfs_log_perror("Failed to open ntfs attribute");
|
||||
goto error_exit;
|
||||
}
|
||||
/* Done with the $Bitmap mft record. */
|
||||
|
||||
if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
|
||||
ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
|
||||
(long long)vol->lcnbmp_na->data_size,
|
||||
(long long)vol->lcnbmp_na->allocated_size);
|
||||
goto io_error_exit;
|
||||
}
|
||||
|
||||
/* Now load the upcase table from $UpCase. */
|
||||
ntfs_log_debug("Loading $UpCase...\n");
|
||||
|
|
Loading…
Reference in New Issue