From 9d730b0da11e58afc0f84814ec01074d737ca587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Tue, 30 Jul 2013 10:17:28 +0200 Subject: [PATCH] Set the backup boot sector in ntfsresize when the size is reliable Traditionally the backup boot sector is not set by ntfsresize because the exact partition size is not yet known. A chkdsk is triggered to subsequently insert it. However ntfsresize is frequently activated by a partition editor which has an exact knowledge of the wanted layout, and the backup boot sector can be inserted by ntfsresize. This is only done if the target partition size is defined with no unit suffix, and it is a multiple of the sector size. Anyway the backup boot sector cannot overwrite useful data as it is inserted between the file system size and the target partition size. --- ntfsprogs/ntfsresize.c | 46 +++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/ntfsprogs/ntfsresize.c b/ntfsprogs/ntfsresize.c index f6560677..08b4ec44 100644 --- a/ntfsprogs/ntfsresize.c +++ b/ntfsprogs/ntfsresize.c @@ -145,6 +145,7 @@ static struct { int info; int infombonly; int expand; + int reliable_size; int show_progress; int badsectors; int check; @@ -424,8 +425,10 @@ static s64 get_new_volume_size(char *s) if (size <= 0 || errno == ERANGE) err_exit("Illegal new volume size\n"); - if (!*suffix) + if (!*suffix) { + opt.reliable_size = 1; return size; + } if (strlen(suffix) == 2 && suffix[1] == 'i') prefix_kind = 1024; @@ -2570,20 +2573,24 @@ static int setup_lcn_bitmap(struct bitmap *bm, s64 nr_clusters) */ static void update_bootsector(ntfs_resize_t *r) { - NTFS_BOOT_SECTOR bs; - s64 bs_size = sizeof(NTFS_BOOT_SECTOR); + NTFS_BOOT_SECTOR *bs; ntfs_volume *vol = r->vol; + s64 bs_size = vol->sector_size; printf("Updating Boot record ...\n"); + bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size); + if (!bs) + perr_exit("ntfs_malloc"); + if (vol->dev->d_ops->seek(vol->dev, 0, SEEK_SET) == (off_t)-1) perr_exit("lseek"); - if (vol->dev->d_ops->read(vol->dev, &bs, bs_size) == -1) + if (vol->dev->d_ops->read(vol->dev, bs, bs_size) == -1) perr_exit("read() error"); - bs.number_of_sectors = cpu_to_sle64(r->new_volume_size * - bs.bpb.sectors_per_cluster); + bs->number_of_sectors = cpu_to_sle64(r->new_volume_size * + bs->bpb.sectors_per_cluster); if (r->mftmir_old) { r->progress.flags |= NTFS_PROGBAR_SUPPRESS; @@ -2594,12 +2601,12 @@ static void update_bootsector(ntfs_resize_t *r) else copy_clusters(r, r->mftmir_rl.lcn, r->mftmir_old, r->mftmir_rl.length); - bs.mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn); + bs->mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn); r->progress.flags &= ~NTFS_PROGBAR_SUPPRESS; } /* Set the start of the relocated MFT */ if (r->new_mft_start) { - bs.mft_lcn = cpu_to_sle64(r->new_mft_start->lcn); + bs->mft_lcn = cpu_to_sle64(r->new_mft_start->lcn); /* no more need for the new MFT start */ free(r->new_mft_start); r->new_mft_start = (runlist_element*)NULL; @@ -2609,8 +2616,25 @@ static void update_bootsector(ntfs_resize_t *r) perr_exit("lseek"); if (!opt.ro_flag) - if (vol->dev->d_ops->write(vol->dev, &bs, bs_size) == -1) + if (vol->dev->d_ops->write(vol->dev, bs, bs_size) == -1) perr_exit("write() error"); + /* + * Set the backup boot sector, if the target size is + * either not defined or is defined with no multiplier + * suffix and is a multiple of the sector size. + * With these conditions we can be confident enough that + * the partition size is already defined or it will be + * later defined with the same exact value. + */ + if (!opt.ro_flag && opt.reliable_size + && !(opt.bytes % vol->sector_size)) { + if (vol->dev->d_ops->seek(vol->dev, opt.bytes + - vol->sector_size, SEEK_SET) == (off_t)-1) + perr_exit("lseek"); + if (vol->dev->d_ops->write(vol->dev, bs, bs_size) == -1) + perr_exit("write() error"); + } + free(bs); } /** @@ -4372,8 +4396,10 @@ int main(int argc, char **argv) "size!\nCorrupt partition table or incorrect device " "partitioning?\n"); - if (!opt.bytes && !opt.info && !opt.infombonly) + if (!opt.bytes && !opt.info && !opt.infombonly) { opt.bytes = device_size; + opt.reliable_size = 1; + } /* Take the integer part: don't make the volume bigger than requested */ new_size = opt.bytes / vol->cluster_size;