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