Esempio n. 1
0
/*
 * VFS call to manage extended attributes in UFS.  If filename_vp is
 * non-NULL, it must be passed in locked, and regardless of errors in
 * processing, will be unlocked.
 */
int
ufs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp,
    int attrnamespace, const char *attrname)
{
	struct ufsmount *ump = VFSTOUFS(mp);
	struct thread *td = curthread;
	int error;

	/*
	 * Processes with privilege, but in jail, are not allowed to
	 * configure extended attributes.
	 */
	error = priv_check(td, PRIV_UFS_EXTATTRCTL);
	if (error) {
		if (filename_vp != NULL)
			VOP_UNLOCK(filename_vp, 0);
		return (error);
	}

	/*
	 * We only allow extattrctl(2) on UFS1 file systems, as UFS2 uses
	 * native extended attributes.
	 */
	if (ump->um_fstype != UFS1) {
		if (filename_vp != NULL)
			VOP_UNLOCK(filename_vp, 0);
		return (EOPNOTSUPP);
	}

	switch(cmd) {
	case UFS_EXTATTR_CMD_START:
		if (filename_vp != NULL) {
			VOP_UNLOCK(filename_vp, 0);
			return (EINVAL);
		}
		if (attrname != NULL)
			return (EINVAL);

		error = ufs_extattr_start(mp, td);

		return (error);
		
	case UFS_EXTATTR_CMD_STOP:
		if (filename_vp != NULL) {
			VOP_UNLOCK(filename_vp, 0);
			return (EINVAL);
		}
		if (attrname != NULL)
			return (EINVAL);

		error = ufs_extattr_stop(mp, td);

		return (error);

	case UFS_EXTATTR_CMD_ENABLE:

		if (filename_vp == NULL)
			return (EINVAL);
		if (attrname == NULL) {
			VOP_UNLOCK(filename_vp, 0);
			return (EINVAL);
		}

		/*
		 * ufs_extattr_enable_with_open() will always unlock the
		 * vnode, regardless of failure.
		 */
		ufs_extattr_uepm_lock(ump);
		error = ufs_extattr_enable_with_open(ump, filename_vp,
		    attrnamespace, attrname, td);
		ufs_extattr_uepm_unlock(ump);

		return (error);

	case UFS_EXTATTR_CMD_DISABLE:

		if (filename_vp != NULL) {
			VOP_UNLOCK(filename_vp, 0);
			return (EINVAL);
		}
		if (attrname == NULL)
			return (EINVAL);

		ufs_extattr_uepm_lock(ump);
		error = ufs_extattr_disable(ump, attrnamespace, attrname,
		    td);
		ufs_extattr_uepm_unlock(ump);

		return (error);

	default:
		return (EINVAL);
	}
}
Esempio n. 2
0
/*
 * Given a locked directory vnode, iterate over the names in the directory
 * and use ufs_extattr_lookup() to retrieve locked vnodes of potential
 * attribute files.  Then invoke ufs_extattr_enable_with_open() on each
 * to attempt to start the attribute.  Leaves the directory locked on
 * exit.
 */
static int
ufs_extattr_iterate_directory(struct ufsmount *ump, struct vnode *dvp,
    int attrnamespace, struct thread *td)
{
	struct vop_readdir_args vargs;
	struct dirent *dp, *edp;
	struct vnode *attr_vp;
	struct uio auio;
	struct iovec aiov;
	char *dirbuf;
	int error, eofflag = 0;

	if (dvp->v_type != VDIR)
		return (ENOTDIR);

	dirbuf = malloc(DIRBLKSIZ, M_TEMP, M_WAITOK);

	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_rw = UIO_READ;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_td = td;
	auio.uio_offset = 0;

	vargs.a_gen.a_desc = NULL;
	vargs.a_vp = dvp;
	vargs.a_uio = &auio;
	vargs.a_cred = td->td_ucred;
	vargs.a_eofflag = &eofflag;
	vargs.a_ncookies = NULL;
	vargs.a_cookies = NULL;

	while (!eofflag) {
		auio.uio_resid = DIRBLKSIZ;
		aiov.iov_base = dirbuf;
		aiov.iov_len = DIRBLKSIZ;
		error = ufs_readdir(&vargs);
		if (error) {
			printf("ufs_extattr_iterate_directory: ufs_readdir "
			    "%d\n", error);
			return (error);
		}

		edp = (struct dirent *)&dirbuf[DIRBLKSIZ - auio.uio_resid];
		for (dp = (struct dirent *)dirbuf; dp < edp; ) {
			if (dp->d_reclen == 0)
				break;
			error = ufs_extattr_lookup(dvp, UE_GETDIR_LOCKPARENT,
			    dp->d_name, &attr_vp, td);
			if (error) {
				printf("ufs_extattr_iterate_directory: lookup "
				    "%s %d\n", dp->d_name, error);
			} else if (attr_vp == dvp) {
				vrele(attr_vp);
			} else if (attr_vp->v_type != VREG) {
				vput(attr_vp);
			} else {
				error = ufs_extattr_enable_with_open(ump,
				    attr_vp, attrnamespace, dp->d_name, td);
				vrele(attr_vp);
				if (error) {
					printf("ufs_extattr_iterate_directory: "
					    "enable %s %d\n", dp->d_name,
					    error);
				} else if (bootverbose) {
					printf("UFS autostarted EA %s\n",
					    dp->d_name);
				}
			}
			dp = (struct dirent *) ((char *)dp + dp->d_reclen);
			if (dp >= edp)
				break;
		}
	}
	free(dirbuf, M_TEMP);
	
	return (0);
}
Esempio n. 3
0
/*
 * VFS call to manage extended attributes in UFS.  If filename_vp is
 * non-NULL, it must be passed in locked, and regardless of errors in
 * processing, will be unlocked.
 */
