Skip to content

Instantly share code, notes, and snippets.

@wjt
Last active January 16, 2017 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wjt/855a9c76fab774555ada2c9aeb92cf53 to your computer and use it in GitHub Desktop.
Save wjt/855a9c76fab774555ada2c9aeb92cf53 to your computer and use it in GitHub Desktop.
ntfsextents: fix incorrect handling of merged runs
After the filesystem is defragmented, ntfsextents produced suspicious output
like the following:
...
47934664704 292540416
47934664704 930017280
47934664704 2045247488
...
where a section of the disk repeats. This corresponds to the LCN_RL_NOT_MAPPED
case: it seems that a series of contiguous extents can be represented by more
than one runlist element referencing the same base VCN. The correct mapping
for the example above is:
...
47934664704 292540416
48227205120 637476864
48864681984 1115230208
...
which is what we produce with this patch, which is derived from the
corresponding logic in ntfs_attr_pread_i().
The following equivalent, more aesthetically-pleasing output is not worth the
hassle to produce:
...
47934664704 2045247488
...
https://phabricator.endlessm.com/T13743
Index: ntfs-3g-2014.2.15AR.2/ntfsprogs/ntfsextents.c
===================================================================
--- ntfs-3g-2014.2.15AR.2.orig/ntfsprogs/ntfsextents.c
+++ ntfs-3g-2014.2.15AR.2/ntfsprogs/ntfsextents.c
@@ -42,7 +42,7 @@ int main(int argc, const char *argv[])
ntfs_inode *ni;
ntfs_attr *na = NULL;
runlist_element *rl;
- s64 remaining;
+ s64 ofs, total, remaining;
ntfs_log_set_handler(ntfs_log_handler_stderr);
@@ -100,7 +100,8 @@ int main(int argc, const char *argv[])
goto out;
}
- for (remaining = na->data_size; remaining; rl++) {
+ ofs = - (rl->vcn << vol->cluster_size_bits);
+ for (total = 0, remaining = na->data_size; remaining; rl++, ofs = 0) {
unsigned long data_size;
if (rl->lcn == LCN_RL_NOT_MAPPED) {
@@ -110,6 +111,8 @@ int main(int argc, const char *argv[])
ntfs_log_error("ERROR: Failed to find VCN #2\n");
goto out;
}
+ /* Needed for case when runs merged. */
+ ofs = total - (rl->vcn << vol->cluster_size_bits);
}
if (!rl->length) {
ntfs_log_error("ERROR: Zero run length\n");
@@ -123,8 +126,9 @@ int main(int argc, const char *argv[])
ntfs_log_error("ERROR: File has hole\n");
goto out;
}
- data_size = min(remaining, rl->length << vol->cluster_size_bits);
- printf("%ld %ld\n", rl->lcn << vol->cluster_size_bits, data_size);
+ data_size = min(remaining, (rl->length << vol->cluster_size_bits) - ofs);
+ printf("%ld %ld\n", (rl->lcn << vol->cluster_size_bits) + ofs, data_size);
+ total += data_size;
remaining -= data_size;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment