Module Name:    src
Committed By:   manu
Date:           Tue Jun 28 16:19:16 UTC 2011

Modified Files:
        src/lib/libperfuse: Makefile fuse.h ops.c perfuse.c perfuse_priv.h
            subr.c

Log Message:
Add support for extended attributes


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/lib/libperfuse/Makefile
cvs rdiff -u -r1.3 -r1.4 src/lib/libperfuse/fuse.h
cvs rdiff -u -r1.30 -r1.31 src/lib/libperfuse/ops.c
cvs rdiff -u -r1.15 -r1.16 src/lib/libperfuse/perfuse.c
cvs rdiff -u -r1.18 -r1.19 src/lib/libperfuse/perfuse_priv.h
cvs rdiff -u -r1.11 -r1.12 src/lib/libperfuse/subr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libperfuse/Makefile
diff -u src/lib/libperfuse/Makefile:1.4 src/lib/libperfuse/Makefile:1.5
--- src/lib/libperfuse/Makefile:1.4	Thu May 26 12:56:30 2011
+++ src/lib/libperfuse/Makefile	Tue Jun 28 16:19:16 2011
@@ -1,11 +1,9 @@
-# $NetBSD: Makefile,v 1.4 2011/05/26 12:56:30 joerg Exp $
+# $NetBSD: Makefile,v 1.5 2011/06/28 16:19:16 manu Exp $
 
 LIB=            perfuse
-LIBDPLIBS+=     puffs	${.CURDIR}/../libpuffs
+LIBDPLIBS+=     puffs	/usr/src/lib/libpuffs
 
-.ifdef DEBUG
 PERFUSE_OPT_DEBUG_FLAGS=   -g -DPERFUSE_DEBUG
-.endif
 
 CWARNFLAGS.clang+=	-Wno-format-security
 

Index: src/lib/libperfuse/fuse.h
diff -u src/lib/libperfuse/fuse.h:1.3 src/lib/libperfuse/fuse.h:1.4
--- src/lib/libperfuse/fuse.h:1.3	Wed May 11 14:52:48 2011
+++ src/lib/libperfuse/fuse.h	Tue Jun 28 16:19:16 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: fuse.h,v 1.3 2011/05/11 14:52:48 jakllsch Exp $ */
+/*  $NetBSD: fuse.h,v 1.4 2011/06/28 16:19:16 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010 Emmanuel Dreyfus. All rights reserved.
@@ -39,6 +39,11 @@
 #define FUSE_BUFSIZE MAX(FUSE_PREF_BUFSIZE /* CONSTCOND */, FUSE_MIN_BUFSIZE)
 #endif /* FUSE_BUFSIZE */
 
