vfs_syscalls.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,115 行 · 第 1/4 页

C
2,115
字号
	void *v;	register_t *retval;{	register struct sys_fstatfs_args /* {		syscallarg(int) fd;		syscallarg(struct statfs *) buf;	} */ *uap = v;	struct file *fp;	struct mount *mp;	register struct statfs *sp;	int error;	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)		return (error);	mp = ((struct vnode *)fp->f_data)->v_mount;	sp = &mp->mnt_stat;	if ((error = VFS_STATFS(mp, sp, p)) != 0)		return (error);	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));}/* * Get statistics on all filesystems. */intsys_getfsstat(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_getfsstat_args /* {		syscallarg(struct statfs *) buf;		syscallarg(long) bufsize;		syscallarg(int) flags;	} */ *uap = v;	register struct mount *mp, *nmp;	register struct statfs *sp;	caddr_t sfsp;	long count, maxcount, error;	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);	sfsp = (caddr_t)SCARG(uap, buf);	for (count = 0,	     mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {		nmp = mp->mnt_list.cqe_next;		if (sfsp && count < maxcount &&		    ((mp->mnt_flag & MNT_MLOCK) == 0)) {			sp = &mp->mnt_stat;			/*			 * If MNT_NOWAIT is specified, do not refresh the			 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT.			 */			if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 ||			    (SCARG(uap, flags) & MNT_WAIT)) &&			    (error = VFS_STATFS(mp, sp, p)))				continue;			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));			if (error)				return (error);			sfsp += sizeof(*sp);		}		count++;	}	if (sfsp && count > maxcount)		*retval = maxcount;	else		*retval = count;	return (0);}/* * Change current working directory to a given file descriptor. *//* ARGSUSED */intsys_fchdir(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	struct sys_fchdir_args /* {		syscallarg(int) fd;	} */ *uap = v;	register struct filedesc *fdp = p->p_fd;	struct vnode *vp, *tdp;	struct mount *mp;	struct file *fp;	int error;	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)		return (error);	vp = (struct vnode *)fp->f_data;	VREF(vp);	VOP_LOCK(vp);	if (vp->v_type != VDIR)		error = ENOTDIR;	else		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);	while (!error && (mp = vp->v_mountedhere) != NULL) {		if (mp->mnt_flag & MNT_MLOCK) {			mp->mnt_flag |= MNT_MWAIT;			sleep((caddr_t)mp, PVFS);			continue;		}		if ((error = VFS_ROOT(mp, &tdp)) != 0)			break;		vput(vp);		vp = tdp;	}	VOP_UNLOCK(vp);	if (error) {		vrele(vp);		return (error);	}	vrele(fdp->fd_cdir);	fdp->fd_cdir = vp;	return (0);}/* * Change current working directory (``.''). *//* ARGSUSED */intsys_chdir(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	struct sys_chdir_args /* {		syscallarg(char *) path;	} */ *uap = v;	register struct filedesc *fdp = p->p_fd;	int error;	struct nameidata nd;	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,	    SCARG(uap, path), p);	if ((error = change_dir(&nd, p)) != 0)		return (error);	vrele(fdp->fd_cdir);	fdp->fd_cdir = nd.ni_vp;	return (0);}/* * Change notion of root (``/'') directory. *//* ARGSUSED */intsys_chroot(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	struct sys_chroot_args /* {		syscallarg(char *) path;	} */ *uap = v;	register struct filedesc *fdp = p->p_fd;	int error;	struct nameidata nd;	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)		return (error);	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,	    SCARG(uap, path), p);	if ((error = change_dir(&nd, p)) != 0)		return (error);	if (fdp->fd_rdir != NULL)		vrele(fdp->fd_rdir);	fdp->fd_rdir = nd.ni_vp;	return (0);}/* * Common routine for chroot and chdir. */static intchange_dir(ndp, p)	register struct nameidata *ndp;	struct proc *p;{	struct vnode *vp;	int error;	if ((error = namei(ndp)) != 0)		return (error);	vp = ndp->ni_vp;	if (vp->v_type != VDIR)		error = ENOTDIR;	else		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);	VOP_UNLOCK(vp);	if (error)		vrele(vp);	return (error);}/* * Check permissions, allocate an open file structure, * and call the device open routine if any. */intsys_open(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_open_args /* {		syscallarg(char *) path;		syscallarg(int) flags;		syscallarg(int) mode;	} */ *uap = v;	register struct filedesc *fdp = p->p_fd;	register struct file *fp;	register struct vnode *vp;	int flags, cmode;	struct file *nfp;	int type, indx, error;	struct flock lf;	struct nameidata nd;	extern struct fileops vnops;	if ((error = falloc(p, &nfp, &indx)) != 0)		return (error);	fp = nfp;	flags = FFLAGS(SCARG(uap, flags));	cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);	p->p_dupfd = -indx - 1;			/* XXX check for fdopen */	if ((error = vn_open(&nd, flags, cmode)) != 0) {		ffree(fp);		if ((error == ENODEV || error == ENXIO) &&		    p->p_dupfd >= 0 &&			/* XXX from fdopen */		    (error =			dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) {			*retval = indx;			return (0);		}		if (error == ERESTART)			error = EINTR;		fdp->fd_ofiles[indx] = NULL;		return (error);	}	p->p_dupfd = 0;	vp = nd.ni_vp;	fp->f_flag = flags & FMASK;	fp->f_type = DTYPE_VNODE;	fp->f_ops = &vnops;	fp->f_data = (caddr_t)vp;	if (flags & (O_EXLOCK | O_SHLOCK)) {		lf.l_whence = SEEK_SET;		lf.l_start = 0;		lf.l_len = 0;		if (flags & O_EXLOCK)			lf.l_type = F_WRLCK;		else			lf.l_type = F_RDLCK;		type = F_FLOCK;		if ((flags & FNONBLOCK) == 0)			type |= F_WAIT;		VOP_UNLOCK(vp);		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);		if (error) {			(void) vn_close(vp, fp->f_flag, fp->f_cred, p);			ffree(fp);			fdp->fd_ofiles[indx] = NULL;			return (error);		}		VOP_LOCK(vp);		fp->f_flag |= FHASLOCK;	}	VOP_UNLOCK(vp);	*retval = indx;	return (0);}/* * Create a special file. *//* ARGSUSED */intsys_mknod(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_mknod_args /* {		syscallarg(char *) path;		syscallarg(int) mode;		syscallarg(int) dev;	} */ *uap = v;	register struct vnode *vp;	struct vattr vattr;	int error;	int whiteout = 0;	struct nameidata nd;	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)		return (error);	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);	if ((error = namei(&nd)) != 0)		return (error);	vp = nd.ni_vp;	if (vp != NULL)		error = EEXIST;	else {		VATTR_NULL(&vattr);		vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;		vattr.va_rdev = SCARG(uap, dev);		whiteout = 0;		switch (SCARG(uap, mode) & S_IFMT) {		case S_IFMT:	/* used by badsect to flag bad sectors */			vattr.va_type = VBAD;			break;		case S_IFCHR:			vattr.va_type = VCHR;			break;		case S_IFBLK:			vattr.va_type = VBLK;			break;		case S_IFWHT:			whiteout = 1;			break;		default:			error = EINVAL;			break;		}	}	if (!error) {		VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);		if (whiteout) {			error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);			if (error)				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);			vput(nd.ni_dvp);		} else {			error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,						&nd.ni_cnd, &vattr);		}	} else {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		if (vp)			vrele(vp);	}	return (error);}/* * Create a named pipe. *//* ARGSUSED */intsys_mkfifo(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{#ifndef FIFO	return (EOPNOTSUPP);#else	register struct sys_mkfifo_args /* {		syscallarg(char *) path;		syscallarg(int) mode;	} */ *uap = v;	struct vattr vattr;	int error;	struct nameidata nd;	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);	if ((error = namei(&nd)) != 0)		return (error);	if (nd.ni_vp != NULL) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == nd.ni_vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vrele(nd.ni_vp);		return (EEXIST);	}	VATTR_NULL(&vattr);	vattr.va_type = VFIFO;	vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask;	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);	return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));#endif /* FIFO */}/* * Make a hard file link. *//* ARGSUSED */intsys_link(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_link_args /* {		syscallarg(char *) path;		syscallarg(char *) link;	} */ *uap = v;	register struct vnode *vp;	struct nameidata nd;	int error;	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);	if ((error = namei(&nd)) != 0)		return (error);	vp = nd.ni_vp;	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);	if ((error = namei(&nd)) != 0)		goto out;	if (nd.ni_vp) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == nd.ni_vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vrele(nd.ni_vp);		error = EEXIST;		goto out;	}	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);	VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);	error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);out:	vrele(vp);	return (error);}/* * Make a symbolic link. *//* ARGSUSED */intsys_symlink(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_symlink_args /* {		syscallarg(char *) path;		syscallarg(char *) link;	} */ *uap = v;	struct vattr vattr;	char *path;	int error;	struct nameidata nd;	MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);	error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);	if (error)		goto out;	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);	if ((error = namei(&nd)) != 0)		goto out;	if (nd.ni_vp) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == nd.ni_vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vrele(nd.ni_vp);		error = EEXIST;		goto out;	}	VATTR_NULL(&vattr);	vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask;	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);	error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);out:	FREE(path, M_NAMEI);	return (error);}/* * Delete a whiteout from the filesystem. *//* ARGSUSED */intsys_undelete(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	register struct sys_undelete_args /* {		syscallarg(char *) path;	} */ *uap = v;	int error;	struct nameidata nd;	NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,	    SCARG(uap, path), p);	error = namei(&nd);	if (error)		return (error);	if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == nd.ni_vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		if (nd.ni_vp)			vrele(nd.ni_vp);		return (EEXIST);	}	VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);	if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);	vput(nd.ni_dvp);	return (error);}/* * Delete a name from the filesystem. *//* ARGSUSED */int

⌨️ 快捷键说明

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