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)
edge.strict_endians
cantab.net!aia21 2003-10-29 17:40:03 +00:00
parent 34a712077d
commit 8f310e5bf2
1 changed files with 107 additions and 37 deletions

View File

@ -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;