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