summaryrefslogtreecommitdiff
path: root/sbin/fdisk
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2021-01-30 18:16:37 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2021-01-30 18:16:37 +0000
commit3be90840a39985a450e532f778578b327fafb741 (patch)
tree748d5ec3856634ef6f22e64c9245f913b17940c6 /sbin/fdisk
parent786f3b09a9c8dac98727784b25a42694a38eb2a9 (diff)
Make editing GPT easier/safer by defaulting offet to beginning of largest
free space and preventing the creation of overlapping partitions. Prompted & tested by landry@
Diffstat (limited to 'sbin/fdisk')
-rw-r--r--sbin/fdisk/cmd.c15
-rw-r--r--sbin/fdisk/gpt.c133
-rw-r--r--sbin/fdisk/gpt.h20
3 files changed, 149 insertions, 19 deletions
diff --git a/sbin/fdisk/cmd.c b/sbin/fdisk/cmd.c
index c467056e0b8..b283116a965 100644
--- a/sbin/fdisk/cmd.c
+++ b/sbin/fdisk/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.98 2017/11/13 21:00:32 krw Exp $ */
+/* $OpenBSD: cmd.c,v 1.99 2021/01/30 18:16:36 krw Exp $ */
/*
* Copyright (c) 1997 Tobias Weingartner
@@ -167,7 +167,6 @@ Xgedit(char *args)
struct gpt_partition *gg;
char *name;
u_int16_t *utf;
- u_int64_t bs, ns;
int i, pn;
pn = strtonum(args, 0, NGPTPARTITIONS - 1, &errstr);
@@ -187,13 +186,11 @@ Xgedit(char *args)
goto done;
}
- bs = getuint64("Partition offset", letoh64(gg->gp_lba_start),
- letoh64(gh.gh_lba_start), letoh64(gh.gh_lba_end));
- ns = getuint64("Partition size", letoh64(gg->gp_lba_end) - bs + 1,
- 1, letoh64(gh.gh_lba_end) - bs + 1);
-
- gg->gp_lba_start = htole64(bs);
- gg->gp_lba_end = htole64(bs + ns - 1);
+ if (GPT_get_lba_start(pn) == -1 ||
+ GPT_get_lba_end(pn) == -1) {
+ *gg = oldpart;
+ goto done;
+ }
name = ask_string("Partition name", utf16le_to_string(gg->gp_name));
if (strlen(name) >= GPTPARTNAMESIZE) {
diff --git a/sbin/fdisk/gpt.c b/sbin/fdisk/gpt.c
index 3048e91c3ea..105035d3bbc 100644
--- a/sbin/fdisk/gpt.c
+++ b/sbin/fdisk/gpt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gpt.c,v 1.11 2016/03/28 16:55:09 mestre Exp $ */
+/* $OpenBSD: gpt.c,v 1.12 2021/01/30 18:16:36 krw Exp $ */
/*
* Copyright (c) 2015 Markus Muller <mmu@grummel.net>
* Copyright (c) 2015 Kenneth R Westerback <krw@openbsd.org>
@@ -42,6 +42,9 @@
struct gpt_header gh;
struct gpt_partition gp[NGPTPARTITIONS];
+struct gpt_partition **sort_gpt(void);
+int lba_start_cmp(const void *e1, const void *e2);
+
int
GPT_get_header(off_t where)
{
@@ -456,3 +459,131 @@ GPT_write(void)
return (0);
}
+
+int
+gp_lba_start_cmp(const void *e1, const void *e2)
+{
+ struct gpt_partition *p1 = *(struct gpt_partition **)e1;
+ struct gpt_partition *p2 = *(struct gpt_partition **)e2;
+ u_int64_t o1;
+ u_int64_t o2;
+
+ o1 = letoh64(p1->gp_lba_start);
+ o2 = letoh64(p2->gp_lba_start);
+
+ if (o1 < o2)
+ return -1;
+ else if (o1 > o2)
+ return 1;
+ else
+ return 0;
+}
+
+struct gpt_partition **
+sort_gpt(void)
+{
+ static struct gpt_partition *sgp[NGPTPARTITIONS+2];
+ unsigned int i, j;
+
+ memset(sgp, 0, sizeof(sgp));
+
+ j = 0;
+ for (i = 0; i < letoh32(gh.gh_part_num); i++) {
+ if (letoh64(gp[i].gp_lba_start) >= letoh64(gh.gh_lba_start))
+ sgp[j++] = &gp[i];
+ }
+
+ if (j > 1) {
+ if (mergesort(sgp, j, sizeof(sgp[0]), gp_lba_start_cmp) == -1) {
+ printf("unable to sort gpt by lba start\n");
+ return NULL;
+ }
+ }
+
+ return (sgp);
+}
+
+int
+GPT_get_lba_start(unsigned int pn)
+{
+ struct gpt_partition **sgp;
+ uint64_t bs, bigbs, nextbs, ns;
+ unsigned int i;
+
+ bs = letoh64(gh.gh_lba_start);
+
+ if (letoh64(gp[pn].gp_lba_start) >= bs) {
+ bs = letoh64(gp[pn].gp_lba_start);
+ } else {
+ sgp = sort_gpt();
+ if (sgp == NULL)
+ return -1;
+ if (sgp[0] != NULL) {
+ bigbs = bs;
+ ns = 0;
+ for (i = 0; sgp[i] != NULL; i++) {
+ nextbs = letoh64(sgp[i]->gp_lba_start);
+ if (bs < nextbs && ns < nextbs - bs) {
+ ns = nextbs - bs;
+ bigbs = bs;
+ }
+ bs = letoh64(sgp[i]->gp_lba_end) + 1;
+ }
+ nextbs = letoh64(gh.gh_lba_end) + 1;
+ if (bs < nextbs && ns < nextbs - bs) {
+ ns = nextbs - bs;
+ bigbs = bs;
+ }
+ if (ns == 0) {
+ printf("no space for partition %u\n", pn);
+ return -1;
+ }
+ bs = bigbs;
+ }
+ }
+
+ bs = getuint64("Partition offset", bs, letoh64(gh.gh_lba_start),
+ letoh64(gh.gh_lba_end));
+
+ for (i = 0; i < letoh32(gh.gh_part_num); i++) {
+ if (i == pn)
+ continue;
+ if (bs >= letoh64(gp[i].gp_lba_start) &&
+ bs <= letoh64(gp[i].gp_lba_end)) {
+ printf("partition %u can't start inside partition %u\n",
+ pn, i);
+ return -1;
+ }
+ }
+
+ gp[pn].gp_lba_start = htole64(bs);
+
+ return 0;
+}
+
+int
+GPT_get_lba_end(unsigned int pn)
+{
+ struct gpt_partition **sgp;
+ uint64_t bs, nextbs, ns;
+ unsigned int i;
+
+ sgp = sort_gpt();
+ if (sgp == NULL)
+ return -1;
+
+ bs = letoh64(gp[pn].gp_lba_start);
+ ns = letoh64(gh.gh_lba_end) - bs + 1;
+ for (i = 0; sgp[i] != NULL; i++) {
+ nextbs = letoh64(sgp[i]->gp_lba_start);
+ if (nextbs > bs) {
+ ns = nextbs - bs;
+ break;
+ }
+ }
+ ns = getuint64("Partition size", ns, 1, ns);
+
+ gp[pn].gp_lba_end = htole64(bs + ns - 1);
+
+ return 0;
+}
diff --git a/sbin/fdisk/gpt.h b/sbin/fdisk/gpt.h
index ace4b2583c0..d6060242d5d 100644
--- a/sbin/fdisk/gpt.h
+++ b/sbin/fdisk/gpt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: gpt.h,v 1.6 2016/01/09 18:10:57 krw Exp $ */
+/* $OpenBSD: gpt.h,v 1.7 2021/01/30 18:16:36 krw Exp $ */
/*
* Copyright (c) 2015 Markus Muller <mmu@grummel.net>
* Copyright (c) 2015 Kenneth R Westerback <krw@openbsd.org>
@@ -16,15 +16,17 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-int GPT_get_hdr(off_t);
-int GPT_get_partition_table(off_t);
-void GPT_get_gpt(int);
-int GPT_init(void);
-int GPT_write(void);
+void GPT_get_gpt(int);
+int GPT_get_hdr(off_t);
+int GPT_get_partition_table(off_t);
+int GPT_get_lba_start(unsigned int);
+int GPT_get_lba_end(unsigned int);
-void GPT_print(char *, int);
-void GPT_print_part(int, char *, int);
-void GPT_print_parthdr(int);
+int GPT_init(void);
+int GPT_write(void);
+void GPT_print(char *, int);
+void GPT_print_part(int, char *, int);
+void GPT_print_parthdr(int);
extern struct gpt_header gh;
extern struct gpt_partition gp[NGPTPARTITIONS];