#include "sys/param.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/user.h" #include "sys/inode.h" #include "sys/file.h" #include "sys/conf.h" #include "sys/stat.h" #include "sys/ioctl.h" #include "sys/var.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); } /* * 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; struct stat ds; if(ip->i_flag&(IACC|IUPD|ICHG)) 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_rdev; ds.st_size = ip->i_size; /* * 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 i; register 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; uap = (struct a *)u.u_ap; fp = getf(uap->fdes); if (fp == NULL) return; switch(uap->cmd) { case 0: i = uap->arg; if (i < 0 || i > NOFILE) { u.u_error = EINVAL; return; } if ((i = ufalloc(i)) < 0) return; u.u_ofile[i] = fp; fp->f_count++; break; case 1: u.u_rval1 = u.u_pofile[uap->fdes]; break; case 2: u.u_pofile[uap->fdes] = uap->arg; break; case 3: u.u_rval1 = fp->f_flag+FOPEN; break; case 4: fp->f_flag &= (FREAD|FWRITE); fp->f_flag |= (uap->arg-FOPEN) & ~(FREAD|FWRITE); break; default: u.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; uap = (struct a *)u.u_ap; if ((fp = getf(uap->fdes)) == NULL) return; ip = fp->f_inode; if ((ip->i_mode&IFMT) != IFCHR) { u.u_error = ENOTTY; return; } dev = (dev_t)ip->i_rdev; (*cdevsw[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() { 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; if(!suser()) return; 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_mode&IFMT) != IFDIR) { u.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(dev == 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 = dev; (*bdevsw[major(dev)].d_open)(minor(dev), !uap->ronly); if(u.u_error) goto out1; bp = bread(dev, SUPERB); if(u.u_error) { brelse(bp); goto out1; } mp->m_inodp = ip; 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; mp->m_flags = MINUSE; fp->s_ilock = 0; fp->s_flock = 0; fp->s_ninode = 0; fp->s_inode[0] = 0; fp->s_ronly = uap->ronly & 1; brelse(bp); ip->i_flag |= IMOUNT; prele(ip); return; out1: mp->m_flags = MFREE; out: if (u.u_error == 0) u.u_error = EBUSY; iput(ip); } /* * the umount system call. */ sumount() { 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; xumount(dev); /* remove unused sticky files from text table */ update(); for(mp = &mount[0]; mp < (struct mount *)v.ve_mount; mp++) if(mp->m_flags == MINUSE && dev == mp->m_dev) goto found; u.u_error = EINVAL; return; found: 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[major(dev)].d_close)(minor(dev), 0); 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(major(dev) >= bdevcnt) u.u_error = ENXIO; iput(ip); return(dev); }