xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 2323)
1*2323Swnj /*	vfs_syscalls.c	4.4	01/31/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  */
13837Sbill smount()
13937Sbill {
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;
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;
184*2323Swnj 	bp->b_flags |= B_LOCKED;
185*2323Swnj 	mp->m_bufp = bp;
186*2323Swnj 	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;
19237Sbill 	brelse(bp);
19337Sbill 	ip->i_flag |= IMOUNT;
19437Sbill 	prele(ip);
19537Sbill 	return;
19637Sbill 
19737Sbill out:
19837Sbill 	u.u_error = EBUSY;
19937Sbill out1:
20037Sbill 	iput(ip);
20137Sbill }
20237Sbill 
20337Sbill /*
20437Sbill  * the umount system call.
20537Sbill  */
20637Sbill sumount()
20737Sbill {
20837Sbill 	dev_t dev;
20937Sbill 	register struct inode *ip;
21037Sbill 	register struct mount *mp;
21137Sbill 	struct buf *bp;
212*2323Swnj 	int stillopen, flag;
21337Sbill 	register struct a {
21437Sbill 		char	*fspec;
21537Sbill 	};
21637Sbill 
21737Sbill 	dev = getmdev();
21837Sbill 	if(u.u_error)
21937Sbill 		return;
22037Sbill 	xumount(dev);	/* remove unused sticky files from text table */
22137Sbill 	update();
22237Sbill 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
22337Sbill 		if(mp->m_bufp != NULL && dev == mp->m_dev)
22437Sbill 			goto found;
22537Sbill 	u.u_error = EINVAL;
22637Sbill 	return;
22737Sbill 
22837Sbill found:
22937Sbill 	for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
230*2323Swnj 		if (ip->i_number != 0 && dev == ip->i_dev) {
23137Sbill 			u.u_error = EBUSY;
23237Sbill 			return;
233*2323Swnj 		} else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
234*2323Swnj 		    ip->i_un.i_rdev == dev)
235*2323Swnj 			stillopen++;
23637Sbill 	ip = mp->m_inodp;
23737Sbill 	ip->i_flag &= ~IMOUNT;
23837Sbill 	plock(ip);
23937Sbill 	iput(ip);
240*2323Swnj 	if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
241*2323Swnj 		panic("umount");
242*2323Swnj 	bp->b_flags &= ~B_LOCKED;
2432304Skre 	flag = !bp->b_un.b_filsys->s_ronly;
24437Sbill 	mp->m_bufp = NULL;
24537Sbill 	brelse(bp);
2462304Skre 	if (!stillopen) {
2472304Skre 		mpurge(mp - &mount[0]);
2482304Skre 		(*bdevsw[major(dev)].d_close)(dev, flag);
2492304Skre 		binval(dev);
2502304Skre 	}
25137Sbill }
25237Sbill 
25337Sbill /*
25437Sbill  * Common code for mount and umount.
25537Sbill  * Check that the user's argument is a reasonable
25637Sbill  * thing on which to mount, and return the device number if so.
25737Sbill  */
25837Sbill dev_t
25937Sbill getmdev()
26037Sbill {
26137Sbill 	dev_t dev;
26237Sbill 	register struct inode *ip;
26337Sbill 
26437Sbill 	if (!suser())
26537Sbill 		return(NODEV);
26637Sbill 	ip = namei(uchar, 0);
26737Sbill 	if(ip == NULL)
26837Sbill 		return(NODEV);
26937Sbill 	if((ip->i_mode&IFMT) != IFBLK)
27037Sbill 		u.u_error = ENOTBLK;
27137Sbill 	dev = (dev_t)ip->i_un.i_rdev;
27237Sbill 	if(major(dev) >= nblkdev)
27337Sbill 		u.u_error = ENXIO;
27437Sbill 	iput(ip);
27537Sbill 	return(dev);
27637Sbill }
277