int
ufs_extattrctl(struct mount *mp, int cmd, struct vnode *filename_vp,
    int attrnamespace, const char *attrname, struct proc *p)
{
	struct ufsmount	*ump = VFSTOUFS(mp);
	int	error;

#if 0
	/* jail? -XXX */
	/*
	 * Processes with privilege, but in jail, are not allowed to
	 * configure extended attributes.
	 */
	if ((error = suser_xxx(p->p_ucred, p, 0))) {
		if (filename_vp != NULL)
			VOP_UNLOCK(filename_vp, 0, p);
		return (error);
	}
#endif

	switch(cmd) {
	case UFS_EXTATTR_CMD_START:
		if (filename_vp != NULL) {
			VOP_UNLOCK(filename_vp, 0, p);
			return (EINVAL);
		}
		if (attrname != NULL)
			return (EINVAL);

		error = ufs_extattr_start(mp, p);

		return (error);
		
	case UFS_EXTATTR_CMD_STOP:
		if (filename_vp != NULL) {
			VOP_UNLOCK(filename_vp, 0, p);
			return (EINVAL);
		}
		if (attrname != NULL)
			return (EINVAL);

		error = ufs_extattr_stop(mp, p);

		return (error);

	case UFS_EXTATTR_CMD_ENABLE:

		if (filename_vp == NULL)
			return (EINVAL);
		if (attrname == NULL) {
			VOP_UNLOCK(filename_vp, 0, p);
			return (EINVAL);
		}

		/*
		 * ufs_extattr_enable_with_open() will always unlock the
		 * vnode, regardless of failure.
		 */
		ufs_extattr_uepm_lock(ump, p);
		error = ufs_extattr_enable_with_open(ump, filename_vp,
		    attrnamespace, attrname, p);
		ufs_extattr_uepm_unlock(ump, p);

		return (error);

	case UFS_EXTATTR_CMD_DISABLE:

		if (filename_vp != NULL) {
			VOP_UNLOCK(filename_vp, 0, p);
			return (EINVAL);
		}
		if (attrname == NULL)
			return (EINVAL);

		ufs_extattr_uepm_lock(ump, p);
		error = ufs_extattr_disable(ump, attrnamespace, attrname, p);
		ufs_extattr_uepm_unlock(ump, p);

		return (error);

	default:
		return (EINVAL);
	}
}
Esempio n. 4
0
/*
 * Given a locked directory vnode, iterate over the names in the directory
 * and use ufs_extattr_lookup() to retrieve locked vnodes of potential
 * attribute files.  Then invoke ufs_extattr_enable_with_open() on each
 * to attempt to start the attribute.  Leaves the directory locked on
 * exit.
 */
