xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 7535)
1*7535Sroot /*	vfs_syscalls.c	4.31	82/07/25	*/
237Sbill 
337Sbill #include "../h/param.h"
437Sbill #include "../h/systm.h"
537Sbill #include "../h/dir.h"
637Sbill #include "../h/user.h"
76254Sroot #include "../h/file.h"
86574Smckusic #include "../h/stat.h"
937Sbill #include "../h/inode.h"
106574Smckusic #include "../h/fs.h"
116254Sroot #include "../h/buf.h"
126254Sroot #include "../h/proc.h"
136254Sroot #include "../h/inline.h"
147439Sroot #ifdef EFS
157439Sroot #include "../net/in.h"
167439Sroot #include "../h/efs.h"
177439Sroot #endif
187482Skre #include "../h/quota.h"
197505Sroot #include "../h/descrip.h"
2037Sbill 
216254Sroot chdir()
226254Sroot {
236254Sroot 
246254Sroot 	chdirec(&u.u_cdir);
256254Sroot }
266254Sroot 
276254Sroot chroot()
286254Sroot {
296254Sroot 
306254Sroot 	if (suser())
316254Sroot 		chdirec(&u.u_rdir);
326254Sroot }
336254Sroot 
346254Sroot chdirec(ipp)
356254Sroot register struct inode **ipp;
366254Sroot {
376254Sroot 	register struct inode *ip;
386254Sroot 	struct a {
396254Sroot 		char	*fname;
406254Sroot 	};
416254Sroot 
426254Sroot 	ip = namei(uchar, 0, 1);
436254Sroot 	if(ip == NULL)
446254Sroot 		return;
456254Sroot 	if((ip->i_mode&IFMT) != IFDIR) {
466254Sroot 		u.u_error = ENOTDIR;
476254Sroot 		goto bad;
486254Sroot 	}
496254Sroot 	if(access(ip, IEXEC))
506254Sroot 		goto bad;
517122Smckusick 	iunlock(ip);
527142Smckusick 	if (*ipp)
537142Smckusick 		irele(*ipp);
546254Sroot 	*ipp = ip;
556254Sroot 	return;
566254Sroot 
576254Sroot bad:
586254Sroot 	iput(ip);
596254Sroot }
606254Sroot 
6137Sbill /*
626254Sroot  * Open system call.
636254Sroot  */
646254Sroot open()
656254Sroot {
666254Sroot 	register struct inode *ip;
676254Sroot 	register struct a {
686254Sroot 		char	*fname;
696254Sroot 		int	rwmode;
706254Sroot 	} *uap;
716254Sroot 
726254Sroot 	uap = (struct a *)u.u_ap;
736254Sroot 	ip = namei(uchar, 0, 1);
746254Sroot 	if (ip == NULL)
756254Sroot 		return;
766254Sroot 	open1(ip, ++uap->rwmode, 0);
776254Sroot }
786254Sroot 
796254Sroot /*
806254Sroot  * Creat system call.
816254Sroot  */
827505Sroot ocreat()
836254Sroot {
846254Sroot 	register struct inode *ip;
856254Sroot 	register struct a {
866254Sroot 		char	*fname;
876254Sroot 		int	fmode;
886254Sroot 	} *uap;
896254Sroot 
906254Sroot 	uap = (struct a *)u.u_ap;
916254Sroot 	ip = namei(uchar, 1, 1);
926254Sroot 	if (ip == NULL) {
936254Sroot 		if (u.u_error)
946254Sroot 			return;
956254Sroot 		ip = maknode(uap->fmode&07777&(~ISVTX));
966254Sroot 		if (ip==NULL)
976254Sroot 			return;
986254Sroot 		open1(ip, FWRITE, 2);
996254Sroot 	} else
1006254Sroot 		open1(ip, FWRITE, 1);
1016254Sroot }
1026254Sroot 
1036254Sroot /*
1046254Sroot  * Common code for open and creat.
1056254Sroot  * Check permissions, allocate an open file structure,
1066254Sroot  * and call the device open routine if any.
1076254Sroot  */
1086254Sroot open1(ip, mode, trf)
1096254Sroot 	register struct inode *ip;
1106254Sroot 	register mode;
1116254Sroot {
1126254Sroot 	register struct file *fp;
1136254Sroot 	int i;
1146254Sroot 
1156254Sroot 	if (trf != 2) {
1166254Sroot 		if (mode&FREAD)
1176254Sroot 			(void) access(ip, IREAD);
1186254Sroot 		if (mode&FWRITE) {
1196254Sroot 			(void) access(ip, IWRITE);
1206254Sroot 			if ((ip->i_mode&IFMT) == IFDIR)
1216254Sroot 				u.u_error = EISDIR;
1226254Sroot 		}
1236254Sroot 	}
1247142Smckusick 	if (u.u_error) {
1257142Smckusick 		iput(ip);
1267142Smckusick 		return;
1277142Smckusick 	}
1286254Sroot 	if (trf == 1)
1296254Sroot 		itrunc(ip);
1307122Smckusick 	iunlock(ip);
1316254Sroot 	if ((fp = falloc()) == NULL)
1326254Sroot 		goto out;
1336254Sroot 	fp->f_flag = mode&(FREAD|FWRITE);
1347505Sroot 	fp->f_type = DTYPE_FILE;
1356254Sroot 	i = u.u_r.r_val1;
1366254Sroot 	fp->f_inode = ip;
1377439Sroot #ifdef EFS
1387439Sroot 	openi(ip, mode&(FREAD|FWRITE), trf);
1397439Sroot #else
1406254Sroot 	openi(ip, mode&(FREAD|FWRITE));
1417439Sroot #endif
1426254Sroot 	if (u.u_error == 0)
1436254Sroot 		return;
1446254Sroot 	u.u_ofile[i] = NULL;
1456254Sroot 	fp->f_count--;
1466254Sroot out:
1477142Smckusick 	irele(ip);
1486254Sroot }
1496254Sroot 
1506254Sroot /*
1516254Sroot  * Mknod system call
1526254Sroot  */
1536254Sroot mknod()
1546254Sroot {
1556254Sroot 	register struct inode *ip;
1566254Sroot 	register struct a {
1576254Sroot 		char	*fname;
1586254Sroot 		int	fmode;
1596254Sroot 		int	dev;
1606254Sroot 	} *uap;
1616254Sroot 
1626254Sroot 	uap = (struct a *)u.u_ap;
1636254Sroot 	if (suser()) {
1646254Sroot 		ip = namei(uchar, 1, 0);
1656254Sroot 		if (ip != NULL) {
1666254Sroot 			u.u_error = EEXIST;
1676254Sroot 			goto out;
1686254Sroot 		}
1696254Sroot 	}
1706254Sroot 	if (u.u_error)
1716254Sroot 		return;
1726254Sroot 	ip = maknode(uap->fmode);
1736254Sroot 	if (ip == NULL)
1746254Sroot 		return;
1756254Sroot 	if (uap->dev) {
1766254Sroot 		/*
1776254Sroot 		 * Want to be able to use this to make badblock
1786254Sroot 		 * inodes, so don't truncate the dev number.
1796254Sroot 		 */
1806574Smckusic 		ip->i_rdev = uap->dev;
1816254Sroot 		ip->i_flag |= IACC|IUPD|ICHG;
1826254Sroot 	}
1836254Sroot 
1846254Sroot out:
1856254Sroot 	iput(ip);
1866254Sroot }
1876254Sroot 
1886254Sroot /*
1896254Sroot  * link system call
1906254Sroot  */
1916254Sroot link()
1926254Sroot {
1936254Sroot 	register struct inode *ip, *xp;
1946254Sroot 	register struct a {
1956254Sroot 		char	*target;
1966254Sroot 		char	*linkname;
1976254Sroot 	} *uap;
1986254Sroot 
1996254Sroot 	uap = (struct a *)u.u_ap;
2006254Sroot 	ip = namei(uchar, 0, 1);    /* well, this routine is doomed anyhow */
2016254Sroot 	if (ip == NULL)
2026254Sroot 		return;
2037439Sroot 	if ((ip->i_mode&IFMT)==IFDIR && !suser()) {
2047439Sroot 		iput(ip);
2057439Sroot 		return;
2067439Sroot 	}
2076254Sroot 	ip->i_nlink++;
2086254Sroot 	ip->i_flag |= ICHG;
2096254Sroot 	iupdat(ip, &time, &time, 1);
2107122Smckusick 	iunlock(ip);
2116254Sroot 	u.u_dirp = (caddr_t)uap->linkname;
2126254Sroot 	xp = namei(uchar, 1, 0);
2136254Sroot 	if (xp != NULL) {
2146254Sroot 		u.u_error = EEXIST;
2156254Sroot 		iput(xp);
2166254Sroot 		goto out;
2176254Sroot 	}
2186254Sroot 	if (u.u_error)
2196254Sroot 		goto out;
2206254Sroot 	if (u.u_pdir->i_dev != ip->i_dev) {
2216254Sroot 		iput(u.u_pdir);
2226254Sroot 		u.u_error = EXDEV;
2236254Sroot 		goto out;
2246254Sroot 	}
225*7535Sroot 	direnter(ip);
2266254Sroot out:
2276254Sroot 	if (u.u_error) {
2286254Sroot 		ip->i_nlink--;
2296254Sroot 		ip->i_flag |= ICHG;
2306254Sroot 	}
2316254Sroot out1:
2327142Smckusick 	irele(ip);
2336254Sroot }
2346254Sroot 
2356254Sroot /*
2366254Sroot  * symlink -- make a symbolic link
2376254Sroot  */
2386254Sroot symlink()
2396254Sroot {
2406254Sroot 	register struct a {
2416254Sroot 		char	*target;
2426254Sroot 		char	*linkname;
2436254Sroot 	} *uap;
2446254Sroot 	register struct inode *ip;
2456254Sroot 	register char *tp;
2466254Sroot 	register c, nc;
2476254Sroot 
2486254Sroot 	uap = (struct a *)u.u_ap;
2496254Sroot 	tp = uap->target;
2506254Sroot 	nc = 0;
2516254Sroot 	while (c = fubyte(tp)) {
2526254Sroot 		if (c < 0) {
2536254Sroot 			u.u_error = EFAULT;
2546254Sroot 			return;
2556254Sroot 		}
2566254Sroot 		tp++;
2576254Sroot 		nc++;
2586254Sroot 	}
2596254Sroot 	u.u_dirp = uap->linkname;
2606254Sroot 	ip = namei(uchar, 1, 0);
2616254Sroot 	if (ip) {
2626254Sroot 		iput(ip);
2636254Sroot 		u.u_error = EEXIST;
2646254Sroot 		return;
2656254Sroot 	}
2666254Sroot 	if (u.u_error)
2676254Sroot 		return;
2686254Sroot 	ip = maknode(IFLNK | 0777);
2696254Sroot 	if (ip == NULL)
2706254Sroot 		return;
2716254Sroot 	u.u_base = uap->target;
2726254Sroot 	u.u_count = nc;
2736254Sroot 	u.u_offset = 0;
2746254Sroot 	u.u_segflg = 0;
2756254Sroot 	writei(ip);
2766254Sroot 	iput(ip);
2776254Sroot }
2786254Sroot 
2796254Sroot /*
2806254Sroot  * Unlink system call.
2816254Sroot  * Hard to avoid races here, especially
2826254Sroot  * in unlinking directories.
2836254Sroot  */
2846254Sroot unlink()
2856254Sroot {
2866254Sroot 	register struct inode *ip, *pp;
2876254Sroot 	struct a {
2886254Sroot 		char	*fname;
2896254Sroot 	};
2906574Smckusic 	struct fs *fs;
2916574Smckusic 	struct buf *bp;
2926574Smckusic 	int lbn, bn, base;
2937142Smckusick 	int unlinkingdot = 0;
2946254Sroot 
2956254Sroot 	pp = namei(uchar, 2, 0);
296*7535Sroot 	if (pp == NULL)
2976254Sroot 		return;
2987439Sroot #ifdef EFS
2997439Sroot 	/* divert to extended file system if off machine. */
3007439Sroot 	if (efsinode(pp)) {
3017439Sroot 		dev_t ndev = pp->i_rdev;
3027439Sroot 
3037439Sroot 		iput(pp);	/* avoid recursive hang on inode */
3047439Sroot 		efsunlink(ndev);
3057439Sroot 		if (u.u_error != EEXIST)
3067439Sroot 			return;
3077439Sroot 
3087439Sroot 		/*
3097439Sroot 		 * If a null pathname remainder, then do
3107439Sroot 		 * the unlink locally after restoring state.
3117439Sroot 		 */
3127439Sroot 		u.u_error = 0;
3137439Sroot 		u.u_dirp = (caddr_t)u.u_arg[0];
3147439Sroot 		pp = namei(uchar, 2, 0);
3157439Sroot 	}
3167439Sroot #endif
3177439Sroot 
3186254Sroot 	/*
3196254Sroot 	 * Check for unlink(".")
3206254Sroot 	 * to avoid hanging on the iget
3216254Sroot 	 */
3226254Sroot 	if (pp->i_number == u.u_dent.d_ino) {
3236254Sroot 		ip = pp;
3246254Sroot 		ip->i_count++;
3257142Smckusick 		unlinkingdot++;
3266254Sroot 	} else
3276574Smckusic 		ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
3286254Sroot 	if(ip == NULL)
3296254Sroot 		goto out1;
3306254Sroot 	if((ip->i_mode&IFMT)==IFDIR && !suser())
3316254Sroot 		goto out;
3326254Sroot 	/*
3336254Sroot 	 * Don't unlink a mounted file.
3346254Sroot 	 */
3356254Sroot 	if (ip->i_dev != pp->i_dev) {
3366254Sroot 		u.u_error = EBUSY;
3376254Sroot 		goto out;
3386254Sroot 	}
3396254Sroot 	if (ip->i_flag&ITEXT)
3406254Sroot 		xrele(ip);	/* try once to free text */
341*7535Sroot 	if (dirremove()) {
342*7535Sroot 		ip->i_nlink--;
343*7535Sroot 		ip->i_flag |= ICHG;
3446254Sroot 	}
3456254Sroot out:
3467142Smckusick 	if (unlinkingdot)
3477142Smckusick 		irele(ip);
3487142Smckusick 	else
3497142Smckusick 		iput(ip);
3506254Sroot out1:
3516254Sroot 	iput(pp);
3526254Sroot }
3536254Sroot 
3546254Sroot /*
3556254Sroot  * Seek system call
3566254Sroot  */
3576254Sroot seek()
3586254Sroot {
3596254Sroot 	register struct file *fp;
3606254Sroot 	register struct a {
3616254Sroot 		int	fdes;
3626254Sroot 		off_t	off;
3636254Sroot 		int	sbase;
3646254Sroot 	} *uap;
3656254Sroot 
3666254Sroot 	uap = (struct a *)u.u_ap;
3676254Sroot 	fp = getf(uap->fdes);
3686254Sroot 	if (fp == NULL)
3696254Sroot 		return;
3707505Sroot 	if (fp->f_type == DTYPE_SOCKET) {
3716254Sroot 		u.u_error = ESPIPE;
3726254Sroot 		return;
3736254Sroot 	}
3746254Sroot 	if (uap->sbase == 1)
3756254Sroot 		uap->off += fp->f_offset;
3767439Sroot 	else if (uap->sbase == 2) {
3777439Sroot #ifdef EFS
3787439Sroot 		struct inode *ip = fp->f_inode;
3797439Sroot 		uap->off += efsinode(ip) ? efsfilesize(fp) : ip->i_size;
3807439Sroot #else
3816254Sroot 		uap->off += fp->f_inode->i_size;
3827439Sroot #endif
3837439Sroot 	}
3846254Sroot 	fp->f_offset = uap->off;
3856254Sroot 	u.u_r.r_off = uap->off;
3866254Sroot }
3876254Sroot 
3886254Sroot /*
3896254Sroot  * Access system call
3906254Sroot  */
3916254Sroot saccess()
3926254Sroot {
3936254Sroot 	register svuid, svgid;
3946254Sroot 	register struct inode *ip;
3956254Sroot 	register struct a {
3966254Sroot 		char	*fname;
3976254Sroot 		int	fmode;
3986254Sroot 	} *uap;
3996254Sroot 
4006254Sroot 	uap = (struct a *)u.u_ap;
4016254Sroot 	svuid = u.u_uid;
4026254Sroot 	svgid = u.u_gid;
4036254Sroot 	u.u_uid = u.u_ruid;
4046254Sroot 	u.u_gid = u.u_rgid;
4056254Sroot 	ip = namei(uchar, 0, 1);
4067439Sroot #ifdef EFS
4077439Sroot 	if (efsinode(ip)) {
4087439Sroot 		dev_t ndev = ip->i_rdev;
4097439Sroot 
4107439Sroot 		iput(ip);
4117439Sroot 		efssaccess(ndev);
4127439Sroot 		if (u.u_error != EEXIST)
4137439Sroot 			return;
4147439Sroot 		u.u_error = 0;
4157439Sroot 		u.u_dirp = (caddr_t)u.u_arg[0];
4167439Sroot 		ip = namei(uchar, 0, 1);
4177439Sroot 	}
4187439Sroot #endif
4196254Sroot 	if (ip != NULL) {
4206254Sroot 		if (uap->fmode&(IREAD>>6))
4216254Sroot 			(void) access(ip, IREAD);
4226254Sroot 		if (uap->fmode&(IWRITE>>6))
4236254Sroot 			(void) access(ip, IWRITE);
4246254Sroot 		if (uap->fmode&(IEXEC>>6))
4256254Sroot 			(void) access(ip, IEXEC);
4266254Sroot 		iput(ip);
4276254Sroot 	}
4286254Sroot 	u.u_uid = svuid;
4296254Sroot 	u.u_gid = svgid;
4306254Sroot }
4316254Sroot 
4326254Sroot /*
43337Sbill  * the fstat system call.
43437Sbill  */
43537Sbill fstat()
43637Sbill {
43737Sbill 	register struct file *fp;
43837Sbill 	register struct a {
43937Sbill 		int	fdes;
44037Sbill 		struct stat *sb;
44137Sbill 	} *uap;
44237Sbill 
44337Sbill 	uap = (struct a *)u.u_ap;
44437Sbill 	fp = getf(uap->fdes);
4454828Swnj 	if (fp == NULL)
44637Sbill 		return;
4477439Sroot #ifdef EFS
4487439Sroot 	if (efsinode(fp->f_inode)) {
4497439Sroot 		efsfstat(fp->f_inode->i_rdev, fp);
4507439Sroot 		return;
4517439Sroot 	}
4527439Sroot #endif
4537505Sroot 	if (fp->f_type == DTYPE_SOCKET)
4544891Swnj 		u.u_error = sostat(fp->f_socket, uap->sb);
4554828Swnj 	else
4564828Swnj 		stat1(fp->f_inode, uap->sb);
45737Sbill }
45837Sbill 
45937Sbill /*
4606574Smckusic  * Stat system call.  This version follows links.
46137Sbill  */
46237Sbill stat()
46337Sbill {
46437Sbill 	register struct inode *ip;
46537Sbill 	register struct a {
46637Sbill 		char	*fname;
46737Sbill 		struct stat *sb;
46837Sbill 	} *uap;
46937Sbill 
47037Sbill 	uap = (struct a *)u.u_ap;
4716423Sroot 	ip = namei(uchar, 0, 1);
4724828Swnj 	if (ip == NULL)
47337Sbill 		return;
4747439Sroot #ifdef EFS
4757439Sroot 	if (efsinode(ip)) {
4767439Sroot 		dev_t ndev = ip->i_rdev;
4777439Sroot 
4787439Sroot 		iput(ip);
4797439Sroot 		efsstat(ndev);
4807439Sroot 		if (u.u_error != EEXIST)
4817439Sroot 			return;
4827439Sroot 		u.u_error = 0;
4837439Sroot 		u.u_dirp = (caddr_t)u.u_arg[0];
4847439Sroot 		ip = namei(uchar, 0, 1);
4857439Sroot 	}
4867439Sroot #endif
4873624Sroot 	stat1(ip, uap->sb);
48837Sbill 	iput(ip);
48937Sbill }
49037Sbill 
49137Sbill /*
4926574Smckusic  * Lstat system call.  This version does not follow links.
4935992Swnj  */
4945992Swnj lstat()
4955992Swnj {
4965992Swnj 	register struct inode *ip;
4975992Swnj 	register struct a {
4985992Swnj 		char	*fname;
4995992Swnj 		struct stat *sb;
5005992Swnj 	} *uap;
5015992Swnj 
5025992Swnj 	uap = (struct a *)u.u_ap;
5036423Sroot 	ip = namei(uchar, 0, 0);
5045992Swnj 	if (ip == NULL)
5055992Swnj 		return;
5067439Sroot #ifdef EFS
5077439Sroot 	if (efsinode(ip)) {
5087439Sroot 		dev_t ndev = ip->i_rdev;
5097439Sroot 
5107439Sroot 		iput(ip);
5117439Sroot 		efslstat(ndev);
5127439Sroot 		if (u.u_error != EEXIST)
5137439Sroot 			return;
5147439Sroot 		u.u_error = 0;
5157439Sroot 		u.u_dirp = (caddr_t)u.u_arg[0];
5167439Sroot 		ip = namei(uchar, 0, 0);
5177439Sroot 	}
5187439Sroot #endif
5196153Ssam 	stat1(ip, uap->sb);
5205992Swnj 	iput(ip);
5215992Swnj }
5225992Swnj 
5235992Swnj /*
52437Sbill  * The basic routine for fstat and stat:
52537Sbill  * get the inode and pass appropriate parts back.
52637Sbill  */
5273624Sroot stat1(ip, ub)
5284828Swnj 	register struct inode *ip;
5294828Swnj 	struct stat *ub;
53037Sbill {
53137Sbill 	struct stat ds;
53237Sbill 
5331204Sbill 	IUPDAT(ip, &time, &time, 0);
53437Sbill 	/*
5357023Smckusick 	 * Copy from inode table
53637Sbill 	 */
53737Sbill 	ds.st_dev = ip->i_dev;
53837Sbill 	ds.st_ino = ip->i_number;
53937Sbill 	ds.st_mode = ip->i_mode;
54037Sbill 	ds.st_nlink = ip->i_nlink;
54137Sbill 	ds.st_uid = ip->i_uid;
54237Sbill 	ds.st_gid = ip->i_gid;
5436574Smckusic 	ds.st_rdev = (dev_t)ip->i_rdev;
5443624Sroot 	ds.st_size = ip->i_size;
5456574Smckusic 	ds.st_atime = ip->i_atime;
5466574Smckusic 	ds.st_mtime = ip->i_mtime;
5476574Smckusic 	ds.st_ctime = ip->i_ctime;
5487023Smckusick 	ds.st_blksize = ip->i_fs->fs_bsize;
54937Sbill 	if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
55037Sbill 		u.u_error = EFAULT;
55137Sbill }
55237Sbill 
55337Sbill /*
5545992Swnj  * Return target name of a symbolic link
55537Sbill  */
5565992Swnj readlink()
5575992Swnj {
5585992Swnj 	register struct inode *ip;
5595992Swnj 	register struct a {
5605992Swnj 		char	*name;
5615992Swnj 		char	*buf;
5625992Swnj 		int	count;
5635992Swnj 	} *uap;
5645992Swnj 
5655992Swnj 	ip = namei(uchar, 0, 0);
5665992Swnj 	if (ip == NULL)
5675992Swnj 		return;
5687439Sroot #ifdef EFS
5697439Sroot 	if (efsinode(ip)) {
5707439Sroot 		dev_t ndev = ip->i_rdev;
5717439Sroot 
5727439Sroot 		iput(ip);
5737439Sroot 		efsreadlink(ndev);
5747439Sroot 		if (u.u_error != EEXIST)
5757439Sroot 			return;
5767439Sroot 		u.u_error = 0;
5777439Sroot 		u.u_dirp = (caddr_t)u.u_arg[0];
5787439Sroot 		ip = namei(uchar, 0, 0);
5797439Sroot 		return (0);
5807439Sroot 	}
5817439Sroot #endif
5825992Swnj 	if ((ip->i_mode&IFMT) != IFLNK) {
5835992Swnj 		u.u_error = ENXIO;
5845992Swnj 		goto out;
5855992Swnj 	}
5865992Swnj 	uap = (struct a *)u.u_ap;
5875992Swnj 	u.u_offset = 0;
5885992Swnj 	u.u_base = uap->buf;
5895992Swnj 	u.u_count = uap->count;
5905992Swnj 	u.u_segflg = 0;
5915992Swnj 	readi(ip);
5925992Swnj out:
5935992Swnj 	iput(ip);
5945992Swnj 	u.u_r.r_val1 = uap->count - u.u_count;
5955992Swnj }
5965992Swnj 
5976254Sroot chmod()
5985992Swnj {
5996254Sroot 	register struct inode *ip;
6005992Swnj 	register struct a {
6016254Sroot 		char	*fname;
6026254Sroot 		int	fmode;
6035992Swnj 	} *uap;
6045992Swnj 
6055992Swnj 	uap = (struct a *)u.u_ap;
6066254Sroot 	if ((ip = owner(1)) == NULL)
6075992Swnj 		return;
6087439Sroot #ifdef EFS
6097439Sroot 	if (efsinode(ip)) {
6107439Sroot 		dev_t ndev = ip->i_rdev;
6117439Sroot 
6127439Sroot 		iput(ip);
6137439Sroot 		efschmod(ndev);
6147439Sroot 		if (u.u_error != EEXIST)
6157439Sroot 			return;
6167439Sroot 		u.u_error = 0;
6177439Sroot 		u.u_dirp = (caddr_t)u.u_arg[0];
6187439Sroot 		ip = owner(1);
6197439Sroot 	}
6207439Sroot #endif
6216254Sroot 	ip->i_mode &= ~07777;
6227439Sroot 	if (u.u_uid) {
6236254Sroot 		uap->fmode &= ~ISVTX;
6247439Sroot 		if (ip->i_gid >= NGRPS ||
6257439Sroot 		    (u.u_grps[ip->i_gid/(sizeof(int)*8)] &
6267439Sroot 		     (1 << ip->i_gid%(sizeof(int)*8))) == 0)
6277439Sroot 			uap->fmode &= ~ISGID;
6287482Skre #if	MUSH
6297482Skre 		if (u.u_quota->q_syflags & QF_UMASK && u.u_uid != 0 &&
6307482Skre 		    (ip->i_mode & IFMT) != IFCHR)
6317482Skre 			uap->fmode &= ~u.u_cmask;
6327482Skre #endif
6337439Sroot 	}
6346254Sroot 	ip->i_mode |= uap->fmode&07777;
6356254Sroot 	ip->i_flag |= ICHG;
6366254Sroot 	if (ip->i_flag&ITEXT && (ip->i_mode&ISVTX)==0)
6376254Sroot 		xrele(ip);
6387482Skre #ifdef MELB
6397482Skre 	if ((ip->i_mode & ISUID) && ip->i_uid == 0)
6407482Skre 		printf("%s: ino %d (%s) setuid root\n"
6417482Skre 		    , getfs(ip->i_dev)->s_fsmnt
6427482Skre 		    , ip->i_number
6437482Skre 		    , u.u_dent.d_name
6447482Skre 		);
6457482Skre #endif
6465992Swnj 	iput(ip);
6475992Swnj }
6485992Swnj 
6496254Sroot chown()
65037Sbill {
6516254Sroot 	register struct inode *ip;
65237Sbill 	register struct a {
6536254Sroot 		char	*fname;
6546254Sroot 		int	uid;
6556254Sroot 		int	gid;
65637Sbill 	} *uap;
6577482Skre #if	QUOTA
6587482Skre 	register long change;
6597482Skre #endif
66037Sbill 
66137Sbill 	uap = (struct a *)u.u_ap;
6626254Sroot 	if (!suser() || (ip = owner(0)) == NULL)
66337Sbill 		return;
6647439Sroot #ifdef EFS
6657439Sroot 	if (efsinode(ip)) {
6667439Sroot 		dev_t ndev = ip->i_rdev;
6677439Sroot 
6687439Sroot 		iput(ip);
6697439Sroot 		efschown(ndev);
6707439Sroot 		if (u.u_error != EEXIST)
6717439Sroot 			return;
6727439Sroot 		u.u_error = 0;
6737439Sroot 		u.u_dirp = (caddr_t)u.u_arg[0];
6747439Sroot 		ip = owner(0);
6757439Sroot 	}
6767439Sroot #endif
6777482Skre #if	QUOTA
6787439Sroot 	/*
6797482Skre 	 * This doesn't allow for holes in files (which hopefully don't
6807482Skre 	 * happen often in files that we chown), and is not accurate anyway
6817482Skre 	 * (eg: it totally ignores 3 level indir blk files - but hopefully
6827482Skre 	 * noone who can make a file that big will have a quota)
6837482Skre 	 */
6847482Skre 	if (ip->i_uid == uap->uid)
6857482Skre 		change = 0;
6867482Skre 	else {
6877482Skre 		register struct fs *fs = ip->i_fs;
6887482Skre 
6897482Skre 		if (ip->i_size > (change = NDADDR * fs->fs_bsize)) {
6907482Skre 			register off_t size;
6917482Skre 
6927482Skre 			size = blkroundup(fs, ip->i_size) - change;
6937482Skre 			change += size;
6947482Skre 			change += fs->fs_bsize;
6957482Skre 			/* This assumes NIADDR <= 2 */
6967482Skre 			if (size > NINDIR(fs) * fs->fs_bsize)
6977482Skre 				change += fs->fs_bsize;
6987482Skre 		} else
6997482Skre 			change = fragroundup(fs, ip->i_size);
7007482Skre 		change /= DEV_BSIZE;
7017482Skre 	}
7027482Skre 	chkdq(ip, -change, 1);
7037482Skre 	chkiq(ip->i_dev, ip, ip->i_uid, 1);
7047482Skre 	dqrele(ip->i_dquot);
7057482Skre #endif
7067482Skre 	/*
7077439Sroot 	 * keep uid/gid's in sane range - no err, so chown(file, uid, -1)
7087439Sroot 	 * will do something useful
7097439Sroot 	 */
7107439Sroot 	if (uap->uid >= 0 && uap->uid <= 32767)	/* should have a const	*/
7117439Sroot 		ip->i_uid = uap->uid;
7127439Sroot 	if (uap->gid >= 0 && uap->gid <= 32767)	/* same here		*/
7137439Sroot 		ip->i_gid = uap->gid;
7146254Sroot 	ip->i_flag |= ICHG;
7156254Sroot 	if (u.u_ruid != 0)
7166254Sroot 		ip->i_mode &= ~(ISUID|ISGID);
7177482Skre #if	QUOTA
7187482Skre 	ip->i_dquot = inoquota(ip);
7197482Skre 	chkdq(ip, change, 1);
7207482Skre 	chkiq(ip->i_dev, NULL, uap->uid, 1);
7217482Skre #endif
7226254Sroot 	iput(ip);
72337Sbill }
72437Sbill 
72537Sbill /*
7266254Sroot  * Set IUPD and IACC times on file.
7276254Sroot  * Can't set ICHG.
72837Sbill  */
7296254Sroot utime()
7304828Swnj {
73137Sbill 	register struct a {
7326254Sroot 		char	*fname;
7336254Sroot 		time_t	*tptr;
73437Sbill 	} *uap;
7356254Sroot 	register struct inode *ip;
7366254Sroot 	time_t tv[2];
73737Sbill 
73837Sbill 	uap = (struct a *)u.u_ap;
7396254Sroot 	if ((ip = owner(1)) == NULL)
74037Sbill 		return;
7416254Sroot 	if (copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof(tv))) {
7426254Sroot 		u.u_error = EFAULT;
7436254Sroot 	} else {
7447439Sroot #ifdef EFS
7457439Sroot 		if (efsinode(ip)) {
7467439Sroot 			dev_t ndev = ip->i_rdev;
7477439Sroot 
7487439Sroot 			iput(ip);
7497439Sroot 			efsutime(ndev, uap->fname, tv);
7507439Sroot 			if (u.u_error != EEXIST)
7517439Sroot 				return;
7527439Sroot 			u.u_error = 0;
7537439Sroot 			u.u_dirp = (caddr_t)u.u_arg[0];
7547439Sroot 			ip = owner(1);
7557439Sroot 		}
7567439Sroot #endif
7576254Sroot 		ip->i_flag |= IACC|IUPD|ICHG;
7586254Sroot 		iupdat(ip, &tv[0], &tv[1], 0);
75937Sbill 	}
76037Sbill 	iput(ip);
76137Sbill }
76237Sbill 
7636254Sroot sync()
76437Sbill {
76537Sbill 
7665416Swnj 	update(0);
76737Sbill }
768*7535Sroot 
769*7535Sroot /*
770*7535Sroot  * Make a new file.
771*7535Sroot  */
772*7535Sroot struct inode *
773*7535Sroot maknode(mode)
774*7535Sroot 	int mode;
775*7535Sroot {
776*7535Sroot 	register struct inode *ip;
777*7535Sroot 	ino_t ipref;
778*7535Sroot 
779*7535Sroot 	if ((mode & IFMT) == IFDIR)
780*7535Sroot 		ipref = dirpref(u.u_pdir->i_fs);
781*7535Sroot 	else
782*7535Sroot 		ipref = u.u_pdir->i_number;
783*7535Sroot 	ip = ialloc(u.u_pdir, ipref, mode);
784*7535Sroot 	if (ip == NULL) {
785*7535Sroot 		iput(u.u_pdir);
786*7535Sroot 		return(NULL);
787*7535Sroot 	}
788*7535Sroot #ifdef	QUOTA
789*7535Sroot 	if (ip->i_dquot != NODQUOT)
790*7535Sroot 		panic("maknode: dquot");
791*7535Sroot #endif
792*7535Sroot 	ip->i_flag |= IACC|IUPD|ICHG;
793*7535Sroot 	if ((mode & IFMT) == 0)
794*7535Sroot 		mode |= IFREG;
795*7535Sroot 	ip->i_mode = mode & ~u.u_cmask;
796*7535Sroot 	ip->i_nlink = 1;
797*7535Sroot 	ip->i_uid = u.u_uid;
798*7535Sroot 	ip->i_gid = u.u_pdir->i_gid;
799*7535Sroot #ifdef	QUOTA
800*7535Sroot 	ip->i_dquot = inoquota(ip);
801*7535Sroot #endif
802*7535Sroot 
803*7535Sroot 	/*
804*7535Sroot 	 * Make sure inode goes to disk before directory entry.
805*7535Sroot 	 */
806*7535Sroot 	iupdat(ip, &time, &time, 1);
807*7535Sroot 	direnter(ip);
808*7535Sroot 	if (u.u_error) {
809*7535Sroot 		/*
810*7535Sroot 		 * write error occurred trying to update directory
811*7535Sroot 		 * so must deallocate the inode
812*7535Sroot 		 */
813*7535Sroot 		ip->i_nlink = 0;
814*7535Sroot 		ip->i_flag |= ICHG;
815*7535Sroot 		iput(ip);
816*7535Sroot 		return(NULL);
817*7535Sroot 	}
818*7535Sroot 	return(ip);
819*7535Sroot }
820