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; +}