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

📄 vfs_syscalls.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
struct chown_args {	char	*path;	int	uid;	int	gid;};/* ARGSUSED */chown(p, uap, retval)	struct proc *p;	register struct chown_args *uap;	int *retval;{	register struct vnode *vp;	struct vattr vattr;	int error;	struct nameidata nd;	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);	VOP_LOCK(vp);	if (vp->v_mount->mnt_flag & MNT_RDONLY)		error = EROFS;	else {		VATTR_NULL(&vattr);		vattr.va_uid = uap->uid;		vattr.va_gid = uap->gid;		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);	}	vput(vp);	return (error);}/* * Set ownership given a file descriptor. */struct fchown_args {	int	fd;	int	uid;	int	gid;};/* ARGSUSED */fchown(p, uap, retval)	struct proc *p;	register struct fchown_args *uap;	int *retval;{	struct vattr vattr;	struct vnode *vp;	struct file *fp;	int error;	if (error = getvnode(p->p_fd, uap->fd, &fp))		return (error);	vp = (struct vnode *)fp->f_data;	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);	VOP_LOCK(vp);	if (vp->v_mount->mnt_flag & MNT_RDONLY)		error = EROFS;	else {		VATTR_NULL(&vattr);		vattr.va_uid = uap->uid;		vattr.va_gid = uap->gid;		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);	}	VOP_UNLOCK(vp);	return (error);}/* * Set the access and modification times of a file. */struct utimes_args {	char	*path;	struct	timeval *tptr;};/* ARGSUSED */utimes(p, uap, retval)	struct proc *p;	register struct utimes_args *uap;	int *retval;{	register struct vnode *vp;	struct timeval tv[2];	struct vattr vattr;	int error;	struct nameidata nd;	VATTR_NULL(&vattr);	if (uap->tptr == NULL) {		microtime(&tv[0]);		tv[1] = tv[0];		vattr.va_vaflags |= VA_UTIMES_NULL;	} else if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv)))  		return (error);	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);	VOP_LOCK(vp);	if (vp->v_mount->mnt_flag & MNT_RDONLY)		error = EROFS;	else {		vattr.va_atime.ts_sec = tv[0].tv_sec;		vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000;		vattr.va_mtime.ts_sec = tv[1].tv_sec;		vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000;		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);	}	vput(vp);	return (error);}/* * Truncate a file given its path name. */struct truncate_args {	char	*path;	int	pad;	off_t	length;};/* ARGSUSED */truncate(p, uap, retval)	struct proc *p;	register struct truncate_args *uap;	int *retval;{	register struct vnode *vp;	struct vattr vattr;	int error;	struct nameidata nd;	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);	VOP_LOCK(vp);	if (vp->v_type == VDIR)		error = EISDIR;	else if ((error = vn_writechk(vp)) == 0 &&	    (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {		VATTR_NULL(&vattr);		vattr.va_size = uap->length;		error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);	}	vput(vp);	return (error);}/* * Truncate a file given a file descriptor. */struct ftruncate_args {	int	fd;	int	pad;	off_t	length;};/* ARGSUSED */ftruncate(p, uap, retval)	struct proc *p;	register struct ftruncate_args *uap;	int *retval;{	struct vattr vattr;	struct vnode *vp;	struct file *fp;	int error;	if (error = getvnode(p->p_fd, uap->fd, &fp))		return (error);	if ((fp->f_flag & FWRITE) == 0)		return (EINVAL);	vp = (struct vnode *)fp->f_data;	LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);	VOP_LOCK(vp);	if (vp->v_type == VDIR)		error = EISDIR;	else if ((error = vn_writechk(vp)) == 0) {		VATTR_NULL(&vattr);		vattr.va_size = uap->length;		error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);	}	VOP_UNLOCK(vp);	return (error);}#if defined(COMPAT_43) || defined(COMPAT_SUNOS)/* * Truncate a file given its path name. */struct otruncate_args {	char	*path;	long	length;};/* ARGSUSED */otruncate(p, uap, retval)	struct proc *p;	register struct otruncate_args *uap;	int *retval;{	struct truncate_args nuap;	nuap.path = uap->path;	nuap.length = uap->length;	return (truncate(p, &nuap, retval));}/* * Truncate a file given a file descriptor. */struct oftruncate_args {	int	fd;	long	length;};/* ARGSUSED */oftruncate(p, uap, retval)	struct proc *p;	register struct oftruncate_args *uap;	int *retval;{	struct ftruncate_args nuap;	nuap.fd = uap->fd;	nuap.length = uap->length;	return (ftruncate(p, &nuap, retval));}#endif /* COMPAT_43 || COMPAT_SUNOS *//* * Sync an open file. */struct fsync_args {	int	fd;};/* ARGSUSED */fsync(p, uap, retval)	struct proc *p;	struct fsync_args *uap;	int *retval;{	register struct vnode *vp;	struct file *fp;	int error;	if (error = getvnode(p->p_fd, uap->fd, &fp))		return (error);	vp = (struct vnode *)fp->f_data;	VOP_LOCK(vp);	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);	VOP_UNLOCK(vp);	return (error);}/* * Rename files.  Source and destination must either both be directories, * or both not be directories.  If target is a directory, it must be empty. */struct rename_args {	char	*from;	char	*to;};/* ARGSUSED */rename(p, uap, retval)	struct proc *p;	register struct rename_args *uap;	int *retval;{	register struct vnode *tvp, *fvp, *tdvp;	struct nameidata fromnd, tond;	int error;	NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,		uap->from, p);	if (error = namei(&fromnd))		return (error);	fvp = fromnd.ni_vp;	NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,		UIO_USERSPACE, uap->to, p);	if (error = namei(&tond)) {		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);		vrele(fromnd.ni_dvp);		vrele(fvp);		goto out1;	}	tdvp = tond.ni_dvp;	tvp = tond.ni_vp;	if (tvp != NULL) {		if (fvp->v_type == VDIR && tvp->v_type != VDIR) {			error = ENOTDIR;			goto out;		} else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {			error = EISDIR;			goto out;		}	}	if (fvp == tdvp)		error = EINVAL;	/*	 * If source is the same as the destination (that is the	 * same inode number with the same name in the same directory),	 * then there is nothing to do.	 */	if (fvp == tvp && fromnd.ni_dvp == tdvp &&	    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&	    !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,	      fromnd.ni_cnd.cn_namelen))		error = -1;out:	if (!error) {		LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE);		if (fromnd.ni_dvp != tdvp)			LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);		if (tvp)			LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE);		error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,				   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);	} else {		VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);		if (tdvp == tvp)			vrele(tdvp);		else			vput(tdvp);		if (tvp)			vput(tvp);		VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);		vrele(fromnd.ni_dvp);		vrele(fvp);	}	vrele(tond.ni_startdir);	FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);out1:	if (fromnd.ni_startdir)		vrele(fromnd.ni_startdir);	FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);	if (error == -1)		return (0);	return (error);}/* * Make a directory file. */struct mkdir_args {	char	*path;	int	mode;};/* ARGSUSED */mkdir(p, uap, retval)	struct proc *p;	register struct mkdir_args *uap;	int *retval;{	register struct vnode *vp;	struct vattr vattr;	int error;	struct nameidata nd;	NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->path, p);	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	if (vp != NULL) {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vrele(vp);		return (EEXIST);	}	VATTR_NULL(&vattr);	vattr.va_type = VDIR;	vattr.va_mode = (uap->mode & ACCESSPERMS) &~ p->p_fd->fd_cmask;	LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);	error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);	if (!error)		vput(nd.ni_vp);	return (error);}/* * Remove a directory file. */struct rmdir_args {	char	*path;};/* ARGSUSED */rmdir(p, uap, retval)	struct proc *p;	struct rmdir_args *uap;	int *retval;{	register struct vnode *vp;	int error;	struct nameidata nd;	NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->path, p);	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	if (vp->v_type != VDIR) {		error = ENOTDIR;		goto out;	}	/*	 * No rmdir "." please.	 */	if (nd.ni_dvp == vp) {		error = EINVAL;		goto out;	}	/*	 * The root of a mounted filesystem cannot be deleted.	 */	if (vp->v_flag & VROOT)		error = EBUSY;out:	if (!error) {		LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);		LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE);		error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);	} else {		VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);		if (nd.ni_dvp == vp)			vrele(nd.ni_dvp);		else			vput(nd.ni_dvp);		vput(vp);	}	return (error);}#ifdef COMPAT_43/* * Read a block of directory entries in a file system independent format. */struct ogetdirentries_args {	int	fd;	char	*buf;	u_int	count;	long	*basep;};ogetdirentries(p, uap, retval)	struct proc *p;	register struct ogetdirentries_args *uap;	int *retval;{	register struct vnode *vp;	struct file *fp;	struct uio auio, kuio;	struct iovec aiov, kiov;	struct dirent *dp, *edp;	caddr_t dirbuf;	int error, readcnt;	long loff;	if (error = getvnode(p->p_fd, uap->fd, &fp))		return (error);	if ((fp->f_flag & FREAD) == 0)		return (EBADF);	vp = (struct vnode *)fp->f_data;	if (vp->v_type != VDIR)		return (EINVAL);	aiov.iov_base = uap->buf;	aiov.iov_len = uap->count;	auio.uio_iov = &aiov;	auio.uio_iovcnt = 1;	auio.uio_rw = UIO_READ;	auio.uio_segflg = UIO_USERSPACE;	auio.uio_procp = p;	auio.uio_resid = uap->count;	VOP_LOCK(vp);	loff = auio.uio_offset = fp->f_offset;#	if (BYTE_ORDER != LITTLE_ENDIAN)		if (vp->v_mount->mnt_maxsymlinklen <= 0) {			error = VOP_READDIR(vp, &auio, fp->f_cred);			fp->f_offset = auio.uio_offset;		} else#	endif	{		kuio = auio;		kuio.uio_iov = &kiov;		kuio.uio_segflg = UIO_SYSSPACE;		kiov.iov_len = uap->count;		MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK);		kiov.iov_base = dirbuf;		error = VOP_READDIR(vp, &kuio, fp->f_cred);		fp->f_offset = kuio.uio_offset;		if (error == 0) {			readcnt = uap->count - kuio.uio_resid;			edp = (struct dirent *)&dirbuf[readcnt];			for (dp = (struct dirent *)dirbuf; dp < edp; ) {#				if (BYTE_ORDER == LITTLE_ENDIAN)					/*					 * The expected low byte of					 * dp->d_namlen is our dp->d_type.					 * The high MBZ byte of dp->d_namlen					 * is our dp->d_namlen.					 */					dp->d_type = dp->d_namlen;					dp->d_namlen = 0;#				else					/*					 * The dp->d_type is the high byte					 * of the expected dp->d_namlen,					 * so must be zero'ed.					 */					dp->d_type = 0;#				endif				if (dp->d_reclen > 0) {					dp = (struct dirent *)					    ((char *)dp + dp->d_reclen);				} else {					error = EIO;					break;				}			}			if (dp >= edp)				error = uiomove(dirbuf, readcnt, &auio);		}		FREE(dirbuf, M_TEMP);	}	VOP_UNLOCK(vp);	if (error)		return (error);	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));	*retval = uap->count - auio.uio_resid;	return (error);}#endif/* * Read a block of directory entries in a file system independent format. */struct getdirentries_args {	int	fd;	char	*buf;	u_int	count;	long	*basep;};getdirentries(p, uap, retval)	struct proc *p;	register struct getdirentries_args *uap;	int *retval;{	register struct vnode *vp;	struct file *fp;	struct uio auio;	struct iovec aiov;	long loff;	int error;	if (error = getvnode(p->p_fd, uap->fd, &fp))		return (error);	if ((fp->f_flag & FREAD) == 0)		return (EBADF);	vp = (struct vnode *)fp->f_data;unionread:	if (vp->v_type != VDIR)		return (EINVAL);	aiov.iov_base = uap->buf;	aiov.iov_len = uap->count;	auio.uio_iov = &aiov;	auio.uio_iovcnt = 1;	auio.uio_rw = UIO_READ;	auio.uio_segflg = UIO_USERSPACE;	auio.uio_procp = p;	auio.uio_resid = uap->count;	VOP_LOCK(vp);	loff = auio.uio_offset = fp->f_offset;	error = VOP_READDIR(vp, &auio, fp->f_cred);	fp->f_offset = auio.uio_offset;	VOP_UNLOCK(vp);	if (error)		return (error);#ifdef UNION{	extern int (**union_vnodeop_p)();	extern struct vnode *union_lowervp __P((struct vnode *));	if ((uap->count == auio.uio_resid) &&	    (vp->v_op == union_vnodeop_p)) {		struct vnode *tvp = vp;		vp = union_lowervp(vp);		if (vp != NULLVP) {			VOP_LOCK(vp);			error = VOP_OPEN(vp, FREAD);			VOP_UNLOCK(vp);			if (error) {				vrele(vp);				return (error);			}			fp->f_data = (caddr_t) vp;			fp->f_offset = 0;			error = vn_close(tvp, FREAD, fp->f_cred, p);			if (error)				return (error);			goto unionread;		}	}}#endif	if ((uap->count == auio.uio_resid) &&	    (vp->v_flag & VROOT) &&	    (vp->v_mount->mnt_flag & MNT_UNION)) {		struct vnode *tvp = vp;		vp = vp->v_mount->mnt_vnodecovered;		VREF(vp);		fp->f_data = (caddr_t) vp;		fp->f_offset = 0;		vrele(tvp);		goto unionread;	}	error = copyout((caddr_t)&loff, (caddr_t)uap->basep, sizeof(long));	*retval = uap->count - auio.uio_resid;	return (error);}/* * Set the mode mask for creation of filesystem nodes. */struct umask_args {	int	newmask;};mode_t				/* XXX */umask(p, uap, retval)	struct proc *p;	struct umask_args *uap;	int *retval;{	register struct filedesc *fdp;	fdp = p->p_fd;	*retval = fdp->fd_cmask;	fdp->fd_cmask = uap->newmask & ALLPERMS;	return (0);}/* * Void all references to file by ripping underlying filesystem * away from vnode. */struct revoke_args {	char	*path;};/* ARGSUSED */revoke(p, uap, retval)	struct proc *p;	register struct revoke_args *uap;	int *retval;{	register struct vnode *vp;	struct vattr vattr;	int error;	struct nameidata nd;	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p);	if (error = namei(&nd))		return (error);	vp = nd.ni_vp;	if (vp->v_type != VCHR && vp->v_type != VBLK) {		error = EINVAL;		goto out;	}	if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))		goto out;	if (p->p_ucred->cr_uid != vattr.va_uid &&	    (error = suser(p->p_ucred, &p->p_acflag)))		goto out;	if (vp->v_usecount > 1 || (vp->v_flag & VALIASED))		vgoneall(vp);out:	vrele(vp);	return (error);}/* * Convert a user file descriptor to a kernel file entry. */getvnode(fdp, fd, fpp)	struct filedesc *fdp;	struct file **fpp;	int fd;{	struct file *fp;	if ((u_int)fd >= fdp->fd_nfiles ||	    (fp = fdp->fd_ofiles[fd]) == NULL)		return (EBADF);	if (fp->f_type != DTYPE_VNODE)		return (EINVAL);	*fpp = fp;	return (0);}

⌨️ 快捷键说明

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