1*2879Swnj /* vfs_syscalls.c 4.8 03/03/81 */ 237Sbill 337Sbill #include "../h/param.h" 437Sbill #include "../h/systm.h" 537Sbill #include "../h/mount.h" 637Sbill #include "../h/ino.h" 737Sbill #include "../h/reg.h" 837Sbill #include "../h/buf.h" 937Sbill #include "../h/filsys.h" 1037Sbill #include "../h/dir.h" 1137Sbill #include "../h/user.h" 1237Sbill #include "../h/inode.h" 1337Sbill #include "../h/file.h" 1437Sbill #include "../h/conf.h" 1537Sbill #include "../h/stat.h" 1694Sbill #include "../h/inline.h" 1737Sbill 1837Sbill /* 1937Sbill * the fstat system call. 2037Sbill */ 2137Sbill fstat() 2237Sbill { 2337Sbill register struct file *fp; 2437Sbill register struct a { 2537Sbill int fdes; 2637Sbill struct stat *sb; 2737Sbill } *uap; 2837Sbill 2937Sbill uap = (struct a *)u.u_ap; 3037Sbill fp = getf(uap->fdes); 3137Sbill if(fp == NULL) 3237Sbill return; 3337Sbill stat1(fp->f_inode, uap->sb, fp->f_flag&FPIPE? fp->f_un.f_offset: 0); 3437Sbill } 3537Sbill 3637Sbill /* 3737Sbill * the stat system call. 3837Sbill */ 3937Sbill stat() 4037Sbill { 4137Sbill register struct inode *ip; 4237Sbill register struct a { 4337Sbill char *fname; 4437Sbill struct stat *sb; 4537Sbill } *uap; 4637Sbill 4737Sbill uap = (struct a *)u.u_ap; 4837Sbill ip = namei(uchar, 0); 4937Sbill if(ip == NULL) 5037Sbill return; 5137Sbill stat1(ip, uap->sb, (off_t)0); 5237Sbill iput(ip); 5337Sbill } 5437Sbill 5537Sbill /* 5637Sbill * The basic routine for fstat and stat: 5737Sbill * get the inode and pass appropriate parts back. 5837Sbill */ 5937Sbill stat1(ip, ub, pipeadj) 6037Sbill register struct inode *ip; 6137Sbill struct stat *ub; 6237Sbill off_t pipeadj; 6337Sbill { 6437Sbill register struct dinode *dp; 6537Sbill register struct buf *bp; 6637Sbill struct stat ds; 6737Sbill 681204Sbill IUPDAT(ip, &time, &time, 0); 6937Sbill /* 7037Sbill * first copy from inode table 7137Sbill */ 7237Sbill ds.st_dev = ip->i_dev; 7337Sbill ds.st_ino = ip->i_number; 7437Sbill ds.st_mode = ip->i_mode; 7537Sbill ds.st_nlink = ip->i_nlink; 7637Sbill ds.st_uid = ip->i_uid; 7737Sbill ds.st_gid = ip->i_gid; 7837Sbill ds.st_rdev = (dev_t)ip->i_un.i_rdev; 7937Sbill ds.st_size = ip->i_size - pipeadj; 8037Sbill /* 8137Sbill * next the dates in the disk 8237Sbill */ 8337Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 8437Sbill dp = bp->b_un.b_dino; 8537Sbill dp += itoo(ip->i_number); 8637Sbill ds.st_atime = dp->di_atime; 8737Sbill ds.st_mtime = dp->di_mtime; 8837Sbill ds.st_ctime = dp->di_ctime; 8937Sbill brelse(bp); 9037Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 9137Sbill u.u_error = EFAULT; 9237Sbill } 9337Sbill 9437Sbill /* 9537Sbill * the dup system call. 9637Sbill */ 9737Sbill dup() 9837Sbill { 9937Sbill register struct file *fp; 10037Sbill register struct a { 10137Sbill int fdes; 10237Sbill int fdes2; 10337Sbill } *uap; 10437Sbill register i, m; 10537Sbill 10637Sbill uap = (struct a *)u.u_ap; 10737Sbill m = uap->fdes & ~077; 10837Sbill uap->fdes &= 077; 10937Sbill fp = getf(uap->fdes); 11037Sbill if(fp == NULL) 11137Sbill return; 11237Sbill if ((m&0100) == 0) { 11337Sbill if ((i = ufalloc()) < 0) 11437Sbill return; 11537Sbill } else { 11637Sbill i = uap->fdes2; 11737Sbill if (i<0 || i>=NOFILE) { 11837Sbill u.u_error = EBADF; 11937Sbill return; 12037Sbill } 12137Sbill if (u.u_vrpages[i]) { 12237Sbill u.u_error = ETXTBSY; 12337Sbill return; 12437Sbill } 12537Sbill u.u_r.r_val1 = i; 12637Sbill } 12737Sbill if (i!=uap->fdes) { 12837Sbill if (u.u_ofile[i]!=NULL) 12937Sbill closef(u.u_ofile[i]); 13037Sbill u.u_ofile[i] = fp; 13137Sbill fp->f_count++; 13237Sbill } 13337Sbill } 13437Sbill 13537Sbill /* 13637Sbill * the mount system call. 13737Sbill */ 138*2879Swnj smount() { 13937Sbill dev_t dev; 14037Sbill register struct inode *ip; 14137Sbill register struct mount *mp; 14237Sbill struct mount *smp; 14337Sbill register struct filsys *fp; 14437Sbill struct buf *bp; 14537Sbill register struct a { 14637Sbill char *fspec; 14737Sbill char *freg; 14837Sbill int ronly; 14937Sbill } *uap; 150*2879Swnj register char *cp; 15137Sbill 15237Sbill uap = (struct a *)u.u_ap; 15337Sbill dev = getmdev(); 15437Sbill if(u.u_error) 15537Sbill return; 15637Sbill u.u_dirp = (caddr_t)uap->freg; 15737Sbill ip = namei(uchar, 0); 15837Sbill if(ip == NULL) 15937Sbill return; 16037Sbill if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) 16137Sbill goto out; 16237Sbill smp = NULL; 16337Sbill for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 16437Sbill if(mp->m_bufp != NULL) { 16537Sbill if(dev == mp->m_dev) 16637Sbill goto out; 16737Sbill } else 16837Sbill if(smp == NULL) 16937Sbill smp = mp; 17037Sbill } 17137Sbill mp = smp; 17237Sbill if(mp == NULL) 17337Sbill goto out; 17437Sbill (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 17537Sbill if(u.u_error) 17637Sbill goto out; 17737Sbill bp = bread(dev, SUPERB); 17837Sbill if(u.u_error) { 17937Sbill brelse(bp); 18037Sbill goto out1; 18137Sbill } 18237Sbill mp->m_inodp = ip; 18337Sbill mp->m_dev = dev; 1842323Swnj bp->b_flags |= B_LOCKED; 1852323Swnj mp->m_bufp = bp; 1862323Swnj fp = bp->b_un.b_filsys; 18737Sbill fp->s_ilock = 0; 18837Sbill fp->s_flock = 0; 18937Sbill fp->s_ronly = uap->ronly & 1; 19037Sbill fp->s_nbehind = 0; 19137Sbill fp->s_lasti = 1; 192*2879Swnj u.u_dirp = uap->freg; 193*2879Swnj for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) 194*2879Swnj if ((*cp++ = uchar()) == 0) 195*2879Swnj u.u_dirp--; /* get 0 again */ 196*2879Swnj *cp = 0; 19737Sbill brelse(bp); 19837Sbill ip->i_flag |= IMOUNT; 19937Sbill prele(ip); 20037Sbill return; 20137Sbill 20237Sbill out: 20337Sbill u.u_error = EBUSY; 20437Sbill out1: 20537Sbill iput(ip); 20637Sbill } 20737Sbill 20837Sbill /* 20937Sbill * the umount system call. 21037Sbill */ 21137Sbill sumount() 21237Sbill { 21337Sbill dev_t dev; 21437Sbill register struct inode *ip; 21537Sbill register struct mount *mp; 21637Sbill struct buf *bp; 2172323Swnj int stillopen, flag; 21837Sbill register struct a { 21937Sbill char *fspec; 22037Sbill }; 22137Sbill 22237Sbill dev = getmdev(); 22337Sbill if(u.u_error) 22437Sbill return; 22537Sbill xumount(dev); /* remove unused sticky files from text table */ 22637Sbill update(); 22737Sbill for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 22837Sbill if(mp->m_bufp != NULL && dev == mp->m_dev) 22937Sbill goto found; 23037Sbill u.u_error = EINVAL; 23137Sbill return; 23237Sbill 23337Sbill found: 2342436Skre stillopen = 0; 2352737Swnj for(ip = inode; ip < inodeNINODE; ip++) 2362323Swnj if (ip->i_number != 0 && dev == ip->i_dev) { 23737Sbill u.u_error = EBUSY; 23837Sbill return; 2392323Swnj } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 2402323Swnj ip->i_un.i_rdev == dev) 2412323Swnj stillopen++; 24237Sbill ip = mp->m_inodp; 24337Sbill ip->i_flag &= ~IMOUNT; 24437Sbill plock(ip); 24537Sbill iput(ip); 2462323Swnj if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 2472323Swnj panic("umount"); 2482323Swnj bp->b_flags &= ~B_LOCKED; 2492304Skre flag = !bp->b_un.b_filsys->s_ronly; 25037Sbill mp->m_bufp = NULL; 25137Sbill brelse(bp); 2522454Swnj mpurge(mp - &mount[0]); 2532304Skre if (!stillopen) { 2542304Skre (*bdevsw[major(dev)].d_close)(dev, flag); 2552304Skre binval(dev); 2562304Skre } 25737Sbill } 25837Sbill 25937Sbill /* 26037Sbill * Common code for mount and umount. 26137Sbill * Check that the user's argument is a reasonable 26237Sbill * thing on which to mount, and return the device number if so. 26337Sbill */ 26437Sbill dev_t 26537Sbill getmdev() 26637Sbill { 26737Sbill dev_t dev; 26837Sbill register struct inode *ip; 26937Sbill 27037Sbill if (!suser()) 27137Sbill return(NODEV); 27237Sbill ip = namei(uchar, 0); 27337Sbill if(ip == NULL) 27437Sbill return(NODEV); 27537Sbill if((ip->i_mode&IFMT) != IFBLK) 27637Sbill u.u_error = ENOTBLK; 27737Sbill dev = (dev_t)ip->i_un.i_rdev; 27837Sbill if(major(dev) >= nblkdev) 27937Sbill u.u_error = ENXIO; 28037Sbill iput(ip); 28137Sbill return(dev); 28237Sbill } 283