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

📄 gfs_syscalls.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
	register struct gnode *gp;	register struct nameidata *ndp = &u.u_nd;	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 bad2;	}	gp = gfs_namei(ndp);		if (gp == NULL)	        goto bad2;	if (access(gp, GWRITE))		goto bad;	if ((gp->g_mode&GFMT) == GFDIR) {		u.u_error = EISDIR;		goto bad;	}	if (GTRUNC(gp, uap->length, u.u_cred) == GNOFUNC)		u.u_error = EOPNOTSUPP;bad:	gput(gp);bad2:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Truncate a file given a file descriptor. */ftruncate(){	register struct a {		int	fd;		u_long	length;	} *uap = (struct a *)u.u_ap;	register struct gnode *gp;	register struct file *fp;	fp = getgnode(uap->fd);	if (fp == NULL)		return;	if ((fp->f_flag&FWRITE) == 0) {		u.u_error = EINVAL;		return;	}	if ((gp = (struct gnode *)fp->f_data) == 0) {		u.u_error = EBADF;		return;	}	if (ISREADONLY(gp->g_mp)) {		u.u_error = EROFS;		return;	}		gfs_lock(gp);	if (GTRUNC(gp, uap->length, fp->f_cred) == GNOFUNC)		u.u_error = EOPNOTSUPP;	gfs_unlock(gp);	return;}/* * symlink -- make a symbolic link */symlink(){	register struct a {		char	*target;		char	*linkname;	} *uap;	register struct gnode *gp;	register struct nameidata *ndp = &u.u_nd;	register char *target_cp;	register char *source_cp;		uap = (struct a *)u.u_ap;		/* get us the target name */		KM_ALLOC(target_cp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (target_cp == NULL) {		u.u_error = EIO;		return;	}	if (u.u_error = copyinstr(uap->target, target_cp, MAXPATHLEN,				  (u_int *) 0)) {	        goto out1;	}		/* get us the source name */		KM_ALLOC(source_cp, char *, MAXPATHLEN, KM_NAMEI, KM_NOARG);	if (source_cp == NULL) {		u.u_error = EIO;	        goto out1;	}	if (u.u_error = copyinstr(uap->linkname, source_cp, MAXPATHLEN,				  (u_int *) 0)) {	        goto out2;	}		/* we may not create a symlink when the source exists */		ndp->ni_nameiop = CREATE;	ndp->ni_dirp = source_cp;	gp = gfs_namei(ndp);	if (gp) {		gput(gp);		u.u_error = EEXIST;	        goto out2;	}	if (u.u_error) {	        goto out2;	}	/* create the special file type for a symlink */	if (GSYMLINK(ndp, target_cp) == GNOFUNC)		u.u_error = EOPNOTSUPP;out2:	KM_FREE(source_cp, KM_NAMEI);out1:	KM_FREE(target_cp, KM_NAMEI);}/* * Seek system call */lseek(){	register struct file *fp;	register struct a {		int	fd;		off_t	off;		int	sbase;	} *uap;	register struct gnode *gp;	register long where;	register int ret = 0;		uap = (struct a *)u.u_ap;	GETF(fp, uap->fd);	if (fp->f_type != DTYPE_INODE) {		u.u_error = ESPIPE;		return;	}	if (fp->f_data == (caddr_t)0) {		u.u_error = EBADF;		return;	}		/* should seeks just arbitrarily be done?, should we check	 * with the correct sfs to see if the operation can be done?	 */		gp = (struct gnode *)fp->f_data;	switch (uap->sbase) {	case L_INCR:		where = fp->f_offset + uap->off;		break;	case L_XTND:		where = uap->off + ((struct gnode *)fp->f_data)->g_size;		break;	case L_SET:		where = uap->off;		break;	default:		u.u_error = EINVAL;		return;	}	/*	 * if gnode type is a regular file, and resulting offset	 * would be negative, return an error.	 */	if ((where < 0) && ((gp->g_mode & GFMT) == GFREG)) { 		u.u_error = EINVAL; 		return; 	}	/*	 * Call sfs's seek routine	 */	ret = GSEEK(gp, where);		/* 	 * there needs to be a documentation change here, if   	 * the seek is not successful (which is not possible for	 * ufs), fp->offset does not change	 */	if (u.u_error) {		u.u_error = EINVAL;		where = -1;	 } else {		if (ret) {			u.u_error = EOPNOTSUPP;			return;		}		smp_lock(&fp->f_lk, LK_RETRY);		fp->f_offset = where;		smp_unlock(&fp->f_lk);	}	u.u_r.r_off = where;}/* * Access system call */saccess(){	register int svuid, svgid;	register struct gnode *gp;	register struct a {		char	*fname;		int	fmode;	} *uap;	register struct nameidata *ndp = &u.u_nd;	register long	mode_mask = ~(X_OK | R_OK | W_OK);	uap = (struct a *)u.u_ap;	if (uap->fmode & mode_mask) {		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(uap->fname, ndp->ni_dirp, MAXPATHLEN,				  (u_int *) 0)) {		KM_FREE(ndp->ni_dirp, KM_NAMEI);	        return;	}	svuid = u.u_uid;	svgid = u.u_gid;	u.u_uid = u.u_ruid;	u.u_gid = u.u_rgid;	ndp->ni_nameiop = LOOKUP | FOLLOW;	gp = gfs_namei(ndp);	if (gp != NULL) {				/*		 * make checks for M_NODEV, M_NOSUID, and M_NOEXEC		 * flags 		 */				if ((uap->fmode&R_OK) && access(gp, GREAD))			goto done;		if ((uap->fmode&W_OK) && access(gp, GWRITE))			goto done;		/*		 * convoluted as it seems, the following test		 * needs to be checked:		 *	if a regular file is being checked for exec		 *		and the filesystem is NOSUID		 *		and the file is SUID or SGID		 *		and we are not the super user		 *	or if a regular file is being checked for exec		 *		and the filesystem is NOEXEC		 *		and we are not the super user		 * we may not permit access to the file		 */		if (uap->fmode&X_OK) {			if ((gp->g_mp->m_flags & M_NOSUID) &&			    (gp->g_mode & (GSUID | GSGID)) &&			    (gp->g_mode & GFREG) &&			    u.u_uid) {				u.u_error = EROFS;				goto done;			}			if ((gp->g_mp->m_flags & M_NOEXEC) &&			    (gp->g_mode & GEXEC) &&			    (gp->g_mode & GFREG) &&			    u.u_uid) {				u.u_error = EROFS;				goto done;			}			if (access(gp, GEXEC))				goto done;		}done:		gput(gp);	}	u.u_uid = svuid;	u.u_gid = svgid;	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Stat system call.  This version follows links. */stat(){	stat1(FOLLOW);}/* * Lstat system call.  This version does not follow links. */lstat(){	stat1(NOFOLLOW);}stat1(follow)	register int follow;{	register struct gnode *gp;	register struct a {		char	*fname;		struct stat *ub;	} *uap;	struct stat sb;	register struct nameidata *ndp = &u.u_nd;	uap = (struct a *)u.u_ap;	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)	        goto out;	gfs_unlock(gp);	(void) GSTAT(gp, &sb);	grele(gp);	if (!u.u_error)	 	u.u_error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb));out:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}/* * Return target name of a symbolic link */readlink(){	register struct gnode *gp;	register struct a {		char	*name;		char	*buf;		int	count;	} *uap = (struct a *)u.u_ap;	register struct nameidata *ndp = &u.u_nd;	struct uio _auio;	register struct uio *auio = &_auio;	struct iovec _aiov;	register struct iovec *aiov = &_aiov;		ndp->ni_nameiop = LOOKUP;	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->name, ndp->ni_dirp, MAXPATHLEN,				  (u_int *)0)) {	        goto out1;	}	gp = gfs_namei(ndp);		if (gp == NULL)	        goto out1;	/* if the sfs doesn't allow links everything is cool */			if ((gp->g_mode&GFMT) != GFLNK) {		u.u_error = EINVAL;		goto out;	}	auio->uio_iov = aiov;	auio->uio_iovcnt = 1;	aiov->iov_base = uap->buf;	aiov->iov_len = auio->uio_resid = uap->count;	auio->uio_segflg = auio->uio_offset = 0;	if (GREADLINK(gp, auio) == GNOFUNC)		u.u_error = EOPNOTSUPP;out:	gput(gp);	if (u.u_error == NULL)		u.u_r.r_val1 = uap->count - auio->uio_resid;out1:	KM_FREE(ndp->ni_dirp, KM_NAMEI);}struct file *getgnode(fdes)	register int fdes;{	register struct file *fp;	if ((unsigned)fdes > u.u_omax || (fp = U_OFILE(fdes)) == NULL) {		u.u_error = EBADF;		return ((struct file *)0);	}	if (fp->f_type != DTYPE_INODE && fp->f_type != DTYPE_PORT) {		u.u_error = EINVAL;		return ((struct file *)0);	}	return (fp);}getmnt(){	register struct a {		u_int	*cookie;		struct 	fs_data	*buf;		u_int	nbytes;		int	mode;		char	*path;	} *uap = (struct a *) u.u_ap;	register u_int number;	register struct mount *mp;	int cookie, i;		register struct fs_data *fs_data;	register int count;	register struct gnode *gp;	register struct nameidata *ndp = &u.u_nd;	register struct gnode *rgp;	switch(uap->mode) {	case STAT_ONE:	case NOSTAT_ONE:	        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->path, ndp->ni_dirp, MAXPATHLEN,					 (u_int *) 0)) {		        goto out;		}		ndp->ni_nameiop = LOOKUP | FOLLOW;		gp = gfs_namei(ndp);		if (gp == NULL)		        goto out;		gfs_unlock(gp);  		mp = gp->g_mp;		if (uap->mode == STAT_ONE) {			gref(mp->m_rootgp);			fs_data = GGETFSDATA(mp); 			grele(mp->m_rootgp);		} else			fs_data = mp->m_fs_data;		if (! u.u_error)			u.u_error = copyout((caddr_t) fs_data,			(caddr_t) uap->buf, sizeof(struct fs_data)); 		u.u_r.r_val1 = 1;		grele(gp);out:		KM_FREE(ndp->ni_dirp, KM_NAMEI);		break;	case STAT_MANY:	case NOSTAT_MANY: 		/* insure we can get all the stuff out. */		if ((count = number = 		    uap->nbytes / sizeof(struct fs_data)) < 1) {			u.u_error = EINVAL;	                break;		}		if (u.u_error = copyin(uap->cookie, &cookie, 				       sizeof(cookie)))	                break;					if (cookie < 0 || cookie > NMOUNT) {			u.u_error = EINVAL;	                break;		}		i = cookie;             /* save in case none found */		for (mp = &mount[cookie]; mp < &mount[NMOUNT] && number; 		    mp++, cookie++) {			/*			 * Check if mp is mounted on and if so get a			 * ref on its file system.			 */			if (rgp = fref(mp, (dev_t)0)) {				number--;				if (uap->mode == STAT_MANY) {					gref(mp->m_rootgp);					fs_data = GGETFSDATA(mp);					grele(mp->m_rootgp);					if (u.u_error == EINTR)  {						grele(rgp);						break;					}				} else					fs_data = mp->m_fs_data;				if (!u.u_error)					if (u.u_error = copyout((caddr_t)fs_data,								(caddr_t) uap->buf, 								sizeof(struct fs_data))) {						grele(rgp);						break;					}				/*				 * Release ref on file system.				 */				grele(rgp);				/* save slot # of last one found */				/* we wouldn't have to do this, if this was */				/* a linked list */				i = cookie;				uap->buf++;			}		}		( ((u.u_r.r_val1 = count - number) > 0) ? (cookie = ++i) : 		(cookie = i) );		copyout(&cookie, uap->cookie, sizeof(cookie));		break;		default:		u.u_error = EINVAL;		break;	}}getdirentries(){	register struct a {		int fd;		struct gen_dir *buf;		u_int nbytes;		u_int *cookie;	} *uap = (struct a *) u.u_ap;	register struct file *fp;	register struct gnode *gp;	struct uio _auio;	register struct uio *auio = &_auio;	struct iovec _aiov;	register struct iovec *aiov = &_aiov;	register int ret;		if ((fp = getgnode(uap->fd)) == NULL) {   /* bad file descriptor */		/* 		 * getgnode returns EINVAL if not an INODE or PORT		 * we just interpret that to mean it isn't a directory		 * either		 */ 		if (u.u_error == EINVAL)			u.u_error = ENOTDIR;		return;	}	if (fp->f_type != DTYPE_INODE) {	/* this must be a gnode */		u.u_error = EOPNOTSUPP;			return;	}		gp = (struct gnode *) fp->f_data;	if ((gp->g_mode & GFMT) != GFDIR) {	/* this must be a directory */		u.u_error = ENOTDIR;		return;	}		/* check for valid buffer */	if (uap->nbytes < DIRBLKSIZ || (uap->nbytes & (DIRBLKSIZ-1))		|| !useracc(uap->buf,uap->nbytes,B_WRITE)) {		u.u_error = EINVAL;		return;	}	aiov->iov_base = (caddr_t) uap->buf;	aiov->iov_len = uap->nbytes;	auio->uio_iov = aiov;	auio->uio_iovcnt = 1;	auio->uio_segflg = UIO_USERSPACE;	auio->uio_offset = fp->f_offset;	auio->uio_resid = uap->nbytes;	ret = GGETDIRENTS(gp, auio, fp->f_cred);	if (u.u_error)		return;	/* POSIX says update access time */        if (u.u_procp->p_progenv == A_POSIX)                gp->g_flag |= GACC;	u.u_error = copyout((caddr_t)&fp->f_offset,				(caddr_t)uap->cookie,sizeof(long));	u.u_r.r_val1 = uap->nbytes - auio->uio_resid;	smp_lock(&fp->f_lk, LK_RETRY);	fp->f_offset = auio->uio_offset;	/* for lseek and next read */	smp_unlock(&fp->f_lk);}

⌨️ 快捷键说明

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