Add support for extended attributes
This commit is contained in:
parent
4492ea236c
commit
8ae0a67d6d
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ perfuse_cache_write(pu, opc, size, runs)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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 @@ perfuse_init(pc, pmi)
|
|||
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;
|
||||
|
||||
|
|
|
@ -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_get_fh(puffs_cookie_t, int);
|
|||
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 @@ int perfuse_node_write(struct puffs_usermount *, puffs_cookie_t,
|
|||
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
|
||||
|
||||
|
|
|
@ -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 @@ perfuse_node_path(opc)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue