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