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