summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Brauer <henning@cvs.openbsd.org>2015-04-29 09:58:17 +0000
committerHenning Brauer <henning@cvs.openbsd.org>2015-04-29 09:58:17 +0000
commitbf26c62fb48bc314c1469e85352d390ce2d41ae9 (patch)
treedbe6652adf9e425b89cdd475710ae38eb4047269
parent9262668f605e58651cad2b313f7cb3a50acde70a (diff)
support passing a template file for the auto-allocation to disklabel.
template gives mountpoints, min-max size ranges and percentage of disk foremost intended for autoinstalls, installer bits to follow soon. with input from many, ok theo
-rw-r--r--sbin/disklabel/disklabel.838
-rw-r--r--sbin/disklabel/disklabel.c19
-rw-r--r--sbin/disklabel/editor.c186
-rw-r--r--sbin/disklabel/extern.h3
4 files changed, 228 insertions, 18 deletions
diff --git a/sbin/disklabel/disklabel.8 b/sbin/disklabel/disklabel.8
index 4adb090d2de..b73c1f81eab 100644
--- a/sbin/disklabel/disklabel.8
+++ b/sbin/disklabel/disklabel.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: disklabel.8,v 1.112 2015/02/28 21:51:57 bentley Exp $
+.\" $OpenBSD: disklabel.8,v 1.113 2015/04/29 09:58:16 henning Exp $
.\" $NetBSD: disklabel.8,v 1.9 1995/03/18 14:54:38 cgd Exp $
.\"
.\" Copyright (c) 1987, 1988, 1991, 1993
@@ -33,7 +33,7 @@
.\"
.\" @(#)disklabel.8 8.2 (Berkeley) 4/19/94
.\"
-.Dd $Mdocdate: February 28 2015 $
+.Dd $Mdocdate: April 29 2015 $
.Dt DISKLABEL 8
.Os
.Sh NAME
@@ -42,20 +42,24 @@
.Sh SYNOPSIS
.Nm disklabel
.Op Fl Acdtv
+.Op Fl T Ar file
.Op Fl h | p Ar unit
.Ar disk
.Nm disklabel
.Fl w
.Op Fl Acdnv
+.Op Fl T Ar file
.Ar disk Ar disktype
.Op Ar packid
.Nm disklabel
.Fl e
.Op Fl Acdnv
+.Op Fl T Ar file
.Ar disk
.Nm disklabel
.Fl E
.Op Fl Acdnv
+.Op Fl T Ar file
.Op Fl F Ns | Ns Fl f Ar file
.Ar disk
.Nm disklabel
@@ -196,6 +200,13 @@ file.
Format the label as a
.Xr disktab 5
entry.
+.It Fl T Ar file
+Read the template for automatic allocation from
+.Ar file
+instead of using the builtin one.
+See
+.Sx AUTOMATIC DISK ALLOCATION
+below for the format.
.It Fl v
Print additional information during operation
.Pq verbose mode .
@@ -590,6 +601,29 @@ swap 10% of disk. 80M \(en 2x max physical memory
/ 95% of disk. 700M \(en 4G
swap 5% of disk. 1M \(en 2x max physical memory
.Ed
+.Pp
+A template for the automatic allocation can be passed to disklabel using
+the
+.Fl T
+option.
+The template consists of one line per partition, with each line giving
+mountpoint, min-max size range, and percentage of disk, space-separated.
+Max can be unlimited by specifying '*'.
+If only mountpoint and min size are given, the partition is created with that
+exact size.
+.Pp
+.Bd -literal -offset indent -compact
+/ 250M
+swap 80-256M 10%
+/tmp 120M-4G 8%
+/var 80M-4G 13%
+/usr 900M-2G 5%
+/usr/X11R6 512M-1G 3%
+/usr/local 2G-10G 10%
+/usr/src 1-2G 2%
+/usr/obj 1.3G-2G 4%
+/home 1G-* 45%
+.Ed
.Sh FILES
.Bl -tag -width Pa -compact
.It Pa /etc/disktab
diff --git a/sbin/disklabel/disklabel.c b/sbin/disklabel/disklabel.c
index 68e36118a20..d9a6226e776 100644
--- a/sbin/disklabel/disklabel.c
+++ b/sbin/disklabel/disklabel.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: disklabel.c,v 1.199 2015/02/07 02:09:13 deraadt Exp $ */
+/* $OpenBSD: disklabel.c,v 1.200 2015/04/29 09:58:16 henning Exp $ */
/*
* Copyright (c) 1987, 1993
@@ -122,8 +122,9 @@ main(int argc, char *argv[])
int ch, f, error = 0;
struct disklabel *lp;
FILE *t;
+ char *autotable = NULL;
- while ((ch = getopt(argc, argv, "ABEf:F:hRb:cdenp:tvw")) != -1)
+ while ((ch = getopt(argc, argv, "ABEf:F:hRb:cdenp:tT:vw")) != -1)
switch (ch) {
case 'A':
aflag = 1;
@@ -171,6 +172,9 @@ main(int argc, char *argv[])
case 't':
tflag = 1;
break;
+ case 'T':
+ autotable = optarg;
+ break;
case 'w':
if (op != UNSPEC)
usage();
@@ -220,6 +224,9 @@ main(int argc, char *argv[])
if (f < 0)
err(4, "%s", specname);
+ if (autotable != NULL)
+ parse_autotable(autotable);
+
switch (op) {
case EDIT:
if (argc != 1)
@@ -1467,13 +1474,13 @@ void
usage(void)
{
fprintf(stderr,
- "usage: disklabel [-Acdtv] [-h | -p unit] disk\t(read)\n");
+ "usage: disklabel [-Acdtv] [-h | -p unit] disk\t\t(read)\n");
fprintf(stderr,
- " disklabel -w [-Acdnv] disk disktype [packid]\t(write)\n");
+ " disklabel -w [-Acdnv] [-T file] disk disktype [packid]\t(write)\n");
fprintf(stderr,
- " disklabel -e [-Acdnv] disk\t\t\t(edit)\n");
+ " disklabel -e [-Acdnv] [-T file] disk\t\t\t(edit)\n");
fprintf(stderr,
- " disklabel -E [-Acdnv] [-F|-f file] disk\t\t(simple editor)"
+ " disklabel -E [-Acdnv] [-T file] [-F|-f file] disk\t(simple editor)"
"\n");
fprintf(stderr,
" disklabel -R [-nv] [-F|-f file] disk protofile\t\t(restore)\n\n");
diff --git a/sbin/disklabel/editor.c b/sbin/disklabel/editor.c
index abd494433f0..36df5cd8322 100644
--- a/sbin/disklabel/editor.c
+++ b/sbin/disklabel/editor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: editor.c,v 1.292 2015/03/17 19:11:55 otto Exp $ */
+/* $OpenBSD: editor.c,v 1.293 2015/04/29 09:58:16 henning Exp $ */
/*
* Copyright (c) 1997-2000 Todd C. Miller <Todd.Miller@courtesan.com>
@@ -73,7 +73,7 @@ struct space_allocation {
};
/* entries for swap and var are changed by editor_allocspace() */
-const struct space_allocation alloc_big[] = {
+struct space_allocation alloc_big[] = {
{ MEG(80), GIG(1), 5, "/" },
{ MEG(80), MEG(256), 10, "swap" },
{ MEG(120), GIG(4), 8, "/tmp" },
@@ -91,19 +91,19 @@ const struct space_allocation alloc_big[] = {
/* Anything beyond this leave for the user to decide */
};
-const struct space_allocation alloc_medium[] = {
+struct space_allocation alloc_medium[] = {
{ MEG(800), GIG(2), 5, "/" },
{ MEG(80), MEG(256), 10, "swap" },
{ MEG(900), GIG(3), 78, "/usr" },
{ MEG(256), GIG(2), 7, "/home" }
};
-const struct space_allocation alloc_small[] = {
+struct space_allocation alloc_small[] = {
{ MEG(700), GIG(4), 95, "/" },
{ MEG(1), MEG(256), 5, "swap" }
};
-const struct space_allocation alloc_stupid[] = {
+struct space_allocation alloc_stupid[] = {
{ MEG(1), MEG(2048), 100, "/" }
};
@@ -111,15 +111,18 @@ const struct space_allocation alloc_stupid[] = {
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
#endif
-const struct {
- const struct space_allocation *table;
+struct alloc_table {
+ struct space_allocation *table;
int sz;
-} alloc_table[] = {
+};
+
+struct alloc_table alloc_table_default[] = {
{ alloc_big, nitems(alloc_big) },
{ alloc_medium, nitems(alloc_medium) },
{ alloc_small, nitems(alloc_small) },
{ alloc_stupid, nitems(alloc_stupid) }
};
+struct alloc_table *alloc_table = alloc_table_default;
void edit_parms(struct disklabel *);
void editor_resize(struct disklabel *, char *);
@@ -157,6 +160,11 @@ u_int64_t max_partition_size(struct disklabel *, int);
void display_edit(struct disklabel *, char, u_int64_t);
int64_t getphysmem(void);
void psize(u_int64_t sz, char unit, struct disklabel *lp);
+char *get_token(char **, size_t *);
+int apply_unit(double, u_char, u_int64_t *);
+int parse_sizespec(const char *, double *, char **);
+int parse_sizerange(char *, u_int64_t *, u_int64_t *);
+int parse_pct(char *, int *);
static u_int64_t starting_sector;
static u_int64_t ending_sector;
@@ -578,7 +586,7 @@ again:
lastalloc * sizeof(struct space_allocation));
/* bump max swap based on phys mem, little physmem gets 2x swap */
- if (index == 0) {
+ if (index == 0 && alloc_table == alloc_table_default) {
if (physmem < MEG(256))
alloc[1].minsz = alloc[1].maxsz = 2 * physmem;
else
@@ -2363,3 +2371,163 @@ display_edit(struct disklabel *lp, char unit, u_int64_t fr)
for (i = 0; i < lp->d_npartitions; i++)
display_partition(stdout, lp, i, unit);
}
+
+void
+parse_autotable(char *filename)
+{
+ FILE *cfile;
+ size_t len;
+ char *buf, *p, *t;
+ uint idx = 0, pctsum = 0;
+ struct space_allocation *sa;
+
+ if ((cfile = fopen(filename, "r")) == NULL)
+ err(1, "%s", filename);
+ if ((alloc_table = calloc(1, sizeof(struct alloc_table))) == NULL)
+ err(1, NULL);
+
+ while ((buf = fgetln(cfile, &len)) != NULL) {
+ if ((alloc_table[0].table = reallocarray(alloc_table[0].table,
+ idx + 1, sizeof(*sa))) == NULL)
+ err(1, NULL);
+ sa = &(alloc_table[0].table[idx]);
+ idx++;
+
+ p = buf;
+ if ((sa->mp = get_token(&p, &len)) == NULL ||
+ (sa->mp[0] != '/' && strcmp(sa->mp, "swap")))
+ errx(1, "%s: parse error on line %u", filename, idx);
+ if ((t = get_token(&p, &len)) == NULL ||
+ parse_sizerange(t, &sa->minsz, &sa->maxsz) == -1)
+ errx(1, "%s: parse error on line %u", filename, idx);
+ if ((t = get_token(&p, &len)) != NULL &&
+ parse_pct(t, &sa->rate) == -1)
+ errx(1, "%s: parse error on line %u", filename, idx);
+ if (sa->minsz > sa->maxsz)
+ errx(1, "%s: min size > max size on line %u", filename,
+ idx);
+ pctsum += sa->rate;
+ }
+ if (pctsum > 100)
+ errx(1, "%s: sum of extra space allocation > 100%%", filename);
+ alloc_table[0].sz = idx;
+ fclose(cfile);
+}
+
+char *
+get_token(char **s, size_t *len)
+{
+ char *p, *r;
+ size_t tlen = 0;
+
+ p = *s;
+ while (*len > 0 && !isspace((u_char)*s[0])) {
+ (*s)++;
+ (*len)--;
+ tlen++;
+ }
+ if (tlen == 0)
+ return (NULL);
+
+ /* eat whitespace */
+ while (*len > 0 && isspace((u_char)*s[0])) {
+ (*s)++;
+ (*len)--;
+ }
+
+ tlen++; /* null termination */
+ if ((r = malloc(tlen)) == NULL)
+ err(1, NULL);
+ strlcpy(r, p, tlen);
+ return (r);
+}
+
+int
+apply_unit(double val, u_char unit, u_int64_t *n)
+{
+ u_int64_t factor = 1;
+
+ switch (tolower(unit)) {
+ case 't':
+ factor *= 1024;
+ /* FALLTHROUGH */
+ case 'g':
+ factor *= 1024;
+ /* FALLTHROUGH */
+ case 'm':
+ factor *= 1024;
+ /* FALLTHROUGH */
+ case 'k':
+ factor *= 1024;
+ break;
+ default:
+ return (-1);
+ }
+
+ val *= factor / DEV_BSIZE;
+ if (val > ULLONG_MAX)
+ return (-1);
+ *n = val;
+ return (0);
+}
+
+int
+parse_sizespec(const char *buf, double *val, char **unit)
+{
+ *val = strtod(buf, unit);
+ if ((*val == 0 && *unit == buf) || *val <= 0)
+ return (-1);
+ if (*unit != NULL && *unit[0] == '\0')
+ *unit = NULL;
+ return (0);
+}
+
+int
+parse_sizerange(char *buf, u_int64_t *min, u_int64_t *max)
+{
+ char *p, *unit1 = NULL, *unit2 = NULL;
+ double val1 = 0, val2 = 0;
+
+ if ((p = strchr(buf, '-')) != NULL) {
+ p[0] = '\0';
+ p++;
+ }
+ *max = 0;
+ if (parse_sizespec(buf, &val1, &unit1) == -1)
+ return (-1);
+ if (p != NULL && p[0] != '\0') {
+ if (p[0] == '*')
+ *max = -1;
+ else
+ if (parse_sizespec(p, &val2, &unit2) == -1)
+ return (-1);
+ }
+ if (unit1 == NULL && (unit1 = unit2) == NULL)
+ return (-1);
+ if (apply_unit(val1, unit1[0], min) == -1)
+ return (-1);
+ if (val2 > 0) {
+ if (apply_unit(val2, unit2[0], max) == -1)
+ return (-1);
+ } else
+ if (*max == 0)
+ *max = *min;
+ free(buf);
+ return (0);
+}
+
+int
+parse_pct(char *buf, int *n)
+{
+ const char *errstr;
+
+ if (buf[strlen(buf) - 1] == '%')
+ buf[strlen(buf) - 1] = '\0';
+ *n = strtonum(buf, 0, 100, &errstr);
+ if (errstr) {
+ warnx("parse percent %s: %s", buf, errstr);
+ return (-1);
+ }
+ free(buf);
+ return (0);
+}
diff --git a/sbin/disklabel/extern.h b/sbin/disklabel/extern.h
index 2ddea11139d..92311d4d737 100644
--- a/sbin/disklabel/extern.h
+++ b/sbin/disklabel/extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: extern.h,v 1.25 2014/07/10 13:31:23 florian Exp $ */
+/* $OpenBSD: extern.h,v 1.26 2015/04/29 09:58:16 henning Exp $ */
/*
* Copyright (c) 2003 Theo de Raadt <deraadt@openbsd.org>
@@ -34,6 +34,7 @@ void editor_allocspace(struct disklabel *);
void mpsave(struct disklabel *);
void mpcopy(char **, char **);
void mpfree(char **);
+void parse_autotable(char *);
int writelabel(int, char *, struct disklabel *);
extern char bootarea[], *specname, *fstabfile;