diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2009-07-14 11:50:55 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2009-07-14 13:32:16 +0100 |
commit | 2600359b9b520ab386f069fbbcd656e5cdbd9b76 (patch) | |
tree | 215a08e6a9081935321692e8fe6aee8fa7e53930 /daemon | |
parent | 7b3c76c95162f773dec03e0555d3060f0d2546c9 (diff) | |
download | libguestfs-2600359b9b520ab386f069fbbcd656e5cdbd9b76.tar.gz libguestfs-2600359b9b520ab386f069fbbcd656e5cdbd9b76.tar.xz libguestfs-2600359b9b520ab386f069fbbcd656e5cdbd9b76.zip |
Support for Linux extended attributes.
This commit adds six calls to support Linux extended attributes.
They are:
getxattrs list all extended attributes for a file or directory
setxattr add/replace an extended attribute
removexattr remove an extended attribute
lgetxattrs \
lsetxattr (same as above, but operate on symbolic links)
lremovexattr /
See attr(5) for more information.
This also adds support for the FBuffer field type, which maps to
an XDR opaque<> or a C (int, char *) pair.
Diffstat (limited to 'daemon')
-rw-r--r-- | daemon/Makefile.am | 1 | ||||
-rw-r--r-- | daemon/configure.ac | 5 | ||||
-rw-r--r-- | daemon/xattr.c | 284 |
3 files changed, 289 insertions, 1 deletions
diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 846a95c7..7b8a87ee 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -65,6 +65,7 @@ guestfsd_SOURCES = \ umask.c \ upload.c \ wc.c \ + xattr.c \ zero.c \ zerofree.c \ $(top_builddir)/../src/guestfs_protocol.h \ diff --git a/daemon/configure.ac b/daemon/configure.ac index 238532ea..2fd1ae93 100644 --- a/daemon/configure.ac +++ b/daemon/configure.ac @@ -63,7 +63,10 @@ AC_CHECK_LIB([portablexdr],[xdrmem_create],[],[ ]) dnl Functions which may not be available in older distributions. -AC_CHECK_FUNCS([futimens]) +AC_CHECK_FUNCS([futimens listxattr llistxattr getxattr lgetxattr setxattr lsetxattr removexattr lremovexattr]) + +dnl Headers. +AC_CHECK_HEADERS([attr/xattr.h]) dnl Produce output files. AC_CONFIG_HEADERS([config.h]) diff --git a/daemon/xattr.c b/daemon/xattr.c new file mode 100644 index 00000000..76f44bbf --- /dev/null +++ b/daemon/xattr.c @@ -0,0 +1,284 @@ +/* libguestfs - the guestfsd daemon + * Copyright (C) 2009 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <config.h> + +#include <stdio.h> +#include <unistd.h> + +#ifdef HAVE_ATTR_XATTR_H +#include <attr/xattr.h> + +#include "../src/guestfs_protocol.h" +#include "daemon.h" +#include "actions.h" + +static guestfs_int_xattr_list *getxattrs (char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t (*getxattr) (const char *path, const char *name, void *value, size_t size)); +static int _setxattr (char *xattr, char *val, int vallen, char *path, int (*setxattr) (const char *path, const char *name, const void *value, size_t size, int flags)); +static int _removexattr (char *xattr, char *path, int (*removexattr) (const char *path, const char *name)); + +guestfs_int_xattr_list * +do_getxattrs (char *path) +{ +#if defined(HAVE_LISTXATTR) && defined(HAVE_GETXATTR) + return getxattrs (path, listxattr, getxattr); +#else + reply_with_error ("getxattrs: no support for listxattr and getxattr"); + return NULL; +#endif +} + +guestfs_int_xattr_list * +do_lgetxattrs (char *path) +{ +#if defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR) + return getxattrs (path, llistxattr, lgetxattr); +#else + reply_with_error ("lgetxattrs: no support for llistxattr and lgetxattr"); + return NULL; +#endif +} + +int +do_setxattr (char *xattr, char *val, int vallen, char *path) +{ +#if defined(HAVE_SETXATTR) + return _setxattr (xattr, val, vallen, path, setxattr); +#else + reply_with_error ("setxattr: no support for setxattr"); + return -1; +#endif +} + +int +do_lsetxattr (char *xattr, char *val, int vallen, char *path) +{ +#if defined(HAVE_LSETXATTR) + return _setxattr (xattr, val, vallen, path, lsetxattr); +#else + reply_with_error ("lsetxattr: no support for lsetxattr"); + return -1; +#endif +} + +int +do_removexattr (char *xattr, char *path) +{ +#if defined(HAVE_REMOVEXATTR) + return _removexattr (xattr, path, removexattr); +#else + reply_with_error ("removexattr: no support for removexattr"); + return -1; +#endif +} + +int +do_lremovexattr (char *xattr, char *path) +{ +#if defined(HAVE_LREMOVEXATTR) + return _removexattr (xattr, path, lremovexattr); +#else + reply_with_error ("lremovexattr: no support for lremovexattr"); + return -1; +#endif +} + +static guestfs_int_xattr_list * +getxattrs (char *path, + ssize_t (*listxattr) (const char *path, char *list, size_t size), + ssize_t (*getxattr) (const char *path, const char *name, + void *value, size_t size)) +{ + ssize_t len, vlen; + char *buf = NULL; + int i, j; + guestfs_int_xattr_list *r = NULL; + + NEED_ROOT (NULL); + ABS_PATH (path, NULL); + + CHROOT_IN; + len = listxattr (path, NULL, 0); + CHROOT_OUT; + if (len == -1) { + reply_with_perror ("listxattr"); + goto error; + } + + buf = malloc (len); + if (buf == NULL) { + reply_with_perror ("malloc"); + goto error; + } + + CHROOT_IN; + len = listxattr (path, buf, len); + CHROOT_OUT; + if (len == -1) { + reply_with_perror ("listxattr"); + goto error; + } + + r = calloc (1, sizeof (*r)); + if (r == NULL) { + reply_with_perror ("malloc"); + goto error; + } + + /* What we get from the kernel is a string "foo\0bar\0baz" of length + * len. First count the strings. + */ + r->guestfs_int_xattr_list_len = 0; + for (i = 0; i < len; i += strlen (&buf[i]) + 1) + r->guestfs_int_xattr_list_len++; + + r->guestfs_int_xattr_list_val = + calloc (r->guestfs_int_xattr_list_len, sizeof (guestfs_int_xattr)); + if (r->guestfs_int_xattr_list_val == NULL) { + reply_with_perror ("calloc"); + goto error; + } + + for (i = 0, j = 0; i < len; i += strlen (&buf[i]) + 1, ++j) { + CHROOT_IN; + vlen = getxattr (path, &buf[i], NULL, 0); + CHROOT_OUT; + if (vlen == -1) { + reply_with_perror ("getxattr"); + goto error; + } + + r->guestfs_int_xattr_list_val[j].attrname = strdup (&buf[i]); + r->guestfs_int_xattr_list_val[j].attrval.attrval_val = malloc (vlen); + r->guestfs_int_xattr_list_val[j].attrval.attrval_len = vlen; + + if (r->guestfs_int_xattr_list_val[j].attrname == NULL || + r->guestfs_int_xattr_list_val[j].attrval.attrval_val == NULL) { + reply_with_perror ("malloc"); + goto error; + } + + CHROOT_IN; + vlen = getxattr (path, &buf[i], + r->guestfs_int_xattr_list_val[j].attrval.attrval_val, + vlen); + CHROOT_OUT; + if (vlen == -1) { + reply_with_perror ("getxattr"); + goto error; + } + } + + free (buf); + + return r; + + error: + free (buf); + if (r) { + if (r->guestfs_int_xattr_list_val) + for (i = 0; i < r->guestfs_int_xattr_list_len; ++i) { + free (r->guestfs_int_xattr_list_val[i].attrname); + free (r->guestfs_int_xattr_list_val[i].attrval.attrval_val); + } + free (r->guestfs_int_xattr_list_val); + } + free (r); + return NULL; +} + +static int +_setxattr (char *xattr, char *val, int vallen, char *path, + int (*setxattr) (const char *path, const char *name, + const void *value, size_t size, int flags)) +{ + int r; + + CHROOT_IN; + r = setxattr (path, xattr, val, vallen, 0); + CHROOT_OUT; + if (r == -1) { + reply_with_perror ("setxattr"); + return -1; + } + + return 0; +} + +static int +_removexattr (char *xattr, char *path, + int (*removexattr) (const char *path, const char *name)) +{ + int r; + + CHROOT_IN; + r = removexattr (path, xattr); + CHROOT_OUT; + if (r == -1) { + reply_with_perror ("removexattr"); + return -1; + } + + return 0; +} + +#else /* !HAVE_ATTR_XATTR_H */ + +guestfs_int_xattr_list * +do_getxattrs (char *path) +{ + reply_with_error ("getxattrs: no support for xattrs"); + return NULL; +} + +guestfs_int_xattr_list * +do_lgetxattrs (char *path) +{ + reply_with_error ("lgetxattrs: no support for xattrs"); + return NULL; +} + +int +do_setxattr (char *xattr, char *val, int vallen, char *path) +{ + reply_with_error ("setxattr: no support for xattrs"); + return -1; +} + +int +do_lsetxattr (char *xattr, char *val, int vallen, char *path) +{ + reply_with_error ("lsetxattr: no support for xattrs"); + return -1; +} + +int +do_removexattr (char *xattr, char *path) +{ + reply_with_error ("removexattr: no support for xattrs"); + return -1; +} + +int +do_lremovexattr (char *xattr, char *path) +{ + reply_with_error ("lremovexattr: no support for xattrs"); + return -1; +} + +#endif /* !HAVE_ATTR_XATTR_H */ |