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