- Remove attrlist.[ch]::ntfs_attrlist_set because it was very bad idea to separate it from ntfs_attrlist_entry_{add,rm}.

- Update ntfs_attrlist_entry_{add,rm} and ntfs_inode_add_attrlist to work without it.
- Some other fixes, improvements and cleanups.

(Logical change 1.615)
edge.strict_endians
(none)!yura 2004-10-17 15:56:39 +00:00
parent 758dcd21ce
commit 3cb8b787bd
5 changed files with 133 additions and 146 deletions

View File

@ -48,8 +48,6 @@ xx/xx/2004 - 2.0.0-WIP
- Add new API unistr.[hc]::ntfs_ucsndup(). (Anton)
- Make libntfs/attrib.c::ntfs_attr_open() make a copy of the attribute
name unless it is one of the internal names. (Anton)
- Move out common part of ntfs_attrlist_entry_{add,rm} to new API:
attrlist.[ch]::ntfs_attrlist_set. (Yura)
- New API: attrib.[ch]::ntfs_resident_attr_record_add. (Yura)
- New API: inode.[ch]::ntfs_inode_add_attrlist. (Yura)
- New API: attrlist.[ch]::ntfs_attrlist_need. (Yura)

View File

@ -28,7 +28,6 @@
extern int ntfs_attrlist_need(ntfs_inode *ni);
extern int ntfs_attrlist_set(ntfs_inode *ni, u8 *new_al, int new_al_len);
extern int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr);
extern int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx);

View File

