Add start_vcn parameter to ntfs_get_size_for_mapping_pairs() and
ntfs_mapping_pairs_build() and adapt all callers. (Logical change 1.533)edge.strict_endians
parent
3dc22bbae1
commit
06086ae5c7
|
@ -65,13 +65,14 @@ extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
|
|||
extern int ntfs_get_nr_significant_bytes(const s64 n);
|
||||
|
||||
extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
|
||||
const runlist_element *rl);
|
||||
const runlist_element *rl, const VCN start_vcn);
|
||||
|
||||
extern int ntfs_write_significant_bytes(s8 *dst, const s8 *dst_max,
|
||||
const s64 n);
|
||||
|
||||
extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
|
||||
const int dst_len, const runlist_element *rl);
|
||||
const int dst_len, const runlist_element *rl,
|
||||
const VCN start_vcn);
|
||||
|
||||
extern int ntfs_rl_truncate(runlist **rl, const VCN start_vcn);
|
||||
|
||||
|
|
|
@ -2440,7 +2440,7 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na,
|
|||
}
|
||||
}
|
||||
/* Determine the size of the mapping pairs array. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl);
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0);
|
||||
if (mp_size < 0) {
|
||||
err = errno;
|
||||
// FIXME: Eeek!
|
||||
|
@ -2513,7 +2513,7 @@ static int ntfs_attr_make_non_resident(ntfs_attr *na,
|
|||
|
||||
/* Generate the mapping pairs array in the attribute record. */
|
||||
if (ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, arec_size - mp_ofs,
|
||||
rl) < 0) {
|
||||
rl, 0) < 0) {
|
||||
err = errno;
|
||||
// FIXME: Eeek! We need rollback! (AIA)
|
||||
Dprintf("%s(): Eeek! Failed to build mapping pairs. Leaving "
|
||||
|
@ -3018,7 +3018,7 @@ static int ntfs_non_resident_attr_shrink(ntfs_attr *na, const s64 newsize)
|
|||
if (a->highest_vcn)
|
||||
a->highest_vcn = scpu_to_le64(first_free_vcn - 1);
|
||||
/* Get the size for the new mapping pairs array. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, na->rl);
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, na->rl, 0);
|
||||
if (mp_size <= 0) {
|
||||
err = errno;
|
||||
// FIXME: Eeek! We need rollback! (AIA)
|
||||
|
@ -3032,7 +3032,7 @@ static int ntfs_non_resident_attr_shrink(ntfs_attr *na, const s64 newsize)
|
|||
* correct destination, i.e. the attribute record itself.
|
||||
*/
|
||||
if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
|
||||
a->mapping_pairs_offset), mp_size, na->rl)) {
|
||||
a->mapping_pairs_offset), mp_size, na->rl, 0)) {
|
||||
err = errno;
|
||||
// FIXME: Eeek! We need rollback! (AIA)
|
||||
Dprintf("%s(): Eeek! Mapping pairs build "
|
||||
|
@ -3270,7 +3270,7 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize)
|
|||
na->rl = rln;
|
||||
|
||||
/* Get the size for the new mapping pairs array. */
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, na->rl);
|
||||
mp_size = ntfs_get_size_for_mapping_pairs(vol, na->rl, 0);
|
||||
if (mp_size <= 0) {
|
||||
err = errno;
|
||||
Dprintf("%s(): Eeek! Get size for mapping "
|
||||
|
@ -3344,7 +3344,7 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize)
|
|||
* correct destination, i.e. the attribute record itself.
|
||||
*/
|
||||
if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu(
|
||||
a->mapping_pairs_offset), mp_size, na->rl)) {
|
||||
a->mapping_pairs_offset), mp_size, na->rl, 0)) {
|
||||
err = errno;
|
||||
Dprintf("%s(): BUG! Mapping pairs build "
|
||||
"failed. Please run chkdsk and if "
|
||||
|
|
|
@ -1238,10 +1238,12 @@ __inline__ int ntfs_get_nr_significant_bytes(const s64 n)
|
|||
* ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array
|
||||
* @vol: ntfs volume (needed for the ntfs version)
|
||||
* @rl: runlist for which to determine the size of the mapping pairs
|
||||
* @start_vcn: vcn at which to start the mapping pairs array
|
||||
*
|
||||
* Walk the runlist @rl and calculate the size in bytes of the mapping pairs
|
||||
* array corresponding to the runlist @rl. This for example allows us to
|
||||
* allocate a buffer of the right size when building the mapping pairs array.
|
||||
* array corresponding to the runlist @rl, starting at vcn @start_vcn. This
|
||||
* for example allows us to allocate a buffer of the right size when building
|
||||
* the mapping pairs array.
|
||||
*
|
||||
* If @rl is NULL, just return 1 (for the single terminator byte).
|
||||
*
|
||||
|
@ -1249,41 +1251,86 @@ __inline__ int ntfs_get_nr_significant_bytes(const s64 n)
|
|||
* errno set to the error code. The following error codes are defined:
|
||||
* EINVAL - Run list contains unmapped elements. Make sure to only pass
|
||||
* fully mapped runlists to this function.
|
||||
* - @start_vcn is invalid.
|
||||
* EIO - The runlist is corrupt.
|
||||
*/
|
||||
int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
|
||||
const runlist_element *rl)
|
||||
const runlist_element *rl, const VCN start_vcn)
|
||||
{
|
||||
LCN prev_lcn;
|
||||
int i, rls;
|
||||
int rls;
|
||||
|
||||
if (!rl)
|
||||
if (start_vcn < 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (!rl) {
|
||||
if (start_vcn) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* Skip to runlist element containing @start_vcn. */
|
||||
while (rl->length && start_vcn >= rl[1].vcn)
|
||||
rl++;
|
||||
if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
prev_lcn = 0;
|
||||
/* Always need the termining zero byte. */
|
||||
rls = 1;
|
||||
for (prev_lcn = i = 0; rl[i].length; i++) {
|
||||
if (rl[i].length < 0 || rl[i].lcn < LCN_HOLE)
|
||||
/* Do the first partial run if present. */
|
||||
if (start_vcn > rl->vcn) {
|
||||
s64 delta;
|
||||
|
||||
/* We know rl->length != 0 already. */
|
||||
if (rl->length < 0 || rl->lcn < LCN_HOLE)
|
||||
goto err_out;
|
||||
delta = start_vcn - rl->vcn;
|
||||
/* Header byte + length. */
|
||||
rls += 1 + ntfs_get_nr_significant_bytes(rl[i].length);
|
||||
rls += 1 + ntfs_get_nr_significant_bytes(rl->length - delta);
|
||||
/*
|
||||
* If the logical cluster number (lcn) denotes a hole and we
|
||||
* are on NTFS 3.0+, we don't store it at all, i.e. we need
|
||||
* zero space. On earlier NTFS versions we just store the lcn.
|
||||
* Note: this assumes that on NTFS 1.2-, holes are stored with
|
||||
* an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
|
||||
*/
|
||||
if (rl[i].lcn == LCN_HOLE && vol->major_ver >= 3)
|
||||
continue;
|
||||
if (rl->lcn >= 0 || vol->major_ver < 3) {
|
||||
prev_lcn = rl->lcn;
|
||||
if (rl->lcn >= 0)
|
||||
prev_lcn += delta;
|
||||
/* Change in lcn. */
|
||||
rls += ntfs_get_nr_significant_bytes(prev_lcn);
|
||||
}
|
||||
/* Go to next runlist element. */
|
||||
rl++;
|
||||
}
|
||||
/* Do the full runs. */
|
||||
for (; rl->length; rl++) {
|
||||
if (rl->length < 0 || rl->lcn < LCN_HOLE)
|
||||
goto err_out;
|
||||
/* Header byte + length. */
|
||||
rls += 1 + ntfs_get_nr_significant_bytes(rl->length);
|
||||
/*
|
||||
* Change in lcn. Note: this assumes that on NTFS 1.2-, holes
|
||||
* are stored with an lcn of -1 and _not_ a delta_lcn of -1
|
||||
* (unless both are -1).
|
||||
* If the logical cluster number (lcn) denotes a hole and we
|
||||
* are on NTFS 3.0+, we don't store it at all, i.e. we need
|
||||
* zero space. On earlier NTFS versions we just store the lcn.
|
||||
* Note: this assumes that on NTFS 1.2-, holes are stored with
|
||||
* an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
|
||||
*/
|
||||
rls += ntfs_get_nr_significant_bytes(rl[i].lcn - prev_lcn);
|
||||
prev_lcn = rl[i].lcn;
|
||||
if (rl->lcn >= 0 || vol->major_ver < 3) {
|
||||
/* Change in lcn. */
|
||||
rls += ntfs_get_nr_significant_bytes(rl->lcn -
|
||||
prev_lcn);
|
||||
prev_lcn = rl->lcn;
|
||||
}
|
||||
}
|
||||
return rls;
|
||||
err_out:
|
||||
if (rl[i].lcn == LCN_RL_NOT_MAPPED)
|
||||
if (rl->lcn == LCN_RL_NOT_MAPPED)
|
||||
errno = EINVAL;
|
||||
else
|
||||
errno = EIO;
|
||||
|
@ -1348,10 +1395,12 @@ err_out:
|
|||
* @dst: destination buffer to which to write the mapping pairs array
|
||||
* @dst_len: size of destination buffer @dst in bytes
|
||||
* @rl: runlist for which to build the mapping pairs array
|
||||
* @start_vcn: vcn at which to start the mapping pairs array
|
||||
*
|
||||
* Create the mapping pairs array from the runlist @rl and save the array in
|
||||
* @dst. @dst_len is the size of @dst in bytes and it should be at least equal
|
||||
* to the value obtained by calling ntfs_get_size_for_mapping_pairs().
|
||||
* Create the mapping pairs array from the runlist @rl, starting at vcn
|
||||
* @start_vcn and save the array in @dst. @dst_len is the size of @dst in
|
||||
* bytes and it should be at least equal to the value obtained by calling
|
||||
* ntfs_get_size_for_mapping_pairs().
|
||||
*
|
||||
* If @rl is NULL, just write a single terminator byte to @dst.
|
||||
*
|
||||
|
@ -1359,35 +1408,87 @@ err_out:
|
|||
* The following error codes are defined:
|
||||
* EINVAL - Run list contains unmapped elements. Make sure to only pass
|
||||
* fully mapped runlists to this function.
|
||||
* - @start_vcn is invalid.
|
||||
* EIO - The runlist is corrupt.
|
||||
* ENOSPC - The destination buffer is too small.
|
||||
*/
|
||||
int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
|
||||
const int dst_len, const runlist_element *rl)
|
||||
const int dst_len, const runlist_element *rl,
|
||||
const VCN start_vcn)
|
||||
{
|
||||
LCN prev_lcn;
|
||||
s8 *dst_max;
|
||||
int i;
|
||||
s8 len_len, lcn_len;
|
||||
|
||||
if (start_vcn < 0)
|
||||
goto val_err;
|
||||
if (!rl) {
|
||||
if (start_vcn)
|
||||
goto val_err;
|
||||
if (dst_len < 1)
|
||||
goto size_err;
|
||||
/* Terminator byte. */
|
||||
*dst = 0;
|
||||
return 0;
|
||||
}
|
||||
/* Skip to runlist element containing @start_vcn. */
|
||||
while (rl->length && start_vcn >= rl[1].vcn)
|
||||
rl++;
|
||||
if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn)
|
||||
goto val_err;
|
||||
/*
|
||||
* @dst_max is used for bounds checking in
|
||||
* ntfs_write_significant_bytes().
|
||||
*/
|
||||
dst_max = dst + dst_len - 1;
|
||||
for (prev_lcn = i = 0; rl[i].length; i++) {
|
||||
if (rl[i].length < 0 || rl[i].lcn < LCN_HOLE)
|
||||
prev_lcn = 0;
|
||||
/* Do the first partial run if present. */
|
||||
if (start_vcn > rl->vcn) {
|
||||
s64 delta;
|
||||
|
||||
/* We know rl->length != 0 already. */
|
||||
if (rl->length < 0 || rl->lcn < LCN_HOLE)
|
||||
goto err_out;
|
||||
delta = start_vcn - rl->vcn;
|
||||
/* Write length. */
|
||||
len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
|
||||
rl->length - delta);
|
||||
if (len_len < 0)
|
||||
goto size_err;
|
||||
/*
|
||||
* If the logical cluster number (lcn) denotes a hole and we
|
||||
* are on NTFS 3.0+, we don't store it at all, i.e. we need
|
||||
* zero space. On earlier NTFS versions we just write the lcn
|
||||
* change. FIXME: Do we need to write the lcn change or just
|
||||
* the lcn in that case? Not sure as I have never seen this
|
||||
* case on NT4. - We assume that we just need to write the lcn
|
||||
* change until someone tells us otherwise... (AIA)
|
||||
*/
|
||||
if (rl->lcn >= 0 || vol->major_ver < 3) {
|
||||
prev_lcn = rl->lcn;
|
||||
if (rl->lcn >= 0)
|
||||
prev_lcn += delta;
|
||||
/* Write change in lcn. */
|
||||
lcn_len = ntfs_write_significant_bytes(dst + 1 +
|
||||
len_len, dst_max, prev_lcn);
|
||||
if (lcn_len < 0)
|
||||
goto size_err;
|
||||
} else
|
||||
lcn_len = 0;
|
||||
/* Update header byte. */
|
||||
*dst = lcn_len << 4 | len_len;
|
||||
/* Position ourselves at next mapping pairs array element. */
|
||||
dst += 1 + len_len + lcn_len;
|
||||
/* Go to next runlist element. */
|
||||
rl++;
|
||||
}
|
||||
/* Do the full runs. */
|
||||
for (; rl->length; rl++) {
|
||||
if (rl->length < 0 || rl->lcn < LCN_HOLE)
|
||||
goto err_out;
|
||||
/* Write length. */
|
||||
len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
|
||||
rl[i].length);
|
||||
rl->length);
|
||||
if (len_len < 0)
|
||||
goto size_err;
|
||||
/*
|
||||
|
@ -1399,12 +1500,13 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
|
|||
* case on NT4. - We assume that we just need to write the lcn
|
||||
* change until someone tells us otherwise... (AIA)
|
||||
*/
|
||||
if (rl[i].lcn != LCN_HOLE || vol->major_ver < 3) {
|
||||
if (rl->lcn >= 0 || vol->major_ver < 3) {
|
||||
/* Write change in lcn. */
|
||||
lcn_len = ntfs_write_significant_bytes(dst + 1 +
|
||||
len_len, dst_max, rl[i].lcn - prev_lcn);
|
||||
len_len, dst_max, rl->lcn - prev_lcn);
|
||||
if (lcn_len < 0)
|
||||
goto size_err;
|
||||
prev_lcn = rl[i].lcn;
|
||||
prev_lcn = rl->lcn;
|
||||
} else
|
||||
lcn_len = 0;
|
||||
/* Update header byte. */
|
||||
|
@ -1420,8 +1522,11 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
|
|||
size_err:
|
||||
errno = ENOSPC;
|
||||
return -1;
|
||||
val_err:
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
err_out:
|
||||
if (rl[i].lcn == LCN_RL_NOT_MAPPED)
|
||||
if (rl->lcn == LCN_RL_NOT_MAPPED)
|
||||
errno = EINVAL;
|
||||
else
|
||||
errno = EIO;
|
||||
|
|
|
@ -1235,7 +1235,7 @@ static int insert_positioned_attr_in_mft_record(MFT_RECORD *m,
|
|||
} else {
|
||||
hdr_size = 64;
|
||||
if (val_len) {
|
||||
mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl);
|
||||
mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0);
|
||||
if (mpa_size < 0) {
|
||||
err = -errno;
|
||||
Eprintf("Failed to get size for mapping "
|
||||
|
@ -1322,7 +1322,7 @@ static int insert_positioned_attr_in_mft_record(MFT_RECORD *m,
|
|||
Eprintf("Error writing non-resident attribute value."
|
||||
"\n");
|
||||
err = ntfs_mapping_pairs_build(vol, (s8*)a + hdr_size +
|
||||
((name_len + 7) & ~7), mpa_size, rl);
|
||||
((name_len + 7) & ~7), mpa_size, rl, 0);
|
||||
}
|
||||
a->initialized_size = cpu_to_le64(inited_size);
|
||||
if (err < 0 || bw != val_len) {
|
||||
|
@ -1431,7 +1431,7 @@ static int insert_non_resident_attr_in_mft_record(MFT_RECORD *m,
|
|||
} else {
|
||||
hdr_size = 64;
|
||||
if (val_len) {
|
||||
mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl);
|
||||
mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0);
|
||||
if (mpa_size < 0) {
|
||||
err = -errno;
|
||||
Eprintf("Failed to get size for mapping "
|
||||
|
@ -1512,7 +1512,7 @@ static int insert_non_resident_attr_in_mft_record(MFT_RECORD *m,
|
|||
Eprintf("Error writing non-resident attribute value."
|
||||
"\n");
|
||||
err = ntfs_mapping_pairs_build(vol, (s8*)a + hdr_size +
|
||||
((name_len + 7) & ~7), mpa_size, rl);
|
||||
((name_len + 7) & ~7), mpa_size, rl, 0);
|
||||
}
|
||||
if (err < 0 || bw != val_len) {
|
||||
// FIXME: Handle error.
|
||||
|
|
|
@ -669,7 +669,7 @@ static s64 move_datarun (ntfs_volume *vol, ntfs_inode *ino, ATTR_RECORD *rec,
|
|||
|
||||
printf ("move %lld,%lld,%lld to %lld,%lld,%lld\n", run->vcn, run->lcn, run->length, to->vcn, to->lcn, to->length);
|
||||
|
||||
need_from = ntfs_get_size_for_mapping_pairs (vol, from);
|
||||
need_from = ntfs_get_size_for_mapping_pairs(vol, from, 0);
|
||||
printf ("orig data run = %d bytes\n", need_from);
|
||||
|
||||
//ntfs_debug_runlist_dump2 (from, 5, "\t");
|
||||
|
@ -683,7 +683,7 @@ static s64 move_datarun (ntfs_volume *vol, ntfs_inode *ino, ATTR_RECORD *rec,
|
|||
|
||||
//ntfs_debug_runlist_dump2 (from, 5, "\t");
|
||||
|
||||
need_to = ntfs_get_size_for_mapping_pairs (vol, from);
|
||||
need_to = ntfs_get_size_for_mapping_pairs(vol, from, 0);
|
||||
printf ("new data run = %d bytes\n", need_to);
|
||||
|
||||
need_from = calc_attr_length (rec, need_from);
|
||||
|
@ -708,7 +708,8 @@ static s64 move_datarun (ntfs_volume *vol, ntfs_inode *ino, ATTR_RECORD *rec,
|
|||
memset (((u8*)rec) +rec->mapping_pairs_offset, 0, need_to - rec->mapping_pairs_offset);
|
||||
|
||||
// update data runs
|
||||
ntfs_mapping_pairs_build (vol, ((u8*)rec) + rec->mapping_pairs_offset, need_to, from);
|
||||
ntfs_mapping_pairs_build(vol, ((u8*)rec) + rec->mapping_pairs_offset,
|
||||
need_to, from, 0);
|
||||
|
||||
// commit
|
||||
ntfs_inode_mark_dirty (ino);
|
||||
|
|
|
@ -1097,7 +1097,7 @@ static void replace_attribute_runlist(ntfs_volume *vol,
|
|||
|
||||
rl_fixup(&rl);
|
||||
|
||||
if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl)) == -1)
|
||||
if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0)) == -1)
|
||||
perr_exit("ntfs_get_size_for_mapping_pairs");
|
||||
|
||||
if (a->name_length) {
|
||||
|
@ -1157,7 +1157,7 @@ static void replace_attribute_runlist(ntfs_volume *vol,
|
|||
if (!(mp = calloc(1, mp_size)))
|
||||
perr_exit("Couldn't get memory");
|
||||
|
||||
if (ntfs_mapping_pairs_build(vol, mp, mp_size, rl))
|
||||
if (ntfs_mapping_pairs_build(vol, mp, mp_size, rl, 0))
|
||||
perr_exit("ntfs_mapping_pairs_build");
|
||||
|
||||
memmove((u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp, mp_size);
|
||||
|
|
Loading…
Reference in New Issue