Module Name:    src
Committed By:   jnemeth
Date:           Tue Nov 19 05:03:41 UTC 2013

Modified Files:
        src/sbin/gpt: add.c gpt.8 gpt.c map.c map.h

Log Message:
     Add two new options to the "add" subcommand:

-a alignment -- attempt to align the start and size of the partition
-l label -- supply a label for the partition

These options were inspired by FreeBSD's gpart(8) command, but the
code was written by me.


To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/sbin/gpt/add.c src/sbin/gpt/gpt.8
cvs rdiff -u -r1.20 -r1.21 src/sbin/gpt/gpt.c
cvs rdiff -u -r1.3 -r1.4 src/sbin/gpt/map.c
cvs rdiff -u -r1.1.1.1 -r1.2 src/sbin/gpt/map.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/gpt/add.c
diff -u src/sbin/gpt/add.c:1.14 src/sbin/gpt/add.c:1.15
--- src/sbin/gpt/add.c:1.14	Sun May 26 21:26:17 2013
+++ src/sbin/gpt/add.c	Tue Nov 19 05:03:41 2013
@@ -29,7 +29,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/add.c,v 1.14 2006/06/22 22:05:28 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: add.c,v 1.14 2013/05/26 21:26:17 wiz Exp $");
+__RCSID("$NetBSD: add.c,v 1.15 2013/11/19 05:03:41 jnemeth Exp $");
 #endif
 
 #include <sys/types.h>
@@ -46,19 +46,21 @@ __RCSID("$NetBSD: add.c,v 1.14 2013/05/2
 #include "gpt.h"
 
 static uuid_t type;
-static off_t block, size;
+static off_t alignment, block, size;
 static unsigned int entry;
+static uint8_t *name;
 
-const char addmsg[] = "add [-b lba] [-i index] [-s lba] [-t type] "
-	"device ...";
+const char addmsg1[] = "add [-a alignment] [-b lba] [-i index] [-l label]";
+const char addmsg2[] = "    [-s lba] [-t type] device ...";
 
 __dead static void
 usage_add(void)
 {
 
 	fprintf(stderr,
-	    "usage: %s %s\n",
-	    getprogname(), addmsg);
+	    "usage: %s %s\n"
+	    "       %*s %s\n", getprogname(), addmsg1,
+	    (int)strlen(getprogname()), "", addmsg2);
 	exit(1);
 }
 
@@ -72,6 +74,8 @@ add(int fd)
 	struct gpt_hdr *hdr;
 	struct gpt_ent *ent;
 	unsigned int i;
+	off_t alignsecs;
+	
 
 	gpt = map_find(MAP_TYPE_PRI_GPT_HDR);
 	ent = NULL;
@@ -128,15 +132,30 @@ add(int fd)
 		}
 	}
 
