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