1*3624Sroot /* vfs_syscalls.c 4.10 81/04/28 */ 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; 33*3624Sroot if (fp->f_flag&FPORT) { 34*3624Sroot ptstat(fp); 35*3624Sroot return; 36*3624Sroot } 37*3624Sroot stat1(fp->f_inode, uap->sb); 3837Sbill } 3937Sbill 4037Sbill /* 4137Sbill * the stat system call. 4237Sbill */ 4337Sbill stat() 4437Sbill { 4537Sbill register struct inode *ip; 4637Sbill register struct a { 4737Sbill char *fname; 4837Sbill struct stat *sb; 4937Sbill } *uap; 5037Sbill 5137Sbill uap = (struct a *)u.u_ap; 5237Sbill ip = namei(uchar, 0); 5337Sbill if(ip == NULL) 5437Sbill return; 55*3624Sroot stat1(ip, uap->sb); 5637Sbill iput(ip); 5737Sbill } 5837Sbill 5937Sbill /* 6037Sbill * The basic routine for fstat and stat: 6137Sbill * get the inode and pass appropriate parts back. 6237Sbill */ 63*3624Sroot stat1(ip, ub) 6437Sbill register struct inode *ip; 6537Sbill struct stat *ub; 6637Sbill { 6737Sbill register struct dinode *dp; 6837Sbill register struct buf *bp; 6937Sbill struct stat ds; 7037Sbill 711204Sbill IUPDAT(ip, &time, &time, 0); 7237Sbill /* 7337Sbill * first copy from inode table 7437Sbill */ 7537Sbill ds.st_dev = ip->i_dev; 7637Sbill ds.st_ino = ip->i_number; 7737Sbill ds.st_mode = ip->i_mode; 7837Sbill ds.st_nlink = ip->i_nlink; 7937Sbill ds.st_uid = ip->i_uid; 8037Sbill ds.st_gid = ip->i_gid; 8137Sbill ds.st_rdev = (dev_t)ip->i_un.i_rdev; 82*3624Sroot ds.st_size = ip->i_size; 8337Sbill /* 8437Sbill * next the dates in the disk 8537Sbill */ 8637Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 8737Sbill dp = bp->b_un.b_dino; 8837Sbill dp += itoo(ip->i_number); 8937Sbill ds.st_atime = dp->di_atime; 9037Sbill ds.st_mtime = dp->di_mtime; 9137Sbill ds.st_ctime = dp->di_ctime; 9237Sbill brelse(bp); 9337Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 9437Sbill u.u_error = EFAULT; 9537Sbill } 9637Sbill 9737Sbill /* 9837Sbill * the dup system call. 9937Sbill */ 10037Sbill dup() 10137Sbill { 10237Sbill register struct file *fp; 10337Sbill register struct a { 10437Sbill int fdes; 10537Sbill int fdes2; 10637Sbill } *uap; 10737Sbill register i, m; 10837Sbill 10937Sbill uap = (struct a *)u.u_ap; 11037Sbill m = uap->fdes & ~077; 11137Sbill uap->fdes &= 077; 11237Sbill fp = getf(uap->fdes); 11337Sbill if(fp == NULL) 11437Sbill return; 11537Sbill if ((m&0100) == 0) { 11637Sbill if ((i = ufalloc()) < 0) 11737Sbill return; 11837Sbill } else { 11937Sbill i = uap->fdes2; 12037Sbill if (i<0 || i>=NOFILE) { 12137Sbill u.u_error = EBADF; 12237Sbill return; 12337Sbill } 12437Sbill if (u.u_vrpages[i]) { 12537Sbill u.u_error = ETXTBSY; 12637Sbill return; 12737Sbill } 12837Sbill u.u_r.r_val1 = i; 12937Sbill } 13037Sbill if (i!=uap->fdes) { 13137Sbill if (u.u_ofile[i]!=NULL) 13237Sbill closef(u.u_ofile[i]); 13337Sbill u.u_ofile[i] = fp; 13437Sbill fp->f_count++; 13537Sbill } 13637Sbill } 13737Sbill 13837Sbill /* 13937Sbill * the mount system call. 14037Sbill */ 1412879Swnj smount() { 14237Sbill dev_t dev; 14337Sbill register struct inode *ip; 14437Sbill register struct mount *mp; 14537Sbill struct mount *smp; 14637Sbill register struct filsys *fp; 14737Sbill struct buf *bp; 14837Sbill register struct a { 14937Sbill char *fspec; 15037Sbill char *freg; 15137Sbill int ronly; 15237Sbill } *uap; 1532879Swnj register char *cp; 15437Sbill 15537Sbill uap = (struct a *)u.u_ap; 15637Sbill dev = getmdev(); 15737Sbill if(u.u_error) 15837Sbill return; 15937Sbill u.u_dirp = (caddr_t)uap->freg; 16037Sbill ip = namei(uchar, 0); 16137Sbill if(ip == NULL) 16237Sbill return; 16337Sbill if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0) 16437Sbill goto out; 16537Sbill smp = NULL; 16637Sbill for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 16737Sbill if(mp->m_bufp != NULL) { 16837Sbill if(dev == mp->m_dev) 16937Sbill goto out; 17037Sbill } else 17137Sbill if(smp == NULL) 17237Sbill smp = mp; 17337Sbill } 17437Sbill mp = smp; 17537Sbill if(mp == NULL) 17637Sbill goto out; 17737Sbill (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 17837Sbill if(u.u_error) 17937Sbill goto out; 18037Sbill bp = bread(dev, SUPERB); 18137Sbill if(u.u_error) { 18237Sbill brelse(bp); 18337Sbill goto out1; 18437Sbill } 18537Sbill mp->m_inodp = ip; 18637Sbill mp->m_dev = dev; 1872323Swnj bp->b_flags |= B_LOCKED; 1882323Swnj mp->m_bufp = bp; 1892323Swnj fp = bp->b_un.b_filsys; 19037Sbill fp->s_ilock = 0; 19137Sbill fp->s_flock = 0; 19237Sbill fp->s_ronly = uap->ronly & 1; 19337Sbill fp->s_nbehind = 0; 19437Sbill fp->s_lasti = 1; 1952879Swnj u.u_dirp = uap->freg; 1962879Swnj for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) 1972879Swnj if ((*cp++ = uchar()) == 0) 1982879Swnj u.u_dirp--; /* get 0 again */ 1992879Swnj *cp = 0; 20037Sbill brelse(bp); 20137Sbill ip->i_flag |= IMOUNT; 20237Sbill prele(ip); 20337Sbill return; 20437Sbill 20537Sbill out: 20637Sbill u.u_error = EBUSY; 20737Sbill out1: 20837Sbill iput(ip); 20937Sbill } 21037Sbill 21137Sbill /* 21237Sbill * the umount system call. 21337Sbill */ 21437Sbill sumount() 21537Sbill { 21637Sbill dev_t dev; 21737Sbill register struct inode *ip; 21837Sbill register struct mount *mp; 21937Sbill struct buf *bp; 2202323Swnj int stillopen, flag; 22137Sbill register struct a { 22237Sbill char *fspec; 22337Sbill }; 22437Sbill 22537Sbill dev = getmdev(); 22637Sbill if(u.u_error) 22737Sbill return; 22837Sbill xumount(dev); /* remove unused sticky files from text table */ 22937Sbill update(); 23037Sbill for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 23137Sbill if(mp->m_bufp != NULL && dev == mp->m_dev) 23237Sbill goto found; 23337Sbill u.u_error = EINVAL; 23437Sbill return; 23537Sbill 23637Sbill found: 2372436Skre stillopen = 0; 2382737Swnj for(ip = inode; ip < inodeNINODE; ip++) 2392323Swnj if (ip->i_number != 0 && dev == ip->i_dev) { 24037Sbill u.u_error = EBUSY; 24137Sbill return; 2422323Swnj } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 2432323Swnj ip->i_un.i_rdev == dev) 2442323Swnj stillopen++; 24537Sbill ip = mp->m_inodp; 24637Sbill ip->i_flag &= ~IMOUNT; 24737Sbill plock(ip); 24837Sbill iput(ip); 2492323Swnj if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 2502323Swnj panic("umount"); 2512323Swnj bp->b_flags &= ~B_LOCKED; 2522304Skre flag = !bp->b_un.b_filsys->s_ronly; 25337Sbill mp->m_bufp = NULL; 25437Sbill brelse(bp); 2552454Swnj mpurge(mp - &mount[0]); 2562304Skre if (!stillopen) { 2572304Skre (*bdevsw[major(dev)].d_close)(dev, flag); 2582304Skre binval(dev); 2592304Skre } 26037Sbill } 26137Sbill 26237Sbill /* 26337Sbill * Common code for mount and umount. 26437Sbill * Check that the user's argument is a reasonable 26537Sbill * thing on which to mount, and return the device number if so. 26637Sbill */ 26737Sbill dev_t 26837Sbill getmdev() 26937Sbill { 27037Sbill dev_t dev; 27137Sbill register struct inode *ip; 27237Sbill 27337Sbill if (!suser()) 27437Sbill return(NODEV); 27537Sbill ip = namei(uchar, 0); 27637Sbill if(ip == NULL) 27737Sbill return(NODEV); 27837Sbill if((ip->i_mode&IFMT) != IFBLK) 27937Sbill u.u_error = ENOTBLK; 28037Sbill dev = (dev_t)ip->i_un.i_rdev; 28137Sbill if(major(dev) >= nblkdev) 28237Sbill u.u_error = ENXIO; 28337Sbill iput(ip); 28437Sbill return(dev); 28537Sbill } 286