-	map = map_alloc(block, size);
-	if (map == NULL) {
-		warnx("%s: error: not enough space available on device", device_name);
-		return;
+	if (alignment > 0) {
+		alignsecs = alignment / secsz;
+		map = map_alloc(block, size, alignsecs);
+		if (map == NULL) {
+			warnx("%s: error: not enough space available on device for an aligned partition", device_name);
+			map = map_alloc(block, size, 0);
+			if (map == NULL) {
+				warnx("%s: error: not enough available on device", device_name);
+				return;
+			}
+		}
+	} else {
+		map = map_alloc(block, size, 0);
+		if (map == NULL) {
+			warnx("%s: error: not enough space available on device", device_name);
+			return;
+		}
 	}
 
 	le_uuid_enc(ent->ent_type, &type);
 	ent->ent_lba_start = htole64(map->map_start);
 	ent->ent_lba_end = htole64(map->map_start + map->map_size - 1LL);
+	if (name != NULL)
+		utf8_to_utf16(name, ent->ent_name, 36);
 
 	hdr->hdr_crc_table = htole32(crc32(tbl->map_data,
 	    le32toh(hdr->hdr_entries) * le32toh(hdr->hdr_entsz)));
@@ -177,10 +196,18 @@ cmd_add(int argc, char *argv[])
 {
 	char *p;
 	int ch, fd;
+	int64_t human_num;
 
 	/* Get the migrate options */
-	while ((ch = getopt(argc, argv, "b:i:s:t:")) != -1) {
+	while ((ch = getopt(argc, argv, "a:b:i:l:s:t:")) != -1) {
 		switch(ch) {
+		case 'a':
+			if (alignment > 0)
+				usage_add();
+			if (dehumanize_number(optarg, &human_num) < 0)
+				usage_add();
+			alignment = human_num;
+			break;
 		case 'b':
 			if (block > 0)
 				usage_add();
@@ -195,6 +222,11 @@ cmd_add(int argc, char *argv[])
 			if (*p != 0 || entry < 1)
 				usage_add();
 			break;
+		case 'l':
+			if (name != NULL)
+				usage_add();
+			name = (uint8_t *)strdup(optarg);
+			break;
 		case 's':
 			if (size > 0)
 				usage_add();
@@ -229,6 +261,13 @@ cmd_add(int argc, char *argv[])
 			continue;
 		}
 
+		if (alignment % secsz != 0) {
+			warnx("Alignment must be a multiple of sector size; ");
+			warnx("the sector size for %s is %d bytes.",
+			    device_name, secsz);
+			continue;
+		}
+
 		add(fd);
 
 		gpt_close(fd);
Index: src/sbin/gpt/gpt.8
diff -u src/sbin/gpt/gpt.8:1.14 src/sbin/gpt/gpt.8:1.15
--- src/sbin/gpt/gpt.8:1.14	Thu Oct 24 06:59:03 2013
+++ src/sbin/gpt/gpt.8	Tue Nov 19 05:03:41 2013
@@ -1,4 +1,4 @@
-.\" $NetBSD: gpt.8,v 1.14 2013/10/24 06:59:03 jnemeth Exp $
+.\" $NetBSD: gpt.8,v 1.15 2013/11/19 05:03:41 jnemeth Exp $
 .\"
 .\" Copyright (c) 2002 Marcel Moolenaar
 .\" All rights reserved.
@@ -26,7 +26,7 @@
 .\"
 .\" $FreeBSD: src/sbin/gpt/gpt.8,v 1.17 2006/06/22 22:22:32 marcel Exp $
 .\"
-.Dd October 23, 2013
+.Dd November 18, 2013
 .Dt GPT 8
 .Os
 .Sh NAME
@@ -104,6 +104,14 @@ of an unused disk space.
 The command-specific options can be used to control this behaviour.
 .Pp
 The
+.Fl a Ar alignment
+option allows the user to specify an alignment for the start and size.
+The alignment may have a suffix to indicate its magnitude.
+.Nm
+will attempt to align the partition.
+If it can not, then it will attempt to create an unaligned partition.
+.Pp
+The
 .Fl b Ar number
 option allows the user to specify the starting (beginning) sector number of
 the partition.
@@ -117,6 +125,10 @@ be used for the new partition.
 By default, the first free entry is selected.
 .Pp
 The
+.Fl l Ar label
+option allows the user to specify a label for the partition.
+.Pp
+The
 .Fl s Ar count
 option allows the user to specify the size of the partition in sectors.
 The minimum size is 1.

Index: src/sbin/gpt/gpt.c
diff -u src/sbin/gpt/gpt.c:1.20 src/sbin/gpt/gpt.c:1.21
--- src/sbin/gpt/gpt.c:1.20	Sat Apr 13 18:32:01 2013
+++ src/sbin/gpt/gpt.c	Tue Nov 19 05:03:41 2013
@@ -31,7 +31,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/gpt.c,v 1.16 2006/07/07 02:44:23 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: gpt.c,v 1.20 2013/04/13 18:32:01 jakllsch Exp $");
+__RCSID("$NetBSD: gpt.c,v 1.21 2013/11/19 05:03:41 jnemeth Exp $");
 #endif
 
 #include <sys/param.h>
@@ -784,8 +784,8 @@ static struct {
 __dead static void
 usage(void)
 {
-	extern const char addmsg[], biosbootmsg[], createmsg[], destroymsg[];
-	extern const char labelmsg1[], labelmsg2[], labelmsg3[];
+	extern const char addmsg1[], addmsg2[], biosbootmsg[], createmsg[];
+	extern const char destroymsg[], labelmsg1[], labelmsg2[], labelmsg3[];
 	extern const char migratemsg[], recovermsg[], removemsg1[];
 	extern const char removemsg2[], showmsg[];
 
@@ -796,13 +796,15 @@ usage(void)
 	    "       %s %s\n"
 	    "       %s %s\n"
 	    "       %s %s\n"
+	    "       %s %s\n"
 	    "       %*s %s\n"
 	    "       %s %s\n"
 	    "       %s %s\n"
 	    "       %s %s\n"
 	    "       %s %s\n"
 	    "       %s %s\n",
-	    getprogname(), addmsg,
+	    getprogname(), addmsg1,
+	    getprogname(), addmsg2,
 	    getprogname(), biosbootmsg,
 	    getprogname(), createmsg,
 	    getprogname(), destroymsg,

Index: src/sbin/gpt/map.c
diff -u src/sbin/gpt/map.c:1.3 src/sbin/gpt/map.c:1.4
--- src/sbin/gpt/map.c:1.3	Sat Oct 26 20:31:23 2013
+++ src/sbin/gpt/map.c	Tue Nov 19 05:03:41 2013
@@ -29,7 +29,7 @@
 __FBSDID("$FreeBSD: src/sbin/gpt/map.c,v 1.6 2005/08/31 01:47:19 marcel Exp $");
 #endif
 #ifdef __RCSID
-__RCSID("$NetBSD: map.c,v 1.3 2013/10/26 20:31:23 jnemeth Exp $");
+__RCSID("$NetBSD: map.c,v 1.4 2013/11/19 05:03:41 jnemeth Exp $");
 #endif
 
 #include <sys/types.h>
@@ -141,28 +141,49 @@ map_add(off_t start, off_t size, int typ
 }
 
 map_t *
-map_alloc(off_t start, off_t size)
+map_alloc(off_t start, off_t size, off_t alignment)
 {
 	off_t delta;
 	map_t *m;
 
+	if (alignment > 0) {
+		if ((start % alignment) != 0)
+			start = (start + alignment) / alignment * alignment;
+		if ((size % alignment) != 0)
+			size = (size + alignment) / alignment * alignment;
+	}
+
 	for (m = mediamap; m != NULL; m = m->map_next) {
 		if (m->map_type != MAP_TYPE_UNUSED || m->map_start < 2)
 			continue;
 		if (start != 0 && m->map_start > start)
 			return (NULL);
-		delta = (start != 0) ? start - m->map_start : 0;
-		if (size == 0 || m->map_size - delta >= size) {
-			if (m->map_size - delta <= 0)
+
+		if (start != 0)
+			delta = start - m->map_start;
+		else if (alignment > 0 && m->map_start % alignment != 0)
+			delta = (m->map_start + alignment) /
+			        alignment * alignment - m->map_start;
+		else
+			delta = 0;
+
+                if (size == 0 || m->map_size - delta >= size) {
+			if (m->map_size - delta < alignment)
 				continue;
-			if (size == 0)
-				size = m->map_size - delta;
-			return (map_add(m->map_start + delta, size,
-				    MAP_TYPE_GPT_PART, NULL));
+			if (size == 0) {
+				if (alignment > 0 &&
+				    (m->map_size - delta) % alignment != 0)
+					size = (m->map_size - delta) /
+					    alignment * alignment;
+				else
+					size = m->map_size - delta;
+			}
+			return map_add(m->map_start + delta, size,
+				    MAP_TYPE_GPT_PART, NULL);
 		}
 	}
 
-	return (NULL);
+	return NULL;
 }
 
 map_t *

Index: src/sbin/gpt/map.h
diff -u src/sbin/gpt/map.h:1.1.1.1 src/sbin/gpt/map.h:1.2
--- src/sbin/gpt/map.h:1.1.1.1	Sun Oct 15 22:34:16 2006
+++ src/sbin/gpt/map.h	Tue Nov 19 05:03:41 2013
@@ -51,7 +51,7 @@ typedef struct map {
 extern int lbawidth;
 
 map_t *map_add(off_t, off_t, int, void*);
-map_t *map_alloc(off_t, off_t);
+map_t *map_alloc(off_t, off_t, off_t);
 map_t *map_find(int);
 map_t *map_first(void);
 map_t *map_last(void);

Reply via email to