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