xref: /original-bsd/lib/libc/gen/disklabel.c (revision ef743ec4)
1*ef743ec4Ssam /*	@(#)disklabel.c	4.2 (Berkeley) 02/08/83	*/
29876a848Ssam 
39876a848Ssam #include <disktab.h>
49876a848Ssam #include <stdio.h>
59876a848Ssam 
69876a848Ssam static	char *dgetstr();
79876a848Ssam 
89876a848Ssam struct disktab *
99876a848Ssam getdiskbyname(name)
109876a848Ssam 	char *name;
119876a848Ssam {
129876a848Ssam 	static struct disktab disk;
139876a848Ssam 	static char localbuf[100], *cp = localbuf;
149876a848Ssam 	register struct	disktab *dp = &disk;
15*ef743ec4Ssam 	register struct partition *pp;
16*ef743ec4Ssam 	char p, psize[3], pbsize[3], pfsize[3];
17*ef743ec4Ssam 	char buf[BUFSIZ];
189876a848Ssam 
199876a848Ssam 	if (dgetent(buf, name) <= 0)
209876a848Ssam 		return ((struct disktab *)0);
219876a848Ssam 	dp->d_name = cp;
229876a848Ssam 	strcpy(cp, name);
239876a848Ssam 	cp += strlen(name) + 1;
249876a848Ssam 	dp->d_type = dgetstr("ty", &cp);
259876a848Ssam 	dp->d_secsize = dgetnum("se");
269876a848Ssam 	if (dp->d_secsize < 0)
279876a848Ssam 		dp->d_secsize = 512;
289876a848Ssam 	dp->d_ntracks = dgetnum("nt");
299876a848Ssam 	dp->d_nsectors = dgetnum("ns");
309876a848Ssam 	dp->d_ncylinders = dgetnum("nc");
319876a848Ssam 	dp->d_rpm = dgetnum("rm");
329876a848Ssam 	if (dp->d_rpm < 0)
339876a848Ssam 		dp->d_rpm = 3600;
34*ef743ec4Ssam 	strcpy(psize, "px");
35*ef743ec4Ssam 	strcpy(pbsize, "bx");
36*ef743ec4Ssam 	strcpy(pfsize, "fx");
379876a848Ssam 	for (p = 'a'; p < 'i'; p++) {
38*ef743ec4Ssam 		psize[1] = pbsize[1] = pfsize[1] = p;
39*ef743ec4Ssam 		pp = &dp->d_partitions[p - 'a'];
40*ef743ec4Ssam 		pp->p_size = dgetnum(psize);
41*ef743ec4Ssam 		pp->p_bsize = dgetnum(pbsize);
42*ef743ec4Ssam 		pp->p_fsize = dgetnum(pfsize);
439876a848Ssam 	}
449876a848Ssam 	return (dp);
459876a848Ssam }
469876a848Ssam 
479876a848Ssam #include <ctype.h>
489876a848Ssam 
499876a848Ssam static	char *tbuf;
509876a848Ssam static	char *dskip();
519876a848Ssam static	char *ddecode();
529876a848Ssam 
539876a848Ssam /*
549876a848Ssam  * Get an entry for disk name in buffer bp,
559876a848Ssam  * from the diskcap file.  Parse is very rudimentary;
569876a848Ssam  * we just notice escaped newlines.
579876a848Ssam  */
589876a848Ssam static
599876a848Ssam dgetent(bp, name)
609876a848Ssam 	char *bp, *name;
619876a848Ssam {
629876a848Ssam 	register char *cp;
639876a848Ssam 	register int c;
649876a848Ssam 	register int i = 0, cnt = 0;
659876a848Ssam 	char ibuf[BUFSIZ];
669876a848Ssam 	int tf;
679876a848Ssam 
689876a848Ssam 	tbuf = bp;
699876a848Ssam 	tf = open(DISKTAB, 0);
709876a848Ssam 	if (tf < 0)
719876a848Ssam 		return (-1);
729876a848Ssam 	for (;;) {
739876a848Ssam 		cp = bp;
749876a848Ssam 		for (;;) {
759876a848Ssam 			if (i == cnt) {
769876a848Ssam 				cnt = read(tf, ibuf, BUFSIZ);
779876a848Ssam 				if (cnt <= 0) {
789876a848Ssam 					close(tf);
799876a848Ssam 					return (0);
809876a848Ssam 				}
819876a848Ssam 				i = 0;
829876a848Ssam 			}
839876a848Ssam 			c = ibuf[i++];
849876a848Ssam 			if (c == '\n') {
859876a848Ssam 				if (cp > bp && cp[-1] == '\\'){
869876a848Ssam 					cp--;
879876a848Ssam 					continue;
889876a848Ssam 				}
899876a848Ssam 				break;
909876a848Ssam 			}
919876a848Ssam 			if (cp >= bp+BUFSIZ) {
929876a848Ssam 				write(2,"Disktab entry too long\n", 23);
939876a848Ssam 				break;
949876a848Ssam 			} else
959876a848Ssam 				*cp++ = c;
969876a848Ssam 		}
979876a848Ssam 		*cp = 0;
989876a848Ssam 
999876a848Ssam 		/*
1009876a848Ssam 		 * The real work for the match.
1019876a848Ssam 		 */
1029876a848Ssam 		if (dnamatch(name)) {
1039876a848Ssam 			close(tf);
1049876a848Ssam 			return (1);
1059876a848Ssam 		}
1069876a848Ssam 	}
1079876a848Ssam }
1089876a848Ssam 
1099876a848Ssam /*
1109876a848Ssam  * Dnamatch deals with name matching.  The first field of the disktab
1119876a848Ssam  * entry is a sequence of names separated by |'s, so we compare
1129876a848Ssam  * against each such name.  The normal : terminator after the last
1139876a848Ssam  * name (before the first field) stops us.
1149876a848Ssam  */
1159876a848Ssam static
1169876a848Ssam dnamatch(np)
1179876a848Ssam 	char *np;
1189876a848Ssam {
1199876a848Ssam 	register char *Np, *Bp;
1209876a848Ssam 
1219876a848Ssam 	Bp = tbuf;
1229876a848Ssam 	if (*Bp == '#')
1239876a848Ssam 		return (0);
1249876a848Ssam 	for (;;) {
1259876a848Ssam 		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
1269876a848Ssam 			continue;
1279876a848Ssam 		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
1289876a848Ssam 			return (1);
1299876a848Ssam 		while (*Bp && *Bp != ':' && *Bp != '|')
1309876a848Ssam 			Bp++;
1319876a848Ssam 		if (*Bp == 0 || *Bp == ':')
1329876a848Ssam 			return (0);
1339876a848Ssam 		Bp++;
1349876a848Ssam 	}
1359876a848Ssam }
1369876a848Ssam 
1379876a848Ssam /*
1389876a848Ssam  * Skip to the next field.  Notice that this is very dumb, not
1399876a848Ssam  * knowing about \: escapes or any such.  If necessary, :'s can be put
1409876a848Ssam  * into the diskcap file in octal.
1419876a848Ssam  */
1429876a848Ssam static char *
1439876a848Ssam dskip(bp)
1449876a848Ssam 	register char *bp;
1459876a848Ssam {
1469876a848Ssam 
1479876a848Ssam 	while (*bp && *bp != ':')
1489876a848Ssam 		bp++;
1499876a848Ssam 	if (*bp == ':')
1509876a848Ssam 		bp++;
1519876a848Ssam 	return (bp);
1529876a848Ssam }
1539876a848Ssam 
1549876a848Ssam /*
1559876a848Ssam  * Return the (numeric) option id.
1569876a848Ssam  * Numeric options look like
1579876a848Ssam  *	li#80
1589876a848Ssam  * i.e. the option string is separated from the numeric value by
1599876a848Ssam  * a # character.  If the option is not found we return -1.
1609876a848Ssam  * Note that we handle octal numbers beginning with 0.
1619876a848Ssam  */
1629876a848Ssam static
1639876a848Ssam dgetnum(id)
1649876a848Ssam 	char *id;
1659876a848Ssam {
1669876a848Ssam 	register int i, base;
1679876a848Ssam 	register char *bp = tbuf;
1689876a848Ssam 
1699876a848Ssam 	for (;;) {
1709876a848Ssam 		bp = dskip(bp);
1719876a848Ssam 		if (*bp == 0)
1729876a848Ssam 			return (-1);
1739876a848Ssam 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
1749876a848Ssam 			continue;
1759876a848Ssam 		if (*bp == '@')
1769876a848Ssam 			return (-1);
1779876a848Ssam 		if (*bp != '#')
1789876a848Ssam 			continue;
1799876a848Ssam 		bp++;
1809876a848Ssam 		base = 10;
1819876a848Ssam 		if (*bp == '0')
1829876a848Ssam 			base = 8;
1839876a848Ssam 		i = 0;
1849876a848Ssam 		while (isdigit(*bp))
1859876a848Ssam 			i *= base, i += *bp++ - '0';
1869876a848Ssam 		return (i);
1879876a848Ssam 	}
1889876a848Ssam }
1899876a848Ssam 
1909876a848Ssam /*
1919876a848Ssam  * Handle a flag option.
1929876a848Ssam  * Flag options are given "naked", i.e. followed by a : or the end
1939876a848Ssam  * of the buffer.  Return 1 if we find the option, or 0 if it is
1949876a848Ssam  * not given.
1959876a848Ssam  */
1969876a848Ssam static
1979876a848Ssam dgetflag(id)
1989876a848Ssam 	char *id;
1999876a848Ssam {
2009876a848Ssam 	register char *bp = tbuf;
2019876a848Ssam 
2029876a848Ssam 	for (;;) {
2039876a848Ssam 		bp = dskip(bp);
2049876a848Ssam 		if (!*bp)
2059876a848Ssam 			return (0);
2069876a848Ssam 		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
2079876a848Ssam 			if (!*bp || *bp == ':')
2089876a848Ssam 				return (1);
2099876a848Ssam 			else if (*bp == '@')
2109876a848Ssam 				return (0);
2119876a848Ssam 		}
2129876a848Ssam 	}
2139876a848Ssam }
2149876a848Ssam 
2159876a848Ssam /*
2169876a848Ssam  * Get a string valued option.
2179876a848Ssam  * These are given as
2189876a848Ssam  *	cl=^Z
2199876a848Ssam  * Much decoding is done on the strings, and the strings are
2209876a848Ssam  * placed in area, which is a ref parameter which is updated.
2219876a848Ssam  * No checking on area overflow.
2229876a848Ssam  */
2239876a848Ssam static char *
2249876a848Ssam dgetstr(id, area)
2259876a848Ssam 	char *id, **area;
2269876a848Ssam {
2279876a848Ssam 	register char *bp = tbuf;
2289876a848Ssam 
2299876a848Ssam 	for (;;) {
2309876a848Ssam 		bp = dskip(bp);
2319876a848Ssam 		if (!*bp)
2329876a848Ssam 			return (0);
2339876a848Ssam 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
2349876a848Ssam 			continue;
2359876a848Ssam 		if (*bp == '@')
2369876a848Ssam 			return (0);
2379876a848Ssam 		if (*bp != '=')
2389876a848Ssam 			continue;
2399876a848Ssam 		bp++;
2409876a848Ssam 		return (ddecode(bp, area));
2419876a848Ssam 	}
2429876a848Ssam }
2439876a848Ssam 
2449876a848Ssam /*
2459876a848Ssam  * Tdecode does the grung work to decode the
2469876a848Ssam  * string capability escapes.
2479876a848Ssam  */
2489876a848Ssam static char *
2499876a848Ssam ddecode(str, area)
2509876a848Ssam 	register char *str;
2519876a848Ssam 	char **area;
2529876a848Ssam {
2539876a848Ssam 	register char *cp;
2549876a848Ssam 	register int c;
2559876a848Ssam 	register char *dp;
2569876a848Ssam 	int i;
2579876a848Ssam 
2589876a848Ssam 	cp = *area;
2599876a848Ssam 	while ((c = *str++) && c != ':') {
2609876a848Ssam 		switch (c) {
2619876a848Ssam 
2629876a848Ssam 		case '^':
2639876a848Ssam 			c = *str++ & 037;
2649876a848Ssam 			break;
2659876a848Ssam 
2669876a848Ssam 		case '\\':
2679876a848Ssam 			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
2689876a848Ssam 			c = *str++;
2699876a848Ssam nextc:
2709876a848Ssam 			if (*dp++ == c) {
2719876a848Ssam 				c = *dp++;
2729876a848Ssam 				break;
2739876a848Ssam 			}
2749876a848Ssam 			dp++;
2759876a848Ssam 			if (*dp)
2769876a848Ssam 				goto nextc;
2779876a848Ssam 			if (isdigit(c)) {
2789876a848Ssam 				c -= '0', i = 2;
2799876a848Ssam 				do
2809876a848Ssam 					c <<= 3, c |= *str++ - '0';
2819876a848Ssam 				while (--i && isdigit(*str));
2829876a848Ssam 			}
2839876a848Ssam 			break;
2849876a848Ssam 		}
2859876a848Ssam 		*cp++ = c;
2869876a848Ssam 	}
2879876a848Ssam 	*cp++ = 0;
2889876a848Ssam 	str = *area;
2899876a848Ssam 	*area = cp;
2909876a848Ssam 	return (str);
2919876a848Ssam }
292