diff --git a/include/ntfs-3g/attrib.h b/include/ntfs-3g/attrib.h index 47c40847..35ad4cf9 100644 --- a/include/ntfs-3g/attrib.h +++ b/include/ntfs-3g/attrib.h @@ -343,6 +343,7 @@ extern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra); extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn); extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize); +extern int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize); /** * get_attribute_value_length - return the length of the value of an attribute diff --git a/libntfs-3g/attrib.c b/libntfs-3g/attrib.c index 787f7b64..36d16b8a 100644 --- a/libntfs-3g/attrib.c +++ b/libntfs-3g/attrib.c @@ -6073,7 +6073,8 @@ put_err_out: * ERANGE - @newsize is not valid for the attribute type of @na. * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST. */ -static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize) +static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize, + BOOL holes) { LCN lcn_seek_from; VCN first_free_vcn; @@ -6137,7 +6138,7 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize) * If we extend $DATA attribute on NTFS 3+ volume, we can add * sparse runs instead of real allocation of clusters. */ - if (na->type == AT_DATA && vol->major_ver >= 3) { + if ((na->type == AT_DATA && vol->major_ver >= 3) && holes) { rl = ntfs_malloc(0x1000); if (!rl) return -1; @@ -6297,12 +6298,13 @@ put_err_out: } -static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) +static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize, + BOOL holes) { int ret; ntfs_log_enter("Entering\n"); - ret = ntfs_non_resident_attr_expand_i(na, newsize); + ret = ntfs_non_resident_attr_expand_i(na, newsize, holes); ntfs_log_leave("\n"); return ret; } @@ -6311,6 +6313,7 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) * ntfs_attr_truncate - resize an ntfs attribute * @na: open ntfs attribute to resize * @newsize: new size (in bytes) to which to resize the attribute + * @holes: try creating a hole if expanding * * Change the size of an open ntfs attribute @na to @newsize bytes. If the * attribute is made bigger and the attribute is resident the newly @@ -6327,7 +6330,7 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) * EOPNOTSUPP - The desired resize is not implemented yet. * EACCES - Encrypted attribute. */ -int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) +static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 newsize, BOOL holes) { int ret = STATUS_ERROR; s64 fullsize; @@ -6392,7 +6395,8 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) else fullsize = newsize; if (fullsize > na->data_size) - ret = ntfs_non_resident_attr_expand(na, fullsize); + ret = ntfs_non_resident_attr_expand(na, fullsize, + holes); else ret = ntfs_non_resident_attr_shrink(na, fullsize); } else @@ -6401,7 +6405,25 @@ out: ntfs_log_leave("Return status %d\n", ret); return ret; } - + +/* + * Resize an attribute, creating a hole if relevant + */ + +int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) +{ + return (ntfs_attr_truncate_i(na, newsize, TRUE)); +} + +/* + * Resize an attribute, avoiding hole creation + */ + +int ntfs_attr_truncate_solid(ntfs_attr *na, const s64 newsize) +{ + return (ntfs_attr_truncate_i(na, newsize, FALSE)); +} + /* * Stuff a hole in a compressed file * @@ -6462,7 +6484,7 @@ static int stuff_hole(ntfs_attr *na, const s64 pos) if (!ret && ((na->initialized_size + end_size) < pos) && ntfs_non_resident_attr_expand(na, - pos - end_size)) + pos - end_size, TRUE)) ret = -1; else na->initialized_size diff --git a/ntfsprogs/ntfscp.c b/ntfsprogs/ntfscp.c index a3f2a082..fe6538e5 100644 --- a/ntfsprogs/ntfscp.c +++ b/ntfsprogs/ntfscp.c @@ -528,7 +528,7 @@ int main(int argc, char *argv[]) ntfs_log_verbose("Old file size: %lld\n", (long long)na->data_size); if (na->data_size != new_size) { - if (__ntfs_attr_truncate(na, new_size, FALSE)) { + if (ntfs_attr_truncate_solid(na, new_size)) { ntfs_log_perror("ERROR: Couldn't resize attribute"); goto close_attr; }