Home | History | Annotate | Line # | Download | only in disklabel
interact.c revision 1.8.2.2
      1 /*	$NetBSD: interact.c,v 1.8.2.2 1999/12/17 23:07:32 he 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 #include <sys/cdefs.h>
     33 #ifndef lint
     34 __RCSID("$NetBSD: interact.c,v 1.8.2.2 1999/12/17 23:07:32 he Exp $");
     35 #endif /* lint */
     36 
     37 #include <stdio.h>
     38 #include <string.h>
     39 #include <stdlib.h>
     40 #include <util.h>
     41 #include <sys/types.h>
     42 #include <sys/param.h>
     43 #define FSTYPENAMES
     44 #include <sys/disklabel.h>
     45 
     46 #include "extern.h"
     47 
     48 static void cmd_help __P((struct disklabel *, char *, int));
     49 static void cmd_print __P((struct disklabel *, char *, int));
     50 static void cmd_part __P((struct disklabel *, char *, int));
     51 static void cmd_label __P((struct disklabel *, char *, int));
     52 static void cmd_round __P((struct disklabel *, char *, int));
     53 static void cmd_name __P((struct disklabel *, char *, int));
     54 static int runcmd __P((char *, struct disklabel *, int));
     55 static int getinput __P((const char *, const char *, const char *, char *));
     56 static void defnum __P((char *, struct disklabel *, int));
     57 static int getnum __P((char *, int, struct disklabel *));
     58 static void deffstypename __P((char *, int));
     59 static int getfstypename __P((const char *));
     60 
     61 static int rounding = 0;	/* sector rounding */
     62 
     63 static struct cmds {
     64 	const char *name;
     65 	void (*func) __P((struct disklabel *, char *, int));
     66 	const char *help;
     67 } cmds[] = {
     68 	{ "?",	cmd_help,	"print this menu" },
     69 	{ "N",	cmd_name,	"name the label" },
     70 	{ "P",	cmd_print,	"print current partition table" },
     71 	{ "Q",	NULL,		"quit" },
     72 	{ "R",	cmd_round,	"rounding (c)ylinders (s)ectors" },
     73 	{ "W",	cmd_label,	"write the current partition table" },
     74 	{ NULL, NULL,		NULL }
     75 };
     76 
     77 
     78 
     79 static void
     80 cmd_help(lp, s, fd)
     81 	struct disklabel *lp;
     82 	char *s;
     83 	int fd;
     84 {
     85 	struct cmds *cmd;
     86 
     87 	for (cmd = cmds; cmd->name != NULL; cmd++)
     88 		printf("%s\t%s\n", cmd->name, cmd->help);
     89 	printf("[a-%c]\tdefine named partition\n",
     90 	    'a' + getmaxpartitions() - 1);
     91 }
     92 
     93 
     94 static void
     95 cmd_print(lp, s, fd)
     96 	struct disklabel *lp;
     97 	char *s;
     98 	int fd;
     99 {
    100 	display(stdout, lp);
    101 }
    102 
    103 
    104 static void
    105 cmd_name(lp, s, fd)
    106 	struct disklabel *lp;
    107 	char *s;
    108 	int fd;
    109 {
    110 	char line[BUFSIZ];
    111 	int i = getinput(":", "Label name", lp->d_packname, line);
    112 
    113 	if (i <= 0)
    114 		return;
    115 	(void) strncpy(lp->d_packname, line, sizeof(lp->d_packname));
    116 }
    117 
    118 
    119 static void
    120 cmd_round(lp, s, fd)
    121 	struct disklabel *lp;
    122 	char *s;
    123 	int fd;
    124 {
    125 	int i;
    126 	char line[BUFSIZ];
    127 
    128 	i = getinput(":", "Rounding", rounding ? "cylinders" : "sectors", line);
    129 
    130 	if (i <= 0)
    131 		return;
    132 
    133 	switch (line[0]) {
    134 	case 'c':
    135 		rounding = 1;
    136 		return;
    137 	case 's':
    138 		rounding = 0;
    139 		return;
    140 	default:
    141 		printf("Rounding can be (c)ylinders or (s)ectors\n");
    142 		return;
    143 	}
    144 }
    145 
    146 
    147 static void
    148 cmd_part(lp, s, fd)
    149 	struct disklabel *lp;
    150 	char *s;
    151 	int fd;
    152 {
    153 	int i;
    154 	char line[BUFSIZ];
    155 	char def[BUFSIZ];
    156 	int part = *s - 'a';
    157 	struct partition *p = &lp->d_partitions[part];
    158 
    159 	if (part >= lp->d_npartitions)
    160 		lp->d_npartitions = part + 1;
    161 
    162 	for (;;) {
    163 		deffstypename(def, p->p_fstype);
    164 		i = getinput(":", "Filesystem type", def, line);
    165 		if (i <= 0)
    166 			break;
    167 		if ((i = getfstypename(line)) == -1) {
    168 			printf("Invalid file system typename `%s'\n", line);
    169 			continue;
    170 		}
    171 		p->p_fstype = i;
    172 		break;
    173 	}
    174 	for (;;) {
    175 		defnum(def, lp, p->p_offset);
    176 		i = getinput(":", "Start offset", def, line);
    177 		if (i <= 0)
    178 			break;
    179 		if ((i = getnum(line, 0, lp)) == -1) {
    180 			printf("Bad offset `%s'\n", line);
    181 			continue;
    182 		}
    183 		p->p_offset = i;
    184 		break;
    185 	}
    186 	for (;;) {
    187 		defnum(def, lp, p->p_size);
    188 		i = getinput(":", "Partition size ('$' for all remaining)",
    189 		    def, line);
    190 		if (i <= 0)
    191 			break;
    192 		if ((i = getnum(line, lp->d_secperunit - p->p_offset, lp))
    193 		    == -1) {
    194 			printf("Bad size `%s'\n", line);
    195 			continue;
    196 		}
    197 		p->p_size = i;
    198 		break;
    199 	}
    200 }
    201 
    202 
    203 static void
    204 cmd_label(lp, s, fd)
    205 	struct disklabel *lp;
    206 	char *s;
    207 	int fd;
    208 {
    209 	char line[BUFSIZ];
    210 	int i;
    211 
    212 	i = getinput("?", "Label disk", "n", line);
    213 
    214 	if (i <= 0 || (*line != 'y' && *line != 'Y') )
    215 		return;
    216 
    217 	if (checklabel(lp) != 0) {
    218 		printf("Label not written\n");
    219 		return;
    220 	}
    221 
    222 	if (writelabel(fd, bootarea, lp) != 0) {
    223 		printf("Label not written\n");
    224 		return;
    225 	}
    226 	printf("Label written\n");
    227 }
    228 
    229 
    230 static int
    231 runcmd(line, lp, fd)
    232 	char *line;
    233 	struct disklabel *lp;
    234 	int fd;
    235 {
    236 	struct cmds *cmd;
    237 
    238 	for (cmd = cmds; cmd->name != NULL; cmd++)
    239 		if (strncmp(line, cmd->name, strlen(cmd->name)) == 0) {
    240 			if (cmd->func == NULL)
    241 				return -1;
    242 			(*cmd->func)(lp, line, fd);
    243 			return 0;
    244 		}
    245 
    246 	if (line[1] == '\0' &&
    247 	    line[0] >= 'a' && line[0] < 'a' + getmaxpartitions()) {
    248 		cmd_part(lp, line, fd);
    249 		return 0;
    250 	}
    251 
    252 	printf("Unknown command %s\n", line);
    253 	return 1;
    254 }
    255 
    256 
    257 static int
    258 getinput(sep, prompt, def, line)
    259 	const char *sep;
    260 	const char *prompt;
    261 	const char *def;
    262 	char *line;
    263 {
    264 	for (;;) {
    265 		printf("%s", prompt);
    266 		if (def)
    267 			printf(" [%s]", def);
    268 		printf("%s ", sep);
    269 
    270 		if (fgets(line, BUFSIZ, stdin) == NULL)
    271 			return -1;
    272 		if (line[0] == '\n' || line[0] == '\0') {
    273 			if (def)
    274 				return 0;
    275 		}
    276 		else {
    277 			char *p;
    278 
    279 			if ((p = strrchr(line, '\n')) != NULL)
    280 				*p = '\0';
    281 			return 1;
    282 		}
    283 	}
    284 }
    285 
    286 
    287 static void
    288 defnum(buf, lp, size)
    289 	char *buf;
    290 	struct disklabel *lp;
    291 	int size;
    292 {
    293 	(void) snprintf(buf, BUFSIZ, "%gc, %ds, %gM",
    294 	    size / (float) lp->d_secpercyl,
    295 	    size, size  * (lp->d_secsize / (float) (1024 * 1024)));
    296 }
    297 
    298 
    299 static int
    300 getnum(buf, max, lp)
    301 	char *buf;
    302 	int max;
    303 	struct disklabel *lp;
    304 {
    305 	char *ep;
    306 	double d;
    307 	int rv;
    308 
    309 	if (max && buf[0] == '$' && buf[1] == 0)
    310 		return max;
    311 
    312 	d = strtod(buf, &ep);
    313 	if (buf == ep)
    314 		return -1;
    315 
    316 #define ROUND(a)	((a / lp->d_secpercyl) + \
    317 		 ((a % lp->d_secpercyl) ? 1 : 0)) * lp->d_secpercyl
    318 
    319 	switch (*ep) {
    320 	case '\0':
    321 	case 's':
    322 		rv = (int) d;
    323 		break;
    324 
    325 	case 'c':
    326 		rv = (int) (d * lp->d_secpercyl);
    327 		break;
    328 
    329 	case 'M':
    330 		rv =  (int) (d * 1024 * 1024 / lp->d_secsize);
    331 		break;
    332 
    333 	default:
    334 		printf("Unit error %c\n", *ep);
    335 		return -1;
    336 	}
    337 
    338 	if (rounding)
    339 		return ROUND(rv);
    340 	else
    341 		return rv;
    342 }
    343 
    344 
    345 static void
    346 deffstypename(buf, i)
    347 	char *buf;
    348 	int i;
    349 {
    350 	if (i < 0 || i >= FSMAXTYPES)
    351 		i = 0;
    352 	(void) strcpy(buf, fstypenames[i]);
    353 }
    354 
    355 
    356 static int
    357 getfstypename(buf)
    358 	const char *buf;
    359 {
    360 	int i;
    361 
    362 	for (i = 0; i < FSMAXTYPES; i++)
    363 		if (strcmp(buf, fstypenames[i]) == 0)
    364 			return i;
    365 	return -1;
    366 }
    367 
    368 
    369 void
    370 interact(lp, fd)
    371 	struct disklabel *lp;
    372 	int fd;
    373 {
    374 	char line[BUFSIZ];
    375 
    376 	for (;;) {
    377 		if (getinput(">", "partition", NULL, line) == -1)
    378 			return;
    379 		if (runcmd(line, lp, fd) == -1)
    380 			return;
    381 	}
    382 }
    383