@ -2396,7 +2396,7 @@ int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
base_ni = ni->base_ni;
else
base_ni = ni;
if (NInoAttrList(base_ni)) {
if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
if (ntfs_attrlist_entry_add(ni, a)) {
err = errno;
ntfs_attr_record_resize(m, a, 0);
@ -2526,7 +2526,7 @@ int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
base_ni = ni->base_ni;
else
base_ni = ni;
if (NInoAttrList(base_ni)) {
if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) {
if (ntfs_attrlist_entry_add(ni, a)) {
err = errno;
ntfs_attr_record_resize(m, a, 0);
@ -2583,29 +2583,15 @@ int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx) {
return -1;
}
Dprintf("%s(): Entering for inode 0x%llx, attr 0x%x, lowest_vcn "
"%lld.\n", __FUNCTION__, (long long) ctx->ntfs_ino->mft_no,
(unsigned) le32_to_cpu(ctx->attr->type),
(long long) sle64_to_cpu(ctx->attr->lowest_vcn));
Dprintf("%s(): Entering for inode 0x%llx, attr 0x%x.\n",
__FUNCTION__, (long long) ctx->ntfs_ino->mft_no,
(unsigned) le32_to_cpu(ctx->attr->type));
type = ctx->attr->type;
ni = ctx->ntfs_ino;
if (ctx->base_ntfs_ino)
base_ni = ctx->base_ntfs_ino;
else
base_ni = ctx->ntfs_ino;
/*
* Remove record from $ATTRIBUTE_LIST if present and we don't want
* delete $ATTRIBUTE_LIST itself.
*/
if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST) {
if (ntfs_attrlist_entry_rm(ctx)) {
err = errno;
Dprintf("%s(): Coudn't delete record from "
"$ATTRIBUTE_LIST.\n", __FUNCTION__);
errno = err;
return -1;
}
}
/* Remove attribute itself. */
if (ntfs_attr_record_resize(ctx->mrec, ctx->attr, 0)) {
@ -2620,10 +2606,25 @@ int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx) {
}
ntfs_inode_mark_dirty(ni);
/*
* Remove record from $ATTRIBUTE_LIST if present and we don't want
* delete $ATTRIBUTE_LIST itself.
*/
if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST) {
if (ntfs_attrlist_entry_rm(ctx)) {
err = errno;
Dprintf("%s(): Coudn't delete record from "
"$ATTRIBUTE_LIST.\n", __FUNCTION__);
errno = err;
return -1;
}
}
/* Post $ATTRIBUTE_LIST delete setup. */
if (type == AT_ATTRIBUTE_LIST) {
if (NInoAttrList(base_ni) && base_ni->attr_list)
free(base_ni->attr_list);
base_ni->attr_list = NULL;
NInoClearAttrList(base_ni);
NInoAttrListClearDirty(base_ni);
}
@ -3321,10 +3322,19 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
goto put_err_out;
}
/* We can't move out attribute list. */
/* We can't move out attribute list, thus move out others. */
if (na->type == AT_ATTRIBUTE_LIST) {
err = ENOSPC;
goto put_err_out;
ntfs_attr_put_search_ctx(ctx);
if (ntfs_inode_free_space(na->ni, offsetof(ATTR_RECORD,
non_resident_attr_end) + 8)) {
err = errno;
Dprintf("%s(): Couldn't free space in the MFT record "
"to make attribute list non resident.\n",
__FUNCTION__);
errno = err;
return -1;
}
return ntfs_resident_attr_resize(na, newsize);
}
/*
@ -3712,7 +3722,7 @@ int ntfs_attr_update_mapping_pairs(ntfs_attr *na)
if (na->type == AT_ATTRIBUTE_LIST) {
ntfs_attr_put_search_ctx(ctx);
if (ntfs_inode_free_space(na->ni, mp_size -
exp_max_mp_size)) {
cur_max_mp_size)) {
if (errno != ENOSPC)
return -1;
Dprintf("%s(): Attribute list mapping "
@ -4287,6 +4297,7 @@ put_err_out:
int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
{
if (!na || newsize < 0 || (na->ni == FILE_MFT && na->type == AT_DATA)) {
Dprintf("%s(): Invalid aruments passed.\n", __FUNCTION__);
errno = EINVAL;
return -1;
}

View File

@ -82,77 +82,6 @@ int ntfs_attrlist_need(ntfs_inode *ni)
return 0;
}
/**
* ntfs_attrlist_set - set new attribute list for ntfs inode
* @ni: opened ntfs inode attribute list set for
* @new_al: new attribute list
* @new_al_len: length of new attribute list
*
* Return 0 on success and -1 on error with errno set to the error code. The
* following error codes are defined:
* EINVAL - Invalid argumets passed to function.
* ENOMEM - Not enough memory to allocate necessary buffers.
* ENOTSUP - Code that required for set is not implemented yet.
* EIO - I/O error occured or damaged filesystem.
*/
int ntfs_attrlist_set(ntfs_inode *ni, u8 *new_al, int new_al_len)
{
ntfs_attr *na = NULL;
int err;
if (!ni || !new_al || new_al_len < 1) {
Dprintf("%s(): Invalid argumets.\n", __FUNCTION__);
errno = EINVAL;
return -1;
}
Dprintf("%s(): Entering for inode 0x%llx, new_al_len %d.\n",
__FUNCTION__, (long long) ni->mft_no, new_al_len);
/* Make attribute list length 8 byte aligment. */
new_al_len = (new_al_len + 7) & ~7;
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, 0, 0);
if (!na) {
err = errno;
Dprintf("%s(): Coudn't open $ATTRIBUTE_LIST.\n", __FUNCTION__);
goto err_out;
}
/*
* Setup im-memory attribute list. We need this to perform attribute
* truncate (we need update attribute list in case other attributes
* will be moved away from their current MFT record).
*/
if (NInoAttrList(ni) && ni->attr_list)
free(ni->attr_list);
ni->attr_list = new_al;
ni->attr_list_size = new_al_len;
NInoSetAttrList(ni);
NInoAttrListSetDirty(ni);
/* Resize $ATTRIBUTE_LIST attribute. */
if (ntfs_attr_truncate(na, new_al_len)) {
/*
* FIXME: We leave new attribute list. But need to restore old
* and update in it records for moved attributes. Difficult to
* do if we haven't attribute list before truncate and records
* were moved.
*/
err = errno;
Dprintf("%s(): Eeek! $ATTRIBUTE_LIST resize failed. Probably "
"leaving inconsist metadata.\n", __FUNCTION__);
goto err_out;
}
/* Done! */
ntfs_attr_close(na);
return 0;
err_out:
if (na)
ntfs_attr_close(na);
errno = err;
return -1;
}
/**
* ntfs_attrlist_entry_add - add an attribute list attribute entry
* @ni: opened ntfs inode, which contains that attribute
@ -169,6 +98,7 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
{
ATTR_LIST_ENTRY *ale;
MFT_REF mref;
ntfs_attr *na = NULL;
u8 *new_al;
int new_al_len;
int err;
@ -193,6 +123,7 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
return -1;
}
/* Determine size and allocate memory for new attribute list. */
new_al_len = (ni->attr_list_size + sizeof(ATTR_LIST_ENTRY) +
sizeof(ntfschar) * attr->name_length + 7) & ~7;
new_al = malloc(new_al_len);
@ -202,6 +133,20 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
return -1;
}
/* Reisze $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, NULL, 0);
if (!na) {
err = errno;
Dprintf("%s(): Failed to open $ATTRIBUTE_LIST attribute.\n",
__FUNCTION__);
goto err_out;
}
if (ntfs_attr_truncate(na, new_al_len)) {
err = errno;
Dprintf("%s(): $ATTRIBUTE_LIST resize failed.\n", __FUNCTION__);
goto err_out;
}
/* Find offset at which insert new entry. */
ale = (ATTR_LIST_ENTRY *) ni->attr_list;
for(; (u8 *)ale < ni->attr_list + ni->attr_list_size;
@ -218,7 +163,7 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
err = EIO;
Dprintf("%s(): Corrupt attribute name. Run chkdsk.\n",
__FUNCTION__);
goto err_out;
goto rollback;
}
if (err < 0)
continue;
@ -233,7 +178,7 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
Dprintf("%s(): Attribute with same type, name and "
"lowest vcn already present in attribute "
"list.\n", __FUNCTION__);
goto err_out;
goto rollback;
}
break;
}
@ -262,13 +207,22 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
attr->name_length * sizeof(ntfschar));
/* Set new runlist. */
if (ntfs_attrlist_set(ni, new_al, new_al_len)) {
err = errno;
goto err_out;
}
if (ni->attr_list)
free(ni->attr_list);
ni->attr_list = new_al;
ni->attr_list_size = new_al_len;
NInoAttrListSetDirty(ni);
/* Done! */
ntfs_attr_close(na);
return 0;
rollback:
if (ntfs_attr_truncate(na, ni->attr_list_size)) {
Dprintf("%s(): $ATTRIBUTE_LIST resize failed. Rollback failed. "
"Leaving inconsist metadata.\n", __FUNCTION__);
}
err_out:
if (na)
ntfs_attr_close(na);
free(new_al);
errno = err;
return -1;
@ -278,8 +232,7 @@ err_out:
* ntfs_attrlist_entry_rm - remove an attribute list attribute entry
* @ctx: attribute search context describing the attrubute list entry
*
* Remove the attribute list entry @ctx->al_entry from the attribute list
* attribute of the base mft record to which the attribute @ctx->attr belongs.
* Remove the attribute list entry @ctx->al_entry from the attribute list.
*
* Return 0 on success and -1 on error with errno set to the error code.
*/
@ -288,10 +241,11 @@ int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
u8 *new_al;
int new_al_len;
ntfs_inode *base_ni;
ntfs_attr *na;
ATTR_LIST_ENTRY *ale;
int err;
if (!ctx || !ctx->ntfs_ino || !ctx->attr || !ctx->al_entry) {
if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) {
Dprintf("%s(): Invalid argumets.\n", __FUNCTION__);
errno = EINVAL;
return -1;
@ -305,8 +259,8 @@ int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
Dprintf("%s(): Entering for inode 0x%llx, attr 0x%x, lowest_vcn "
"%lld.\n", __FUNCTION__, (long long) ctx->ntfs_ino->mft_no,
(unsigned) le32_to_cpu(ctx->attr->type),
(long long) le64_to_cpu(ctx->attr->lowest_vcn));
(unsigned) le32_to_cpu(ctx->al_entry->type),
(long long) le64_to_cpu(ctx->al_entry->lowest_vcn));
if (!NInoAttrList(base_ni)) {
Dprintf("%s(): Attribute list isn't present.\n", __FUNCTION__);
@ -322,6 +276,20 @@ int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
errno = ENOMEM;
return -1;
}
/* Reisze $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, NULL, 0);
if (!na) {
err = errno;
Dprintf("%s(): Failed to open $ATTRIBUTE_LIST attribute.\n",
__FUNCTION__);
goto err_out;
}
if (ntfs_attr_truncate(na, new_al_len)) {
err = errno;
Dprintf("%s(): $ATTRIBUTE_LIST resize failed.\n", __FUNCTION__);
goto err_out;
}
/* Copy entries from old attribute list to new. */
memcpy(new_al, base_ni->attr_list, (u8*)ale - base_ni->attr_list);
@ -329,12 +297,17 @@ int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
ale->length), new_al_len - ((u8*)ale - base_ni->attr_list));
/* Set new runlist. */
if (ntfs_attrlist_set(base_ni, new_al, new_al_len)) {
err = errno;
goto err_out;
}
if (base_ni->attr_list)
free(base_ni->attr_list);
base_ni->attr_list = new_al;
base_ni->attr_list_size = new_al_len;
NInoAttrListSetDirty(base_ni);
/* Done! */
ntfs_attr_close(na);
return 0;
err_out:
if (na)
ntfs_attr_close(na);
free(new_al);
errno = err;
return -1;

