support passing a template file for the auto-allocation to disklabel.
authorhenning <henning@openbsd.org>
Wed, 29 Apr 2015 09:58:16 +0000 (09:58 +0000)
committerhenning <henning@openbsd.org>
Wed, 29 Apr 2015 09:58:16 +0000 (09:58 +0000)
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

sbin/disklabel/disklabel.8
sbin/disklabel/disklabel.c
sbin/disklabel/editor.c
sbin/disklabel/extern.h

index 4adb090..b73c1f8 100644 (file)
@@ -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
 .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
index 68e3611..d9a6226 100644 (file)
@@ -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");
index abd4944..36df5cd 100644 (file)
@@ -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);
+}
index 2ddea11..92311d4 100644 (file)
@@ -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;