diff options
Diffstat (limited to 'libattr')
-rw-r--r-- | libattr/Makefile | 7 | ||||
-rw-r--r-- | libattr/attr_copy_fd.c | 168 | ||||
-rw-r--r-- | libattr/attr_copy_file.c | 166 | ||||
-rw-r--r-- | libattr/libattr.c | 23 | ||||
-rw-r--r-- | libattr/libattr.h | 11 |
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 |