xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 1204)
1*1204Sbill /*	vfs_syscalls.c	3.5	10/03/80	*/
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 
68*1204Sbill 	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;
18437Sbill 	mp->m_bufp = geteblk();
18537Sbill 	bcopy((caddr_t)bp->b_un.b_addr, mp->m_bufp->b_un.b_addr, BSIZE);
18637Sbill 	fp = mp->m_bufp->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;
21237Sbill 	register struct a {
21337Sbill 		char	*fspec;
21437Sbill 	};
21537Sbill 
21637Sbill 	dev = getmdev();
21737Sbill 	if(u.u_error)
21837Sbill 		return;
21937Sbill 	xumount(dev);	/* remove unused sticky files from text table */
22037Sbill 	update();
22137Sbill 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
22237Sbill 		if(mp->m_bufp != NULL && dev == mp->m_dev)
22337Sbill 			goto found;
22437Sbill 	u.u_error = EINVAL;
22537Sbill 	return;
22637Sbill 
22737Sbill found:
22837Sbill 	for(ip = &inode[0]; ip < &inode[NINODE]; ip++)
22937Sbill 		if(ip->i_number != 0 && dev == ip->i_dev) {
23037Sbill 			u.u_error = EBUSY;
23137Sbill 			return;
23237Sbill 		}
233349Sbill 	mpurge(mp - &mount[0]);
23437Sbill 	(*bdevsw[major(dev)].d_close)(dev, 0);
23537Sbill 	ip = mp->m_inodp;
23637Sbill 	ip->i_flag &= ~IMOUNT;
23737Sbill 	plock(ip);
23837Sbill 	iput(ip);
23937Sbill 	bp = mp->m_bufp;
24037Sbill 	mp->m_bufp = NULL;
24137Sbill 	brelse(bp);
24237Sbill }
24337Sbill 
24437Sbill /*
24537Sbill  * Common code for mount and umount.
24637Sbill  * Check that the user's argument is a reasonable
24737Sbill  * thing on which to mount, and return the device number if so.
24837Sbill  */
24937Sbill dev_t
25037Sbill getmdev()
25137Sbill {
25237Sbill 	dev_t dev;
25337Sbill 	register struct inode *ip;
25437Sbill 
25537Sbill #ifdef UCB
25637Sbill 	if (!suser())
25737Sbill 		return(NODEV);
25837Sbill #endif
25937Sbill 	ip = namei(uchar, 0);
26037Sbill 	if(ip == NULL)
26137Sbill 		return(NODEV);
26237Sbill 	if((ip->i_mode&IFMT) != IFBLK)
26337Sbill 		u.u_error = ENOTBLK;
26437Sbill 	dev = (dev_t)ip->i_un.i_rdev;
26537Sbill 	if(major(dev) >= nblkdev)
26637Sbill 		u.u_error = ENXIO;
26737Sbill 	iput(ip);
26837Sbill 	return(dev);
26937Sbill }
270