Home | History | Annotate | Line # | Download | only in disklabel
interact.c revision 1.4
      1 /*	$NetBSD: interact.c,v 1.4 1997/03/18 21:26:44 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed by Christos Zoulas.
     17  * 4. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #ifndef lint
     33 static char rcsid[] = "$NetBSD: interact.c,v 1.4 1997/03/18 21:26:44 christos Exp $";
     34 #endif /* lint */
     35 
     36 #include <stdio.h>
     37 #include <string.h>
     38 #include <stdlib.h>
     39 #include <util.h>
     40 #include <sys/types.h>
     41 #include <sys/param.h>
     42 #define DKTYPENAMES
     43 #include <sys/disklabel.h>
     44 
     45 #include "extern.h"
     46 
     47 static void cmd_help __P((struct disklabel *, char *, int));
     48 static void cmd_print __P((struct disklabel *, char *, int));
     49 static void cmd_part __P((struct disklabel *, char *, int));
     50 static void cmd_label __P((struct disklabel *, char *, int));
     51 static void cmd_round __P((struct disklabel *, char *, int));
     52 static void cmd_name __P((struct disklabel *, char *, int));
     53 static int runcmd __P((char *, struct disklabel *, int));
     54 static int getinput __P((const char *, const char *, const char *, char *));
     55 static void defnum __P((char *, struct disklabel *, int));
     56 static int getnum __P((char *, struct disklabel *));
     57 static void deffstypename __P((char *, int));
     58 static int getfstypename __P((const char *));
     59 
     60 static int rounding = 0;	/* sector rounding */
     61 
     62 static struct cmds {
     63 	const char *name;
     64 	void (*func) __P((struct disklabel *, char *, int));
     65 	const char *help;
     66 } cmds[] = {
     67 	{ "?",	cmd_help,	"print this menu" },
     68 	{ "N",	cmd_name,	"name the label" },
     69 	{ "P",	cmd_print,	"print current partition table" },
     70 	{ "Q",	NULL,		"quit" },
     71 	{ "R",	cmd_round,	"rounding (c)ylinders (s)ectors" },
     72 	{ "W",	cmd_label,	"write the current partition table" },
     73 	{ NULL, NULL,		NULL }
     74 };
     75 
     76 
     77 
     78 static void
     79 cmd_help(lp, s, fd)
     80 	struct disklabel *lp;
     81 	char *s;
     82 	int fd;
     83 {
     84 	struct cmds *cmd;
     85 
     86 	for (cmd = cmds; cmd->name != NULL; cmd++)
     87 		printf("%s\t%s\n", cmd->name, cmd->help);
     88 	printf("[a-%c]\tdefine named partition\n",
     89 	    'a' + getmaxpartitions() - 1);
     90 }
     91 
     92 
     93 static void
     94 cmd_print(lp, s, fd)
     95 	struct disklabel *lp;
     96 	char *s;
     97 	int fd;
     98 {
     99 	display(stdout, lp);
    100 }
    101 
    102 
    103 static void
    104 cmd_name(lp, s, fd)
    105 	struct disklabel *lp;
    106 	char *s;
    107 	int fd;
    108 {
    109 	char line[BUFSIZ];
    110 	int i = getinput(":", "Label name", lp->d_packname, line);
    111 
    112 	if (i <= 0)
    113 		return;
    114 	(void) strncpy(lp->d_packname, line, sizeof(lp->d_packname));
    115 }
    116 
    117 
    118 static void
    119 cmd_round(lp, s, fd)
    120 	struct disklabel *lp;
    121 	char *s;
    122 	int fd;
    123 {
    124 	int i;
    125 	char line[BUFSIZ];
    126 
    127 	i = getinput(":", "Rounding", rounding ? "cylinders" : "sectors", line);
    128 
    129 	if (i <= 0)
    130 		return;
    131 
    132 	switch (line[0]) {
    133 	case 'c':
    134 		rounding = 1;
    135 		return;
    136 	case 's':
    137 		rounding = 0;
    138 		return;
    139 	default:
    140 		printf("Rounding can be (c)ylinders or (s)ectors\n");
    141 		return;
    142 	}
    143 }
    144 
    145 
    146 static void
    147 cmd_part(lp, s, fd)
    148 	struct disklabel *lp;
    149 	char *s;
    150 	int fd;
    151 {
    152 	int i;
    153 	char line[BUFSIZ];
    154 	char def[BUFSIZ];
    155 	int part = *s - 'a';
    156 	struct partition *p = &lp->d_partitions[part];
    157 
    158 	if (part >= lp->d_npartitions)
    159 		lp->d_npartitions = part + 1;
    160 
    161 	for (;;) {
    162 		deffstypename(def, p->p_fstype);
    163 		i = getinput(":", "Filesystem type", def, line);
    164 		if (i <= 0)
    165 			break;
    166 		if ((i = getfstypename(line)) == -1) {
    167 			printf("Invalid file system typename `%s'\n", line);
    168 			continue;
    169 		}
    170 		p->p_fstype = i;
    171 		break;
    172 	}
    173 	for (;;) {
    174 		defnum(def, lp, p->p_offset);
    175 		i = getinput(":", "Start offset", def, line);
    176 		if (i <= 0)
    177 			break;
    178 		if ((i = getnum(line, lp)) == -1) {
    179 			printf("Bad offset `%s'\n", line);
    180 			continue;
    181 		}
    182 		p->p_offset = i;
    183 		break;
    184 	}
    185 	for (;;) {
    186 		defnum(def, lp, p->p_size);
    187 		i = getinput(":", "Partition size", def, line);
    188 		if (i <= 0)
    189 			break;
    190 		if ((i = getnum(line, lp)) == -1) {
    191 			printf("Bad size `%s'\n", line);
    192 			continue;
    193 		}
    194 		p->p_size = i;
    195 		break;
    196 	}
    197 }
    198 
    199 
    200 static void
    201 cmd_label(lp, s, fd)
    202 	struct disklabel *lp;
    203 	char *s;
    204 	int fd;
    205 {
    206 	char line[BUFSIZ];
    207 	int i;
    208 
    209 	i = getinput("?", "Label disk", "n", line);
    210 
    211 	if (i <= 0 || *line != 'y')
    212 		return;
    213 
    214 	if (checklabel(lp) != 0) {
    215 		printf("Label not written\n");
    216 		return;
    217 	}
    218 
    219 	if ((i = writelabel(fd, bootarea, lp)) != 0) {
    220 		printf("Label not written %d\n", strerror(i));
    221 		return;
    222 	}
    223 	printf("Label written\n");
    224 }
    225 
    226 
    227 static int
    228 runcmd(line, lp, fd)
    229 	char *line;
    230 	struct disklabel *lp;
    231 	int fd;
    232 {
    233 	struct cmds *cmd;
    234 
    235 	for (cmd = cmds; cmd->name != NULL; cmd++)
    236 		if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) {
    237 			if (cmd->func == NULL)
    238 				return -1;
    239 			(*cmd->func)(lp, line, fd);
    240 			return;
    241 		}
    242 
    243 	if (line[1] == '\0' &&
    244 	    line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) {
    245 		cmd_part(lp, line, fd);
    246 		return;
    247 	}
    248 
    249 	printf("Unknown command %s\n", line);
    250 }
    251 
    252 
    253 static int
    254 getinput(sep, prompt, def, line)
    255 	const char *sep;
    256 	const char *prompt;
    257 	const char *def;
    258 	char *line;
    259 {
    260 	for (;;) {
    261 		printf("%s", prompt);
    262 		if (def)
    263 			printf(" [%s]", def);
    264 		printf("%s ", sep);
    265 
    266 		if (fgets(line, BUFSIZ, stdin) == NULL)
    267 			return -1;
    268 		if (line[0] == '\n' || line[0] == '\0') {
    269 			if (def)
    270 				return 0;
    271 		}
    272 		else {
    273 			char *p;
    274 
    275 			if ((p = strrchr(line, '\n')) != NULL)
    276 				*p = '\0';
    277 			return 1;
    278 		}
    279 	}
    280 }
    281 
    282 
    283 static void
    284 defnum(buf, lp, size)
    285 	char *buf;
    286 	struct disklabel *lp;
    287 	int size;
    288 {
    289 	(void) snprintf(buf, BUFSIZ, "%gc, %ds, %gM",
    290 	    size / (float) lp->d_secpercyl,
    291 	    size, size  * (lp->d_secsize / (float) (1024 * 1024)));
    292 }
    293 
    294 
    295 static int
    296 getnum(buf, lp)
    297 	char *buf;
    298 	struct disklabel *lp;
    299 {
    300 	char *ep;
    301 	double d = strtod(buf, &ep);
    302 	int rv;
    303 
    304 	if (buf == ep)
    305 		return -1;
    306 
    307 #define ROUND(a)	((a / lp->d_secpercyl) + \
    308 			 ((a % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl
    309 
    310 	switch (*ep) {
    311 	case '\0':
    312 	case 's':
    313 		rv = (int) d;
    314 		break;
    315 
    316 	case 'c':
    317 		rv = (int) (d * lp->d_secpercyl);
    318 		break;
    319 
    320 	case 'M':
    321 		rv =  (int) (d * 1024 * 1024 / lp->d_secsize);
    322 		break;
    323 
    324 	default:
    325 		printf("Unit error %c\n", *ep);
    326 		return -1;
    327 	}
    328 
    329 	if (rounding)
    330 		return ROUND(rv);
    331 	else
    332 		return rv;
    333 }
    334 
    335 
    336 static void
    337 deffstypename(buf, i)
    338 	char *buf;
    339 	int i;
    340 {
    341 	if (i < 0 || i >= DKMAXTYPES)
    342 		i = 0;
    343 	(void) strcpy(buf, fstypenames[i]);
    344 }
    345 
    346 
    347 static int
    348 getfstypename(buf)
    349 	const char *buf;
    350 {
    351 	int i;
    352 
    353 	for (i = 0; i < DKMAXTYPES; i++)
    354 		if (strcmp(buf, fstypenames[i]) == 0)
    355 			return i;
    356 	return -1;
    357 }
    358 
    359 
    360 void
    361 interact(lp, fd)
    362 	struct disklabel *lp;
    363 	int fd;
    364 {
    365 	char line[BUFSIZ];
    366 
    367 	for (;;) {
    368 		if (getinput(">", "partition", NULL, line) == -1)
    369 			return;
    370 		if (runcmd(line, lp, fd) == -1)
    371 			return;
    372 	}
    373 }
    374