1*4891Swnj /* vfs_syscalls.c 4.13 81/11/14 */ 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); 314828Swnj if (fp == NULL) 3237Sbill return; 334828Swnj if (fp->f_flag & FSOCKET) 34*4891Swnj u.u_error = sostat(fp->f_socket, uap->sb); 354828Swnj else 364828Swnj stat1(fp->f_inode, uap->sb); 3737Sbill } 3837Sbill 3937Sbill /* 404828Swnj * Stat system call. 4137Sbill */ 4237Sbill stat() 4337Sbill { 4437Sbill register struct inode *ip; 4537Sbill register struct a { 4637Sbill char *fname; 4737Sbill struct stat *sb; 4837Sbill } *uap; 4937Sbill 5037Sbill uap = (struct a *)u.u_ap; 5137Sbill ip = namei(uchar, 0); 524828Swnj if (ip == NULL) 5337Sbill return; 543624Sroot stat1(ip, uap->sb); 5537Sbill iput(ip); 5637Sbill } 5737Sbill 5837Sbill /* 5937Sbill * The basic routine for fstat and stat: 6037Sbill * get the inode and pass appropriate parts back. 6137Sbill */ 623624Sroot stat1(ip, ub) 634828Swnj register struct inode *ip; 644828Swnj struct stat *ub; 6537Sbill { 6637Sbill register struct dinode *dp; 6737Sbill register struct buf *bp; 6837Sbill struct stat ds; 6937Sbill 701204Sbill IUPDAT(ip, &time, &time, 0); 7137Sbill /* 724828Swnj * First copy from inode table 7337Sbill */ 7437Sbill ds.st_dev = ip->i_dev; 7537Sbill ds.st_ino = ip->i_number; 7637Sbill ds.st_mode = ip->i_mode; 7737Sbill ds.st_nlink = ip->i_nlink; 7837Sbill ds.st_uid = ip->i_uid; 7937Sbill ds.st_gid = ip->i_gid; 8037Sbill ds.st_rdev = (dev_t)ip->i_un.i_rdev; 813624Sroot ds.st_size = ip->i_size; 8237Sbill /* 834828Swnj * Next the dates in the disk 8437Sbill */ 8537Sbill bp = bread(ip->i_dev, itod(ip->i_number)); 8637Sbill dp = bp->b_un.b_dino; 8737Sbill dp += itoo(ip->i_number); 8837Sbill ds.st_atime = dp->di_atime; 8937Sbill ds.st_mtime = dp->di_mtime; 9037Sbill ds.st_ctime = dp->di_ctime; 9137Sbill brelse(bp); 9237Sbill if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) 9337Sbill u.u_error = EFAULT; 9437Sbill } 9537Sbill 9637Sbill /* 974828Swnj * Dup system call. 9837Sbill */ 9937Sbill dup() 10037Sbill { 10137Sbill register struct file *fp; 10237Sbill register struct a { 10337Sbill int fdes; 10437Sbill int fdes2; 10537Sbill } *uap; 10637Sbill register i, m; 10737Sbill 10837Sbill uap = (struct a *)u.u_ap; 10937Sbill m = uap->fdes & ~077; 11037Sbill uap->fdes &= 077; 11137Sbill fp = getf(uap->fdes); 1124828Swnj if (fp == NULL) 11337Sbill return; 11437Sbill if ((m&0100) == 0) { 11537Sbill if ((i = ufalloc()) < 0) 11637Sbill return; 11737Sbill } else { 11837Sbill i = uap->fdes2; 11937Sbill if (i<0 || i>=NOFILE) { 12037Sbill u.u_error = EBADF; 12137Sbill return; 12237Sbill } 12337Sbill u.u_r.r_val1 = i; 12437Sbill } 1254828Swnj if (i != uap->fdes) { 12637Sbill if (u.u_ofile[i]!=NULL) 12737Sbill closef(u.u_ofile[i]); 12837Sbill u.u_ofile[i] = fp; 12937Sbill fp->f_count++; 13037Sbill } 13137Sbill } 13237Sbill 13337Sbill /* 1344828Swnj * Mount system call. 13537Sbill */ 1364828Swnj smount() 1374828Swnj { 13837Sbill dev_t dev; 13937Sbill register struct inode *ip; 14037Sbill register struct mount *mp; 14137Sbill struct mount *smp; 14237Sbill register struct filsys *fp; 14337Sbill struct buf *bp; 14437Sbill register struct a { 14537Sbill char *fspec; 14637Sbill char *freg; 14737Sbill int ronly; 14837Sbill } *uap; 1492879Swnj register char *cp; 15037Sbill 15137Sbill uap = (struct a *)u.u_ap; 15237Sbill dev = getmdev(); 1534828Swnj if (u.u_error) 15437Sbill return; 15537Sbill u.u_dirp = (caddr_t)uap->freg; 15637Sbill ip = namei(uchar, 0); 1574828Swnj if (ip == NULL) 15837Sbill return; 1594828Swnj if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) 16037Sbill goto out; 16137Sbill smp = NULL; 1624828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 1634828Swnj if (mp->m_bufp != NULL) { 1644828Swnj if (dev == mp->m_dev) 16537Sbill goto out; 16637Sbill } else 1674828Swnj if (smp == NULL) 16837Sbill smp = mp; 16937Sbill } 17037Sbill mp = smp; 1714828Swnj if (mp == NULL) 17237Sbill goto out; 17337Sbill (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 1744828Swnj if (u.u_error) 17537Sbill goto out; 17637Sbill bp = bread(dev, SUPERB); 1774828Swnj if (u.u_error) { 17837Sbill brelse(bp); 17937Sbill goto out1; 18037Sbill } 18137Sbill mp->m_inodp = ip; 18237Sbill mp->m_dev = dev; 1832323Swnj bp->b_flags |= B_LOCKED; 1842323Swnj mp->m_bufp = bp; 1852323Swnj fp = bp->b_un.b_filsys; 18637Sbill fp->s_ilock = 0; 18737Sbill fp->s_flock = 0; 18837Sbill fp->s_ronly = uap->ronly & 1; 18937Sbill fp->s_nbehind = 0; 19037Sbill fp->s_lasti = 1; 1912879Swnj u.u_dirp = uap->freg; 1922879Swnj for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) 1932879Swnj if ((*cp++ = uchar()) == 0) 1942879Swnj u.u_dirp--; /* get 0 again */ 1952879Swnj *cp = 0; 19637Sbill brelse(bp); 19737Sbill ip->i_flag |= IMOUNT; 1984828Swnj irele(ip); 19937Sbill return; 20037Sbill 20137Sbill out: 20237Sbill u.u_error = EBUSY; 20337Sbill out1: 20437Sbill iput(ip); 20537Sbill } 20637Sbill 20737Sbill /* 20837Sbill * the umount system call. 20937Sbill */ 21037Sbill sumount() 21137Sbill { 21237Sbill dev_t dev; 21337Sbill register struct inode *ip; 21437Sbill register struct mount *mp; 21537Sbill struct buf *bp; 2162323Swnj int stillopen, flag; 21737Sbill register struct a { 21837Sbill char *fspec; 21937Sbill }; 22037Sbill 22137Sbill dev = getmdev(); 2224828Swnj if (u.u_error) 22337Sbill return; 22437Sbill xumount(dev); /* remove unused sticky files from text table */ 22537Sbill update(); 2264828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 2274828Swnj if (mp->m_bufp != NULL && dev == mp->m_dev) 22837Sbill goto found; 22937Sbill u.u_error = EINVAL; 23037Sbill return; 23137Sbill 23237Sbill found: 2332436Skre stillopen = 0; 2344828Swnj for (ip = inode; ip < inodeNINODE; ip++) 2352323Swnj if (ip->i_number != 0 && dev == ip->i_dev) { 23637Sbill u.u_error = EBUSY; 23737Sbill return; 2382323Swnj } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && 2392323Swnj ip->i_un.i_rdev == dev) 2402323Swnj stillopen++; 24137Sbill ip = mp->m_inodp; 24237Sbill ip->i_flag &= ~IMOUNT; 2434828Swnj ilock(ip); 24437Sbill iput(ip); 2452323Swnj if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) 2462323Swnj panic("umount"); 2472323Swnj bp->b_flags &= ~B_LOCKED; 2482304Skre flag = !bp->b_un.b_filsys->s_ronly; 24937Sbill mp->m_bufp = NULL; 25037Sbill brelse(bp); 2512454Swnj mpurge(mp - &mount[0]); 2522304Skre if (!stillopen) { 2532304Skre (*bdevsw[major(dev)].d_close)(dev, flag); 2542304Skre binval(dev); 2552304Skre } 25637Sbill } 25737Sbill 25837Sbill /* 25937Sbill * Common code for mount and umount. 26037Sbill * Check that the user's argument is a reasonable 26137Sbill * thing on which to mount, and return the device number if so. 26237Sbill */ 26337Sbill dev_t 26437Sbill getmdev() 26537Sbill { 26637Sbill dev_t dev; 26737Sbill register struct inode *ip; 26837Sbill 26937Sbill if (!suser()) 27037Sbill return(NODEV); 27137Sbill ip = namei(uchar, 0); 2724828Swnj if (ip == NULL) 27337Sbill return(NODEV); 2744828Swnj if ((ip->i_mode&IFMT) != IFBLK) 27537Sbill u.u_error = ENOTBLK; 27637Sbill dev = (dev_t)ip->i_un.i_rdev; 2774828Swnj if (major(dev) >= nblkdev) 27837Sbill u.u_error = ENXIO; 27937Sbill iput(ip); 28037Sbill return(dev); 28137Sbill } 282