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