xref: /csrg-svn/lib/libc/gen/disklabel.c (revision 21417)
1*21417Sdist /*
2*21417Sdist  * Copyright (c) 1983 Regents of the University of California.
3*21417Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21417Sdist  * specifies the terms and conditions for redistribution.
5*21417Sdist  */
610748Ssam 
7*21417Sdist #ifndef lint
8*21417Sdist static char sccsid[] = "@(#)disklabel.c	5.1 (Berkeley) 05/30/85";
9*21417Sdist #endif not lint
10*21417Sdist 
1110748Ssam #include <disktab.h>
1210748Ssam #include <stdio.h>
1310748Ssam 
1410748Ssam static	char *dgetstr();
1510748Ssam 
1610748Ssam struct disktab *
1710748Ssam getdiskbyname(name)
1810748Ssam 	char *name;
1910748Ssam {
2010748Ssam 	static struct disktab disk;
2110748Ssam 	static char localbuf[100], *cp = localbuf;
2210748Ssam 	register struct	disktab *dp = &disk;
2310760Ssam 	register struct partition *pp;
2410760Ssam 	char p, psize[3], pbsize[3], pfsize[3];
2510760Ssam 	char buf[BUFSIZ];
2610748Ssam 
2710748Ssam 	if (dgetent(buf, name) <= 0)
2810748Ssam 		return ((struct disktab *)0);
2910748Ssam 	dp->d_name = cp;
3010748Ssam 	strcpy(cp, name);
3110748Ssam 	cp += strlen(name) + 1;
3210748Ssam 	dp->d_type = dgetstr("ty", &cp);
3310748Ssam 	dp->d_secsize = dgetnum("se");
3410748Ssam 	if (dp->d_secsize < 0)
3510748Ssam 		dp->d_secsize = 512;
3610748Ssam 	dp->d_ntracks = dgetnum("nt");
3710748Ssam 	dp->d_nsectors = dgetnum("ns");
3810748Ssam 	dp->d_ncylinders = dgetnum("nc");
3910748Ssam 	dp->d_rpm = dgetnum("rm");
4010748Ssam 	if (dp->d_rpm < 0)
4110748Ssam 		dp->d_rpm = 3600;
4210760Ssam 	strcpy(psize, "px");
4310760Ssam 	strcpy(pbsize, "bx");
4410760Ssam 	strcpy(pfsize, "fx");
4510748Ssam 	for (p = 'a'; p < 'i'; p++) {
4610760Ssam 		psize[1] = pbsize[1] = pfsize[1] = p;
4710760Ssam 		pp = &dp->d_partitions[p - 'a'];
4810760Ssam 		pp->p_size = dgetnum(psize);
4910760Ssam 		pp->p_bsize = dgetnum(pbsize);
5010760Ssam 		pp->p_fsize = dgetnum(pfsize);
5110748Ssam 	}
5210748Ssam 	return (dp);
5310748Ssam }
5410748Ssam 
5510748Ssam #include <ctype.h>
5610748Ssam 
5710748Ssam static	char *tbuf;
5810748Ssam static	char *dskip();
5910748Ssam static	char *ddecode();
6010748Ssam 
6110748Ssam /*
6210748Ssam  * Get an entry for disk name in buffer bp,
6310748Ssam  * from the diskcap file.  Parse is very rudimentary;
6410748Ssam  * we just notice escaped newlines.
6510748Ssam  */
6610748Ssam static
6710748Ssam dgetent(bp, name)
6810748Ssam 	char *bp, *name;
6910748Ssam {
7010748Ssam 	register char *cp;
7110748Ssam 	register int c;
7210748Ssam 	register int i = 0, cnt = 0;
7310748Ssam 	char ibuf[BUFSIZ];
7410748Ssam 	int tf;
7510748Ssam 
7610748Ssam 	tbuf = bp;
7710748Ssam 	tf = open(DISKTAB, 0);
7810748Ssam 	if (tf < 0)
7910748Ssam 		return (-1);
8010748Ssam 	for (;;) {
8110748Ssam 		cp = bp;
8210748Ssam 		for (;;) {
8310748Ssam 			if (i == cnt) {
8410748Ssam 				cnt = read(tf, ibuf, BUFSIZ);
8510748Ssam 				if (cnt <= 0) {
8610748Ssam 					close(tf);
8710748Ssam 					return (0);
8810748Ssam 				}
8910748Ssam 				i = 0;
9010748Ssam 			}
9110748Ssam 			c = ibuf[i++];
9210748Ssam 			if (c == '\n') {
9310748Ssam 				if (cp > bp && cp[-1] == '\\'){
9410748Ssam 					cp--;
9510748Ssam 					continue;
9610748Ssam 				}
9710748Ssam 				break;
9810748Ssam 			}
9910748Ssam 			if (cp >= bp+BUFSIZ) {
10010748Ssam 				write(2,"Disktab entry too long\n", 23);
10110748Ssam 				break;
10210748Ssam 			} else
10310748Ssam 				*cp++ = c;
10410748Ssam 		}
10510748Ssam 		*cp = 0;
10610748Ssam 
10710748Ssam 		/*
10810748Ssam 		 * The real work for the match.
10910748Ssam 		 */
11010748Ssam 		if (dnamatch(name)) {
11110748Ssam 			close(tf);
11210748Ssam 			return (1);
11310748Ssam 		}
11410748Ssam 	}
11510748Ssam }
11610748Ssam 
11710748Ssam /*
11810748Ssam  * Dnamatch deals with name matching.  The first field of the disktab
11910748Ssam  * entry is a sequence of names separated by |'s, so we compare
12010748Ssam  * against each such name.  The normal : terminator after the last
12110748Ssam  * name (before the first field) stops us.
12210748Ssam  */
12310748Ssam static
12410748Ssam dnamatch(np)
12510748Ssam 	char *np;
12610748Ssam {
12710748Ssam 	register char *Np, *Bp;
12810748Ssam 
12910748Ssam 	Bp = tbuf;
13010748Ssam 	if (*Bp == '#')
13110748Ssam 		return (0);
13210748Ssam 	for (;;) {
13310748Ssam 		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
13410748Ssam 			continue;
13510748Ssam 		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
13610748Ssam 			return (1);
13710748Ssam 		while (*Bp && *Bp != ':' && *Bp != '|')
13810748Ssam 			Bp++;
13910748Ssam 		if (*Bp == 0 || *Bp == ':')
14010748Ssam 			return (0);
14110748Ssam 		Bp++;
14210748Ssam 	}
14310748Ssam }
14410748Ssam 
14510748Ssam /*
14610748Ssam  * Skip to the next field.  Notice that this is very dumb, not
14710748Ssam  * knowing about \: escapes or any such.  If necessary, :'s can be put
14810748Ssam  * into the diskcap file in octal.
14910748Ssam  */
15010748Ssam static char *
15110748Ssam dskip(bp)
15210748Ssam 	register char *bp;
15310748Ssam {
15410748Ssam 
15510748Ssam 	while (*bp && *bp != ':')
15610748Ssam 		bp++;
15710748Ssam 	if (*bp == ':')
15810748Ssam 		bp++;
15910748Ssam 	return (bp);
16010748Ssam }
16110748Ssam 
16210748Ssam /*
16310748Ssam  * Return the (numeric) option id.
16410748Ssam  * Numeric options look like
16510748Ssam  *	li#80
16610748Ssam  * i.e. the option string is separated from the numeric value by
16710748Ssam  * a # character.  If the option is not found we return -1.
16810748Ssam  * Note that we handle octal numbers beginning with 0.
16910748Ssam  */
17010748Ssam static
17110748Ssam dgetnum(id)
17210748Ssam 	char *id;
17310748Ssam {
17410748Ssam 	register int i, base;
17510748Ssam 	register char *bp = tbuf;
17610748Ssam 
17710748Ssam 	for (;;) {
17810748Ssam 		bp = dskip(bp);
17910748Ssam 		if (*bp == 0)
18010748Ssam 			return (-1);
18110748Ssam 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
18210748Ssam 			continue;
18310748Ssam 		if (*bp == '@')
18410748Ssam 			return (-1);
18510748Ssam 		if (*bp != '#')
18610748Ssam 			continue;
18710748Ssam 		bp++;
18810748Ssam 		base = 10;
18910748Ssam 		if (*bp == '0')
19010748Ssam 			base = 8;
19110748Ssam 		i = 0;
19210748Ssam 		while (isdigit(*bp))
19310748Ssam 			i *= base, i += *bp++ - '0';
19410748Ssam 		return (i);
19510748Ssam 	}
19610748Ssam }
19710748Ssam 
19810748Ssam /*
19910748Ssam  * Handle a flag option.
20010748Ssam  * Flag options are given "naked", i.e. followed by a : or the end
20110748Ssam  * of the buffer.  Return 1 if we find the option, or 0 if it is
20210748Ssam  * not given.
20310748Ssam  */
20410748Ssam static
20510748Ssam dgetflag(id)
20610748Ssam 	char *id;
20710748Ssam {
20810748Ssam 	register char *bp = tbuf;
20910748Ssam 
21010748Ssam 	for (;;) {
21110748Ssam 		bp = dskip(bp);
21210748Ssam 		if (!*bp)
21310748Ssam 			return (0);
21410748Ssam 		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
21510748Ssam 			if (!*bp || *bp == ':')
21610748Ssam 				return (1);
21710748Ssam 			else if (*bp == '@')
21810748Ssam 				return (0);
21910748Ssam 		}
22010748Ssam 	}
22110748Ssam }
22210748Ssam 
22310748Ssam /*
22410748Ssam  * Get a string valued option.
22510748Ssam  * These are given as
22610748Ssam  *	cl=^Z
22710748Ssam  * Much decoding is done on the strings, and the strings are
22810748Ssam  * placed in area, which is a ref parameter which is updated.
22910748Ssam  * No checking on area overflow.
23010748Ssam  */
23110748Ssam static char *
23210748Ssam dgetstr(id, area)
23310748Ssam 	char *id, **area;
23410748Ssam {
23510748Ssam 	register char *bp = tbuf;
23610748Ssam 
23710748Ssam 	for (;;) {
23810748Ssam 		bp = dskip(bp);
23910748Ssam 		if (!*bp)
24010748Ssam 			return (0);
24110748Ssam 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
24210748Ssam 			continue;
24310748Ssam 		if (*bp == '@')
24410748Ssam 			return (0);
24510748Ssam 		if (*bp != '=')
24610748Ssam 			continue;
24710748Ssam 		bp++;
24810748Ssam 		return (ddecode(bp, area));
24910748Ssam 	}
25010748Ssam }
25110748Ssam 
25210748Ssam /*
25310748Ssam  * Tdecode does the grung work to decode the
25410748Ssam  * string capability escapes.
25510748Ssam  */
25610748Ssam static char *
25710748Ssam ddecode(str, area)
25810748Ssam 	register char *str;
25910748Ssam 	char **area;
26010748Ssam {
26110748Ssam 	register char *cp;
26210748Ssam 	register int c;
26310748Ssam 	register char *dp;
26410748Ssam 	int i;
26510748Ssam 
26610748Ssam 	cp = *area;
26710748Ssam 	while ((c = *str++) && c != ':') {
26810748Ssam 		switch (c) {
26910748Ssam 
27010748Ssam 		case '^':
27110748Ssam 			c = *str++ & 037;
27210748Ssam 			break;
27310748Ssam 
27410748Ssam 		case '\\':
27510748Ssam 			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
27610748Ssam 			c = *str++;
27710748Ssam nextc:
27810748Ssam 			if (*dp++ == c) {
27910748Ssam 				c = *dp++;
28010748Ssam 				break;
28110748Ssam 			}
28210748Ssam 			dp++;
28310748Ssam 			if (*dp)
28410748Ssam 				goto nextc;
28510748Ssam 			if (isdigit(c)) {
28610748Ssam 				c -= '0', i = 2;
28710748Ssam 				do
28810748Ssam 					c <<= 3, c |= *str++ - '0';
28910748Ssam 				while (--i && isdigit(*str));
29010748Ssam 			}
29110748Ssam 			break;
29210748Ssam 		}
29310748Ssam 		*cp++ = c;
29410748Ssam 	}
29510748Ssam 	*cp++ = 0;
29610748Ssam 	str = *area;
29710748Ssam 	*area = cp;
29810748Ssam 	return (str);
29910748Ssam }
300