xref: /csrg-svn/sys/stand.att/open.c (revision 60328)
149149Sbostic /*-
249149Sbostic  * Copyright (c) 1982, 1988 The Regents of the University of California.
349149Sbostic  * All rights reserved.
449149Sbostic  *
549149Sbostic  * %sccs.include.proprietary.c%
649149Sbostic  *
7*60328Smckusick  *	@(#)open.c	7.6 (Berkeley) 05/24/93
849149Sbostic  */
949149Sbostic 
1049149Sbostic #include <sys/param.h>
1149149Sbostic #include <sys/reboot.h>
1256509Sbostic 
1353697Ssklower #include <ufs/ufs/dir.h>
14*60328Smckusick #include <stand.att/saio.h>
1549149Sbostic 
1649149Sbostic int	firstopen;
1749149Sbostic u_int	opendev;			/* last device opened */
1849149Sbostic extern u_int bootdev;
1949149Sbostic 
2049149Sbostic struct dirstuff {
2149149Sbostic 	int loc;
2249149Sbostic 	struct iob *io;
2355894Shibler 	char *name;
2449149Sbostic };
2549149Sbostic 
2649149Sbostic #ifndef SMALL
2749149Sbostic static ino_t dlook __P((char *, struct iob *, char *));
2849149Sbostic static int find __P((char *, struct iob *));
2949149Sbostic static int getdev __P((char *, int));
3049149Sbostic static int getunit __P((char *));
3149149Sbostic static struct direct *readdir __P((struct dirstuff *));
3249149Sbostic static int openi __P((int, struct iob *));
3349149Sbostic #endif
3449149Sbostic 
3549149Sbostic open(str, how)
3649149Sbostic 	char *str;
3749149Sbostic 	int how;
3849149Sbostic {
3949149Sbostic 	static int firstopen = 1;
4049149Sbostic 	register struct iob *file;
4149149Sbostic 	register char *t;
4249149Sbostic 	register int cnt;
4349149Sbostic 	int fdesc, args[8], *argp;
4449149Sbostic 
4549149Sbostic 	if (firstopen) {
4649149Sbostic 		for (cnt = 0; cnt < SOPEN_MAX; cnt++)
4749149Sbostic 			iob[cnt].i_flgs = 0;
4849149Sbostic 		firstopen = 0;
4949149Sbostic 	}
5049149Sbostic 
5149149Sbostic 	for (fdesc = 0;; fdesc++) {
5249149Sbostic 		if (fdesc == SOPEN_MAX)
5349149Sbostic 			_stop("No more file slots");
5449149Sbostic 		if (iob[fdesc].i_flgs == 0) {
5549149Sbostic 			file = &iob[fdesc];
5649149Sbostic 			file->i_flgs |= F_ALLOC;
5749149Sbostic 			file->i_adapt = file->i_ctlr = file->i_unit =
5849149Sbostic 			    file->i_part = 0;
5949149Sbostic 			break;
6049149Sbostic 		}
6149149Sbostic 	}
6249149Sbostic 
6349149Sbostic 	for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
6449149Sbostic #ifndef SMALL
6549149Sbostic 	for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
6649149Sbostic 		if (isupper(*t))
6749149Sbostic 			*t = tolower(*t);
6849149Sbostic 	switch(*t) {
6949149Sbostic 	case '(':	/* type(adapt, ctlr, drive, partition)file */
7049149Sbostic 		if ((file->i_dev = getdev(str, t - str)) == -1)
7149149Sbostic 			goto bad;
7249149Sbostic 		for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
7349149Sbostic 			for (++t; isspace(*t); ++t);
7449149Sbostic 			if (*t == ')')
7549149Sbostic 				break;
7649149Sbostic 			if (!isdigit(*t))
7749149Sbostic 				goto badspec;
7849149Sbostic 			*argp++ = atoi(t);
7949149Sbostic 			for (++t; isdigit(*t); ++t);
8049149Sbostic 			if (*t != ',' && *t != ')' || cnt == 4)
8149149Sbostic 				goto badspec;
8249149Sbostic 		}
8349149Sbostic 		for (++t; isspace(*t); ++t);
8449149Sbostic 		argp -= 4;
8549149Sbostic 		file->i_adapt = *argp++;
8649149Sbostic 		file->i_ctlr = *argp++;
8749149Sbostic 		file->i_unit = *argp++;
8849149Sbostic 		file->i_part = *argp;
8949149Sbostic 		break;
9049149Sbostic 	case ':':	/* [A-Za-z]*[0-9]*[A-Za-z]:file */
9149149Sbostic 		for (t = str; *t != ':' && !isdigit(*t); ++t);
9249149Sbostic 		if ((file->i_dev = getdev(str, t - str)) == -1)
9349149Sbostic 			goto bad;
9449149Sbostic 		if ((file->i_unit = getunit(t)) == -1)
9549149Sbostic 			goto bad;
9649149Sbostic 		for (; isdigit(*t); ++t);
9749149Sbostic 		if (*t >= 'a' && *t <= 'h')
9849149Sbostic 			file->i_part = *t++ - 'a';
9949149Sbostic 		if (*t != ':') {
10049149Sbostic 			errno = EOFFSET;
10149149Sbostic 			goto badspec;
10249149Sbostic 		}
10349149Sbostic 		for (++t; isspace(*t); ++t);
10449149Sbostic 		break;
10549149Sbostic 	case '/':
10649149Sbostic 	default:		/* default bootstrap unit and device */
10749149Sbostic #else
10849149Sbostic 	{
10949149Sbostic #endif /* SMALL */
11049149Sbostic 		file->i_dev = B_TYPE(bootdev);
11149149Sbostic 		file->i_adapt = B_ADAPTOR(bootdev);
11249149Sbostic 		file->i_ctlr = B_CONTROLLER(bootdev);
11349149Sbostic 		file->i_unit = B_UNIT(bootdev);
11449149Sbostic 		file->i_part = B_PARTITION(bootdev);
11549149Sbostic 		t = str;
11649149Sbostic 	}
11749149Sbostic 
11849149Sbostic 	opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr,
11949149Sbostic 	    file->i_unit, file->i_part);
12049149Sbostic 
12149149Sbostic 	if (errno = devopen(file))
12249149Sbostic 		goto bad;
12349149Sbostic 
12449149Sbostic 	if (*t == '\0') {
12549149Sbostic 		file->i_flgs |= how + 1;
12649149Sbostic 		file->i_cc = 0;
12749149Sbostic 		file->i_offset = 0;
12849149Sbostic 		return (fdesc+3);
12949149Sbostic 	}
13049149Sbostic #ifndef SMALL
13149149Sbostic 	else if (how != 0) {
13249149Sbostic 		printf("Can't write files yet.. Sorry\n");
13349149Sbostic 		errno = EIO;
13449149Sbostic 		goto bad;
13549149Sbostic 	}
13649149Sbostic #endif
13749149Sbostic 	file->i_ma = (char *)(&file->i_fs);
13849149Sbostic 	file->i_cc = SBSIZE;
13949149Sbostic 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
14049149Sbostic 	file->i_offset = 0;
14149149Sbostic 	if (devread(file) < 0) {
14249149Sbostic 		errno = file->i_error;
14349149Sbostic 		printf("super block read error\n");
14449149Sbostic 		goto bad;
14549149Sbostic 	}
14649149Sbostic 	if ((cnt = find(t, file)) == 0) {
14749149Sbostic 		errno = ESRCH;
14849149Sbostic 		goto bad;
14949149Sbostic 	}
15049149Sbostic 	if (openi(cnt, file) < 0) {
15149149Sbostic 		errno = file->i_error;
15249149Sbostic 		goto bad;
15349149Sbostic 	}
15449149Sbostic 	file->i_offset = 0;
15549149Sbostic 	file->i_cc = 0;
15649149Sbostic 	file->i_flgs |= F_FILE | (how+1);
15749149Sbostic 	return (fdesc+3);
15849149Sbostic 
15949149Sbostic #ifndef SMALL
16049149Sbostic badspec:
16149149Sbostic 	printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n");
16249149Sbostic #endif
16349149Sbostic bad:
16449149Sbostic 	file->i_flgs = 0;
16549149Sbostic 	return (-1);
16649149Sbostic }
16749149Sbostic 
16849149Sbostic #ifndef SMALL
16949149Sbostic static
17049149Sbostic getdev(str, len)
17149149Sbostic 	register char *str;
17249149Sbostic 	int len;
17349149Sbostic {
17449149Sbostic 	register struct devsw *dp;
17549149Sbostic 	register int i;
17649149Sbostic 	char savedch = str[len];
17749149Sbostic 
17849149Sbostic 	str[len] = '\0';
17949149Sbostic 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
18049149Sbostic 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
18149149Sbostic 			str[len] = savedch;
18249149Sbostic 			return (i);
18349149Sbostic 		}
18449149Sbostic 	printf("Unknown device\nKnown devices are:\n");
18549149Sbostic 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
18649149Sbostic 		if (dp->dv_name)
18749149Sbostic 			printf(" %s", dp->dv_name);
18849149Sbostic 	printf("\n");
18949149Sbostic 	errno = ENXIO;
19049149Sbostic 	return (-1);
19149149Sbostic }
19249149Sbostic 
19349149Sbostic static
19449149Sbostic getunit(cp)
19549149Sbostic 	register char *cp;
19649149Sbostic {
19749149Sbostic 	int unit;
19849149Sbostic 
19949149Sbostic 	unit = atoi(cp);
20049149Sbostic 	if ((u_int)unit > 255) {
20149149Sbostic 		printf("minor device number out of range (0-255)\n");
20249149Sbostic 		errno = EUNIT;
20349149Sbostic 		return (-1);
20449149Sbostic 	}
20549149Sbostic 	return (unit);
20649149Sbostic }
20749149Sbostic #endif /* SMALL */
20849149Sbostic 
20949149Sbostic static
21049149Sbostic find(path, file)
21149149Sbostic 	register char *path;
21249149Sbostic 	struct iob *file;
21349149Sbostic {
21449149Sbostic 	register char *q;
21549149Sbostic 	char *dir, c;
21649149Sbostic 	int n;
21749149Sbostic 
21849149Sbostic 	if (path == NULL || *path == '\0') {
21949149Sbostic 		printf("null path\n");
22049149Sbostic 		return (0);
22149149Sbostic 	}
22249149Sbostic 
22349149Sbostic 	if (openi((ino_t) ROOTINO, file) < 0) {
22449149Sbostic 		printf("can't read root inode\n");
22549149Sbostic 		return (0);
22649149Sbostic 	}
22749149Sbostic 	dir = path;
22849149Sbostic 	while (*path) {
22949149Sbostic 		while (*path == '/')
23049149Sbostic 			path++;
23149149Sbostic 		q = path;
23249149Sbostic 		while(*q != '/' && *q != '\0')
23349149Sbostic 			q++;
23449149Sbostic 		c = *q;
23549149Sbostic 		*q = '\0';
23649149Sbostic 		if (q == path) path = "." ;	/* "/" means "/." */
23749149Sbostic 
23849149Sbostic 		if ((n = dlook(path, file, dir)) != 0) {
23949149Sbostic 			if (c == '\0')
24049149Sbostic 				break;
24149149Sbostic 			if (openi(n, file) < 0)
24249149Sbostic 				return (0);
24349149Sbostic 			*q = c;
24449149Sbostic 			path = q;
24549149Sbostic 			continue;
24649149Sbostic 		} else {
24749149Sbostic 			printf("%s: not found\n", path);
24849149Sbostic 			return (0);
24949149Sbostic 		}
25049149Sbostic 	}
25149149Sbostic 	return (n);
25249149Sbostic }
25349149Sbostic 
25449149Sbostic static ino_t
25549149Sbostic dlook(s, io, dir)
25649149Sbostic 	char *s;
25749149Sbostic 	register struct iob *io;
25849149Sbostic 	char *dir;
25949149Sbostic {
26049149Sbostic 	register struct direct *dp;
26149149Sbostic 	register struct dinode *ip;
26249149Sbostic 	struct dirstuff dirp;
26349149Sbostic 	int len;
26449149Sbostic 
26549149Sbostic 	if (s == NULL || *s == '\0')
26649149Sbostic 		return (0);
26749149Sbostic 	ip = &io->i_ino;
26849149Sbostic 	if ((ip->di_mode&IFMT) != IFDIR) {
26949149Sbostic 		printf("%s: not a directory\n", dir);
27049149Sbostic 		return (0);
27149149Sbostic 	}
27249149Sbostic 	if (ip->di_size == 0) {
27349149Sbostic 		printf("%s: zero length directory\n", dir);
27449149Sbostic 		return (0);
27549149Sbostic 	}
27649149Sbostic 	len = strlen(s);
27749149Sbostic 	dirp.loc = 0;
27849149Sbostic 	dirp.io = io;
27955894Shibler 	dirp.name = dir;
28049149Sbostic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
28149149Sbostic 		if(dp->d_ino == 0)
28249149Sbostic 			continue;
28349149Sbostic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
28449149Sbostic 			return (dp->d_ino);
28549149Sbostic 	}
28649149Sbostic 	return (0);
28749149Sbostic }
28849149Sbostic 
28949149Sbostic static struct direct *
29049149Sbostic readdir(dirp)
29149149Sbostic 	register struct dirstuff *dirp;
29249149Sbostic {
29349149Sbostic 	register struct direct *dp;
29449149Sbostic 	register struct iob *io;
29549149Sbostic 	daddr_t lbn, d;
29649149Sbostic 	int off;
29749149Sbostic 
29849149Sbostic 	io = dirp->io;
29949149Sbostic 	for(;;) {
30049149Sbostic 		if (dirp->loc >= io->i_ino.di_size)
30149149Sbostic 			return (NULL);
30249149Sbostic 		off = blkoff(&io->i_fs, dirp->loc);
30349149Sbostic 		if (off == 0) {
30449149Sbostic 			lbn = lblkno(&io->i_fs, dirp->loc);
30549149Sbostic 			d = bmap(io, lbn);
30649149Sbostic 			if(d == 0)
30749149Sbostic 				return (NULL);
30849149Sbostic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
30949149Sbostic 			io->i_ma = io->i_buf;
31049149Sbostic 			io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
31149149Sbostic 			if (devread(io) < 0) {
31249149Sbostic 				errno = io->i_error;
31355894Shibler 				printf("%s: directory read error, bn %ld\n",
31455894Shibler 					dirp->name, io->i_bn);
31549149Sbostic 				return (NULL);
31649149Sbostic 			}
31749149Sbostic 		}
31849149Sbostic 		dp = (struct direct *)(io->i_buf + off);
31949149Sbostic 		dirp->loc += dp->d_reclen;
32055894Shibler 		if (dp->d_ino == 0) {
32155894Shibler 			if (dp->d_reclen == 0) {
32255894Shibler 				printf("%s: bad directory entry, offset %ld\n",
32355894Shibler 				       dirp->name, dirp->loc);
32455894Shibler 				return (NULL);
32555894Shibler 			}
32649149Sbostic 			continue;
32755894Shibler 		}
32849149Sbostic 		return (dp);
32949149Sbostic 	}
33049149Sbostic }
33149149Sbostic 
33249149Sbostic static
33349149Sbostic openi(n, io)
33449149Sbostic 	int n;
33549149Sbostic 	register struct iob *io;
33649149Sbostic {
33749149Sbostic 	register struct dinode *dp;
33849149Sbostic 	int cc;
33949149Sbostic 
34049149Sbostic 	io->i_offset = 0;
34149149Sbostic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
34249149Sbostic 	io->i_cc = io->i_fs.fs_bsize;
34349149Sbostic 	io->i_ma = io->i_buf;
34449149Sbostic 	cc = devread(io);
34549149Sbostic 	dp = (struct dinode *)io->i_buf;
34649149Sbostic 	io->i_ino = dp[itoo(&io->i_fs, n)];
34749149Sbostic 	return (cc);
34849149Sbostic }
349