sockaddr's now require length (K. Sklower);
[unix-history] / usr / src / lib / libc / gen / disklabel.c
CommitLineData
586c39b1 1/*
64022921
KB
2 * Copyright (c) 1983, 1987 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
586c39b1
DF
16 */
17
2ce81398 18#if defined(LIBC_SCCS) && !defined(lint)
64022921
KB
19static char sccsid[] = "@(#)disklabel.c 5.10 (Berkeley) %G%";
20#endif /* LIBC_SCCS and not lint */
ae284747 21
77118868
MK
22#include <sys/param.h>
23#include <sys/fs.h>
24#include <sys/file.h>
25#define DKTYPENAMES
26#include <sys/disklabel.h>
ae284747 27#include <stdio.h>
6665218a 28#include <strings.h>
ae284747
SL
29
30static char *dgetstr();
31
77118868 32struct disklabel *
ae284747
SL
33getdiskbyname(name)
34 char *name;
35{
572daa42
MT
36 static struct disklabel disk;
37 static char boot[BUFSIZ];
38 char localbuf[BUFSIZ];
39 char buf[BUFSIZ];
40 char *cp, *cq; /* can't be register */
77118868 41 register struct disklabel *dp = &disk;
8f13241a 42 register struct partition *pp;
572daa42
MT
43 char p, max, psize[3], pbsize[3],
44 pfsize[3], poffset[3], ptype[3];
45 u_long *dx;
ae284747
SL
46
47 if (dgetent(buf, name) <= 0)
77118868
MK
48 return ((struct disklabel *)0);
49 bzero((char *)&disk, sizeof(disk));
572daa42
MT
50 /*
51 * typename
52 */
77118868
MK
53 cq = dp->d_typename;
54 cp = buf;
55 while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 &&
56 (*cq = *cp) && *cq != '|' && *cq != ':')
57 cq++, cp++;
58 *cq = '\0';
572daa42
MT
59 /*
60 * boot name (optional) xxboot, bootxx
61 */
62 cp = boot;
63 dp->d_boot0 = dgetstr("b0", &cp);
64 dp->d_boot1 = dgetstr("b1", &cp);
77118868
MK
65 cp = localbuf;
66 cq = dgetstr("ty", &cp);
67 if (cq && strcmp(cq, "removable") == 0)
68 dp->d_flags |= D_REMOVABLE;
69 else if (cq && strcmp(cq, "simulated") == 0)
70 dp->d_flags |= D_RAMDISK;
71 if (dgetflag("sf"))
72 dp->d_flags |= D_BADSECT;
572daa42 73
77118868
MK
74#define getnumdflt(field, dname, dflt) \
75 { int f = dgetnum(dname); \
76 (field) = f == -1 ? (dflt) : f; }
77
78 getnumdflt(dp->d_secsize, "se", DEV_BSIZE);
ae284747
SL
79 dp->d_ntracks = dgetnum("nt");
80 dp->d_nsectors = dgetnum("ns");
81 dp->d_ncylinders = dgetnum("nc");
77118868
MK
82 cq = dgetstr("dt", &cp);
83 if (cq)
84 dp->d_type = gettype(cq, dktypenames);
85 else
86 getnumdflt(dp->d_type, "dt", 0);
87 getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
88 getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
89 getnumdflt(dp->d_rpm, "rm", 3600);
90 getnumdflt(dp->d_interleave, "il", 1);
91 getnumdflt(dp->d_trackskew, "sk", 0);
92 getnumdflt(dp->d_cylskew, "cs", 0);
93 getnumdflt(dp->d_headswitch, "hs", 0);
94 getnumdflt(dp->d_trkseek, "ts", 0);
95 getnumdflt(dp->d_bbsize, "bs", BBSIZE);
96 getnumdflt(dp->d_sbsize, "sb", SBSIZE);
8f13241a
SL
97 strcpy(psize, "px");
98 strcpy(pbsize, "bx");
99 strcpy(pfsize, "fx");
77118868
MK
100 strcpy(poffset, "ox");
101 strcpy(ptype, "tx");
102 max = 'a' - 1;
103 pp = &dp->d_partitions[0];
104 for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) {
105 psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p;
8f13241a 106 pp->p_size = dgetnum(psize);
77118868
MK
107 if (pp->p_size == -1)
108 pp->p_size = 0;
109 else {
110 pp->p_offset = dgetnum(poffset);
111 getnumdflt(pp->p_fsize, pfsize, 0);
112 if (pp->p_fsize)
113 pp->p_frag = dgetnum(pbsize) / pp->p_fsize;
114 getnumdflt(pp->p_fstype, ptype, 0);
115 if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp)))
116 pp->p_fstype = gettype(cq, fstypenames);
117 max = p;
118 }
119 }
120 dp->d_npartitions = max + 1 - 'a';
6665218a 121 (void)strcpy(psize, "dx");
77118868
MK
122 dx = dp->d_drivedata;
123 for (p = '0'; p < '0' + NDDATA; p++, dx++) {
124 psize[1] = p;
125 getnumdflt(*dx, psize, 0);
ae284747 126 }
77118868
MK
127 dp->d_magic = DISKMAGIC;
128 dp->d_magic2 = DISKMAGIC;
ae284747
SL
129 return (dp);
130}
131
132#include <ctype.h>
133
134static char *tbuf;
135static char *dskip();
136static char *ddecode();
137
138/*
139 * Get an entry for disk name in buffer bp,
140 * from the diskcap file. Parse is very rudimentary;
141 * we just notice escaped newlines.
142 */
143static
144dgetent(bp, name)
145 char *bp, *name;
146{
147 register char *cp;
148 register int c;
149 register int i = 0, cnt = 0;
150 char ibuf[BUFSIZ];
151 int tf;
152
153 tbuf = bp;
154 tf = open(DISKTAB, 0);
155 if (tf < 0)
156 return (-1);
157 for (;;) {
158 cp = bp;
159 for (;;) {
160 if (i == cnt) {
161 cnt = read(tf, ibuf, BUFSIZ);
162 if (cnt <= 0) {
163 close(tf);
164 return (0);
165 }
166 i = 0;
167 }
168 c = ibuf[i++];
169 if (c == '\n') {
170 if (cp > bp && cp[-1] == '\\'){
171 cp--;
172 continue;
173 }
174 break;
175 }
176 if (cp >= bp+BUFSIZ) {
177 write(2,"Disktab entry too long\n", 23);
178 break;
179 } else
180 *cp++ = c;
181 }
182 *cp = 0;
183
184 /*
185 * The real work for the match.
186 */
187 if (dnamatch(name)) {
188 close(tf);
189 return (1);
190 }
191 }
192}
193
194/*
195 * Dnamatch deals with name matching. The first field of the disktab
196 * entry is a sequence of names separated by |'s, so we compare
197 * against each such name. The normal : terminator after the last
198 * name (before the first field) stops us.
199 */
200static
201dnamatch(np)
202 char *np;
203{
204 register char *Np, *Bp;
205
206 Bp = tbuf;
207 if (*Bp == '#')
208 return (0);
209 for (;;) {
210 for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
211 continue;
212 if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
213 return (1);
214 while (*Bp && *Bp != ':' && *Bp != '|')
215 Bp++;
216 if (*Bp == 0 || *Bp == ':')
217 return (0);
218 Bp++;
219 }
220}
221
222/*
223 * Skip to the next field. Notice that this is very dumb, not
224 * knowing about \: escapes or any such. If necessary, :'s can be put
225 * into the diskcap file in octal.
226 */
227static char *
228dskip(bp)
229 register char *bp;
230{
231
232 while (*bp && *bp != ':')
233 bp++;
234 if (*bp == ':')
235 bp++;
236 return (bp);
237}
238
239/*
240 * Return the (numeric) option id.
241 * Numeric options look like
242 * li#80
243 * i.e. the option string is separated from the numeric value by
244 * a # character. If the option is not found we return -1.
245 * Note that we handle octal numbers beginning with 0.
246 */
247static
248dgetnum(id)
249 char *id;
250{
251 register int i, base;
252 register char *bp = tbuf;
253
254 for (;;) {
255 bp = dskip(bp);
256 if (*bp == 0)
257 return (-1);
258 if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
259 continue;
260 if (*bp == '@')
261 return (-1);
262 if (*bp != '#')
263 continue;
264 bp++;
265 base = 10;
266 if (*bp == '0')
267 base = 8;
268 i = 0;
269 while (isdigit(*bp))
270 i *= base, i += *bp++ - '0';
271 return (i);
272 }
273}
274
275/*
276 * Handle a flag option.
277 * Flag options are given "naked", i.e. followed by a : or the end
278 * of the buffer. Return 1 if we find the option, or 0 if it is
279 * not given.
280 */
281static
282dgetflag(id)
283 char *id;
284{
285 register char *bp = tbuf;
286
287 for (;;) {
288 bp = dskip(bp);
289 if (!*bp)
290 return (0);
291 if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
292 if (!*bp || *bp == ':')
293 return (1);
294 else if (*bp == '@')
295 return (0);
296 }
297 }
298}
299
300/*
301 * Get a string valued option.
302 * These are given as
303 * cl=^Z
304 * Much decoding is done on the strings, and the strings are
305 * placed in area, which is a ref parameter which is updated.
306 * No checking on area overflow.
307 */
308static char *
309dgetstr(id, area)
310 char *id, **area;
311{
312 register char *bp = tbuf;
313
314 for (;;) {
315 bp = dskip(bp);
316 if (!*bp)
317 return (0);
318 if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
319 continue;
320 if (*bp == '@')
321 return (0);
322 if (*bp != '=')
323 continue;
324 bp++;
325 return (ddecode(bp, area));
326 }
327}
328
329/*
330 * Tdecode does the grung work to decode the
331 * string capability escapes.
332 */
333static char *
334ddecode(str, area)
335 register char *str;
336 char **area;
337{
338 register char *cp;
339 register int c;
340 register char *dp;
341 int i;
342
343 cp = *area;
344 while ((c = *str++) && c != ':') {
345 switch (c) {
346
347 case '^':
348 c = *str++ & 037;
349 break;
350
351 case '\\':
352 dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
353 c = *str++;
354nextc:
355 if (*dp++ == c) {
356 c = *dp++;
357 break;
358 }
359 dp++;
360 if (*dp)
361 goto nextc;
362 if (isdigit(c)) {
363 c -= '0', i = 2;
364 do
365 c <<= 3, c |= *str++ - '0';
366 while (--i && isdigit(*str));
367 }
368 break;
369 }
370 *cp++ = c;
371 }
372 *cp++ = 0;
373 str = *area;
374 *area = cp;
375 return (str);
376}
77118868
MK
377
378static
379gettype(t, names)
380 char *t;
381 char **names;
382{
383 register char **nm;
384
385 for (nm = names; *nm; nm++)
49f0b7cf 386 if (strcasecmp(t, *nm) == 0)
77118868
MK
387 return (nm - names);
388 if (isdigit(*t))
389 return (atoi(t));
390 return (0);
391}
392
77118868
MK
393dkcksum(lp)
394 register struct disklabel *lp;
395{
396 register u_short *start, *end;
397 register u_short sum = 0;
398
399 start = (u_short *)lp;
400 end = (u_short *)&lp->d_partitions[lp->d_npartitions];
401 while (start < end)
402 sum ^= *start++;
403 return (sum);
404}