summaryrefslogtreecommitdiffstats
path: root/disk-utils/partx.c
diff options
context:
space:
mode:
authorPhillip Susi2012-12-14 20:57:25 +0100
committerKarel Zak2012-12-19 10:48:12 +0100
commit3b905b794e93609af7e42459d32b27e7c18ce02e (patch)
treea62b4c1bcc42166aba12c2c20abe1630bb70b2e8 /disk-utils/partx.c
parentsulogin: map NL to CR-NL on output in initial termios settings (diff)
downloadkernel-qcow2-util-linux-3b905b794e93609af7e42459d32b27e7c18ce02e.tar.gz
kernel-qcow2-util-linux-3b905b794e93609af7e42459d32b27e7c18ce02e.tar.xz
kernel-qcow2-util-linux-3b905b794e93609af7e42459d32b27e7c18ce02e.zip
partx: add update command
Update the kernel partition table to match what is on disk. Remove any extra partitions and add any missing ones. Signed-off-by: Phillip Susi <psusi@ubuntu.com>
Diffstat (limited to 'disk-utils/partx.c')
-rw-r--r--disk-utils/partx.c112
1 files changed, 109 insertions, 3 deletions
diff --git a/disk-utils/partx.c b/disk-utils/partx.c
index 909157902..45bf7739f 100644
--- a/disk-utils/partx.c
+++ b/disk-utils/partx.c
@@ -59,6 +59,7 @@ enum {
ACT_LIST,
ACT_SHOW,
ACT_ADD,
+ ACT_UPD,
ACT_DELETE
};
@@ -402,6 +403,105 @@ static int add_parts(int fd, const char *device,
return rc;
}
+static void upd_parts_warnx(const char *device, int first, int last)
+{
+ if (first == last)
+ warnx(_("%s: error updating partition %d"), device, first);
+ else
+ warnx(_("%s: error updating partitions %d-%d"),
+ device, first, last);
+}
+
+static int upd_parts(int fd, const char *device, dev_t devno,
+ blkid_partlist ls, int lower, int upper)
+{
+ int i, n, an, nparts, rc = 0, errfirst = 0, errlast = 0, err;
+ blkid_partition par;
+ uintmax_t start, size;
+
+ assert(fd >= 0);
+ assert(device);
+ assert(ls);
+
+ nparts = blkid_partlist_numof_partitions(ls);
+ if (!lower)
+ lower = 1;
+ if (!upper || lower < 0 || upper < 0) {
+ n = get_max_partno(device, devno);
+ if (!upper)
+ upper = n > nparts ? n : nparts;
+ else if (upper < 0)
+ upper = n + upper + 1;
+ if (lower < 0)
+ lower = n + lower + 1;
+ }
+ if (lower > upper) {
+ warnx(_("specified range <%d:%d> "
+ "does not make sense"), lower, upper);
+ return -1;
+ }
+
+ for (i = 0, n = lower; n <= upper; n++) {
+ par = blkid_partlist_get_partition(ls, i);
+ an = blkid_partition_get_partno(par);
+
+ if (lower && n < lower)
+ continue;
+ if (upper && n > upper)
+ continue;
+
+ start = blkid_partition_get_start(par);
+ size = blkid_partition_get_size(par);
+
+ if (blkid_partition_is_extended(par))
+ /*
+ * Let's follow the Linux kernel and reduce
+ * DOS extended partition to 1 or 2 sectors.
+ */
+ size = min(size, (uintmax_t) 2);
+
+ err = partx_del_partition(fd, n);
+ if (err == -1 && errno == ENXIO)
+ err = 0; /* good, it already doesn't exist */
+ if (an == n)
+ {
+ if (i < nparts)
+ i++;
+ if (err == -1 && errno == EBUSY)
+ {
+ /* try to resize */
+ err = partx_resize_partition(fd, n, start, size);
+ if (verbose)
+ printf(_("%s: partition #%d resized\n"), device, n);
+ if (err == 0)
+ continue;
+ }
+ if (err == 0 && partx_add_partition(fd, n, start, size) == 0) {
+ if (verbose)
+ printf(_("%s: partition #%d added\n"), device, n);
+ continue;
+ }
+ }
+ if (err == 0)
+ continue;
+ rc = -1;
+ if (verbose)
+ warn(_("%s: updating partition #%d failed"), device, n);
+ if (!errfirst)
+ errlast = errfirst = n;
+ else if (errlast + 1 == n)
+ errlast++;
+ else {
+ upd_parts_warnx(device, errfirst, errlast);
+ errlast = errfirst = n;
+ }
+ }
+
+ if (errfirst)
+ upd_parts_warnx(device, errfirst, errlast);
+ return rc;
+}
+
static int list_parts(blkid_partlist ls, int lower, int upper)
{
int i, nparts;
@@ -600,7 +700,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
fputs(USAGE_HEADER, out);
fprintf(out,
- _(" %s [-a|-d|-s] [--nr <n:m> | <partition>] <disk>\n"),
+ _(" %s [-a|-d|-s|-u] [--nr <n:m> | <partition>] <disk>\n"),
program_invocation_short_name);
fputs(USAGE_OPTIONS, out);
@@ -608,7 +708,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
" -d, --delete delete specified partitions or all of them\n"
" -l, --list list partitions (DEPRECATED)\n"
" -s, --show list partitions\n\n"
-
+ " -u, --update update specified partitions or all of them\n"
" -b, --bytes print SIZE in bytes rather than in human readable format\n"
" -g, --noheadings don't print headings for --show\n"
" -n, --nr <n:m> specify the range of partitions (e.g. --nr 2:4)\n"
@@ -650,6 +750,7 @@ int main(int argc, char **argv)
{ "show", no_argument, NULL, 's' },
{ "add", no_argument, NULL, 'a' },
{ "delete", no_argument, NULL, 'd' },
+ { "update", no_argument, NULL, 'u' },
{ "type", required_argument, NULL, 't' },
{ "nr", required_argument, NULL, 'n' },
{ "output", required_argument, NULL, 'o' },
@@ -672,7 +773,7 @@ int main(int argc, char **argv)
atexit(close_stdout);
while ((c = getopt_long(argc, argv,
- "abdglrsvn:t:o:PhV", long_opts, NULL)) != -1) {
+ "abdglrsuvn:t:o:PhV", long_opts, NULL)) != -1) {
err_exclusive_options(c, long_opts, excl, excl_st);
@@ -713,6 +814,9 @@ int main(int argc, char **argv)
case 't':
type = optarg;
break;
+ case 'u':
+ what = ACT_UPD;
+ break;
case 'v':
verbose = 1;
break;
@@ -870,6 +974,8 @@ int main(int argc, char **argv)
case ACT_ADD:
rc = add_parts(fd, wholedisk, ls, lower, upper);
break;
+ case ACT_UPD:
+ rc = upd_parts(fd, wholedisk, disk_devno, ls, lower, upper);
case ACT_NONE:
break;
default: