/* @(#)sys3.c	1.4 */#include "sys/param.h"#include "sys/types.h"#include "sys/sysmacros.h"#include "sys/systm.h"#include "sys/mount.h"#include "sys/ino.h"#include "sys/buf.h"#include "sys/filsys.h"#include "sys/dir.h"#include "sys/signal.h"#include "sys/user.h"#include "sys/errno.h"#include "sys/inode.h"#include "sys/file.h"#include "sys/conf.h"#include "sys/stat.h"#include "sys/ttold.h"#include "sys/var.h"#ifdef UCB_NET#include "sys/termio.h"#include "net/misc.h"#include "net/socketvar.h"#endif/* * the fstat system call. */fstat(){	register struct file *fp;	register struct a {		int	fdes;		struct stat *sb;	} *uap;	uap = (struct a *)u.u_ap;	fp = getf(uap->fdes);	if(fp == NULL)		return;#ifdef UCB_NET	if (fp->f_flag & FSOCKET)		u.u_error = sostat((struct socket *)fp->f_socket, uap->sb);	else#endif	stat1(fp->f_inode, uap->sb);}/* * the stat system call. */stat(){	register struct inode *ip;	register struct a {		char	*fname;		struct stat *sb;	} *uap;	uap = (struct a *)u.u_ap;	ip = namei(uchar, 0);	if(ip == NULL)		return;	stat1(ip, uap->sb);	iput(ip);}/* * The basic routine for fstat and stat: * get the inode and pass appropriate parts back. */stat1(ip, ub)register struct inode *ip;struct stat *ub;{	register struct dinode *dp;	register struct buf *bp;	register struct stat *dsp;	struct stat ds;	if(ip->i_flag&(IACC|IUPD|ICHG))		iupdat(ip, &time, &time);	/*	 * first copy from inode table	 */	dsp = &ds;	dsp->st_dev = brdev(ip->i_dev);	dsp->st_ino = ip->i_number;	dsp->st_mode = ip->i_mode;	dsp->st_nlink = ip->i_nlink;	dsp->st_uid = ip->i_uid;	dsp->st_gid = ip->i_gid;	dsp->st_rdev = (dev_t)ip->i_rdev;	dsp->st_size = ip->i_size;	/*	 * next the dates in the disk	 */	bp = bread(ip->i_dev, FsITOD(ip->i_dev, ip->i_number));	dp = bp->b_un.b_dino;	dp += FsITOO(ip->i_dev, ip->i_number);	dsp->st_atime = dp->di_atime;	dsp->st_mtime = dp->di_mtime;	dsp->st_ctime = dp->di_ctime;	brelse(bp);	if (copyout((caddr_t)dsp, (caddr_t)ub, sizeof(ds)) < 0)		u.u_error = EFAULT;}/* * the dup system call. */dup(){	register struct file *fp;	int i;	struct a {		int	fdes;	} *uap;	uap = (struct a *)u.u_ap;	fp = getf(uap->fdes);	if(fp == NULL)		return;	if ((i = ufalloc(0)) < 0)		return;	u.u_ofile[i] = fp;	fp->f_count++;}/* * the file control system call. */fcntl(){	register struct file *fp;	register struct a {		int	fdes;		int	cmd;		int	arg;	} *uap;	register i;	register struct user *up;	up = &u;	uap = (struct a *)up->u_ap;	fp = getf(uap->fdes);	if (fp == NULL)		return;	switch(uap->cmd) {	case 0:		i = uap->arg;		if (i < 0 || i > NOFILE) {			up->u_error = EINVAL;			return;		}		if ((i = ufalloc(i)) < 0)			return;		up->u_ofile[i] = fp;		fp->f_count++;		break;	case 1:		up->u_rval1 = up->u_pofile[uap->fdes];		break;	case 2:		up->u_pofile[uap->fdes] = uap->arg;		break;	case 3:		up->u_rval1 = fp->f_flag+FOPEN;		break;	case 4:		fp->f_flag &= (FREAD|FWRITE);		fp->f_flag |= (uap->arg-FOPEN) & ~(FREAD|FWRITE);		break;	default:		up->u_error = EINVAL;	}}/* * character special i/o control */ioctl(){	register struct file *fp;	register struct inode *ip;	register struct a {		int	fdes;		int	cmd;		int	arg;	} *uap;	register dev_t dev;#ifdef UCB_NET	register unsigned fmt;#endif	uap = (struct a *)u.u_ap;	if ((fp = getf(uap->fdes)) == NULL)		return;#ifdef UCB_NET	if (fp->f_flag & FSOCKET) {		soioctl((struct socket *)fp->f_socket, uap->cmd, (caddr_t)uap->arg);		return;	}#endif	ip = fp->f_inode;#ifdef UCB_NET	fmt = ip->i_mode & IFMT;	if (fmt != IFCHR) {		if (uap->cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR			|| fmt == IFIFO)) {			off_t nread;			if ((ip->i_mode&IFMT)==IFIFO)				nread = ip->i_size;			else				nread = ip->i_size - fp->f_offset;			if (copyout((caddr_t)&nread, (caddr_t)uap->arg,				 sizeof(off_t)))				u.u_error = EFAULT;		} else if (uap->cmd == FIONBIO /*|| uap->cmd == FIOASYNC*/)			return;		else			u.u_error = ENOTTY;		return;	}#else	if ((ip->i_mode&IFMT) != IFCHR) {		u.u_error = ENOTTY;		return;	}#endif UCB_NET	dev = (dev_t)ip->i_rdev;	(*cdevsw[(short)major(dev)].d_ioctl)(minor(dev),uap->cmd,uap->arg,fp->f_flag);}/* * old stty and gtty */stty(){	register struct a {		int	fdes;		int	arg;		int	narg;	} *uap;	uap = (struct a *)u.u_ap;	uap->narg = uap->arg;	uap->arg = TIOCSETP;	ioctl();}gtty(){	register struct a {		int	fdes;		int	arg;		int	narg;	} *uap;	uap = (struct a *)u.u_ap;	uap->narg = uap->arg;	uap->arg = TIOCGETP;	ioctl();}/* * the mount system call. */smount(){	register struct user *up;	register dev_t dev;	register struct inode *ip;	register struct mount *mp;	struct mount *smp;	register struct filsys *fp;	struct inode *bip = NULL;	register struct a {		char	*fspec;		char	*freg;		int	ronly;	} *uap;	up = &u;	uap = (struct a *)up->u_ap;	if(!suser())		return;	ip = namei(uchar, 0);	if(ip == NULL)		return;	if((ip->i_mode&IFMT) != IFBLK)		up->u_error = ENOTBLK;	dev = (dev_t)ip->i_rdev;	if(bmajor(dev) >= bdevcnt)		if (!up->u_error)			up->u_error = ENXIO;	if (up->u_error)		goto out;	bip = ip;	up->u_dirp = (caddr_t)uap->freg;	ip = namei(uchar, 0);	if(ip == NULL) {		iput(bip);		return;	}	if ((ip->i_mode&IFMT) != IFDIR) {		up->u_error = ENOTDIR;		goto out;	}	if (ip->i_count != 1)		goto out;	if (ip->i_number == ROOTINO)		goto out;	smp = NULL;	for(mp = &mount[0]; mp < (struct mount *)v.ve_mount; mp++) {		if(mp->m_flags != MFREE) {			if (brdev(dev) == brdev(mp->m_dev))				goto out;		} else		if(smp == NULL)			smp = mp;	}	mp = smp;	if(mp == NULL)		goto out;	mp->m_flags = MINTER;	mp->m_dev = brdev(dev);	(*bdevsw[(short)bmajor(dev)].d_open)(minor(dev),		uap->ronly ?  (FREAD | FKERNEL) : (FREAD | FWRITE | FKERNEL));	if(up->u_error)		goto out1;	mp->m_bufp = geteblk();	fp = mp->m_bufp->b_un.b_filsys;	up->u_offset = SUPERBOFF;	up->u_count = sizeof(struct filsys);	up->u_base = (caddr_t)fp;	up->u_segflg = 1;	readi(bip);	if (up->u_error) {		brelse(mp->m_bufp);		goto out1;	}	mp->m_inodp = ip;	mp->m_flags = MINUSE;	if (fp->s_magic != FsMAGIC)		fp->s_type = Fs1b;	/* assume old file system */	if (fp->s_type == Fs2b)		mp->m_dev |= Fs2BLK;#if FsTYPE == 4	if (fp->s_type == Fs4b)		mp->m_dev |= Fs4BLK;#endif	if (brdev(pipedev) == brdev(mp->m_dev))		pipedev = mp->m_dev;	fp->s_ilock = 0;	fp->s_flock = 0;	fp->s_ninode = 0;	fp->s_inode[0] = 0;	fp->s_ronly = uap->ronly & 1;	if (mp->m_mount = iget(mp->m_dev, ROOTINO))		prele(mp->m_mount);	else {		brelse(mp->m_bufp);		goto out1;	}	ip->i_flag |= IMOUNT;	iput(bip);	prele(ip);	return;out1:	mp->m_flags = MFREE;out:	if (bip != NULL)		iput(bip);	if (up->u_error == 0)		up->u_error = EBUSY;	iput(ip);}/* * the umount system call. */sumount(){	register dev_t dev;	register struct inode *ip;	register struct mount *mp;	register struct a {		char	*fspec;	};	if(!suser())		return;	dev = getmdev();	if(u.u_error)		return;	for(mp = &mount[0]; mp < (struct mount *)v.ve_mount; mp++)		if(mp->m_flags == MINUSE && brdev(dev) == brdev(mp->m_dev))			goto found;	u.u_error = EINVAL;	return;found:	dev = mp->m_dev;	(void) xumount(dev);	/* remove unused sticky files from text table */	update();	if (mp->m_mount) {		plock(mp->m_mount);		iput(mp->m_mount);		mp->m_mount = NULL;	}	for(ip = &inode[0]; ip < (struct inode *)v.ve_inode; ip++)		if(ip->i_number != 0 && dev == ip->i_dev) {			u.u_error = EBUSY;			return;		}	(*bdevsw[(short)bmajor(dev)].d_close)(minor(dev), FKERNEL);	binval(dev);	ip = mp->m_inodp;	ip->i_flag &= ~IMOUNT;	plock(ip);	iput(ip);	brelse(mp->m_bufp);	mp->m_bufp = NULL;	mp->m_flags = MFREE;}/* * Common code for mount and umount. * Check that the user's argument is a reasonable * thing on which to mount, and return the device number if so. */dev_tgetmdev(){	dev_t dev;	register struct inode *ip;	ip = namei(uchar, 0);	if(ip == NULL)		return(NODEV);	if((ip->i_mode&IFMT) != IFBLK)		u.u_error = ENOTBLK;	dev = (dev_t)ip->i_rdev;	if(bmajor(dev) >= bdevcnt)		u.u_error = ENXIO;	iput(ip);	return(dev);}