View File

@ -525,6 +525,7 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
u8 *al, *aln;
int al_len, al_allocated;
ATTR_LIST_ENTRY *ale;
ntfs_attr *na;
if (!ni) {
Dprintf("%s(): Invalid argumets.\n", __FUNCTION__);
@ -617,52 +618,47 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
al = aln;
ntfs_attr_put_search_ctx(ctx);
/* Set in-memory attribute list. */
ni->attr_list = al;
ni->attr_list_size = al_len;
NInoSetAttrList(ni);
/* Free space if there is not enough it for $ATTRIBUTE_LIST. */
if (le32_to_cpu(ni->mrec->bytes_allocated) -
le32_to_cpu(ni->mrec->bytes_in_use) <
offsetof(ATTR_RECORD, resident_attr_end)) {
/*
* Set temporary in-memory attribute list. We need this to be
* able perform attribute lookups and move out attributes.
*/
ni->attr_list = al;
ni->attr_list_size = al_len;
NInoSetAttrList(ni);
/* Free space. */
if (ntfs_inode_free_space(ni,
offsetof(ATTR_RECORD, resident_attr_end))) {
/*
* Couldn't free space, unset temporary in-memory
* attribute list and fail.
*/
/* Failed to free space. */
err = errno;
Dprintf("%s(): Failed to free space for "
"$ATTRIBUTE_LIST.\n", __FUNCTION__);
ni->attr_list = NULL;
NInoClearAttrList(ni);
goto err_out;
free(al);
goto rollback;
}
/* Unset temporary in-memory attribute list. */
ni->attr_list = NULL;
NInoClearAttrList(ni);
}
/* Add $ATTRIBUTE_LIST to mft record. */
if (ntfs_resident_attr_record_add(ni, AT_ATTRIBUTE_LIST, 0, 0, 0) < 0) {
na = ntfs_inode_add_attr(ni, AT_ATTRIBUTE_LIST, NULL, 0, al_len);
if (!na) {
err = errno;
Dprintf("%s(): Couldn't add $ATTRIBUTE_LIST to MFT record.\n",
__FUNCTION__);
goto err_out;
}
/* Set new attribute list. */
if (ntfs_attrlist_set(ni, al, al_len)) {
err = errno;
Dprintf("%s(): Coudn't set attribute list.\n", __FUNCTION__);
goto err_out;
Dprintf("%s(): Failed to add $ATTRIBUTE_LIST.\n", __FUNCTION__);
goto rollback;
}
/* Done! */
ntfs_attr_close(na);
return 0;
rollback:
/*
* FIXME: We should here scan attribute list for attributes that placed
* not in the base MFT record and move them to it.
*/
/* Unset in-memory attribute list. */
ni->attr_list = NULL;
NInoClearAttrList(ni);
errno = err;
return -1;
put_err_out:
ntfs_attr_put_search_ctx(ctx);
err_out:
@ -681,7 +677,7 @@ err_out:
int ntfs_inode_free_space(ntfs_inode *ni, int size)
{
ntfs_attr_search_ctx *ctx;
int freed = 0, err;
int freed, err;
if (!ni || size < 0) {
Dprintf("%s(): Invalid argumets.\n", __FUNCTION__);
@ -691,8 +687,11 @@ int ntfs_inode_free_space(ntfs_inode *ni, int size)
Dprintf("%s(): Entering for inode 0x%llx, size %d.\n",
__FUNCTION__, (long long) ni->mft_no, size);
freed = (le32_to_cpu(ni->mrec->bytes_allocated) -
le32_to_cpu(ni->mrec->bytes_in_use));
if (!size)
if (size <= freed)
return 0;
ctx = ntfs_attr_get_search_ctx(ni, 0);
@ -820,11 +819,12 @@ put_err_out:
ntfs_attr *ntfs_inode_add_attr(ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, s64 size)
{
int attr_rec_size, err, i, offset;
u32 attr_rec_size;
int err, i, offset;
ntfs_inode *attr_ni;
ntfs_attr *na;
if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) {
if (!ni || size < 0) {
Dprintf("%s(): Invalid arguments passed.\n", __FUNCTION__);
errno = EINVAL;
return NULL;
@ -883,6 +883,12 @@ ntfs_attr *ntfs_inode_add_attr(ntfs_inode *ni, ATTR_TYPES type,
goto add_attr_record;
}
/* Attribute list can be placed only in the base MFT record. */
if (type == AT_ATTRIBUTE_LIST) {
err = ENOSPC;
goto err_out;
}
/* Try to add to extent inodes. */
if (ntfs_inode_attach_all_extents(ni)) {
err = errno;