+/* From <linux/limits.h> */
+#define LINUX_XATTR_NAME_MAX   255 
+#define LINUX_XATTR_SIZE_MAX 65536
+#define LINUX_XATTR_LIST_MAX 65536 
+
 struct fuse_attr {
 	uint64_t	ino;
 	uint64_t	size;

Index: src/lib/libperfuse/ops.c
diff -u src/lib/libperfuse/ops.c:1.30 src/lib/libperfuse/ops.c:1.31
--- src/lib/libperfuse/ops.c:1.30	Wed Jun  1 15:54:10 2011
+++ src/lib/libperfuse/ops.c	Tue Jun 28 16:19:16 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: ops.c,v 1.30 2011/06/01 15:54:10 manu Exp $ */
+/*  $NetBSD: ops.c,v 1.31 2011/06/28 16:19:16 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -36,6 +36,7 @@
 #include <puffs.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
+#include <sys/extattr.h>
 #include <machine/vmparam.h>
 
 #include "perfuse_priv.h"
@@ -2924,3 +2925,213 @@
 	return;
 }
 
+/* ARGSUSED4 */
+int
+perfuse_node_getextattr(pu, opc, attrns, attrname, attrsize, attr, resid, pcr)
+	struct puffs_usermount *pu;
+	puffs_cookie_t opc;
+	int attrns;
+	const char *attrname;
+	size_t *attrsize;
+	uint8_t *attr;
+	size_t *resid;
+	const struct puffs_cred *pcr;
+{
+	struct perfuse_state *ps;
+	char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
+	perfuse_msg_t *pm;
+	struct fuse_getxattr_in *fgi;
+	struct fuse_getxattr_out *fgo;
+	struct fuse_out_header *foh;
+	size_t attrnamelen;
+	size_t len;
+	char *np;
+	int error;
+
+	ps = puffs_getspecific(pu);
+	attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
+	attrnamelen = strlen(attrname) + 1;
+	len = sizeof(*fgi) + attrnamelen;
+
+	pm = ps->ps_new_msg(pu, opc, FUSE_GETXATTR, len, pcr);
+	fgi = GET_INPAYLOAD(ps, pm, fuse_getxattr_in);
+	fgi->size = (resid != NULL) ? *resid : 0;
+	np = (char *)(void *)(fgi + 1);
+	(void)strlcpy(np, attrname, attrnamelen);
+	
+	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
+		goto out;
+
+	/*
+	 * We just get fuse_getattr_out with list size if we requested
+	 * a null size.
+	 */
+	if (resid == NULL) {
+		fgo = GET_OUTPAYLOAD(ps, pm, fuse_getxattr_out);
+
+		if (attrsize != NULL)
+			*attrsize = fgo->size;
+
+		goto out;
+	}
+
+	/*
+	 * And with a non null requested size, we get the list just 
+	 * after the header
+	 */
+	foh = GET_OUTHDR(ps, pm);
+	np = (char *)(void *)(foh + 1);
+
+	if (resid != NULL) {
+		len = MAX(foh->len - sizeof(*foh), *resid);
+		(void)memcpy(attr, np, len);
+		*resid -= len;
+	}
+	
+out: 
+	ps->ps_destroy_msg(pm);
+
+	return error;
+}
+
+int
+perfuse_node_setextattr(pu, opc, attrns, attrname, attr, resid, pcr)
+	struct puffs_usermount *pu;
+	puffs_cookie_t opc;
+	int attrns;
+	const char *attrname;
+	uint8_t *attr;
+	size_t *resid;
+	const struct puffs_cred *pcr;
+{
+	struct perfuse_state *ps;
+	char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
+	perfuse_msg_t *pm;
+	struct fuse_setxattr_in *fsi;
+	size_t attrnamelen;
+	size_t len;
+	char *np;
+	int error;
+	
+	ps = puffs_getspecific(pu);
+	attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
+	attrnamelen = strlen(attrname) + 1;
+	len = sizeof(*fsi) + attrnamelen + *resid;
+
+	pm = ps->ps_new_msg(pu, opc, FUSE_SETXATTR, len, pcr);
+	fsi = GET_INPAYLOAD(ps, pm, fuse_setxattr_in);
+	fsi->size = *resid;
+	fsi->flags = 0;
+	np = (char *)(void *)(fsi + 1);
+	(void)strlcpy(np, attrname, attrnamelen);
+	np += attrnamelen;
+	(void)memcpy(np, (char *)attr, *resid);
+
+	if ((error = xchg_msg(pu, opc, pm, 
+			      NO_PAYLOAD_REPLY_LEN, wait_reply)) != 0)
+		goto out;
+
+	*resid = 0;
+out: 
+	ps->ps_destroy_msg(pm);
+
+	return error;
+}
+
+/* ARGSUSED2 */
+int
+perfuse_node_listextattr(pu, opc, attrns, attrsize, attrs, resid, pcr)
+	struct puffs_usermount *pu;
+	puffs_cookie_t opc;
+	int attrns;
+	size_t *attrsize;
+	uint8_t *attrs;
+	size_t *resid;
+	const struct puffs_cred *pcr;
+{
+	struct perfuse_state *ps;
+	perfuse_msg_t *pm;
+	struct fuse_getxattr_in *fgi;
+	struct fuse_getxattr_out *fgo;
+	struct fuse_out_header *foh;
+	char *np;
+	size_t len, puffs_len;
+	int error;
+	
+	ps = puffs_getspecific(pu);
+	len = sizeof(*fgi);
+
+	pm = ps->ps_new_msg(pu, opc, FUSE_LISTXATTR, len, pcr);
+	fgi = GET_INPAYLOAD(ps, pm, fuse_getxattr_in);
+	if (resid != NULL)
+		fgi->size = *resid;
+	else
+		fgi->size = 0;
+	
+	if ((error = xchg_msg(pu, opc, pm, UNSPEC_REPLY_LEN, wait_reply)) != 0)
+		goto out;
+
+	/*
+	 * We just get fuse_getattr_out with list size if we requested
+	 * a null size.
+	 */
+	if (resid == NULL) {
+		fgo = GET_OUTPAYLOAD(ps, pm, fuse_getxattr_out);
+
+		if (attrsize != NULL)
+			*attrsize = fgo->size;
+
+		goto out;
+	}
+
+	/*
+	 * And with a non null requested size, we get the list just 
+	 * after the header
+	 */
+	foh = GET_OUTHDR(ps, pm);
+	np = (char *)(void *)(foh + 1);
+	puffs_len = foh->len - sizeof(*foh);
+
+	if (attrs != NULL) {
+		(void)memcpy(attrs, np, puffs_len);
+		*resid -= puffs_len;
+	}
+
+	if (attrsize != NULL) 
+		*attrsize = puffs_len;
+
+out: 
+	ps->ps_destroy_msg(pm);
+
+	return error;
+}
+
+int
+perfuse_node_deleteextattr(pu, opc, attrns, attrname, pcr)
+	struct puffs_usermount *pu;
+	puffs_cookie_t opc;
+	int attrns;
+	const char *attrname;
+	const struct puffs_cred *pcr;
+{
+	struct perfuse_state *ps;
+	char fuse_attrname[LINUX_XATTR_NAME_MAX + 1];
+	perfuse_msg_t *pm;
+	size_t attrnamelen;
+	char *np;
+	int error;
+	
+	ps = puffs_getspecific(pu);
+	attrname = perfuse_native_ns(attrns, attrname, fuse_attrname);
+	attrnamelen = strlen(attrname) + 1;
+
+	pm = ps->ps_new_msg(pu, opc, FUSE_REMOVEXATTR, attrnamelen, pcr);
+	np = _GET_INPAYLOAD(ps, pm, char *);
+	(void)strlcpy(np, attrname, attrnamelen);
+	
+	error = xchg_msg(pu, opc, pm, NO_PAYLOAD_REPLY_LEN, wait_reply);
+	
+	ps->ps_destroy_msg(pm);
+
+	return error;
+}

Index: src/lib/libperfuse/perfuse.c
diff -u src/lib/libperfuse/perfuse.c:1.15 src/lib/libperfuse/perfuse.c:1.16
--- src/lib/libperfuse/perfuse.c:1.15	Mon May 30 14:50:08 2011
+++ src/lib/libperfuse/perfuse.c	Tue Jun 28 16:19:16 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse.c,v 1.15 2011/05/30 14:50:08 manu Exp $ */
+/*  $NetBSD: perfuse.c,v 1.16 2011/06/28 16:19:16 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -34,6 +34,7 @@
 #include <puffs.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/extattr.h>
 #include <sys/un.h>
 #include <machine/vmparam.h>
 
@@ -476,6 +477,12 @@
 	PUFFSOP_SET(pops, perfuse, node, advlock);
 	PUFFSOP_SET(pops, perfuse, node, read);
 	PUFFSOP_SET(pops, perfuse, node, write);
+#ifdef PUFFS_EXTNAMELEN
+	PUFFSOP_SET(pops, perfuse, node, getextattr);
+	PUFFSOP_SET(pops, perfuse, node, setextattr);
+	PUFFSOP_SET(pops, perfuse, node, listextattr);
+	PUFFSOP_SET(pops, perfuse, node, deleteextattr);
+#endif /* PUFFS_EXTNAMELEN */
 
 	puffs_flags = PUFFS_KFLAG_WTCACHE;
 

Index: src/lib/libperfuse/perfuse_priv.h
diff -u src/lib/libperfuse/perfuse_priv.h:1.18 src/lib/libperfuse/perfuse_priv.h:1.19
--- src/lib/libperfuse/perfuse_priv.h:1.18	Mon May 30 14:50:08 2011
+++ src/lib/libperfuse/perfuse_priv.h	Tue Jun 28 16:19:16 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: perfuse_priv.h,v 1.18 2011/05/30 14:50:08 manu Exp $ */
+/*  $NetBSD: perfuse_priv.h,v 1.19 2011/06/28 16:19:16 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -147,12 +147,13 @@
 uint64_t perfuse_next_unique(struct puffs_usermount *);
 char *perfuse_node_path(puffs_cookie_t);
 int perfuse_node_close_common(struct puffs_usermount *, puffs_cookie_t, int);
+const char *perfuse_native_ns(const int, const char *, char *);
 
 char *perfuse_fs_mount(int, ssize_t);
 
 
 /*
- * opc.c - filesystem operations
+ * ops.c - filesystem operations
  */
 int perfuse_fs_unmount(struct puffs_usermount *, int);
 int perfuse_fs_statvfs(struct puffs_usermount *, struct statvfs *);
@@ -221,6 +222,15 @@
     uint8_t *, off_t, size_t *, const struct puffs_cred *, int);
 void perfuse_cache_write(struct puffs_usermount *,
     puffs_cookie_t, size_t, struct puffs_cacherun *);
