1*5416Swnj /* vfs_syscalls.c 4.16 82/01/16 */ 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" 174918Swnj #include "../h/socket.h" 184918Swnj #include "../h/socketvar.h" 1937Sbill 2037Sbill /* 2137Sbill * the fstat system call. 2237Sbill */ 2337Sbill fstat() 2437Sbill { 2537Sbill register struct file *fp; 2637Sbill register struct a { 2737Sbill int fdes; 2837Sbill struct stat *sb; 2937Sbill } *uap; 3037Sbill 3137Sbill uap = (struct a *)u.u_ap; 3237Sbill fp = getf(uap->fdes); 334828Swnj if (fp == NULL) 3437Sbill return; 354828Swnj if (fp->f_flag & FSOCKET) 364891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 374828Swnj else 384828Swnj stat1(fp->f_inode, uap->sb); 3937Sbill } 4037Sbill 4137Sbill /* 424828Swnj * Stat system call. 4337Sbill */ 4437Sbill stat() 4537Sbill { 4637Sbill register struct inode *ip; 4737Sbill register struct a { 4837Sbill char *fname; 4937Sbill struct stat *sb; 5037Sbill } *uap; 5137Sbill 5237Sbill uap = (struct a *)u.u_ap; 5337Sbill ip = namei(uchar, 0); 544828Swnj if (ip == NULL) 5537Sbill return; 563624Sroot stat1(ip, uap->sb); 5737Sbill iput(ip); 5837Sbill } 5937Sbill 6037Sbill /* 6137Sbill * The basic routine for fstat and stat: 6237Sbill * get the inode and pass appropriate parts back. 6337Sbill */ 643624Sroot stat1(ip, ub) 654828Swnj register struct inode *ip; 664828Swnj struct stat *ub; 6737Sbill { 6837Sbill register struct dinode *dp; 6937Sbill register struct buf *bp; 7037Sbill struct stat ds; 7137Sbill 721204Sbill IUPDAT(ip, &time, &time, 0); 7337Sbill /* 744828Swnj * First copy from inode table 7537Sbill */ 7637Sbill ds.st_dev = ip->i_dev; 7737Sbill ds.st_ino = ip->i_number; 7837Sbill ds.st_mode = ip->i_mode; 7937Sbill ds.st_nlink = ip->i_nlink; 8037Sbill ds.st_uid = ip->i_uid; 8137Sbill ds.st_gid = ip->i_gid; 8237Sbill ds.st_rdev = (dev_t)ip->i_un.i_rdev; 833624Sroot ds.st_size = ip->i_size; 8437Sbill /* 854828Swnj * Next the dates in the disk 8637Sbill */ 8737Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 8837Sbill dp = bp->b_un.b_dino; 8937Sbill dp += itoo(ip->i_number); 9037Sbill ds.st_atime = dp->di_atime; 9137Sbill ds.st_mtime = dp->di_mtime; 9237Sbill ds.st_ctime = dp->di_ctime; 9337Sbill brelse(bp); 9437Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 9537Sbill u.u_error = EFAULT; 9637Sbill } 9737Sbill 9837Sbill /* 994828Swnj * Dup system call. 10037Sbill */ 10137Sbill dup() 10237Sbill { 10337Sbill register struct file *fp; 10437Sbill register struct a { 10537Sbill int fdes; 10637Sbill int fdes2; 10737Sbill } *uap; 10837Sbill register i, m; 10937Sbill 11037Sbill uap = (struct a *)u.u_ap; 11137Sbill m = uap->fdes & ~077; 11237Sbill uap->fdes &= 077; 11337Sbill fp = getf(uap->fdes); 1144828Swnj if (fp == NULL) 11537Sbill return; 11637Sbill if ((m&0100) == 0) { 11737Sbill if ((i = ufalloc()) < 0) 11837Sbill return; 11937Sbill } else { 12037Sbill i = uap->fdes2; 12137Sbill if (i<0 || i>=NOFILE) { 12237Sbill u.u_error = EBADF; 12337Sbill return; 12437Sbill } 12537Sbill u.u_r.r_val1 = i; 12637Sbill } 1274828Swnj 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 /* 1364828Swnj * Mount system call. 13737Sbill */ 1384828Swnj smount() 1394828Swnj { 14037Sbill dev_t dev; 14137Sbill register struct inode *ip; 14237Sbill register struct mount *mp; 14337Sbill struct mount *smp; 14437Sbill register struct filsys *fp; 14537Sbill struct buf *bp; 14637Sbill register struct a { 14737Sbill char *fspec; 14837Sbill char *freg; 14937Sbill int ronly; 15037Sbill } *uap; 1512879Swnj register char *cp; 15237Sbill 15337Sbill uap = (struct a *)u.u_ap; 15437Sbill dev = getmdev(); 1554828Swnj if (u.u_error) 15637Sbill return; 15737Sbill u.u_dirp = (caddr_t)uap->freg; 15837Sbill ip = namei(uchar, 0); 1594828Swnj if (ip == NULL) 16037Sbill return; 1614828Swnj if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) 16237Sbill goto out; 16337Sbill smp = NULL; 1644828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 1654828Swnj if (mp->m_bufp != NULL) { 1664828Swnj if (dev == mp->m_dev) 16737Sbill goto out; 16837Sbill } else 1694828Swnj if (smp == NULL) 17037Sbill smp = mp; 17137Sbill } 17237Sbill mp = smp; 1734828Swnj if (mp == NULL) 17437Sbill goto out; 17537Sbill (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 1764828Swnj if (u.u_error) 17737Sbill goto out; 17837Sbill bp = bread(dev, SUPERB); 1794828Swnj if (u.u_error) { 18037Sbill brelse(bp); 18137Sbill goto out1; 18237Sbill } 18337Sbill mp->m_inodp = ip; 18437Sbill mp->m_dev = dev; 1852323Swnj bp->b_flags |= B_LOCKED; 1862323Swnj mp->m_bufp = bp; 1872323Swnj fp = bp->b_un.b_filsys; 18837Sbill fp->s_ilock = 0; 18937Sbill fp->s_flock = 0; 19037Sbill fp->s_ronly = uap->ronly & 1; 19137Sbill fp->s_nbehind = 0; 19237Sbill fp->s_lasti = 1; 1932879Swnj u.u_dirp = uap->freg; 1942879Swnj for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) 1952879Swnj if ((*cp++ = uchar()) == 0) 1962879Swnj u.u_dirp--; /* get 0 again */ 1972879Swnj *cp = 0; 19837Sbill brelse(bp); 19937Sbill ip->i_flag |= IMOUNT; 2004828Swnj irele(ip); 20137Sbill return; 20237Sbill 20337Sbill out: 20437Sbill u.u_error = EBUSY; 20537Sbill out1: 20637Sbill iput(ip); 20737Sbill } 20837Sbill 20937Sbill /* 21037Sbill * the umount system call. 21137Sbill */ 21237Sbill sumount() 21337Sbill { 21437Sbill dev_t dev; 21537Sbill register struct inode *ip; 21637Sbill register struct mount *mp; 21737Sbill struct buf *bp; 2182323Swnj int stillopen, flag; 21937Sbill register struct a { 22037Sbill char *fspec; 22137Sbill }; 22237Sbill 22337Sbill dev = getmdev(); 2244828Swnj if (u.u_error) 22537Sbill return; 22637Sbill xumount(dev); /* remove unused sticky files from text table */ 227*5416Swnj update(0); 2284828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 2294828Swnj if (mp->m_bufp != NULL && dev == mp->m_dev) 23037Sbill goto found; 23137Sbill u.u_error = EINVAL; 23237Sbill return; 23337Sbill 23437Sbill found: 2352436Skre stillopen = 0; 2364828Swnj for (ip = inode; ip < inodeNINODE; ip++) 2372323Swnj if (ip->i_number != 0 && dev == ip->i_dev) { 23837Sbill u.u_error = EBUSY; 23937Sbill return; 2402323Swnj } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 2412323Swnj ip->i_un.i_rdev == dev) 2422323Swnj stillopen++; 24337Sbill ip = mp->m_inodp; 24437Sbill ip->i_flag &= ~IMOUNT; 2454828Swnj ilock(ip); 24637Sbill iput(ip); 2472323Swnj if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 2482323Swnj panic("umount"); 2492323Swnj bp->b_flags &= ~B_LOCKED; 2502304Skre flag = !bp->b_un.b_filsys->s_ronly; 25137Sbill mp->m_bufp = NULL; 25237Sbill brelse(bp); 2532454Swnj mpurge(mp - &mount[0]); 2542304Skre if (!stillopen) { 2552304Skre (*bdevsw[major(dev)].d_close)(dev, flag); 2562304Skre binval(dev); 2572304Skre } 25837Sbill } 25937Sbill 26037Sbill /* 26137Sbill * Common code for mount and umount. 26237Sbill * Check that the user's argument is a reasonable 26337Sbill * thing on which to mount, and return the device number if so. 26437Sbill */ 26537Sbill dev_t 26637Sbill getmdev() 26737Sbill { 26837Sbill dev_t dev; 26937Sbill register struct inode *ip; 27037Sbill 27137Sbill if (!suser()) 27237Sbill return(NODEV); 27337Sbill ip = namei(uchar, 0); 2744828Swnj if (ip == NULL) 27537Sbill return(NODEV); 2764828Swnj if ((ip->i_mode&IFMT) != IFBLK) 27737Sbill u.u_error = ENOTBLK; 27837Sbill dev = (dev_t)ip->i_un.i_rdev; 2794828Swnj if (major(dev) >= nblkdev) 28037Sbill u.u_error = ENXIO; 28137Sbill iput(ip); 28237Sbill return(dev); 28337Sbill } 284