xref: /csrg-svn/sys/stand.att/open.c (revision 63721)
149149Sbostic /*-
2*63721Sbostic  * Copyright (c) 1982, 1988, 1993
3*63721Sbostic  *	The Regents of the University of California.  All rights reserved.
449149Sbostic  *
549149Sbostic  * %sccs.include.proprietary.c%
649149Sbostic  *
7*63721Sbostic  *	@(#)open.c	8.1 (Berkeley) 07/07/93
849149Sbostic  */
949149Sbostic 
1049149Sbostic #include <sys/param.h>
1149149Sbostic #include <sys/reboot.h>
1256509Sbostic 
1353697Ssklower #include <ufs/ufs/dir.h>
1460328Smckusick #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
2763719Smckusick /*
2863719Smckusick  * XXX avoid stdio... its a long story.
2963719Smckusick  */
3063719Smckusick #define isupper(c)	((c) >= 'A' && (c) <= 'Z')
3163719Smckusick #define tolower(c)	((c) - 'A' + 'a')
3263719Smckusick #define isspace(c)	((c) == ' ' || (c) == '\t')
3363719Smckusick #define isdigit(c)	((c) >= '0' && (c) <= '9')
3463719Smckusick 
3549149Sbostic static ino_t dlook __P((char *, struct iob *, char *));
3649149Sbostic static int find __P((char *, struct iob *));
3749149Sbostic static int getdev __P((char *, int));
3849149Sbostic static int getunit __P((char *));
3949149Sbostic static struct direct *readdir __P((struct dirstuff *));
4049149Sbostic static int openi __P((int, struct iob *));
4149149Sbostic #endif
4249149Sbostic 
open(str,how)4349149Sbostic open(str, how)
4449149Sbostic 	char *str;
4549149Sbostic 	int how;
4649149Sbostic {
4749149Sbostic 	static int firstopen = 1;
4849149Sbostic 	register struct iob *file;
4949149Sbostic 	register char *t;
5049149Sbostic 	register int cnt;
5149149Sbostic 	int fdesc, args[8], *argp;
5249149Sbostic 
5349149Sbostic 	if (firstopen) {
5449149Sbostic 		for (cnt = 0; cnt < SOPEN_MAX; cnt++)
5549149Sbostic 			iob[cnt].i_flgs = 0;
5649149Sbostic 		firstopen = 0;
5749149Sbostic 	}
5849149Sbostic 
5949149Sbostic 	for (fdesc = 0;; fdesc++) {
6049149Sbostic 		if (fdesc == SOPEN_MAX)
6149149Sbostic 			_stop("No more file slots");
6249149Sbostic 		if (iob[fdesc].i_flgs == 0) {
6349149Sbostic 			file = &iob[fdesc];
6449149Sbostic 			file->i_flgs |= F_ALLOC;
6549149Sbostic 			file->i_adapt = file->i_ctlr = file->i_unit =
6649149Sbostic 			    file->i_part = 0;
6749149Sbostic 			break;
6849149Sbostic 		}
6949149Sbostic 	}
7049149Sbostic 
7149149Sbostic 	for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
7249149Sbostic #ifndef SMALL
7349149Sbostic 	for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
7449149Sbostic 		if (isupper(*t))
7549149Sbostic 			*t = tolower(*t);
7649149Sbostic 	switch(*t) {
7749149Sbostic 	case '(':	/* type(adapt, ctlr, drive, partition)file */
7849149Sbostic 		if ((file->i_dev = getdev(str, t - str)) == -1)
7949149Sbostic 			goto bad;
8049149Sbostic 		for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
8149149Sbostic 			for (++t; isspace(*t); ++t);
8249149Sbostic 			if (*t == ')')
8349149Sbostic 				break;
8449149Sbostic 			if (!isdigit(*t))
8549149Sbostic 				goto badspec;
8649149Sbostic 			*argp++ = atoi(t);
8749149Sbostic 			for (++t; isdigit(*t); ++t);
8849149Sbostic 			if (*t != ',' && *t != ')' || cnt == 4)
8949149Sbostic 				goto badspec;
9049149Sbostic 		}
9149149Sbostic 		for (++t; isspace(*t); ++t);
9249149Sbostic 		argp -= 4;
9349149Sbostic 		file->i_adapt = *argp++;
9449149Sbostic 		file->i_ctlr = *argp++;
9549149Sbostic 		file->i_unit = *argp++;
9649149Sbostic 		file->i_part = *argp;
9749149Sbostic 		break;
9849149Sbostic 	case ':':	/* [A-Za-z]*[0-9]*[A-Za-z]:file */
9949149Sbostic 		for (t = str; *t != ':' && !isdigit(*t); ++t);
10049149Sbostic 		if ((file->i_dev = getdev(str, t - str)) == -1)
10149149Sbostic 			goto bad;
10249149Sbostic 		if ((file->i_unit = getunit(t)) == -1)
10349149Sbostic 			goto bad;
10449149Sbostic 		for (; isdigit(*t); ++t);
10549149Sbostic 		if (*t >= 'a' && *t <= 'h')
10649149Sbostic 			file->i_part = *t++ - 'a';
10749149Sbostic 		if (*t != ':') {
10849149Sbostic 			errno = EOFFSET;
10949149Sbostic 			goto badspec;
11049149Sbostic 		}
11149149Sbostic 		for (++t; isspace(*t); ++t);
11249149Sbostic 		break;
11349149Sbostic 	case '/':
11449149Sbostic 	default:		/* default bootstrap unit and device */
11549149Sbostic #else
11649149Sbostic 	{
11749149Sbostic #endif /* SMALL */
11849149Sbostic 		file->i_dev = B_TYPE(bootdev);
11949149Sbostic 		file->i_adapt = B_ADAPTOR(bootdev);
12049149Sbostic 		file->i_ctlr = B_CONTROLLER(bootdev);
12149149Sbostic 		file->i_unit = B_UNIT(bootdev);
12249149Sbostic 		file->i_part = B_PARTITION(bootdev);
12349149Sbostic 		t = str;
12449149Sbostic 	}
12549149Sbostic 
12649149Sbostic 	opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr,
12749149Sbostic 	    file->i_unit, file->i_part);
12849149Sbostic 
12949149Sbostic 	if (errno = devopen(file))
13049149Sbostic 		goto bad;
13149149Sbostic 
13249149Sbostic 	if (*t == '\0') {
13349149Sbostic 		file->i_flgs |= how + 1;
13449149Sbostic 		file->i_cc = 0;
13549149Sbostic 		file->i_offset = 0;
13649149Sbostic 		return (fdesc+3);
13749149Sbostic 	}
13849149Sbostic #ifndef SMALL
13949149Sbostic 	else if (how != 0) {
14049149Sbostic 		printf("Can't write files yet.. Sorry\n");
14149149Sbostic 		errno = EIO;
14249149Sbostic 		goto bad;
14349149Sbostic 	}
14449149Sbostic #endif
14549149Sbostic 	file->i_ma = (char *)(&file->i_fs);
14649149Sbostic 	file->i_cc = SBSIZE;
14749149Sbostic 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
14849149Sbostic 	file->i_offset = 0;
14949149Sbostic 	if (devread(file) < 0) {
15049149Sbostic 		errno = file->i_error;
15149149Sbostic 		printf("super block read error\n");
15249149Sbostic 		goto bad;
15349149Sbostic 	}
15449149Sbostic 	if ((cnt = find(t, file)) == 0) {
15549149Sbostic 		errno = ESRCH;
15649149Sbostic 		goto bad;
15749149Sbostic 	}
15849149Sbostic 	if (openi(cnt, file) < 0) {
15949149Sbostic 		errno = file->i_error;
16049149Sbostic 		goto bad;
16149149Sbostic 	}
16249149Sbostic 	file->i_offset = 0;
16349149Sbostic 	file->i_cc = 0;
16449149Sbostic 	file->i_flgs |= F_FILE | (how+1);
16549149Sbostic 	return (fdesc+3);
16649149Sbostic 
16749149Sbostic #ifndef SMALL
16849149Sbostic badspec:
16949149Sbostic 	printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n");
17049149Sbostic #endif
17149149Sbostic bad:
17249149Sbostic 	file->i_flgs = 0;
17349149Sbostic 	return (-1);
17449149Sbostic }
17549149Sbostic 
17649149Sbostic #ifndef SMALL
17749149Sbostic static
getdev(str,len)17849149Sbostic getdev(str, len)
17949149Sbostic 	register char *str;
18049149Sbostic 	int len;
18149149Sbostic {
18249149Sbostic 	register struct devsw *dp;
18349149Sbostic 	register int i;
18449149Sbostic 	char savedch = str[len];
18549149Sbostic 
18649149Sbostic 	str[len] = '\0';
18749149Sbostic 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
18849149Sbostic 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
18949149Sbostic 			str[len] = savedch;
19049149Sbostic 			return (i);
19149149Sbostic 		}
19249149Sbostic 	printf("Unknown device\nKnown devices are:\n");
19349149Sbostic 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
19449149Sbostic 		if (dp->dv_name)
19549149Sbostic 			printf(" %s", dp->dv_name);
19649149Sbostic 	printf("\n");
19749149Sbostic 	errno = ENXIO;
19849149Sbostic 	return (-1);
19949149Sbostic }
20049149Sbostic 
20149149Sbostic static
getunit(cp)20249149Sbostic getunit(cp)
20349149Sbostic 	register char *cp;
20449149Sbostic {
20549149Sbostic 	int unit;
20649149Sbostic 
20749149Sbostic 	unit = atoi(cp);
20849149Sbostic 	if ((u_int)unit > 255) {
20949149Sbostic 		printf("minor device number out of range (0-255)\n");
21049149Sbostic 		errno = EUNIT;
21149149Sbostic 		return (-1);
21249149Sbostic 	}
21349149Sbostic 	return (unit);
21449149Sbostic }
21563719Smckusick 
21663719Smckusick /*
21763719Smckusick  * XXX more stdio-avoidance.
21863719Smckusick  */
atoi(cp)21963719Smckusick atoi(cp)
22063719Smckusick 	char *cp;
22163719Smckusick {
22263719Smckusick 	int val = 0;
22363719Smckusick 
22463719Smckusick 	while (*cp >= '0' && *cp <= '9')
22563719Smckusick 		val = val * 10 + (*cp++ - '0');
22663719Smckusick 	return (val);
22763719Smckusick }
22849149Sbostic #endif /* SMALL */
22949149Sbostic 
23049149Sbostic static
find(path,file)23149149Sbostic find(path, file)
23249149Sbostic 	register char *path;
23349149Sbostic 	struct iob *file;
23449149Sbostic {
23549149Sbostic 	register char *q;
23649149Sbostic 	char *dir, c;
23749149Sbostic 	int n;
23849149Sbostic 
23949149Sbostic 	if (path == NULL || *path == '\0') {
24049149Sbostic 		printf("null path\n");
24149149Sbostic 		return (0);
24249149Sbostic 	}
24349149Sbostic 
24449149Sbostic 	if (openi((ino_t) ROOTINO, file) < 0) {
24549149Sbostic 		printf("can't read root inode\n");
24649149Sbostic 		return (0);
24749149Sbostic 	}
24849149Sbostic 	dir = path;
24949149Sbostic 	while (*path) {
25049149Sbostic 		while (*path == '/')
25149149Sbostic 			path++;
25249149Sbostic 		q = path;
25349149Sbostic 		while(*q != '/' && *q != '\0')
25449149Sbostic 			q++;
25549149Sbostic 		c = *q;
25649149Sbostic 		*q = '\0';
25749149Sbostic 		if (q == path) path = "." ;	/* "/" means "/." */
25849149Sbostic 
25949149Sbostic 		if ((n = dlook(path, file, dir)) != 0) {
26049149Sbostic 			if (c == '\0')
26149149Sbostic 				break;
26249149Sbostic 			if (openi(n, file) < 0)
26349149Sbostic 				return (0);
26449149Sbostic 			*q = c;
26549149Sbostic 			path = q;
26649149Sbostic 			continue;
26749149Sbostic 		} else {
26849149Sbostic 			printf("%s: not found\n", path);
26949149Sbostic 			return (0);
27049149Sbostic 		}
27149149Sbostic 	}
27249149Sbostic 	return (n);
27349149Sbostic }
27449149Sbostic 
27549149Sbostic static ino_t
dlook(s,io,dir)27649149Sbostic dlook(s, io, dir)
27749149Sbostic 	char *s;
27849149Sbostic 	register struct iob *io;
27949149Sbostic 	char *dir;
28049149Sbostic {
28149149Sbostic 	register struct direct *dp;
28249149Sbostic 	register struct dinode *ip;
28349149Sbostic 	struct dirstuff dirp;
28449149Sbostic 	int len;
28549149Sbostic 
28649149Sbostic 	if (s == NULL || *s == '\0')
28749149Sbostic 		return (0);
28849149Sbostic 	ip = &io->i_ino;
28949149Sbostic 	if ((ip->di_mode&IFMT) != IFDIR) {
29049149Sbostic 		printf("%s: not a directory\n", dir);
29149149Sbostic 		return (0);
29249149Sbostic 	}
29349149Sbostic 	if (ip->di_size == 0) {
29449149Sbostic 		printf("%s: zero length directory\n", dir);
29549149Sbostic 		return (0);
29649149Sbostic 	}
29749149Sbostic 	len = strlen(s);
29849149Sbostic 	dirp.loc = 0;
29949149Sbostic 	dirp.io = io;
30055894Shibler 	dirp.name = dir;
30149149Sbostic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
30249149Sbostic 		if(dp->d_ino == 0)
30349149Sbostic 			continue;
30449149Sbostic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
30549149Sbostic 			return (dp->d_ino);
30649149Sbostic 	}
30749149Sbostic 	return (0);
30849149Sbostic }
30949149Sbostic 
31049149Sbostic static struct direct *
readdir(dirp)31149149Sbostic readdir(dirp)
31249149Sbostic 	register struct dirstuff *dirp;
31349149Sbostic {
31449149Sbostic 	register struct direct *dp;
31549149Sbostic 	register struct iob *io;
31649149Sbostic 	daddr_t lbn, d;
31749149Sbostic 	int off;
31849149Sbostic 
31949149Sbostic 	io = dirp->io;
32049149Sbostic 	for(;;) {
32149149Sbostic 		if (dirp->loc >= io->i_ino.di_size)
32249149Sbostic 			return (NULL);
32349149Sbostic 		off = blkoff(&io->i_fs, dirp->loc);
32449149Sbostic 		if (off == 0) {
32549149Sbostic 			lbn = lblkno(&io->i_fs, dirp->loc);
32649149Sbostic 			d = bmap(io, lbn);
32749149Sbostic 			if(d == 0)
32849149Sbostic 				return (NULL);
32949149Sbostic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
33049149Sbostic 			io->i_ma = io->i_buf;
33149149Sbostic 			io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
33249149Sbostic 			if (devread(io) < 0) {
33349149Sbostic 				errno = io->i_error;
33455894Shibler 				printf("%s: directory read error, bn %ld\n",
33555894Shibler 					dirp->name, io->i_bn);
33649149Sbostic 				return (NULL);
33749149Sbostic 			}
33849149Sbostic 		}
33949149Sbostic 		dp = (struct direct *)(io->i_buf + off);
34049149Sbostic 		dirp->loc += dp->d_reclen;
34155894Shibler 		if (dp->d_ino == 0) {
34255894Shibler 			if (dp->d_reclen == 0) {
34355894Shibler 				printf("%s: bad directory entry, offset %ld\n",
34455894Shibler 				       dirp->name, dirp->loc);
34555894Shibler 				return (NULL);
34655894Shibler 			}
34749149Sbostic 			continue;
34855894Shibler 		}
34949149Sbostic 		return (dp);
35049149Sbostic 	}
35149149Sbostic }
35249149Sbostic 
35349149Sbostic static
openi(n,io)35449149Sbostic openi(n, io)
35549149Sbostic 	int n;
35649149Sbostic 	register struct iob *io;
35749149Sbostic {
35849149Sbostic 	register struct dinode *dp;
35949149Sbostic 	int cc;
36049149Sbostic 
36149149Sbostic 	io->i_offset = 0;
36249149Sbostic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
36349149Sbostic 	io->i_cc = io->i_fs.fs_bsize;
36449149Sbostic 	io->i_ma = io->i_buf;
36549149Sbostic 	cc = devread(io);
36649149Sbostic 	dp = (struct dinode *)io->i_buf;
36749149Sbostic 	io->i_ino = dp[itoo(&io->i_fs, n)];
36849149Sbostic 	return (cc);
36949149Sbostic }
370