xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 5582)
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