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