xref: /original-bsd/sys/stand.att/open.c (revision 68a7e0e7)
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.6 (Berkeley) 05/24/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 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;
279 	dirp.name = dir;
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;
313 				printf("%s: directory read error, bn %ld\n",
314 					dirp->name, io->i_bn);
315 				return (NULL);
316 			}
317 		}
318 		dp = (struct direct *)(io->i_buf + off);
319 		dirp->loc += dp->d_reclen;
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 			}
326 			continue;
327 		}
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 }
349