From 38ff4602a7344c8e45aef7e15cec996b49794c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Tue, 19 Jul 2016 11:44:59 +0200 Subject: [PATCH] Cleared the sparse flags when clearing the bad cluster list The bad cluster list may be updated in ntfsresize and ntfsfix. Though technically it is organized as a sparse file, Windows does not set the sparse flags. Do the same to avoid problems with third-party packages. --- ntfsprogs/ntfsfix.c | 44 ++++++++++++++++++++++++++++++++++++++++-- ntfsprogs/ntfsresize.c | 12 +++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/ntfsprogs/ntfsfix.c b/ntfsprogs/ntfsfix.c index 4394d5fb..d56b5c0e 100644 --- a/ntfsprogs/ntfsfix.c +++ b/ntfsprogs/ntfsfix.c @@ -341,6 +341,39 @@ static int empty_journal(ntfs_volume *vol) return 0; } +/* + * Clear the sparse flag of an attribute + */ + +static int clear_sparse(ntfs_attr *na, const char *name) +{ + ntfs_attr_search_ctx *ctx; + int res; + + res = -1; + ctx = ntfs_attr_get_search_ctx(na->ni, NULL); + if (ctx) { + if (!ntfs_attr_lookup(na->type, na->name, na->name_len, + CASE_SENSITIVE, 0, NULL, 0, ctx)) { + na->data_flags &= ~ATTR_IS_SPARSE; + ctx->attr->data_size = cpu_to_sle64(na->data_size); + ctx->attr->initialized_size + = cpu_to_sle64(na->initialized_size); + ctx->attr->flags = cpu_to_le16(na->data_flags); + ctx->attr->compression_unit = 0; + ntfs_inode_mark_dirty(ctx->ntfs_ino); + NInoFileNameSetDirty(na->ni); + res = 0; + } else + ntfs_log_perror("Could not locate attribute for %s", + name); + ntfs_attr_put_search_ctx(ctx); + } else + ntfs_log_perror("Could not get a search context for %s", + name); + return (res); +} + /** * Clear the bad cluster marks (option) */ @@ -372,15 +405,14 @@ static int clear_badclus(ntfs_volume *vol) * (which requires setting the data size according * to allocation), then reallocate a sparse stream * to full size of volume and reset the data size. + * Note : the sparse flags should not be set. */ na->data_size = na->allocated_size; na->initialized_size = na->allocated_size; if (!ntfs_attr_truncate(na,0) && !ntfs_attr_truncate(na,vol->nr_clusters << vol->cluster_size_bits)) { - na->data_size = 0; na->initialized_size = 0; - ni->flags |= FILE_ATTR_SPARSE_FILE; NInoFileNameSetDirty(ni); ok = TRUE; } else { @@ -390,6 +422,14 @@ static int clear_badclus(ntfs_volume *vol) ntfs_log_info("No bad clusters..."); ok = TRUE; } + /* + * The sparse flags are not set after an initial + * formatting, so do the same. + */ + if (ok) { + ni->flags &= ~FILE_ATTR_SPARSE_FILE; + ok = !clear_sparse(na, "$BadClus::$Bad"); + } ntfs_attr_close(na); } else { ntfs_log_perror("Failed to open $BadClus::$Bad"); diff --git a/ntfsprogs/ntfsresize.c b/ntfsprogs/ntfsresize.c index 6e592816..379fb053 100644 --- a/ntfsprogs/ntfsresize.c +++ b/ntfsprogs/ntfsresize.c @@ -2377,6 +2377,7 @@ static void truncate_badclust_bad_attr(ntfs_resize_t *resize) { ntfs_inode *base_ni; ntfs_attr *na; + ntfs_attr_search_ctx *ctx; s64 nr_clusters = resize->new_volume_size; ntfs_volume *vol = resize->vol; @@ -2390,7 +2391,16 @@ static void truncate_badclust_bad_attr(ntfs_resize_t *resize) err_printf("Could not adjust the bad sector list\n"); exit(1); } - na->ni->flags |= FILE_ATTR_SPARSE_FILE; + /* Clear the sparse flags, even if there are bad clusters */ + na->ni->flags &= ~FILE_ATTR_SPARSE_FILE; + na->data_flags &= ~ATTR_IS_SPARSE; + ctx = resize->ctx; + ctx->attr->data_size = cpu_to_sle64(na->data_size); + ctx->attr->initialized_size = cpu_to_sle64(na->initialized_size); + ctx->attr->flags = cpu_to_le16(na->data_flags); + ctx->attr->compression_unit = 0; + ntfs_inode_mark_dirty(ctx->ntfs_ino); + NInoFileNameSetDirty(na->ni); NInoFileNameSetDirty(na->ni); ntfs_attr_close(na);