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