1*5582Swnj /* vfs_syscalls.c 4.17 82/01/19 */ 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) 129*5582Swnj closef(u.u_ofile[i], 0); 130*5582Swnj if (u.u_error) 131*5582Swnj return; 13237Sbill u.u_ofile[i] = fp; 13337Sbill fp->f_count++; 13437Sbill } 13537Sbill } 13637Sbill 13737Sbill /* 1384828Swnj * Mount system call. 13937Sbill */ 1404828Swnj smount() 1414828Swnj { 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(); 1574828Swnj if (u.u_error) 15837Sbill return; 15937Sbill u.u_dirp = (caddr_t)uap->freg; 16037Sbill ip = namei(uchar, 0); 1614828Swnj if (ip == NULL) 16237Sbill return; 1634828Swnj if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) 16437Sbill goto out; 16537Sbill smp = NULL; 1664828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { 1674828Swnj if (mp->m_bufp != NULL) { 1684828Swnj if (dev == mp->m_dev) 16937Sbill goto out; 17037Sbill } else 1714828Swnj if (smp == NULL) 17237Sbill smp = mp; 17337Sbill } 17437Sbill mp = smp; 1754828Swnj if (mp == NULL) 17637Sbill goto out; 17737Sbill (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); 1784828Swnj if (u.u_error) 17937Sbill goto out; 18037Sbill bp = bread(dev, SUPERB); 1814828Swnj 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; 2024828Swnj irele(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(); 2264828Swnj if (u.u_error) 22737Sbill return; 22837Sbill xumount(dev); /* remove unused sticky files from text table */ 2295416Swnj update(0); 2304828Swnj for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) 2314828Swnj 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; 2384828Swnj 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; 2474828Swnj ilock(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); 2764828Swnj if (ip == NULL) 27737Sbill return(NODEV); 2784828Swnj if ((ip->i_mode&IFMT) != IFBLK) 27937Sbill u.u_error = ENOTBLK; 28037Sbill dev = (dev_t)ip->i_un.i_rdev; 2814828Swnj if (major(dev) >= nblkdev) 28237Sbill u.u_error = ENXIO; 28337Sbill iput(ip); 28437Sbill return(dev); 28537Sbill } 286