From fcdb401959d791ab6c72e41041bed51eeb2ab107 Mon Sep 17 00:00:00 2001 From: "cantab.net!aia21" Date: Tue, 31 Aug 2004 15:33:48 +0000 Subject: [PATCH] Exclude (Logical change 1.518) --- ChangeLog | 5 +- libntfs/attrib.c | 159 +++++++++++++++++------------------------------ 2 files changed, 59 insertions(+), 105 deletions(-) diff --git a/ChangeLog b/ChangeLog index b397d5d1..6388a404 100644 --- a/ChangeLog +++ b/ChangeLog @@ -34,14 +34,12 @@ xx/xx/2004 - 1.9.3-WIP - Add a @start_vcn parameter to lcnalloc.[ch]::ntfs_cluster_alloc. (Yura) - Add ntfscp utility, at present it can only overwrite files. It can - increment file size if we don't need allocate new mft records, - and decrease file size if $ATTRIBUTE_LIST not present. (Yura) + increment/decrease file size if $ATTRIBUTE_LIST not present. (Yura) - Added new API lcnalloc.[ch]::ntfs_cluster_free_from_rl, and made ntfs_cluster_alloc use it. (Yura) - Bugfix in ntfs_cluster_alloc for count = 0. (Yura) - Bugfix in ntfs_attr_map{_whole_,_}runlist: make it not fail if runlist already mapped. (Yura) - - ntfsls: Add a -R recursive option (Giang, Carmelo) - Make ntfslabel pay attention to --no-action. (Yuval) - Several bugfixes in ntfs_cluster_alloc. (Anton) - Make all of libntfs only output anything if configured with @@ -88,6 +86,7 @@ xx/xx/2004 - 1.9.3-WIP in two error code paths in ntfs_compressed_attr_pread(). (Anton) - Fix a bug where an uncompressed block could be misdetected as a compressed one if it was made up of multiple runs. (Anton) + - ntfsls: Add a -R recursive option (Giang, Carmelo) 05/04/2004 - 1.9.1 - Make mkntfs create bootable volumes and fixes/updates. - Update with SuSE 9.1 beta 1 versions of GNU build system. diff --git a/libntfs/attrib.c b/libntfs/attrib.c index 7fdf84d7..ec71707f 100644 --- a/libntfs/attrib.c +++ b/libntfs/attrib.c @@ -3138,16 +3138,15 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) u8 *mft_rec_copy = NULL; u32 mft_rec_copy_size = 0; LCN lcn_seek_from; - VCN first_free_vcn, highest_vcn, cur_highest_vcn; + VCN first_free_vcn; s64 nr_need_allocate; ntfs_volume *vol; ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a, *a2; - MFT_RECORD *m, *m2; + ATTR_RECORD *a; + MFT_RECORD *m; runlist *rl, *rln; u32 new_alen, new_muse; int err, mp_size, cur_max_mp_size, exp_max_mp_size; - ntfs_inode *ni; Dprintf("%s(): Entering for inode 0x%llx, attr 0x%x.\n", __FUNCTION__, (unsigned long long)na->ni->mft_no, na->type); @@ -3163,13 +3162,10 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) err = errno; if (err == ENOENT) err = EIO; - Dprintf("%s(): Eeek! Failed to find first extent of " - "attribute.\n", __FUNCTION__); goto put_err_out; } a = ctx->attr; m = ctx->mrec; - ni = ctx->ntfs_ino; /* * Check that the attribute name hasn't been placed after the mapping @@ -3201,44 +3197,29 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) goto put_err_out; } + if (NInoAttrList(na->ni)) { + err = ENOTSUP; + goto put_err_out; + } + /* The first cluster outside the new allocation. */ first_free_vcn = (newsize + vol->cluster_size - 1) >> vol->cluster_size_bits; - /* Highest VCN in the current allocation. */ - highest_vcn = (na->allocated_size >> vol->cluster_size_bits) - 1; /* * Compare the new allocation with the old one and only allocate * clusters if there is a change. */ - if (highest_vcn + 1 != first_free_vcn) { - /* Highest VCN of current attribute extent. */ - cur_highest_vcn = sle64_to_cpu(a->highest_vcn); - - /* Find last extent of attribute, if already not finded. */ - if (cur_highest_vcn && highest_vcn != cur_highest_vcn) { - if (ntfs_attr_lookup(na->type, na->name, na->name_len, - 0, highest_vcn, NULL, 0, ctx)) { - err = errno; - if (err == ENOENT) - err = EIO; - Dprintf("%s(): Eeek! Failed to find last " - "extent of attribute.\n", __FUNCTION__); - goto put_err_out; - } - } - a2 = ctx->attr; - m2 = ctx->mrec; + if ((na->allocated_size >> vol->cluster_size_bits) != first_free_vcn) { + nr_need_allocate = first_free_vcn - + (na->allocated_size >> vol->cluster_size_bits); - /* Map runlist for it. */ - if (ntfs_attr_map_runlist(na, sle64_to_cpu(a2->lowest_vcn))) { + if (ntfs_attr_map_runlist (na, 0)) { err = errno; - Dprintf("%s(): Eeek! ntfs_attr_map_runlist failed.\n", - __FUNCTION__); + Dprintf("%s(): Eeek! " + "ntfs_attr_map_whole_runlist failed.\n", + __FUNCTION__); goto put_err_out; } - - /* Calculate how many clusters we need to allocate. */ - nr_need_allocate = first_free_vcn - (highest_vcn + 1); /* * Determine first after last LCN of attribute. We will start @@ -3263,7 +3244,8 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) } rl = ntfs_cluster_alloc(vol, nr_need_allocate, lcn_seek_from, - DATA_ZONE, highest_vcn + 1); + DATA_ZONE, na->allocated_size >> + vol->cluster_size_bits); if (!rl) { err = errno; Dprintf("%s(): Eeek! Cluster allocation " @@ -3271,36 +3253,21 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) goto put_err_out; } - /* Append new clusters to attribute runlist. */ - rln = ntfs_runlists_merge(na->rl, rl); + /* Append new clusters to attribute runlist */ + rln = ntfs_runlists_merge (na->rl, rl); if (!rln) { - /* Failed, free just allocated clusters. */ + /* Failed, free just allocated clusters */ err = errno; Dprintf("%s(): Eeek! Run list merge " "failed.\n", __FUNCTION__); - ntfs_cluster_free_from_rl(vol, rl); - free(rl); + ntfs_cluster_free_from_rl (vol, rl); + free (rl); goto put_err_out; } na->rl = rln; - /* - * We need to rebuild mapping only for last extent of attribute. - * Seek to correct position in runlist. - */ - rl = na->rl; - while(rl->vcn != sle64_to_cpu(a2->lowest_vcn)) { - rl++; - if (!rl->length) { - err = EIO; - Dprintf("%s(): Eeek! Failed to find required " - "VCN.\n", __FUNCTION__); - goto rollback; - } - } - /* Get the size for the new mapping pairs array. */ - mp_size = ntfs_get_size_for_mapping_pairs(vol, rl); + mp_size = ntfs_get_size_for_mapping_pairs(vol, na->rl); if (mp_size <= 0) { err = errno; Dprintf("%s(): Eeek! Get size for mapping " @@ -3309,39 +3276,35 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) } /* * Determine maximum possible length of mapping pairs, - * if we shall *not* expand space for mapping pairs. + * if we shall *not* expand space for mapping pairs */ - cur_max_mp_size = le32_to_cpu(a2->length) - - le16_to_cpu(a2->mapping_pairs_offset); + cur_max_mp_size = le32_to_cpu(a->length) - + le16_to_cpu(a->mapping_pairs_offset); /* * Determine maximum possible length of mapping pairs, - * if we shall expand space for mapping pairs. + * if we shall expand space for mapping pairs */ - exp_max_mp_size = le32_to_cpu(m2->bytes_allocated) - - le32_to_cpu(m2->bytes_in_use) + cur_max_mp_size; + exp_max_mp_size = le32_to_cpu(m->bytes_allocated) + - le32_to_cpu(m->bytes_in_use) + cur_max_mp_size; - /* - * We need to allocate new mft records to perform resize. - * Not supported yet. - */ if (mp_size > exp_max_mp_size) { err = ENOTSUP; - Dprintf("%s(): Eeek! Maping pairs size is too big.\n", - __FUNCTION__); + Dprintf("%s(): Eeek! Maping pairs size is" + " too big.\n", __FUNCTION__); goto rollback; } /* Backup mft record. We need this for rollback. */ - mft_rec_copy_size = le32_to_cpu(m2->bytes_in_use); + mft_rec_copy_size = le32_to_cpu(m->bytes_in_use); mft_rec_copy = malloc(mft_rec_copy_size); if (!mft_rec_copy) { err = ENOMEM; Dprintf("%s(): Eeek! Not enough memory to " "allocate %d bytes.\n", __FUNCTION__, - le32_to_cpu(m2->bytes_in_use)); + le32_to_cpu(m->bytes_in_use)); goto rollback; } - memcpy(mft_rec_copy, m2, mft_rec_copy_size); + memcpy(mft_rec_copy, m, mft_rec_copy_size); /* Expand space for mapping pairs if we need this. */ if (mp_size > cur_max_mp_size) { @@ -3349,11 +3312,11 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) * Calculate the new attribute length and mft record * bytes used. */ - new_alen = (le16_to_cpu(a2->mapping_pairs_offset) + new_alen = (le16_to_cpu(a->mapping_pairs_offset) + mp_size + 7) & ~7; - new_muse = le32_to_cpu(m2->bytes_in_use) - - le32_to_cpu(a2->length) + new_alen; - if (new_muse > le32_to_cpu(m2->bytes_allocated)) { + new_muse = le32_to_cpu(m->bytes_in_use) - + le32_to_cpu(a->length) + new_alen; + if (new_muse > le32_to_cpu(m->bytes_allocated)) { Dprintf("%s(): BUG! Ran out of space in" " mft record. Please run chkdsk" " and if that doesn't find any " @@ -3365,20 +3328,20 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) goto rollback; } /* Move the following attributes making space. */ - memmove((u8*)a2 + new_alen, (u8*)a2 + le32_to_cpu( - a2->length), le32_to_cpu( - m2->bytes_in_use) - ((u8*)a2 - - (u8*)m2) - le32_to_cpu(a2->length)); + memmove((u8*)a + new_alen, (u8*)a + le32_to_cpu( + a->length), le32_to_cpu(m->bytes_in_use) + - ((u8*)a - (u8*)m) - le32_to_cpu( + a->length)); /* Update the sizes of the attribute and mft records. */ - a2->length = cpu_to_le32(new_alen); - m2->bytes_in_use = cpu_to_le32(new_muse); + a->length = cpu_to_le32(new_alen); + m->bytes_in_use = cpu_to_le32(new_muse); } /* * Generate the new mapping pairs array directly into the * correct destination, i.e. the attribute record itself. */ - if (ntfs_mapping_pairs_build(vol, (u8*)a2 + le16_to_cpu( - a2->mapping_pairs_offset), mp_size, rl)) { + if (ntfs_mapping_pairs_build(vol, (u8*)a + le16_to_cpu( + a->mapping_pairs_offset), mp_size, na->rl)) { err = errno; Dprintf("%s(): BUG! Mapping pairs build " "failed. Please run chkdsk and if " @@ -3390,39 +3353,35 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize) goto rollback; } - /* - * Reminder: We may not update a->highest_vcn if it equal to 0 - * and our attribute is single extent. - */ - if (a2->highest_vcn) - a2->highest_vcn = scpu_to_le64(first_free_vcn - 1); - - /* Set the inode dirty so it is written out later. */ - if (ctx->ntfs_ino != ni) - ntfs_inode_mark_dirty(ctx->ntfs_ino); - /* Update the attribute record and the ntfs_attr structure. */ na->allocated_size = first_free_vcn << vol->cluster_size_bits; a->allocated_size = scpu_to_le64(na->allocated_size); + /* + * Reminder: We may not update a->highest_vcn if it equal to 0. + */ + if (a->highest_vcn) + a->highest_vcn = scpu_to_le64(first_free_vcn - 1); } /* Update the attribute record and the ntfs attribute structure. */ na->data_size = newsize; a->data_size = scpu_to_le64(newsize); /* Set the inode dirty so it is written out later. */ - ntfs_inode_mark_dirty(ni); + ntfs_inode_mark_dirty(ctx->ntfs_ino); /* Done! */ if (mft_rec_copy) free(mft_rec_copy); ntfs_attr_put_search_ctx(ctx); return 0; rollback: - if (ntfs_cluster_free(vol, na, highest_vcn + 1, -1) < 0) { + if (ntfs_cluster_free(vol, na, na->allocated_size >> + vol->cluster_size_bits, -1) < 0) { Dprintf("%s(): Eeek! Leaking clusters. Run chkdsk!\n", __FUNCTION__); err = EIO; } /* Now, truncate the runlist itself. */ - if (ntfs_rl_truncate(&na->rl, highest_vcn + 1)) { + if (ntfs_rl_truncate(&na->rl, na->allocated_size >> + vol->cluster_size_bits)) { /* * Failed to truncate the runlist, so just throw it away, it * will be mapped afresh on next use. @@ -3432,7 +3391,7 @@ rollback: } /* Restote mft record. */ if (mft_changed) - memcpy(m2, mft_rec_copy, mft_rec_copy_size); + memcpy(m, mft_rec_copy, mft_rec_copy_size); if (mft_rec_copy) free(mft_rec_copy); put_err_out: @@ -3476,10 +3435,6 @@ int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) errno = EINVAL; return -1; } - - if (newsize == na->data_size) - return 0; - /* * Encrypted attributes are not supported. We return access denied, * which is what Windows NT4 does, too.