date and time created 83/11/10 16:04:16 by ralph
[unix-history] / usr / src / lib / libc / gen / disklabel.c
CommitLineData
8f13241a 1/* @(#)disklabel.c 4.2 (Berkeley) %G% */
ae284747
SL
2
3#include <disktab.h>
4#include <stdio.h>
5
6static char *dgetstr();
7
8struct disktab *
9getdiskbyname(name)
10 char *name;
11{
12 static struct disktab disk;
13 static char localbuf[100], *cp = localbuf;
14 register struct disktab *dp = &disk;
8f13241a
SL
15 register struct partition *pp;
16 char p, psize[3], pbsize[3], pfsize[3];
17 char buf[BUFSIZ];
ae284747
SL
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;
8f13241a
SL
34 strcpy(psize, "px");
35 strcpy(pbsize, "bx");
36 strcpy(pfsize, "fx");
ae284747 37 for (p = 'a'; p < 'i'; p++) {
8f13241a
SL
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);
ae284747
SL
43 }
44 return (dp);
45}
46
47#include <ctype.h>
48
49static char *tbuf;
50static char *dskip();
51static 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 */
58static
59dgetent(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 */
115static
116dnamatch(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 */
142static char *
143dskip(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 */
162static
163dgetnum(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 */
196static
197dgetflag(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 */
223static char *
224dgetstr(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 */
248static char *
249ddecode(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++;
269nextc:
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}