#include "../h/local.h" #ifdef SCCS_ID static char SCCS_ID [] = "@(#)sys3.c 3.2 01:53:36 - 81/12/10 "; #endif SCCS_ID #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; #ifdef SVC6 if (u.u_svc6) { struct v6stat ds; register i; iupdat(ip, &time, &time); ds.st6_dev = ip->i_dev; ds.st6_ino = ip->i_number; ds.st6_mode = ip->i_mode & ~(ILARG|DIALLOC|DILARG); if (ip->i_mode != 0) ds.st6_mode |= DIALLOC; if (ip->i_mode&ILARG) ds.st6_mode |= DILARG; ds.st6_nlink = ip->i_nlink; ds.st6_uid = ip->i_uid; ds.st6_gid = ip->i_gid; ds.st6_siz0 = 0; ds.st6_siz1 = ip->i_size - pipeadj; for (i = 0; i < 8; i++) ds.st6_addr[i] = ip->i_un.i_addr[i]; bp = bread(ip->i_dev, itod(ip->i_number)); dp = bp->b_un.b_dino; dp += itoo(ip->i_number); ds.st6_atm0 = ds.st6_mtm0 = 0; ds.st6_atime = dp->di_atime; ds.st6_mtime = dp->di_mtime; brelse(bp); if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) u.u_error = EFAULT; } else { #endif SVC6 struct stat ds; #ifdef UCB_NODUPS iupdat(ip, &time, &time, 0); #else UCB_NODUPS iupdat(ip, &time, &time); #endif UCB_NODUPS /* * 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; #ifdef V6 ds.st_ctime = dp->di_mtime; #else V6 ds.st_ctime = dp->di_ctime; #endif V6 brelse(bp); if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) u.u_error = EFAULT; #ifdef SVC6 } #endif SVC6 } /* * 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; } 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(); #ifdef CGL_LOCAL /* only suser can mount */ if(u.u_error || !suser()) #else CGL_LOCAL if(u.u_error) #endif CGL_LOCAL 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 < mountNMOUNT; 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; #ifdef UCB_MOUNT if (((mp-mount)%NSBPFSB) == 0 && mp->m_caddr == NULL) { mp->m_bufp = geteblk(); mount1(mp); } else mp->m_bufp = (struct buf *)1; #else UCB_MOUNT mp->m_bufp = geteblk(); #endif UCB_MOUNT #ifdef UCB_MOUNT bcopy((caddr_t)bp->b_un.b_addr, mp->m_caddr, SBSIZE); fp = mp->m_caddr; #else UCB_MOUNT bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE); fp = mp->m_bufp->b_un.b_filsys; #endif UCB_MOUNT fp->s_ilock = 0; fp->s_flock = 0; fp->s_ronly = uap->ronly & 1; #ifdef CGL_ISRCH fp->s_lasti = 1; fp->s_nbehind = 0; #endif CGL_ISRCH #ifdef UCB_FSNAM { char *cp; u.u_dirp = (caddr_t)uap->freg; for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof(fp->s_fsmnt)-1]; ) if ((*cp++ = uchar()) == 0) u.u_dirp--; /* get 0 again */ *cp = 0; } #endif UCB_FSNAM 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(); #ifdef CGL_LOCAL /* only suser can umount */ if(u.u_error || !suser()) #else CGL_LOCAL if(u.u_error) #endif CGL_LOCAL return; xumount(dev); /* remove unused sticky files from text table */ update(); for(mp = &mount[0]; mp < mountNMOUNT; mp++) if(mp->m_bufp != NULL && dev == mp->m_dev) goto found; u.u_error = EINVAL; return; found: for(ip = &inode[0]; ip < inodeNINODE; ip++) if(ip->i_number != 0 && dev == ip->i_dev) { u.u_error = EBUSY; return; } (*bdevsw[major(dev)].d_close)(dev, 0); #ifdef UCB_UMOUNT { struct buf *dp; /* Klein & McConnell fix */ dp = bdevsw[major(dev)].d_tab; for (bp=dp->b_forw; bp!=dp; bp=bp->b_forw) { spl6(); if (bp->b_dev == dev) { #ifdef UCB_BHASH bunhash(bp); #endif UCB_BHASH bp->b_dev = NODEV; } spl0(); } } #endif UCB_UMOUNT ip = mp->m_inodp; ip->i_flag &= ~IMOUNT; plock(ip); iput(ip); bp = mp->m_bufp; mp->m_bufp = NULL; #ifndef UCB_MOUNT brelse(bp); #endif UCB_MOUNT } /* * 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_un.i_rdev; if(major(dev) >= nblkdev) u.u_error = ENXIO; iput(ip); return(dev); } #ifdef UCB_MOUNT /* * distribute a buffer's address through * NSBPFSB succeeding mount table entries */ mount1(mp) register struct mount *mp; { register a, i; a = mp->m_bufp->b_un.b_addr; for (i=0; im_caddr = a + sizeof(struct filsys) * i; } #endif UCB_MOUNT