summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2010-04-28 14:40:46 +0200
committerKarel Zak2010-04-28 14:40:46 +0200
commit6a2de3f13134dfd49eb93c7b15552de81b868c8a (patch)
treedbb776360c23ea72c32bb3572e56936d4bf6ad98
parentfdisk: improve add partition dialog (diff)
downloadkernel-qcow2-util-linux-6a2de3f13134dfd49eb93c7b15552de81b868c8a.tar.gz
kernel-qcow2-util-linux-6a2de3f13134dfd49eb93c7b15552de81b868c8a.tar.xz
kernel-qcow2-util-linux-6a2de3f13134dfd49eb93c7b15552de81b868c8a.zip
fdisk: improve 'move begin of partition' command
The 'b' command ("move beginning of data in a partition") implementation is too restricted. For example: Device Boot Start End Blocks Id System /dev/sdb1 2048 22527 10240 83 Linux .... Partition number (1-4): 1 New beginning of data (2048-22527, default 2048): ^^^^^^^^^^ the range is defined by the current partition size. New version: Partition number (1-4): 1 New beginning of data (1-22527, default 2048): ^^^^^^^ allows to move the begin to arbitrary place if the place is not allocated by any other partition. This is useful for people who don't want to use the default partitioning (1MiB offset, 1MiB grain). The 'b' command is expert command and does not force users to use an aligned LBA (fdisk(8) still prints warning (in 'p' command) if any partition is not aligned to the physical sector boundary). Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--fdisk/fdisk.c35
1 files changed, 30 insertions, 5 deletions
diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c
index f2e69dd96..0126e67b5 100644
--- a/fdisk/fdisk.c
+++ b/fdisk/fdisk.c
@@ -2662,7 +2662,8 @@ static void
move_begin(int i) {
struct pte *pe = &ptes[i];
struct partition *p = pe->part_table;
- unsigned int new, first;
+ unsigned int new, free_start, curr_start, last;
+ int x;
if (warn_geometry())
return;
@@ -2670,13 +2671,37 @@ move_begin(int i) {
printf(_("Partition %d has no data area\n"), i + 1);
return;
}
- first = get_partition_start(pe);
- new = read_int(first, first, first + get_nr_sects(p) - 1, first,
+
+ /* the default start is at the second sector of the disk or at the
+ * second sector of the extended partition
+ */
+ free_start = pe->offset ? pe->offset + 1 : 1;
+
+ curr_start = get_partition_start(pe);
+
+ /* look for a free space before the current start of the partition */
+ for (x = 0; x < partitions; x++) {
+ unsigned int end;
+ struct pte *prev_pe = &ptes[x];
+ struct partition *prev_p = prev_pe->part_table;
+
+ if (!prev_p)
+ continue;
+ end = get_partition_start(prev_pe) + get_nr_sects(prev_p);
+
+ if (!is_cleared_partition(prev_p) &&
+ end > free_start && end <= curr_start)
+ free_start = end;
+ }
+
+ last = get_partition_start(pe) + get_nr_sects(p) - 1;
+
+ new = read_int(free_start, curr_start, last, free_start,
_("New beginning of data")) - pe->offset;
if (new != get_nr_sects(p)) {
- first = get_nr_sects(p) + get_start_sect(p) - new;
- set_nr_sects(p, first);
+ unsigned int sects = get_nr_sects(p) + get_start_sect(p) - new;
+ set_nr_sects(p, sects);
set_start_sect(p, new);
pe->changed = 1;
}