diff options
| author | christos <christos@NetBSD.org> | 1997-03-08 23:46:08 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 1997-03-08 23:46:08 +0000 |
| commit | 72fbacb380ea4e2dfba5a16e6bdba2004aa2af95 (patch) | |
| tree | ecf83b015392c0e27cb0031506358b4a9ea7734f /sbin/disklabel | |
| parent | d15724228ecb1298eb5d83c24be215ef943f596e (diff) | |
Add -i (interactive mode to create/edit labels) inspired by the SunOS/Solaris
format/partition command.
Diffstat (limited to 'sbin/disklabel')
| -rw-r--r-- | sbin/disklabel/Makefile | 4 | ||||
| -rw-r--r-- | sbin/disklabel/disklabel.8 | 10 | ||||
| -rw-r--r-- | sbin/disklabel/disklabel.c | 44 | ||||
| -rw-r--r-- | sbin/disklabel/extern.h | 36 | ||||
| -rw-r--r-- | sbin/disklabel/interact.c | 370 |
5 files changed, 448 insertions, 16 deletions
diff --git a/sbin/disklabel/Makefile b/sbin/disklabel/Makefile index bf2c52ad497..27d0774f096 100644 --- a/sbin/disklabel/Makefile +++ b/sbin/disklabel/Makefile @@ -1,8 +1,8 @@ -# $NetBSD: Makefile,v 1.18 1995/10/17 16:34:04 cgd Exp $ +# $NetBSD: Makefile,v 1.19 1997/03/08 23:46:08 christos Exp $ # @(#)Makefile 8.2 (Berkeley) 3/17/94 PROG= disklabel -SRCS= disklabel.c dkcksum.c +SRCS= disklabel.c dkcksum.c interact.c MAN= disklabel.5 disklabel.8 .if ${MACHINE} == "amiga" diff --git a/sbin/disklabel/disklabel.8 b/sbin/disklabel/disklabel.8 index 26026ab7530..d843b133212 100644 --- a/sbin/disklabel/disklabel.8 +++ b/sbin/disklabel/disklabel.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: disklabel.8,v 1.12 1996/10/02 13:49:44 christos Exp $ +.\" $NetBSD: disklabel.8,v 1.13 1997/03/08 23:46:09 christos Exp $ .\" .\" Copyright (c) 1987, 1988, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -56,6 +56,10 @@ .Op Fl r .Ar disk .Nm disklabel +.Fl i +.Op Fl r +.Ar disk +.Nm disklabel .Fl R .Op Fl r .Ar disk Ar protofile @@ -186,6 +190,10 @@ and used to rewrite the disk label. Existing bootstrap code is unchanged regardless of whether .Fl r was specified. +.Pp +Labels can also created interactively using the +.Fl e +flag. The .Fl C flag causes the partition offset and size values to be displayed in diff --git a/sbin/disklabel/disklabel.c b/sbin/disklabel/disklabel.c index 6bc6a50bc11..fd64bfbbb42 100644 --- a/sbin/disklabel/disklabel.c +++ b/sbin/disklabel/disklabel.c @@ -1,4 +1,4 @@ -/* $NetBSD: disklabel.c,v 1.36 1996/10/20 21:59:36 thorpej Exp $ */ +/* $NetBSD: disklabel.c,v 1.37 1997/03/08 23:46:10 christos Exp $ */ /* * Copyright (c) 1987, 1993 @@ -47,7 +47,7 @@ static char copyright[] = /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94"; #else -static char rcsid[] = "$NetBSD: disklabel.c,v 1.36 1996/10/20 21:59:36 thorpej Exp $"; +static char rcsid[] = "$NetBSD: disklabel.c,v 1.37 1997/03/08 23:46:10 christos Exp $"; #endif #endif /* not lint */ @@ -71,6 +71,7 @@ static char rcsid[] = "$NetBSD: disklabel.c,v 1.36 1996/10/20 21:59:36 thorpej E #include <stdlib.h> #include <unistd.h> #include "pathnames.h" +#include "extern.h" /* * Disklabel: read and write disklabels. @@ -103,7 +104,7 @@ static char tmpfil[] = _PATH_TMP; static char namebuf[BBSIZE], *np = namebuf; static struct disklabel lab; -static char bootarea[BBSIZE]; +char bootarea[BBSIZE]; #if NUMBOOT > 0 @@ -117,7 +118,7 @@ static char boot1[MAXPATHLEN]; #endif static enum { - UNSPEC, EDIT, READ, RESTORE, SETWRITEABLE, WRITE, WRITEBOOT + UNSPEC, EDIT, READ, RESTORE, SETWRITEABLE, WRITE, WRITEBOOT, INTERACT } op = UNSPEC; static int rflag; @@ -126,9 +127,9 @@ static int Cflag; #ifdef DEBUG static int debug; -#define OPTIONS "BCNRWb:ders:tw" +#define OPTIONS "BCNRWb:deirs:tw" #else -#define OPTIONS "BCNRWb:ers:tw" +#define OPTIONS "BCNRWb:eirs:tw" #endif #ifdef __i386__ @@ -141,21 +142,17 @@ extern u_short dkcksum __P((struct disklabel *)); static void makedisktab __P((FILE *, struct disklabel *)); static void makelabel __P((char *, char *, struct disklabel *)); -static int writelabel __P((int, char *, struct disklabel *)); static void l_perror __P((char *)); static struct disklabel *readlabel __P((int)); static struct disklabel *makebootarea __P((char *, struct disklabel *, int)); -static void display __P((FILE *, struct disklabel *)); static int edit __P((struct disklabel *, int)); static int editit __P((void)); static char *skip __P((char *)); static char *word __P((char *)); static int getasciilabel __P((FILE *, struct disklabel *)); -static int checklabel __P((struct disklabel *)); static void setbootflag __P((struct disklabel *)); static void usage __P((void)); - int main(argc, argv) int argc; @@ -205,6 +202,11 @@ main(argc, argv) usage(); op = EDIT; break; + case 'i': + if (op != UNSPEC) + usage(); + op = INTERACT; + break; case 't': ++tflag; break; @@ -282,6 +284,20 @@ main(argc, argv) error = edit(lp, f); break; + case INTERACT: + if (argc != 1) + usage(); + lp = readlabel(f); + /* + * XXX: Fill some default values so checklabel does not fail + */ + if (lp->d_bbsize == 0) + lp->d_bbsize = BBSIZE; + if (lp->d_sbsize == 0) + lp->d_sbsize = SBSIZE; + interact(lp, f); + break; + case READ: if (argc != 1) usage(); @@ -393,7 +409,7 @@ makelabel(type, name, lp) (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); } -static int +int writelabel(f, boot, lp) int f; char *boot; @@ -874,7 +890,7 @@ makedisktab(f, lp) (void) fflush(f); } -static void +void display(f, lp) FILE *f; struct disklabel *lp; @@ -1416,7 +1432,7 @@ getasciilabel(f, lp) * Check disklabel for errors and fill in * derived fields according to supplied values. */ -static int +int checklabel(lp) struct disklabel *lp; { @@ -1584,6 +1600,8 @@ usage() "(to write label)" }, { "%s -e [-r] disk", "(to edit label)" }, + { "%s -i [-r] disk", + "(to create a label interactively)" }, { "%s -R [-r] disk protofile", "(to restore label)" }, #endif diff --git a/sbin/disklabel/extern.h b/sbin/disklabel/extern.h new file mode 100644 index 00000000000..1b8334c9ccb --- /dev/null +++ b/sbin/disklabel/extern.h @@ -0,0 +1,36 @@ +/* $NetBSD: extern.h,v 1.1 1997/03/08 23:46:11 christos Exp $ */ + +/* + * Copyright (c) 1997 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +int writelabel __P((int, char *, struct disklabel *)); +int checklabel __P((struct disklabel *)); +void display __P((FILE *, struct disklabel *)); +int interac __P((struct disklabel *, int)); +extern char bootarea[]; diff --git a/sbin/disklabel/interact.c b/sbin/disklabel/interact.c new file mode 100644 index 00000000000..e7cfdea17f1 --- /dev/null +++ b/sbin/disklabel/interact.c @@ -0,0 +1,370 @@ +/* $NetBSD: interact.c,v 1.1 1997/03/08 23:46:12 christos Exp $ */ + +/* + * Copyright (c) 1997 Christos Zoulas. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christos Zoulas. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$NetBSD: interact.c,v 1.1 1997/03/08 23:46:12 christos Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/param.h> +#define DKTYPENAMES +#include <sys/disklabel.h> + +#include "extern.h" + +static void cmd_help __P((struct disklabel *, char *, int)); +static void cmd_print __P((struct disklabel *, char *, int)); +static void cmd_part __P((struct disklabel *, char *, int)); +static void cmd_label __P((struct disklabel *, char *, int)); +static void cmd_round __P((struct disklabel *, char *, int)); +static void cmd_name __P((struct disklabel *, char *, int)); +static int runcmd __P((char *, struct disklabel *, int)); +static int getinput __P((const char *, const char *, const char *, char *)); +static void defnum __P((char *, struct disklabel *, int)); +static int getnum __P((char *, struct disklabel *)); +static void deffstypename __P((char *, int)); +static int getfstypename __P((const char *)); + +static int rounding = 0; /* sector rounding */ + +static struct cmds { + const char *name; + void (*func) __P((struct disklabel *, char *, int)); + const char *help; +} cmds[] = { + { "a", cmd_part, "define partition a" }, + { "b", cmd_part, "define partition b" }, + { "c", cmd_part, "define partition c" }, + { "d", cmd_part, "define partition d" }, + { "e", cmd_part, "define partition e" }, + { "f", cmd_part, "define partition f" }, + { "g", cmd_part, "define partition g" }, + { "h", cmd_part, "define partition h" }, + { "l", cmd_label, "write the current partition table" }, + { "n", cmd_name, "name the label" }, + { "p", cmd_print, "print current partition table" }, + { "q", NULL, "quit" }, + { "r", cmd_round, "rounding (c)ylinders (s)ectors" }, + { "?", cmd_help, "print this menu" }, + { NULL, NULL, NULL } +}; + + + +static void +cmd_help(lp, s, fd) + struct disklabel *lp; + char *s; + int fd; +{ + struct cmds *cmd; + for (cmd = cmds; cmd->name != NULL; cmd++) + printf("%s\t%s\n", cmd->name, cmd->help); +} + + +static void +cmd_print(lp, s, fd) + struct disklabel *lp; + char *s; + int fd; +{ + display(stdout, lp); +} + + +static void +cmd_name(lp, s, fd) + struct disklabel *lp; + char *s; + int fd; +{ + char line[BUFSIZ]; + int i = getinput(":", "Label name", lp->d_packname, line); + + if (i <= 0) + return; + (void) strncpy(lp->d_packname, line, sizeof(lp->d_packname)); +} + + +static void +cmd_round(lp, s, fd) + struct disklabel *lp; + char *s; + int fd; +{ + int i; + char line[BUFSIZ]; + + i = getinput(":", "Rounding", rounding ? "cylinders" : "sectors", line); + + if (i <= 0) + return; + + switch (line[0]) { + case 'c': + rounding = 1; + return; + case 's': + rounding = 0; + return; + default: + printf("Rounding can be (c)ylinders or (s)ectors\n"); + return; + } +} + + +static void +cmd_part(lp, s, fd) + struct disklabel *lp; + char *s; + int fd; +{ + int i; + char line[BUFSIZ]; + char def[BUFSIZ]; + int part = *s - 'a'; + struct partition *p = &lp->d_partitions[part]; + + if (part <= lp->d_npartitions) + lp->d_npartitions = part + 1; + + for (;;) { + deffstypename(def, p->p_fstype); + i = getinput(":", "Filesystem type", def, line); + if (i <= 0) + break; + if ((i = getfstypename(line)) == -1) { + printf("Invalid file system typename `%s'\n", line); + continue; + } + p->p_fstype = i; + break; + } + for (;;) { + defnum(def, lp, p->p_offset); + i = getinput(":", "Start offset", def, line); + if (i <= 0) + break; + if ((i = getnum(line, lp)) == -1) { + printf("Bad offset `%s'\n", line); + continue; + } + p->p_offset = i; + break; + } + for (;;) { + defnum(def, lp, p->p_size); + i = getinput(":", "Partition size", def, line); + if (i <= 0) + break; + if ((i = getnum(line, lp)) == -1) { + printf("Bad size `%s'\n", line); + continue; + } + p->p_size = i; + break; + } +} + + +static void +cmd_label(lp, s, fd) + struct disklabel *lp; + char *s; + int fd; +{ + char line[BUFSIZ]; + int i; + + i = getinput("?", "Label disk", "n", line); + + if (i <= 0 || *line != 'y') + return; + + if (checklabel(lp) != 0) { + printf("Label not written\n"); + return; + } + + if ((i = writelabel(fd, bootarea, lp)) != 0) { + printf("Label not written %d\n", strerror(i)); + return; + } + printf("Label written\n"); +} + + +static int +runcmd(line, lp, fd) + char *line; + struct disklabel *lp; + int fd; +{ + struct cmds *cmd; + + for (cmd = cmds; cmd->name != NULL; cmd++) + if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) { + if (cmd->func == NULL) + return -1; + (*cmd->func)(lp, line, fd); + return; + } + printf("Unknown command %s\n", line); +} + + +static int +getinput(sep, prompt, def, line) + const char *sep; + const char *prompt; + const char *def; + char *line; +{ + for (;;) { + printf("%s", prompt); + if (def) + printf(" [%s]", def); + printf("%s ", sep); + + if (fgets(line, BUFSIZ, stdin) == NULL) + return -1; + if (line[0] == '\n' || line[0] == '\0') { + if (def) + return 0; + } + else { + char *p; + + if ((p = strrchr(line, '\n')) != NULL) + *p = '\0'; + return 1; + } + } +} + + +static void +defnum(buf, lp, size) + char *buf; + struct disklabel *lp; + int size; +{ + (void) snprintf(buf, BUFSIZ, "%gc, %ds, %gM", + size / (float) lp->d_secpercyl, + size, size * (lp->d_secsize / (float) (1024 * 1024))); +} + + +static int +getnum(buf, lp) + char *buf; + struct disklabel *lp; +{ + char *ep; + double d = strtod(buf, &ep); + int rv; + + if (buf == ep) + return -1; + +#define ROUND(a) ((a / lp->d_secpercyl) + \ + ((a % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl + + switch (*ep) { + case '\0': + case 's': + rv = (int) d; + break; + + case 'c': + rv = (int) (d * lp->d_secpercyl); + break; + + case 'M': + rv = (int) (d * 1024 * 1024 / lp->d_secsize); + break; + + default: + printf("Unit error %c\n", *ep); + return -1; + } + + if (rounding) + return ROUND(rv); + else + return rv; +} + + +static void +deffstypename(buf, i) + char *buf; + int i; +{ + if (i < 0 || i >= DKMAXTYPES) + i = 0; + (void) strcpy(buf, fstypenames[i]); +} + + +static int +getfstypename(buf) + const char *buf; +{ + int i; + + for (i = 0; i < DKMAXTYPES; i++) + if (strcmp(buf, fstypenames[i]) == 0) + return i; + return -1; +} + + +void +interact(lp, fd) + struct disklabel *lp; + int fd; +{ + char line[BUFSIZ]; + + for (;;) { + if (getinput(">", "partition", NULL, line) == -1) + return; + if (runcmd(line, lp, fd) == -1) + return; + } +} |
