vfs_sys.c

来自「操作系统SunOS 4.1.3版本的源码」· C语言 代码 · 共 716 行

C
716
字号
#ifndef lintstatic	char sccsid[] = "@(#)vfs_sys.c 1.1 92/07/30 Copyr 1986 Sun Micro";#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * Basic file system reading code for standalone I/O system. * Simulates a primitive UNIX I/O system (read(), write(), open(), etc). * Does not attempt writes to file systems, tho writing to whole devices * is supported, when the driver supports it. */#include "boot/param.h"#include <sys/param.h>#include <stand/saio.h>#include "boot/systm.h"#include <sys/dir.h>#include <sys/time.h>#include "boot/vnode.h"#include <ufs/fs.h>#include "boot/inode.h"#include <sys/uio.h>#include <sys/fcntl.h>#include <sys/file.h>#include <sys/user.h>#include "boot/iob.h"#ifdef OPENPROMS#include "boot/conf.h"#endif#undef uextern struct user u;/* These are the pools of buffers, iob's, etc. */char		b[NBUFS][MAXBSIZE];daddr_t		blknos[NBUFS];struct iob	iob[NFILES];static	int	dump_debug = 20;extern	char	*gethex();char	*string();char	*dev_unit_file();char	*pathname();char	*server_path();/* * */intxopen(str, how)	char    *str;	int	how;{	register char *p;	char	dev[DEV_NAME_LEN+1];	char	filename[FILE_NAME_LEN+1];	char	server[SERVER_NAME_LEN+1];	char	pathname[PATHNAME_LEN+1];	int	ctlr,	unit,	part;	if ((p = dev_unit_file(str, dev, &ctlr, &unit, &part, filename)) !=	    (char *)-1)	{		if (*p != '\0')	{			printf ("garbage after filename '%s'\n",				filename);			return (-1);		}		return (open_dev_file(dev, ctlr, unit, part, filename));	} else if ((p = server_path(str, server, pathname)) !=	    (char *)-1)	{		if (*p != '\0')	{			printf ("garbage after pathname '%s'\n",				pathname);			return (-1);		}		return (open_server_path(server, pathname));	} else	{		printf ("syntax error: try again\n");		return (-1);	}}/* * Parse the construct: * *	<dev_unit_file> -> <dev>(<ctlr>, <unit>, <part>) <filename> */char	*dev_unit_file(str, dev, ctlr, unit, part, filename)	char	*str;	char	*dev;	int	*ctlr;	int	*unit;	int	*part;	char	*filename;{	char	*p;	if ((p = string(str, dev)) == (char *)-1)	{		printf ("%s: bad device\n", str);		return ((char *)-1);	}	if (*p++ != '(')	{		return ((char *)-1);	}	p = gethex(p, ctlr);	if (*p++ != ',')	{		return ((char *)-1);	}	p = gethex(p, unit);	if (*p++ != ',')	{		return ((char *)-1);	}	p = gethex(p, part);	if (*p++ != ')')	{		return ((char *)-1);	}	if ((p = string(p, filename)) == (char *)-1)	{		return ((char *)-1);	}	return (p);}/* * Parses: * *	<server_path> -> <server> : <pathname> */char	*server_path(str, server, path)	char	*str;	char	*server;	char	*path;{	char	*p;	if ((p = string(str, server)) == (char *)-1)	{		printf("%s: bad server name\n", str);		return ((char *)-1);	}	if (*p++ != ':')	{		printf("%s: no ':' following server name\n", str);		return ((char *)-1);	}	if ((p = pathname(p, path)) == (char *)-1)	{		printf("%s: bad pathname\n", str);		return ((char *)-1);	}	return (0);}/* * Parses: *	<path> =  / <string> */char	*pathname(str, path)	char	*str;	char	*path;{	char	*p, *p1;	for (p = str, p1 = path; *p; p++, p1++)		*p1 = *p;	*p1 = '\0';	return (p);}/* * Parses: * *	<string> -> {[a-z][A-Z][0-9][._-,:+%]}* * * Terminates the output string with a zero byte. * Returns: pointer to the next character after the end of * the string, or -1 if there is no valid character in the * string. */char	*string(str, dest)	char	*str;	char	*dest;{	char	*p, *p1;	for (p = str; *p == ' '; p++);	for (p1 = dest; *p; p++, p1++)	{		if ((*p >= 'a') && (*p <= 'z'))			*p1 = *p;		else if ((*p >= 'A') && (*p <= 'Z'))			*p1 = *p;		else if ((*p >= '0') && (*p <= '9'))			*p1 = *p;		else if ((*p == '.') || (*p == '_') || (*p == '-') ||			 (*p == ',') || (*p == ':') || (*p == '+') ||			 (*p == '%') || (*p == '*') || (*p == '/'))				*p1 = *p;		else			break;	}	if (p1 == dest)		{	 /* No valid characters. */		dprint(dump_debug, 6,			"string: no valid characters p 0x%x p1 0x%x\n", p, p1);		*p1 = '\0';		return ((char *)-1);	}	*p1 = '\0';	return (p);	/* Next character after string */}open_server_path(server, path)	char	*server;	char	*path;{	return (-1);}intopen_dev_file(dev, ctlr, unit, part, file)	char	*dev;	int	ctlr;	int	unit;	int	part;	char	*file;{	return (-1);}fopen(fnamep, fmode, cmode)	char *fnamep;	int fmode;	int cmode;{}boot_lseek(fd, off, sbase)	int	fd;	register off_t  off;	int    sbase;{	struct iob *fp;	u.u_error = getvnodefp(fd, &fp);	if (u.u_error) {#ifdef		DUMP_DEBUG		dprint(dump_debug, 6, "lseek: bad fd 0x%x\n", fd);#endif		DUMP_DEBUG		return (-1);	}	if (((struct vnode *)fp->i_ino.i_devvp)->v_type == VFIFO) {		u.u_error = ESPIPE;		return (-1);	}	switch (sbase) {	case L_INCR:		fp->i_offset += off;		break;	case L_XTND: {		struct vattr vattr;		u.u_error = VOP_GETATTR((struct vnode *)fp->i_ino.i_devvp,		    &vattr, u.u_cred);		if (u.u_error)			return (-1);		fp->i_offset = off + vattr.va_size;		break;	}	case L_SET:		fp->i_offset = off;		break;	default:		u.u_error = EINVAL;	}	u.u_r.r_off = fp->i_offset;#ifdef	DUMP_DEBUG1	dprint(dump_debug, 6, "lseek: new offset 0x%x\n", fp->i_offset);#endif	DUMP_DEBUG1	return (0);}/*ARGSUSED*/boot_read(fdesc, buf, count)	int	fdesc;	register char   *buf;	int	count;{	int	this_count = 0x2000;	int	total_read = 0;	int	this_read = 0;	int	cc;#ifdef	DUMP_DEBUG1	dprint(dump_debug, 6, "read(fdesc %x, buf %x, count %x)\n",		fdesc, buf, count);#endif	DUMP_DEBUG1	while (count > 0)	{		cc = (count > this_count) ? this_count : count;		this_read = xread(fdesc, buf, cc);		if (u.u_error != 0)  {#ifdef	DEBUG			printf("boot_read: u.u_error = %d!\n", u.u_error);#endif	DEBUG			return (-1);		}		if (this_read == 0)  {		/* EOF */#ifdef	DEBUG			printf("boot_read: this_read = 0, total_read = %d\n",			    total_read);#endif	DEBUG			break;		}		count -= this_read;		buf += this_read;		total_read += this_read;		feedback();	/* Show activity */	}#ifdef	DEBUG	printf("boot_read: returning total_read = %d\n", total_read);#endif	DEBUG	return (total_read);}xread(fdesc, buf, count)	int	fdesc;	register char   *buf;	int	count;{	struct uio auio;	struct iovec aiov;#ifdef	DUMP_DEBUG1	dprint(dump_debug, 6,		"xread(fdesc %x, buf %x, count %x)\n",		fdesc, buf, count);#endif	DUMP_DEBUG1	aiov.iov_base = buf;	aiov.iov_len = count;	auio.uio_iov = &aiov;	auio.uio_iovcnt = 1;	/*	 *  It's all dark, really.	 */	auio.uio_seg = UIOSEG_KERNEL;	rwuio(fdesc, &auio, UIO_READ);	return (count-auio.uio_resid);}xclose(fdesc)	int	fdesc;{#ifdef	lint	fdesc = fdesc;#endif	lint}exit(){	_stop((char *)0);}_stop(s)	char    *s;{	if (s) printf("%s\n", s);	_exit();}panic(s)	char    *s;{	_stop(s);}/* * Open a device.   No files involved at this point. */opendev(fdesc, file, how)	int	fdesc;	struct	iob	*file;	int	how;{#ifdef OPENPROMS	if (prom_getversion() > 0)		return (obp_opendev(fdesc, file, how));#endif#ifndef sun4m	/*	 * Only set ctlr field if device is an IPI ctlr.  This allows	 * UNIX to be booted from multiple IPI ctlrs.  Can't set	 * ctlr number in this fashion if sd device (such as CD-ROM)	 * since the bits are used for unit info (see below)	 */	if (major(file->i_ino.i_dev) == 1)		file->i_si.si_ctlr = minor(file->i_ino.i_dev) >> 6;	/* XXX	 * Purposely don't "AND" unit with 0x7, might break	 * other drivers. Driver must get rid of the ctlr	 * explicitly.	 */	file->i_si.si_unit = minor(file->i_ino.i_dev) >> 3;	file->i_si.si_boff = minor(file->i_ino.i_dev) & 0x7;#ifndef OPENPROMS	/*	 * XXX HACK HACK HACK - the non-OPENPROM "sd" driver (among others)	 * assumes that it will be given "unit" as a PROM style	 * (target * 8) + lun number.  But getblockdev() needs to give	 * a real UNIX minor number (or loose some bits), thus it does	 * if ("sd") unit = (((unit & 0xF8) >> 2) | (unit & 0x01));	 * Now we convert the si_unit for the "sd" driver back into	 * (target * 8) + lun.	 * This HACK is here instead of fixing "sd" driver so we	 * don't have to fix tpboot and standalone copy (may they die soon!)	 * as this work is being done betwee 4.1 preFCS and FCS!!!	 */	/* HARDCODE "sd" major number */	if (major(file->i_ino.i_dev) == 7)		file->i_si.si_unit =		    ((minor(file->i_ino.i_dev) & 0xF0) >> 1) |		    ((minor(file->i_ino.i_dev) & 0x08) >> 3);#endif OPENPROMS	if (devopen(&file->i_si)) {		file->i_flgs = 0;#ifdef		DUMP_DEBUG1		dprint(dump_debug, 6, "opendev: bad open\n");#endif		DUMP_DEBUG1		return (-1);	/* if devopen fails, open fails */	}	file->i_flgs |= how+1;	file->i_cc = 0;	file->i_offset = 0;	return (fdesc+3);#endif !sun4m}#ifdef OPENPROMS/* * Open a device.   No files involved at this point. */obp_opendev(fdesc, file, how)	int	fdesc;	struct	iob	*file;	int	how;{	register struct boottab *dp;	register struct binfo *bd;	register int	phandle;	char	 devtype[32];	dp = file->i_boottab;	bd = (struct binfo *)kmem_alloc(sizeof (struct binfo));	bzero((caddr_t)bd, sizeof (struct binfo));	(struct binfo *)file->i_si.si_devdata = bd;	bd->name = dp->b_desc;	bd->ihandle = 0;	if (devopen(&file->i_si)) {		file->i_flgs = 0;#ifdef		DUMP_DEBUG1		dprint(dump_debug, 6, "opendev: bad open\n");#endif		DUMP_DEBUG1		return (-1);	/* if devopen fails, open fails */	}	/*	 * find out if the open device is a block device	 */	phandle = prom_getphandle(bd->ihandle);	devtype[0] = '\0';	(void)prom_getprop(phandle, "device_type", devtype);	switch (dp->b_dev[0]) {	case 'b':		if ((strcmp (devtype, "block") != 0) &&		    (strcmp (devtype, "byte") != 0)) {			devclose(&file->i_si);			file->i_flgs = 0;#ifdef		DUMP_DEBUG			dprint(dump_debug, 6,			"opendev: open device is not a block or byte device\n");#endif		DUMP_DEBUG			return (-2);	/* if devopen fails, open fails */		}		break;	case 'n':		if (strcmp (devtype, "network") != 0) {			devclose(&file->i_si);			file->i_flgs = 0;#ifdef		DUMP_DEBUG			dprint(dump_debug, 6,			    "opendev: open device is not a network device\n");#endif		DUMP_DEBUG			return (-2);	/* if devopen fails, open fails */		}		break;	default:		devclose(&file->i_si);		file->i_flgs = 0;#ifdef		DUMP_DEBUG		dprint(dump_debug, 6,		"opendev: open device is not a block, byte or net device\n");#endif		DUMP_DEBUG		return (-2);	/* if devopen fails, open fails */	}	file->i_flgs |= how+1;	file->i_cc = 0;	file->i_offset = 0;	return (fdesc+3);}#endifrwuio(fdesc, uio, rw)	int	fdesc;	register struct uio *uio;	enum uio_rw rw;{	register struct iob *file;	register struct iovec *iov;	int i;#ifdef	DUMP_DEBUG1	dprint(dump_debug, 6, "rwuio(fdesc 0x%x uio 0x%x rw 0x%x)\n",		fdesc, uio, rw);#endif	DUMP_DEBUG1	file = &iob[fdesc];	uio->uio_resid = 0;	/*	 * It's all dark, really.	 */	uio->uio_seg = UIOSEG_KERNEL;	iov = uio->uio_iov;	for (i = 0; i < uio->uio_iovcnt; i++) {		if (iov->iov_len < 0) {			u.u_error = EINVAL;#ifdef	DEBUG			printf("rwuio: EINVAL: iov_len = %d\n", iov->iov_len);#endif	DEBUG			return;		}		uio->uio_resid += iov->iov_len;		if (uio->uio_resid < 0) {			u.u_error = EINVAL;#ifdef	DEBUG			printf("rwuio: EINVAL: iov_len %d, uio_resid %d\n",			    iov->iov_len, uio->uio_resid);#endif	DEBUG			return;		}		iov++;	}	/*	 * file->i_offset should be set correctly by lseek.	 */	uio->uio_offset = file->i_offset;	uio->uio_fmode = 0 /* fp->f_flag */;	if ((i = vno_rw(file, rw, uio)) != 0) {#ifdef	DEBUG		printf("rwuio: EIO: error %d from vno_rw!\n", i);#endif	DEBUG		u.u_error = EIO;		return;	}	file->i_offset = uio->uio_offset;#ifdef	DUMP_DEBUG1	dprint(dump_debug, 6, "rwuio: new offset 0x%x\n", file->i_offset);#endif	DUMP_DEBUG1}vno_rw(fp, rw, uiop)	struct iob *fp;	enum uio_rw rw;	struct uio *uiop;{	struct vnode *vp;	register int error;	/*	 * We store a pointer to the vnode in i_devvp.	 */	vp = fp->i_ino.i_devvp;#ifdef	DUMP_DEBUG1	dprint(dump_debug, 6, "vno_rw: fp 0x%x vp 0x%x\n", fp, vp);#endif	DUMP_DEBUG1	if (vp->v_type == VREG) {		error = VOP_RDWR(vp, uiop, rw, IO_UNIT, u.u_cred);	} else if (vp->v_type == VFIFO) {		/*		 * NOTE: Kludge to ensure that FAPPEND stays set.		 *	  This ensures that fp->f_offset is always accurate.		 *		 *	fp->f_flag |= FAPPEND;		 */		/*		 * NOTE: Kludge to ensure 'no delay' bit passes thru		 */		error = VOP_RDWR(vp, uiop, rw, IO_APPEND, u.u_cred);	} else {		error = VOP_RDWR(vp, uiop, rw, 0, u.u_cred);	}	if (error)  {#ifdef	DEBUG		printf("vno_rw: returning error %d from VOP_RDWR, v_type ",		    error);		switch (vp->v_type)  {		case VREG:	printf("VREG\n"); break;		case VFIFO:	printf("VFIFO\n"); break;		default:	printf("default (%d)\n", vp->v_type); break;		}#endif	DEBUG		return (error);	}	return (0);}/* * Get the file structure entry for the file descrpitor, but make sure * its a vnode. */intgetvnodefp(fd, fpp)	int fd;	struct iob **fpp;{	register struct iob *fp;#ifdef	NEVER	fp = getf(fd);	if (fp == (struct file *)0)		return (EBADF);	if (fp->f_type != DTYPE_VNODE)		return (EINVAL);#endif	NEVER	fp = &iob[fd];	*fpp = fp;	return (0);}#define		DIR_BUFF_LEN	512list_directory(dir)	char	*dir;{	char	buffer[DIR_BUFF_LEN];	long	basep;	int	directory;	struct	direct	*dp;#ifdef	DUMP_DEBUG	dprint(dump_debug, 6, "list_directory('%s')\n", dir);#endif	DUMP_DEBUG	if ((directory = open (dir, O_RDONLY)) == -1)	{		dprint(dump_debug, 10,			"list_directory: bad directory %s\n", dir);		return (-1);	}#ifdef	DUMP_DEBUG	dprint(dump_debug, 6,		"list_directory: directory '%s' fd 0x%x\n", dir, directory);#endif	DUMP_DEBUG	while (1)	{		if (getdirents(directory, buffer, DIR_BUFF_LEN, &basep) == -1) {#ifdef		DUMP_DEBUG		dprint(dump_debug, 10, "list_directory: bad getdirents\n");#endif		DUMP_DEBUG		return (-1);		}		if (u.u_r.r_val1 == 0)	{#ifdef			DUMP_DEBUG			dprint(dump_debug, 6,				"list_directory: end of directory\n");#endif			DUMP_DEBUG			return (0);		}		for (dp = (struct direct *)buffer; dp < (struct direct *)		    ((char *)buffer + u.u_r.r_val1); /* enpty */) {			printf("ino 0x%x: name '%s'\n",			dp->d_fileno, &(dp->d_name[0]));			dp = (struct direct *)((char *)dp + dp->d_reclen);		}	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?