+int perfuse_node_getextattr(struct puffs_usermount *, puffs_cookie_t,
+    int, const char *, size_t *, uint8_t *, size_t *, 
+    const struct puffs_cred *);
+int perfuse_node_setextattr(struct puffs_usermount *, puffs_cookie_t,
+    int, const char *, uint8_t *, size_t *, const struct puffs_cred *);
+int perfuse_node_listextattr(struct puffs_usermount *, puffs_cookie_t,
+    int, size_t *, uint8_t *, size_t *, const struct puffs_cred *);
+int perfuse_node_deleteextattr(struct puffs_usermount *, puffs_cookie_t,
+    int, const char *, const struct puffs_cred *);
 
 __END_DECLS
 

Index: src/lib/libperfuse/subr.c
diff -u src/lib/libperfuse/subr.c:1.11 src/lib/libperfuse/subr.c:1.12
--- src/lib/libperfuse/subr.c:1.11	Mon Apr 25 04:54:53 2011
+++ src/lib/libperfuse/subr.c	Tue Jun 28 16:19:16 2011
@@ -1,4 +1,4 @@
-/*  $NetBSD: subr.c,v 1.11 2011/04/25 04:54:53 manu Exp $ */
+/*  $NetBSD: subr.c,v 1.12 2011/06/28 16:19:16 manu Exp $ */
 
 /*-
  *  Copyright (c) 2010-2011 Emmanuel Dreyfus. All rights reserved.
@@ -33,9 +33,19 @@
 #include <syslog.h>
 #include <puffs.h>
 #include <paths.h>
+#include <sys/extattr.h>
 
 #include "perfuse_priv.h"
 
+struct perfuse_ns_map {
+	const char *pnm_ns;
+	const size_t pnm_nslen;
+	const int pnm_native_ns;
+};
+
+#define PERFUSE_NS_MAP(ns, native_ns)	\
+	{ ns ".", sizeof(ns), native_ns }
+
 static size_t node_path(puffs_cookie_t, char *, size_t);
 
 struct puffs_node *
@@ -233,3 +243,51 @@
 
 	return buf;
 }
+
+const char *
+perfuse_native_ns(attrnamespace, attrname, fuse_attrname)
+	const int attrnamespace;
+	const char *attrname;
+	char *fuse_attrname;
+{
+	const struct perfuse_ns_map *pnm;
+	const struct perfuse_ns_map perfuse_ns_map[] = {
+		PERFUSE_NS_MAP("trusted", EXTATTR_NAMESPACE_SYSTEM),
+		PERFUSE_NS_MAP("security", EXTATTR_NAMESPACE_SYSTEM),
+		PERFUSE_NS_MAP("system", EXTATTR_NAMESPACE_SYSTEM),
+		PERFUSE_NS_MAP("user", EXTATTR_NAMESPACE_USER),
+		{ NULL, 0, EXTATTR_NAMESPACE_USER },
+	};
+
+	/*
+	 * If attribute has a reserved Linux namespace (e.g.: trusted.foo)
+	 * and that namespace matches the requested native namespace
+	 * we have nothing to do. 
+	 * Otherwise we have either:
+	 * (system|trusted|security).* with user namespace: prepend user.
+	 * anything else with system napespace: prepend system.
+	 */
+	for (pnm = perfuse_ns_map; pnm->pnm_ns; pnm++) {
+		if (strncmp(attrname, pnm->pnm_ns, pnm->pnm_nslen) != 0) 
+			continue;
+
+		if (attrnamespace == pnm->pnm_native_ns)
+			return attrname;
+
+	 	/* (system|trusted|security).* with user namespace */
+		if (attrnamespace == EXTATTR_NAMESPACE_USER) {
+			(void)snprintf(fuse_attrname, LINUX_XATTR_NAME_MAX, 
+				       "user.%s", attrname);
+			return (const char *)fuse_attrname;
+		}
+	}
+
+	/* anything else with system napespace */
+	if (attrnamespace == EXTATTR_NAMESPACE_SYSTEM) {
+		(void)snprintf(fuse_attrname, LINUX_XATTR_NAME_MAX, 
+			       "system.%s", attrname);
+		return (const char *)fuse_attrname;
+	}
+
+	return (const char *)attrname;
+}

Reply via email to