diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c index 4e628020..3bc4b5ff 100644 --- a/libntfs-3g/attrib.c +++ b/libntfs-3g/attrib.c @@ -376,10 +376,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; @@ -397,16 +396,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 @@ -414,22 +426,27 @@ 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 ((!(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 attr 0x%x has corrupt flags " + "(0x%x <> 0x%x)", (unsigned long long)ni->mft_no, + type, a->flags, na->ni->flags); + goto put_err_out; } - __ntfs_attr_init(na, ni, type, name, name_len); + + if ((NAttrCompressed(na) || NAttrSparse(na)) && !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; + } + if (a->non_resident) { ntfs_attr_init(na, TRUE, a->flags & ATTR_IS_COMPRESSED, a->flags & ATTR_IS_ENCRYPTED, @@ -452,7 +469,6 @@ put_err_out: ntfs_attr_put_search_ctx(ctx); err_out: free(na); - errno = err; return NULL; } @@ -791,8 +807,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