xref: /csrg-svn/sys/stand.att/sys.c (revision 48826)
123243Smckusick /*
229310Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323243Smckusick  * All rights reserved.  The Berkeley software License Agreement
423243Smckusick  * specifies the terms and conditions for redistribution.
523243Smckusick  *
6*48826Swilliam  *	@(#)sys.c	7.14 (Berkeley) 04/28/91
723243Smckusick  */
8327Sbill 
940498Sroot #include "sys/param.h"
1045792Sbostic #include "sys/reboot.h"
1140498Sroot #include "ufs/dir.h"
1245792Sbostic #include "stand/saio.h"		/* used from machine/stand dir */
13327Sbill 
1434942Sbostic #define	isdigit(c)	((u_int)((c) - '0') <= 9)
1534463Sbostic #define	isspace(c)	((c) == ' ' || (c) == '\t')
1634942Sbostic #define	isupper(c)	((u_int)((c) - 'A') <= 'Z' - 'A')
1734463Sbostic #define	tolower(c)	((c) - 'A' + 'a')
1834463Sbostic 
19327Sbill ino_t	dlook();
20327Sbill 
216068Smckusic struct dirstuff {
226068Smckusic 	int loc;
236068Smckusic 	struct iob *io;
246068Smckusic };
256068Smckusic 
2634463Sbostic struct iob iob[NFILES];
2734463Sbostic 
28327Sbill static
2910022Ssam openi(n, io)
306068Smckusic 	register struct iob *io;
31327Sbill {
32327Sbill 	register struct dinode *dp;
3311083Ssam 	int cc;
34327Sbill 
35327Sbill 	io->i_offset = 0;
366068Smckusic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
376068Smckusic 	io->i_cc = io->i_fs.fs_bsize;
38327Sbill 	io->i_ma = io->i_buf;
3911083Ssam 	cc = devread(io);
40327Sbill 	dp = (struct dinode *)io->i_buf;
4140500Smckusick 	io->i_ino = dp[itoo(&io->i_fs, n)];
4211083Ssam 	return (cc);
43327Sbill }
44327Sbill 
45327Sbill static
46327Sbill find(path, file)
476068Smckusic 	register char *path;
486068Smckusic 	struct iob *file;
49327Sbill {
50327Sbill 	register char *q;
5134463Sbostic 	char *dir, c;
52327Sbill 	int n;
53327Sbill 
5434463Sbostic 	if (path == NULL || *path == '\0') {
55327Sbill 		printf("null path\n");
5610022Ssam 		return (0);
57327Sbill 	}
58327Sbill 
5911083Ssam 	if (openi((ino_t) ROOTINO, file) < 0) {
6011083Ssam 		printf("can't read root inode\n");
6111083Ssam 		return (0);
6211083Ssam 	}
6330768Skarels 	dir = path;
64327Sbill 	while (*path) {
65327Sbill 		while (*path == '/')
66327Sbill 			path++;
67327Sbill 		q = path;
68327Sbill 		while(*q != '/' && *q != '\0')
69327Sbill 			q++;
70327Sbill 		c = *q;
71327Sbill 		*q = '\0';
7225166Skarels 		if (q == path) path = "." ;	/* "/" means "/." */
73327Sbill 
7430768Skarels 		if ((n = dlook(path, file, dir)) != 0) {
7511083Ssam 			if (c == '\0')
76327Sbill 				break;
7711083Ssam 			if (openi(n, file) < 0)
7811083Ssam 				return (0);
79327Sbill 			*q = c;
80327Sbill 			path = q;
81327Sbill 			continue;
82327Sbill 		} else {
8325166Skarels 			printf("%s: not found\n", path);
8410022Ssam 			return (0);
85327Sbill 		}
86327Sbill 	}
8710022Ssam 	return (n);
88327Sbill }
89327Sbill 
9034463Sbostic #define	NBUFS	4
9134463Sbostic static char	b[NBUFS][MAXBSIZE];
9234463Sbostic static daddr_t	blknos[NBUFS];
9334463Sbostic 
94327Sbill static daddr_t
95327Sbill sbmap(io, bn)
966068Smckusic 	register struct iob *io;
976068Smckusic 	daddr_t bn;
98327Sbill {
9940500Smckusick 	register struct dinode *ip;
1006068Smckusic 	int i, j, sh;
101327Sbill 	daddr_t nb, *bap;
102327Sbill 
103327Sbill 	ip = &io->i_ino;
1046068Smckusic 	if (bn < 0) {
105327Sbill 		printf("bn negative\n");
10610022Ssam 		return ((daddr_t)0);
107327Sbill 	}
108327Sbill 
109327Sbill 	/*
1106068Smckusic 	 * blocks 0..NDADDR are direct blocks
111327Sbill 	 */
1126068Smckusic 	if(bn < NDADDR) {
11340500Smckusick 		nb = ip->di_db[bn];
11410022Ssam 		return (nb);
115327Sbill 	}
116327Sbill 
117327Sbill 	/*
1186068Smckusic 	 * addresses NIADDR have single and double indirect blocks.
1196068Smckusic 	 * the first step is to determine how many levels of indirection.
120327Sbill 	 */
1216068Smckusic 	sh = 1;
1226068Smckusic 	bn -= NDADDR;
1236068Smckusic 	for (j = NIADDR; j > 0; j--) {
1246068Smckusic 		sh *= NINDIR(&io->i_fs);
1256068Smckusic 		if (bn < sh)
126327Sbill 			break;
1276068Smckusic 		bn -= sh;
128327Sbill 	}
1296068Smckusic 	if (j == 0) {
1306068Smckusic 		printf("bn ovf %D\n", bn);
1316068Smckusic 		return ((daddr_t)0);
132327Sbill 	}
133327Sbill 
134327Sbill 	/*
1356068Smckusic 	 * fetch the first indirect block address from the inode
136327Sbill 	 */
13740500Smckusick 	nb = ip->di_ib[NIADDR - j];
1386068Smckusic 	if (nb == 0) {
139327Sbill 		printf("bn void %D\n",bn);
14010022Ssam 		return ((daddr_t)0);
141327Sbill 	}
142327Sbill 
143327Sbill 	/*
144327Sbill 	 * fetch through the indirect blocks
145327Sbill 	 */
1466068Smckusic 	for (; j <= NIADDR; j++) {
147327Sbill 		if (blknos[j] != nb) {
1486068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
149327Sbill 			io->i_ma = b[j];
1506068Smckusic 			io->i_cc = io->i_fs.fs_bsize;
15111083Ssam 			if (devread(io) != io->i_fs.fs_bsize) {
15211083Ssam 				if (io->i_error)
15311083Ssam 					errno = io->i_error;
15411083Ssam 				printf("bn %D: read error\n", io->i_bn);
15511083Ssam 				return ((daddr_t)0);
15611083Ssam 			}
157327Sbill 			blknos[j] = nb;
158327Sbill 		}
159327Sbill 		bap = (daddr_t *)b[j];
1606068Smckusic 		sh /= NINDIR(&io->i_fs);
1616068Smckusic 		i = (bn / sh) % NINDIR(&io->i_fs);
162327Sbill 		nb = bap[i];
163327Sbill 		if(nb == 0) {
164327Sbill 			printf("bn void %D\n",bn);
16510022Ssam 			return ((daddr_t)0);
166327Sbill 		}
167327Sbill 	}
16810022Ssam 	return (nb);
169327Sbill }
170327Sbill 
1716068Smckusic /*
1726068Smckusic  * get next entry in a directory.
1736068Smckusic  */
1746068Smckusic struct direct *
1756068Smckusic readdir(dirp)
1766068Smckusic 	register struct dirstuff *dirp;
177327Sbill {
1786068Smckusic 	register struct direct *dp;
1796068Smckusic 	register struct iob *io;
1806068Smckusic 	daddr_t lbn, d;
1816068Smckusic 	int off;
182327Sbill 
1836068Smckusic 	io = dirp->io;
1846068Smckusic 	for(;;) {
18540500Smckusick 		if (dirp->loc >= io->i_ino.di_size)
18611083Ssam 			return (NULL);
1876068Smckusic 		off = blkoff(&io->i_fs, dirp->loc);
1886068Smckusic 		if (off == 0) {
1896068Smckusic 			lbn = lblkno(&io->i_fs, dirp->loc);
1906068Smckusic 			d = sbmap(io, lbn);
1916068Smckusic 			if(d == 0)
19234463Sbostic 				return (NULL);
1936068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
1946068Smckusic 			io->i_ma = io->i_buf;
19540500Smckusick 			io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn);
19611083Ssam 			if (devread(io) < 0) {
19711083Ssam 				errno = io->i_error;
19825166Skarels 				printf("bn %D: directory read error\n",
19925166Skarels 					io->i_bn);
20011083Ssam 				return (NULL);
20111083Ssam 			}
2026068Smckusic 		}
2036068Smckusic 		dp = (struct direct *)(io->i_buf + off);
2046068Smckusic 		dirp->loc += dp->d_reclen;
2056068Smckusic 		if (dp->d_ino == 0)
2066068Smckusic 			continue;
2076068Smckusic 		return (dp);
208327Sbill 	}
209327Sbill }
210327Sbill 
21140500Smckusick static ino_t
21240500Smckusick dlook(s, io, dir)
21340500Smckusick 	char *s;
21440500Smckusick 	register struct iob *io;
21540500Smckusick 	char *dir;
21640500Smckusick {
21740500Smckusick 	register struct direct *dp;
21840500Smckusick 	register struct dinode *ip;
21940500Smckusick 	struct dirstuff dirp;
22040500Smckusick 	int len;
22140500Smckusick 
22240500Smckusick 	if (s == NULL || *s == '\0')
22340500Smckusick 		return (0);
22440500Smckusick 	ip = &io->i_ino;
22540500Smckusick 	if ((ip->di_mode&IFMT) != IFDIR) {
22640500Smckusick 		printf("%s: not a directory\n", dir);
22740500Smckusick 		return (0);
22840500Smckusick 	}
22940500Smckusick 	if (ip->di_size == 0) {
23040500Smckusick 		printf("%s: zero length directory\n", dir);
23140500Smckusick 		return (0);
23240500Smckusick 	}
23340500Smckusick 	len = strlen(s);
23440500Smckusick 	dirp.loc = 0;
23540500Smckusick 	dirp.io = io;
23640500Smckusick 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
23740500Smckusick 		if(dp->d_ino == 0)
23840500Smckusick 			continue;
23940500Smckusick 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
24040500Smckusick 			return (dp->d_ino);
24140500Smckusick 	}
24240500Smckusick 	return (0);
24340500Smckusick }
24440500Smckusick 
245327Sbill lseek(fdesc, addr, ptr)
24610022Ssam 	int fdesc, ptr;
24710022Ssam 	off_t addr;
248327Sbill {
249327Sbill 	register struct iob *io;
250327Sbill 
25134463Sbostic #ifndef SMALL
25234463Sbostic 	if (ptr != L_SET) {
253327Sbill 		printf("Seek not from beginning of file\n");
25410022Ssam 		errno = EOFFSET;
25510022Ssam 		return (-1);
256327Sbill 	}
25734463Sbostic #endif
258327Sbill 	fdesc -= 3;
259*48826Swilliam #ifndef SMALL
2606068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
26110022Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
26210022Ssam 		errno = EBADF;
26310022Ssam 		return (-1);
26410022Ssam 	}
265*48826Swilliam #endif
266327Sbill 	io->i_offset = addr;
2676068Smckusic 	io->i_bn = addr / DEV_BSIZE;
268327Sbill 	io->i_cc = 0;
26910022Ssam 	return (0);
270327Sbill }
271327Sbill 
272327Sbill getc(fdesc)
27310022Ssam 	int fdesc;
274327Sbill {
275327Sbill 	register struct iob *io;
2766068Smckusic 	register struct fs *fs;
277327Sbill 	register char *p;
2786068Smckusic 	int c, lbn, off, size, diff;
279327Sbill 
280327Sbill 
281*48826Swilliam #ifndef SMALL
282327Sbill 	if (fdesc >= 0 && fdesc <= 2)
28310022Ssam 		return (getchar());
284*48826Swilliam #endif
285327Sbill 	fdesc -= 3;
2866068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
28710022Ssam 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
28810022Ssam 		errno = EBADF;
28910022Ssam 		return (-1);
29010022Ssam 	}
291327Sbill 	p = io->i_ma;
292327Sbill 	if (io->i_cc <= 0) {
2936068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
29440500Smckusick 			diff = io->i_ino.di_size - io->i_offset;
2956068Smckusic 			if (diff <= 0)
2966068Smckusic 				return (-1);
2976068Smckusic 			fs = &io->i_fs;
2986068Smckusic 			lbn = lblkno(fs, io->i_offset);
2996068Smckusic 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
3006068Smckusic 			off = blkoff(fs, io->i_offset);
30140500Smckusick 			size = dblksize(fs, &io->i_ino, lbn);
3026068Smckusic 		} else {
303*48826Swilliam 			io->i_bn = io->i_offset / DEV_BSIZE + io->i_boff;
3046068Smckusic 			off = 0;
3056068Smckusic 			size = DEV_BSIZE;
3066068Smckusic 		}
307327Sbill 		io->i_ma = io->i_buf;
3086068Smckusic 		io->i_cc = size;
30911083Ssam 		if (devread(io) < 0) {
31011083Ssam 			errno = io->i_error;
31111083Ssam 			return (-1);
31211083Ssam 		}
3136068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
31440500Smckusick 			if (io->i_offset - off + size >= io->i_ino.di_size)
3156068Smckusic 				io->i_cc = diff + off;
316327Sbill 			io->i_cc -= off;
3176068Smckusic 		}
318327Sbill 		p = &io->i_buf[off];
319327Sbill 	}
320327Sbill 	io->i_cc--;
321327Sbill 	io->i_offset++;
322327Sbill 	c = (unsigned)*p++;
323327Sbill 	io->i_ma = p;
32410022Ssam 	return (c);
325327Sbill }
3266068Smckusic 
32710022Ssam int	errno;
328327Sbill 
329327Sbill read(fdesc, buf, count)
33010022Ssam 	int fdesc, count;
33110022Ssam 	char *buf;
332327Sbill {
33325166Skarels 	register i, size;
334327Sbill 	register struct iob *file;
33525166Skarels 	register struct fs *fs;
33625166Skarels 	int lbn, off;
337327Sbill 
33810022Ssam 	errno = 0;
339*48826Swilliam #ifndef SMALL
34045352Sbostic 	if (fdesc >= 0 && fdesc <= 2) {
341327Sbill 		i = count;
342327Sbill 		do {
343327Sbill 			*buf = getchar();
344327Sbill 		} while (--i && *buf++ != '\n');
34510022Ssam 		return (count - i);
346327Sbill 	}
347*48826Swilliam #endif
348327Sbill 	fdesc -= 3;
3496068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
35010022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
35110022Ssam 		errno = EBADF;
35210022Ssam 		return (-1);
35310022Ssam 	}
35410022Ssam 	if ((file->i_flgs&F_READ) == 0) {
35510022Ssam 		errno = EBADF;
35610022Ssam 		return (-1);
35710022Ssam 	}
35834463Sbostic #ifndef SMALL
3596068Smckusic 	if ((file->i_flgs & F_FILE) == 0) {
360327Sbill 		file->i_cc = count;
361327Sbill 		file->i_ma = buf;
3627446Sroot 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
363327Sbill 		i = devread(file);
36410022Ssam 		if (i < 0)
36510022Ssam 			errno = file->i_error;
36630547Skarels 		else
36730547Skarels 			file->i_offset += i;
36810022Ssam 		return (i);
369327Sbill 	}
37034463Sbostic #endif
37140500Smckusick 	if (file->i_offset+count > file->i_ino.di_size)
37240500Smckusick 		count = file->i_ino.di_size - file->i_offset;
37325166Skarels 	if ((i = count) <= 0)
37425166Skarels 		return (0);
37525166Skarels 	/*
37625166Skarels 	 * While reading full blocks, do I/O into user buffer.
37725166Skarels 	 * Anything else uses getc().
37825166Skarels 	 */
37925166Skarels 	fs = &file->i_fs;
38025166Skarels 	while (i) {
38125166Skarels 		off = blkoff(fs, file->i_offset);
38225166Skarels 		lbn = lblkno(fs, file->i_offset);
38340500Smckusick 		size = dblksize(fs, &file->i_ino, lbn);
384*48826Swilliam #ifndef SMALL
38525166Skarels 		if (off == 0 && size <= i) {
38625166Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
38725166Skarels 			    file->i_boff;
38825166Skarels 			file->i_cc = size;
38925166Skarels 			file->i_ma = buf;
39025166Skarels 			if (devread(file) < 0) {
39125166Skarels 				errno = file->i_error;
39225166Skarels 				return (-1);
39325166Skarels 			}
39425166Skarels 			file->i_offset += size;
39525166Skarels 			file->i_cc = 0;
39625166Skarels 			buf += size;
39725166Skarels 			i -= size;
39825166Skarels 		} else {
399*48826Swilliam #endif
40025166Skarels 			size -= off;
40125166Skarels 			if (size > i)
40225166Skarels 				size = i;
40325166Skarels 			i -= size;
40425166Skarels 			do {
40525166Skarels 				*buf++ = getc(fdesc+3);
40625166Skarels 			} while (--size);
407*48826Swilliam #ifndef	SMALL
40825166Skarels 		}
409*48826Swilliam #endif
41025166Skarels 	}
41125166Skarels 	return (count);
412327Sbill }
413327Sbill 
41434463Sbostic #ifndef SMALL
415327Sbill write(fdesc, buf, count)
41610022Ssam 	int fdesc, count;
41710022Ssam 	char *buf;
418327Sbill {
419327Sbill 	register i;
420327Sbill 	register struct iob *file;
421327Sbill 
42210022Ssam 	errno = 0;
423327Sbill 	if (fdesc >= 0 && fdesc <= 2) {
424327Sbill 		i = count;
425327Sbill 		while (i--)
426327Sbill 			putchar(*buf++);
42710022Ssam 		return (count);
428327Sbill 	}
429327Sbill 	fdesc -= 3;
4306068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
43110022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
43210022Ssam 		errno = EBADF;
43310022Ssam 		return (-1);
43410022Ssam 	}
43510022Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
43610022Ssam 		errno = EBADF;
43710022Ssam 		return (-1);
43810022Ssam 	}
439327Sbill 	file->i_cc = count;
440327Sbill 	file->i_ma = buf;
4417446Sroot 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
442327Sbill 	i = devwrite(file);
4437446Sroot 	file->i_offset += count;
44410022Ssam 	if (i < 0)
44510022Ssam 		errno = file->i_error;
44610022Ssam 	return (i);
447327Sbill }
44834463Sbostic #endif
449327Sbill 
4503349Swnj int	openfirst = 1;
45134463Sbostic u_int	opendev;		/* last device opened */
45234463Sbostic extern u_int bootdev;
4533349Swnj 
454327Sbill open(str, how)
4556068Smckusic 	char *str;
45610022Ssam 	int how;
457327Sbill {
45834463Sbostic 	register char *t;
45934463Sbostic 	register int cnt;
460327Sbill 	register struct iob *file;
46134463Sbostic 	int fdesc, args[8], *argp;
462327Sbill 
4633349Swnj 	if (openfirst) {
46434463Sbostic 		for (cnt = 0; cnt < NFILES; cnt++)
46534463Sbostic 			iob[cnt].i_flgs = 0;
4663349Swnj 		openfirst = 0;
467327Sbill 	}
468327Sbill 
46934463Sbostic 	for (fdesc = 0;; fdesc++) {
47034463Sbostic 		if (fdesc == NFILES)
47134463Sbostic 			_stop("No more file slots");
47234463Sbostic 		if (iob[fdesc].i_flgs == 0) {
47334463Sbostic 			file = &iob[fdesc];
47434463Sbostic 			file->i_flgs |= F_ALLOC;
47534463Sbostic 			file->i_adapt = file->i_ctlr = file->i_unit =
47634463Sbostic 			    file->i_part = 0;
47734463Sbostic 			break;
47834463Sbostic 		}
47934463Sbostic 	}
480327Sbill 
48134463Sbostic 	for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
48234463Sbostic #ifndef SMALL
48334463Sbostic 	for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
48434463Sbostic 		if (isupper(*t))
48534463Sbostic 			*t = tolower(*t);
48634463Sbostic 	switch(*t) {
48734463Sbostic 	case '(':	/* type(adapt, ctlr, drive, partition)file */
48840500Smckusick 		if ((file->i_dev = getdev(str, t - str)) == -1)
48930547Skarels 			goto bad;
49034463Sbostic 		for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
49134463Sbostic 			for (++t; isspace(*t); ++t);
49234463Sbostic 			if (*t == ')')
49334463Sbostic 				break;
49434463Sbostic 			if (!isdigit(*t))
49530547Skarels 				goto badspec;
49634463Sbostic 			*argp++ = atoi(t);
49734463Sbostic 			for (++t; isdigit(*t); ++t);
49834463Sbostic 			if (*t != ',' && *t != ')' || cnt == 4)
49934463Sbostic 				goto badspec;
50030547Skarels 		}
50134463Sbostic 		for (++t; isspace(*t); ++t);
50234463Sbostic 		argp -= 4;
50334463Sbostic 		file->i_adapt = *argp++;
50434463Sbostic 		file->i_ctlr = *argp++;
50534463Sbostic 		file->i_unit = *argp++;
50634463Sbostic 		file->i_part = *argp;
50734463Sbostic 		break;
50834463Sbostic 	case ':':	/* [A-Za-z]*[0-9]*[A-Za-z]:file */
50934463Sbostic 		for (t = str; *t != ':' && !isdigit(*t); ++t);
51040500Smckusick 		if ((file->i_dev = getdev(str, t - str)) == -1)
51130547Skarels 			goto bad;
51234463Sbostic 		if ((file->i_unit = getunit(t)) == -1)
51330547Skarels 			goto bad;
51434463Sbostic 		for (; isdigit(*t); ++t);
51534463Sbostic 		if (*t >= 'a' && *t <= 'h')
51634463Sbostic 			file->i_part = *t++ - 'a';
51734463Sbostic 		if (*t != ':') {
51825166Skarels 			errno = EOFFSET;
51930547Skarels 			goto badspec;
52025166Skarels 		}
52134463Sbostic 		for (++t; isspace(*t); ++t);
52234463Sbostic 		break;
52334463Sbostic 	case '/':
52434463Sbostic 	default:		/* default bootstrap unit and device */
52534463Sbostic #else
52634463Sbostic 	{
52734463Sbostic #endif /* SMALL */
52840500Smckusick 		file->i_dev = B_TYPE(bootdev);
52934463Sbostic 		file->i_adapt = B_ADAPTOR(bootdev);
53034463Sbostic 		file->i_ctlr = B_CONTROLLER(bootdev);
53134463Sbostic 		file->i_unit = B_UNIT(bootdev);
53234463Sbostic 		file->i_part = B_PARTITION(bootdev);
53334463Sbostic 		t = str;
53425166Skarels 	}
53534463Sbostic 
53640500Smckusick 	opendev = MAKEBOOTDEV(file->i_dev, file->i_adapt, file->i_ctlr,
53734463Sbostic 	    file->i_unit, file->i_part);
53834463Sbostic 
53930547Skarels 	if (errno = devopen(file))
54030547Skarels 		goto bad;
54134463Sbostic 
54234463Sbostic 	if (*t == '\0') {
54334463Sbostic 		file->i_flgs |= how + 1;
54425166Skarels 		file->i_cc = 0;
54525166Skarels 		file->i_offset = 0;
54625166Skarels 		return (fdesc+3);
54725166Skarels 	}
54834463Sbostic #ifndef SMALL
54934463Sbostic 	else if (how != 0) {
55034463Sbostic 		printf("Can't write files yet.. Sorry\n");
55134463Sbostic 		errno = EIO;
55234463Sbostic 		goto bad;
55334463Sbostic 	}
55433408Skarels #endif
5556068Smckusic 	file->i_ma = (char *)(&file->i_fs);
5566068Smckusic 	file->i_cc = SBSIZE;
55730768Skarels 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
5586068Smckusic 	file->i_offset = 0;
55911083Ssam 	if (devread(file) < 0) {
56011083Ssam 		errno = file->i_error;
56111083Ssam 		printf("super block read error\n");
56230547Skarels 		goto bad;
56311083Ssam 	}
56434463Sbostic 	if ((cnt = find(t, file)) == 0) {
56510022Ssam 		errno = ESRCH;
56630547Skarels 		goto bad;
567327Sbill 	}
56834463Sbostic 	if (openi(cnt, file) < 0) {
56911083Ssam 		errno = file->i_error;
57030547Skarels 		goto bad;
57111083Ssam 	}
572327Sbill 	file->i_offset = 0;
573327Sbill 	file->i_cc = 0;
574327Sbill 	file->i_flgs |= F_FILE | (how+1);
57510022Ssam 	return (fdesc+3);
57630547Skarels 
57733408Skarels #ifndef SMALL
57830547Skarels badspec:
579*48826Swilliam 	printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file -or- <device><unit><partitionletter>:<file>\n");
58033408Skarels #endif
58130547Skarels bad:
58230547Skarels 	file->i_flgs = 0;
58330547Skarels 	return (-1);
584327Sbill }
585327Sbill 
58630924Skarels #ifndef SMALL
58730547Skarels static
58830547Skarels getdev(str, len)
58933408Skarels 	register char *str;
59030547Skarels 	int len;
59130547Skarels {
59230547Skarels 	register struct devsw *dp;
59333408Skarels 	register int i;
59434463Sbostic 	char savedch = str[len];
59530547Skarels 
59634463Sbostic 	str[len] = '\0';
59733408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
59833408Skarels 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
59934463Sbostic 			str[len] = savedch;
60033408Skarels 			return (i);
60133408Skarels 		}
60233408Skarels 	printf("Unknown device\nKnown devices are:\n");
60333408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
60433408Skarels 		if (dp->dv_name)
60533408Skarels 			printf(" %s", dp->dv_name);
60634463Sbostic 	printf("\n");
60730547Skarels 	errno = ENXIO;
60830547Skarels 	return (-1);
60930547Skarels }
61030547Skarels 
61130547Skarels static
61230547Skarels getunit(cp)
61330547Skarels 	register char *cp;
61430547Skarels {
61534463Sbostic 	int unit;
61630547Skarels 
61734463Sbostic 	unit = atoi(cp);
61834463Sbostic 	if ((u_int)unit > 255) {
61930547Skarels 		printf("minor device number out of range (0-255)\n");
62030547Skarels 		errno = EUNIT;
62134463Sbostic 		return (-1);
62230547Skarels 	}
62334463Sbostic 	return (unit);
62430547Skarels }
62534463Sbostic #endif /* SMALL */
62630547Skarels 
627327Sbill close(fdesc)
62810022Ssam 	int fdesc;
629327Sbill {
630*48826Swilliam #ifndef SMALL
631327Sbill 	struct iob *file;
632327Sbill 
633327Sbill 	fdesc -= 3;
6346068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
63510022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
63610022Ssam 		errno = EBADF;
63710022Ssam 		return (-1);
63810022Ssam 	}
639327Sbill 	if ((file->i_flgs&F_FILE) == 0)
640327Sbill 		devclose(file);
641327Sbill 	file->i_flgs = 0;
642*48826Swilliam #endif
64310022Ssam 	return (0);
644327Sbill }
645327Sbill 
64634463Sbostic #ifndef SMALL
64710022Ssam ioctl(fdesc, cmd, arg)
64810022Ssam 	int fdesc, cmd;
64910022Ssam 	char *arg;
65010022Ssam {
65110022Ssam 	register struct iob *file;
65210022Ssam 	int error = 0;
65310022Ssam 
65410331Shelge 	fdesc -= 3;
65510022Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
65610022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
65710022Ssam 		errno = EBADF;
65810022Ssam 		return (-1);
65910022Ssam 	}
66010022Ssam 	switch (cmd) {
66110022Ssam 
66210022Ssam 	case SAIOHDR:
66310022Ssam 		file->i_flgs |= F_HDR;
66410022Ssam 		break;
66510022Ssam 
66610022Ssam 	case SAIOCHECK:
66710022Ssam 		file->i_flgs |= F_CHECK;
66810022Ssam 		break;
66910022Ssam 
67010022Ssam 	case SAIOHCHECK:
67110022Ssam 		file->i_flgs |= F_HCHECK;
67210022Ssam 		break;
67310022Ssam 
67410331Shelge 	case SAIONOBAD:
67510331Shelge 		file->i_flgs |= F_NBSF;
67610331Shelge 		break;
67710331Shelge 
67810331Shelge 	case SAIODOBAD:
67910331Shelge 		file->i_flgs &= ~F_NBSF;
68010331Shelge 		break;
68110331Shelge 
68210022Ssam 	default:
68310022Ssam 		error = devioctl(file, cmd, arg);
68410022Ssam 		break;
68510022Ssam 	}
68610022Ssam 	if (error < 0)
68710022Ssam 		errno = file->i_error;
68810022Ssam 	return (error);
68910022Ssam }
69034463Sbostic #endif /* SMALL */
69110022Ssam 
692*48826Swilliam #ifndef i386
693327Sbill exit()
694327Sbill {
695327Sbill 	_stop("Exit called");
696327Sbill }
697*48826Swilliam #endif
698327Sbill 
699327Sbill _stop(s)
70010022Ssam 	char *s;
701327Sbill {
7022391Stoy 	int i;
70341542Smckusick 	static int stopped = 0;
7042391Stoy 
70541542Smckusick 	if (!stopped) {
70641542Smckusick 		stopped++;
70741542Smckusick 		for (i = 0; i < NFILES; i++)
70841542Smckusick 			if (iob[i].i_flgs != 0)
70941542Smckusick 				close(i);
71041542Smckusick 	}
711327Sbill 	printf("%s\n", s);
712327Sbill 	_rtt();
713327Sbill }
714