xref: /csrg-svn/lib/libc/gen/disklabel.c (revision 10748)
1*10748Ssam /*	@(#)disklabel.c	4.1 (Berkeley) 02/06/83	*/
2*10748Ssam 
3*10748Ssam #include <disktab.h>
4*10748Ssam #include <stdio.h>
5*10748Ssam 
6*10748Ssam static	char *dgetstr();
7*10748Ssam 
8*10748Ssam struct disktab *
9*10748Ssam getdiskbyname(name)
10*10748Ssam 	char *name;
11*10748Ssam {
12*10748Ssam 	static struct disktab disk;
13*10748Ssam 	static char localbuf[100], *cp = localbuf;
14*10748Ssam 	register struct	disktab *dp = &disk;
15*10748Ssam 	char p, part[3], buf[BUFSIZ];
16*10748Ssam 
17*10748Ssam 	if (dgetent(buf, name) <= 0)
18*10748Ssam 		return ((struct disktab *)0);
19*10748Ssam 	dp->d_name = cp;
20*10748Ssam 	strcpy(cp, name);
21*10748Ssam 	cp += strlen(name) + 1;
22*10748Ssam 	dp->d_type = dgetstr("ty", &cp);
23*10748Ssam 	dp->d_secsize = dgetnum("se");
24*10748Ssam 	if (dp->d_secsize < 0)
25*10748Ssam 		dp->d_secsize = 512;
26*10748Ssam 	dp->d_ntracks = dgetnum("nt");
27*10748Ssam 	dp->d_nsectors = dgetnum("ns");
28*10748Ssam 	dp->d_ncylinders = dgetnum("nc");
29*10748Ssam 	dp->d_rpm = dgetnum("rm");
30*10748Ssam 	if (dp->d_rpm < 0)
31*10748Ssam 		dp->d_rpm = 3600;
32*10748Ssam 	strcpy(part, "px");
33*10748Ssam 	for (p = 'a'; p < 'i'; p++) {
34*10748Ssam 		part[1] = p;
35*10748Ssam 		dp->d_partitions[p - 'a'] = dgetnum(part);
36*10748Ssam 	}
37*10748Ssam 	return (dp);
38*10748Ssam }
39*10748Ssam 
40*10748Ssam #include <ctype.h>
41*10748Ssam 
42*10748Ssam static	char *tbuf;
43*10748Ssam static	char *dskip();
44*10748Ssam static	char *ddecode();
45*10748Ssam 
46*10748Ssam /*
47*10748Ssam  * Get an entry for disk name in buffer bp,
48*10748Ssam  * from the diskcap file.  Parse is very rudimentary;
49*10748Ssam  * we just notice escaped newlines.
50*10748Ssam  */
51*10748Ssam static
52*10748Ssam dgetent(bp, name)
53*10748Ssam 	char *bp, *name;
54*10748Ssam {
55*10748Ssam 	register char *cp;
56*10748Ssam 	register int c;
57*10748Ssam 	register int i = 0, cnt = 0;
58*10748Ssam 	char ibuf[BUFSIZ];
59*10748Ssam 	int tf;
60*10748Ssam 
61*10748Ssam 	tbuf = bp;
62*10748Ssam 	tf = open(DISKTAB, 0);
63*10748Ssam 	if (tf < 0)
64*10748Ssam 		return (-1);
65*10748Ssam 	for (;;) {
66*10748Ssam 		cp = bp;
67*10748Ssam 		for (;;) {
68*10748Ssam 			if (i == cnt) {
69*10748Ssam 				cnt = read(tf, ibuf, BUFSIZ);
70*10748Ssam 				if (cnt <= 0) {
71*10748Ssam 					close(tf);
72*10748Ssam 					return (0);
73*10748Ssam 				}
74*10748Ssam 				i = 0;
75*10748Ssam 			}
76*10748Ssam 			c = ibuf[i++];
77*10748Ssam 			if (c == '\n') {
78*10748Ssam 				if (cp > bp && cp[-1] == '\\'){
79*10748Ssam 					cp--;
80*10748Ssam 					continue;
81*10748Ssam 				}
82*10748Ssam 				break;
83*10748Ssam 			}
84*10748Ssam 			if (cp >= bp+BUFSIZ) {
85*10748Ssam 				write(2,"Disktab entry too long\n", 23);
86*10748Ssam 				break;
87*10748Ssam 			} else
88*10748Ssam 				*cp++ = c;
89*10748Ssam 		}
90*10748Ssam 		*cp = 0;
91*10748Ssam 
92*10748Ssam 		/*
93*10748Ssam 		 * The real work for the match.
94*10748Ssam 		 */
95*10748Ssam 		if (dnamatch(name)) {
96*10748Ssam 			close(tf);
97*10748Ssam 			return (1);
98*10748Ssam 		}
99*10748Ssam 	}
100*10748Ssam }
101*10748Ssam 
102*10748Ssam /*
103*10748Ssam  * Dnamatch deals with name matching.  The first field of the disktab
104*10748Ssam  * entry is a sequence of names separated by |'s, so we compare
105*10748Ssam  * against each such name.  The normal : terminator after the last
106*10748Ssam  * name (before the first field) stops us.
107*10748Ssam  */
108*10748Ssam static
109*10748Ssam dnamatch(np)
110*10748Ssam 	char *np;
111*10748Ssam {
112*10748Ssam 	register char *Np, *Bp;
113*10748Ssam 
114*10748Ssam 	Bp = tbuf;
115*10748Ssam 	if (*Bp == '#')
116*10748Ssam 		return (0);
117*10748Ssam 	for (;;) {
118*10748Ssam 		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
119*10748Ssam 			continue;
120*10748Ssam 		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
121*10748Ssam 			return (1);
122*10748Ssam 		while (*Bp && *Bp != ':' && *Bp != '|')
123*10748Ssam 			Bp++;
124*10748Ssam 		if (*Bp == 0 || *Bp == ':')
125*10748Ssam 			return (0);
126*10748Ssam 		Bp++;
127*10748Ssam 	}
128*10748Ssam }
129*10748Ssam 
130*10748Ssam /*
131*10748Ssam  * Skip to the next field.  Notice that this is very dumb, not
132*10748Ssam  * knowing about \: escapes or any such.  If necessary, :'s can be put
133*10748Ssam  * into the diskcap file in octal.
134*10748Ssam  */
135*10748Ssam static char *
136*10748Ssam dskip(bp)
137*10748Ssam 	register char *bp;
138*10748Ssam {
139*10748Ssam 
140*10748Ssam 	while (*bp && *bp != ':')
141*10748Ssam 		bp++;
142*10748Ssam 	if (*bp == ':')
143*10748Ssam 		bp++;
144*10748Ssam 	return (bp);
145*10748Ssam }
146*10748Ssam 
147*10748Ssam /*
148*10748Ssam  * Return the (numeric) option id.
149*10748Ssam  * Numeric options look like
150*10748Ssam  *	li#80
151*10748Ssam  * i.e. the option string is separated from the numeric value by
152*10748Ssam  * a # character.  If the option is not found we return -1.
153*10748Ssam  * Note that we handle octal numbers beginning with 0.
154*10748Ssam  */
155*10748Ssam static
156*10748Ssam dgetnum(id)
157*10748Ssam 	char *id;
158*10748Ssam {
159*10748Ssam 	register int i, base;
160*10748Ssam 	register char *bp = tbuf;
161*10748Ssam 
162*10748Ssam 	for (;;) {
163*10748Ssam 		bp = dskip(bp);
164*10748Ssam 		if (*bp == 0)
165*10748Ssam 			return (-1);
166*10748Ssam 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
167*10748Ssam 			continue;
168*10748Ssam 		if (*bp == '@')
169*10748Ssam 			return (-1);
170*10748Ssam 		if (*bp != '#')
171*10748Ssam 			continue;
172*10748Ssam 		bp++;
173*10748Ssam 		base = 10;
174*10748Ssam 		if (*bp == '0')
175*10748Ssam 			base = 8;
176*10748Ssam 		i = 0;
177*10748Ssam 		while (isdigit(*bp))
178*10748Ssam 			i *= base, i += *bp++ - '0';
179*10748Ssam 		return (i);
180*10748Ssam 	}
181*10748Ssam }
182*10748Ssam 
183*10748Ssam /*
184*10748Ssam  * Handle a flag option.
185*10748Ssam  * Flag options are given "naked", i.e. followed by a : or the end
186*10748Ssam  * of the buffer.  Return 1 if we find the option, or 0 if it is
187*10748Ssam  * not given.
188*10748Ssam  */
189*10748Ssam static
190*10748Ssam dgetflag(id)
191*10748Ssam 	char *id;
192*10748Ssam {
193*10748Ssam 	register char *bp = tbuf;
194*10748Ssam 
195*10748Ssam 	for (;;) {
196*10748Ssam 		bp = dskip(bp);
197*10748Ssam 		if (!*bp)
198*10748Ssam 			return (0);
199*10748Ssam 		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
200*10748Ssam 			if (!*bp || *bp == ':')
201*10748Ssam 				return (1);
202*10748Ssam 			else if (*bp == '@')
203*10748Ssam 				return (0);
204*10748Ssam 		}
205*10748Ssam 	}
206*10748Ssam }
207*10748Ssam 
208*10748Ssam /*
209*10748Ssam  * Get a string valued option.
210*10748Ssam  * These are given as
211*10748Ssam  *	cl=^Z
212*10748Ssam  * Much decoding is done on the strings, and the strings are
213*10748Ssam  * placed in area, which is a ref parameter which is updated.
214*10748Ssam  * No checking on area overflow.
215*10748Ssam  */
216*10748Ssam static char *
217*10748Ssam dgetstr(id, area)
218*10748Ssam 	char *id, **area;
219*10748Ssam {
220*10748Ssam 	register char *bp = tbuf;
221*10748Ssam 
222*10748Ssam 	for (;;) {
223*10748Ssam 		bp = dskip(bp);
224*10748Ssam 		if (!*bp)
225*10748Ssam 			return (0);
226*10748Ssam 		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
227*10748Ssam 			continue;
228*10748Ssam 		if (*bp == '@')
229*10748Ssam 			return (0);
230*10748Ssam 		if (*bp != '=')
231*10748Ssam 			continue;
232*10748Ssam 		bp++;
233*10748Ssam 		return (ddecode(bp, area));
234*10748Ssam 	}
235*10748Ssam }
236*10748Ssam 
237*10748Ssam /*
238*10748Ssam  * Tdecode does the grung work to decode the
239*10748Ssam  * string capability escapes.
240*10748Ssam  */
241*10748Ssam static char *
242*10748Ssam ddecode(str, area)
243*10748Ssam 	register char *str;
244*10748Ssam 	char **area;
245*10748Ssam {
246*10748Ssam 	register char *cp;
247*10748Ssam 	register int c;
248*10748Ssam 	register char *dp;
249*10748Ssam 	int i;
250*10748Ssam 
251*10748Ssam 	cp = *area;
252*10748Ssam 	while ((c = *str++) && c != ':') {
253*10748Ssam 		switch (c) {
254*10748Ssam 
255*10748Ssam 		case '^':
256*10748Ssam 			c = *str++ & 037;
257*10748Ssam 			break;
258*10748Ssam 
259*10748Ssam 		case '\\':
260*10748Ssam 			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
261*10748Ssam 			c = *str++;
262*10748Ssam nextc:
263*10748Ssam 			if (*dp++ == c) {
264*10748Ssam 				c = *dp++;
265*10748Ssam 				break;
266*10748Ssam 			}
267*10748Ssam 			dp++;
268*10748Ssam 			if (*dp)
269*10748Ssam 				goto nextc;
270*10748Ssam 			if (isdigit(c)) {
271*10748Ssam 				c -= '0', i = 2;
272*10748Ssam 				do
273*10748Ssam 					c <<= 3, c |= *str++ - '0';
274*10748Ssam 				while (--i && isdigit(*str));
275*10748Ssam 			}
276*10748Ssam 			break;
277*10748Ssam 		}
278*10748Ssam 		*cp++ = c;
279*10748Ssam 	}
280*10748Ssam 	*cp++ = 0;
281*10748Ssam 	str = *area;
282*10748Ssam 	*area = cp;
283*10748Ssam 	return (str);
284*10748Ssam }
285