[PATCH] partx: add update command

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>
---
 disk-utils/partx.8 |    6 ++-
 disk-utils/partx.c |  112 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/disk-utils/partx.8 b/disk-utils/partx.8
index 6142bd0..6d945f0 100644
--- a/disk-utils/partx.8
+++ b/disk-utils/partx.8
@@ -8,9 +8,9 @@
 partx \- tell the Linux kernel about the presence and numbering of
 on-disk partitions
 .SH SYNOPSIS
-partx [\-a|\-d|\-s] [\-t TYPE] [\-n M:N] [\-] disk
+partx [\-a|\-d|\-s|\-u] [\-t TYPE] [\-n M:N] [\-] disk
 .br
-partx [\-a|\-d|\-s] [\-t TYPE] partition [disk]
+partx [\-a|\-d|\-s|\-u] [\-t TYPE] partition [disk]
 .SH DESCRIPTION
 Given a device or disk-image,
 .B partx
@@ -43,6 +43,8 @@ Add the specified partitions, or read the disk and add all partitions.
 Print the SIZE column in bytes rather than in human-readable format.
 .IP "\fB\-d\fR, \fB\-\-delete\fP"
 Delete the specified partitions or all partitions.
+.IP "\fB\-u\fR, \fB\-\-update\fP"
+Update the specified partitions.
 .IP "\fB\-g\fR, \fB\-\-noheadings\fP"
 Do not print a header line.
 .IP "\fB\-h\fR, \fB\-\-help\fP"
diff --git a/disk-utils/partx.c b/disk-utils/partx.c
index 9091579..45bf773 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:
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux