1 /*-
2 * Copyright (c) 1982, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.proprietary.c%
6 *
7 * @(#)open.c 8.1 (Berkeley) 07/07/93
8 */
9
10 #include <sys/param.h>
11 #include <sys/reboot.h>
12
13 #include <ufs/ufs/dir.h>
14 #include <stand.att/saio.h>
15
16 int firstopen;
17 u_int opendev; /* last device opened */
18 extern u_int bootdev;
19
20 struct dirstuff {
21 int loc;
22 struct iob *io;
23 char *name;
24 };
25
26 #ifndef SMALL
27 /*
28 * XXX avoid stdio... its a long story.
29 */
30 #define isupper(c) ((c) >= 'A' && (c) <= 'Z')
31 #define tolower(c) ((c) - 'A' + 'a')
32 #define isspace(c) ((c) == ' ' || (c) == '\t')
33 #define isdigit(c) ((c) >= '0' && (c) <= '9')
34
35 static ino_t dlook __P((char *, struct iob *, char *));
36 static int find __P((char *, struct iob *));
37 static int getdev __P((char *, int));
38 static int getunit __P((char *));
39 static struct direct *readdir __P((struct dirstuff *));
40 static int openi __P((int, struct iob *));
41 #endif
42
open(str,how)43 open(str, how)
44 char *str;
45 int how;
46 {
47 static int firstopen = 1;
48 register struct iob *file;
49 register char *t;
50 register int cnt;
51 int fdesc, args[8], *argp;
52
53 if (firstopen) {
54 for (cnt = 0; cnt < SOPEN_MAX; cnt++)
55 iob[cnt].i_flgs = 0;
56 firstopen = 0;
57 }
58
59 for (fdesc = 0;; fdesc++) {
60 if (fdesc == SOPEN_MAX)
61 _stop("No more file slots");
62 if (iob[fdesc].i_flgs == 0) {
63 file = &iob[fdesc];
64 file->i_flgs |= F_ALLOC;
65 file->i_adapt = file->i_ctlr = file->i_unit =
66 file->i_part = 0;
67 break;
68 }
69 }
70
71 for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
72 #ifndef SMALL
73 for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
74 if (isupper(*t))
75 *t = tolower(*t);
76 switch(*t) {
77 case '(': /* type(adapt, ctlr, drive, partition)file */
78 if ((file->i_dev = getdev(str, t - str)) == -1)
79 goto bad;
80 for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
81 for (++t; isspace(*t); ++t);
82 if (*t == ')')
83 break;
84 if (!isdigit(*t))
85 goto badspec;
86 *argp++ = atoi(t);
87 for (++t; isdigit(*t); ++t);
88 if (*t != ',' && *t != ')' || cnt == 4)
89 goto badspec;
90 }
91 for (++t; isspace(*t); ++t);
92 argp -= 4;
93 file->i_adapt = *argp++;
94 file->i_ctlr = *argp++;
95 file->i_unit = *argp++;
96 file->i_part = *argp;
97 break;
98 case ':': /* [A-Za-z]*[0-9]*[A-Za-z]:file */
99 for (t = str; *t != ':' && !isdigit(*t); ++t);
100 if ((file->i_dev = getdev(str, t - str)) == -1)
101 goto bad;
102 if ((file->i_unit = getunit(t)) == -1)
103 goto bad;
104 for (; isdigit(*t); ++t);
105 if (*t >= 'a' && *t <= 'h')
106 file->i_part = *t++ - 'a';
107 if (*t != ':') {
108 errno = EOFFSET;
109 goto badspec;
110 }
111 for (++t; isspace(*t); ++t);
112 break;
113 case '/':
114 default: /* default bootstrap unit and device */
115 #else
116 {
117 #endif /* SMALL */
118 file->i_dev = B_TYPE(bootdev);
119 file->i_adapt = B_ADAPTOR(bootdev);
120 file->i_ctlr = B_CONTROLLER(bootdev);
121 file->i_unit = B_UNIT(bootdev);
122 file->i_part = B_PARTITION(bootdev);
123 t = str;
124 }
125
126 opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr,
127 file->i_unit, file->i_part);
128
129 if (errno = devopen(file))
130 goto bad;
131
132 if (*t == '\0') {
133 file->i_flgs |= how + 1;
134 file->i_cc = 0;
135 file->i_offset = 0;
136 return (fdesc+3);
137 }
138 #ifndef SMALL
139 else if (how != 0) {
140 printf("Can't write files yet.. Sorry\n");
141 errno = EIO;
142 goto bad;
143 }
144 #endif
145 file->i_ma = (char *)(&file->i_fs);
146 file->i_cc = SBSIZE;
147 file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
148 file->i_offset = 0;
149 if (devread(file) < 0) {
150 errno = file->i_error;
151 printf("super block read error\n");
152 goto bad;
153 }
154 if ((cnt = find(t, file)) == 0) {
155 errno = ESRCH;
156 goto bad;
157 }
158 if (openi(cnt, file) < 0) {
159 errno = file->i_error;
160 goto bad;
161 }
162 file->i_offset = 0;
163 file->i_cc = 0;
164 file->i_flgs |= F_FILE | (how+1);
165 return (fdesc+3);
166
167 #ifndef SMALL
168 badspec:
169 printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n");
170 #endif
171 bad:
172 file->i_flgs = 0;
173 return (-1);
174 }
175
176 #ifndef SMALL
177 static
getdev(str,len)178 getdev(str, len)
179 register char *str;
180 int len;
181 {
182 register struct devsw *dp;
183 register int i;
184 char savedch = str[len];
185
186 str[len] = '\0';
187 for (dp = devsw, i = 0; i < ndevs; dp++, i++)
188 if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
189 str[len] = savedch;
190 return (i);
191 }
192 printf("Unknown device\nKnown devices are:\n");
193 for (dp = devsw, i = 0; i < ndevs; dp++, i++)
194 if (dp->dv_name)
195 printf(" %s", dp->dv_name);
196 printf("\n");
197 errno = ENXIO;
198 return (-1);
199 }
200
201 static
getunit(cp)202 getunit(cp)
203 register char *cp;
204 {
205 int unit;
206
207 unit = atoi(cp);
208 if ((u_int)unit > 255) {
209 printf("minor device number out of range (0-255)\n");
210 errno = EUNIT;
211 return (-1);
212 }
213 return (unit);
214 }
215
216 /*
217 * XXX more stdio-avoidance.
218 */
atoi(cp)219 atoi(cp)
220 char *cp;
221 {
222 int val = 0;
223
224 while (*cp >= '0' && *cp <= '9')
225 val = val * 10 + (*cp++ - '0');
226 return (val);
227 }
228 #endif /* SMALL */
229
230 static
find(path,file)231 find(path, file)
232 register char *path;
233 struct iob *file;
234 {
235 register char *q;
236 char *dir, c;
237 int n;
238
239 if (path == NULL || *path == '\0') {
240 printf("null path\n");
241 return (0);
242 }
243
244 if (openi((ino_t) ROOTINO, file) < 0) {
245 printf("can't read root inode\n");
246 return (0);
247 }
248 dir = path;
249 while (*path) {
250 while (*path == '/')
251 path++;
252 q = path;
253 while(*q != '/' && *q != '\0')
254 q++;
255 c = *q;
256 *q = '\0';
257 if (q == path) path = "." ; /* "/" means "/." */
258
259 if ((n = dlook(path, file, dir)) != 0) {
260 if (c == '\0')
261 break;
262 if (openi(n, file) < 0)
263 return (0);
264 *q = c;
265 path = q;
266 continue;
267 } else {
268 printf("%s: not found\n", path);
269 return (0);
270 }
271 }
272 return (n);
273 }
274
275 static ino_t
dlook(s,io,dir)276 dlook(s, io, dir)
277 char *s;
278 register struct iob *io;
279 char *dir;
280 {
281 register struct direct *dp;
282 register struct dinode *ip;
283 struct dirstuff dirp;
284 int len;
285
286 if (s == NULL || *s == '\0')
287 return (0);
288 ip = &io->i_ino;
289 if ((ip->di_mode&IFMT) != IFDIR) {
290 printf("%s: not a directory\n", dir);
291 return (0);
292 }
293 if (ip->di_size == 0) {
294 printf("%s: zero length directory\n", dir);
295 return (0);
296 }
297 len = strlen(s);
298 dirp.loc = 0;
299 dirp.io = io;
300 dirp.name = dir;
301 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
302 if(dp->d_ino == 0)
303 continue;
304 if (dp->d_namlen == len && !strcmp(s, dp->d_name))
305 return (dp->d_ino);
306 }
307 return (0);
308 }
309
310 static struct direct *
readdir(dirp)311 readdir(dirp)
312 register struct dirstuff *dirp;
313 {
314 register struct direct *dp;
315 register struct iob *io;
316 daddr_t lbn, d;
317 int off;
318
319 io = dirp->io;
320 for(;;) {
321 if (dirp->loc >= io->i_ino.di_size)
322 return (NULL);
323 off = blkoff(&io->i_fs, dirp->loc);
324 if (off == 0) {
325 lbn = lblkno(&io->i_fs, dirp->loc);
326 d = bmap(io, lbn);
327 if(d == 0)
328 return (NULL);
329 io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
330 io->i_ma = io->i_buf;
331 io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
332 if (devread(io) < 0) {
333 errno = io->i_error;
334 printf("%s: directory read error, bn %ld\n",
335 dirp->name, io->i_bn);
336 return (NULL);
337 }
338 }
339 dp = (struct direct *)(io->i_buf + off);
340 dirp->loc += dp->d_reclen;
341 if (dp->d_ino == 0) {
342 if (dp->d_reclen == 0) {
343 printf("%s: bad directory entry, offset %ld\n",
344 dirp->name, dirp->loc);
345 return (NULL);
346 }
347 continue;
348 }
349 return (dp);
350 }
351 }
352
353 static
openi(n,io)354 openi(n, io)
355 int n;
356 register struct iob *io;
357 {
358 register struct dinode *dp;
359 int cc;
360
361 io->i_offset = 0;
362 io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
363 io->i_cc = io->i_fs.fs_bsize;
364 io->i_ma = io->i_buf;
365 cc = devread(io);
366 dp = (struct dinode *)io->i_buf;
367 io->i_ino = dp[itoo(&io->i_fs, n)];
368 return (cc);
369 }
370