From 459f98c2b21fdc0cb037260d4c062dbcde9aa39a Mon Sep 17 00:00:00 2001 From: flatcap Date: Mon, 19 Sep 2005 20:50:01 +0000 Subject: [PATCH] fix a couple of range bugs (insert,replace) Anton: fix mergeable - use to merge non-adjacent holes Anton: factor out "tail" in replace - simplifying code comment and retest code --- libntfs/runlist.c | 60 +++++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/libntfs/runlist.c b/libntfs/runlist.c index 6fb40803..bb2114af 100644 --- a/libntfs/runlist.c +++ b/libntfs/runlist.c @@ -111,17 +111,21 @@ static __inline__ BOOL ntfs_rl_are_mergeable(runlist_element *dst, return FALSE; } - if ((dst->lcn < 0) || (src->lcn < 0)) { /* Are we merging holes? */ - if (dst->lcn == LCN_HOLE && src->lcn == LCN_HOLE) - return TRUE; + /* We can merge unmapped regions even if they are misaligned. */ + if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED)) + return TRUE; + /* If the runs are misaligned, we cannot merge them. */ + if ((dst->vcn + dst->length) != src->vcn) return FALSE; - } - if ((dst->lcn + dst->length) != src->lcn) /* Are the runs contiguous? */ - return FALSE; - if ((dst->vcn + dst->length) != src->vcn) /* Are the runs misaligned? */ - return FALSE; - - return TRUE; + /* If both runs are non-sparse and contiguous, we can merge them. */ + if ((dst->lcn >= 0) && (src->lcn >= 0) && + ((dst->lcn + dst->length) == src->lcn)) + return TRUE; + /* If we are merging two holes, we can merge them. */ + if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE)) + return TRUE; + /* Cannot merge. */ + return FALSE; } /** @@ -166,7 +170,7 @@ static __inline__ void __ntfs_rl_merge(runlist_element *dst, static __inline__ runlist_element *ntfs_rl_append(runlist_element *dst, int dsize, runlist_element *src, int ssize, int loc) { - BOOL right; /* Right end of @src needs merging */ + BOOL right = FALSE; /* Right end of @src needs merging */ int marker; /* End of the inserted runs */ if (!dst || !src) { @@ -176,7 +180,8 @@ static __inline__ runlist_element *ntfs_rl_append(runlist_element *dst, } /* First, check if the right hand end needs merging. */ - right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1); + if ((loc + 1) < dsize) + right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1); /* Space required: @dst size + @src size, less one if we merged. */ dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right); @@ -330,8 +335,9 @@ static __inline__ runlist_element *ntfs_rl_insert(runlist_element *dst, static __inline__ runlist_element *ntfs_rl_replace(runlist_element *dst, int dsize, runlist_element *src, int ssize, int loc) { - BOOL left = FALSE; /* Left end of @src needs merging */ - BOOL right; /* Right end of @src needs merging */ + BOOL left = FALSE; /* Left end of @src needs merging */ + BOOL right = FALSE; /* Right end of @src needs merging */ + int tail; /* Start of tail of @dst */ int marker; /* End of the inserted runs */ if (!dst || !src) { @@ -340,13 +346,14 @@ static __inline__ runlist_element *ntfs_rl_replace(runlist_element *dst, return NULL; } - /* First, merge the left and right ends, if necessary. */ - right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1); + /* First, see if the left and right ends need merging. */ + if ((loc + 1) < dsize) + right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1); if (loc > 0) left = ntfs_rl_are_mergeable(dst + loc - 1, src); /* Allocate some space. We'll need less if the left, right, or both - * ends were merged. + * ends get merged. */ dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right); if (!dst) @@ -355,24 +362,33 @@ static __inline__ runlist_element *ntfs_rl_replace(runlist_element *dst, * We are guaranteed to succeed from here so can start modifying the * original runlists. */ + + /* First, merge the left and right ends, if necessary. */ if (right) __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); if (left) __ntfs_rl_merge(dst + loc - 1, src); + /* + * tail - Offset of the tail of @dst + * Nominally: @tail = @loc + 1 (location, skipping the replaced run) + * If "right", then one of @dst's runs is already merged into @src. + */ + tail = loc + right + 1; + /* * marker - First run after the @src runs that have been inserted - * Nominally: marker = @loc + @ssize (location + number of runs in @src) + * Nominally: @marker = @loc + @ssize (location + number of runs in @src) * If "left", then the first run in @src has been merged with one in @dst. */ marker = loc + ssize - left; /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, marker, loc + right + 1, dsize - loc - right - 1); + ntfs_rl_mm(dst, marker, tail, dsize - tail); ntfs_rl_mc(dst, loc, src, left, ssize - left); /* We may have changed the length of the file, so fix the end marker */ - if (((dsize - loc - right - 1) > 0) && (dst[marker].lcn == LCN_ENOENT)) + if (((dsize - tail) > 0) && (dst[marker].lcn == LCN_ENOENT)) dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; return dst; @@ -1855,6 +1871,7 @@ static void test_rl_pure (char *contig, char *multi) static runlist_element file4[] = { { 0, -3, 0 } /* NOENT */ }; +#if 0 static runlist_element file5[] = { { 0, -2, 100 }, /* NOTMAP */ { 100, 1100, 100 }, /* DATA */ @@ -1868,6 +1885,7 @@ static void test_rl_pure (char *contig, char *multi) { 100, -2, 100 }, /* NOTMAP */ { 200, -3, 0 } /* NOENT */ }; +#endif BOOL c, m; if (strcmp (contig, "contig") == 0) @@ -1907,6 +1925,7 @@ static void test_rl_pure (char *contig, char *multi) test_rl_pure_test (18, c, m, 140, 40, file3, sizeof (file3)); test_rl_pure_test (19, c, m, 0, 40, file4, sizeof (file4)); test_rl_pure_test (20, c, m, 40, 40, file4, sizeof (file4)); +#if 0 test_rl_pure_test (21, c, m, 0, 40, file5, sizeof (file5)); test_rl_pure_test (22, c, m, 40, 40, file5, sizeof (file5)); test_rl_pure_test (23, c, m, 60, 40, file5, sizeof (file5)); @@ -1921,6 +1940,7 @@ static void test_rl_pure (char *contig, char *multi) test_rl_pure_test (32, c, m, 400, 100, file5, sizeof (file5)); test_rl_pure_test (33, c, m, 160, 100, file6, sizeof (file6)); test_rl_pure_test (34, c, m, 100, 140, file6, sizeof (file6)); +#endif } /**