⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gfs_syscalls.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Change current working directory (``.''). */chdir(){	chdirec(&u.u_cdir);}/* * Change notion of root (``/'') directory. */chroot(){	if (suser())		chdirec(&u.u_rdir);}/* * Common routine for chroot and chdir. */chdirec(gpp)	register struct gnode **gpp;{	register struct gnode *gp;	register struct a {		char	*fname;	} *uap = (struct a *)u.u_ap;	register struct nameidata *ndp = &u.u_nd;	register int ret;		ndp->ni_nameiop = LOOKUP | FOLLOW;	KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->fname, ndp->ni_dirp, MAXPATHLEN,				  (u_int *) 0)) {	        goto out;	}	gp = gfs_namei(ndp);		if (gp == NULL || u.u_error) 	        goto out;	if ((gp->g_mode&GFMT) != GFDIR) {		u.u_error = ENOTDIR;		goto bad;	}	if (access(gp, GEXEC))		goto bad;	gfs_unlock(gp);	if (*gpp)		grele(*gpp);	*gpp = gp;        goto out;bad:	gput(gp);out:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Open system call. */open(){	register struct a {		char	*fname;		int	mode;		int	crtmode;	} *uap = (struct a *) u.u_ap;	copen(uap->mode-FOPEN, uap->crtmode, uap->fname);}/* * Creat system call. */creat(){	register struct a {		char	*fname;		int	fmode;	} *uap = (struct a *)u.u_ap;	copen(FWRITE|FCREAT|FTRUNC, uap->fmode, uap->fname);}/* * Common code for open and creat. * Check permissions, allocate an open file structure, * and call the device open routine if any. */copen(mode, arg, fname)	register int mode;	int arg;	caddr_t fname;{	register struct gnode *gp;	register struct file *fp;	register struct nameidata *ndp = &u.u_nd;	register int i;	caddr_t value;	int ret;		if ((mode&(FREAD|FWRITE)) == 0) {		u.u_error = EINVAL;		return;	}	KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(fname, ndp->ni_dirp, MAXPATHLEN,				  (u_int *)0)) {	        goto out;	}	if (mode&FCREAT) {		if (mode & FEXCL)			ndp->ni_nameiop = CREATE;		else			ndp->ni_nameiop = CREATE | FOLLOW;		gp = gfs_namei(ndp);		if (gp == NULL) {			if (u.u_error) {			        goto out;			}			/*			 * Don't let a non super user create a regular file			 * with the sticky bit set.			 */			if (u.u_uid)				arg &= ~GSVTX;			if ((gp = GMAKNODE((arg & 07777) | GFREG, (dev_t) 0,					   ndp))			== (struct gnode *) GNOFUNC) {				u.u_error = EOPNOTSUPP;			        goto out;			}			if (gp == NULL) {			        goto out;			}			mode &= ~FTRUNC;		} else {			if (mode&FEXCL) {				u.u_error = EEXIST;				gput(gp);			        goto out;			}			mode &= ~FCREAT;		}	} else {		ndp->ni_nameiop = LOOKUP | FOLLOW;		gp = gfs_namei(ndp);		if (gp == NULL) {		        goto out;		}			}	if ((gp->g_mode & GFMT) == GFSOCK) {		u.u_error = EOPNOTSUPP;		goto free_gp;	}	if ((mode&FCREAT) == 0) {		if (mode&FREAD)			if (access(gp, GREAD))				goto free_gp;		if (mode&(FWRITE|FTRUNC)) {			if (access(gp, GWRITE))				goto free_gp;			if ((gp->g_mode&GFMT) == GFDIR) {				u.u_error = EISDIR;				goto free_gp;			}		}	}waitinuse:	while ((mode & FBLKINUSE) && (gp->g_flag & GINUSE))  { /*002*/		if (mode & FNDELAY) {			u.u_error = EWOULDBLOCK;			goto free_gp;		}		sleep_unlock((caddr_t)&gp->g_flag, PLOCK, &gp->g_lk);		gfs_lock(gp);			}	if ((gp->g_mode & GFMT) == GFPORT)		mode &= ~FTRUNC;	if (mode&FTRUNC) {		if (GTRUNC(gp, (u_long)0, u.u_cred) == GNOFUNC)			u.u_error = EOPNOTSUPP;		if (u.u_error)			goto free_gp;	}	/*	 * This should be done first to verify this resource exists.	 */	fp = falloc();	if (fp == NULL)		goto free_gp;			gfs_unlock(gp);	fp->f_flag = mode&FMASK;	if ((gp->g_mode & GFMT) == GFPORT) {		/*		 * For named-pipes, the FNDELAY flag must propagate to		 * the rdwr layer.  Also, FAPPEND must always be set so		 * that fp->f_offset is correctly maintained.		 */		fp->f_offset = 0;		fp->f_flag |= FAPPEND | (mode & FNDELAY);		fp->f_type = DTYPE_PORT;	}	else		fp->f_type = DTYPE_INODE;	fp->f_ops = &gnodeops;	fp->f_data = (caddr_t)gp;	i = u.u_r.r_val1;	if (setjmp(&u.u_qsave)) {		if (u.u_error == 0)			u.u_error = EINTR;		goto free_fp;	}	u.u_error = GOPEN(gp, mode);	if (u.u_error == 0) {		if ((mode&FBLKANDSET)==FBLKANDSET) { /*002*/			gp->g_flag |= GINUSE;			U_POFILE_SET(i, U_POFILE(i) | UF_INUSE);			(*fp->f_ops->fo_ioctl)(fp, FIOSINUSE, value, u.u_cred);			u.u_r.r_val1 = i;		}		goto out;	}	/*	 * The call to the sfs open routine failed or was interrupted. Clean	 * up the u-area and deallocated the file table entry so it can be	 * used by someone else.	 */free_fp:	U_OFILE_SET(i,NULL);	U_POFILE_SET(i,0);	crfree(fp->f_cred);	smp_lock(&lk_file, LK_RETRY);	fp->f_data = (caddr_t)0;	fp->f_count = 0;	smp_unlock(&lk_file);	fp = NULL;	if (u.u_error==EALREADY && (gp->g_flag&GINUSE)) { 				   /*  gnode was grabbed while we were */		u.u_error = 0;	   /*  blocked.  wait to free up again.*/		gfs_lock(gp);		/* need to lock again */		goto waitinuse;	    	}free_gp:	if (!smp_owner(&gp->g_lk))		grele(gp);	else		gput(gp);out:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Mknod system call */mknod(){	register struct gnode *gp;	register struct a {		char	*fname;		int	fmode;		int	dev;	} *uap;	register struct nameidata *ndp = &u.u_nd;	register int ret;		uap = (struct a *)u.u_ap;	if (!suser() && ((uap->fmode & GFMT) != GFPORT))		return;			/* if a non-privileged user is making	*/			/* a port node then negate the error	*/			/* posted by SUSER.			*/	u.u_error = 0;	ndp->ni_nameiop = CREATE;	KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->fname, ndp->ni_dirp, MAXPATHLEN,				  (u_int *) 0)) {	        goto out2;	}	gp = gfs_namei(ndp);	if (gp != NULL) {		u.u_error = EEXIST;		goto out;	}	if (u.u_error) {	        goto out2;	}		if ((gp = GMAKNODE(uap->fmode, uap->dev, ndp)) == (struct gnode *) GNOFUNC) {		u.u_error = EOPNOTSUPP;	        goto out2;	}	if (gp == NULL) {	        goto out2;	}	out:	gput(gp);out2:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Synch an open file. */fsync(){	register struct a {		int	fd;	} *uap = (struct a *)u.u_ap;	register struct gnode *gp;	register struct file *fp;		fp = getgnode(uap->fd);	if (fp == NULL)		return;	if ((gp = (struct gnode *)fp->f_data) == 0) {		u.u_error = EBADF;		return;	}	gfs_lock(gp);	if (GSYNCG(gp, fp->f_cred) == GNOFUNC)		u.u_error = EOPNOTSUPP;	gfs_unlock(gp);}/* * Change mode of a file given path name. */chmod(){	register struct gnode *gp;	register struct a {		char	*fname;		int	fmode;	} *uap = (struct a *)u.u_ap;	/* where should owner be? */		if ((gp = owner(uap->fname, FOLLOW)) == NULL)		return;	u.u_error = chmod1(gp, uap->fmode, u.u_cred);	gput(gp);}/* * Change mode of a file given a file descriptor. */fchmod(){	register struct a {		int	fd;		int	fmode;	} *uap;	register struct gnode *gp;	register struct file *fp;		uap = (struct a *)u.u_ap;	fp = getgnode(uap->fd);	if (fp == NULL)		return;	if ((gp = (struct gnode *)fp->f_data) == 0) {		u.u_error = EBADF;		return;	}	if (u.u_uid != gp->g_uid && !suser())		return;	gfs_lock(gp);	u.u_error = chmod1(gp, uap->fmode, fp->f_cred);	gfs_unlock(gp);}/* * Change the mode on a file. * Gnode must be locked before calling. */chmod1(gp, mode, cred)	register struct gnode *gp;	register int mode;	struct	ucred	*cred;{        register int sticky = gp->g_mode & GSVTX;	register int ret;	if (ISREADONLY(gp->g_mp))		return(EROFS);			if (u.u_uid) {		if ((gp->g_mode & GFMT) != GFDIR)			mode &= ~GSVTX;		if (!groupmember(gp->g_gid))			mode &= ~GSGID;	}        /* for the new text table sticky changes blow away unref-ed text */        if ((gp->g_flag&GTEXT) && (mode&GSVTX) && sticky == 0) {                xrele(gp);	}        gp->g_mode &= ~07777;	gp->g_mode |= mode&07777;	gp->g_flag |= (GCHG | GCMODE);	if (!ISLOCAL(gp->g_mp)) {		if (ret = GUPDATE(gp, 0, 0, 0, cred)) {			return(ret);		}	}	if (gp->g_flag&GTEXT && (gp->g_mode&GSVTX) == 0 && sticky)		xrele(gp);	return(0);}/* * Set ownership given a path name. */chown(){	register struct gnode *gp;	register struct a {		char	*fname;		int	uid;		int	gid;	} *uap;	uap = (struct a *)u.u_ap;	/*	 * owner() is not going to perform additional access checks	 * over chown1(). Leave it for now, but this should change	 * eventually.	 */	if ((gp = owner(uap->fname, NOFOLLOW)) == NULL)		return;	u.u_error = chown1(gp, uap->uid, uap->gid, u.u_cred);	gput(gp);}/* * Set ownership given a file descriptor. */fchown(){	register struct a {		int	fd;		int	uid;		int	gid;	} *uap;	register struct gnode *gp;	register struct file *fp;		uap = (struct a *)u.u_ap;	fp = getgnode(uap->fd);	if (fp == NULL)		return;	if ((gp = (struct gnode *)fp->f_data) == 0) {		u.u_error = EBADF;		return;	}	if (!suser())		return;	gfs_lock(gp);	u.u_error = chown1(gp, uap->uid, uap->gid, fp->f_cred);	gfs_unlock(gp);}/* * Perform chown operation on gnode gp; * gnode must be locked prior to call. */chown1(gp, uid, gid, cred)	register struct gnode *gp;	struct	ucred	*cred;	register int uid, gid;{	register int ret = 0;#ifdef QUOTA	register long change;#endif	if (ISREADONLY(gp->g_mp))		return(EROFS);	if (uid == -1)		uid = gp->g_uid;	if (gid == -1)		gid = gp->g_gid;	if (uid != gp->g_uid && !suser())		return(u.u_error);	if (gid != gp->g_gid && !groupmember(gid) && !suser())		return(u.u_error);#ifdef QUOTA	if (gp->g_uid == uid)		/* this just speeds things a little */		change = 0;	else		change = gp->g_blocks;	(void) chkdq(gp, -change, 1);	(void) chkiq(gp->g_dev, gp, gp->g_uid, 1);	dquot_lock(gp->g_dquot);	dqrele(gp->g_dquot);	dquot_unlock(gp->g_dquot);#endif	gp->g_uid = uid;	gp->g_gid = gid;	gp->g_flag |= (GCHG | GCID);			if (u.u_ruid != 0)		gp->g_mode &= ~(GSUID|GSGID);		if (!ISLOCAL(gp->g_mp)) {		if (ret = GUPDATE(gp, 0, 0, 0, cred)) {			return(ret);		}	}		#ifdef QUOTA	gp->g_dquot = inoquota(gp);	(void) chkdq(gp, change, 1);	(void) chkiq(gp->g_dev, (struct gnode *)NULL, uid, 1);	return (u.u_error);	#else	return (ret);#endif}utimes(){	register struct a {		char	*fname;		struct	timeval *tptr;	} *uap = (struct a *)u.u_ap;	register struct gnode *gp;	struct timeval tv[2]; 	register struct nameidata *ndp = &u.u_nd;	register int ret;	 	ndp->ni_nameiop = LOOKUP | FOLLOW;	KM_ALLOC(ndp->ni_dirp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (ndp->ni_dirp == NULL) {		u.u_error = EIO;		return;	} 	if (u.u_error = copyinstr(uap->fname, ndp->ni_dirp, MAXPATHLEN,				  (u_int *)0))	{		KM_FREE(ndp->ni_dirp, KM_NAMEI);		return;	} 	gp = GNAMEI(ndp);	KM_FREE(ndp->ni_dirp, KM_NAMEI);	if (gp == NULL) {		return;	}	if (ISREADONLY(gp->g_mp)) {		u.u_error = EROFS;		gput(gp);		return;	}	ret = GGETVAL(gp);	if (uap->tptr != NULL) {		u.u_error = copyin((caddr_t)uap->tptr, (caddr_t)tv,				   sizeof (tv));		}	else {		tv[0].tv_sec = tv[1].tv_sec = timepick->tv_sec;		tv[0].tv_usec = tv[1].tv_usec = timepick->tv_usec;	}	/* If not the owner or su and tptr is NULL, check for write access. */	/* If tptr is not NULL then EPERM error condition.		    */	if ((u.u_error == 0) && (u.u_uid != gp->g_uid) && u.u_uid != 0) {		if (uap->tptr != NULL) 			u.u_error = EPERM;		else			access(gp,GWRITE);	}		if (u.u_error == 0) {		if (tv[0].tv_sec < 0 || tv[0].tv_usec < 0 ||		    tv[1].tv_sec < 0 || tv[1].tv_usec < 0 ||		    tv[0].tv_usec >= 1000000 || tv[1].tv_usec >= 1000000)			u.u_error = EINVAL;		else {			gp->g_flag |= GMOD|GACC|GUPD|GCHG;			if (GUPDATE(gp, &tv[0], &tv[1], 0, u.u_cred)			    == GNOFUNC)				u.u_error = EOPNOTSUPP;		}	}				gput(gp);}/* * Flush any pending I/O. */sync(){	update();	gfs_gupdat(NODEV);}/* * Truncate a file given its path name. */truncate(){	register struct a {		char	*fname;		u_long	length;	} *uap = (struct a *)u.u_ap;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -