xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 6153)
1*6153Ssam /*	vfs_syscalls.c	4.19	82/03/12	*/
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 /*
425992Swnj  * Stat system call.  This version does not follow links.
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;
535992Swnj 	ip = namei(uchar, 0, 0);
544828Swnj 	if (ip == NULL)
5537Sbill 		return;
563624Sroot 	stat1(ip, uap->sb);
5737Sbill 	iput(ip);
5837Sbill }
5937Sbill 
6037Sbill /*
615992Swnj  * Lstat system call.  This version does follow links.
625992Swnj  */
635992Swnj lstat()
645992Swnj {
655992Swnj 	register struct inode *ip;
665992Swnj 	register struct a {
675992Swnj 		char	*fname;
685992Swnj 		struct stat *sb;
695992Swnj 	} *uap;
705992Swnj 
715992Swnj 	uap = (struct a *)u.u_ap;
725992Swnj 	ip = namei(uchar, 0, 1);
735992Swnj 	if (ip == NULL)
745992Swnj 		return;
75*6153Ssam 	stat1(ip, uap->sb);
765992Swnj 	iput(ip);
775992Swnj }
785992Swnj 
795992Swnj /*
8037Sbill  * The basic routine for fstat and stat:
8137Sbill  * get the inode and pass appropriate parts back.
8237Sbill  */
833624Sroot stat1(ip, ub)
844828Swnj 	register struct inode *ip;
854828Swnj 	struct stat *ub;
8637Sbill {
8737Sbill 	register struct dinode *dp;
8837Sbill 	register struct buf *bp;
8937Sbill 	struct stat ds;
9037Sbill 
911204Sbill 	IUPDAT(ip, &time, &time, 0);
9237Sbill 	/*
934828Swnj 	 * First copy from inode table
9437Sbill 	 */
9537Sbill 	ds.st_dev = ip->i_dev;
9637Sbill 	ds.st_ino = ip->i_number;
9737Sbill 	ds.st_mode = ip->i_mode;
9837Sbill 	ds.st_nlink = ip->i_nlink;
9937Sbill 	ds.st_uid = ip->i_uid;
10037Sbill 	ds.st_gid = ip->i_gid;
10137Sbill 	ds.st_rdev = (dev_t)ip->i_un.i_rdev;
1023624Sroot 	ds.st_size = ip->i_size;
10337Sbill 	/*
1045992Swnj 	 * next the dates in the disk
10537Sbill 	 */
10637Sbill 	bp = bread(ip->i_dev, itod(ip->i_number));
10737Sbill 	dp = bp->b_un.b_dino;
10837Sbill 	dp += itoo(ip->i_number);
10937Sbill 	ds.st_atime = dp->di_atime;
11037Sbill 	ds.st_mtime = dp->di_mtime;
11137Sbill 	ds.st_ctime = dp->di_ctime;
11237Sbill 	brelse(bp);
11337Sbill 	if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
11437Sbill 		u.u_error = EFAULT;
11537Sbill }
11637Sbill 
11737Sbill /*
1185992Swnj  * Return target name of a symbolic link
11937Sbill  */
1205992Swnj readlink()
1215992Swnj {
1225992Swnj 	register struct inode *ip;
1235992Swnj 	register struct a {
1245992Swnj 		char	*name;
1255992Swnj 		char	*buf;
1265992Swnj 		int	count;
1275992Swnj 	} *uap;
1285992Swnj 
1295992Swnj 	ip = namei(uchar, 0, 0);
1305992Swnj 	if (ip == NULL)
1315992Swnj 		return;
1325992Swnj 	if ((ip->i_mode&IFMT) != IFLNK) {
1335992Swnj 		u.u_error = ENXIO;
1345992Swnj 		goto out;
1355992Swnj 	}
1365992Swnj 	uap = (struct a *)u.u_ap;
1375992Swnj 	u.u_offset = 0;
1385992Swnj 	u.u_base = uap->buf;
1395992Swnj 	u.u_count = uap->count;
1405992Swnj 	u.u_segflg = 0;
1415992Swnj 	readi(ip);
1425992Swnj out:
1435992Swnj 	iput(ip);
1445992Swnj 	u.u_r.r_val1 = uap->count - u.u_count;
1455992Swnj }
1465992Swnj 
1475992Swnj /*
1485992Swnj  * symlink -- make a symbolic link
1495992Swnj  */
1505992Swnj symlink()
1515992Swnj {
1525992Swnj 	register struct a {
1535992Swnj 		char	*target;
1545992Swnj 		char	*linkname;
1555992Swnj 	} *uap;
1565992Swnj 	register struct inode *ip;
1575992Swnj 	register char *tp;
1585992Swnj 	register c, nc;
1595992Swnj 
1605992Swnj 	uap = (struct a *)u.u_ap;
1615992Swnj 	tp = uap->target;
1625992Swnj 	nc = 0;
1635992Swnj 	while (c = fubyte(tp)) {
1645992Swnj 		if (c < 0) {
1655992Swnj 			u.u_error = EFAULT;
1665992Swnj 			return;
1675992Swnj 		}
1685992Swnj 		tp++;
1695992Swnj 		nc++;
1705992Swnj 	}
1715992Swnj 	u.u_dirp = uap->linkname;
1725992Swnj 	ip = namei(uchar, 1, 0);
1735992Swnj 	if (ip) {
1745992Swnj 		iput(ip);
1755992Swnj 		u.u_error = EEXIST;
1765992Swnj 		return;
1775992Swnj 	}
1785992Swnj 	ip = maknode(IFLNK | 0777);
1795992Swnj 	if (ip == NULL)
1805992Swnj 		return;
1815992Swnj 	u.u_base = uap->target;
1825992Swnj 	u.u_count = nc;
1835992Swnj 	u.u_offset = 0;
1845992Swnj 	u.u_segflg = 0;
1855992Swnj 	writei(ip);
1865992Swnj 	iput(ip);
1875992Swnj }
1885992Swnj 
1895992Swnj /*
1905992Swnj  * the dup system call.
1915992Swnj  */
19237Sbill dup()
19337Sbill {
19437Sbill 	register struct file *fp;
19537Sbill 	register struct a {
19637Sbill 		int	fdes;
19737Sbill 		int	fdes2;
19837Sbill 	} *uap;
19937Sbill 	register i, m;
20037Sbill 
20137Sbill 	uap = (struct a *)u.u_ap;
20237Sbill 	m = uap->fdes & ~077;
20337Sbill 	uap->fdes &= 077;
20437Sbill 	fp = getf(uap->fdes);
2054828Swnj 	if (fp == NULL)
20637Sbill 		return;
20737Sbill 	if ((m&0100) == 0) {
20837Sbill 		if ((i = ufalloc()) < 0)
20937Sbill 			return;
21037Sbill 	} else {
21137Sbill 		i = uap->fdes2;
21237Sbill 		if (i<0 || i>=NOFILE) {
21337Sbill 			u.u_error = EBADF;
21437Sbill 			return;
21537Sbill 		}
21637Sbill 		u.u_r.r_val1 = i;
21737Sbill 	}
2184828Swnj 	if (i != uap->fdes) {
21937Sbill 		if (u.u_ofile[i]!=NULL)
2205582Swnj 			closef(u.u_ofile[i], 0);
2215582Swnj 		if (u.u_error)
2225582Swnj 			return;
22337Sbill 		u.u_ofile[i] = fp;
22437Sbill 		fp->f_count++;
22537Sbill 	}
22637Sbill }
22737Sbill 
22837Sbill /*
2294828Swnj  * Mount system call.
23037Sbill  */
2314828Swnj smount()
2324828Swnj {
23337Sbill 	dev_t dev;
23437Sbill 	register struct inode *ip;
23537Sbill 	register struct mount *mp;
23637Sbill 	struct mount *smp;
23737Sbill 	register struct filsys *fp;
23837Sbill 	struct buf *bp;
23937Sbill 	register struct a {
24037Sbill 		char	*fspec;
24137Sbill 		char	*freg;
24237Sbill 		int	ronly;
24337Sbill 	} *uap;
2442879Swnj 	register char *cp;
24537Sbill 
24637Sbill 	uap = (struct a *)u.u_ap;
24737Sbill 	dev = getmdev();
2484828Swnj 	if (u.u_error)
24937Sbill 		return;
25037Sbill 	u.u_dirp = (caddr_t)uap->freg;
2515992Swnj 	ip = namei(uchar, 0, 1);
2524828Swnj 	if (ip == NULL)
25337Sbill 		return;
2544828Swnj 	if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
25537Sbill 		goto out;
25637Sbill 	smp = NULL;
2574828Swnj 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
2584828Swnj 		if (mp->m_bufp != NULL) {
2594828Swnj 			if (dev == mp->m_dev)
26037Sbill 				goto out;
26137Sbill 		} else
2624828Swnj 		if (smp == NULL)
26337Sbill 			smp = mp;
26437Sbill 	}
26537Sbill 	mp = smp;
2664828Swnj 	if (mp == NULL)
26737Sbill 		goto out;
26837Sbill 	(*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
2694828Swnj 	if (u.u_error)
27037Sbill 		goto out;
27137Sbill 	bp = bread(dev, SUPERB);
2724828Swnj 	if (u.u_error) {
27337Sbill 		brelse(bp);
27437Sbill 		goto out1;
27537Sbill 	}
27637Sbill 	mp->m_inodp = ip;
27737Sbill 	mp->m_dev = dev;
2782323Swnj 	bp->b_flags |= B_LOCKED;
2792323Swnj 	mp->m_bufp = bp;
2802323Swnj 	fp = bp->b_un.b_filsys;
28137Sbill 	fp->s_ilock = 0;
28237Sbill 	fp->s_flock = 0;
28337Sbill 	fp->s_ronly = uap->ronly & 1;
28437Sbill 	fp->s_nbehind = 0;
28537Sbill 	fp->s_lasti = 1;
2862879Swnj 	u.u_dirp = uap->freg;
2872879Swnj 	for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
2882879Swnj 		if ((*cp++ = uchar()) == 0)
2892879Swnj 			u.u_dirp--;		/* get 0 again */
2902879Swnj 	*cp = 0;
29137Sbill 	brelse(bp);
29237Sbill 	ip->i_flag |= IMOUNT;
2934828Swnj 	irele(ip);
29437Sbill 	return;
29537Sbill 
29637Sbill out:
29737Sbill 	u.u_error = EBUSY;
29837Sbill out1:
29937Sbill 	iput(ip);
30037Sbill }
30137Sbill 
30237Sbill /*
30337Sbill  * the umount system call.
30437Sbill  */
30537Sbill sumount()
30637Sbill {
30737Sbill 	dev_t dev;
30837Sbill 	register struct inode *ip;
30937Sbill 	register struct mount *mp;
31037Sbill 	struct buf *bp;
3112323Swnj 	int stillopen, flag;
31237Sbill 	register struct a {
31337Sbill 		char	*fspec;
31437Sbill 	};
31537Sbill 
31637Sbill 	dev = getmdev();
3174828Swnj 	if (u.u_error)
31837Sbill 		return;
31937Sbill 	xumount(dev);	/* remove unused sticky files from text table */
3205416Swnj 	update(0);
3214828Swnj 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
3224828Swnj 		if (mp->m_bufp != NULL && dev == mp->m_dev)
32337Sbill 			goto found;
32437Sbill 	u.u_error = EINVAL;
32537Sbill 	return;
32637Sbill 
32737Sbill found:
3282436Skre 	stillopen = 0;
3294828Swnj 	for (ip = inode; ip < inodeNINODE; ip++)
3302323Swnj 		if (ip->i_number != 0 && dev == ip->i_dev) {
33137Sbill 			u.u_error = EBUSY;
33237Sbill 			return;
3332323Swnj 		} else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
3342323Swnj 		    ip->i_un.i_rdev == dev)
3352323Swnj 			stillopen++;
33637Sbill 	ip = mp->m_inodp;
33737Sbill 	ip->i_flag &= ~IMOUNT;
3384828Swnj 	ilock(ip);
33937Sbill 	iput(ip);
3402323Swnj 	if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
3412323Swnj 		panic("umount");
3422323Swnj 	bp->b_flags &= ~B_LOCKED;
3432304Skre 	flag = !bp->b_un.b_filsys->s_ronly;
34437Sbill 	mp->m_bufp = NULL;
34537Sbill 	brelse(bp);
3462454Swnj 	mpurge(mp - &mount[0]);
3472304Skre 	if (!stillopen) {
3482304Skre 		(*bdevsw[major(dev)].d_close)(dev, flag);
3492304Skre 		binval(dev);
3502304Skre 	}
35137Sbill }
35237Sbill 
35337Sbill /*
35437Sbill  * Common code for mount and umount.
35537Sbill  * Check that the user's argument is a reasonable
35637Sbill  * thing on which to mount, and return the device number if so.
35737Sbill  */
35837Sbill dev_t
35937Sbill getmdev()
36037Sbill {
36137Sbill 	dev_t dev;
36237Sbill 	register struct inode *ip;
36337Sbill 
36437Sbill 	if (!suser())
36537Sbill 		return(NODEV);
3665992Swnj 	ip = namei(uchar, 0, 1);
3674828Swnj 	if (ip == NULL)
36837Sbill 		return(NODEV);
3694828Swnj 	if ((ip->i_mode&IFMT) != IFBLK)
37037Sbill 		u.u_error = ENOTBLK;
37137Sbill 	dev = (dev_t)ip->i_un.i_rdev;
3724828Swnj 	if (major(dev) >= nblkdev)
37337Sbill 		u.u_error = ENXIO;
37437Sbill 	iput(ip);
37537Sbill 	return(dev);
37637Sbill }
377