OSDN Git Service

Fixed expanding a resident attribute without inserting holes
authorJean-Pierre André <jpandre@users.sourceforge.net>
Mon, 9 Sep 2013 13:27:38 +0000 (15:27 +0200)
committerJean-Pierre André <jpandre@users.sourceforge.net>
Mon, 9 Sep 2013 13:27:38 +0000 (15:27 +0200)
When calling ntfstruncate() to expand a resident attribute, the function
is called again recursively, losing the requirement for not inserting
holes. This is for forwarding the requirement (used by ntfscp).

include/ntfs-3g/attrib.h
libntfs-3g/attrib.c

index 1979ba6..a0bee26 100644 (file)
@@ -61,7 +61,8 @@ typedef enum {
 typedef enum {                 /* ways of processing holes when expanding */
        HOLES_NO,
        HOLES_OK,
-       HOLES_DELAY
+       HOLES_DELAY,
+       HOLES_NONRES
 } hole_type;
 
 /**
index 01eaa46..269ccf8 100644 (file)
@@ -4929,7 +4929,7 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize);
  *     ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST.
  */
 static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
-                       BOOL force_non_resident)
+                       hole_type holes)
 {
        ntfs_attr_search_ctx *ctx;
        ntfs_volume *vol;
@@ -4967,7 +4967,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
         * attribute non-resident if the attribute type supports it. If it is
         * smaller we can go ahead and attempt the resize.
         */
-       if ((newsize < vol->mft_record_size) && !force_non_resident) {
+       if ((newsize < vol->mft_record_size) && (holes != HOLES_NONRES)) {
                /* Perform the resize of the attribute record. */
                if (!(ret = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr,
                                newsize))) {
@@ -5012,7 +5012,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
                 * could cause the attribute to be made resident again,
                 * so size changes are not allowed.
                 */
-               if (force_non_resident) {
+               if (holes == HOLES_NONRES) {
                        ret = 0;
                        if (newsize != na->data_size) {
                                ntfs_log_error("Cannot change size when"
@@ -5023,7 +5023,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
                        return (ret);
                }
                /* Resize non-resident attribute */
-               return ntfs_attr_truncate_i(na, newsize, HOLES_OK);
+               return ntfs_attr_truncate_i(na, newsize, holes);
        } else if (errno != ENOSPC && errno != EPERM) {
                err = errno;
                ntfs_log_perror("Failed to make attribute non-resident");
@@ -5079,7 +5079,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
                ntfs_inode_mark_dirty(tna->ni);
                ntfs_attr_close(tna);
                ntfs_attr_put_search_ctx(ctx);
-               return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
+               return ntfs_resident_attr_resize_i(na, newsize, holes);
        }
        /* Check whether error occurred. */
        if (errno != ENOENT) {
@@ -5099,7 +5099,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
                        ntfs_log_perror("Could not free space in MFT record");
                        return -1;
                }
-               return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
+               return ntfs_resident_attr_resize_i(na, newsize, holes);
        }
 
        /*
@@ -5138,7 +5138,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
                ntfs_attr_put_search_ctx(ctx);
                if (ntfs_inode_add_attrlist(ni))
                        return -1;
-               return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
+               return ntfs_resident_attr_resize_i(na, newsize, holes);
        }
        /* Allocate new mft record. */
        ni = ntfs_mft_record_alloc(vol, ni);
@@ -5159,7 +5159,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
 
        ntfs_attr_put_search_ctx(ctx);
        /* Try to perform resize once again. */
-       return ntfs_resident_attr_resize_i(na, newsize, force_non_resident);
+       return ntfs_resident_attr_resize_i(na, newsize, holes);
 
 resize_done:
        /*
@@ -5180,7 +5180,7 @@ static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize)
        int ret; 
        
        ntfs_log_enter("Entering\n");
-       ret = ntfs_resident_attr_resize_i(na, newsize, FALSE);
+       ret = ntfs_resident_attr_resize_i(na, newsize, HOLES_OK);
        ntfs_log_leave("\n");
        return ret;
 }
@@ -5204,7 +5204,7 @@ int ntfs_attr_force_non_resident(ntfs_attr *na)
 {
        int res;
 
-       res = ntfs_resident_attr_resize_i(na, na->data_size, TRUE);
+       res = ntfs_resident_attr_resize_i(na, na->data_size, HOLES_NONRES);
        if (!res && !NAttrNonResident(na)) {
                res = -1;
                errno = EIO;
@@ -6442,7 +6442,7 @@ static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize,
                else
                        ret = ntfs_non_resident_attr_shrink(na, fullsize);
        } else
-               ret = ntfs_resident_attr_resize(na, newsize);
+               ret = ntfs_resident_attr_resize_i(na, newsize, holes);
 out:   
        ntfs_log_leave("Return status %d\n", ret);
        return ret;