FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
/*
 * Vnode operation to retrieve extended attributes on a vnode.
 */
Vnode operation to retrieve extended attributes on a vnode.
Vnode operation to retrieve extended attributes on a vnode .
static int
zfs_listextattr(struct vop_listextattr_args *ap)
{
	zfsvfs_t *zfsvfs = VTOZ(ap->a_vp)->z_zfsvfs;
	struct thread *td = ap->a_td;
	struct nameidata nd;
	char attrprefix[16];
	u_char dirbuf[sizeof(struct dirent)];
	struct dirent *dp;
	struct iovec aiov;
	struct uio auio, *uio = ap->a_uio;
	size_t *sizep = ap->a_size;
	size_t plen;
	vnode_t *xvp = NULL, *vp;
	int done, error, eof, pos;
	error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
	    ap->a_cred, ap->a_td, VREAD);
	if (error != 0)
		return (error);
	error = zfs_create_attrname(ap->a_attrnamespace, "", attrprefix,
	    sizeof(attrprefix));
	if (error != 0)
		return (error);
	plen = strlen(attrprefix);
	ZFS_ENTER(zfsvfs);
	if (sizep != NULL)
		*sizep = 0;
	error = zfs_lookup(ap->a_vp, NULL, &xvp, NULL, 0, ap->a_cred, td,
	    LOOKUP_XATTR);
	if (error != 0) {
		ZFS_EXIT(zfsvfs);
		if (error == ENOATTR)
			error = 0;
		return (error);
	}
	NDINIT_ATVP(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKSHARED,
	    UIO_SYSSPACE, ".", xvp, td);
	error = namei(&nd);
	vp = nd.ni_vp;
	NDFREE(&nd, NDF_ONLY_PNBUF);
	if (error != 0) {
		ZFS_EXIT(zfsvfs);
		return (error);
	}
	auio.uio_iov = &aiov;
	auio.uio_iovcnt = 1;
	auio.uio_segflg = UIO_SYSSPACE;
	auio.uio_td = td;
	auio.uio_rw = UIO_READ;
	auio.uio_offset = 0;
	do {
		u_char nlen;
		aiov.iov_base = (void *)dirbuf;
		aiov.iov_len = sizeof(dirbuf);
		auio.uio_resid = sizeof(dirbuf);
		error = VOP_READDIR(vp, &auio, ap->a_cred, &eof, NULL, NULL);
		done = sizeof(dirbuf) - auio.uio_resid;
		if (error != 0)
			break;
		for (pos = 0; pos < done;) {
			dp = (struct dirent *)(dirbuf + pos);
			pos += dp->d_reclen;
			if (dp->d_type != DT_REG && dp->d_type != DT_UNKNOWN)
				continue;
			if (plen == 0 && strncmp(dp->d_name, "freebsd:", 8) == 0)
				continue;
			else if (strncmp(dp->d_name, attrprefix, plen) != 0)
				continue;
			nlen = dp->d_namlen - plen;
			if (sizep != NULL)
				*sizep += 1 + nlen;
			else if (uio != NULL) {
				error = uiomove(&nlen, 1, uio->uio_rw, uio);
				if (error == 0) {
					error = uiomove(dp->d_name + plen, nlen,
					    uio->uio_rw, uio);
				}
				if (error != 0)
					break;
			}
		}
	} while (!eof && error == 0);
	vput(vp);
	ZFS_EXIT(zfsvfs);
	return (error);
}
static int zfs_listextattr ( struct vop_listextattr_args * ap ) { zfsvfs_t * zfsvfs = VTOZ ( ap -> a_vp ) -> z_zfsvfs ; struct thread * td = ap -> a_td ; struct nameidata nd ; char attrprefix [ 16 ] ; u_char dirbuf [ sizeof ( struct dirent ) ] ; struct dirent * dp ; struct iovec aiov ; struct uio auio , * uio = ap -> a_uio ; size_t * sizep = ap -> a_size ; size_t plen ; vnode_t * xvp = NULL , * vp ; int done , error , eof , pos ; error = extattr_check_cred ( ap -> a_vp , ap -> a_attrnamespace , ap -> a_cred , ap -> a_td , VREAD ) ; if ( error != 0 ) return ( error ) ; error = zfs_create_attrname ( ap -> a_attrnamespace , " " , attrprefix , sizeof ( attrprefix ) ) ; if ( error != 0 ) return ( error ) ; plen = strlen ( attrprefix ) ; ZFS_ENTER ( zfsvfs ) ; if ( sizep != NULL ) * sizep = 0 ; error = zfs_lookup ( ap -> a_vp , NULL , & xvp , NULL , 0 , ap -> a_cred , td , LOOKUP_XATTR ) ; if ( error != 0 ) { ZFS_EXIT ( zfsvfs ) ; if ( error == ENOATTR ) error = 0 ; return ( error ) ; } NDINIT_ATVP ( & nd , LOOKUP , NOFOLLOW | LOCKLEAF | LOCKSHARED , UIO_SYSSPACE , " " , xvp , td ) ; error = namei ( & nd ) ; vp = nd . ni_vp ; NDFREE ( & nd , NDF_ONLY_PNBUF ) ; if ( error != 0 ) { ZFS_EXIT ( zfsvfs ) ; return ( error ) ; } auio . uio_iov = & aiov ; auio . uio_iovcnt = 1 ; auio . uio_segflg = UIO_SYSSPACE ; auio . uio_td = td ; auio . uio_rw = UIO_READ ; auio . uio_offset = 0 ; do { u_char nlen ; aiov . iov_base = ( void * ) dirbuf ; aiov . iov_len = sizeof ( dirbuf ) ; auio . uio_resid = sizeof ( dirbuf ) ; error = VOP_READDIR ( vp , & auio , ap -> a_cred , & eof , NULL , NULL ) ; done = sizeof ( dirbuf ) - auio . uio_resid ; if ( error != 0 ) break ; for ( pos = 0 ; pos < done ; ) { dp = ( struct dirent * ) ( dirbuf + pos ) ; pos += dp -> d_reclen ; if ( dp -> d_type != DT_REG && dp -> d_type != DT_UNKNOWN ) continue ; if ( plen == 0 && strncmp ( dp -> d_name , " " , 8 ) == 0 ) continue ; else if ( strncmp ( dp -> d_name , attrprefix , plen ) != 0 ) continue ; nlen = dp -> d_namlen - plen ; if ( sizep != NULL ) * sizep += 1 + nlen ; else if ( uio != NULL ) { error = uiomove ( & nlen , 1 , uio -> uio_rw , uio ) ; if ( error == 0 ) { error = uiomove ( dp -> d_name + plen , nlen , uio -> uio_rw , uio ) ; } if ( error != 0 ) break ; } } } while ( ! eof && error == 0 ) ; vput ( vp ) ; ZFS_EXIT ( zfsvfs ) ; return ( error ) ; }
Vnode operation to retrieve extended attributes on a vnode.
Vnode operation to retrieve extended attributes on a vnode .
/*
vop_listextattr {
	IN struct vnode *a_vp;
	IN int a_attrnamespace;
	INOUT struct uio *a_uio;
	OUT size_t *a_size;
	IN struct ucred *a_cred;
	IN struct thread *a_td;
};
*/ /*
		 * ENOATTR means that the EA directory does not yet exist,
		 * i.e. there are no extended attributes there.
		 */ /*
			 * XXX: Temporarily we also accept DT_UNKNOWN, as this
			 * is what we get when attribute was created on Solaris.
			 */ /*
				 * Format of extattr name entry is one byte for
				 * length and the rest for name.
				 */