From e6620be16de9d74017d0cc4095a2ca1f034e85ed Mon Sep 17 00:00:00 2001 From: Yura Pakhuchiy Date: Fri, 8 Jun 2007 13:35:47 +0300 Subject: [PATCH] Do not create holes in ntfs_attr_pwrite that will be instantiated right after creation * Add new API: __ntfs_attr_truncate that allow user to select whether holes should be created or clusters allocated * Update ntfs_attr_pwrite and ntfscp to use it. --- include/ntfs/attrib.h | 1 + libntfs/attrib.c | 27 +++++++++++++++++++++------ ntfsprogs/ntfscp.c | 6 +++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/ntfs/attrib.h b/include/ntfs/attrib.h index a1502c99..2daee4d6 100644 --- a/include/ntfs/attrib.h +++ b/include/ntfs/attrib.h @@ -315,6 +315,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, BOOL sparse); extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize); extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, diff --git a/libntfs/attrib.c b/libntfs/attrib.c index 6bdf7cd8..4864db54 100644 --- a/libntfs/attrib.c +++ b/libntfs/attrib.c @@ -986,7 +986,7 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) /* If the write reaches beyond the end, extend the attribute. */ old_data_size = na->data_size; if (pos + count > na->data_size) { - if (ntfs_attr_truncate(na, pos + count)) { + if (__ntfs_attr_truncate(na, pos + count, FALSE)) { eo = errno; ntfs_log_trace("Attribute extend failed.\n"); errno = eo; @@ -4698,6 +4698,7 @@ put_err_out: * ntfs_non_resident_attr_expand - expand a non-resident, open ntfs attribute * @na: non-resident ntfs attribute to expand * @newsize: new size (in bytes) to which to expand the attribute + * @sparse: if TRUE then will create hole if possible * * Expand the size of a non-resident, open ntfs attribute @na to @newsize bytes, * by allocating new clusters. @@ -4708,7 +4709,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(ntfs_attr *na, const s64 newsize) +static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize, + BOOL sparse) { LCN lcn_seek_from; VCN first_free_vcn; @@ -4758,7 +4760,7 @@ static int ntfs_non_resident_attr_expand(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 && sparse) { rl = ntfs_malloc(0x1000); if (!rl) return -1; @@ -4903,10 +4905,12 @@ put_err_out: return -1; } + /** - * ntfs_attr_truncate - resize an ntfs attribute + * __ntfs_attr_truncate - resize an ntfs attribute * @na: open ntfs attribute to resize * @newsize: new size (in bytes) to which to resize the attribute + * @sparse: if TRUE then will create hole if possible * * 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 @@ -4926,7 +4930,7 @@ put_err_out: * @newsize bytes length. * EOPNOTSUPP - The desired resize is not implemented yet. */ -int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) +int __ntfs_attr_truncate(ntfs_attr *na, const s64 newsize, BOOL sparse) { int ret; @@ -4959,7 +4963,8 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) } if (NAttrNonResident(na)) { if (newsize > na->data_size) - ret = ntfs_non_resident_attr_expand(na, newsize); + ret = ntfs_non_resident_attr_expand(na, newsize, + sparse); else ret = ntfs_non_resident_attr_shrink(na, newsize); } else @@ -4971,6 +4976,16 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) return ret; } + +/** + * Wrapper around __ntfs_attr_truncate that always tries to creates hole + */ +int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) +{ + return __ntfs_attr_truncate(na, newsize, TRUE); +} + + /** * ntfs_attr_readall - read the entire data from an ntfs attribute * @ni: open ntfs inode in which the ntfs attribute resides diff --git a/ntfsprogs/ntfscp.c b/ntfsprogs/ntfscp.c index b7a96927..72af5a96 100644 --- a/ntfsprogs/ntfscp.c +++ b/ntfsprogs/ntfscp.c @@ -1,7 +1,7 @@ /** * ntfscp - Part of the Linux-NTFS project. * - * Copyright (c) 2004-2006 Yura Pakhuchiy + * Copyright (c) 2004-2007 Yura Pakhuchiy * Copyright (c) 2005 Anton Altaparmakov * Copyright (c) 2006 Hil Liao * @@ -85,7 +85,7 @@ static void version(void) { ntfs_log_info("\n%s v%s (libntfs %s) - Overwrite files on NTFS " "volume.\n\n", EXEC_NAME, VERSION, ntfs_libntfs_version()); - ntfs_log_info("Copyright (c) 2004-2006 Yura Pakhuchiy\n"); + ntfs_log_info("Copyright (c) 2004-2007 Yura Pakhuchiy\n"); ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); } @@ -524,7 +524,7 @@ int main(int argc, char *argv[]) ntfs_log_verbose("Old file size: %lld\n", na->data_size); if (na->data_size != new_size) { - if (ntfs_attr_truncate(na, new_size)) { + if (__ntfs_attr_truncate(na, new_size, FALSE)) { ntfs_log_perror("ERROR: Couldn't resize attribute"); goto close_attr; }