summaryrefslogtreecommitdiff
path: root/libattr
diff options
context:
space:
mode:
Diffstat (limited to 'libattr')
-rw-r--r--libattr/Makefile7
-rw-r--r--libattr/attr_copy_fd.c168
-rw-r--r--libattr/attr_copy_file.c166
-rw-r--r--libattr/libattr.c23
-rw-r--r--libattr/libattr.h11
5 files changed, 365 insertions, 10 deletions
diff --git a/libattr/Makefile b/libattr/Makefile
index 854db51..f9f9e14 100644
--- a/libattr/Makefile
+++ b/libattr/Makefile
@@ -36,10 +36,13 @@ include $(TOPDIR)/include/builddefs
LTLIBRARY = libattr.la
LT_CURRENT = 1
-LT_REVISION = 1
+LT_REVISION = 2
LT_AGE = 0
-CFILES = libattr.c syscalls.c
+CFILES = libattr.c syscalls.c attr_copy_fd.c attr_copy_file.c
+HFILES = libattr.h
+
+LCFLAGS = -include libattr.h
default: $(LTLIBRARY)
diff --git a/libattr/attr_copy_fd.c b/libattr/attr_copy_fd.c
new file mode 100644
index 0000000..78e6383
--- /dev/null
+++ b/libattr/attr_copy_fd.c
@@ -0,0 +1,168 @@
+/* Copy extended attributes between files. */
+
+/* Copyright (C) 2002 Andreas Gruenbacher <agruen@suse.de>, SuSE Linux AG.
+
+ 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, 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; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if defined (HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+#endif
+
+#if defined(HAVE_ATTR_XATTR_H)
+# include <attr/xattr.h>
+#endif
+
+#define ERROR_CONTEXT_MACROS
+#include "error_context.h"
+
+#if !defined(ENOTSUP)
+# define ENOTSUP (-1)
+#endif
+
+#if defined(HAVE_ALLOCA)
+# define my_alloc(size) alloca (size)
+# define my_free(ptr) do { } while(0)
+#else
+# define my_alloc(size) malloc (size)
+# define my_free(ptr) free (ptr)
+#endif
+
+static int
+check_no_acl(const char *name, struct error_context *ctx)
+{
+ return strcmp(name, "system.posix_acl_access") &&
+ strcmp(name, "system.posix_acl_default");
+}
+
+/* Copy extended attributes from src_path to dst_path. If the file
+ has an extended Access ACL (system.posix_acl_access) and that is
+ copied successfully, the file mode permission bits are copied as
+ a side effect. This may not always the case, so the file mode
+ and/or ownership must be copied separately. */
+int
+attr_copy_fd(const char *src_path, int src_fd,
+ const char *dst_path, int dst_fd,
+ int (*check) (const char *, struct error_context *),
+ struct error_context *ctx)
+{
+#if defined(HAVE_FLISTXATTR) && defined(HAVE_FGETXATTR) && \
+ defined(HAVE_FSETXATTR)
+ int ret = 0;
+ ssize_t size;
+ char *names = NULL, *end_names, *name, *value = NULL;
+
+ /* ignore acls by default */
+ if (check == NULL)
+ check = check_no_acl;
+
+ size = flistxattr (src_fd, NULL, 0);
+ if (size < 0) {
+ if (errno != ENOSYS && errno != ENOTSUP) {
+ const char *qpath = quote (ctx, src_path);
+ error (ctx, _("listing attributes of %s"), qpath);
+ quote_free (ctx, qpath);
+ ret = -1;
+ }
+ goto getout;
+ }
+ names = (char *) my_alloc (size+1);
+ if (names == NULL) {
+ error (ctx, "");
+ ret = -1;
+ goto getout;
+ }
+ size = flistxattr (src_fd, names, size);
+ if (size < 0) {
+ const char *qpath = quote (ctx, src_path);
+ error (ctx, _("listing attributes of %s"), qpath);
+ quote_free (ctx, qpath);
+ my_free (names);
+ ret = -1;
+ goto getout;
+ } else {
+ names[size] = '\0';
+ end_names = names + size;
+ }
+
+ for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
+ void *old_value;
+
+ /* check if this attribute shall be preserved */
+ if (!*name || !check(name, ctx))
+ continue;
+
+ size = fgetxattr (src_fd, name, NULL, 0);
+ if (size < 0) {
+ const char *qpath = quote (ctx, src_path);
+ const char *qname = quote (ctx, name);
+ error (ctx, _("getting attribute %s of %s"),
+ qpath, qname);
+ quote_free (ctx, qname);
+ quote_free (ctx, qpath);
+ ret = -1;
+ continue; /* may not have permission to access */
+ }
+ value = (char *) realloc (old_value = value, size);
+ if (size != 0 && value == NULL) {
+ free(old_value);
+ error (ctx, "");
+ ret = -1;
+ }
+ size = fgetxattr (src_fd, name, value, size);
+ if (size < 0) {
+ const char *qpath = quote (ctx, src_path);
+ const char *qname = quote (ctx, name);
+ error (ctx, _("getting attribute %s of %s"),
+ qname, qpath);
+ quote_free (ctx, qname);
+ quote_free (ctx, qpath);
+ ret = -1;
+ }
+ if (fsetxattr (dst_fd, name, value, size, 0) != 0)
+ {
+ const char *qpath = quote (ctx, dst_path);
+ if (errno == ENOSYS) {
+ error (ctx, _("setting attributes for %s"),
+ qpath);
+ ret = -1;
+ break; /* no hope of getting any further */
+ } else {
+ const char *qname = quote (ctx, name);
+ error (ctx, _("setting attribute %s for %s"),
+ qname, qpath);
+ quote_free (ctx, qname);
+ ret = -1;
+ }
+ quote_free (ctx, qpath);
+ }
+ }
+getout:
+ free (value);
+ my_free (names);
+ return ret;
+#else
+ return 0;
+#endif
+}
+
diff --git a/libattr/attr_copy_file.c b/libattr/attr_copy_file.c
new file mode 100644
index 0000000..98296ed
--- /dev/null
+++ b/libattr/attr_copy_file.c
@@ -0,0 +1,166 @@
+/* Copy extended attributes between files. */
+
+/* Copyright (C) 2002 Andreas Gruenbacher <agruen@suse.de>, SuSE Linux AG.
+
+ 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, 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; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if defined (HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+#endif
+
+#if defined(HAVE_ATTR_XATTR_H)
+# include <attr/xattr.h>
+#endif
+
+#define ERROR_CONTEXT_MACROS
+#include "error_context.h"
+
+#if !defined(ENOTSUP)
+# define ENOTSUP (-1)
+#endif
+
+#if defined(HAVE_ALLOCA)
+# define my_alloc(size) alloca (size)
+# define my_free(ptr) do { } while(0)
+#else
+# define my_alloc(size) malloc (size)
+# define my_free(ptr) free (ptr)
+#endif
+
+static int
+check_no_acl(const char *name, struct error_context *ctx)
+{
+ return strcmp(name, "system.posix_acl_access") &&
+ strcmp(name, "system.posix_acl_default");
+}
+
+/* Copy extended attributes from src_path to dst_path. If the file
+ has an extended Access ACL (system.posix_acl_access) and that is
+ copied successfully, the file mode permission bits are copied as
+ a side effect. This may not always the case, so the file mode
+ and/or ownership must be copied separately. */
+int
+attr_copy_file(const char *src_path, const char *dst_path,
+ int (*check) (const char *, struct error_context *),
+ struct error_context *ctx)
+{
+#if defined(HAVE_LISTXATTR) && defined(HAVE_GETXATTR) && defined(HAVE_SETXATTR)
+ int ret = 0;
+ ssize_t size;
+ char *names = NULL, *end_names, *name, *value = NULL;
+
+ /* ignore acls by default */
+ if (check == NULL)
+ check = check_no_acl;
+
+ size = listxattr (src_path, NULL, 0);
+ if (size < 0) {
+ if (errno != ENOSYS && errno != ENOTSUP) {
+ const char *qpath = quote (ctx, src_path);
+ error (ctx, _("listing attributes of %s"), qpath);
+ quote_free (ctx, qpath);
+ ret = -1;
+ }
+ goto getout;
+ }
+ names = (char *) my_alloc (size+1);
+ if (names == NULL) {
+ error (ctx, "");
+ ret = -1;
+ goto getout;
+ }
+ size = listxattr (src_path, names, size);
+ if (size < 0) {
+ const char *qpath = quote (ctx, src_path);
+ error (ctx, _("listing attributes of %s"), qpath);
+ quote_free (ctx, qpath);
+ my_free (names);
+ ret = -1;
+ goto getout;
+ } else {
+ names[size] = '\0';
+ end_names = names + size;
+ }
+
+ for (name = names; name != end_names; name = strchr(name, '\0') + 1) {
+ void *old_value;
+
+ /* check if this attribute shall be preserved */
+ if (!*name || !check(name, ctx))
+ continue;
+
+ size = getxattr (src_path, name, NULL, 0);
+ if (size < 0) {
+ const char *qpath = quote (ctx, src_path);
+ const char *qname = quote (ctx, name);
+ error (ctx, _("getting attribute %s of %s"),
+ qname, qpath);
+ quote_free (ctx, qname);
+ quote_free (ctx, qpath);
+ ret = -1;
+ continue; /* may not have permission to access */
+ }
+ value = (char *) realloc (old_value = value, size);
+ if (size != 0 && value == NULL) {
+ free(old_value);
+ error (ctx, "");
+ ret = -1;
+ }
+ size = getxattr (src_path, name, value, size);
+ if (size < 0) {
+ const char *qpath = quote (ctx, src_path);
+ const char *qname = quote (ctx, name);
+ error (ctx, _("getting attribute %s of %s"),
+ qname, qpath);
+ quote_free (ctx, qname);
+ quote_free (ctx, qpath);
+ ret = -1;
+ }
+ if (setxattr (dst_path, name, value, size, 0) != 0)
+ {
+ const char *qpath = quote (ctx, dst_path);
+ if (errno == ENOSYS) {
+ error (ctx, _("setting attributes for %s"),
+ qpath);
+ ret = -1;
+ break; /* no hope of getting any further */
+ } else {
+ const char *qname = quote (ctx, name);
+ error (ctx, _("setting attribute %s for %s"),
+ qname, qpath);
+ quote_free (ctx, qname);
+ ret = -1;
+ }
+ quote_free (ctx, qpath);
+ }
+ }
+getout:
+ free (value);
+ my_free (names);
+ return ret;
+#else
+ return 0;
+#endif
+}
+
diff --git a/libattr/libattr.c b/libattr/libattr.c
index 110f07c..1c37abc 100644
--- a/libattr/libattr.c
+++ b/libattr/libattr.c
@@ -44,25 +44,32 @@
#undef MAXNAMELEN
#define MAXNAMELEN 256
-static const char *user_name = "user.";
-static const char *root_name = "xfsroot.";
-
/*
* Convert IRIX API components into Linux/XFS API components
*/
static int
api_convert(char *name, const char *irixname, int irixflags)
{
- int len = strlen(irixname);
+ static const char *user_name = "user.";
+ static const char *trusted_name = "trusted.";
+ static const char *xfsroot_name = "xfsroot.";
+ static int compat = -1;
+
+ if (compat == -1)
+ compat = (getenv("COMPAT_XFSROOT") != NULL);
- if (len >= MAXNAMELEN) {
+ if (strlen(irixname) >= MAXNAMELEN) {
errno = EINVAL;
return -1;
}
- if (irixflags & ATTR_ROOT)
- strcpy(name, root_name);
- else
+ if (irixflags & ATTR_ROOT) {
+ if (compat)
+ strcpy(name, xfsroot_name);
+ else
+ strcpy(name, trusted_name);
+ } else {
strcpy(name, user_name);
+ }
strcat(name, irixname);
return 0;
}
diff --git a/libattr/libattr.h b/libattr/libattr.h
new file mode 100644
index 0000000..316c1db
--- /dev/null
+++ b/libattr/libattr.h
@@ -0,0 +1,11 @@
+/* Features we provide ourself. */
+
+#define HAVE_ATTR_XATTR_H 1
+#define HAVE_CONFIG_H 1
+
+#define HAVE_FGETXATTR 1
+#define HAVE_FLISTXATTR 1
+#define HAVE_FSETXATTR 1
+#define HAVE_GETXATTR 1
+#define HAVE_LISTXATTR 1
+#define HAVE_SETXATTR 1