From 8f310e5bf2fb1789432d186979f4fd489ceb5026 Mon Sep 17 00:00:00 2001 From: "cantab.net!aia21" Date: Wed, 29 Oct 2003 17:40:03 +0000 Subject: [PATCH] Make ntfs_attr_make_non_resident() return error EPERM if it is called for an attribute that cannot be non-resident. Implement ntfs_attr_can_be_resident(). Start working on ntfs_attr_make_resident(). (Logical change 1.220) --- libntfs/attrib.c | 144 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 107 insertions(+), 37 deletions(-) diff --git a/libntfs/attrib.c b/libntfs/attrib.c index e8289316..23c4c364 100644 --- a/libntfs/attrib.c +++ b/libntfs/attrib.c @@ -2030,6 +2030,42 @@ int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type) return -1; } +/** + * ntfs_attr_can_be_resident - check if an attribute can be resident + * @vol: ntfs volume to which the attribute belongs + * @type: attribute type which to check + * + * Check whether the attribute of @type on the ntfs volume @vol is allowed to + * be resident. This information is derived from our ntfs knowledge and may + * not be completely accurate, especially when user defined attributes are + * present. Basically we allow everything to be resident except for index + * allocation and extended attribute attributes. + * + * Return 0 if the attribute is allowed to be resident and -1 if not or an + * error occured. On error the error code is stored in errno. The following + * error codes are defined: + * EPERM - The attribute is not allowed to be resident. + * EINVAL - Invalid parameters (e.g. @vol is not valid). + * + * Warning: In the system file $MFT the attribute $Bitmap must be non-resident + * otherwise windows will not boot (blue screen of death)! We cannot + * check for this here as we don't know which inode's $Bitmap is being + * asked about so the caller needs to special case this. + */ +int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPES type) +{ + if (!vol || !vol->attrdef || !type) { + errno = EINVAL; + return -1; + } + + if (type != AT_INDEX_ALLOCATION && type != AT_EA) + return 0; + + errno = EPERM; + return -1; +} + /** * ntfs_attr_record_resize - resize an attribute record * @m: mft record containing attribute record @@ -2150,7 +2186,10 @@ int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, * * Convert a resident ntfs attribute to a non-resident one. * - * Return 0 on success and -1 on error with errno set to the error code. + * Return 0 on success and -1 on error with errno set to the error code. The + * following error codes are defined: + * EPERM - The attribute is not allowed to be non-resident. + * TODO: others... * * NOTE to self: No changes in the attribute list are required to move from * a resident to a non-resident attribute. @@ -2177,6 +2216,11 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na, errno = EINVAL; return -1; } + + /* Check that the attribute is allowed to be non-resident. */ + if (ntfs_attr_can_be_non_resident(vol, na->type)) + return -1; + /* * Check that the attribute name hasn't been placed after the * attribute value. If it has we need to move it. @@ -2419,37 +2463,22 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize) } /* There is not enough space in the mft record to perform the resize. */ - /* Check if the attribute is allowed to be non-resident. */ - if (!ntfs_attr_can_be_non_resident(vol, na->type)) { - /* Make the attribute non-resident. */ - if (!ntfs_attr_make_non_resident(na, ctx)) { - // TODO: Attribute is now non-resident. Resize it! - // goto resize_done; - fprintf(stderr, "%s(): TODO: Resize attribute now that " - "it is non-resident.\n", __FUNCTION__); - ntfs_inode_mark_dirty(ctx->ntfs_ino); - err = ENOTSUP; - goto put_err_out; - } - /* Error! If not enough space, just continue. */ - if (errno != ENOSPC) { - err = errno; - // FIXME: Eeek! - fprintf(stderr, "%s(): Eeek! Failed to make attribute " - "non-resident. Aborting...\n", - __FUNCTION__); - goto put_err_out; - } - } else { - /* - * If the attribute can be non-resident but an error occured - * while making it non-resident, abort. - */ - if (errno != EPERM) { - err = errno; - goto put_err_out; - } - /* Attribute is not allowed to be non-resident, continue. */ + /* Make the attribute non-resident if possible. */ + if (!ntfs_attr_make_non_resident(na, ctx)) { + // TODO: Attribute is now non-resident. Resize it! + // goto resize_done; + fprintf(stderr, "%s(): TODO: Resize attribute now that " + "it is non-resident.\n", __FUNCTION__); + ntfs_inode_mark_dirty(ctx->ntfs_ino); + err = ENOTSUP; + goto put_err_out; + } else if (errno != ENOSPC && errno != EPERM) { + err = errno; + // FIXME: Eeek! + fprintf(stderr, "%s(): Eeek! Failed to make attribute " + "non-resident. Aborting...\n", + __FUNCTION__); + goto put_err_out; } // TODO: Try to make other attributes non-resident. @@ -2476,14 +2505,30 @@ put_err_out: } /** - * ntfs_attr_make_resident - + * ntfs_attr_make_resident - convert a non-resident to a resident attribute + * @na: open ntfs attribute to make resident + * @ctx: ntfs search context describing the attribute + * + * Convert a non-resident ntfs attribute to a resident one. + * + * Return 0 on success and -1 on error with errno set to the error code. The + * following error codes are defined: + * EPERM - The attribute is not allowed to be resident. + * TODO: others... + * + * Warning: We do not set the inode dirty and we do not write out anything! + * We expect the caller to do this as this is a fairly low level + * function and it is likely there will be further changes made. */ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx) { - // FIXME: For now we cheat and assume there is no attribute list - // present. (AIA) - if (NInoAttrList(na->ni)) { - errno = ENOTSUP; + /* Some preliminary sanity checking. */ + if (!NAttrNonResident(na)) { + // FIXME: Eeek! + fprintf(stderr, "%s(): Eeek! Trying to make resident " + "attribute resident. Aborting...\n", + __FUNCTION__); + errno = EINVAL; return -1; } @@ -2493,6 +2538,31 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx) return -1; } + /* Check that the attribute is allowed to be resident. */ + if (ntfs_attr_can_be_resident(vol, na->type)) + return -1; + + /* + * Check that the attribute name hasn't been placed after the + * mapping pairs array. If it has we need to move it. + * TODO: Implement the move. For now just abort. (AIA) + */ + if (a->name_length && le16_to_cpu(a->name_offset) >= + le16_to_cpu(a->mapping_pairs_offset)) { + // FIXME: Eeek! + fprintf(stderr, "%s(): Eeek! Name is placed after the mapping " + "pairs array. Aborting...\n", __FUNCTION__); + errno = ENOTSUP; + return -1; + } + + // FIXME: For now we cheat and assume there is no attribute list + // present. (AIA) + if (NInoAttrList(na->ni)) { + errno = ENOTSUP; + return -1; + } + errno = ENOTSUP; return -1;