static int
ufs_extattr_iterate_directory(struct ufsmount *ump, struct vnode *dvp,
    int attrnamespace, struct thread *td)
{
	struct vop_readdir_args vargs;
	struct dirent *dp, *edp;
	struct vnode *attr_vp;
	struct uio auio;
	struct iovec aiov;
	char *dirbuf;
	int error, eofflag = 0;

	if (dvp->v_type != VDIR)
		return (ENOTDIR);

	dirbuf = malloc(DIRBLKSIZ, M_TEMP, M_WAITOK);

	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_rw = UIO_READ;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_td = td;
	auio.uio_offset = 0;

	vargs.a_gen.a_desc = NULL;
	vargs.a_vp = dvp;
	vargs.a_uio = &auio;
	vargs.a_cred = td->td_ucred;
	vargs.a_eofflag = &eofflag;
	vargs.a_ncookies = NULL;
	vargs.a_cookies = NULL;

	while (!eofflag) {
		auio.uio_resid = DIRBLKSIZ;
		aiov.iov_base = dirbuf;
		aiov.iov_len = DIRBLKSIZ;
		error = ufs_readdir(&vargs);
		if (error) {
			printf("ufs_extattr_iterate_directory: ufs_readdir "
			    "%d\n", error);
			return (error);
		}

		/*
		 * XXXRW: While in UFS, we always get DIRBLKSIZ returns from
		 * the directory code on success, on other file systems this
		 * may not be the case.  For portability, we should check the
		 * read length on return from ufs_readdir().
		 */
		edp = (struct dirent *)&dirbuf[DIRBLKSIZ];
		for (dp = (struct dirent *)dirbuf; dp < edp; ) {
#if (BYTE_ORDER == LITTLE_ENDIAN)
			dp->d_type = dp->d_namlen;
			dp->d_namlen = 0;
#else
			dp->d_type = 0;
#endif
			if (dp->d_reclen == 0)
				break;
			error = ufs_extattr_lookup(dvp, UE_GETDIR_LOCKPARENT,
			    dp->d_name, &attr_vp, td);
			if (error) {
				printf("ufs_extattr_iterate_directory: lookup "
				    "%s %d\n", dp->d_name, error);
			} else if (attr_vp == dvp) {
				vrele(attr_vp);
			} else if (attr_vp->v_type != VREG) {
				vput(attr_vp);
			} else {
				error = ufs_extattr_enable_with_open(ump,
				    attr_vp, attrnamespace, dp->d_name, td);
				vrele(attr_vp);
				if (error) {
					printf("ufs_extattr_iterate_directory: "
					    "enable %s %d\n", dp->d_name,
					    error);
				} else if (bootverbose) {
					printf("UFS autostarted EA %s\n",
					    dp->d_name);
				}
			}
			dp = (struct dirent *) ((char *)dp + dp->d_reclen);
			if (dp >= edp)
				break;
		}
	}
	free(dirbuf, M_TEMP);
	
	return (0);
}
Esempio n. 5
0
/*
 * Given a locked directory vnode, iterate over the names in the directory
 * and use ufs_extattr_lookup() to retrieve locked vnodes of potential
 * attribute files.  Then invoke ufs_extattr_enable_with_open() on each
 * to attempt to start the attribute.  Leaves the directory locked on
 * exit.
 */
static int
ufs_extattr_iterate_directory(struct ufsmount *ump, struct vnode *dvp,
    int attrnamespace, struct proc *p)
{
	struct vop_readdir_args vargs;
	struct dirent *dp, *edp;
	struct vnode *attr_vp;
	struct uio auio;
	struct iovec aiov;
	char *dirbuf;
	int error, eofflag = 0;

	if (dvp->v_type != VDIR)
		return (ENOTDIR);

	MALLOC(dirbuf, char *, DIRBLKSIZ, M_TEMP, M_WAITOK);

	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_rw = UIO_READ;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_procp = p;
	auio.uio_offset = 0;

	vargs.a_desc = NULL;
	vargs.a_vp = dvp;
	vargs.a_uio = &auio;
	vargs.a_cred = p->p_ucred;
	vargs.a_eofflag = &eofflag;
	vargs.a_ncookies = NULL;
	vargs.a_cookies = NULL;

	while (!eofflag) {
		auio.uio_resid = DIRBLKSIZ;
		aiov.iov_base = dirbuf;
		aiov.iov_len = DIRBLKSIZ;
		error = ufs_readdir(&vargs);
		if (error) {
			printf("ufs_extattr_iterate_directory: ufs_readdir "
			    "%d\n", error);
			return (error);
		}

		edp = (struct dirent *)&dirbuf[DIRBLKSIZ];
		for (dp = (struct dirent *)dirbuf; dp < edp; ) {
#if (BYTE_ORDER == LITTLE_ENDIAN)
			dp->d_type = dp->d_namlen;
			dp->d_namlen = 0;
#else
			dp->d_type = 0;
#endif
			if (dp->d_reclen == 0)
				break;
			error = ufs_extattr_lookup(dvp, UE_GETDIR_LOCKPARENT,
			    dp->d_name, &attr_vp, p);
			if (error) {
				printf("ufs_extattr_iterate_directory: lookup "
				    "%s %d\n", dp->d_name, error);
			} else if (attr_vp == dvp) {
				vrele(attr_vp);
			} else if (attr_vp->v_type != VREG) {
/*
 * Eventually, this will be uncommented, but in the mean time, the ".."
 * entry causes unnecessary console warnings.
				printf("ufs_extattr_iterate_directory: "
				    "%s not VREG\n", dp->d_name);
*/
				vput(attr_vp);
			} else {
				error = ufs_extattr_enable_with_open(ump,
				    attr_vp, attrnamespace, dp->d_name, p);
				vrele(attr_vp);
				if (error) {
					printf("ufs_extattr_iterate_directory: "
					    "enable %s %d\n", dp->d_name,
					    error);
				} else {
/*
 * While it's nice to have some visual output here, skip for the time-being.
 * Probably should be enabled by -v at boot.
					printf("Autostarted %s\n", dp->d_name);
 */
printf("Autostarted %s\n", dp->d_name); /* XXX - debug*/
				}
			}
			dp = (struct dirent *) ((char *)dp + dp->d_reclen);
			if (dp >= edp)
				break;
		}
	}
	FREE(dirbuf, M_TEMP);
	
	return (0);
}