--- /dev/null
+/* vfs_syscalls.c 3.1 %H% */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/ino.h"
+#include "../h/reg.h"
+#include "../h/buf.h"
+#include "../h/filsys.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/stat.h"
+
+/*
+ * 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;
+ stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0);
+}
+
+/*
+ * 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, (off_t)0);
+ iput(ip);
+}
+
+/*
+ * The basic routine for fstat and stat:
+ * get the inode and pass appropriate parts back.
+ */
+stat1(ip, ub, pipeadj)
+register struct inode *ip;
+struct stat *ub;
+off_t pipeadj;
+{
+ register struct dinode *dp;
+ register struct buf *bp;
+ struct stat ds;
+
+ iupdat(ip, &time, &time);
+ /*
+ * first copy from inode table
+ */
+ ds.st_dev = ip->i_dev;
+ ds.st_ino = ip->i_number;
+ ds.st_mode = ip->i_mode;
+ ds.st_nlink = ip->i_nlink;
+ ds.st_uid = ip->i_uid;
+ ds.st_gid = ip->i_gid;
+ ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_size = ip->i_size - pipeadj;
+ /*
+ * next the dates in the disk
+ */
+ bp = bread(ip->i_dev, itod(ip->i_number));
+ dp = bp->b_un.b_dino;
+ dp += itoo(ip->i_number);
+ ds.st_atime = dp->di_atime;
+ ds.st_mtime = dp->di_mtime;
+ ds.st_ctime = dp->di_ctime;
+ brelse(bp);
+ if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
+ u.u_error = EFAULT;
+}
+
+/*
+ * the dup system call.
+ */
+dup()
+{
+ register struct file *fp;
+ register struct a {
+ int fdes;
+ int fdes2;
+ } *uap;
+ register i, m;
+
+ uap = (struct a *)u.u_ap;
+ m = uap->fdes & ~077;
+ uap->fdes &= 077;
+ fp = getf(uap->fdes);
+ if(fp == NULL)
+ return;
+ if ((m&0100) == 0) {
+ if ((i = ufalloc()) < 0)
+ return;
+ } else {
+ i = uap->fdes2;
+ if (i<0 || i>=NOFILE) {
+ u.u_error = EBADF;
+ return;
+ }
+ if (u.u_vrpages[i]) {
+ u.u_error = ETXTBSY;
+ return;
+ }
+ u.u_r.r_val1 = i;
+ }
+ if (i!=uap->fdes) {
+ if (u.u_ofile[i]!=NULL)
+ closef(u.u_ofile[i]);
+ u.u_ofile[i] = fp;
+ fp->f_count++;
+ }
+}
+
+/*
+ * the mount system call.
+ */
+smount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct mount *smp;
+ register struct filsys *fp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ char *freg;
+ int ronly;
+ } *uap;
+
+ uap = (struct a *)u.u_ap;
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ u.u_dirp = (caddr_t)uap->freg;
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return;
+ if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
+ goto out;
+ smp = NULL;
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
+ if(mp->m_bufp != NULL) {
+ if(dev == mp->m_dev)
+ goto out;
+ } else
+ if(smp == NULL)
+ smp = mp;
+ }
+ mp = smp;
+ if(mp == NULL)
+ goto out;
+ (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
+ if(u.u_error)
+ goto out;
+ bp = bread(dev, SUPERB);
+ if(u.u_error) {
+ brelse(bp);
+ goto out1;
+ }
+ mp->m_inodp = ip;
+ mp->m_dev = dev;
+ mp->m_bufp = geteblk();
+ bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
+ fp = mp->m_bufp->b_un.b_filsys;
+ fp->s_ilock = 0;
+ fp->s_flock = 0;
+ fp->s_ronly = uap->ronly & 1;
+ fp->s_nbehind = 0;
+ fp->s_lasti = 1;
+ brelse(bp);
+ ip->i_flag |= IMOUNT;
+ prele(ip);
+ return;
+
+out:
+ u.u_error = EBUSY;
+out1:
+ iput(ip);
+}
+
+/*
+ * the umount system call.
+ */
+sumount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ };
+
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ xumount(dev); /* remove unused sticky files from text table */
+ update();
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ if(mp->m_bufp != NULL && dev == mp->m_dev)
+ goto found;
+ u.u_error = EINVAL;
+ return;
+
+found:
+ for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+ if(ip->i_number != 0 && dev == ip->i_dev) {
+ u.u_error = EBUSY;
+ return;
+ }
+ (*bdevsw[major(dev)].d_close)(dev, 0);
+ ip = mp->m_inodp;
+ ip->i_flag &= ~IMOUNT;
+ plock(ip);
+ iput(ip);
+ bp = mp->m_bufp;
+ mp->m_bufp = NULL;
+ brelse(bp);
+}
+
+/*
+ * 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;
+
+#ifdef UCB
+ if (!suser())
+ return(NODEV);
+#endif
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return(NODEV);
+ if((ip->i_mode&IFMT) != IFBLK)
+ u.u_error = ENOTBLK;
+ dev = (dev_t)ip->i_un.i_rdev;
+ if(major(dev) >= nblkdev)
+ u.u_error = ENXIO;
+ iput(ip);
+ return(dev);
+}
--- /dev/null
+/* ffs_vnops.c 3.1 %H% */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/ino.h"
+#include "../h/reg.h"
+#include "../h/buf.h"
+#include "../h/filsys.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/stat.h"
+
+/*
+ * 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;
+ stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0);
+}
+
+/*
+ * 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, (off_t)0);
+ iput(ip);
+}
+
+/*
+ * The basic routine for fstat and stat:
+ * get the inode and pass appropriate parts back.
+ */
+stat1(ip, ub, pipeadj)
+register struct inode *ip;
+struct stat *ub;
+off_t pipeadj;
+{
+ register struct dinode *dp;
+ register struct buf *bp;
+ struct stat ds;
+
+ iupdat(ip, &time, &time);
+ /*
+ * first copy from inode table
+ */
+ ds.st_dev = ip->i_dev;
+ ds.st_ino = ip->i_number;
+ ds.st_mode = ip->i_mode;
+ ds.st_nlink = ip->i_nlink;
+ ds.st_uid = ip->i_uid;
+ ds.st_gid = ip->i_gid;
+ ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_size = ip->i_size - pipeadj;
+ /*
+ * next the dates in the disk
+ */
+ bp = bread(ip->i_dev, itod(ip->i_number));
+ dp = bp->b_un.b_dino;
+ dp += itoo(ip->i_number);
+ ds.st_atime = dp->di_atime;
+ ds.st_mtime = dp->di_mtime;
+ ds.st_ctime = dp->di_ctime;
+ brelse(bp);
+ if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
+ u.u_error = EFAULT;
+}
+
+/*
+ * the dup system call.
+ */
+dup()
+{
+ register struct file *fp;
+ register struct a {
+ int fdes;
+ int fdes2;
+ } *uap;
+ register i, m;
+
+ uap = (struct a *)u.u_ap;
+ m = uap->fdes & ~077;
+ uap->fdes &= 077;
+ fp = getf(uap->fdes);
+ if(fp == NULL)
+ return;
+ if ((m&0100) == 0) {
+ if ((i = ufalloc()) < 0)
+ return;
+ } else {
+ i = uap->fdes2;
+ if (i<0 || i>=NOFILE) {
+ u.u_error = EBADF;
+ return;
+ }
+ if (u.u_vrpages[i]) {
+ u.u_error = ETXTBSY;
+ return;
+ }
+ u.u_r.r_val1 = i;
+ }
+ if (i!=uap->fdes) {
+ if (u.u_ofile[i]!=NULL)
+ closef(u.u_ofile[i]);
+ u.u_ofile[i] = fp;
+ fp->f_count++;
+ }
+}
+
+/*
+ * the mount system call.
+ */
+smount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct mount *smp;
+ register struct filsys *fp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ char *freg;
+ int ronly;
+ } *uap;
+
+ uap = (struct a *)u.u_ap;
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ u.u_dirp = (caddr_t)uap->freg;
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return;
+ if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
+ goto out;
+ smp = NULL;
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
+ if(mp->m_bufp != NULL) {
+ if(dev == mp->m_dev)
+ goto out;
+ } else
+ if(smp == NULL)
+ smp = mp;
+ }
+ mp = smp;
+ if(mp == NULL)
+ goto out;
+ (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
+ if(u.u_error)
+ goto out;
+ bp = bread(dev, SUPERB);
+ if(u.u_error) {
+ brelse(bp);
+ goto out1;
+ }
+ mp->m_inodp = ip;
+ mp->m_dev = dev;
+ mp->m_bufp = geteblk();
+ bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
+ fp = mp->m_bufp->b_un.b_filsys;
+ fp->s_ilock = 0;
+ fp->s_flock = 0;
+ fp->s_ronly = uap->ronly & 1;
+ fp->s_nbehind = 0;
+ fp->s_lasti = 1;
+ brelse(bp);
+ ip->i_flag |= IMOUNT;
+ prele(ip);
+ return;
+
+out:
+ u.u_error = EBUSY;
+out1:
+ iput(ip);
+}
+
+/*
+ * the umount system call.
+ */
+sumount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ };
+
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ xumount(dev); /* remove unused sticky files from text table */
+ update();
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ if(mp->m_bufp != NULL && dev == mp->m_dev)
+ goto found;
+ u.u_error = EINVAL;
+ return;
+
+found:
+ for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+ if(ip->i_number != 0 && dev == ip->i_dev) {
+ u.u_error = EBUSY;
+ return;
+ }
+ (*bdevsw[major(dev)].d_close)(dev, 0);
+ ip = mp->m_inodp;
+ ip->i_flag &= ~IMOUNT;
+ plock(ip);
+ iput(ip);
+ bp = mp->m_bufp;
+ mp->m_bufp = NULL;
+ brelse(bp);
+}
+
+/*
+ * 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;
+
+#ifdef UCB
+ if (!suser())
+ return(NODEV);
+#endif
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return(NODEV);
+ if((ip->i_mode&IFMT) != IFBLK)
+ u.u_error = ENOTBLK;
+ dev = (dev_t)ip->i_un.i_rdev;
+ if(major(dev) >= nblkdev)
+ u.u_error = ENXIO;
+ iput(ip);
+ return(dev);
+}
--- /dev/null
+/* ufs_vnops.c 3.1 %H% */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/ino.h"
+#include "../h/reg.h"
+#include "../h/buf.h"
+#include "../h/filsys.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/stat.h"
+
+/*
+ * 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;
+ stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0);
+}
+
+/*
+ * 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, (off_t)0);
+ iput(ip);
+}
+
+/*
+ * The basic routine for fstat and stat:
+ * get the inode and pass appropriate parts back.
+ */
+stat1(ip, ub, pipeadj)
+register struct inode *ip;
+struct stat *ub;
+off_t pipeadj;
+{
+ register struct dinode *dp;
+ register struct buf *bp;
+ struct stat ds;
+
+ iupdat(ip, &time, &time);
+ /*
+ * first copy from inode table
+ */
+ ds.st_dev = ip->i_dev;
+ ds.st_ino = ip->i_number;
+ ds.st_mode = ip->i_mode;
+ ds.st_nlink = ip->i_nlink;
+ ds.st_uid = ip->i_uid;
+ ds.st_gid = ip->i_gid;
+ ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_size = ip->i_size - pipeadj;
+ /*
+ * next the dates in the disk
+ */
+ bp = bread(ip->i_dev, itod(ip->i_number));
+ dp = bp->b_un.b_dino;
+ dp += itoo(ip->i_number);
+ ds.st_atime = dp->di_atime;
+ ds.st_mtime = dp->di_mtime;
+ ds.st_ctime = dp->di_ctime;
+ brelse(bp);
+ if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
+ u.u_error = EFAULT;
+}
+
+/*
+ * the dup system call.
+ */
+dup()
+{
+ register struct file *fp;
+ register struct a {
+ int fdes;
+ int fdes2;
+ } *uap;
+ register i, m;
+
+ uap = (struct a *)u.u_ap;
+ m = uap->fdes & ~077;
+ uap->fdes &= 077;
+ fp = getf(uap->fdes);
+ if(fp == NULL)
+ return;
+ if ((m&0100) == 0) {
+ if ((i = ufalloc()) < 0)
+ return;
+ } else {
+ i = uap->fdes2;
+ if (i<0 || i>=NOFILE) {
+ u.u_error = EBADF;
+ return;
+ }
+ if (u.u_vrpages[i]) {
+ u.u_error = ETXTBSY;
+ return;
+ }
+ u.u_r.r_val1 = i;
+ }
+ if (i!=uap->fdes) {
+ if (u.u_ofile[i]!=NULL)
+ closef(u.u_ofile[i]);
+ u.u_ofile[i] = fp;
+ fp->f_count++;
+ }
+}
+
+/*
+ * the mount system call.
+ */
+smount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct mount *smp;
+ register struct filsys *fp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ char *freg;
+ int ronly;
+ } *uap;
+
+ uap = (struct a *)u.u_ap;
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ u.u_dirp = (caddr_t)uap->freg;
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return;
+ if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
+ goto out;
+ smp = NULL;
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
+ if(mp->m_bufp != NULL) {
+ if(dev == mp->m_dev)
+ goto out;
+ } else
+ if(smp == NULL)
+ smp = mp;
+ }
+ mp = smp;
+ if(mp == NULL)
+ goto out;
+ (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
+ if(u.u_error)
+ goto out;
+ bp = bread(dev, SUPERB);
+ if(u.u_error) {
+ brelse(bp);
+ goto out1;
+ }
+ mp->m_inodp = ip;
+ mp->m_dev = dev;
+ mp->m_bufp = geteblk();
+ bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
+ fp = mp->m_bufp->b_un.b_filsys;
+ fp->s_ilock = 0;
+ fp->s_flock = 0;
+ fp->s_ronly = uap->ronly & 1;
+ fp->s_nbehind = 0;
+ fp->s_lasti = 1;
+ brelse(bp);
+ ip->i_flag |= IMOUNT;
+ prele(ip);
+ return;
+
+out:
+ u.u_error = EBUSY;
+out1:
+ iput(ip);
+}
+
+/*
+ * the umount system call.
+ */
+sumount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ };
+
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ xumount(dev); /* remove unused sticky files from text table */
+ update();
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ if(mp->m_bufp != NULL && dev == mp->m_dev)
+ goto found;
+ u.u_error = EINVAL;
+ return;
+
+found:
+ for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+ if(ip->i_number != 0 && dev == ip->i_dev) {
+ u.u_error = EBUSY;
+ return;
+ }
+ (*bdevsw[major(dev)].d_close)(dev, 0);
+ ip = mp->m_inodp;
+ ip->i_flag &= ~IMOUNT;
+ plock(ip);
+ iput(ip);
+ bp = mp->m_bufp;
+ mp->m_bufp = NULL;
+ brelse(bp);
+}
+
+/*
+ * 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;
+
+#ifdef UCB
+ if (!suser())
+ return(NODEV);
+#endif
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return(NODEV);
+ if((ip->i_mode&IFMT) != IFBLK)
+ u.u_error = ENOTBLK;
+ dev = (dev_t)ip->i_un.i_rdev;
+ if(major(dev) >= nblkdev)
+ u.u_error = ENXIO;
+ iput(ip);
+ return(dev);
+}
--- /dev/null
+/* lfs_vnops.c 3.1 %H% */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/ino.h"
+#include "../h/reg.h"
+#include "../h/buf.h"
+#include "../h/filsys.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/stat.h"
+
+/*
+ * 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;
+ stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0);
+}
+
+/*
+ * 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, (off_t)0);
+ iput(ip);
+}
+
+/*
+ * The basic routine for fstat and stat:
+ * get the inode and pass appropriate parts back.
+ */
+stat1(ip, ub, pipeadj)
+register struct inode *ip;
+struct stat *ub;
+off_t pipeadj;
+{
+ register struct dinode *dp;
+ register struct buf *bp;
+ struct stat ds;
+
+ iupdat(ip, &time, &time);
+ /*
+ * first copy from inode table
+ */
+ ds.st_dev = ip->i_dev;
+ ds.st_ino = ip->i_number;
+ ds.st_mode = ip->i_mode;
+ ds.st_nlink = ip->i_nlink;
+ ds.st_uid = ip->i_uid;
+ ds.st_gid = ip->i_gid;
+ ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_size = ip->i_size - pipeadj;
+ /*
+ * next the dates in the disk
+ */
+ bp = bread(ip->i_dev, itod(ip->i_number));
+ dp = bp->b_un.b_dino;
+ dp += itoo(ip->i_number);
+ ds.st_atime = dp->di_atime;
+ ds.st_mtime = dp->di_mtime;
+ ds.st_ctime = dp->di_ctime;
+ brelse(bp);
+ if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
+ u.u_error = EFAULT;
+}
+
+/*
+ * the dup system call.
+ */
+dup()
+{
+ register struct file *fp;
+ register struct a {
+ int fdes;
+ int fdes2;
+ } *uap;
+ register i, m;
+
+ uap = (struct a *)u.u_ap;
+ m = uap->fdes & ~077;
+ uap->fdes &= 077;
+ fp = getf(uap->fdes);
+ if(fp == NULL)
+ return;
+ if ((m&0100) == 0) {
+ if ((i = ufalloc()) < 0)
+ return;
+ } else {
+ i = uap->fdes2;
+ if (i<0 || i>=NOFILE) {
+ u.u_error = EBADF;
+ return;
+ }
+ if (u.u_vrpages[i]) {
+ u.u_error = ETXTBSY;
+ return;
+ }
+ u.u_r.r_val1 = i;
+ }
+ if (i!=uap->fdes) {
+ if (u.u_ofile[i]!=NULL)
+ closef(u.u_ofile[i]);
+ u.u_ofile[i] = fp;
+ fp->f_count++;
+ }
+}
+
+/*
+ * the mount system call.
+ */
+smount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct mount *smp;
+ register struct filsys *fp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ char *freg;
+ int ronly;
+ } *uap;
+
+ uap = (struct a *)u.u_ap;
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ u.u_dirp = (caddr_t)uap->freg;
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return;
+ if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
+ goto out;
+ smp = NULL;
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
+ if(mp->m_bufp != NULL) {
+ if(dev == mp->m_dev)
+ goto out;
+ } else
+ if(smp == NULL)
+ smp = mp;
+ }
+ mp = smp;
+ if(mp == NULL)
+ goto out;
+ (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
+ if(u.u_error)
+ goto out;
+ bp = bread(dev, SUPERB);
+ if(u.u_error) {
+ brelse(bp);
+ goto out1;
+ }
+ mp->m_inodp = ip;
+ mp->m_dev = dev;
+ mp->m_bufp = geteblk();
+ bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
+ fp = mp->m_bufp->b_un.b_filsys;
+ fp->s_ilock = 0;
+ fp->s_flock = 0;
+ fp->s_ronly = uap->ronly & 1;
+ fp->s_nbehind = 0;
+ fp->s_lasti = 1;
+ brelse(bp);
+ ip->i_flag |= IMOUNT;
+ prele(ip);
+ return;
+
+out:
+ u.u_error = EBUSY;
+out1:
+ iput(ip);
+}
+
+/*
+ * the umount system call.
+ */
+sumount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ };
+
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ xumount(dev); /* remove unused sticky files from text table */
+ update();
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ if(mp->m_bufp != NULL && dev == mp->m_dev)
+ goto found;
+ u.u_error = EINVAL;
+ return;
+
+found:
+ for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+ if(ip->i_number != 0 && dev == ip->i_dev) {
+ u.u_error = EBUSY;
+ return;
+ }
+ (*bdevsw[major(dev)].d_close)(dev, 0);
+ ip = mp->m_inodp;
+ ip->i_flag &= ~IMOUNT;
+ plock(ip);
+ iput(ip);
+ bp = mp->m_bufp;
+ mp->m_bufp = NULL;
+ brelse(bp);
+}
+
+/*
+ * 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;
+
+#ifdef UCB
+ if (!suser())
+ return(NODEV);
+#endif
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return(NODEV);
+ if((ip->i_mode&IFMT) != IFBLK)
+ u.u_error = ENOTBLK;
+ dev = (dev_t)ip->i_un.i_rdev;
+ if(major(dev) >= nblkdev)
+ u.u_error = ENXIO;
+ iput(ip);
+ return(dev);
+}
--- /dev/null
+/* ufs_vnops.c 3.1 %H% */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/mount.h"
+#include "../h/ino.h"
+#include "../h/reg.h"
+#include "../h/buf.h"
+#include "../h/filsys.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/inode.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/stat.h"
+
+/*
+ * 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;
+ stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0);
+}
+
+/*
+ * 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, (off_t)0);
+ iput(ip);
+}
+
+/*
+ * The basic routine for fstat and stat:
+ * get the inode and pass appropriate parts back.
+ */
+stat1(ip, ub, pipeadj)
+register struct inode *ip;
+struct stat *ub;
+off_t pipeadj;
+{
+ register struct dinode *dp;
+ register struct buf *bp;
+ struct stat ds;
+
+ iupdat(ip, &time, &time);
+ /*
+ * first copy from inode table
+ */
+ ds.st_dev = ip->i_dev;
+ ds.st_ino = ip->i_number;
+ ds.st_mode = ip->i_mode;
+ ds.st_nlink = ip->i_nlink;
+ ds.st_uid = ip->i_uid;
+ ds.st_gid = ip->i_gid;
+ ds.st_rdev = (dev_t)ip->i_un.i_rdev;
+ ds.st_size = ip->i_size - pipeadj;
+ /*
+ * next the dates in the disk
+ */
+ bp = bread(ip->i_dev, itod(ip->i_number));
+ dp = bp->b_un.b_dino;
+ dp += itoo(ip->i_number);
+ ds.st_atime = dp->di_atime;
+ ds.st_mtime = dp->di_mtime;
+ ds.st_ctime = dp->di_ctime;
+ brelse(bp);
+ if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
+ u.u_error = EFAULT;
+}
+
+/*
+ * the dup system call.
+ */
+dup()
+{
+ register struct file *fp;
+ register struct a {
+ int fdes;
+ int fdes2;
+ } *uap;
+ register i, m;
+
+ uap = (struct a *)u.u_ap;
+ m = uap->fdes & ~077;
+ uap->fdes &= 077;
+ fp = getf(uap->fdes);
+ if(fp == NULL)
+ return;
+ if ((m&0100) == 0) {
+ if ((i = ufalloc()) < 0)
+ return;
+ } else {
+ i = uap->fdes2;
+ if (i<0 || i>=NOFILE) {
+ u.u_error = EBADF;
+ return;
+ }
+ if (u.u_vrpages[i]) {
+ u.u_error = ETXTBSY;
+ return;
+ }
+ u.u_r.r_val1 = i;
+ }
+ if (i!=uap->fdes) {
+ if (u.u_ofile[i]!=NULL)
+ closef(u.u_ofile[i]);
+ u.u_ofile[i] = fp;
+ fp->f_count++;
+ }
+}
+
+/*
+ * the mount system call.
+ */
+smount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct mount *smp;
+ register struct filsys *fp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ char *freg;
+ int ronly;
+ } *uap;
+
+ uap = (struct a *)u.u_ap;
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ u.u_dirp = (caddr_t)uap->freg;
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return;
+ if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
+ goto out;
+ smp = NULL;
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
+ if(mp->m_bufp != NULL) {
+ if(dev == mp->m_dev)
+ goto out;
+ } else
+ if(smp == NULL)
+ smp = mp;
+ }
+ mp = smp;
+ if(mp == NULL)
+ goto out;
+ (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
+ if(u.u_error)
+ goto out;
+ bp = bread(dev, SUPERB);
+ if(u.u_error) {
+ brelse(bp);
+ goto out1;
+ }
+ mp->m_inodp = ip;
+ mp->m_dev = dev;
+ mp->m_bufp = geteblk();
+ bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
+ fp = mp->m_bufp->b_un.b_filsys;
+ fp->s_ilock = 0;
+ fp->s_flock = 0;
+ fp->s_ronly = uap->ronly & 1;
+ fp->s_nbehind = 0;
+ fp->s_lasti = 1;
+ brelse(bp);
+ ip->i_flag |= IMOUNT;
+ prele(ip);
+ return;
+
+out:
+ u.u_error = EBUSY;
+out1:
+ iput(ip);
+}
+
+/*
+ * the umount system call.
+ */
+sumount()
+{
+ dev_t dev;
+ register struct inode *ip;
+ register struct mount *mp;
+ struct buf *bp;
+ register struct a {
+ char *fspec;
+ };
+
+ dev = getmdev();
+ if(u.u_error)
+ return;
+ xumount(dev); /* remove unused sticky files from text table */
+ update();
+ for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
+ if(mp->m_bufp != NULL && dev == mp->m_dev)
+ goto found;
+ u.u_error = EINVAL;
+ return;
+
+found:
+ for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
+ if(ip->i_number != 0 && dev == ip->i_dev) {
+ u.u_error = EBUSY;
+ return;
+ }
+ (*bdevsw[major(dev)].d_close)(dev, 0);
+ ip = mp->m_inodp;
+ ip->i_flag &= ~IMOUNT;
+ plock(ip);
+ iput(ip);
+ bp = mp->m_bufp;
+ mp->m_bufp = NULL;
+ brelse(bp);
+}
+
+/*
+ * 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;
+
+#ifdef UCB
+ if (!suser())
+ return(NODEV);
+#endif
+ ip = namei(uchar, 0);
+ if(ip == NULL)
+ return(NODEV);
+ if((ip->i_mode&IFMT) != IFBLK)
+ u.u_error = ENOTBLK;
+ dev = (dev_t)ip->i_un.i_rdev;
+ if(major(dev) >= nblkdev)
+ u.u_error = ENXIO;
+ iput(ip);
+ return(dev);
+}