From c82edc1013cf28a096cb8f5ba21c28d3e9312227 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 25 Feb 2002 22:10:22 +0000 Subject: Merge of xfs-cmds-2.4.18:slinx:111138a by nathans. bump to version 2.0.0 for extended attribute and other interface changes. incorporate new code, docs, etc from ext2/ext3 project. --- Makefile | 2 +- README | 6 +- VERSION | 6 +- attr/attr.c | 65 +------- build/rpm/attr.spec.in | 23 +-- debian/changelog | 8 +- debian/control | 26 +-- debian/copyright | 13 +- doc/CHANGES | 17 +- doc/COPYING | 8 +- doc/PORTING | 2 +- getfattr/Makefile | 51 ++++++ getfattr/getfattr.c | 422 ++++++++++++++++++++++++++++++++++++++++++++++++ getfattr/walk_tree.c | 94 +++++++++++ getfattr/walk_tree.h | 18 +++ include/Makefile | 6 +- include/attr_kern.h | 65 -------- include/attributes.h | 125 +++++---------- include/xattr.h | 76 +++++++++ libattr/Makefile | 15 +- libattr/attr.c | 319 ------------------------------------- libattr/libattr.c | 249 +++++++++++++++++++++++++++++ libattr/syscalls.c | 167 +++++++++++++++++++ man/Makefile | 2 +- man/man1/attr.1 | 65 ++++---- man/man1/getfattr.1 | 129 +++++++++++++++ man/man1/setfattr.1 | 71 +++++++++ man/man2/attrctl.2 | 350 ---------------------------------------- man/man2/getxattr.2 | 123 ++++++++++++++ man/man2/listxattr.2 | 137 ++++++++++++++++ man/man2/removexattr.2 | 91 +++++++++++ man/man2/setxattr.2 | 126 +++++++++++++++ man/man3/attr_get.3 | 8 +- man/man3/attr_list.3 | 269 ------------------------------- man/man3/attr_multi.3 | 6 +- man/man3/attr_remove.3 | 8 +- man/man3/attr_set.3 | 8 +- man/man5/Makefile | 48 ++++++ man/man5/attr.5 | 110 +++++++++++++ setfattr/Makefile | 50 ++++++ setfattr/setfattr.c | 425 +++++++++++++++++++++++++++++++++++++++++++++++++ test/Makefile | 44 +++++ test/README | 9 ++ test/attr.test | 78 +++++++++ test/run | 145 +++++++++++++++++ 45 files changed, 2831 insertions(+), 1254 deletions(-) create mode 100644 getfattr/Makefile create mode 100644 getfattr/getfattr.c create mode 100644 getfattr/walk_tree.c create mode 100644 getfattr/walk_tree.h delete mode 100644 include/attr_kern.h create mode 100644 include/xattr.h delete mode 100644 libattr/attr.c create mode 100644 libattr/libattr.c create mode 100644 libattr/syscalls.c create mode 100644 man/man1/getfattr.1 create mode 100644 man/man1/setfattr.1 delete mode 100644 man/man2/attrctl.2 create mode 100644 man/man2/getxattr.2 create mode 100644 man/man2/listxattr.2 create mode 100644 man/man2/removexattr.2 create mode 100644 man/man2/setxattr.2 create mode 100644 man/man5/Makefile create mode 100644 man/man5/attr.5 create mode 100644 setfattr/Makefile create mode 100644 setfattr/setfattr.c create mode 100644 test/Makefile create mode 100644 test/README create mode 100644 test/attr.test create mode 100644 test/run diff --git a/Makefile b/Makefile index d239aff..7b96fda 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ LSRCFILES = configure configure.in Makepkgs install-sh README VERSION LDIRT = config.log config.status config.cache confdefs.h conftest* \ Logs/* built .census install.* install-dev.* *.gz -SUBDIRS = include libattr attr man doc debian build +SUBDIRS = include libattr attr getfattr setfattr test man doc debian build default: $(CONFIGURE) ifeq ($(HAVE_BUILDDEFS), no) diff --git a/README b/README index c60b176..a07e36b 100644 --- a/README +++ b/README @@ -4,9 +4,13 @@ _________________________________ See the file doc/INSTALL for build, installation and post- install configuration steps. -Refer to the attr(1) manual page for general extended attribute +Refer to the attr(5) manual page for general extended attribute (EA) information and references to other EA manual pages. +Complete information on the extended attributes project for the +ext2 and ext3 filesystems, refer to: + http://acl.bestbits.at/ + For more information and details on how to contribute to the XFS project see the web pages at: http://oss.sgi.com/projects/xfs/ diff --git a/VERSION b/VERSION index 0422c97..9467406 100644 --- a/VERSION +++ b/VERSION @@ -1,7 +1,7 @@ # # This file is used by configure to get version information # -PKG_MAJOR=1 -PKG_MINOR=1 -PKG_REVISION=4 +PKG_MAJOR=2 +PKG_MINOR=0 +PKG_REVISION=0 PKG_BUILD=0 diff --git a/attr/attr.c b/attr/attr.c index 9a8d9a6..280ded1 100644 --- a/attr/attr.c +++ b/attr/attr.c @@ -30,7 +30,6 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ - #include #include #include @@ -47,7 +46,6 @@ #define SETOP 1 /* do a SET operation */ #define GETOP 2 /* do a GET operation */ #define REMOVEOP 3 /* do a REMOVE operation */ -#define LISTOP 4 /* do a LIST operation */ static char *progname; @@ -58,21 +56,17 @@ usage(void) "Usage: %s [-LRq] -s attrname [-V attrvalue] pathname # set value\n" " %s [-LRq] -g attrname pathname # get value\n" " %s [-LRq] -r attrname pathname # remove attr\n" -" %s [-LRq] -l pathname # list attrs\n" " -s reads a value from stdin and -g writes a value to stdout\n", - progname, progname, progname, progname); + progname, progname, progname); exit(1); } int main(int argc, char **argv) { - char *attrname, *attrvalue, *filename, *buffer; + char *attrname, *attrvalue, *filename; int attrlength; - int opflag, ch, error, follow, verbose, rootflag, i; - attrlist_t *alist; - attrlist_ent_t *aep; - attrlist_cursor_t cursor; + int opflag, ch, error, follow, verbose, rootflag; progname = basename(argv[0]); @@ -82,12 +76,12 @@ main(int argc, char **argv) verbose = 1; follow = opflag = rootflag = 0; attrname = attrvalue = NULL; - while ((ch = getopt(argc, argv, "s:V:g:r:lqLR")) != EOF) { + while ((ch = getopt(argc, argv, "s:V:g:r:qLR")) != EOF) { switch (ch) { case 's': if ((opflag != 0) && (opflag != SETOP)) { fprintf(stderr, - "Only one of -s, -g, -r, or -l allowed\n"); + "Only one of -s, -g, or -r allowed\n"); usage(); } opflag = SETOP; @@ -105,7 +99,7 @@ main(int argc, char **argv) case 'g': if (opflag) { fprintf(stderr, - "Only one of -s, -g, -r, or -l allowed\n"); + "Only one of -s, -g, or -r allowed\n"); usage(); } opflag = GETOP; @@ -114,20 +108,12 @@ main(int argc, char **argv) case 'r': if (opflag) { fprintf(stderr, - "Only one of -s, -g, -r, or -l allowed\n"); + "Only one of -s, -g, or -r allowed\n"); usage(); } opflag = REMOVEOP; attrname = optarg; break; - case 'l': - if (opflag) { - fprintf(stderr, - "Only one of -s, -g, -r, or -l allowed\n"); - usage(); - } - opflag = LISTOP; - break; case 'L': follow++; break; @@ -223,44 +209,9 @@ main(int argc, char **argv) } break; - case LISTOP: - if ((buffer = malloc(ATTR_MAX_VALUELEN)) == NULL) { - perror("malloc"); - exit(1); - } - - memset((char *)&cursor, 0, sizeof(cursor)); - - do { - error = attr_list(filename, buffer, ATTR_MAX_VALUELEN, - (!follow ? ATTR_DONTFOLLOW : 0) | - (rootflag ? ATTR_ROOT : 0), - &cursor); - if (error) { - perror("attr_list"); - fprintf(stderr, "Could not list attributes for %s\n", - filename); - exit(1); - } - - alist = (attrlist_t *)buffer; - for (i = 0; i < alist->al_count; i++) { - aep = (attrlist_ent_t *)&buffer[ alist->al_offset[i] ]; - if (verbose) { - printf("Attribute \"%s\" has a %d byte value for %s\n", - aep->a_name, - aep->a_valuelen, - filename); - } else { - printf("%s\n", aep->a_name); - } - } - } while (alist->al_more); - break; - default: fprintf(stderr, - "At least one of -s, -g, -r, or -l is required\n"); + "At least one of -s, -g, or -r is required\n"); usage(); break; } diff --git a/build/rpm/attr.spec.in b/build/rpm/attr.spec.in index c9d4990..e14e7cc 100644 --- a/build/rpm/attr.spec.in +++ b/build/rpm/attr.spec.in @@ -1,4 +1,4 @@ -Summary: Utility for managing filesystem extended attributes. +Summary: Utilities for managing filesystem extended attributes. Name: @pkg_name@ Version: @pkg_version@ Release: @pkg_release@ @@ -6,6 +6,7 @@ Distribution: @pkg_distribution@ Packager: @pkg_builder@ BuildRoot: @build_root@ Prereq: /sbin/ldconfig +Conflicts: xfsdump < 2.0.0 Source: @pkg_name@-@pkg_version@.src.tar.gz Copyright: Copyright (C) 2000 Silicon Graphics, Inc. Vendor: Silicon Graphics, Inc. @@ -13,23 +14,25 @@ URL: http://oss.sgi.com/projects/xfs/ Group: System Environment/Base %description -A utility for manipulating extended attributes on filesystem -objects, compatible with the SGI IRIX tool of the same name. +A set of tools for manipulating extended attributes on filesystem +objects, in particular getfattr(1) and setfattr(1). +An attr(1) command is also provided which is largely compatible +with the SGI IRIX tool of the same name. %package devel Summary: Extended attribute static libraries and headers. Group: Development/Libraries -Requires: @pkg_name@ +Requires: @pkg_name@ >= 2.0.0 %description devel attr-devel contains the libraries and header files needed to -develop programs which make use of extended attributes. This -interface is compatible with the SGI IRIX extended attribute -interface, and makes use of an unofficial Linux system call. +develop programs which make use of extended attributes. +For Linux programs, the documented system call API is the +recommended interface, but an SGI IRIX compatibility interface +is also provided. -Currently only XFS is supported, and the (experimental, unofficial) -system call interface is likely to change in the future. However, -the API built above this system call is unlikely to change and is +Currently only ext2, ext3 and XFS support extended attributes. +The SGI IRIX compatibility API built above the Linux system calls is used by programs such as xfsdump(8), xfsrestore(8) and xfs_fsr(8). You should install attr-devel if you want to develop programs diff --git a/debian/changelog b/debian/changelog index e607335..6a93561 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,10 @@ -attr (1.1.4-1) unstable; urgency=low +attr (2.0.0-1) unstable; urgency=low - * Bug fix in attr_multi(3), use of "count" parameter was broken + * Major new upstream release + * Several system call changes - THIS WILL NOT WORK WITH OLD KERNELS! + * Uses the new shared ext2/ext3/XFS extended attributes interfaces - -- Nathan Scott Fri, 11 Jan 2002 08:43:58 +1100 + -- Nathan Scott Thu, 7 Feb 2002 13:25:26 +1100 attr (1.1.3-0) unstable; urgency=low diff --git a/debian/control b/debian/control index 09a5e22..b4bb381 100644 --- a/debian/control +++ b/debian/control @@ -7,24 +7,26 @@ Standards-Version: 3.5.5 Package: attr Depends: ${shlibs:Depends} +Conflicts: xfsdump (<< 2.0.0) Architecture: any -Description: Utility for manipulating filesystem extended attributes - A utility for manipulating extended attributes on filesystem - objects, compatible with the SGI IRIX tool of the same name. +Description: Utilities for manipulating filesystem extended attributes + A set of tools for manipulating extended attributes on filesystem + objects, in particular getfattr(1) and setfattr(1). + An attr(1) command is also provided which is largely compatible + with the SGI IRIX tool of the same name. Package: attr-dev Section: devel Priority: extra -Depends: libc6-dev, attr +Depends: libc6-dev, attr (>= 2.0.0) +Conflicts: attr (<< 2.0.0) Architecture: any -Description: Extended attribute static libraries and headers. +Description: Extended attribute static libraries and headers attr-dev contains the libraries and header files needed to develop - programs which make use of extended attributes. + programs which make use of extended attributes. For Linux programs, + the documented system call API is the recommended interface, but an + SGI IRIX compatibility interface is also provided. . - This interface is compatible with the SGI IRIX extended attribute - interface, and makes use of an unofficial Linux system call. - . - Currently only XFS is supported, and the (experimental, unofficial) - system call interface is likely to change in the future. However, - the API built above this system call is unlikely to change and is + Currently only ext2, ext3 and XFS support extended attributes. + The SGI IRIX compatibility API built above the Linux system calls is used by programs such as xfsdump(8), xfsrestore(8) and xfs_fsr(8). diff --git a/debian/copyright b/debian/copyright index d956166..2e88adb 100644 --- a/debian/copyright +++ b/debian/copyright @@ -5,10 +5,15 @@ It can be downloaded from ftp://oss.sgi.com/projects/xfs/download/ Copyright: -Copyright (C) 2000 Silicon Graphics, Inc. +Copyright (C) 2001 Silicon Graphics, Inc. +Copyright (C) 2001 Andreas Gruenbacher. -You are free to distribute this software under the terms of -the GNU General Public License. +You are free to distribute this software under Version 2.1 +of the GNU Lesser General Public License. +On Debian systems, refer to /usr/share/common-licenses/LGPL-2.1 +for the complete text of the GNU Lesser General Public License. + +Certain components (as annotated in the source) are licensed +under the terms of the GNU General Public License. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL file. - diff --git a/doc/CHANGES b/doc/CHANGES index 5a5e060..2b1b111 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,20 +1,23 @@ -attr-1.1.4 (11 Jan 2002) - - bug fix in attr_multi(3), use of "count" was broken +attr-2.0.0 (07 February 2002) + - initial introduction of the new system call interface + - synced up with the ext2 project, incorporated get/set tools + - new man pages for system calls, getfattr(1) and setfattr(1) + - made the attributes.h interface align properly with IRIX -attr-1.1.3 (03 Aug 2001) +attr-1.1.3 (03 August 2001) - bug fix from Juer Lee, syscall use on non-i386 was broken - tested on PowerPC and i386; code is simpler and works - install an additional library symlink for ld, so that the shared lib is always found before the static lib at link time -attr-1.1.2 (27 Jul 2001) +attr-1.1.2 (27 July 2001) - fixes for (hopefully) the last few nits in libtool usage -attr-1.1.1 (23 Jul 2001) +attr-1.1.1 (23 July 2001) - install static libs and libtool archives into /usr/lib - shared libraries are unchanged, however -attr-1.1.0 (16 Jul 2001) +attr-1.1.0 (16 July 2001) - reworked Makefiles to use libtool - rework some of the Debian packaging rules - install attr command into /usr/bin, not /bin @@ -22,7 +25,7 @@ attr-1.1.0 (16 Jul 2001) as it is needed by xfsdump and xfsrestore which must be available for recovery when only root is mounted -attr-1.0.4 (02 Jul 2001) +attr-1.0.4 (02 July 2001) - work around syscall number collision on recent ia64 kernels attr-1.0.3 (18 May 2001) diff --git a/doc/COPYING b/doc/COPYING index a889ebd..d5d18c3 100644 --- a/doc/COPYING +++ b/doc/COPYING @@ -1,8 +1,8 @@ -All the libraries in "attr" are licensed under Version 2.1 -of the GNU Lesser General Public License. +Most components of the "attr" package are licensed under +Version 2.1 of the GNU Lesser General Public License. -All other "attr" components are licensed under Version 2 of -the GNU General Public License. +Some components (as annotated in the source) are licensed +under Version 2 of the GNU General Public License. ---------------------------------------------------------------------- diff --git a/doc/PORTING b/doc/PORTING index 87bedd4..77829c6 100644 --- a/doc/PORTING +++ b/doc/PORTING @@ -42,7 +42,7 @@ example using SUBDIRS : attr/Makefile example static library: attr/libattr/Makefile - example command : attr/attr/Makefile + example command : attr/getfattr/Makefile All Makefiles must define TOPDIR as the root of the project. This allows other stuff to be found relative to $(TOPDIR). diff --git a/getfattr/Makefile b/getfattr/Makefile new file mode 100644 index 0000000..d474763 --- /dev/null +++ b/getfattr/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, +# Mountain View, CA 94043, or: +# +# http://www.sgi.com +# +# For further information regarding this notice, see: +# +# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ +# + +TOPDIR = .. +include $(TOPDIR)/include/builddefs + +LTCOMMAND = getfattr +CFILES = walk_tree.c getfattr.c +HFILES = walk_tree.h + +LLDLIBS = $(LIBATTR) +LTDEPENDENCIES = $(LIBATTR) + +default: $(LTCOMMAND) + +include $(BUILDRULES) + +install: default + $(INSTALL) -m 755 -d $(PKG_BIN_DIR) + $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR) + $(INSTALL) -S $(LTCOMMAND) $(PKG_BIN_DIR)/aget +install-dev: diff --git a/getfattr/getfattr.c b/getfattr/getfattr.c new file mode 100644 index 0000000..bd642cf --- /dev/null +++ b/getfattr/getfattr.c @@ -0,0 +1,422 @@ +/* + * Original getfattr.c: + * Copyright (C) 2001 by Andreas Gruenbacher + * Changes to use revised EA syscall interface: + * Copyright (C) 2001 by SGI XFS development + */ + +#include +#include +#include +#include +#include +#include +#include "walk_tree.h" + +#include +#include +#define _(String) gettext (String) + +#define CMD_LINE_OPTIONS "ade:hln:r:svR5LPV" +#define CMD_LINE_SPEC "[-n name|-d] [-ahsvR5LPV] [-e en] [-r regex] path..." + +int opt_dump; +int opt_symlink; +char *opt_encoding; +char opt_value_only; +int opt_strip_leading_slash = 1; + +const char *progname; +int absolute_warning; +int header_printed; +int had_errors; +regex_t re; + +int do_get_all(const char *, struct stat *, void *); +int do_get_one(const char *, struct stat *, void *); +int get_one(const char *, const char *); +const char *encode(const char *value, size_t *size); + + +void help(void) +{ + printf(_("%s %s -- get extended attributes\n"), + progname, VERSION); + printf(_("Usage: %s %s\n"), + progname, CMD_LINE_SPEC); + printf(_("\t-n name\tdump value of extended attribute `name'\n" + "\t-a\tabsolute pathnames - leading '/' not stripped\n" + "\t-d\tdump all extended attribute values\n" + "\t-e en\tencode values (en = text|hex|base64)\n" + "\t-l\tdump extended attribute values of a symlink\n" + "\t-s\tdump extended system and user attribute values\n" + "\t-v\tprint the attribute value(s) only\n" + "\t-R\trecurse into subdirectories (-5 = post-order)\n" + "\t-L\tlogical walk, follow symbolic links\n" + "\t-P\tphysical walk, do not follow symbolic links\n" + "\t-V\tprint version and exit\n" + "\t-h\tthis help text\n")); +} + +int main(int argc, char *argv[]) +{ + char sys_pattern[] = "^system\\.|^user\\."; + char usr_pattern[] = "^user\\."; + char *pattern = usr_pattern; + char *name = NULL; + + progname = basename(argv[0]); + setlocale(LC_ALL, ""); + + while ((optopt = getopt(argc, argv, CMD_LINE_OPTIONS)) != -1) { + switch(optopt) { + case 'a': /* absolute names */ + opt_strip_leading_slash = 0; + break; + + case 'd': /* dump attribute values */ + opt_dump = 1; + break; + + case 'e': /* encoding */ + if (strcmp(optarg, "text") != 0 && + strcmp(optarg, "hex") != 0 && + strcmp(optarg, "base64") != 0) + goto synopsis; + opt_encoding = optarg; + break; + + case 'h': + help(); + return 0; + + case 'l': /* dump attribute(s) of symlink itself */ + opt_symlink = 1; + break; + + case 'n': /* get named attribute */ + opt_dump = 1; + name = optarg; + break; + + case 'r': + pattern = optarg; + break; + + case 's': + pattern = sys_pattern; + break; + + case 'v': /* get attribute values only */ + opt_value_only = 1; + break; + + case 'H': + walk_symlinks = WALK_HALF_LOGICAL; + break; + + case 'L': + walk_symlinks = WALK_FULL_LOGICAL; + break; + + case 'P': + walk_symlinks = WALK_PHYSICAL; + break; + + case 'R': + walk_recurse = 1; + walk_postorder = 0; + break; + + case '5': + walk_recurse = 1; + walk_postorder = 1; + break; + + case 'V': + printf("%s " VERSION "\n", progname); + return 0; + + default: + goto synopsis; + } + } + if (optind >= argc) + goto synopsis; + + if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) { + fprintf(stderr, _("%s: invalid regular expression \"%s\"\n"), + progname, pattern); + return 1; + } + + while (optind < argc) { + if (name) + had_errors += walk_tree(argv[optind], do_get_one, name); + else + had_errors += walk_tree(argv[optind], do_get_all, NULL); + optind++; + } + + return (had_errors ? 1 : 0); + +synopsis: + fprintf(stderr, _("Usage: %s %s\n" + "Try `%s -h' for more information.\n"), + progname, CMD_LINE_SPEC, progname); + return 2; +} + +int do_getxattr(const char *path, const char *name, void *value, size_t size) +{ + if (opt_symlink) + return lgetxattr(path, name, value, size); + return getxattr(path, name, value, size); +} + +int do_listxattr(const char *path, char *list, size_t size) +{ + if (opt_symlink) + return llistxattr(path, list, size); + return listxattr(path, list, size); +} + +int pstrcmp(const char **a, const char **b) +{ + return strcmp(*a, *b); +} + +int do_get_all(const char *path, struct stat *stat, void *dummy) +{ + /* nathans TODO - use a high-water-mark allocation here! */ + char *v; + char *list; /* ie. make list & lbufsize "static" & realloc */ + int n = 0, count = 0; + ssize_t listsize, lbufsize; + const char **names = NULL; + + lbufsize = do_listxattr(path, NULL, 0); + if (lbufsize < 0) { + if (errno != ENOATTR && errno != ENOTSUP) { + perror(path); + had_errors++; + return 1; + } + } else { + /* nathans TODO - use a high-water-mark allocation here! */ + list = malloc(++lbufsize); + if (!list) { + perror(progname); + had_errors++; + return 1; + } + memset(list, 0, lbufsize); + listsize = do_listxattr(path, list, lbufsize - 1); + if (listsize < 0) { + perror(path); + had_errors++; + return 1; + } + + for (v = list; v - list <= listsize; v += strlen(v)+1) + if (regexec(&re, v, (size_t) 0, NULL, 0) == 0) + count++; + if (count) { + names = (const char **)malloc(count * sizeof(char *)); + if (!names) { + perror(progname); + had_errors++; + return 1; + } + for (v = list; v - list <= listsize; v += strlen(v)+1) + if (regexec(&re, v, (size_t) 0, NULL, 0) == 0) + names[n++] = v; + qsort(names, count, sizeof(char *), + (int (*)(const void *,const void *))pstrcmp); + } + } + if (names) { + header_printed = 0; + for (n = 0; n < count; n++) + get_one(path, names[n]); + if (header_printed) + puts(""); + } + return 0; +} + +int do_get_one(const char *path, struct stat *stat, void *name) +{ + int error; + + header_printed = 0; + error = get_one(path, (const char *)name); + if (header_printed) + puts(""); + return error; +} + +int get_one(const char *path, const char *name) +{ + char *value = NULL; + size_t size = 0; + int error; + + if (opt_dump || opt_value_only) { + error = do_getxattr(path, name, NULL, 0); + if (error < 0) { + const char *strerr; +syscall_failed: + if (!strncmp("system.", name, 7) && errno == ENOATTR) + return 0; /* expected */ + else if (errno == ENOATTR) + strerr = _("No such attribute"); + else + strerr = strerror(errno); + fprintf(stderr, "%s: %s: %s\n", path, name, strerr); + return 1; + } + /* nathans TODO - high-water-mark allocate here too? */ + size = error; + value = (char *)malloc(size+1); + if (!value) { + perror(progname); + return 1; + } + error = do_getxattr(path, name, value, size); + if (error < 0) + goto syscall_failed; + value[size] = '\0'; + size = error; + } + + if (opt_strip_leading_slash) { + if (*path == '/') { + if (!absolute_warning) { + fprintf(stderr, _("%s: Removing leading '/' " + "from absolute path names\n"), + progname); + absolute_warning = 1; + } + while (*path == '/') + path++; + } else if (*path == '.' && *(path+1) == '/') + while (*++path == '/') + /* nothing */ ; + if (*path == '\0') + path = "."; + } + + if (!header_printed && !opt_value_only) { + printf("# file: %s\n", path); + header_printed = 1; + } + if (opt_value_only) + puts(value); + else if (size) { + const char *e = encode(value, &size); + + if (e) + printf("%s=%s\n", name, e); + } else + puts(name); + + return 0; +} + +const char *encode(const char *value, size_t *size) +{ + static char *encoded = NULL, *e; + + if (encoded) + free(encoded); + if (opt_encoding == NULL || strcmp(opt_encoding, "text") == 0) { + int n, extra = 0; + + for (e=(char *)value; e < value + *size; e++) { + if (*e < 32 || *e >= 127) + extra += 4; + else if (*e == '\\' || *e == '"') + extra++; + } + encoded = (char *)malloc(*size + extra + 3); + if (!encoded) { + perror(progname); + had_errors++; + return NULL; + } + e = encoded; + *e++='"'; + for (n = 0; n < *size; n++, value++) { + if (*value < 32 || *value >= 127) { + *e++ = '\\'; + *e++ = '0' + ((unsigned char)*value >> 6); + *e++ = '0' + (((unsigned char)*value & 070) >> 3); + *e++ = '0' + ((unsigned char)*value & 07); + } else if (*value == '\\' || *value == '"') { + *e++ = '\\'; + *e++ = *value; + } else { + *e++ = *value; + } + } + *e++ = '"'; + *e = '\0'; + *size = (e - encoded); + } else if (strcmp(opt_encoding, "hex") == 0) { + static const char *digits = "0123456789abcdef"; + int n; + + encoded = (char *)malloc(*size * 2 + 4); + if (!encoded) { + perror(progname); + had_errors++; + return NULL; + } + e = encoded; + *e++='0'; *e++ = 'x'; + for (n = 0; n < *size; n++, value++) { + *e++ = digits[((unsigned char)*value >> 4)]; + *e++ = digits[((unsigned char)*value & 0x0F)]; + } + *e = '\0'; + *size = (e - encoded); + } else if (strcmp(opt_encoding, "base64") == 0) { + static const char *digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef" + "ghijklmnopqrstuvwxyz0123456789+/"; + int n; + + encoded = (char *)malloc((*size + 2) / 3 * 4 + 1); + if (!encoded) { + perror(progname); + had_errors++; + return NULL; + } + e = encoded; + *e++='0'; *e++ = 's'; + for (n=0; n + 2 < *size; n += 3) { + *e++ = digits[(unsigned char)value[0] >> 2]; + *e++ = digits[(((unsigned char)value[0] & 0x03) << 4) | + (((unsigned char)value[1] & 0xF0) >> 4)]; + *e++ = digits[(((unsigned char)value[1] & 0x0F) << 2) | + ((unsigned char)value[2] >> 6)]; + *e++ = digits[(unsigned char)value[2] & 0x3F]; + value += 3; + } + if (*size - n == 2) { + *e++ = digits[(unsigned char)value[0] >> 2]; + *e++ = digits[(((unsigned char)value[0] & 0x03) << 4) | + (((unsigned char)value[1] & 0xF0) >> 4)]; + *e++ = digits[((unsigned char)value[1] & 0x0F) << 2]; + *e++ = '='; + } else if (*size - n == 1) { + *e++ = digits[(unsigned char)value[0] >> 2]; + *e++ = digits[((unsigned char)value[0] & 0x03) << 4]; + *e++ = '='; + *e++ = '='; + } + *e = '\0'; + *size = (e - encoded); + } + return encoded; +} diff --git a/getfattr/walk_tree.c b/getfattr/walk_tree.c new file mode 100644 index 0000000..468fef4 --- /dev/null +++ b/getfattr/walk_tree.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2001 by Andreas Gruenbacher + * + * TODO: should this be replaced by using nftw(3)? + */ +#include +#include +#include +#include +#include +#include + +#include "walk_tree.h" + +int walk_recurse = 0; +int walk_postorder = 0; +int walk_symlinks = WALK_HALF_LOGICAL; + +int walk_tree(const char *path_p, int (*call)(const char *, struct stat *, + void *), void *arg) +{ + static struct stat st; + static int level = 0; + int follow; + int errors = 0; + + level++; + if (lstat(path_p, &st) != 0) + goto fail; + + if (S_ISLNK(st.st_mode)) { + if (walk_symlinks == WALK_PHYSICAL) + follow = 0; + else { + if (stat(path_p, &st) != 0) + goto fail; + follow = ((walk_symlinks == WALK_HALF_LOGICAL && + level == 1) || + walk_symlinks == WALK_FULL_LOGICAL); + } + } else + follow = 1; + + if (!follow) + goto cleanup; + + if (!walk_postorder) + errors += call(path_p, &st, arg); + + if (walk_recurse && S_ISDIR(st.st_mode)) { + struct dirent *dirent; + DIR *dir; + + char *ipath_p = (char *)path_p; + int ipath_length = strlen(ipath_p); + if (ipath_p[ipath_length-1] != '/') { + ipath_p = (char*)alloca(ipath_length + + _POSIX_PATH_MAX + 2); + if (ipath_p == NULL) + goto fail; + strcpy(ipath_p, path_p); + strcpy(ipath_p + ipath_length, "/"); + ipath_length++; + } + + dir = opendir(path_p); + if (dir == NULL) + goto fail; + while ((dirent = readdir(dir)) != NULL) { + if (!strcmp(dirent->d_name, ".") || + !strcmp(dirent->d_name, "..")) + continue; + strncpy(ipath_p + ipath_length, + dirent->d_name, _POSIX_PATH_MAX); + ipath_p[ipath_length + _POSIX_PATH_MAX] = '\0'; + walk_tree(ipath_p, call, arg); /* recurse */ + } + ipath_p[ipath_length] = '\0'; + closedir(dir); + } + + if (walk_postorder) + errors += call(path_p, &st, arg); + +cleanup: + level--; + return errors; + +fail: + fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno)); + errors++; + goto cleanup; +} + diff --git a/getfattr/walk_tree.h b/getfattr/walk_tree.h new file mode 100644 index 0000000..c84c742 --- /dev/null +++ b/getfattr/walk_tree.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2001 by Andreas Gruenbacher + * + * TODO: should this be replaced by using nftw(3)? + */ +#include + +extern const char *progname; + +#define WALK_FULL_LOGICAL 1 /* follow all symlinks */ +#define WALK_HALF_LOGICAL 2 /* follow symlink arguments */ +#define WALK_PHYSICAL 3 /* don't follow symlinks */ + +extern int walk_recurse; /* recurse into sudirectories */ +extern int walk_postorder; /* walk tree in postorder */ +extern int walk_symlinks; /* follow symbolic links */ + +int walk_tree(const char *, int (*call)(const char *, struct stat *, void *), void *); diff --git a/include/Makefile b/include/Makefile index 677e83e..ef299b7 100644 --- a/include/Makefile +++ b/include/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. +# Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of version 2 of the GNU General Public License as @@ -33,8 +33,8 @@ TOPDIR = .. include $(TOPDIR)/include/builddefs -HFILES = attributes.h -LSRCFILES = builddefs.in buildrules attr_kern.h +HFILES = attributes.h xattr.h +LSRCFILES = builddefs.in buildrules default install : diff --git a/include/attr_kern.h b/include/attr_kern.h deleted file mode 100644 index 3be50b9..0000000 --- a/include/attr_kern.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __ATTR_KERN_H__ -#define __ATTR_KERN_H__ - -/* - * The (experimental) Linux generic attribute syscall - attrctl(2) - */ - -typedef union attr_obj { - char *path; - int fd; - pid_t pid; -} attr_obj_t; - -/* - * attr_obj_t type identifiers - */ -#define ATTR_TYPE_FD 1 /* file descriptor */ -#define ATTR_TYPE_PATH 2 /* path - follow symlinks */ -#define ATTR_TYPE_LPATH 3 /* path - don't follow symlinks */ -#define ATTR_TYPE_PID 4 /* process id */ - -/* - * Kernel-internal version of the attrlist cursor. - */ -typedef struct attrlist_cursor_kern { - __u32 hashval; /* hash value of next entry to add */ - __u32 blkno; /* block containing entry (suggestion)*/ - __u32 offset; /* offset in list of equal-hashvals */ - __u16 pad1; /* padding to match user-level */ - __u8 pad2; /* padding to match user-level */ - __u8 initted; /* T/F: cursor has been initialized */ -} attrlist_cursor_kern_t; - -#endif /* __ATTR_KERN_H__ */ diff --git a/include/attributes.h b/include/attributes.h index f8e42a1..2912cba 100644 --- a/include/attributes.h +++ b/include/attributes.h @@ -1,33 +1,33 @@ /* - * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved. - * + * Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved. + * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. - * + * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * + * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like. Any license provided herein, whether implied or * otherwise, applies only to this software file. Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, * USA. - * + * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ #ifndef __ATTRIBUTES_H__ @@ -38,63 +38,33 @@ extern "C" { #endif /* - * An IRIX-compatible extended attributes API + * An almost-IRIX-compatible extended attributes API + * (the IRIX attribute "list" operation is missing). */ /* - * Valid command flags, may be used with all API calls. - * Multiple flags should be bitwise OR'ed together. - */ -#define ATTR_ROOT 0x0001 /* use attrs in root namespace, not user */ -#define ATTR_CREATE 0x0002 /* pure create: fail if attr already exists */ -#define ATTR_REPLACE 0x0004 /* pure set: fail if attr does not exist */ -#define ATTR_SHIFT 16 /* for supporting extensions */ - -/* - * Additional API specific opcodes & flags + * The maximum size (into the kernel or returned from the kernel) of an + * attribute value or the buffer used for an attr_list() call. Larger + * sizes will result in an E2BIG return code. */ -#define ATTR_DONTFOLLOW (0x0001 << ATTR_SHIFT) /* do not follow symlinks */ -#define ATTR_TRUST (0x0002 << ATTR_SHIFT) - /* tell server we are trusted to properly handle extended attributes */ - -#define ATTR_KERNOTIME (0x0004 << ATTR_SHIFT) - /* don't update inode timestamps. - * The DMI needs a way to update attributes without affecting the - * inode timestamps. Note that this flag is not set-able from user - * mode - it is kernel internal only, but it must not conflict with - * the user flags either. - */ +#define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */ -/* - * Generic extended attribute operation structure - */ -typedef struct attr_op { - int opcode; /* which operation to perform */ - int error; /* result (an errno) of this operation [out] */ - char *name; /* attribute name */ - char *value; /* attribute value [in/out] */ - int length; /* value length [in/out] */ - int flags; /* bitwise OR of #defines below */ - void *aux; /* optional cmd specific data */ -} attr_op_t; /* - * Valid attr_op, attr_multi_op opcodes + * Flags that can be used with any of the simple attribute calls. + * All desired flags should be bit-wise OR'ed together. */ -#define ATTR_OP_GET 1 /* return the indicated attr's value */ -#define ATTR_OP_SET 2 /* set/create the indicated attr/value pair */ -#define ATTR_OP_REMOVE 3 /* remove the indicated attr */ -#define ATTR_OP_LIST 4 /* list attributes associated with a file */ - -#define ATTR_OP_EXT 32 /* for supporting extensions */ -#define ATTR_OP_IRIX_LIST (ATTR_OP_EXT + 0) /* IRIX attr_list semantics */ +#define ATTR_DONTFOLLOW 0x0001 /* do not follow symlinks for a pathname */ +#define ATTR_ROOT 0x0002 /* use root-defined attrs in op, not user */ +#define ATTR_TRUST 0x0004 /* tell server we can be trusted to properly + handle extended attributes */ /* - * The maximum size (into the kernel or returned from the kernel) of an - * attribute value or the buffer used for an attr_list() call. Larger - * sizes will result in an E2BIG return code. + * Additional flags that can be used with the set() attribute call. + * All desired flags (from both lists) should be bit-wise OR'ed together. */ -#define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */ +#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */ +#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */ /* * Define how lists of attribute names are returned to the user from @@ -103,9 +73,9 @@ typedef struct attr_op { * reference an attrlist_ent_t and pack the attrlist_ent_t's at the bottom. */ typedef struct attrlist { - __s32 al_count; /* number of entries in attrlist */ - __s32 al_more; /* T/F: more attrs (do call again) */ - __s32 al_offset[1]; /* byte offsets of attrs [var-sized] */ + int32_t al_count; /* number of entries in attrlist */ + int32_t al_more; /* T/F: more attrs (do call again) */ + int32_t al_offset[1]; /* byte offsets of attrs [var-sized] */ } attrlist_t; /* @@ -113,8 +83,8 @@ typedef struct attrlist { * al_offset[i] entry points to. */ typedef struct attrlist_ent { /* data from attr_list() */ - __u32 a_valuelen; /* number bytes in value of attr */ - char a_name[1]; /* attr name (NULL terminated) */ + u_int32_t a_valuelen; /* number bytes in value of attr */ + char a_name[1]; /* attr name (NULL terminated) */ } attrlist_ent_t; /* @@ -125,7 +95,6 @@ typedef struct attrlist_ent { /* data from attr_list() */ ((attrlist_ent_t *) \ &((char *)buffer)[ ((attrlist_t *)(buffer))->al_offset[index] ]) - /* * Implement a "cursor" for use in successive attr_list() calls. * It provides a way to find the last attribute that was returned in the @@ -135,22 +104,29 @@ typedef struct attrlist_ent { /* data from attr_list() */ * operation on a cursor is to bzero() it. */ typedef struct attrlist_cursor { - __u32 opaque[4]; /* an opaque cookie */ + u_int32_t opaque[4]; /* an opaque cookie */ } attrlist_cursor_t; /* * Multi-attribute operation vector. */ typedef struct attr_multiop { - int am_opcode; /* operation to perform (ATTR_OP_GET, etc.) */ - int am_error; /* [out arg] result of this sub-op (an errno) */ + int32_t am_opcode; /* operation to perform (ATTR_OP_GET, etc.) */ + int32_t am_error; /* [out arg] result of this sub-op (an errno) */ char *am_attrname; /* attribute name to work with */ char *am_attrvalue; /* [in/out arg] attribute value (raw bytes) */ - int am_length; /* [in/out arg] length of value */ - int am_flags; /* bitwise OR of attr API flags defined above */ + int32_t am_length; /* [in/out arg] length of value */ + int32_t am_flags; /* flags (bit-wise OR of #defines above) */ } attr_multiop_t; #define ATTR_MAX_MULTIOPS 128 /* max number ops in an oplist array */ +/* + * Valid values of am_opcode. + */ +#define ATTR_OP_GET 1 /* return the indicated attr's value */ +#define ATTR_OP_SET 2 /* set/create the indicated attr/value pair */ +#define ATTR_OP_REMOVE 3 /* remove the indicated attr */ + /* * Get the value of an attribute. * Valuelength must be set to the maximum size of the value buffer, it will @@ -181,19 +157,6 @@ extern int attr_remove (const char *__path, const char *__attrname, int __flags); extern int attr_removef (int __fd, const char *__attrname, int __flags); -/* - * List the names and sizes of the values of all the attributes of an object. - * "Cursor" must be allocated and zeroed before the first call, it is used - * to maintain context between system calls if all the attribute names won't - * fit into the buffer on the first system call. - * The return value is -1 on error (w/errno set appropriately), 0 on success. - */ -extern int attr_list (const char *__path, char *__buffer, - const int __buffersize, int __flags, - attrlist_cursor_t *__cursor); -extern int attr_listf (int __fd, char *__buffer, const int __buffersize, - int __flags, attrlist_cursor_t *__cursor); - /* * Operate on multiple attributes of the same object simultaneously. * diff --git a/include/xattr.h b/include/xattr.h new file mode 100644 index 0000000..c90be39 --- /dev/null +++ b/include/xattr.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + * USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef __XATTR_H__ +#define __XATTR_H__ + +#include + +#include +#ifndef ENOATTR +# define ENOATTR ENODATA /* fallback value until real errno exists */ +#endif + +#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ + + +__BEGIN_DECLS + +extern int setxattr (const char *__path, const char *__name, + void *__value, size_t __size, int __flags) __THROW; +extern int lsetxattr (const char *__path, const char *__name, + void *__value, size_t __size, int __flags) __THROW; +extern int fsetxattr (int __filedes, const char *__name, + void *__value, size_t __size, int __flags) __THROW; + +extern ssize_t getxattr (const char *__path, const char *__name, + void *__value, size_t __size) __THROW; +extern ssize_t lgetxattr (const char *__path, const char *__name, + void *__value, size_t __size) __THROW; +extern ssize_t fgetxattr (int __filedes, const char *__name, + void *__value, size_t __size) __THROW; + +extern ssize_t listxattr (const char *__path, char *__list, + size_t __size) __THROW; +extern ssize_t llistxattr (const char *__path, char *__list, + size_t __size) __THROW; +extern ssize_t flistxattr (int __filedes, char *__list, + size_t __size) __THROW; + +extern int removexattr (const char *__path, const char *__name) __THROW; +extern int lremovexattr (const char *__path, const char *__name) __THROW; +extern int fremovexattr (int __filedes, const char *__name) __THROW; + +__END_DECLS + +#endif /* __XATTR_H__ */ diff --git a/libattr/Makefile b/libattr/Makefile index b933e2f..f1b6e58 100644 --- a/libattr/Makefile +++ b/libattr/Makefile @@ -2,8 +2,8 @@ # Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify it -# under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. +# under the terms of version 2.1 of the GNU Lesser General Public License +# as published by the Free Software Foundation. # # This program is distributed in the hope that it would be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +16,10 @@ # any, provided herein do not apply to combinations of this program with # other software, or any other product whatsoever. # -# You should have received a copy of the GNU General Public License along -# with this program; if not, write the Free Software Foundation, Inc., 59 -# Temple Place - Suite 330, Boston MA 02111-1307, USA. +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, +# USA. # # Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, # Mountain View, CA 94043, or: @@ -34,11 +35,11 @@ TOPDIR = .. include $(TOPDIR)/include/builddefs LTLIBRARY = libattr.la -LT_CURRENT = 0 +LT_CURRENT = 1 LT_REVISION = 0 LT_AGE = 0 -CFILES = attr.c +CFILES = libattr.c syscalls.c default: $(LTLIBRARY) diff --git a/libattr/attr.c b/libattr/attr.c deleted file mode 100644 index f076b67..0000000 --- a/libattr/attr.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* Experimental system call interface for Linux */ -static int attrctl(attr_obj_t, int, attr_op_t *, int); - -/* Other local function prototypes */ -static int _attr_get(attr_obj_t, int, const char *, char *, int *, int); -static int _attr_set(attr_obj_t, int, const char *, const char *, const int, int); -static int _attr_remove(attr_obj_t, int, const char *, int); -static int _attr_listf(attr_obj_t, int, char *, const int, int, - attrlist_cursor_t *); -static int _attr_multif(attr_obj_t, int, attr_multiop_t *, int, int); - - -/* - * Get the value of an attribute. - */ -int -attr_get(const char *path, const char *attrname, char *attrvalue, - int *valuelength, int flags ) -{ - attr_obj_t obj; - int follow; - obj.path = (char *) path; - follow = (flags & ATTR_DONTFOLLOW) ? ATTR_TYPE_LPATH : ATTR_TYPE_PATH; - return _attr_get(obj, follow, attrname, attrvalue, valuelength, flags); -} - -int -attr_getf(int fd, const char *attrname, char *attrvalue, - int *valuelength, int flags ) -{ - attr_obj_t obj; - obj.fd = fd; - return _attr_get(obj, ATTR_TYPE_FD, attrname, attrvalue, - valuelength, flags); -} - -static int -_attr_get(attr_obj_t obj, int type, const char *attrname, char *attrvalue, - int *valuelength, int flags) -{ - attr_op_t op; - memset(&op, 0, sizeof(attr_op_t)); - op.opcode = ATTR_OP_GET; - op.name = (char *) attrname; - op.value = (char *) attrvalue; /* buffer to fill */ - op.length = *valuelength; /* buffer size */ - op.flags = flags; - - if (attrctl(obj, type, &op, 1) < 0) - return -1; - errno = op.error; - *valuelength = op.length; - return (errno ? -1 : 0); -} - - -/* - * Set the value of an attribute, creating the attribute if necessary. - */ -int -attr_set(const char *path, const char *attrname, const char *attrvalue, - const int valuelength, int flags) -{ - attr_obj_t obj; - int follow; - obj.path = (char *) path; - follow = (flags & ATTR_DONTFOLLOW) ? ATTR_TYPE_LPATH : ATTR_TYPE_PATH; - return _attr_set(obj, follow, attrname, attrvalue, valuelength, flags); -} - -int -attr_setf(int fd, const char *attrname, - const char *attrvalue, const int valuelength, int flags) -{ - attr_obj_t obj; - obj.fd = fd; - return _attr_set(obj, ATTR_TYPE_FD, attrname, attrvalue, - valuelength, flags); -} - -static int -_attr_set(attr_obj_t obj, int type, const char *attrname, - const char *attrvalue, const int valuelength, int flags) -{ - attr_op_t op; - memset(&op, 0, sizeof(attr_op_t)); - op.opcode = ATTR_OP_SET; - op.name = (char *) attrname; - op.value = (char *) attrvalue; - op.length = valuelength; - op.flags = flags; - - if (attrctl(obj, type, &op, 1) < 0) - return -1; - errno = op.error; - return (errno ? -1 : 0); -} - - -/* - * Remove an attribute. - */ -int -attr_remove(const char *path, const char *attrname, int flags) -{ - attr_obj_t obj; - int follow; - obj.path = (char *) path; - follow = (flags & ATTR_DONTFOLLOW) ? ATTR_TYPE_LPATH : ATTR_TYPE_PATH; - return _attr_remove(obj, follow, attrname, flags); -} - -int -attr_removef(int fd, const char *attrname, int flags) -{ - attr_obj_t obj; - obj.fd = fd; - return _attr_remove(obj, ATTR_TYPE_FD, attrname, flags); -} - -static int -_attr_remove(attr_obj_t obj, int type, const char *attrname, int flags) -{ - attr_op_t op; - memset(&op, 0, sizeof(attr_op_t)); - op.opcode = ATTR_OP_REMOVE; - op.name = (char *) attrname; - op.flags = flags; - - if (attrctl(obj, type, &op, 1) < 0) - return -1; - errno = op.error; - return (errno ? -1 : 0); -} - - -/* - * List the names and sizes of the values of all the attributes of an object. - */ -int -attr_list(const char *path, char *buffer, const int buffersize, - int flags, attrlist_cursor_t *cursor) -{ - attr_obj_t obj; - int follow; - obj.path = (char *) path; - follow = (flags & ATTR_DONTFOLLOW) ? ATTR_TYPE_LPATH : ATTR_TYPE_PATH; - return _attr_listf(obj, follow, buffer, buffersize, flags, cursor); -} - -int -attr_listf(int fd, char *buffer, const int buffersize, - int flags, attrlist_cursor_t *cursor) -{ - attr_obj_t obj; - obj.fd = fd; - return _attr_listf(obj, ATTR_TYPE_FD, buffer, buffersize, - flags, cursor); -} - -static int -_attr_listf(attr_obj_t obj, int type, char *buffer, const int buffersize, - int flags, attrlist_cursor_t *cursor) -{ - attr_op_t op; - memset(&op, 0, sizeof(attr_op_t)); - op.opcode = ATTR_OP_IRIX_LIST; - op.value = (char *) buffer; - op.length = buffersize; - op.flags = flags; - op.aux = cursor; - - if (attrctl(obj, type, &op, 1) < 0) - return -1; - errno = op.error; - return (errno ? -1 : 0); -} - -/* - * Operate on multiple attributes of the same object simultaneously - */ -int -attr_multi(const char *path, attr_multiop_t *multiops, int count, int flags) -{ - attr_obj_t obj; - int follow; - obj.path = (char *) path; - follow = (flags & ATTR_DONTFOLLOW) ? ATTR_TYPE_LPATH : ATTR_TYPE_PATH; - return _attr_multif(obj, follow, multiops, count, flags); -} - -int -attr_multif(int fd, attr_multiop_t *multiops, int count, int flags) -{ - attr_obj_t obj; - obj.fd = fd; - return _attr_multif(obj, ATTR_TYPE_FD, multiops, count, flags); -} - -static int -_attr_multif(attr_obj_t obj, int type, attr_multiop_t *multiops, int count, - int flags) -{ - int i; - int error = 0; - attr_op_t *ops; - - /* From the manpage: "attr_multi will fail if ... A bit other than */ - /* ATTR_DONTFOLLOW was set in the flag argument." flags must be */ - /* checked here as they are not passed into the kernel. */ - /* All other flags are checked in the kernel (linvfs_attrctl). */ - - if ((flags & ATTR_DONTFOLLOW) != flags) { - errno = EINVAL; - return -1; - } - - if (! (ops = malloc(count * sizeof (attr_op_t)))) { - errno = ENOMEM; - return -1; - } - - for (i = 0; i < count; i++) { - ops[i].opcode = multiops[i].am_opcode; - ops[i].name = multiops[i].am_attrname; - ops[i].value = multiops[i].am_attrvalue; - ops[i].length = multiops[i].am_length; - ops[i].flags = multiops[i].am_flags; - } - - if (attrctl(obj, type, ops, count) < 0) { - error = -1; - goto free_mem; - } - - /* copy return vals */ - for (i = 0; i < count; i++) { - multiops[i].am_error = ops[i].error; - if (ops[i].opcode == ATTR_OP_GET) - multiops[i].am_length = ops[i].length; - } - - free_mem: - free(ops); - return error; -} - - -/* - * attrctl(2) experimental system call function definition. - */ - -#if __i386__ -# define HAVE_ACL_SYSCALL 1 -# ifndef SYS__attrctl -# define SYS__attrctl 250 -# endif -#elif __ia64__ -# define HAVE_ACL_SYSCALL 1 -# ifndef SYS__attrctl -# define SYS__attrctl 1260 -# endif -#else -# define HAVE_ACL_SYSCALL 0 -#endif - -static int -attrctl(attr_obj_t obj, int type, attr_op_t *ops, int count) -{ -#if HAVE_ACL_SYSCALL - return syscall(SYS__attrctl, obj, type, ops, count); -#else - errno = ENOSYS; - return -1; -#endif -} diff --git a/libattr/libattr.c b/libattr/libattr.c new file mode 100644 index 0000000..e820a39 --- /dev/null +++ b/libattr/libattr.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + * USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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); + + if (len >= MAXNAMELEN) { + errno = EINVAL; + return -1; + } + if (irixflags & ATTR_ROOT) + strcpy(name, root_name); + else + strcpy(name, user_name); + strcat(name, irixname); + return 0; +} + +int +attr_get(const char *path, const char *attrname, char *attrvalue, + int *valuelength, int flags) +{ + int c; + char name[MAXNAMELEN+16]; + + if ((c = api_convert(name, attrname, flags)) < 0) + return c; + if (flags & ATTR_DONTFOLLOW) + c = lgetxattr(path, name, attrvalue, *valuelength); + else + c = getxattr(path, name, attrvalue, *valuelength); + if (c < 0) + return c; + *valuelength = c; + return 0; +} + +int +attr_getf(int fd, const char *attrname, char *attrvalue, + int *valuelength, int flags) +{ + int c; + char name[MAXNAMELEN+16]; + + if ((c = api_convert(name, attrname, flags)) < 0) + return c; + c = fgetxattr(fd, name, attrvalue, *valuelength); + if (c < 0) + return c; + *valuelength = c; + return 0; +} + +int +attr_set(const char *path, const char *attrname, const char *attrvalue, + const int valuelength, int flags) +{ + int c, lflags = 0; + char name[MAXNAMELEN+16]; + void *buffer = (void *)attrvalue; + + if (flags & ATTR_CREATE) + lflags = XATTR_CREATE; + else if (flags & ATTR_REPLACE) + lflags = XATTR_REPLACE; + + if ((c = api_convert(name, attrname, flags)) < 0) + return c; + if (flags & ATTR_DONTFOLLOW) + return lsetxattr(path, name, buffer, valuelength, lflags); + return setxattr(path, name, buffer, valuelength, lflags); +} + +int +attr_setf(int fd, const char *attrname, + const char *attrvalue, const int valuelength, int flags) +{ + int c, lflags = 0; + char name[MAXNAMELEN+16]; + void *buffer = (void *)attrvalue; + + if (flags & ATTR_CREATE) + lflags = XATTR_CREATE; + else if (flags & ATTR_REPLACE) + lflags = XATTR_REPLACE; + + if ((c = api_convert(name, attrname, flags)) < 0) + return c; + return fsetxattr(fd, name, buffer, valuelength, lflags); +} + +int +attr_remove(const char *path, const char *attrname, int flags) +{ + int c; + char name[MAXNAMELEN+16]; + + if ((c = api_convert(name, attrname, flags)) < 0) + return c; + if (flags & ATTR_DONTFOLLOW) + return lremovexattr(path, name); + return removexattr(path, name); +} + +int +attr_removef(int fd, const char *attrname, int flags) +{ + int c; + char name[MAXNAMELEN+16]; + + if ((c = api_convert(name, attrname, flags)) < 0) + return c; + return fremovexattr(fd, name); +} + + +/* + * Helper routines for the attr_multi functions. In IRIX, the + * multi routines are a single syscall - in Linux, we break em + * apart in userspace and make individual syscalls for each. + */ + +static int +attr_single(const char *path, attr_multiop_t *op, int flags) +{ + int r = -1; + + errno = -EINVAL; + flags |= op->am_flags; + if (op->am_opcode & ATTR_OP_GET) + r = attr_get(path, op->am_attrname, op->am_attrvalue, + &op->am_length, flags); + else if (op->am_opcode & ATTR_OP_SET) + r = attr_set(path, op->am_attrname, op->am_attrvalue, + op->am_length, flags); + else if (op->am_opcode & ATTR_OP_REMOVE) + r = attr_remove(path, op->am_attrname, flags); + return r; +} + +static int +attr_singlef(const int fd, attr_multiop_t *op, int flags) +{ + int r = -1; + + errno = -EINVAL; + flags |= op->am_flags; + if (op->am_opcode & ATTR_OP_GET) + r = attr_getf(fd, op->am_attrname, op->am_attrvalue, + &op->am_length, flags); + else if (op->am_opcode & ATTR_OP_SET) + r = attr_setf(fd, op->am_attrname, op->am_attrvalue, + op->am_length, flags); + else if (op->am_opcode & ATTR_OP_REMOVE) + r = attr_removef(fd, op->am_attrname, flags); + return r; +} + +/* + * Operate on multiple attributes of the same object simultaneously + * + * From the manpage: "attr_multi will fail if ... a bit other than + * ATTR_DONTFOLLOW was set in the flag argument." flags must be + * checked here as they are not passed into the kernel. + */ +int +attr_multi(const char *path, attr_multiop_t *multiops, int count, int flags) +{ + int i, tmp, r = -1; + + errno = EINVAL; + if ((flags & ATTR_DONTFOLLOW) != flags) + return r; + + r = errno = 0; + for (i = 0; i < count; i++) { + tmp = attr_single(path, &multiops[i], flags); + if (tmp) r = tmp; + } + return r; +} + +int +attr_multif(int fd, attr_multiop_t *multiops, int count, int flags) +{ + int i, tmp, r = -1; + + errno = EINVAL; + if ((flags & ATTR_DONTFOLLOW) != flags) + return r; + + r = errno = 0; + for (i = 0; i < count; i++) { + tmp = attr_singlef(fd, &multiops[i], flags); + if (tmp) r = tmp; + } + return r; +} diff --git a/libattr/syscalls.c b/libattr/syscalls.c new file mode 100644 index 0000000..f167540 --- /dev/null +++ b/libattr/syscalls.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, + * USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ + +#include + +#if defined(__i386__) +# define HAVE_XATTR_SYSCALLS 1 +# define __NR_setxattr 226 +# define __NR_lsetxattr 227 +# define __NR_fsetxattr 228 +# define __NR_getxattr 229 +# define __NR_lgetxattr 230 +# define __NR_fgetxattr 231 +# define __NR_listxattr 232 +# define __NR_llistxattr 233 +# define __NR_flistxattr 234 +# define __NR_removexattr 235 +# define __NR_lremovexattr 236 +# define __NR_fremovexattr 237 +#elif defined (__sparc__) +# define HAVE_XATTR_SYSCALLS 1 +# define __NR_setxattr 169 +# define __NR_lsetxattr 170 +# define __NR_fsetxattr 171 +# define __NR_getxattr 172 +# define __NR_lgetxattr 173 +# define __NR_fgetxattr 177 +# define __NR_listxattr 178 +# define __NR_llistxattr 179 +# define __NR_flistxattr 180 +# define __NR_removexattr 181 +# define __NR_lremovexattr 182 +# define __NR_fremovexattr 183 +#elif defined (__ia64__) +# define HAVE_XATTR_SYSCALLS 1 +# define __NR_setxattr 1217 +# define __NR_lsetxattr 1218 +# define __NR_fsetxattr 1219 +# define __NR_getxattr 1220 +# define __NR_lgetxattr 1221 +# define __NR_fgetxattr 1222 +# define __NR_listxattr 1223 +# define __NR_llistxattr 1224 +# define __NR_flistxattr 1225 +# define __NR_removexattr 1226 +# define __NR_lremovexattr 1227 +# define __NR_fremovexattr 1228 +#elif defined (__powerpc__) +# define HAVE_XATTR_SYSCALLS 1 +# define __NR_setxattr 208 +# define __NR_lsetxattr 209 +# define __NR_fsetxattr 210 +# define __NR_getxattr 211 +# define __NR_lgetxattr 212 +# define __NR_fgetxattr 213 +# define __NR_listxattr 214 +# define __NR_llistxattr 215 +# define __NR_flistxattr 216 +# define __NR_removexattr 217 +# define __NR_lremovexattr 218 +# define __NR_fremovexattr 219 +#else +# warning "Extended attribute syscalls undefined for this architecture" +# define HAVE_XATTR_SYSCALLS 0 +#endif + +#if HAVE_XATTR_SYSCALLS +# define SYSCALL(args...) syscall(args) +#else +# define SYSCALL(args...) ( errno = ENOSYS, -1 ) +#endif + +int setxattr (const char *path, const char *name, + void *value, size_t size, int flags) +{ + return SYSCALL(__NR_setxattr, path, name, value, size, flags); +} + +int lsetxattr (const char *path, const char *name, + void *value, size_t size, int flags) +{ + return SYSCALL(__NR_lsetxattr, path, name, value, size, flags); +} + +int fsetxattr (int filedes, const char *name, + void *value, size_t size, int flags) +{ + return SYSCALL(__NR_fsetxattr, filedes, name, value, size, flags); +} + +ssize_t getxattr (const char *path, const char *name, + void *value, size_t size) +{ + return SYSCALL(__NR_getxattr, path, name, value, size); +} + +ssize_t lgetxattr (const char *path, const char *name, + void *value, size_t size) +{ + return SYSCALL(__NR_lgetxattr, path, name, value, size); +} + +ssize_t fgetxattr (int filedes, const char *name, + void *value, size_t size) +{ + return SYSCALL(__NR_fgetxattr, filedes, name, value, size); +} + +ssize_t listxattr (const char *path, char *list, size_t size) +{ + return SYSCALL(__NR_listxattr, path, list, size); +} + +ssize_t llistxattr (const char *path, char *list, size_t size) +{ + return SYSCALL(__NR_llistxattr, path, list, size); +} + +ssize_t flistxattr (int filedes, char *list, size_t size) +{ + return SYSCALL(__NR_flistxattr, filedes, list, size); +} + +int removexattr (const char *path, const char *name) +{ + return SYSCALL(__NR_removexattr, path, name); +} + +int lremovexattr (const char *path, const char *name) +{ + return SYSCALL(__NR_lremovexattr, path, name); +} + +int fremovexattr (int filedes, const char *name) +{ + return SYSCALL(__NR_fremovexattr, filedes, name); +} diff --git a/man/Makefile b/man/Makefile index 057c462..35492a3 100644 --- a/man/Makefile +++ b/man/Makefile @@ -33,7 +33,7 @@ TOPDIR = .. include $(TOPDIR)/include/builddefs -SUBDIRS = man1 man2 man3 +SUBDIRS = man1 man2 man3 man5 default install install-dev : $(SUBDIRS) $(SUBDIRS_MAKERULE) diff --git a/man/man1/attr.1 b/man/man1/attr.1 index bf6cbbe..9c1d905 100644 --- a/man/man1/attr.1 +++ b/man/man1/attr.1 @@ -1,6 +1,6 @@ -.TH attr 1 +.TH ATTR 1 "Extended Attributes" "Dec 2001" "XFS Compatibility API" .SH NAME -attr \- manipulate Extended Attributes on filesystem objects +attr \- extended attributes on XFS filesystem objects .SH SYNOPSIS .nf \f3attr\f1 [ \f3\-LRq\f1 ] \f3\-s attrname\f1 [ \f3\-V attrvalue\f1 ] \c @@ -10,33 +10,40 @@ attr \- manipulate Extended Attributes on filesystem objects .sp .8v \f3attr\f1 [ \f3\-LRq\f1 ] \f3\-r attrname pathname\f1 .sp .8v -\f3attr\f1 [ \f3\-LRq\f1 ] \f3\-l pathname\f1 -.sp .8v .fi .SH OVERVIEW -Extended Attributes implement the ability for a user to attach -name/value pairs to objects within the filesystem. +Extended attributes implement the ability for a user to attach +name:value pairs to objects within the XFS filesystem. .P They could be used to store meta-information about the file. For example "character-set=kanji" could tell a document browser to use the Kanji character set when displaying that document and "thumbnail=..." could provide a reduced resolution overview of a high resolution graphic image. +.PP +This document describes the +.I attr +command, which is mostly compatible with the IRIX command of the same name. +It is thus aimed specifically at users of the XFS filesystem - for +filesystem independent extended attribute manipulation, consult the +.IR getfattr (1) +and +.IR setfattr (1) +documentation. .P -The +In the XFS filesystem, the .I names can be up to 256 bytes in length, terminated by the first 0 byte. The intent is that they be printable ASCII (or other character set) names for the attribute. -.P The .I values -can be up to 256KB of arbitrary binary data. +can be up to 64KB of arbitrary binary data. .P -Attributes can be attached to all types of inodes: +Attributes can be attached to all types of XFS inodes: regular files, directories, symbolic links, device nodes, etc. .P -There are 2 disjoint attribute name spaces associated with every +XFS uses 2 disjoint attribute name spaces associated with every filesystem object. They are the .B root @@ -58,7 +65,7 @@ the value of attributes on any particular file. .SH DESCRIPTION The .I attr -utility allows the manipulation of Extended Attributes associated with +utility allows the manipulation of extended attributes associated with filesystem objects from within shell scripts. .PP There are four main operations that @@ -77,18 +84,6 @@ With the flag, \f4stdout\fP will be exactly and only the value of the attribute, suitable for storage directly into a file or processing via a piped command. .TP -.B LIST -The -.B \-l -option tells -.I attr -to list the names of all the attributes that are associated with the object, -and the number of bytes in the value of each of those attributes. -With the -.B \-q -flag, \f4stdout\fP will be a simple list of only the attribute names, -one per line, suitable for input into a script. -.TP .B REMOVE The .B \-r attrname @@ -148,17 +143,21 @@ The standard file interchange/archive programs .IR tar (1), and .IR cpio (1) -will not archive or restore Extended Attributes, +will not archive or restore extended attributes, while the .IR xfsdump (8) program will. +.SH "CAVEATS" +The list option present in the IRIX version of this command is not supported. +.I getfattr +provides a mechanism to retrieve all of the attribute names. .SH "SEE ALSO" -attr_get(2), attr_getf(2), -attr_list(2), attr_listf(2), -attr_multi(2), attr_multif(2), -attr_remove(2), attr_removef(2), -attr_set(2), attr_setf(2), +getfattr(1), +setfattr(1), +attr_get(3), +attr_set(3), +attr_multi(3), +attr_remove(3), +attr(5), +and xfsdump(8). -.SH BUGS -The extended attributes system call used by this program is -experimental and is currently only supported by the XFS filesystem. diff --git a/man/man1/getfattr.1 b/man/man1/getfattr.1 new file mode 100644 index 0000000..7b3ea66 --- /dev/null +++ b/man/man1/getfattr.1 @@ -0,0 +1,129 @@ +.TH GETFATTR 1 "Extended Attributes" "Dec 2001" "File Utilities" +.SH NAME +getfattr, aget \- get extended attributes of filesystem objects +.SH SYNOPSIS +.nf +\f3getfattr\f1 [\f3\-lvR5LP\f1] \f3\-n name\f1 [\f3\-e en\f1] \c +\f3pathname\f1... +\f3getfattr\f1 [\f3\-lvR5LP\f1] \f3\-d\f1 [\f3\-e en\f1] \c +[\f3\-s\f1 | \f3\-r regex\f1] \f3pathname\f1... +\f3getfattr\f1 [\f3\-Vh\f1] +.fi +.SH DESCRIPTION +For each file, +.B getfattr +displays the file name, +and the set of extended attribute names (and optionally values) which +are associated with that file. +.PP +.B aget +is exactly the same as +.BR getfattr , +and is installed for compatibility purposes. +.PP +The output format of +.B "getfattr \-ds" +is as follows: +.fam C +.RS +.nf + 1: # file: somedir/ + 2: user.name0="value0" + 3: system.name0="value1" + 4: user.name1="value2" + 5: ... +.fi +.RE +.fam T +.PP +Line 1 identifies the file name for which the +following lines are being reported. +The remaining lines (lines 2 to 4 above) show the +.I name +and +.I value +pairs associated with the specified file. +.SS OPTIONS +.TP 4 +.I \-n name +Dump the value of the named extended attribute extended attribute. +.TP +.I \-a +Absolute names \- suppress the stripping of leading '/' from an absolute +.IR pathname . +.TP +.I \-d +Dump the values of all extended attributes associated with +.IR pathname . +.TP +.I \-e en +Encode values after retrieving them. +Valid values of +.I en +are "text", "hex", and "base64". +.TP +.I \-l +Do not follow symlinks - if +.I pathname +is a symbolic link, it is not followed, but is instead itself the +inode being examined. +.TP +.I \-r +.I regex +is a regular expression pattern to apply to the set of extended +attribute names being returned. +It defaults to "^user\\." if no +.I \-r +is specified, which causes +.B getfattr +to operate on only extended attributes from the user namespace. +.TP +.I \-s +Dump out both the "user" and "system" namespaces. +Refer to +.BR attr (5) +for a more detailed discussion on namespaces. +This option is useful for backing up extended attributes in a filesystem +independent manner. +It is implemented using a regular expression ("^user\\.|^system\\.") +and so cannot be used in conjunction with the +.I \-r +option described earlier. +.TP +.I \-v +Dump out the extended attribute value(s) only. +.TP +.I \-R +Recurse into subdirectories, dumping extended attributes for each file +encountered (breadth first). +.TP +.I \-5 +Same as \-R, except done in post-order (depth first). +.TP +.I \-L +Refines the \-R or \-5 option - "logical walk" (do follow symbolic links). +.TP +.I \-P +Refines the \-R or \-5 option - "physical walk" (do not follow symbolic links). +.TP +.I \-V +Print the version of +.B getfattr +and exit. +.TP +.I \-h +Print help explaining the command line options. +.TP +.I \-\- +End of command line options. +All remaining parameters are interpreted as file names, even if they +start with a dash character. +.SH AUTHOR +Andreas Gruenbacher, +.RI < a.gruenbacher@computer.org > +and the SGI XFS development team, +.RI < linux-xfs@oss.sgi.com >. +.P +Please send your bug reports or comments to these addresses. +.SH "SEE ALSO" +setfattr(1), and attr(5). diff --git a/man/man1/setfattr.1 b/man/man1/setfattr.1 new file mode 100644 index 0000000..6b71d2a --- /dev/null +++ b/man/man1/setfattr.1 @@ -0,0 +1,71 @@ +.TH SETFATTR 1 "Extended Attributes" "Dec 2001" "File Utilities" +.SH NAME +setfattr, aset \- set extended attributes of filesystem objects +.SH SYNOPSIS +.nf +\f3setfattr\f1 [\f3\-l\f1] \f3\-n name\f1 [\f3\-v value\f1] \f3pathname\f1... +\f3setfattr\f1 [\f3\-l\f1] \f3\-x name\f1 \f3pathname\f1... +\f3setfattr\f1 [\f3\-l\f1] \f3\-B file\f1 +\f3setfattr\f1 [\f3\-Vh\f1] +.fi +.SH DESCRIPTION +The +.B setfattr +command is used to associate a new +.I value +with an extended attribute +.IR name +for each specified file. +.PP +.B aset +is exactly the same as +.BR setfattr , +and is installed for compatibility purposes. +.SS OPTIONS +.TP 4 +.I \-n name +Set the value of the named extended attribute extended attribute. +.TP +.I \-l +Do not follow symlinks - if +.I pathname +is a symbolic link, it is not followed, but is instead itself the +inode being modified. +.TP +.I \-x +Remove the named extended attribute entirely. +.TP +.I \-v +Specifies the new value for the named extended attribute. +.TP +.I \-B +Restores extended attributes using values from the specified file. +The file must be in the format generated by the +.B getfattr +command (\-sdlR options). +The file name +.I \- +may be used in conjunction with this option, to specify the +standard input stream to be used rather than a named file. +.TP +.I \-V +Print the version of +.B setfattr +and exit. +.TP +.I \-h +Print help explaining the command line options. +.TP +.I \-\- +End of command line options. +All remaining parameters are interpreted as file names, even if they +start with a dash character. +.SH AUTHOR +Andreas Gruenbacher, +.RI < a.gruenbacher@computer.org > +and the SGI XFS development team, +.RI < linux-xfs@oss.sgi.com >. +.P +Please send your bug reports or comments to these addresses. +.SH "SEE ALSO" +getfattr(1), and attr(5). diff --git a/man/man2/attrctl.2 b/man/man2/attrctl.2 deleted file mode 100644 index b49b0c7..0000000 --- a/man/man2/attrctl.2 +++ /dev/null @@ -1,350 +0,0 @@ -.TH ATTRCTL 2 -.SH NAME -attrctl \- manipulate (extended) attributes of system objects -.SH C SYNOPSIS -.PP -.sp -.nf -.B #include -.sp -.B "int attrctl (attr_obj_t obj, int type, attr_op_t *ops," -.B " int count);" -.Op -.SH OVERVIEW -The -.I attrctl -system call allows a user to attach name/value pairs to system -objects - typically filesystem objects (inodes). -.P -This is a first draft proposal which may well *not* be the final -interface - it has been implemented to address some immediate -issues with the current XFS implementation and is the first attempt -at an interface which could allow both XFS and EXT2 extended attributes -implementations to coexist. -.P -Extended attributes can be used to store meta-information about a -file, for example "character-set=kanji" could tell a document browser -to use the Kanji character set when displaying that document -and "thumbnail=..." could provide a reduced resolution overview of a -high resolution graphic image. -.P -The -.B names -can be up to MAXNAMELEN bytes in length, terminated by the first \e0 byte. -The intent is that they be printable ASCII (or other character set) -names for the attribute. -.P -The -.B values -can be up to ATTR_MAX_VALUELEN (currently 64KB) of arbitrary binary data. -.P -Attributes can be attached to all types of inodes: -regular files, directories, symbolic links, device nodes, etc. -.P -There are 2 disjoint attribute name spaces associated with every -filesystem object. -They are the -.B root -and -.B user -address spaces. -The -.B root -address space is accessible only to the super-user, -and then only by specifying a flag to the operation request. -Non-root users will not see or be able to modify attributes in the -.B root -address space. -The -.B user -address space is protected by the normal file permissions mechanism, -so the owner of the file can decide who is able to see and/or modify -the value of attributes on any particular file. The attribute get/list -operations require read permission, and attribute set/remove require -write permission. -.P -Attributes are currently supported only in the XFS and EXT2 filesystem -types. However, this system call has been designed to be generic -and extensible, such that other filesystems should be able to make -use of it. -.SH DESCRIPTION -The -.I attrctl -system call provides a way to access arbitrary extended attributes. -.P -.I Obj\^ -indicates the system object whose extended attributes are to be -manipulated. -The contents of the \f4attr_obj_t\f1 union are as follows: -.P -typedef union { -.RS 3 -.nf -.ft 4 -.ta 9n 22n -char *path; -int fd; -pid_t pid; -.ft 1 -.fi -.RE -} attr_obj_t; -.PP -.I type\^ -identifies the type of -.I obj\^ -- currently only file descriptors and path names are implemented -(ATTR_TYPE_NAME and ATTR_TYPE_FD), but processes have also been -proposed (ATTR_TYPE_PID). -.P -.I Ops\^ -refers to an array of one or more input/output structures containing -control information related to attribute operations and those -operations' results. -.PP -The -.I count -argument indicates the number of structures in the -.I ops -array. -.PP -.Op c p a -The contents of an \f4attr_op_t\fP structure are as follows: -.P -typedef struct { -.RS 3 -.nf -.ft 4 -.ta 9n 22n -int opcode; /* which operation to perform (see below) */ -int error; /* [out arg] result of this sub-op (an errno) */ -char *name; /* attribute name to work with */ -char *value; /* [in/out arg] attribute value (raw bytes) */ -int length; /* [in/out arg] length of value */ -int flags; /* flags (bit-wise OR of #defines below) */ -void *aux; /* optional command-specific data */ -.ft 1 -.fi -.RE -} attr_op_t; -.PP -The -.I opcode -field defines how the remaining fields are to be interpreted -and can take on one of the following -.B ATTR_OP -values. -.PP -.B ATTR_OP_GET -returns the -.I value -associated with attribute -.IR name . -The size of the user buffer is passed in as -.IR length , -and the size of the attribute value is returned in the same field. -Valid flags are ATTR_ROOT and ATTR_DONTFOLLOW. -.P -.B ATTR_OP_SET -sets (possibly creating a new attribute) the value of the -attribute specified by -.I name -to -.IR value . -The -.I length -parameter specifies the size of the new value, and the valid -.I flags -are ATTR_ROOT, ATTR_DONTFOLLOW, ATTR_CREATE, and ATTR_REPLACE. -.P -.B ATTR_OP_REMOVE -provides a way to remove previously created attributes. -If the attribute -.I name -exists, the attribute name and its associated value will be -removed. -Valid -.I flags -are ATTR_ROOT and ATTR_DONTFOLLOW. -.P -.B ATTR_OP_LIST -is used to list the existing attributes associated with an object. -The -.I name -field is ignored \- -.I value -and -.I size -specify the buffer to be filled with at least a portion of the -attributes associated with the given object. -An -.B attrlist_t -structure will be written into the -.I value -buffer, containing a list of the attributes associated with the -object, up to a maximum of -.I size -bytes. -The -.B attrlist_t -structure contains the following elements: -.P -typedef struct { -.RS 3 -.nf -.ft 4 -.ta 9n 22n -__s32 count; /* number of entries in attribute list */ -__s32 more; /* [in/out arg] more attrs (call again) */ -__s32 offset[1]; /* byte offsets of attrs [var-sized] */ -.ft 1 -.fi -.RE -} attrlist_t; -.PP -The -.I count -field shows the number of attributes represented in this buffer, -which is also the number of elements in the -.I offset -array. -The -.I more -field will be non-zero if another -.B ATTR_OP_LIST -call would retrieve more attributes. -The -.I offset -array contains the byte offset within the -.I value -buffer of the structure describing each of the attributes, an -.B attrlist_ent_t -structure. -The -.B "ATTR_ENTRY(buffer, index)" -macro will help with decoding the list. -It takes a pointer to the -.I value -and an index into the -.I offset -array, and returns a pointer to the corresponding -.I attrlist_ent_t -structure. -.P -typedef struct { -.RS 3 -.nf -.ft 4 -.ta 9n 22n -__u32 valuelen; /* number of bytes in attribute value */ -char name[]; /* attribute name (NULL terminated) */ -.ft 1 -.fi -.RE -} attrlist_ent_t; -.PP -The -.I valuelen -field shows the size in bytes of the value associated -with the attribute whose name is stored in the -.I name -field. -.P -Valid -.I flags -for the -.B ATTR_LIST -command are ATTR_ROOT and ATTR_DONTFOLLOW. -The -.I aux -pointer is used to reference an opaque cursor (type -.BR attrlist_cursor_t ), -which the kernel uses to track the calling process's position -in the attribute list. -The only valid operations on this cursor are to pass it into the -operation or to zero it out (it should be zeroed before the -first -.B attrctl -call. -Note that multi-threaded applications may keep more than one -cursor in order to serve multiple contexts (i.e. the -.B ATTR_LIST -operation is "thread-safe"). -.P -All operations will set -.I error -to an error code if the operation fails, otherwise it will -contain zero indicating success. The set of valid -.I flags -field values (combined using bitwise OR) is as follows: -.TP -.SM -\%ATTR_ROOT -Look for attribute -.I name -in the -.B root -address space, not in the -.B user -address space (limited to use by the super-user only). -.TP -.SM -\%ATTR_DONTFOLLOW -Do not follow symbolic links when resolving a -.I path -on an -.I attr_set -function call. -The default is to follow symbolic links. -.TP -.SM -\%ATTR_CREATE -Set -.I error -field (EEXIST) if an attribute of the given name already -exists on the indicated object. -This flag is used to implement a pure create operation, -without this flag -.B ATTR_SET -will create the attribute if it does not already exist. -.TP -.SM -\%ATTR_REPLACE -Set -.I error -field (ENOENT) if an attribute of the given name -does not already exist on the indicated object, -otherwise replace the existing attribute\'s value with the -given value. -This flag is used to implement a pure replacement operation, -without this flag -.B ATTR_SET -will create the attribute if it does not already exist. -.PP -The -.I error -field will be set (EINVAL) if both ATTR_CREATE and ATTR_REPLACE -are requested in the same operation. -.SH DIAGNOSTICS -.I attrctl -will return 0 on success, and an error code on any failure. -Since the -.I attrctl -system call is arbitrarily extensible, and the intention is that it -will always be used through an overlying API, refer to the manual -pages for overlying API calls for specific error code values. -.P -.I attrctl -will always attempt to perform all operations, and a set of -operations are not atomic (failure of one operation does not -necessarily cause prior successful operations to be undone). -.SH "SEE ALSO" -attr(1), -.br -attr_list(3), attr_listf(3), -.br -attr_multi(3), attr_multif(3), -.br -attr_remove(3), attr_removef(3), -.br -attr_set(3), attr_setf(3). diff --git a/man/man2/getxattr.2 b/man/man2/getxattr.2 new file mode 100644 index 0000000..813873e --- /dev/null +++ b/man/man2/getxattr.2 @@ -0,0 +1,123 @@ +.\" +.\" Extended attributes system calls manual pages +.\" +.\" (C) Andreas Gruenbacher, February 2001 +.\" (C) Silicon Graphics Inc, September 2001 +.\" +.TH GETXATTR 2 "Extended Attributes" "Dec 2001" "System calls" +.SH NAME +getxattr, lgetxattr, fgetxattr \- retrieve an extended attribute value +.SH SYNOPSIS +.fam C +.nf +.B #include +.sp +.BI "ssize_t getxattr (const char\ *" path ", const char\ *" name ", +.BI "\t\t\t\t void\ *" value ", size_t " size ); +.BI "ssize_t lgetxattr (const char\ *" path ", const char\ *" name ", +.BI "\t\t\t\t void\ *" value ", size_t " size ); +.BI "ssize_t fgetxattr (int " filedes ", const char\ *" name ", +.BI "\t\t\t\t void\ *" value ", size_t " size ); +.fi +.fam T +.SH DESCRIPTION +Extended attributes are +.IR name :\c +.I value +pairs associated with inodes (files, directories, symlinks, etc). +They are extensions to the normal attributes which are associated +with all inodes in the system (i.e. the +.BR stat (2) +data). +A complete overview of extended attributes concepts can be found in +.BR attr (5). +.PP +.B getxattr +retrieves the +.I value +of the extended attribute identified by +.I name +and associated with the given +.I path +in the filesystem. +The length of the attribute +.I value +is returned. +.PP +.B lgetxattr +is identical to +.BR getxattr , +except in the case of a symbolic link, where the link itself is +interrogated, not the file that it refers to. +.PP +.B fgetxattr +is identical to +.BR getxattr , +only the open file pointed to by +.I filedes +(as returned by +.BR open (2)) +is interrogated in place of +.IR path . +.PP +An extended attribute +.I name +is a simple NULL-terminated string. +The name includes a namespace prefix \- there may be several, disjoint +namespaces associated with an individual inode. +The value of an extended attribute is a chunk of arbitrary textual or +binary data of specified length. +.PP +An empty buffer of +.I size +zero can be passed into these calls to return the current size of the +named extended attribute, which can be used to estimate the size of a +buffer which is sufficiently large to hold the value associated with +the extended attribute. +.PP +The interface is designed to allow guessing of initial buffer +sizes, and to enlarge buffers when the return value indicates +that the buffer provided was too small. +.SH RETURN VALUE +On success, a positive number is returned indicating the size of the +extended attribute value. +On failure, \-1 is returned and +.I errno +is set appropriately. +.PP +If the named attribute does not exist, or the process has no access to +this attribute, +.I errno +is set to ENOATTR. +.PP +If the +.I size +of the +.I value +buffer is too small to hold the result, +.I errno +is set to ERANGE. +.PP +If extended attributes are not supported by the filesystem, or are disabled, +.I errno +is set to ENOTSUP. +.PP +The errors documented for the +.BR stat (2) +system call are also applicable here. +.SH AUTHORS +Andreas Gruenbacher, +.RI < a.gruenbacher@computer.org > +and the SGI XFS development team, +.RI < linux-xfs@oss.sgi.com >. +Please send any bug reports or comments to these addresses. +.SH SEE ALSO +.BR getfattr (1), +.BR setfattr (1), +.BR open (2), +.BR stat (2), +.BR setxattr (2), +.BR listxattr (2), +.BR removexattr (2), +and +.BR attr (5). diff --git a/man/man2/listxattr.2 b/man/man2/listxattr.2 new file mode 100644 index 0000000..b1bf578 --- /dev/null +++ b/man/man2/listxattr.2 @@ -0,0 +1,137 @@ +.\" +.\" Extended attributes system calls manual pages +.\" +.\" (C) Andreas Gruenbacher, February 2001 +.\" (C) Silicon Graphics Inc, September 2001 +.\" +.TH LISTXATTR 2 "Extended Attributes" "Dec 2001" "System calls" +.SH NAME +listxattr, llistxattr, flistxattr \- list extended attribute names +.SH SYNOPSIS +.fam C +.nf +.B #include +.sp +.BI "ssize_t listxattr (const char\ *" path ", +.BI "\t\t\t\t char\ *" list ", size_t " size ); +.BI "ssize_t llistxattr (const char\ *" path ", +.BI "\t\t\t\t char\ *" list ", size_t " size ); +.BI "ssize_t flistxattr (int " filedes ", +.BI "\t\t\t\t char\ *" list ", size_t " size ); +.fi +.fam T +.SH DESCRIPTION +Extended attributes are name:value +pairs associated with inodes (files, directories, symlinks, etc). +They are extensions to the normal attributes which are associated +with all inodes in the system (i.e. the +.BR stat (2) +data). +A complete overview of extended attributes concepts can be found in +.BR attr (5). +.PP +.B listxattr +retrieves the +.I list +of extended attribute names associated with the given +.I path +in the filesystem. +The list is the set of (NULL-terminated) names, one after the other. +The length of the attribute name +.I list +is returned. +.PP +.B llistxattr +is identical to +.BR listxattr , +except in the case of a symbolic link, where the list of names of +extended attributes associated with the link itself is retrieved, +not the file that it refers to. +.PP +.B flistxattr +is identical to +.BR listxattr , +only the open file pointed to by +.I filedes +(as returned by +.BR open (2)) +is interrogated in place of +.IR path . +.PP +A single extended attribute +.I name +is a simple NULL-terminated string. +The name includes a namespace prefix \- there may be several, disjoint +namespaces associated with an individual inode. +.PP +An empty buffer of +.I size +zero can be passed into these calls to return the current size of the +list of extended attribute names, which can be used to estimate the +size of a buffer which is sufficiently large to hold the list of names. +.PP +The interface is designed to allow guessing of initial buffer +sizes, and to enlarge buffers when the return value indicates +that the buffer provided was too small. +.SH EXAMPLES +The +.I list +of names is returned as an unordered array of NULL-terminated character +strings (attribute names are separated by NULL characters), like this: +.fam C +.RS +.nf +user.name1\\0system.name1\\0user.name2\\0 +.fi +.RE +.fam T +.P +Filesystems like ext2, ext3 and XFS which implement POSIX ACLs using +extended attributes, might return a +.I list +like this: +.fam C +.RS +.nf +system.posix_acl_access\\0system.posix_acl_default\\0 +.fi +.RE +.fam T +.SH RETURN VALUE +On success, a positive number is returned indicating the size of the +extended attribute name list. +On failure, \-1 is returned and +.I errno +is set appropriately. +.PP +If the +.I size +of the +.I list +buffer is too small to hold the result, +.I errno +is set to ERANGE. +.PP +If extended attributes are not supported by the filesystem, or are disabled, +.I errno +is set to ENOTSUP. +.PP +The errors documented for the +.BR stat (2) +system call are also applicable here. +.SH AUTHORS +Andreas Gruenbacher, +.RI < a.gruenbacher@computer.org > +and the SGI XFS development team, +.RI < linux-xfs@oss.sgi.com >. +Please send any bug reports or comments to these addresses. +.SH SEE ALSO +.BR getfattr (1), +.BR setfattr (1), +.BR open (2), +.BR stat (2), +.BR getxattr (2), +.BR setxattr (2), +.BR removexattr (2), +and +.BR attr (5). diff --git a/man/man2/removexattr.2 b/man/man2/removexattr.2 new file mode 100644 index 0000000..63affc8 --- /dev/null +++ b/man/man2/removexattr.2 @@ -0,0 +1,91 @@ +.\" +.\" Extended attributes system calls manual pages +.\" +.\" (C) Andreas Gruenbacher, February 2001 +.\" (C) Silicon Graphics Inc, September 2001 +.\" +.TH REMOVEXATTR 2 "Extended Attributes" "Dec 2001" "System calls" +.SH NAME +removexattr, lremovexattr, fremovexattr \- remove an extended attribute +.SH SYNOPSIS +.fam C +.nf +.B #include +.sp +.BI "int removexattr (const char\ *" path ", const char\ *" name ); +.BI "int lremovexattr (const char\ *" path ", const char\ *" name ); +.BI "int fremovexattr (int " filedes ", const char\ *" name ); +.fi +.fam T +.SH DESCRIPTION +Extended attributes are +.IR name :\c +value pairs associated with inodes (files, directories, symlinks, etc). +They are extensions to the normal attributes which are associated +with all inodes in the system (i.e. the +.BR stat (2) +data). +A complete overview of extended attributes concepts can be found in +.BR attr (5). +.PP +.B removexattr +removes the extended attribute identified by +.I name +and associated with the given +.I path +in the filesystem. +.PP +.B lremovexattr +is identical to +.BR removexattr , +except in the case of a symbolic link, where the extended attribute is +removed from the link itself, not the file that it refers to. +.PP +.B fremovexattr +is identical to +.BR removexattr , +only the extended attribute is removed from the open file pointed to by +.I filedes +(as returned by +.BR open (2)) +in place of +.IR path . +.PP +An extended attribute name is a simple NULL-terminated string. +The +.I name +includes a namespace prefix \- there may be several, disjoint +namespaces associated with an individual inode. +.SH RETURN VALUE +On success, zero is returned. +On failure, \-1 is returned and +.I errno +is set appropriately. +.PP +If the named attribute does not exist, +.I errno +is set to ENOATTR. +.PP +If extended attributes are not supported by the filesystem, or are disabled, +.I errno +is set to ENOTSUP. +.PP +The errors documented for the +.BR stat (2) +system call are also applicable here. +.SH AUTHORS +Andreas Gruenbacher, +.RI < a.gruenbacher@computer.org > +and the SGI XFS development team, +.RI < linux-xfs@oss.sgi.com >. +Please send any bug reports or comments to these addresses. +.SH SEE ALSO +.BR getfattr (1), +.BR setfattr (1), +.BR open (2), +.BR stat (2), +.BR setxattr (2), +.BR getxattr (2), +.BR listxattr (2), +and +.BR attr (5). diff --git a/man/man2/setxattr.2 b/man/man2/setxattr.2 new file mode 100644 index 0000000..5a5f66f --- /dev/null +++ b/man/man2/setxattr.2 @@ -0,0 +1,126 @@ +.\" +.\" Extended attributes system calls manual pages +.\" +.\" (C) Andreas Gruenbacher, February 2001 +.\" (C) Silicon Graphics Inc, September 2001 +.\" +.TH SETXATTR 2 "Extended Attributes" "Dec 2001" "System calls" +.SH NAME +setxattr, lsetxattr, fsetxattr \- set an extended attribute value +.SH SYNOPSIS +.fam C +.nf +.B #include +.sp +.BI "int setxattr (const char\ *" path ", const char\ *" name ", +.BI "\t\t\t void\ *" value ", size_t " size ", int " flags ); +.BI "int lsetxattr (const char\ *" path ", const char\ *" name ", +.BI "\t\t\t void\ *" value ", size_t " size ", int " flags ); +.BI "int fsetxattr (int " filedes ", const char\ *" name ", +.BI "\t\t\t void\ *" value ", size_t " size ", int " flags ); +.fi +.fam T +.SH DESCRIPTION +Extended attributes are +.IR name :\c +.I value +pairs associated with inodes (files, directories, symlinks, etc). +They are extensions to the normal attributes which are associated +with all inodes in the system (i.e. the +.BR stat (2) +data). +A complete overview of extended attributes concepts can be found in +.BR attr (5). +.PP +.B setxattr +sets the +.I value +of the extended attribute identified by +.I name +and associated with the given +.I path +in the filesystem. +The +.I size +of the +.I value +must be specified. +.PP +.B lsetxattr +is identical to +.BR setxattr , +except in the case of a symbolic link, where the extended attribute is +set on the link itself, not the file that it refers to. +.PP +.B fsetxattr +is identical to +.BR setxattr , +only the extended attribute is set on the open file pointed to by +.I filedes +(as returned by +.BR open (2)) +in place of +.IR path . +.PP +An extended attribute name is a simple NULL-terminated string. +The +.I name +includes a namespace prefix \- there may be several, disjoint +namespaces associated with an individual inode. +The +.I value +of an extended attribute is a chunk of arbitrary textual or +binary data of specified length. +.PP +The +.I flags +parameter can be used to refine the semantics of the operation. +XATTR_CREATE specifies a pure create, which fails if the named +attribute exists already. +XATTR_REPLACE specifies a pure replace operation, which fails if the +named attribute does not already exist. +By default (no flags), the extended attribute will be created if +need be, or will simply replace the value if the attribute exists. +.SH RETURN VALUE +On success, zero is returned. +On failure, \-1 is returned and +.I errno +is set appropriately. +.PP +If XATTR_CREATE is specified, and the attribute exists already, +.I errno +is set to EEXIST. +If XATTR_REPLACE is specified, and the attribute does not exist, +.I errno +is set to ENOATTR. +If XATTR_REMOVE is specified, and the attribute does not exist, +.I errno +is set to ENOATTR. +.PP +If there is insufficient space remaining to store the extended attribute, +.I errno +is set to either ENOSPC, or EDQUOT if quota enforcement was the cause. +.PP +If extended attributes are not supported by the filesystem, or are disabled, +.I errno +is set to ENOTSUP. +.PP +The errors documented for the +.BR stat (2) +system call are also applicable here. +.SH AUTHORS +Andreas Gruenbacher, +.RI < a.gruenbacher@computer.org > +and the SGI XFS development team, +.RI < linux-xfs@oss.sgi.com >. +Please send any bug reports or comments to these addresses. +.SH SEE ALSO +.BR getfattr (1), +.BR setfattr (1), +.BR open (2), +.BR stat (2), +.BR getxattr (2), +.BR listxattr (2), +.BR removexattr (2), +and +.BR attr (5). diff --git a/man/man3/attr_get.3 b/man/man3/attr_get.3 index 2a49624..bff7c86 100644 --- a/man/man3/attr_get.3 +++ b/man/man3/attr_get.3 @@ -1,4 +1,4 @@ -.TH ATTR_GET 3 +.TH ATTR_GET 3 "Extended Attributes" "Dec 2001" "XFS Compatibility API" .SH NAME attr_get, attr_getf \- get the value of a user attribute of a filesystem object .SH C SYNOPSIS @@ -174,11 +174,7 @@ does not refer to a valid descriptor. .SH "SEE ALSO" attr(1), .br -attrctl(2), -.br -attr_list(3), attr_listf(3) -.br -attr_multi(3), attr_multif(3) +attr_multi(3), attr_multif(3), .br attr_remove(3), attr_removef(3), .br diff --git a/man/man3/attr_list.3 b/man/man3/attr_list.3 index cffe16d..e69de29 100644 --- a/man/man3/attr_list.3 +++ b/man/man3/attr_list.3 @@ -1,269 +0,0 @@ -.TH ATTR_LIST 3 -.SH NAME -attr_list, attr_listf \- list the names of the user attributes of a filesystem object -.SH C SYNOPSIS -.PP -.sp -.nf -.B #include -.sp -.B "int attr_list (const char \(**path, char \(**buffer, " -.B " const int buffersize, int flags," -.B " attrlist_cursor_t \(**cursor);" -.PP -.B "int attr_listf (int fd, char \(**buffer, " -.B " const int buffersize, int flags," -.B " attrlist_cursor_t \(**cursor);" -.Op -.SH DESCRIPTION -The -.I attr_list -and -.I attr_listf -functions provide a way to list the existing attributes of a -filesystem object. -.P -.I Path\^ -points to a path name for a filesystem object, and -.I fd\^ -refers to the file descriptor associated with a file. -The -.I buffer -will be filled with a structure describing at least a portion of the -attributes associated with the given filesystem object. -.I Buffer -will be overwritten with an \f4attrlist_t\fP structure -containing a list of the attributes associated with -that filesystem object, up to a maximum of -.I buffersize -bytes. -The -.I buffer -must be sufficiently large to hold the appropriate data structures -plus at least one maximally sized attribute name, -but cannot be more than ATTR_MAX_VALUELEN (currently 64KB) bytes in length. -.PP -.Op c p a -The contents of an \f4attrlist_t\fP structure include the following members: -.P -.RS 3 -.nf -.ft 4 -.ta 9n 22n -__int32_t al_count; /\(** number of entries in attrlist \(**/ -__int32_t al_more; /\(** T/F: more attrs (do syscall again) \(**/ -__int32_t al_offset[1]; /\(** byte offsets of attrs [var-sized] \(**/ -.ft 1 -.fi -.RE -.PP -The -.I al_count -field shows the number of attributes represented in this buffer, -which is also the number of elements in the -.I al_offset -array. -The -.I al_more -field will be non-zero if another -.I attr_list -call would result in more attributes. -The -.I al_offset -array contains the byte offset within the -.I buffer -of the structure describing each of the attributes, -an \f4attrlist_ent_t\fP structure. -The \f4ATTR_ENTRY(buffer, index)\fP macro will help with decoding the list. -It takes a pointer to the -.I buffer -and an -.I index -into the -.I al_offset -array and returns a pointer to the corresponding -\f4attrlist_ent_t\fP structure. -.PP -The contents of an \f4attrlist_ent_t\fP structure -include the following members: -.P -.RS 3 -.nf -.ft 4 -.ta 9n 22n -u_int32_t a_valuelen; /\(** number bytes in value of attr \(**/ -char a_name[]; /\(** attr name (NULL terminated) \(**/ -.ft 1 -.fi -.Op -.RE -.PP -The -.I a_valuelen -field shows the size in bytes of the value -associated with the attribute whose name is stored in the -.I a_name -field. -The name is a NULL terminated string. -.PP -Note that the value of the attribute cannot be obtained through -this interface, the -.I attr_get -call should be used to get the value. -The -.I attr_list -interface tells the calling process how large of a buffer -it must have in order to get the attribute\'s value. -.PP -The -.I flags -argument can contain the following symbols bitwise OR\'ed together: -.TP -.SM -\%ATTR_ROOT -List the attributes that are in the -.B root -address space, not in the -.B user -address space. -(limited to use by super-user only) -.TP -.SM -\%ATTR_DONTFOLLOW -Do not follow symbolic links when resolving a -.I path -on an -.I attr_list -function call. -The default is to follow symbolic links. -.PP -The -.I cursor -argument is a pointer to an opaque data structure that the kernel uses -to track the calling process\'s position in the attribute list. -The only valid operations on a -.I cursor -are to pass it into an -.I attr_list -function call or to zero it out. -It should be zero\'ed out before the first -.I attr_list -call. -Note that multi-threaded applications may keep more than one -.I cursor -in order to serve multiple contexts, ie: the -.I attr_list -call is "thread-safe". -.PP -.I attr_list -will fail if one or more of the following are true: -.TP 17 -.SM -\%[ENOENT] -The named file does not exist. -.TP -.SM -\%[EPERM] -The effective user -.SM ID -does not match the owner of the file -and the effective user -.SM ID -is not super-user. -.TP -.SM -\%[ENOTDIR] -A component of the -path prefix -is not a directory. -.TP -.SM -\%[EACCES] -Search permission is denied on a -component of the -path prefix. -.TP -.SM -\%[EINVAL] -A bit was set in the -.I flag -argument that is not defined for this system call, -or the buffer was too small or too large. -.TP -.SM -\%[EFAULT] -Either -.I Path -or -.I buffer -points outside the allocated address space of the process, or -.I buffer -or -.I bufsize -are not 32bit aligned. -.TP -.SM -\%[ELOOP] -A path name lookup involved too many symbolic links. -.TP -.SM -\%[ENAMETOOLONG] -The length of -.I path -exceeds -.SM -.RI { MAXPATHLEN }, -or a pathname component is longer than -.SM -.RI { MAXNAMELEN }. -.TP -.SM -\%[ENOATTR] -.I attribute\^ -does not exist for this file. -.PP -.I attr_listf\^ -will fail if: -.TP 15 -.SM -\%[EINVAL] -A bit was set in the -.I flag -argument that is not defined for this system call, or -.I fd\^ -refers to a socket, not a file, -or the buffer was too small or too large. -.TP -.SM -\%[EFAULT] -Either -.I Path -or -.I buffer -points outside the allocated address space of the process, or -.I buffer -or -.I bufsize -are not 32bit aligned. -.TP -.SM -\%[EBADF] -.I Fd\^ -does not refer to a valid descriptor. -.SH "SEE ALSO" -attr(1), -.br -attrctl(2), -.br -attr_get(3), attr_getf(3), -.br -attr_multi(3), attr_multif(3) -.br -attr_remove(3), attr_removef(3), -.br -attr_set(3), attr_set(3) -.SH "DIAGNOSTICS" -Upon successful completion, a value of 0 is returned. -Otherwise, a value of \-1 is returned and -.I errno\^ -is set to indicate the error. diff --git a/man/man3/attr_multi.3 b/man/man3/attr_multi.3 index 2daab79..699d218 100644 --- a/man/man3/attr_multi.3 +++ b/man/man3/attr_multi.3 @@ -1,4 +1,4 @@ -.TH ATTR_MULTI 3 +.TH ATTR_MULTI 3 "Extended Attributes" "Dec 2001" "XFS Compatibility API" .SH NAME attr_multi, attr_multif \- manipulate multiple user attributes on a filesystem object at once .SH C SYNOPSIS @@ -253,12 +253,8 @@ does not refer to a valid descriptor. .SH "SEE ALSO" attr(1), .br -attrctl(2), -.br attr_get(3), attr_getf(3), .br -attr_list(3), attr_list(3) -.br attr_remove(3), attr_removef(3), .br attr_set(3), attr_set(3) diff --git a/man/man3/attr_remove.3 b/man/man3/attr_remove.3 index 1a72d50..4360c5f 100644 --- a/man/man3/attr_remove.3 +++ b/man/man3/attr_remove.3 @@ -1,4 +1,4 @@ -.TH ATTR_REMOVE 3 +.TH ATTR_REMOVE 3 "Extended Attributes" "Dec 2001" "XFS Compatibility API" .SH NAME attr_remove, attr_removef \- remove a user attribute of a filesystem object .SH C SYNOPSIS @@ -139,13 +139,9 @@ does not refer to a valid descriptor. .SH "SEE ALSO" attr(1), .br -attrctl(2), -.br attr_get(3), attr_getf(3), .br -attr_list(3), attr_listf(3) -.br -attr_multi(3), attr_multif(3) +attr_multi(3), attr_multif(3), .br attr_set(3), attr_setf(3), .SH "DIAGNOSTICS" diff --git a/man/man3/attr_set.3 b/man/man3/attr_set.3 index 01a04ad..79b1e83 100644 --- a/man/man3/attr_set.3 +++ b/man/man3/attr_set.3 @@ -1,4 +1,4 @@ -.TH ATTR_SET 3 +.TH ATTR_SET 3 "Extended Attributes" "Dec 2001" "XFS Compatibility API" .SH NAME attr_set, attr_setf \- set the value of a user attribute of a filesystem object .SH C SYNOPSIS @@ -199,13 +199,9 @@ does not refer to a valid descriptor. .SH "SEE ALSO" attr(1), .br -attrctl(2), -.br attr_get(3), attr_getf(3), .br -attr_list(3), attr_listf(3) -.br -attr_multi(3), attr_multif(3) +attr_multi(3), attr_multif(3), .br attr_remove(3), attr_removef(3), .SH "DIAGNOSTICS" diff --git a/man/man5/Makefile b/man/man5/Makefile new file mode 100644 index 0000000..b81e765 --- /dev/null +++ b/man/man5/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, +# Mountain View, CA 94043, or: +# +# http://www.sgi.com +# +# For further information regarding this notice, see: +# +# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ +# + +TOPDIR = ../.. +include $(TOPDIR)/include/builddefs + +MAN_SECTION = 5 + +MAN_PAGES = $(shell echo *.$(MAN_SECTION)) +MAN_DEST = $(PKG_MAN_DIR)/man$(MAN_SECTION) +LSRCFILES = $(MAN_PAGES) + +default install : $(MAN_PAGES) + +include $(BUILDRULES) + +install-dev : default + $(INSTALL) -m 755 -d $(MAN_DEST) + $(INSTALL_MAN) diff --git a/man/man5/attr.5 b/man/man5/attr.5 new file mode 100644 index 0000000..4d82071 --- /dev/null +++ b/man/man5/attr.5 @@ -0,0 +1,110 @@ +.\" +.\" Extended attributes manual page +.\" +.\" (C) Andreas Gruenbacher, 2000 +.\" (C) Silicon Graphics Inc, 2001 +.\" +.TH ATTR 5 +.SH NAME +Extended attributes +.SH DESCRIPTION +Extended attributes are name:value pairs associated permanently with +files and directories, similar to the environment strings associated +with a process. +An attribute may be defined or undefined. +If it is defined, its value may be empty or non-empty. +.PP +Extended attributes are extensions to the normal attributes which are +associated with all inodes in the system (i.e. the +.BR stat (2) +data). +They are often used to provide additional functionality +to a filesystem \- for example, additional security features such as +Access Control Lists (ACLs) may be implemented using extended attributes. +.PP +Users with search access to a file or directory may retrieve a list of +attribute names defined for that file or directory. +.PP +Extended attributes are accessed as atomic objects. +Reading retrieves the whole value of an attribute and stores it in a buffer. +Writing replaces any previous value with the new value. +.PP +Currently, support for extended attributes is implemented on Linux by +the ext2, ext3 and XFS filesystem patches, which can be downloaded from +.B http://acl.bestbits.at/ +and +.B http://oss.sgi.com/projects/xfs/ +respectively. +.SH EXTENDED ATTRIBUTE NAMESPACES +Attribute names are zero-terminated strings and typically have a short +(filesystem dependent) length. +The attribute name is always specified in the full +.IR namespace.attribute +form, eg. +.I user.mime_type +or +.IR system.posix_acl_access . +.PP +The namespace mechanism is used to define different classes of extended +attributes. +These different classes exist for several reasons, e.g. the permissions +and capabilities required for manipulating extended attributes of one +namespace may differ to another. +They have also been used to distinguish filesystem-specific attribute +names from canonical, filesystem-independent attribute names. +.PP +The extended attribute namespace is always specified as the first +component of the name. +This greatly simplifies certain operations, and provides a consistent, +explicit interface for all operations. +.PP +Extended +.I user +attributes may be assigned to files and directories for storing arbitrary +additional information such as the mime type, character set or encoding +of a file. +User attributes are subject to the same permissions as the contents of a file. +The file owner can decide who is allowed to read and/or set these attributes. +.PP +Extended +.I system +attributes are used by the kernel to store system objects such as +Access Control Lists and Capabilities. +Read and write access permissions to system attributes +depend on the policy implemented for each system attribute implemented +in the kernel. +.PP +Additional types of extended attributes with different access permissions, +such as attributes that are accessible only to processes trusted by the +kernel, may be added in the future. +.SH FILESYSTEM DIFFERENCES +The kernel and the filesystem may place limits on the maximum number +and size of extended attributes that can be associated with a file. +.PP +In the current ext2 and ext3 filesystem implementations, all extended +attributes must fit on a single filesystem block (1024, 2048 or 4096 bytes, +depending on the block size specified when the filesystem +was created). This limit may be removed in a future version. +Device special files cannot be associated with extended user attributes +(but they may be associated with extended system attributes). Permissions +of device special files define access to the devices rather than to the +device special files. +.PP +In the XFS filesystem implementation, there is no practical limit on the +number of extended attributes associated with a file, and the algorithms +used to store extended attribute information on disk are scalable (stored +either inline in the inode, as an extent, or in a B+ tree). +XFS allows extended attributes to be associated with device inodes. +.SH ADDITIONAL NOTES +Since the filesystems on which extended attributes are stored might also +be used on architectures with a different byte order and machine word +size, care should be taken to store attribute values in an architecture +independent format. +.SH AUTHORS +Andreas Gruenbacher, +.RI < a.gruenbacher@computer.org > +and the SGI XFS development team, +.RI < linux-xfs@oss.sgi.com >. +.SH SEE ALSO +getfattr(1), +setfattr(1). diff --git a/setfattr/Makefile b/setfattr/Makefile new file mode 100644 index 0000000..d3e793b --- /dev/null +++ b/setfattr/Makefile @@ -0,0 +1,50 @@ +# +# Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, +# Mountain View, CA 94043, or: +# +# http://www.sgi.com +# +# For further information regarding this notice, see: +# +# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ +# + +TOPDIR = .. +include $(TOPDIR)/include/builddefs + +LTCOMMAND = setfattr +CFILES = setfattr.c + +LLDLIBS = $(LIBATTR) +LTDEPENDENCIES = $(LIBATTR) + +default: $(LTCOMMAND) + +include $(BUILDRULES) + +install: default + $(INSTALL) -m 755 -d $(PKG_BIN_DIR) + $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR) + $(INSTALL) -S $(LTCOMMAND) $(PKG_BIN_DIR)/aset +install-dev: diff --git a/setfattr/setfattr.c b/setfattr/setfattr.c new file mode 100644 index 0000000..d2a462f --- /dev/null +++ b/setfattr/setfattr.c @@ -0,0 +1,425 @@ +/* + * Original setfattr.c: + * Copyright (C) 2001 by Andreas Gruenbacher + * Changes to use revised EA syscall interface: + * Copyright (C) 2001 by SGI XFS development + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#define _(String) gettext (String) + +#define CMD_LINE_OPTIONS "n:lv:x:B:Vh" +#define CMD_LINE_SPEC1 "{-n name|-x name} [-v value] [-lVh] file..." +#define CMD_LINE_SPEC2 "{-B filename} [-lVh] file..." + +char *opt_name; +char *opt_remove; +char *opt_value; +int opt_restore; +int opt_symlink; + +int had_errors; +const char *progname; + +int do_set(const char *name, const char *value, const char *path); +const char *decode(const char *value, size_t *size); +int restore(FILE *file, const char *filename); +char *next_line(FILE *file); +int hex_digit(char c); +int base64_digit(char c); + +int restore(FILE *file, const char *filename) +{ + char *path_p = NULL, *l; + int line = 0, backup_line, status = 0; + + for(;;) { + backup_line = line; + while ((l = next_line(file)) != NULL && *l == '\0') + line++; + if (l == NULL) + break; + line++; + if (strncmp(l, "# file: ", 8) != 0) { + if (filename) { + fprintf(stderr, _("%s: %s: No filename found " + "in line %d, aborting\n"), + progname, filename, backup_line); + } else { + fprintf(stderr, _("%s: No filename found in" + "line %d of standard input, " + "aborting\n"), + progname, backup_line); + } + status = 1; + goto cleanup; + } else + l += 8; + if (path_p) + free(path_p); + path_p = (char *)malloc(strlen(l) + 1); + if (!path_p) { + status = 1; + goto cleanup; + } + strcpy(path_p, l); + + while ((l = next_line(file)) != NULL && *l != '\0') { + char *name = l, *value = strchr(l, '='); + line++; + if (value == NULL) + value = ""; + else + *value++ = '\0'; + status = do_set(name, value, path_p); + } + if (l != NULL) + line++; + } + +cleanup: + if (path_p) + free(path_p); + return status; +} + +void help(void) +{ + printf(_("%s %s -- set extended attributes\n"), progname, VERSION); + printf(_("Usage: %s %s\n"), progname, CMD_LINE_SPEC1); + printf(_(" %s %s\n"), progname, CMD_LINE_SPEC2); + printf(_("Options:\n")); + printf(_("\t-n name\tset value of extended attribute `name'\n" + "\t-l\tset extended attribute values of a symlink\n" + "\t-x name\tremove extended attribute `name'\n" + "\t-v value\n\t\tvalue for extended attribute `name'\n" + "\t-B filename\n\t\trestore extended attributes (inverse of `getfattr -sdlR')\n" + "\t-V\tprint version and exit\n" + "\t-h\tthis help text\n")); +} + +char *next_line(FILE *file) +{ + static char line[_POSIX_PATH_MAX+32], *c; + if (!fgets(line, sizeof(line), file)) + return NULL; + + c = strrchr(line, '\0'); + while (c > line && (*(c-1) == '\n' || + *(c-1) == '\r')) { + c--; + *c = '\0'; + } + return line; +} + +int main(int argc, char *argv[]) +{ + FILE *file; + int status; + + progname = basename(argv[0]); + + while ((optopt = getopt(argc, argv, CMD_LINE_OPTIONS)) != -1) { + switch(optopt) { + case 'n': /* attribute name */ + if (opt_remove) + goto synopsis; + opt_name = optarg; + break; + + case 'l': /* set attribute on symlink itself */ + opt_symlink = 1; + break; + + case 'v': /* attribute value */ + if (opt_value || opt_remove) + goto synopsis; + opt_value = optarg; + break; + + case 'x': /* remove attribute */ + if (opt_name) + goto synopsis; + opt_remove = optarg; + break; + + case 'B': /* restore */ + opt_restore = 1; + if (strcmp(optarg, "-") == 0) + file = stdin; + else { + file = fopen(optarg, "r"); + if (file == NULL) { + fprintf(stderr, "%s: %s: %s\n", + progname, optarg, + strerror(errno)); + return 1; + } + } + status = restore(file, + (file == stdin) ? NULL : optarg); + if (file != stdin) + fclose(file); + if (status != 0) + return 1; + break; + + case 'V': + printf("%s " VERSION "\n", progname); + return 0; + + case 'h': + help(); + return 0; + + default: + goto synopsis; + } + } + if (((opt_name && opt_remove) || (!opt_name && !opt_remove) || + optind >= argc) && !opt_restore) + goto synopsis; + if (opt_name) { + if (!opt_value) + opt_value = ""; + } else { + opt_name = opt_remove; + opt_value = NULL; + } + while (optind < argc) { + do_set(opt_name, opt_value, argv[optind]); + optind++; + } + + return (had_errors ? 1 : 0); + +synopsis: + fprintf(stderr, _("Usage: %s %s\n" + " %s %s\n" + "Try `%s -h' for more information.\n"), + progname, CMD_LINE_SPEC1, progname, CMD_LINE_SPEC2, progname); + return 2; +} + +int do_setxattr(const char *path, const char *name, void *value, size_t size) +{ + if (opt_symlink) + return lsetxattr(path, name, value, size, 0); + return setxattr(path, name, value, size, 0); +} + +int do_removexattr(const char *path, const char *name) +{ + if (opt_symlink) + return lremovexattr(path, name); + return removexattr(path, name); +} + +int do_set(const char *name, const char *value, const char *path) +{ + size_t size = 0; + int error; + + if (value) { + size = strlen(value); + value = decode(value, &size); + if (!value) + return 1; + } + error = opt_remove? do_removexattr(path, name): + do_setxattr(path, name, (void *)value, size); + if (error < 0) { + perror(path); + had_errors++; + return 1; + } + return 0; +} + +const char *decode(const char *value, size_t *size) +{ + static char *decoded = NULL; + + if (decoded != NULL) { + free(decoded); + decoded = NULL; + } + if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) { + const char *v = value+2, *end = value + *size; + char *d; + + decoded = d = (char *)malloc(*size / 2); + if (!decoded) { + perror(""); + had_errors++; + return NULL; + } + while (v < end) { + int d1, d0; + + while (v < end && isspace(*v)) + v++; + if (v == end) + break; + d1 = hex_digit(*v++); + while (v < end && isspace(*v)) + v++; + if (v == end) { + bad_hex_encoding: + fprintf(stderr, "bad input encoding\n"); + had_errors++; + return NULL; + } + d0 = hex_digit(*v++); + if (d1 < 0 || d0 < 0) + goto bad_hex_encoding; + *d++ = ((d1 << 4) | d0); + } + *size = d - decoded; + } else if (value[0] == '0' && (value[1] == 's' || value[1] == 'S')) { + const char *v = value+2, *end = value + *size; + int d0, d1, d2, d3; + char *d; + + decoded = d = (char *)malloc(*size / 4 * 3); + if (!decoded) { + perror(""); + had_errors++; + return NULL; + } + for(;;) { + while (v < end && isspace(*v)) + v++; + if (v == end) { + d0 = d1 = d2 = d3 = -2; + break; + } + if (v + 4 > end) { + bad_base64_encoding: + fprintf(stderr, "bad input encoding\n"); + had_errors++; + return NULL; + } + d0 = base64_digit(*v++); + d1 = base64_digit(*v++); + d2 = base64_digit(*v++); + d3 = base64_digit(*v++); + if (d0 < 0 || d1 < 0 || d2 < 0 || d3 < 0) + break; + + *d++ = (char)((d0 << 2) | (d1 >> 4)); + *d++ = (char)((d1 << 4) | (d2 >> 2)); + *d++ = (char)((d2 << 6) | d3); + } + if (d0 == -2) { + if (d1 != -2 || d2 != -2 || d3 != -2) + goto bad_base64_encoding; + goto base64_end; + } + if (d0 == -1 || d1 < 0 || d2 == -1 || d3 == -1) + goto bad_base64_encoding; + *d++ = (char)((d0 << 2) | (d1 >> 4)); + if (d2 != -2) + *d++ = (char)((d1 << 4) | (d2 >> 2)); + else { + if (d1 & 0x0F || d3 != -2) + goto bad_base64_encoding; + goto base64_end; + } + if (d3 != -2) + *d++ = (char)((d2 << 6) | d3); + else if (d2 & 0x03) + goto bad_base64_encoding; + base64_end: + while (v < end && isspace(*v)) + v++; + if (v + 4 <= end && *v == '=') { + if (*++v != '=' || *++v != '=' || *++v != '=') + goto bad_base64_encoding; + v++; + } + while (v < end && isspace(*v)) + v++; + if (v < end) + goto bad_base64_encoding; + *size = d - decoded; + } else { + const char *v = value, *end = value + *size; + char *d; + + if (end > v+1 && *v == '"' && *(end-1) == '"') { + v++; + end--; + } + + decoded = d = (char *)malloc(*size); + if (!decoded) { + perror(""); + had_errors++; + return NULL; + } + + while (v < end) { + if (v[0] == '\\') { + if (v[1] == '\\' || v[1] == '"') { + *d++ = *++v; v++; + } else if (v[1] >= '0' && v[1] <= '7') { + int c = 0; + v++; + c = (*v++ - '0'); + if (*v >= '0' && *v <= '7') + c = (c << 3) + (*v++ - '0'); + if (*v >= '0' && *v <= '7') + c = (c << 3) + (*v++ - '0'); + *d++ = c; + } else + *d++ = *v++; + } else + *d++ = *v++; + } + *size = d - decoded; + } + return decoded; +} + +int hex_digit(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else + return -1; +} + +int base64_digit(char c) +{ + if (c >= 'A' && c <= 'Z') + return c - 'A'; + else if (c >= 'a' && c <= 'z') + return 26 + c - 'a'; + else if (c >= '0' && c <= '9') + return 52 + c - '0'; + else if (c == '+') + return 62; + else if (c == '/') + return 63; + else if (c == '=') + return -2; + else + return -1; +} + diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..bc1e326 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,44 @@ +# +# Copyright (c) 2001 Silicon Graphics, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# Further, this software is distributed without any warranty that it is +# free of the rightful claim of any third person regarding infringement +# or the like. Any license provided herein, whether implied or +# otherwise, applies only to this software file. Patent licenses, if +# any, provided herein do not apply to combinations of this program with +# other software, or any other product whatsoever. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write the Free Software Foundation, Inc., 59 +# Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, +# Mountain View, CA 94043, or: +# +# http://www.sgi.com +# +# For further information regarding this notice, see: +# +# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ +# + +TOPDIR = .. +include $(TOPDIR)/include/builddefs + +# ensure we pick these up in the source tarball +LSRCFILES = attr.test run README + +default: + +include $(BUILDRULES) + +install: +install-dev: diff --git a/test/README b/test/README new file mode 100644 index 0000000..ab8f232 --- /dev/null +++ b/test/README @@ -0,0 +1,9 @@ + +Andreas Gruenbacher's tests for the ext2 filesystem extended attributes +support. Most of these tests should work for any filesystem type, and +most are actually used as part of the XFS test suite. However, those +tests relating to the exercising of boundary conditions of attribute +value lengths, etc, are specific to ext2. + + -- nathans@sgi.com + diff --git a/test/attr.test b/test/attr.test new file mode 100644 index 0000000..b1399e8 --- /dev/null +++ b/test/attr.test @@ -0,0 +1,78 @@ +! +! Tests for getting/setting extended file attributes with ext2/ext3 +! The initial size checks are ext2/ext3 specific, but the remainder +! should work for any extended attributes filesystem (eg. XFS). +! +$ mkdir attr-test +$ touch attr-test/f +! Maximum attribute size for 1024 byte blocks = 1024 - (20+20+4) = 980 +$ aset -n user.name -v 968+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ attr-test/f +! Attribute too big for 1024 byte blocks +$ aset -n user.name -v 969++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ attr-test/f +attr-test/f: No space left on device +$ aset -n user.name attr-test/f +$ aget -d attr-test/f +# file: attr-test/f +user.name + +$ aset -n user.name -v 0xbabe attr-test/f +$ aset -n user.name2 -v 0xdeadbeef attr-test/f +$ aset -n user.name3 -v 0xdeface attr-test/f +! +! +$ aget -d -e hex attr-test/f +# file: attr-test/f +user.name=0xbabe +user.name2=0xdeadbeef +user.name3=0xdeface + +$ aget -d -e base64 attr-test/f +# file: attr-test/f +user.name=0sur4= +user.name2=0s3q2+7w== +user.name3=0s3vrO + +! +! shrink value of existing attribute +! +$ aset -n user.name2 -v 0xdeaf attr-test/f +$ aget -d -e hex attr-test/f +# file: attr-test/f +user.name=0xbabe +user.name2=0xdeaf +user.name3=0xdeface + +! +! grow value of existing attribute +! +$ aset -n user.name2 -v 0xdecade attr-test/f +$ aget -d -e hex attr-test/f +# file: attr-test/f +user.name=0xbabe +user.name2=0xdecade +user.name3=0xdeface + +! +! empty value +! +$ aset -n user.name2 attr-test/f +$ aget -d -n user.name2 attr-test/f +# file: attr-test/f +user.name2 + +! +! overwrite empty value +! +$ aset -n user.name2 -v 0xcafe attr-test/f +$ aget -d -e hex -n user.name2 attr-test/f +# file: attr-test/f +user.name2=0xcafe + +! +! remove attribute +! +$ aset -x user.name2 attr-test/f +$ aget -d -n user.name2 attr-test/f +attr-test/f: user.name2: No such attribute +$ rm attr-test/f +$ rmdir attr-test diff --git a/test/run b/test/run new file mode 100644 index 0000000..b545a53 --- /dev/null +++ b/test/run @@ -0,0 +1,145 @@ +#!/usr/bin/perl + +use strict; +use FileHandle; +use POSIX qw(geteuid getegid isatty); + +my $owner = getpwuid(geteuid()); +my $group = getgrgid(getegid()); + +my ($OK, $FAILED) = ("ok", "failed"); +if (isatty(fileno(STDOUT))) { + $OK = "\033[32m" . $OK . "\033[m"; + $FAILED = "\033[31m\033[1m" . $FAILED . "\033[m"; +} + +my ($prog, $in, $out) = ([], [], []); +my $line = 0; +my $prog_line; +for (;;) { + my $script = <>; $line++; + $script =~ s/\@OWNER\@/$owner/g; + $script =~ s/\@GROUP\@/$group/g; + next if (defined($script) && $script =~ /^!/); + if (!defined($script) || $script =~ s/^\$ ?//) { + if (@$prog) { + #print "[$prog_line] \$ ", join(' ', @$prog), " -- "; + my $p = [ @$prog ]; + print "[$prog_line] \$ ", join(' ', + map { s/\s/\\$&/g; $_ } @$p), " -- "; + my $result = exec_test($prog, $in); + my $good = 1; + my $nmax = (@$out > @$result) ? @$out : @$result; + for (my $n=0; $n < $nmax; $n++) { + if (!defined($out->[$n]) || !defined($result->[$n]) || + $out->[$n] ne $result->[$n]) { + $good = 0; + #chomp $out->[$n]; + #chomp $result->[$n]; + #print "$out->[$n] != $result->[$n]"; + } + } + print $good ? $OK : $FAILED, "\n"; + if (!$good) { + for (my $n=0; $n < $nmax; $n++) { + my $l = defined($out->[$n]) ? $out->[$n] : "~"; + chomp $l; + my $r = defined($result->[$n]) ? $result->[$n] : "~"; + chomp $r; + print sprintf("%-37s | %-39s\n", $l, $r); + } + } + } + #$prog = [ split /\s+/, $script ] if $script; + $prog = [ map { s/\\(.)/$1/g; $_ } split /(? ?//) { + push @$in, $script; + } else { + push @$out, $script; + } + last unless defined($script); +} + +sub exec_test($$) { + my ($prog, $in) = @_; + local (*IN, *IN_DUP, *IN2, *OUT_DUP, *OUT, *OUT2); + + if ($prog->[0] eq "umask") { + umask oct $prog->[1]; + return []; + } elsif ($prog->[0] eq "cd") { + if (!chdir $prog->[1]) { + return [ "chdir: $prog->[1]: $!\n" ]; + } + return []; + } + + pipe *IN2, *OUT + or die "Can't create pipe for reading: $!"; + open *IN_DUP, "<&STDIN" + or *IN_DUP = undef; + open *STDIN, "<&IN2" + or die "Can't duplicate pipe for reading: $!"; + close *IN2; + + open *OUT_DUP, ">&STDOUT" + or die "Can't duplicate STDOUT: $!"; + pipe *IN, *OUT2 + or die "Can't create pipe for writing: $!"; + open *STDOUT, ">&OUT2" + or die "Can't duplicate pipe for writing: $!"; + close *OUT2; + + *STDOUT->autoflush(); + *OUT->autoflush(); + + if (fork()) { + # Server + if (*IN_DUP) { + open *STDIN, "<&IN_DUP" + or die "Can't duplicate STDIN: $!"; + close *IN_DUP + or die "Can't close STDIN duplicate: $!"; + } + open *STDOUT, ">&OUT_DUP" + or die "Can't duplicate STDOUT: $!"; + close *OUT_DUP + or die "Can't close STDOUT duplicate: $!"; + + foreach my $line (@$in) { + #print "> $line"; + print OUT $line; + } + close *OUT + or die "Can't close pipe for writing: $!"; + + my $result = []; + while () { + #print "< $_"; + push @$result, $_; + } + return $result; + } else { + # Client + close IN + or die "Can't close read end for input pipe: $!"; + close OUT + or die "Can't close write end for output pipe: $!"; + close OUT_DUP + or die "Can't close STDOUT duplicate: $!"; + local *ERR_DUP; + open ERR_DUP, ">&STDERR" + or die "Can't duplicate STDERR: $!"; + open STDERR, ">&STDOUT" + or die "Can't join STDOUT and STDERR: $!"; + + #print ERR_DUP "<", join(' ', @$prog), ">\n"; + exec @$prog; + print ERR_DUP $prog->[0], ": $!\n"; + exit; + } +} + -- cgit v1.2.3