xref: /csrg-svn/sys/stand.att/sys.c (revision 34463)
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*34463Sbostic  *	@(#)sys.c	7.6 (Berkeley) 05/24/88
723243Smckusick  */
8327Sbill 
930768Skarels #include "param.h"
1030768Skarels #include "inode.h"
1130768Skarels #include "fs.h"
1230768Skarels #include "dir.h"
1330768Skarels #include "reboot.h"
14327Sbill #include "saio.h"
15327Sbill 
16*34463Sbostic #define	isdigit(c)	((c) >= '0' && (c) <= '9')
17*34463Sbostic #define	isspace(c)	((c) == ' ' || (c) == '\t')
18*34463Sbostic #define	isupper(c)	((c) >= 'A' && (c) <= 'Z')
19*34463Sbostic #define	tolower(c)	((c) - 'A' + 'a')
20*34463Sbostic 
21327Sbill ino_t	dlook();
22327Sbill 
236068Smckusic struct dirstuff {
246068Smckusic 	int loc;
256068Smckusic 	struct iob *io;
266068Smckusic };
276068Smckusic 
28*34463Sbostic struct iob iob[NFILES];
29*34463Sbostic 
30327Sbill static
3110022Ssam openi(n, io)
326068Smckusic 	register struct iob *io;
33327Sbill {
34327Sbill 	register struct dinode *dp;
3511083Ssam 	int cc;
36327Sbill 
37327Sbill 	io->i_offset = 0;
386068Smckusic 	io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff;
396068Smckusic 	io->i_cc = io->i_fs.fs_bsize;
40327Sbill 	io->i_ma = io->i_buf;
4111083Ssam 	cc = devread(io);
42327Sbill 	dp = (struct dinode *)io->i_buf;
436068Smckusic 	io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
4411083Ssam 	return (cc);
45327Sbill }
46327Sbill 
47327Sbill static
48327Sbill find(path, file)
496068Smckusic 	register char *path;
506068Smckusic 	struct iob *file;
51327Sbill {
52327Sbill 	register char *q;
53*34463Sbostic 	char *dir, c;
54327Sbill 	int n;
55327Sbill 
56*34463Sbostic 	if (path == NULL || *path == '\0') {
57327Sbill 		printf("null path\n");
5810022Ssam 		return (0);
59327Sbill 	}
60327Sbill 
6111083Ssam 	if (openi((ino_t) ROOTINO, file) < 0) {
6211083Ssam 		printf("can't read root inode\n");
6311083Ssam 		return (0);
6411083Ssam 	}
6530768Skarels 	dir = path;
66327Sbill 	while (*path) {
67327Sbill 		while (*path == '/')
68327Sbill 			path++;
69327Sbill 		q = path;
70327Sbill 		while(*q != '/' && *q != '\0')
71327Sbill 			q++;
72327Sbill 		c = *q;
73327Sbill 		*q = '\0';
7425166Skarels 		if (q == path) path = "." ;	/* "/" means "/." */
75327Sbill 
7630768Skarels 		if ((n = dlook(path, file, dir)) != 0) {
7711083Ssam 			if (c == '\0')
78327Sbill 				break;
7911083Ssam 			if (openi(n, file) < 0)
8011083Ssam 				return (0);
81327Sbill 			*q = c;
82327Sbill 			path = q;
83327Sbill 			continue;
84327Sbill 		} else {
8525166Skarels 			printf("%s: not found\n", path);
8610022Ssam 			return (0);
87327Sbill 		}
88327Sbill 	}
8910022Ssam 	return (n);
90327Sbill }
91327Sbill 
92*34463Sbostic #define	NBUFS	4
93*34463Sbostic static char	b[NBUFS][MAXBSIZE];
94*34463Sbostic static daddr_t	blknos[NBUFS];
95*34463Sbostic 
96327Sbill static daddr_t
97327Sbill sbmap(io, bn)
986068Smckusic 	register struct iob *io;
996068Smckusic 	daddr_t bn;
100327Sbill {
101327Sbill 	register struct inode *ip;
1026068Smckusic 	int i, j, sh;
103327Sbill 	daddr_t nb, *bap;
104327Sbill 
105327Sbill 	ip = &io->i_ino;
1066068Smckusic 	if (bn < 0) {
107327Sbill 		printf("bn negative\n");
10810022Ssam 		return ((daddr_t)0);
109327Sbill 	}
110327Sbill 
111327Sbill 	/*
1126068Smckusic 	 * blocks 0..NDADDR are direct blocks
113327Sbill 	 */
1146068Smckusic 	if(bn < NDADDR) {
1156068Smckusic 		nb = ip->i_db[bn];
11610022Ssam 		return (nb);
117327Sbill 	}
118327Sbill 
119327Sbill 	/*
1206068Smckusic 	 * addresses NIADDR have single and double indirect blocks.
1216068Smckusic 	 * the first step is to determine how many levels of indirection.
122327Sbill 	 */
1236068Smckusic 	sh = 1;
1246068Smckusic 	bn -= NDADDR;
1256068Smckusic 	for (j = NIADDR; j > 0; j--) {
1266068Smckusic 		sh *= NINDIR(&io->i_fs);
1276068Smckusic 		if (bn < sh)
128327Sbill 			break;
1296068Smckusic 		bn -= sh;
130327Sbill 	}
1316068Smckusic 	if (j == 0) {
1326068Smckusic 		printf("bn ovf %D\n", bn);
1336068Smckusic 		return ((daddr_t)0);
134327Sbill 	}
135327Sbill 
136327Sbill 	/*
1376068Smckusic 	 * fetch the first indirect block address from the inode
138327Sbill 	 */
1396068Smckusic 	nb = ip->i_ib[NIADDR - j];
1406068Smckusic 	if (nb == 0) {
141327Sbill 		printf("bn void %D\n",bn);
14210022Ssam 		return ((daddr_t)0);
143327Sbill 	}
144327Sbill 
145327Sbill 	/*
146327Sbill 	 * fetch through the indirect blocks
147327Sbill 	 */
1486068Smckusic 	for (; j <= NIADDR; j++) {
149327Sbill 		if (blknos[j] != nb) {
1506068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff;
151327Sbill 			io->i_ma = b[j];
1526068Smckusic 			io->i_cc = io->i_fs.fs_bsize;
15311083Ssam 			if (devread(io) != io->i_fs.fs_bsize) {
15411083Ssam 				if (io->i_error)
15511083Ssam 					errno = io->i_error;
15611083Ssam 				printf("bn %D: read error\n", io->i_bn);
15711083Ssam 				return ((daddr_t)0);
15811083Ssam 			}
159327Sbill 			blknos[j] = nb;
160327Sbill 		}
161327Sbill 		bap = (daddr_t *)b[j];
1626068Smckusic 		sh /= NINDIR(&io->i_fs);
1636068Smckusic 		i = (bn / sh) % NINDIR(&io->i_fs);
164327Sbill 		nb = bap[i];
165327Sbill 		if(nb == 0) {
166327Sbill 			printf("bn void %D\n",bn);
16710022Ssam 			return ((daddr_t)0);
168327Sbill 		}
169327Sbill 	}
17010022Ssam 	return (nb);
171327Sbill }
172327Sbill 
173327Sbill static ino_t
17430768Skarels dlook(s, io, dir)
1756068Smckusic 	char *s;
1766068Smckusic 	register struct iob *io;
17730768Skarels 	char *dir;
178327Sbill {
179327Sbill 	register struct direct *dp;
180327Sbill 	register struct inode *ip;
1816068Smckusic 	struct dirstuff dirp;
1826068Smckusic 	int len;
183327Sbill 
1846068Smckusic 	if (s == NULL || *s == '\0')
18510022Ssam 		return (0);
186327Sbill 	ip = &io->i_ino;
1876068Smckusic 	if ((ip->i_mode&IFMT) != IFDIR) {
18830768Skarels 		printf("%s: not a directory\n", dir);
18910022Ssam 		return (0);
190327Sbill 	}
1916068Smckusic 	if (ip->i_size == 0) {
19230768Skarels 		printf("%s: zero length directory\n", dir);
19310022Ssam 		return (0);
194327Sbill 	}
1956068Smckusic 	len = strlen(s);
1966068Smckusic 	dirp.loc = 0;
1976068Smckusic 	dirp.io = io;
1986068Smckusic 	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
1996068Smckusic 		if(dp->d_ino == 0)
2006068Smckusic 			continue;
2016068Smckusic 		if (dp->d_namlen == len && !strcmp(s, dp->d_name))
20210022Ssam 			return (dp->d_ino);
203327Sbill 	}
20410022Ssam 	return (0);
205327Sbill }
206327Sbill 
2076068Smckusic /*
2086068Smckusic  * get next entry in a directory.
2096068Smckusic  */
2106068Smckusic struct direct *
2116068Smckusic readdir(dirp)
2126068Smckusic 	register struct dirstuff *dirp;
213327Sbill {
2146068Smckusic 	register struct direct *dp;
2156068Smckusic 	register struct iob *io;
2166068Smckusic 	daddr_t lbn, d;
2176068Smckusic 	int off;
218327Sbill 
2196068Smckusic 	io = dirp->io;
2206068Smckusic 	for(;;) {
2216068Smckusic 		if (dirp->loc >= io->i_ino.i_size)
22211083Ssam 			return (NULL);
2236068Smckusic 		off = blkoff(&io->i_fs, dirp->loc);
2246068Smckusic 		if (off == 0) {
2256068Smckusic 			lbn = lblkno(&io->i_fs, dirp->loc);
2266068Smckusic 			d = sbmap(io, lbn);
2276068Smckusic 			if(d == 0)
228*34463Sbostic 				return (NULL);
2296068Smckusic 			io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff;
2306068Smckusic 			io->i_ma = io->i_buf;
2316068Smckusic 			io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
23211083Ssam 			if (devread(io) < 0) {
23311083Ssam 				errno = io->i_error;
23425166Skarels 				printf("bn %D: directory read error\n",
23525166Skarels 					io->i_bn);
23611083Ssam 				return (NULL);
23711083Ssam 			}
2386068Smckusic 		}
2396068Smckusic 		dp = (struct direct *)(io->i_buf + off);
2406068Smckusic 		dirp->loc += dp->d_reclen;
2416068Smckusic 		if (dp->d_ino == 0)
2426068Smckusic 			continue;
2436068Smckusic 		return (dp);
244327Sbill 	}
245327Sbill }
246327Sbill 
247327Sbill lseek(fdesc, addr, ptr)
24810022Ssam 	int fdesc, ptr;
24910022Ssam 	off_t addr;
250327Sbill {
251327Sbill 	register struct iob *io;
252327Sbill 
253*34463Sbostic #ifndef SMALL
254*34463Sbostic 	if (ptr != L_SET) {
255327Sbill 		printf("Seek not from beginning of file\n");
25610022Ssam 		errno = EOFFSET;
25710022Ssam 		return (-1);
258327Sbill 	}
259*34463Sbostic #endif
260327Sbill 	fdesc -= 3;
2616068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
26210022Ssam 	    ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) {
26310022Ssam 		errno = EBADF;
26410022Ssam 		return (-1);
26510022Ssam 	}
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 
281327Sbill 	if (fdesc >= 0 && fdesc <= 2)
28210022Ssam 		return (getchar());
283327Sbill 	fdesc -= 3;
2846068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
28510022Ssam 	    ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
28610022Ssam 		errno = EBADF;
28710022Ssam 		return (-1);
28810022Ssam 	}
289327Sbill 	p = io->i_ma;
290327Sbill 	if (io->i_cc <= 0) {
2916068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
2926068Smckusic 			diff = io->i_ino.i_size - io->i_offset;
2936068Smckusic 			if (diff <= 0)
2946068Smckusic 				return (-1);
2956068Smckusic 			fs = &io->i_fs;
2966068Smckusic 			lbn = lblkno(fs, io->i_offset);
2976068Smckusic 			io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff;
2986068Smckusic 			off = blkoff(fs, io->i_offset);
2996068Smckusic 			size = blksize(fs, &io->i_ino, lbn);
3006068Smckusic 		} else {
3016068Smckusic 			io->i_bn = io->i_offset / DEV_BSIZE;
3026068Smckusic 			off = 0;
3036068Smckusic 			size = DEV_BSIZE;
3046068Smckusic 		}
305327Sbill 		io->i_ma = io->i_buf;
3066068Smckusic 		io->i_cc = size;
30711083Ssam 		if (devread(io) < 0) {
30811083Ssam 			errno = io->i_error;
30911083Ssam 			return (-1);
31011083Ssam 		}
3116068Smckusic 		if ((io->i_flgs & F_FILE) != 0) {
3126068Smckusic 			if (io->i_offset - off + size >= io->i_ino.i_size)
3136068Smckusic 				io->i_cc = diff + off;
314327Sbill 			io->i_cc -= off;
3156068Smckusic 		}
316327Sbill 		p = &io->i_buf[off];
317327Sbill 	}
318327Sbill 	io->i_cc--;
319327Sbill 	io->i_offset++;
320327Sbill 	c = (unsigned)*p++;
321327Sbill 	io->i_ma = p;
32210022Ssam 	return (c);
323327Sbill }
3246068Smckusic 
32510022Ssam int	errno;
326327Sbill 
327327Sbill read(fdesc, buf, count)
32810022Ssam 	int fdesc, count;
32910022Ssam 	char *buf;
330327Sbill {
33125166Skarels 	register i, size;
332327Sbill 	register struct iob *file;
33325166Skarels 	register struct fs *fs;
33425166Skarels 	int lbn, off;
335327Sbill 
33610022Ssam 	errno = 0;
337327Sbill 	if (fdesc >= 0 & fdesc <= 2) {
338327Sbill 		i = count;
339327Sbill 		do {
340327Sbill 			*buf = getchar();
341327Sbill 		} while (--i && *buf++ != '\n');
34210022Ssam 		return (count - i);
343327Sbill 	}
344327Sbill 	fdesc -= 3;
3456068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
34610022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
34710022Ssam 		errno = EBADF;
34810022Ssam 		return (-1);
34910022Ssam 	}
35010022Ssam 	if ((file->i_flgs&F_READ) == 0) {
35110022Ssam 		errno = EBADF;
35210022Ssam 		return (-1);
35310022Ssam 	}
354*34463Sbostic #ifndef SMALL
3556068Smckusic 	if ((file->i_flgs & F_FILE) == 0) {
356327Sbill 		file->i_cc = count;
357327Sbill 		file->i_ma = buf;
3587446Sroot 		file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
359327Sbill 		i = devread(file);
36010022Ssam 		if (i < 0)
36110022Ssam 			errno = file->i_error;
36230547Skarels 		else
36330547Skarels 			file->i_offset += i;
36410022Ssam 		return (i);
365327Sbill 	}
366*34463Sbostic #endif
36725166Skarels 	if (file->i_offset+count > file->i_ino.i_size)
36825166Skarels 		count = file->i_ino.i_size - file->i_offset;
36925166Skarels 	if ((i = count) <= 0)
37025166Skarels 		return (0);
37125166Skarels 	/*
37225166Skarels 	 * While reading full blocks, do I/O into user buffer.
37325166Skarels 	 * Anything else uses getc().
37425166Skarels 	 */
37525166Skarels 	fs = &file->i_fs;
37625166Skarels 	while (i) {
37725166Skarels 		off = blkoff(fs, file->i_offset);
37825166Skarels 		lbn = lblkno(fs, file->i_offset);
37925166Skarels 		size = blksize(fs, &file->i_ino, lbn);
38025166Skarels 		if (off == 0 && size <= i) {
38125166Skarels 			file->i_bn = fsbtodb(fs, sbmap(file, lbn)) +
38225166Skarels 			    file->i_boff;
38325166Skarels 			file->i_cc = size;
38425166Skarels 			file->i_ma = buf;
38525166Skarels 			if (devread(file) < 0) {
38625166Skarels 				errno = file->i_error;
38725166Skarels 				return (-1);
38825166Skarels 			}
38925166Skarels 			file->i_offset += size;
39025166Skarels 			file->i_cc = 0;
39125166Skarels 			buf += size;
39225166Skarels 			i -= size;
39325166Skarels 		} else {
39425166Skarels 			size -= off;
39525166Skarels 			if (size > i)
39625166Skarels 				size = i;
39725166Skarels 			i -= size;
39825166Skarels 			do {
39925166Skarels 				*buf++ = getc(fdesc+3);
40025166Skarels 			} while (--size);
40125166Skarels 		}
40225166Skarels 	}
40325166Skarels 	return (count);
404327Sbill }
405327Sbill 
406*34463Sbostic #ifndef SMALL
407327Sbill write(fdesc, buf, count)
40810022Ssam 	int fdesc, count;
40910022Ssam 	char *buf;
410327Sbill {
411327Sbill 	register i;
412327Sbill 	register struct iob *file;
413327Sbill 
41410022Ssam 	errno = 0;
415327Sbill 	if (fdesc >= 0 && fdesc <= 2) {
416327Sbill 		i = count;
417327Sbill 		while (i--)
418327Sbill 			putchar(*buf++);
41910022Ssam 		return (count);
420327Sbill 	}
421327Sbill 	fdesc -= 3;
4226068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
42310022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
42410022Ssam 		errno = EBADF;
42510022Ssam 		return (-1);
42610022Ssam 	}
42710022Ssam 	if ((file->i_flgs&F_WRITE) == 0) {
42810022Ssam 		errno = EBADF;
42910022Ssam 		return (-1);
43010022Ssam 	}
431327Sbill 	file->i_cc = count;
432327Sbill 	file->i_ma = buf;
4337446Sroot 	file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE);
434327Sbill 	i = devwrite(file);
4357446Sroot 	file->i_offset += count;
43610022Ssam 	if (i < 0)
43710022Ssam 		errno = file->i_error;
43810022Ssam 	return (i);
439327Sbill }
440*34463Sbostic #endif
441327Sbill 
4423349Swnj int	openfirst = 1;
443*34463Sbostic u_int	opendev;		/* last device opened */
444*34463Sbostic extern u_int bootdev;
4453349Swnj 
446327Sbill open(str, how)
4476068Smckusic 	char *str;
44810022Ssam 	int how;
449327Sbill {
450*34463Sbostic 	register char *t;
451*34463Sbostic 	register int cnt;
452327Sbill 	register struct iob *file;
453*34463Sbostic 	int fdesc, args[8], *argp;
454327Sbill 
4553349Swnj 	if (openfirst) {
456*34463Sbostic 		for (cnt = 0; cnt < NFILES; cnt++)
457*34463Sbostic 			iob[cnt].i_flgs = 0;
4583349Swnj 		openfirst = 0;
459327Sbill 	}
460327Sbill 
461*34463Sbostic 	for (fdesc = 0;; fdesc++) {
462*34463Sbostic 		if (fdesc == NFILES)
463*34463Sbostic 			_stop("No more file slots");
464*34463Sbostic 		if (iob[fdesc].i_flgs == 0) {
465*34463Sbostic 			file = &iob[fdesc];
466*34463Sbostic 			file->i_flgs |= F_ALLOC;
467*34463Sbostic 			file->i_adapt = file->i_ctlr = file->i_unit =
468*34463Sbostic 			    file->i_part = 0;
469*34463Sbostic 			break;
470*34463Sbostic 		}
471*34463Sbostic 	}
472327Sbill 
473*34463Sbostic 	for (cnt = 0; cnt < sizeof(args)/sizeof(args[0]); args[cnt++] = 0);
474*34463Sbostic #ifndef SMALL
475*34463Sbostic 	for (t = str; *t && *t != '/' && *t != ':' && *t != '('; ++t)
476*34463Sbostic 		if (isupper(*t))
477*34463Sbostic 			*t = tolower(*t);
478*34463Sbostic 	switch(*t) {
479*34463Sbostic 	case '(':	/* type(adapt, ctlr, drive, partition)file */
480*34463Sbostic 		if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
48130547Skarels 			goto bad;
482*34463Sbostic 		for (argp = args + 4, cnt = 0; *t != ')'; ++cnt) {
483*34463Sbostic 			for (++t; isspace(*t); ++t);
484*34463Sbostic 			if (*t == ')')
485*34463Sbostic 				break;
486*34463Sbostic 			if (!isdigit(*t))
48730547Skarels 				goto badspec;
488*34463Sbostic 			*argp++ = atoi(t);
489*34463Sbostic 			for (++t; isdigit(*t); ++t);
490*34463Sbostic 			if (*t != ',' && *t != ')' || cnt == 4)
491*34463Sbostic 				goto badspec;
49230547Skarels 		}
493*34463Sbostic 		for (++t; isspace(*t); ++t);
494*34463Sbostic 		argp -= 4;
495*34463Sbostic 		file->i_adapt = *argp++;
496*34463Sbostic 		file->i_ctlr = *argp++;
497*34463Sbostic 		file->i_unit = *argp++;
498*34463Sbostic 		file->i_part = *argp;
499*34463Sbostic 		break;
500*34463Sbostic 	case ':':	/* [A-Za-z]*[0-9]*[A-Za-z]:file */
501*34463Sbostic 		for (t = str; *t != ':' && !isdigit(*t); ++t);
502*34463Sbostic 		if ((file->i_ino.i_dev = getdev(str, t - str)) == -1)
50330547Skarels 			goto bad;
504*34463Sbostic 		if ((file->i_unit = getunit(t)) == -1)
50530547Skarels 			goto bad;
506*34463Sbostic 		for (; isdigit(*t); ++t);
507*34463Sbostic 		if (*t >= 'a' && *t <= 'h')
508*34463Sbostic 			file->i_part = *t++ - 'a';
509*34463Sbostic 		if (*t != ':') {
51025166Skarels 			errno = EOFFSET;
51130547Skarels 			goto badspec;
51225166Skarels 		}
513*34463Sbostic 		for (++t; isspace(*t); ++t);
514*34463Sbostic 		break;
515*34463Sbostic 	case '/':
516*34463Sbostic 	default:		/* default bootstrap unit and device */
517*34463Sbostic #else
518*34463Sbostic 	{
519*34463Sbostic #endif /* SMALL */
520*34463Sbostic 		file->i_ino.i_dev = B_TYPE(bootdev);
521*34463Sbostic 		file->i_adapt = B_ADAPTOR(bootdev);
522*34463Sbostic 		file->i_ctlr = B_CONTROLLER(bootdev);
523*34463Sbostic 		file->i_unit = B_UNIT(bootdev);
524*34463Sbostic 		file->i_part = B_PARTITION(bootdev);
525*34463Sbostic 		t = str;
52625166Skarels 	}
527*34463Sbostic 
528*34463Sbostic 	opendev = MAKEBOOTDEV(file->i_ino.i_dev, file->i_adapt, file->i_ctlr,
529*34463Sbostic 	    file->i_unit, file->i_part);
530*34463Sbostic 
53130547Skarels 	if (errno = devopen(file))
53230547Skarels 		goto bad;
533*34463Sbostic 
534*34463Sbostic 	if (*t == '\0') {
535*34463Sbostic 		file->i_flgs |= how + 1;
53625166Skarels 		file->i_cc = 0;
53725166Skarels 		file->i_offset = 0;
53825166Skarels 		return (fdesc+3);
53925166Skarels 	}
540*34463Sbostic #ifndef SMALL
541*34463Sbostic 	else if (how != 0) {
542*34463Sbostic 		printf("Can't write files yet.. Sorry\n");
543*34463Sbostic 		errno = EIO;
544*34463Sbostic 		goto bad;
545*34463Sbostic 	}
54633408Skarels #endif
5476068Smckusic 	file->i_ma = (char *)(&file->i_fs);
5486068Smckusic 	file->i_cc = SBSIZE;
54930768Skarels 	file->i_bn = SBOFF / DEV_BSIZE + file->i_boff;
5506068Smckusic 	file->i_offset = 0;
55111083Ssam 	if (devread(file) < 0) {
55211083Ssam 		errno = file->i_error;
55311083Ssam 		printf("super block read error\n");
55430547Skarels 		goto bad;
55511083Ssam 	}
556*34463Sbostic 	if ((cnt = find(t, file)) == 0) {
55710022Ssam 		errno = ESRCH;
55830547Skarels 		goto bad;
559327Sbill 	}
560*34463Sbostic 	if (openi(cnt, file) < 0) {
56111083Ssam 		errno = file->i_error;
56230547Skarels 		goto bad;
56311083Ssam 	}
564327Sbill 	file->i_offset = 0;
565327Sbill 	file->i_cc = 0;
566327Sbill 	file->i_flgs |= F_FILE | (how+1);
56710022Ssam 	return (fdesc+3);
56830547Skarels 
56933408Skarels #ifndef SMALL
57030547Skarels badspec:
571*34463Sbostic 	printf("malformed device specification\nusage: device(adaptor, controller, drive, partition)file\n");
57233408Skarels #endif
57330547Skarels bad:
57430547Skarels 	file->i_flgs = 0;
57530547Skarels 	return (-1);
576327Sbill }
577327Sbill 
57830924Skarels #ifndef SMALL
57930547Skarels static
58030547Skarels getdev(str, len)
58133408Skarels 	register char *str;
58230547Skarels 	int len;
58330547Skarels {
58430547Skarels 	register struct devsw *dp;
58533408Skarels 	register int i;
586*34463Sbostic 	char savedch = str[len];
58730547Skarels 
588*34463Sbostic 	str[len] = '\0';
58933408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
59033408Skarels 		if (dp->dv_name && strcmp(str, dp->dv_name) == 0) {
591*34463Sbostic 			str[len] = savedch;
59233408Skarels 			return (i);
59333408Skarels 		}
59433408Skarels 	printf("Unknown device\nKnown devices are:\n");
59533408Skarels 	for (dp = devsw, i = 0; i < ndevs; dp++, i++)
59633408Skarels 		if (dp->dv_name)
59733408Skarels 			printf(" %s", dp->dv_name);
598*34463Sbostic 	printf("\n");
59930547Skarels 	errno = ENXIO;
60030547Skarels 	return (-1);
60130547Skarels }
60230547Skarels 
60330547Skarels static
60430547Skarels getunit(cp)
60530547Skarels 	register char *cp;
60630547Skarels {
607*34463Sbostic 	int unit;
60830547Skarels 
609*34463Sbostic 	unit = atoi(cp);
610*34463Sbostic 	if ((u_int)unit > 255) {
61130547Skarels 		printf("minor device number out of range (0-255)\n");
61230547Skarels 		errno = EUNIT;
613*34463Sbostic 		return (-1);
61430547Skarels 	}
615*34463Sbostic 	return (unit);
61630547Skarels }
617*34463Sbostic #endif /* SMALL */
61830547Skarels 
619327Sbill close(fdesc)
62010022Ssam 	int fdesc;
621327Sbill {
622327Sbill 	struct iob *file;
623327Sbill 
624327Sbill 	fdesc -= 3;
6256068Smckusic 	if (fdesc < 0 || fdesc >= NFILES ||
62610022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
62710022Ssam 		errno = EBADF;
62810022Ssam 		return (-1);
62910022Ssam 	}
630327Sbill 	if ((file->i_flgs&F_FILE) == 0)
631327Sbill 		devclose(file);
632327Sbill 	file->i_flgs = 0;
63310022Ssam 	return (0);
634327Sbill }
635327Sbill 
636*34463Sbostic #ifndef SMALL
63710022Ssam ioctl(fdesc, cmd, arg)
63810022Ssam 	int fdesc, cmd;
63910022Ssam 	char *arg;
64010022Ssam {
64110022Ssam 	register struct iob *file;
64210022Ssam 	int error = 0;
64310022Ssam 
64410331Shelge 	fdesc -= 3;
64510022Ssam 	if (fdesc < 0 || fdesc >= NFILES ||
64610022Ssam 	    ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) {
64710022Ssam 		errno = EBADF;
64810022Ssam 		return (-1);
64910022Ssam 	}
65010022Ssam 	switch (cmd) {
65110022Ssam 
65210022Ssam 	case SAIOHDR:
65310022Ssam 		file->i_flgs |= F_HDR;
65410022Ssam 		break;
65510022Ssam 
65610022Ssam 	case SAIOCHECK:
65710022Ssam 		file->i_flgs |= F_CHECK;
65810022Ssam 		break;
65910022Ssam 
66010022Ssam 	case SAIOHCHECK:
66110022Ssam 		file->i_flgs |= F_HCHECK;
66210022Ssam 		break;
66310022Ssam 
66410331Shelge 	case SAIONOBAD:
66510331Shelge 		file->i_flgs |= F_NBSF;
66610331Shelge 		break;
66710331Shelge 
66810331Shelge 	case SAIODOBAD:
66910331Shelge 		file->i_flgs &= ~F_NBSF;
67010331Shelge 		break;
67110331Shelge 
67210022Ssam 	default:
67310022Ssam 		error = devioctl(file, cmd, arg);
67410022Ssam 		break;
67510022Ssam 	}
67610022Ssam 	if (error < 0)
67710022Ssam 		errno = file->i_error;
67810022Ssam 	return (error);
67910022Ssam }
680*34463Sbostic #endif /* SMALL */
68110022Ssam 
682327Sbill exit()
683327Sbill {
684327Sbill 	_stop("Exit called");
685327Sbill }
686327Sbill 
687327Sbill _stop(s)
68810022Ssam 	char *s;
689327Sbill {
6902391Stoy 	int i;
6912391Stoy 
6922391Stoy 	for (i = 0; i < NFILES; i++)
6932391Stoy 		if (iob[i].i_flgs != 0)
6942391Stoy 			close(i);
695327Sbill 	printf("%s\n", s);
696327Sbill 	_rtt();
697327Sbill }
698