xref: /csrg-svn/sys/tahoe/stand/sys.c (revision 33639)
130308Skarels /*
230308Skarels  * Copyright (c) 1982, 1986 Regents of the University of California.
330308Skarels  * All rights reserved.  The Berkeley software License Agreement
430308Skarels  * specifies the terms and conditions for redistribution.
530308Skarels  *
6*33639Sbostic  *	sys.c	1.4	88/03/03
730308Skarels  *
830757Skarels  * from vax	@(#)sys.c	7.1 (Berkeley) 6/5/86
930308Skarels  */
1025871Ssam 
1125871Ssam #include "param.h"
1225871Ssam #include "inode.h"
1325871Ssam #include "fs.h"
1425871Ssam #include "dir.h"
1530757Skarels #include "reboot.h"
1625871Ssam #include "saio.h"
1730757Skarels #include "../machine/mtpr.h"
1825871Ssam 
1925871Ssam ino_t	dlook();
2025871Ssam 
2125871Ssam struct dirstuff {
2225871Ssam 	int loc;
2325871Ssam 	struct iob *io;
2425871Ssam };
2525871Ssam 
2625871Ssam static
openi(n,io)2725871Ssam openi(n, io)
2825871Ssam 	register struct iob *io;
2925871Ssam {
3025871Ssam 	register struct dinode *dp;
3125871Ssam 	int cc;
3225871Ssam 
3325871Ssam 	io->i_offset = 0;
3425871Ssam 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
3525871Ssam 	io->i_cc = io->i_fs.fs_bsize;
3625871Ssam 	io->i_ma = io->i_buf;
3725871Ssam 	cc = devread(io);
3825871Ssam 	dp = (struct dinode *)io->i_buf;
3925871Ssam 	io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
4025871Ssam 	return (cc);
4125871Ssam }
4225871Ssam 
4325871Ssam static
find(path,file)4425871Ssam find(path, file)
4525871Ssam 	register char *path;
4625871Ssam 	struct iob *file;
4725871Ssam {
4825871Ssam 	register char *q;
4930757Skarels 	char *dir;
5025871Ssam 	char c;
5125871Ssam 	int n;
5225871Ssam 
5325871Ssam 	if (path==NULL || *path=='\0') {
5425871Ssam 		printf("null path\n");
5525871Ssam 		return (0);
5625871Ssam 	}
5725871Ssam 
5825871Ssam 	if (openi((ino_t) ROOTINO, file) < 0) {
5925871Ssam 		printf("can't read root inode\n");
6025871Ssam 		return (0);
6125871Ssam 	}
6230757Skarels 	dir = path;
6325871Ssam 	while (*path) {
6425871Ssam 		while (*path == '/')
6525871Ssam 			path++;
6625871Ssam 		q = path;
6725871Ssam 		while(*q != '/' && *q != '\0')
6825871Ssam 			q++;
6925871Ssam 		c = *q;
7025871Ssam 		*q = '\0';
7130308Skarels 		if (q == path) path = "." ;	/* "/" means "/." */
7225871Ssam 
7330757Skarels 		if ((n = dlook(path, file, dir)) != 0) {
7425871Ssam 			if (c == '\0')
7525871Ssam 				break;
7625871Ssam 			if (openi(n, file) < 0)
7725871Ssam 				return (0);
7825871Ssam 			*q = c;
7925871Ssam 			path = q;
8025871Ssam 			continue;
8125871Ssam 		} else {
8230308Skarels 			printf("%s: not found\n", path);
8325871Ssam 			return (0);
8425871Ssam 		}
8525871Ssam 	}
8625871Ssam 	return (n);
8725871Ssam }
8825871Ssam 
8925871Ssam static daddr_t
sbmap(io,bn)9025871Ssam sbmap(io, bn)
9125871Ssam 	register struct iob *io;
9225871Ssam 	daddr_t bn;
9325871Ssam {
9425871Ssam 	register struct inode *ip;
9525871Ssam 	int i, j, sh;
9625871Ssam 	daddr_t nb, *bap;
9725871Ssam 
9825871Ssam 	ip = &io->i_ino;
9925871Ssam 	if (bn < 0) {
10025871Ssam 		printf("bn negative\n");
10125871Ssam 		return ((daddr_t)0);
10225871Ssam 	}
10325871Ssam 
10425871Ssam 	/*
10525871Ssam 	 * blocks 0..NDADDR are direct blocks
10625871Ssam 	 */
10725871Ssam 	if(bn < NDADDR) {
10825871Ssam 		nb = ip->i_db[bn];
10925871Ssam 		return (nb);
11025871Ssam 	}
11125871Ssam 
11225871Ssam 	/*
11325871Ssam 	 * addresses NIADDR have single and double indirect blocks.
11425871Ssam 	 * the first step is to determine how many levels of indirection.
11525871Ssam 	 */
11625871Ssam 	sh = 1;
11725871Ssam 	bn -= NDADDR;
11825871Ssam 	for (j = NIADDR; j > 0; j--) {
11925871Ssam 		sh *= NINDIR(&io->i_fs);
12025871Ssam 		if (bn < sh)
12125871Ssam 			break;
12225871Ssam 		bn -= sh;
12325871Ssam 	}
12425871Ssam 	if (j == 0) {
12525871Ssam 		printf("bn ovf %D\n", bn);
12625871Ssam 		return ((daddr_t)0);
12725871Ssam 	}
12825871Ssam 
12925871Ssam 	/*
13025871Ssam 	 * fetch the first indirect block address from the inode
13125871Ssam 	 */
13225871Ssam 	nb = ip->i_ib[NIADDR - j];
13325871Ssam 	if (nb == 0) {
13425871Ssam 		printf("bn void %D\n",bn);
13525871Ssam 		return ((daddr_t)0);
13625871Ssam 	}
13725871Ssam 
13825871Ssam 	/*
13925871Ssam 	 * fetch through the indirect blocks
14025871Ssam 	 */
14125871Ssam 	for (; j <= NIADDR; j++) {
14225871Ssam 		if (blknos[j] != nb) {
14325871Ssam 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
14425871Ssam 			io->i_ma = b[j];
14525871Ssam 			io->i_cc = io->i_fs.fs_bsize;
14625871Ssam 			if (devread(io) != io->i_fs.fs_bsize) {
14725871Ssam 				if (io->i_error)
14825871Ssam 					errno = io->i_error;
14925871Ssam 				printf("bn %D: read error\n", io->i_bn);
15025871Ssam 				return ((daddr_t)0);
15125871Ssam 			}
15225871Ssam 			blknos[j] = nb;
15325871Ssam 		}
15425871Ssam 		bap = (daddr_t *)b[j];
15525871Ssam 		sh /= NINDIR(&io->i_fs);
15625871Ssam 		i = (bn / sh) % NINDIR(&io->i_fs);
15725871Ssam 		nb = bap[i];
15825871Ssam 		if(nb == 0) {
15925871Ssam 			printf("bn void %D\n",bn);
16025871Ssam 			return ((daddr_t)0);
16125871Ssam 		}
16225871Ssam 	}
16325871Ssam 	return (nb);
16425871Ssam }
16525871Ssam 
16625871Ssam static ino_t
dlook(s,io,dir)16730757Skarels dlook(s, io, dir)
16825871Ssam 	char *s;
16925871Ssam 	register struct iob *io;
17030757Skarels 	char *dir;
17125871Ssam {
17225871Ssam 	register struct direct *dp;
17325871Ssam 	register struct inode *ip;
17425871Ssam 	struct dirstuff dirp;
17525871Ssam 	int len;
17625871Ssam 
17725871Ssam 	if (s == NULL || *s == '\0')
17825871Ssam 		return (0);
17925871Ssam 	ip = &io->i_ino;
18025871Ssam 	if ((ip->i_mode&IFMT) != IFDIR) {
18130757Skarels 		printf("%s: not a directory\n", dir);
18225871Ssam 		return (0);
18325871Ssam 	}
18425871Ssam 	if (ip->i_size == 0) {
18530757Skarels 		printf("%s: zero length directory\n", dir);
18625871Ssam 		return (0);
18725871Ssam 	}
18825871Ssam 	len = strlen(s);
18925871Ssam 	dirp.loc = 0;
19025871Ssam 	dirp.io = io;
19125871Ssam 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
19225871Ssam 		if(dp->d_ino == 0)
19325871Ssam 			continue;
19425871Ssam 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
19525871Ssam 			return (dp->d_ino);
19625871Ssam 	}
19725871Ssam 	return (0);
19825871Ssam }
19925871Ssam 
20025871Ssam /*
20125871Ssam  * get next entry in a directory.
20225871Ssam  */
20325871Ssam struct direct *
readdir(dirp)20425871Ssam readdir(dirp)
20525871Ssam 	register struct dirstuff *dirp;
20625871Ssam {
20725871Ssam 	register struct direct *dp;
20825871Ssam 	register struct iob *io;
20925871Ssam 	daddr_t lbn, d;
21025871Ssam 	int off;
21125871Ssam 
21225871Ssam 	io = dirp->io;
21325871Ssam 	for(;;) {
21425871Ssam 		if (dirp->loc >= io->i_ino.i_size)
21525871Ssam 			return (NULL);
21625871Ssam 		off = blkoff(&io->i_fs, dirp->loc);
21725871Ssam 		if (off == 0) {
21825871Ssam 			lbn = lblkno(&io->i_fs, dirp->loc);
21925871Ssam 			d = sbmap(io, lbn);
22025871Ssam 			if(d == 0)
22125871Ssam 				return NULL;
22225871Ssam 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
22325871Ssam 			io->i_ma = io->i_buf;
22425871Ssam 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
22525871Ssam 			if (devread(io) < 0) {
22625871Ssam 				errno = io->i_error;
22730308Skarels 				printf("bn %D: directory read error\n",
22830308Skarels 					io->i_bn);
22925871Ssam 				return (NULL);
23025871Ssam 			}
23125871Ssam 		}
23225871Ssam 		dp = (struct direct *)(io->i_buf + off);
23325871Ssam 		dirp->loc += dp->d_reclen;
23425871Ssam 		if (dp->d_ino == 0)
23525871Ssam 			continue;
23625871Ssam 		return (dp);
23725871Ssam 	}
23825871Ssam }
23925871Ssam 
lseek(fdesc,addr,ptr)24025871Ssam lseek(fdesc, addr, ptr)
24125871Ssam 	int fdesc, ptr;
24225871Ssam 	off_t addr;
24325871Ssam {
24425871Ssam 	register struct iob *io;
24525871Ssam 
24630308Skarels #ifndef	SMALL
24725871Ssam 	if (ptr != 0) {
24825871Ssam 		printf("Seek not from beginning of file\n");
24925871Ssam 		errno = EOFFSET;
25025871Ssam 		return (-1);
25125871Ssam 	}
25230308Skarels #endif SMALL
25325871Ssam 	fdesc -= 3;
25425871Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
25525871Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
25625871Ssam 		errno = EBADF;
25725871Ssam 		return (-1);
25825871Ssam 	}
25925871Ssam 	io->i_offset = addr;
26025871Ssam 	io->i_bn = addr / DEV_BSIZE;
26125871Ssam 	io->i_cc = 0;
26225871Ssam 	return (0);
26325871Ssam }
26425871Ssam 
getc(fdesc)26525871Ssam getc(fdesc)
26625871Ssam 	int fdesc;
26725871Ssam {
26825871Ssam 	register struct iob *io;
26925871Ssam 	register struct fs *fs;
27025871Ssam 	register char *p;
27125871Ssam 	int c, lbn, off, size, diff;
27225871Ssam 
27325871Ssam 
27425871Ssam 	if (fdesc >= 0 && fdesc <= 2)
27525871Ssam 		return (getchar());
27625871Ssam 	fdesc -= 3;
27725871Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
27825871Ssam 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
27925871Ssam 		errno = EBADF;
28025871Ssam 		return (-1);
28125871Ssam 	}
28225871Ssam 	p = io->i_ma;
28325871Ssam 	if (io->i_cc <= 0) {
28425871Ssam 		if ((io->i_flgs & F_FILE) != 0) {
28525871Ssam 			diff = io->i_ino.i_size - io->i_offset;
28625871Ssam 			if (diff <= 0)
28725871Ssam 				return (-1);
28825871Ssam 			fs = &io->i_fs;
28925871Ssam 			lbn = lblkno(fs, io->i_offset);
29025871Ssam 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
29125871Ssam 			off = blkoff(fs, io->i_offset);
29225871Ssam 			size = blksize(fs, &io->i_ino, lbn);
29325871Ssam 		} else {
29425871Ssam 			io->i_bn = io->i_offset / DEV_BSIZE;
29525871Ssam 			off = 0;
29625871Ssam 			size = DEV_BSIZE;
29725871Ssam 		}
29825871Ssam 		io->i_ma = io->i_buf;
29925871Ssam 		io->i_cc = size;
30025871Ssam 		if (devread(io) < 0) {
30125871Ssam 			errno = io->i_error;
30225871Ssam 			return (-1);
30325871Ssam 		}
30425871Ssam 		if ((io->i_flgs & F_FILE) != 0) {
30525871Ssam 			if (io->i_offset - off + size >= io->i_ino.i_size)
30625871Ssam 				io->i_cc = diff + off;
30725871Ssam 			io->i_cc -= off;
30825871Ssam 		}
30925871Ssam 		p = &io->i_buf[off];
31025871Ssam 	}
31125871Ssam 	io->i_cc--;
31225871Ssam 	io->i_offset++;
31325871Ssam 	c = (unsigned)*p++;
31425871Ssam 	io->i_ma = p;
31525871Ssam 	return (c);
31625871Ssam }
31725871Ssam 
31825871Ssam int	errno;
31925871Ssam 
read(fdesc,buf,count)32025871Ssam read(fdesc, buf, count)
32125871Ssam 	int fdesc, count;
32225871Ssam 	char *buf;
32325871Ssam {
32430308Skarels 	register i, size;
32525871Ssam 	register struct iob *file;
32630308Skarels 	register struct fs *fs;
32730308Skarels 	int lbn, off;
32825871Ssam 
32925871Ssam 	errno = 0;
33030308Skarels 	if (fdesc >= 0 & fdesc <= 2) {
33125871Ssam 		i = count;
33225871Ssam 		do {
33325871Ssam 			*buf = getchar();
33425871Ssam 		} while (--i && *buf++ != '\n');
33525871Ssam 		return (count - i);
33625871Ssam 	}
33725871Ssam 	fdesc -= 3;
33825871Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
33925871Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
34025871Ssam 		errno = EBADF;
34125871Ssam 		return (-1);
34225871Ssam 	}
34325871Ssam 	if ((file->i_flgs&F_READ) == 0) {
34425871Ssam 		errno = EBADF;
34525871Ssam 		return (-1);
34625871Ssam 	}
34730308Skarels #ifndef	SMALL
34825871Ssam 	if ((file->i_flgs & F_FILE) == 0) {
34925871Ssam 		file->i_cc = count;
35025871Ssam 		file->i_ma = buf;
35125871Ssam 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
35225871Ssam 		i = devread(file);
35325871Ssam 		if (i < 0)
35425871Ssam 			errno = file->i_error;
35530308Skarels 		else
35630308Skarels 			file->i_offset += i;
35725871Ssam 		return (i);
35825871Ssam 	}
35930308Skarels #endif SMALL
36030308Skarels 	if (file->i_offset+count > file->i_ino.i_size)
36130308Skarels 		count = file->i_ino.i_size - file->i_offset;
36230308Skarels 	if ((i = count) <= 0)
36330308Skarels 		return (0);
36430308Skarels 	/*
36530308Skarels 	 * While reading full blocks, do I/O into user buffer.
36630308Skarels 	 * Anything else uses getc().
36730308Skarels 	 */
36830308Skarels 	fs = &file->i_fs;
36930308Skarels 	while (i) {
37030308Skarels 		off = blkoff(fs, file->i_offset);
37130308Skarels 		lbn = lblkno(fs, file->i_offset);
37230308Skarels 		size = blksize(fs, &file->i_ino, lbn);
37330308Skarels 		if (off == 0 && size <= i) {
37430308Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
37530308Skarels 			    file->i_boff;
37630308Skarels 			file->i_cc = size;
37730308Skarels 			file->i_ma = buf;
37830308Skarels 			if (devread(file) < 0) {
37930308Skarels 				errno = file->i_error;
38030308Skarels 				return (-1);
38130308Skarels 			}
38230308Skarels 			file->i_offset += size;
38330308Skarels 			file->i_cc = 0;
38430308Skarels 			buf += size;
38530308Skarels 			i -= size;
38630308Skarels 		} else {
38730308Skarels 			size -= off;
38830308Skarels 			if (size > i)
38930308Skarels 				size = i;
39030308Skarels 			i -= size;
39130308Skarels 			do {
39230308Skarels 				*buf++ = getc(fdesc+3);
39330308Skarels 			} while (--size);
39430308Skarels 		}
39530308Skarels 	}
39630308Skarels 	return (count);
39725871Ssam }
39825871Ssam 
39930308Skarels #ifndef	SMALL
write(fdesc,buf,count)40025871Ssam write(fdesc, buf, count)
40125871Ssam 	int fdesc, count;
40225871Ssam 	char *buf;
40325871Ssam {
40425871Ssam 	register i;
40525871Ssam 	register struct iob *file;
40625871Ssam 
40725871Ssam 	errno = 0;
40825871Ssam 	if (fdesc >= 0 && fdesc <= 2) {
40925871Ssam 		i = count;
41025871Ssam 		while (i--)
41125871Ssam 			putchar(*buf++);
41225871Ssam 		return (count);
41325871Ssam 	}
41425871Ssam 	fdesc -= 3;
41525871Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
41625871Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
41725871Ssam 		errno = EBADF;
41825871Ssam 		return (-1);
41925871Ssam 	}
42025871Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
42125871Ssam 		errno = EBADF;
42225871Ssam 		return (-1);
42325871Ssam 	}
42425871Ssam 	file->i_cc = count;
42525871Ssam 	file->i_ma = buf;
42625871Ssam 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
42725871Ssam 	i = devwrite(file);
42825871Ssam 	file->i_offset += count;
42925871Ssam 	if (i < 0)
43025871Ssam 		errno = file->i_error;
43125871Ssam 	return (i);
43225871Ssam }
43330308Skarels #endif SMALL
43425871Ssam 
43525871Ssam int	openfirst = 1;
43630757Skarels unsigned opendev;		/* last device opened */
43730757Skarels extern	unsigned bootdev;
43825871Ssam 
open(str,how)43925871Ssam open(str, how)
44025871Ssam 	char *str;
44125871Ssam 	int how;
44225871Ssam {
44325871Ssam 	register char *cp;
44430757Skarels 	register int i;
44525871Ssam 	register struct iob *file;
44625871Ssam 	int fdesc;
44725871Ssam 	long atol();
44825871Ssam 
44925871Ssam 	if (openfirst) {
45025871Ssam 		for (i = 0; i < NFILES; i++)
45125871Ssam 			iob[i].i_flgs = 0;
45225871Ssam 		openfirst = 0;
45325871Ssam 	}
45425871Ssam 
45525871Ssam 	for (fdesc = 0; fdesc < NFILES; fdesc++)
45625871Ssam 		if (iob[fdesc].i_flgs == 0)
45725871Ssam 			goto gotfile;
45825871Ssam 	_stop("No more file slots");
45925871Ssam gotfile:
46025871Ssam 	(file = &iob[fdesc])->i_flgs |= F_ALLOC;
46125871Ssam 
46230757Skarels 	for (cp = str; *cp && *cp != '/' && *cp != ':' && *cp != '('; cp++)
46330757Skarels 		;
46430757Skarels 	if (*cp == '(') {
46530757Skarels 		if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
46630757Skarels 			goto bad;
46730757Skarels 		cp++;
46830757Skarels 		if ((file->i_unit = getunit(cp)) == -1)
46930757Skarels 			goto bad;
47030757Skarels 		for (; *cp != ','; cp++)
47130757Skarels 			if (*cp == NULL) {
47230757Skarels 				errno = EOFFSET;
47330757Skarels 				goto badspec;
47430757Skarels 			}
47530757Skarels 		file->i_boff = atol(++cp);
47630757Skarels 		for (;;) {
47730757Skarels 			if (*cp == ')')
47830757Skarels 				break;
47930757Skarels 			if (*cp++)
48030757Skarels 				continue;
48130757Skarels 			goto badspec;
48230757Skarels 		}
48330757Skarels 		cp++;
48430757Skarels 	} else if (*cp != ':') {
48530308Skarels 		/* default bootstrap unit and device */
48630757Skarels 		file->i_ino.i_dev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
48730757Skarels 		file->i_unit = ((bootdev >> B_UNITSHIFT) & B_UNITMASK) +
48830757Skarels 		     (8 * ((bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK));
48930757Skarels 		file->i_boff = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
49030308Skarels 		cp = str;
49130308Skarels 	} else {
49230308Skarels # define isdigit(n)	((n>='0') && (n<='9'))
49330757Skarels 		if (cp == str)
49430757Skarels 			goto badspec;
49530308Skarels 		/*
49630308Skarels 	 	 * syntax for possible device name:
49730308Skarels 	 	 *	<alpha-string><digit-string><letter>:
49830308Skarels 	 	 */
49930308Skarels 		for (cp = str; *cp != ':' && !isdigit(*cp); cp++)
50030308Skarels 			;
50130757Skarels 		if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1)
50230757Skarels 			goto bad;
50330757Skarels 		if ((file->i_unit = getunit(cp)) == -1)
50430757Skarels 			goto bad;
50530757Skarels 		while (isdigit(*cp))
50630757Skarels 			cp++;
50730757Skarels 		file->i_boff = 0;
50830757Skarels 		if (*cp >= 'a' && *cp <= 'h')
50930757Skarels 			file->i_boff = *cp++ - 'a';
51030308Skarels 		if (*cp++ != ':') {
51130308Skarels 			errno = EOFFSET;
51230757Skarels 			goto badspec;
51330308Skarels 		}
51430308Skarels 	}
51530757Skarels 	opendev = file->i_ino.i_dev << B_TYPESHIFT;
51630757Skarels 	opendev |= ((file->i_unit % 8) << B_UNITSHIFT);
51730757Skarels 	opendev |= ((file->i_unit / 8) << B_ADAPTORSHIFT);
51830757Skarels 	opendev |= file->i_boff << B_PARTITIONSHIFT;
51930757Skarels 	opendev |= B_DEVMAGIC;
52030757Skarels 	if (errno = devopen(file))
52130757Skarels 		goto bad;
52230308Skarels 	if (cp != str && *cp == '\0') {
52330308Skarels 		file->i_flgs |= how+1;
52430308Skarels 		file->i_cc = 0;
52530308Skarels 		file->i_offset = 0;
52630308Skarels 		return (fdesc+3);
52730308Skarels 	}
52825871Ssam 	file->i_ma = (char *)(&file->i_fs);
52925871Ssam 	file->i_cc = SBSIZE;
53030757Skarels 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
53125871Ssam 	file->i_offset = 0;
53225871Ssam 	if (devread(file) < 0) {
53325871Ssam 		errno = file->i_error;
53425871Ssam 		printf("super block read error\n");
53530757Skarels 		goto bad;
53625871Ssam 	}
53725871Ssam 	if ((i = find(cp, file)) == 0) {
53825871Ssam 		errno = ESRCH;
53930757Skarels 		goto bad;
54025871Ssam 	}
54130308Skarels #ifndef	SMALL
54225871Ssam 	if (how != 0) {
54325871Ssam 		printf("Can't write files yet.. Sorry\n");
54425871Ssam 		errno = EIO;
54530757Skarels 		goto bad;
54625871Ssam 	}
54730308Skarels #endif SMALL
54825871Ssam 	if (openi(i, file) < 0) {
54925871Ssam 		errno = file->i_error;
55030757Skarels 		goto bad;
55125871Ssam 	}
55225871Ssam 	file->i_offset = 0;
55325871Ssam 	file->i_cc = 0;
55430757Skarels 	file->i_flgs |= F_FILE | (how+1);
55525871Ssam 	return (fdesc+3);
55630757Skarels 
55730757Skarels badspec:
55830757Skarels 	printf("malformed device specification\n");
55930757Skarels bad:
56030757Skarels 	file->i_flgs = 0;
56130757Skarels 	return (-1);
56225871Ssam }
56325871Ssam 
56430757Skarels static
getdev(str,len)56530757Skarels getdev(str, len)
56630757Skarels 	char *str;
56730757Skarels 	int len;
56830757Skarels {
56930757Skarels 	register struct devsw *dp;
57030757Skarels 
57130757Skarels 	for (dp = devsw; dp->dv_name; dp++) {
57230757Skarels 		if (!strncmp(str, dp->dv_name, len))
57330757Skarels 			return (dp - devsw);
57430757Skarels 	}
57530757Skarels 	printf("Unknown device\n");
57630757Skarels 	errno = ENXIO;
57730757Skarels 	return (-1);
57830757Skarels }
57930757Skarels 
58030757Skarels static
getunit(cp)58130757Skarels getunit(cp)
58230757Skarels 	register char *cp;
58330757Skarels {
58430757Skarels 	register int i = 0;
58530757Skarels 
58630757Skarels 	while (*cp >= '0' && *cp <= '9')
58730757Skarels 		i = i * 10 + *cp++ - '0';
58830757Skarels 	if ((unsigned) i > 255) {
58930757Skarels 		printf("minor device number out of range (0-255)\n");
59030757Skarels 		errno = EUNIT;
59130757Skarels 		i = -1;
59230757Skarels 	}
59330757Skarels 	return (i);
59430757Skarels }
59530757Skarels 
close(fdesc)59625871Ssam close(fdesc)
59725871Ssam 	int fdesc;
59825871Ssam {
59925871Ssam 	struct iob *file;
60025871Ssam 
60125871Ssam 	fdesc -= 3;
60225871Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
60325871Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
60425871Ssam 		errno = EBADF;
60525871Ssam 		return (-1);
60625871Ssam 	}
60725871Ssam 	if ((file->i_flgs&F_FILE) == 0)
60825871Ssam 		devclose(file);
60925871Ssam 	file->i_flgs = 0;
61025871Ssam 	return (0);
61125871Ssam }
61225871Ssam 
61330308Skarels #ifndef	SMALL
ioctl(fdesc,cmd,arg)61430308Skarels ioctl(fdesc, cmd, arg)
61530308Skarels 	int fdesc, cmd;
61630308Skarels 	char *arg;
61730308Skarels {
61830308Skarels 	register struct iob *file;
61930308Skarels 	int error = 0;
62025871Ssam 
62130308Skarels 	fdesc -= 3;
62230308Skarels 	if (fdesc < 0 || fdesc >= NFILES ||
62330308Skarels 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
62430308Skarels 		errno = EBADF;
62530308Skarels 		return (-1);
62630308Skarels 	}
62730308Skarels 	switch (cmd) {
62830308Skarels 
62930308Skarels 	case SAIOHDR:
63030308Skarels 		file->i_flgs |= F_HDR;
63130308Skarels 		break;
63230308Skarels 
63330308Skarels 	case SAIOCHECK:
63430308Skarels 		file->i_flgs |= F_CHECK;
63530308Skarels 		break;
63630308Skarels 
63730308Skarels 	case SAIOHCHECK:
63830308Skarels 		file->i_flgs |= F_HCHECK;
63930308Skarels 		break;
64030308Skarels 
64130308Skarels 	case SAIONOBAD:
64230308Skarels 		file->i_flgs |= F_NBSF;
64330308Skarels 		break;
64430308Skarels 
64530308Skarels 	case SAIODOBAD:
64630308Skarels 		file->i_flgs &= ~F_NBSF;
64730308Skarels 		break;
64830308Skarels 
64930308Skarels 	default:
65030308Skarels 		error = devioctl(file, cmd, arg);
65130308Skarels 		break;
65230308Skarels 	}
65330308Skarels 	if (error < 0)
65430308Skarels 		errno = file->i_error;
65530308Skarels 	return (error);
65630308Skarels }
65730308Skarels #endif SMALL
65830308Skarels 
exit()65925871Ssam exit()
66025871Ssam {
66125871Ssam 	_stop("Exit called");
66225871Ssam }
66325871Ssam 
_stop(s)66425871Ssam _stop(s)
66525871Ssam 	char *s;
66625871Ssam {
66725871Ssam 	int i;
66825871Ssam 
66925871Ssam 	for (i = 0; i < NFILES; i++)
67025871Ssam 		if (iob[i].i_flgs != 0)
67125871Ssam 			close(i);
67225871Ssam 	printf("%s\n", s);
67325871Ssam 	_rtt();
67425871Ssam }
675