xref: /csrg-svn/sys/stand.att/sys.c (revision 40498)
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*40498Sroot  *	@(#)sys.c	7.8 (Berkeley) 03/15/90
723243Smckusick  */
8327Sbill 
9*40498Sroot #include "sys/param.h"
10*40498Sroot #include "sys/time.h"
11*40498Sroot #include "sys/vnode.h"
12*40498Sroot #include "ufs/inode.h"
13*40498Sroot #include "ufs/fs.h"
14*40498Sroot #include "ufs/dir.h"
15*40498Sroot #include "sys/reboot.h"
16327Sbill #include "saio.h"
17327Sbill 
1834942Sbostic #define	isdigit(c)	((u_int)((c) - '0') <= 9)
1934463Sbostic #define	isspace(c)	((c) == ' ' || (c) == '\t')
2034942Sbostic #define	isupper(c)	((u_int)((c) - 'A') <= 'Z' - 'A')
2134463Sbostic #define	tolower(c)	((c) - 'A' + 'a')
2234463Sbostic 
23327Sbill ino_t	dlook();
24327Sbill 
256068Smckusic struct dirstuff {
266068Smckusic 	int loc;
276068Smckusic 	struct iob *io;
286068Smckusic };
296068Smckusic 
3034463Sbostic struct iob iob[NFILES];
3134463Sbostic 
32327Sbill static
3310022Ssam openi(n, io)
346068Smckusic 	register struct iob *io;
35327Sbill {
36327Sbill 	register struct dinode *dp;
3711083Ssam 	int cc;
38327Sbill 
39327Sbill 	io->i_offset = 0;
406068Smckusic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
416068Smckusic 	io->i_cc = io->i_fs.fs_bsize;
42327Sbill 	io->i_ma = io->i_buf;
4311083Ssam 	cc = devread(io);
44327Sbill 	dp = (struct dinode *)io->i_buf;
456068Smckusic 	io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
4611083Ssam 	return (cc);
47327Sbill }
48327Sbill 
49327Sbill static
50327Sbill find(path, file)
516068Smckusic 	register char *path;
526068Smckusic 	struct iob *file;
53327Sbill {
54327Sbill 	register char *q;
5534463Sbostic 	char *dir, c;
56327Sbill 	int n;
57327Sbill 
5834463Sbostic 	if (path == NULL || *path == '\0') {
59327Sbill 		printf("null path\n");
6010022Ssam 		return (0);
61327Sbill 	}
62327Sbill 
6311083Ssam 	if (openi((ino_t) ROOTINO, file) < 0) {
6411083Ssam 		printf("can't read root inode\n");
6511083Ssam 		return (0);
6611083Ssam 	}
6730768Skarels 	dir = path;
68327Sbill 	while (*path) {
69327Sbill 		while (*path == '/')
70327Sbill 			path++;
71327Sbill 		q = path;
72327Sbill 		while(*q != '/' && *q != '\0')
73327Sbill 			q++;
74327Sbill 		c = *q;
75327Sbill 		*q = '\0';
7625166Skarels 		if (q == path) path = "." ;	/* "/" means "/." */
77327Sbill 
7830768Skarels 		if ((n = dlook(path, file, dir)) != 0) {
7911083Ssam 			if (c == '\0')
80327Sbill 				break;
8111083Ssam 			if (openi(n, file) < 0)
8211083Ssam 				return (0);
83327Sbill 			*q = c;
84327Sbill 			path = q;
85327Sbill 			continue;
86327Sbill 		} else {
8725166Skarels 			printf("%s: not found\n", path);
8810022Ssam 			return (0);
89327Sbill 		}
90327Sbill 	}
9110022Ssam 	return (n);
92327Sbill }
93327Sbill 
9434463Sbostic #define	NBUFS	4
9534463Sbostic static char	b[NBUFS][MAXBSIZE];
9634463Sbostic static daddr_t	blknos[NBUFS];
9734463Sbostic 
98327Sbill static daddr_t
99327Sbill sbmap(io, bn)
1006068Smckusic 	register struct iob *io;
1016068Smckusic 	daddr_t bn;
102327Sbill {
103327Sbill 	register struct inode *ip;
1046068Smckusic 	int i, j, sh;
105327Sbill 	daddr_t nb, *bap;
106327Sbill 
107327Sbill 	ip = &io->i_ino;
1086068Smckusic 	if (bn < 0) {
109327Sbill 		printf("bn negative\n");
11010022Ssam 		return ((daddr_t)0);
111327Sbill 	}
112327Sbill 
113327Sbill 	/*
1146068Smckusic 	 * blocks 0..NDADDR are direct blocks
115327Sbill 	 */
1166068Smckusic 	if(bn < NDADDR) {
1176068Smckusic 		nb = ip->i_db[bn];
11810022Ssam 		return (nb);
119327Sbill 	}
120327Sbill 
121327Sbill 	/*
1226068Smckusic 	 * addresses NIADDR have single and double indirect blocks.
1236068Smckusic 	 * the first step is to determine how many levels of indirection.
124327Sbill 	 */
1256068Smckusic 	sh = 1;
1266068Smckusic 	bn -= NDADDR;
1276068Smckusic 	for (j = NIADDR; j > 0; j--) {
1286068Smckusic 		sh *= NINDIR(&io->i_fs);
1296068Smckusic 		if (bn < sh)
130327Sbill 			break;
1316068Smckusic 		bn -= sh;
132327Sbill 	}
1336068Smckusic 	if (j == 0) {
1346068Smckusic 		printf("bn ovf %D\n", bn);
1356068Smckusic 		return ((daddr_t)0);
136327Sbill 	}
137327Sbill 
138327Sbill 	/*
1396068Smckusic 	 * fetch the first indirect block address from the inode
140327Sbill 	 */
1416068Smckusic 	nb = ip->i_ib[NIADDR - j];
1426068Smckusic 	if (nb == 0) {
143327Sbill 		printf("bn void %D\n",bn);
14410022Ssam 		return ((daddr_t)0);
145327Sbill 	}
146327Sbill 
147327Sbill 	/*
148327Sbill 	 * fetch through the indirect blocks
149327Sbill 	 */
1506068Smckusic 	for (; j <= NIADDR; j++) {
151327Sbill 		if (blknos[j] != nb) {
1526068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
153327Sbill 			io->i_ma = b[j];
1546068Smckusic 			io->i_cc = io->i_fs.fs_bsize;
15511083Ssam 			if (devread(io) != io->i_fs.fs_bsize) {
15611083Ssam 				if (io->i_error)
15711083Ssam 					errno = io->i_error;
15811083Ssam 				printf("bn %D: read error\n", io->i_bn);
15911083Ssam 				return ((daddr_t)0);
16011083Ssam 			}
161327Sbill 			blknos[j] = nb;
162327Sbill 		}
163327Sbill 		bap = (daddr_t *)b[j];
1646068Smckusic 		sh /= NINDIR(&io->i_fs);
1656068Smckusic 		i = (bn / sh) % NINDIR(&io->i_fs);
166327Sbill 		nb = bap[i];
167327Sbill 		if(nb == 0) {
168327Sbill 			printf("bn void %D\n",bn);
16910022Ssam 			return ((daddr_t)0);
170327Sbill 		}
171327Sbill 	}
17210022Ssam 	return (nb);
173327Sbill }
174327Sbill 
175327Sbill static ino_t
17630768Skarels dlook(s, io, dir)
1776068Smckusic 	char *s;
1786068Smckusic 	register struct iob *io;
17930768Skarels 	char *dir;
180327Sbill {
181327Sbill 	register struct direct *dp;
182327Sbill 	register struct inode *ip;
1836068Smckusic 	struct dirstuff dirp;
1846068Smckusic 	int len;
185327Sbill 
1866068Smckusic 	if (s == NULL || *s == '\0')
18710022Ssam 		return (0);
188327Sbill 	ip = &io->i_ino;
1896068Smckusic 	if ((ip->i_mode&IFMT) != IFDIR) {
19030768Skarels 		printf("%s: not a directory\n", dir);
19110022Ssam 		return (0);
192327Sbill 	}
1936068Smckusic 	if (ip->i_size == 0) {
19430768Skarels 		printf("%s: zero length directory\n", dir);
19510022Ssam 		return (0);
196327Sbill 	}
1976068Smckusic 	len = strlen(s);
1986068Smckusic 	dirp.loc = 0;
1996068Smckusic 	dirp.io = io;
2006068Smckusic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
2016068Smckusic 		if(dp->d_ino == 0)
2026068Smckusic 			continue;
2036068Smckusic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
20410022Ssam 			return (dp->d_ino);
205327Sbill 	}
20610022Ssam 	return (0);
207327Sbill }
208327Sbill 
2096068Smckusic /*
2106068Smckusic  * get next entry in a directory.
2116068Smckusic  */
2126068Smckusic struct direct *
2136068Smckusic readdir(dirp)
2146068Smckusic 	register struct dirstuff *dirp;
215327Sbill {
2166068Smckusic 	register struct direct *dp;
2176068Smckusic 	register struct iob *io;
2186068Smckusic 	daddr_t lbn, d;
2196068Smckusic 	int off;
220327Sbill 
2216068Smckusic 	io = dirp->io;
2226068Smckusic 	for(;;) {
2236068Smckusic 		if (dirp->loc >= io->i_ino.i_size)
22411083Ssam 			return (NULL);
2256068Smckusic 		off = blkoff(&io->i_fs, dirp->loc);
2266068Smckusic 		if (off == 0) {
2276068Smckusic 			lbn = lblkno(&io->i_fs, dirp->loc);
2286068Smckusic 			d = sbmap(io, lbn);
2296068Smckusic 			if(d == 0)
23034463Sbostic 				return (NULL);
2316068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
2326068Smckusic 			io->i_ma = io->i_buf;
2336068Smckusic 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
23411083Ssam 			if (devread(io) < 0) {
23511083Ssam 				errno = io->i_error;
23625166Skarels 				printf("bn %D: directory read error\n",
23725166Skarels 					io->i_bn);
23811083Ssam 				return (NULL);
23911083Ssam 			}
2406068Smckusic 		}
2416068Smckusic 		dp = (struct direct *)(io->i_buf + off);
2426068Smckusic 		dirp->loc += dp->d_reclen;
2436068Smckusic 		if (dp->d_ino == 0)
2446068Smckusic 			continue;
2456068Smckusic 		return (dp);
246327Sbill 	}
247327Sbill }
248327Sbill 
249327Sbill lseek(fdesc, addr, ptr)
25010022Ssam 	int fdesc, ptr;
25110022Ssam 	off_t addr;
252327Sbill {
253327Sbill 	register struct iob *io;
254327Sbill 
25534463Sbostic #ifndef SMALL
25634463Sbostic 	if (ptr != L_SET) {
257327Sbill 		printf("Seek not from beginning of file\n");
25810022Ssam 		errno = EOFFSET;
25910022Ssam 		return (-1);
260327Sbill 	}
26134463Sbostic #endif
262327Sbill 	fdesc -= 3;
2636068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
26410022Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
26510022Ssam 		errno = EBADF;
26610022Ssam 		return (-1);
26710022Ssam 	}
268327Sbill 	io->i_offset = addr;
2696068Smckusic 	io->i_bn = addr / DEV_BSIZE;
270327Sbill 	io->i_cc = 0;
27110022Ssam 	return (0);
272327Sbill }
273327Sbill 
274327Sbill getc(fdesc)
27510022Ssam 	int fdesc;
276327Sbill {
277327Sbill 	register struct iob *io;
2786068Smckusic 	register struct fs *fs;
279327Sbill 	register char *p;
2806068Smckusic 	int c, lbn, off, size, diff;
281327Sbill 
282327Sbill 
283327Sbill 	if (fdesc >= 0 && fdesc <= 2)
28410022Ssam 		return (getchar());
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) {
2946068Smckusic 			diff = io->i_ino.i_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);
3016068Smckusic 			size = blksize(fs, &io->i_ino, lbn);
3026068Smckusic 		} else {
3036068Smckusic 			io->i_bn = io->i_offset / DEV_BSIZE;
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) {
3146068Smckusic 			if (io->i_offset - off + size >= io->i_ino.i_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;
339327Sbill 	if (fdesc >= 0 & fdesc <= 2) {
340327Sbill 		i = count;
341327Sbill 		do {
342327Sbill 			*buf = getchar();
343327Sbill 		} while (--i && *buf++ != '\n');
34410022Ssam 		return (count - i);
345327Sbill 	}
346327Sbill 	fdesc -= 3;
3476068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
34810022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
34910022Ssam 		errno = EBADF;
35010022Ssam 		return (-1);
35110022Ssam 	}
35210022Ssam 	if ((file->i_flgs&F_READ) == 0) {
35310022Ssam 		errno = EBADF;
35410022Ssam 		return (-1);
35510022Ssam 	}
35634463Sbostic #ifndef SMALL
3576068Smckusic 	if ((file->i_flgs & F_FILE) == 0) {
358327Sbill 		file->i_cc = count;
359327Sbill 		file->i_ma = buf;
3607446Sroot 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
361327Sbill 		i = devread(file);
36210022Ssam 		if (i < 0)
36310022Ssam 			errno = file->i_error;
36430547Skarels 		else
36530547Skarels 			file->i_offset += i;
36610022Ssam 		return (i);
367327Sbill 	}
36834463Sbostic #endif
36925166Skarels 	if (file->i_offset+count > file->i_ino.i_size)
37025166Skarels 		count = file->i_ino.i_size - file->i_offset;
37125166Skarels 	if ((i = count) <= 0)
37225166Skarels 		return (0);
37325166Skarels 	/*
37425166Skarels 	 * While reading full blocks, do I/O into user buffer.
37525166Skarels 	 * Anything else uses getc().
37625166Skarels 	 */
37725166Skarels 	fs = &file->i_fs;
37825166Skarels 	while (i) {
37925166Skarels 		off = blkoff(fs, file->i_offset);
38025166Skarels 		lbn = lblkno(fs, file->i_offset);
38125166Skarels 		size = blksize(fs, &file->i_ino, lbn);
38225166Skarels 		if (off == 0 && size <= i) {
38325166Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
38425166Skarels 			    file->i_boff;
38525166Skarels 			file->i_cc = size;
38625166Skarels 			file->i_ma = buf;
38725166Skarels 			if (devread(file) < 0) {
38825166Skarels 				errno = file->i_error;
38925166Skarels 				return (-1);
39025166Skarels 			}
39125166Skarels 			file->i_offset += size;
39225166Skarels 			file->i_cc = 0;
39325166Skarels 			buf += size;
39425166Skarels 			i -= size;
39525166Skarels 		} else {
39625166Skarels 			size -= off;
39725166Skarels 			if (size > i)
39825166Skarels 				size = i;
39925166Skarels 			i -= size;
40025166Skarels 			do {
40125166Skarels 				*buf++ = getc(fdesc+3);
40225166Skarels 			} while (--size);
40325166Skarels 		}
40425166Skarels 	}
40525166Skarels 	return (count);
406327Sbill }
407327Sbill 
40834463Sbostic #ifndef SMALL
409327Sbill write(fdesc, buf, count)
41010022Ssam 	int fdesc, count;
41110022Ssam 	char *buf;
412327Sbill {
413327Sbill 	register i;
414327Sbill 	register struct iob *file;
415327Sbill 
41610022Ssam 	errno = 0;
417327Sbill 	if (fdesc >= 0 && fdesc <= 2) {
418327Sbill 		i = count;
419327Sbill 		while (i--)
420327Sbill 			putchar(*buf++);
42110022Ssam 		return (count);
422327Sbill 	}
423327Sbill 	fdesc -= 3;
4246068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
42510022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
42610022Ssam 		errno = EBADF;
42710022Ssam 		return (-1);
42810022Ssam 	}
42910022Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
43010022Ssam 		errno = EBADF;
43110022Ssam 		return (-1);
43210022Ssam 	}
433327Sbill 	file->i_cc = count;
434327Sbill 	file->i_ma = buf;
4357446Sroot 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
436327Sbill 	i = devwrite(file);
4377446Sroot 	file->i_offset += count;
43810022Ssam 	if (i < 0)
43910022Ssam 		errno = file->i_error;
44010022Ssam 	return (i);
441327Sbill }
44234463Sbostic #endif
443327Sbill 
4443349Swnj int	openfirst = 1;
44534463Sbostic u_int	opendev;		/* last device opened */
44634463Sbostic extern u_int bootdev;
4473349Swnj 
448327Sbill open(str, how)
4496068Smckusic 	char *str;
45010022Ssam 	int how;
451327Sbill {
45234463Sbostic 	register char *t;
45334463Sbostic 	register int cnt;
454327Sbill 	register struct iob *file;
45534463Sbostic 	int fdesc, args[8], *argp;
456327Sbill 
4573349Swnj 	if (openfirst) {
45834463Sbostic 		for (cnt = 0; cnt < NFILES; cnt++)
45934463Sbostic 			iob[cnt].i_flgs = 0;
4603349Swnj 		openfirst = 0;
461327Sbill 	}
462327Sbill 
46334463Sbostic 	for (fdesc = 0;; fdesc++) {
46434463Sbostic 		if (fdesc == NFILES)
46534463Sbostic 			_stop("No more file slots");
46634463Sbostic 		if (iob[fdesc].i_flgs == 0) {
46734463Sbostic 			file = &iob[fdesc];
46834463Sbostic 			file->i_flgs |= F_ALLOC;
46934463Sbostic 			file->i_adapt = file->i_ctlr = file->i_unit =
47034463Sbostic 			    file->i_part = 0;
47134463Sbostic 			break;
47234463Sbostic 		}
47334463Sbostic 	}
474327Sbill 
47534463Sbostic 	for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
47634463Sbostic #ifndef SMALL
47734463Sbostic 	for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
47834463Sbostic 		if (isupper(*t))
47934463Sbostic 			*t = tolower(*t);
48034463Sbostic 	switch(*t) {
48134463Sbostic 	case '(':	/* type(adapt, ctlr, drive, partition)file */
48234463Sbostic 		if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
48330547Skarels 			goto bad;
48434463Sbostic 		for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
48534463Sbostic 			for (++t; isspace(*t); ++t);
48634463Sbostic 			if (*t == ')')
48734463Sbostic 				break;
48834463Sbostic 			if (!isdigit(*t))
48930547Skarels 				goto badspec;
49034463Sbostic 			*argp++ = atoi(t);
49134463Sbostic 			for (++t; isdigit(*t); ++t);
49234463Sbostic 			if (*t != ',' && *t != ')' || cnt == 4)
49334463Sbostic 				goto badspec;
49430547Skarels 		}
49534463Sbostic 		for (++t; isspace(*t); ++t);
49634463Sbostic 		argp -= 4;
49734463Sbostic 		file->i_adapt = *argp++;
49834463Sbostic 		file->i_ctlr = *argp++;
49934463Sbostic 		file->i_unit = *argp++;
50034463Sbostic 		file->i_part = *argp;
50134463Sbostic 		break;
50234463Sbostic 	case ':':	/* [A-Za-z]*[0-9]*[A-Za-z]:file */
50334463Sbostic 		for (t = str; *t != ':' && !isdigit(*t); ++t);
50434463Sbostic 		if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
50530547Skarels 			goto bad;
50634463Sbostic 		if ((file->i_unit = getunit(t)) == -1)
50730547Skarels 			goto bad;
50834463Sbostic 		for (; isdigit(*t); ++t);
50934463Sbostic 		if (*t >= 'a' && *t <= 'h')
51034463Sbostic 			file->i_part = *t++ - 'a';
51134463Sbostic 		if (*t != ':') {
51225166Skarels 			errno = EOFFSET;
51330547Skarels 			goto badspec;
51425166Skarels 		}
51534463Sbostic 		for (++t; isspace(*t); ++t);
51634463Sbostic 		break;
51734463Sbostic 	case '/':
51834463Sbostic 	default:		/* default bootstrap unit and device */
51934463Sbostic #else
52034463Sbostic 	{
52134463Sbostic #endif /* SMALL */
52234463Sbostic 		file->i_ino.i_dev = B_TYPE(bootdev);
52334463Sbostic 		file->i_adapt = B_ADAPTOR(bootdev);
52434463Sbostic 		file->i_ctlr = B_CONTROLLER(bootdev);
52534463Sbostic 		file->i_unit = B_UNIT(bootdev);
52634463Sbostic 		file->i_part = B_PARTITION(bootdev);
52734463Sbostic 		t = str;
52825166Skarels 	}
52934463Sbostic 
53034463Sbostic 	opendev = MAKEBOOTDEV(file->i_ino.i_dev, file->i_adapt, file->i_ctlr,
53134463Sbostic 	    file->i_unit, file->i_part);
53234463Sbostic 
53330547Skarels 	if (errno = devopen(file))
53430547Skarels 		goto bad;
53534463Sbostic 
53634463Sbostic 	if (*t == '\0') {
53734463Sbostic 		file->i_flgs |= how + 1;
53825166Skarels 		file->i_cc = 0;
53925166Skarels 		file->i_offset = 0;
54025166Skarels 		return (fdesc+3);
54125166Skarels 	}
54234463Sbostic #ifndef SMALL
54334463Sbostic 	else if (how != 0) {
54434463Sbostic 		printf("Can't write files yet.. Sorry\n");
54534463Sbostic 		errno = EIO;
54634463Sbostic 		goto bad;
54734463Sbostic 	}
54833408Skarels #endif
5496068Smckusic 	file->i_ma = (char *)(&file->i_fs);
5506068Smckusic 	file->i_cc = SBSIZE;
55130768Skarels 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
5526068Smckusic 	file->i_offset = 0;
55311083Ssam 	if (devread(file) < 0) {
55411083Ssam 		errno = file->i_error;
55511083Ssam 		printf("super block read error\n");
55630547Skarels 		goto bad;
55711083Ssam 	}
55834463Sbostic 	if ((cnt = find(t, file)) == 0) {
55910022Ssam 		errno = ESRCH;
56030547Skarels 		goto bad;
561327Sbill 	}
56234463Sbostic 	if (openi(cnt, file) < 0) {
56311083Ssam 		errno = file->i_error;
56430547Skarels 		goto bad;
56511083Ssam 	}
566327Sbill 	file->i_offset = 0;
567327Sbill 	file->i_cc = 0;
568327Sbill 	file->i_flgs |= F_FILE | (how+1);
56910022Ssam 	return (fdesc+3);
57030547Skarels 
57133408Skarels #ifndef SMALL
57230547Skarels badspec:
57334463Sbostic 	printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file\n");
57433408Skarels #endif
57530547Skarels bad:
57630547Skarels 	file->i_flgs = 0;
57730547Skarels 	return (-1);
578327Sbill }
579327Sbill 
58030924Skarels #ifndef SMALL
58130547Skarels static
58230547Skarels getdev(str, len)
58333408Skarels 	register char *str;
58430547Skarels 	int len;
58530547Skarels {
58630547Skarels 	register struct devsw *dp;
58733408Skarels 	register int i;
58834463Sbostic 	char savedch = str[len];
58930547Skarels 
59034463Sbostic 	str[len] = '\0';
59133408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
59233408Skarels 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
59334463Sbostic 			str[len] = savedch;
59433408Skarels 			return (i);
59533408Skarels 		}
59633408Skarels 	printf("Unknown device\nKnown devices are:\n");
59733408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
59833408Skarels 		if (dp->dv_name)
59933408Skarels 			printf(" %s", dp->dv_name);
60034463Sbostic 	printf("\n");
60130547Skarels 	errno = ENXIO;
60230547Skarels 	return (-1);
60330547Skarels }
60430547Skarels 
60530547Skarels static
60630547Skarels getunit(cp)
60730547Skarels 	register char *cp;
60830547Skarels {
60934463Sbostic 	int unit;
61030547Skarels 
61134463Sbostic 	unit = atoi(cp);
61234463Sbostic 	if ((u_int)unit > 255) {
61330547Skarels 		printf("minor device number out of range (0-255)\n");
61430547Skarels 		errno = EUNIT;
61534463Sbostic 		return (-1);
61630547Skarels 	}
61734463Sbostic 	return (unit);
61830547Skarels }
61934463Sbostic #endif /* SMALL */
62030547Skarels 
621327Sbill close(fdesc)
62210022Ssam 	int fdesc;
623327Sbill {
624327Sbill 	struct iob *file;
625327Sbill 
626327Sbill 	fdesc -= 3;
6276068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
62810022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
62910022Ssam 		errno = EBADF;
63010022Ssam 		return (-1);
63110022Ssam 	}
632327Sbill 	if ((file->i_flgs&F_FILE) == 0)
633327Sbill 		devclose(file);
634327Sbill 	file->i_flgs = 0;
63510022Ssam 	return (0);
636327Sbill }
637327Sbill 
63834463Sbostic #ifndef SMALL
63910022Ssam ioctl(fdesc, cmd, arg)
64010022Ssam 	int fdesc, cmd;
64110022Ssam 	char *arg;
64210022Ssam {
64310022Ssam 	register struct iob *file;
64410022Ssam 	int error = 0;
64510022Ssam 
64610331Shelge 	fdesc -= 3;
64710022Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
64810022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
64910022Ssam 		errno = EBADF;
65010022Ssam 		return (-1);
65110022Ssam 	}
65210022Ssam 	switch (cmd) {
65310022Ssam 
65410022Ssam 	case SAIOHDR:
65510022Ssam 		file->i_flgs |= F_HDR;
65610022Ssam 		break;
65710022Ssam 
65810022Ssam 	case SAIOCHECK:
65910022Ssam 		file->i_flgs |= F_CHECK;
66010022Ssam 		break;
66110022Ssam 
66210022Ssam 	case SAIOHCHECK:
66310022Ssam 		file->i_flgs |= F_HCHECK;
66410022Ssam 		break;
66510022Ssam 
66610331Shelge 	case SAIONOBAD:
66710331Shelge 		file->i_flgs |= F_NBSF;
66810331Shelge 		break;
66910331Shelge 
67010331Shelge 	case SAIODOBAD:
67110331Shelge 		file->i_flgs &= ~F_NBSF;
67210331Shelge 		break;
67310331Shelge 
67410022Ssam 	default:
67510022Ssam 		error = devioctl(file, cmd, arg);
67610022Ssam 		break;
67710022Ssam 	}
67810022Ssam 	if (error < 0)
67910022Ssam 		errno = file->i_error;
68010022Ssam 	return (error);
68110022Ssam }
68234463Sbostic #endif /* SMALL */
68310022Ssam 
684327Sbill exit()
685327Sbill {
686327Sbill 	_stop("Exit called");
687327Sbill }
688327Sbill 
689327Sbill _stop(s)
69010022Ssam 	char *s;
691327Sbill {
6922391Stoy 	int i;
6932391Stoy 
6942391Stoy 	for (i = 0; i < NFILES; i++)
6952391Stoy 		if (iob[i].i_flgs != 0)
6962391Stoy 			close(i);
697327Sbill 	printf("%s\n", s);
698327Sbill 	_rtt();
699327Sbill }
700