summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2002-02-25 23:00:28 +0000
committerNathan Scott <nathans@sgi.com>2002-02-25 23:00:28 +0000
commitaf208e0a7308642f1cfcca8fb97d5a6bb2558a30 (patch)
tree38a4aa110c53f7ef39b24ff7550e225655ffe7c1
parent9a1f53a06b83d155c82cab65f85ce691d7bf31c6 (diff)
downloadattr-af208e0a7308642f1cfcca8fb97d5a6bb2558a30.tar.gz
Merge of xfs-cmds-2.4.18:slinx:112535a by nathans.
merge with AndreasG latest snapshot - long options, rename a couple of options to his prefered letters, -5 is gone, use ntfw instead of doing it ourselves.
-rw-r--r--getfattr/Makefile3
-rw-r--r--getfattr/getfattr.c633
-rw-r--r--getfattr/walk_tree.c94
-rw-r--r--getfattr/walk_tree.h18
-rw-r--r--include/xattr.h6
-rw-r--r--man/man1/getfattr.121
-rw-r--r--setfattr/setfattr.c221
7 files changed, 489 insertions, 507 deletions
diff --git a/getfattr/Makefile b/getfattr/Makefile
index 6b11226..fc23850 100644
--- a/getfattr/Makefile
+++ b/getfattr/Makefile
@@ -34,8 +34,7 @@ TOPDIR = ..
include $(TOPDIR)/include/builddefs
LTCOMMAND = getfattr
-CFILES = walk_tree.c getfattr.c
-HFILES = walk_tree.h
+CFILES = getfattr.c
LLDLIBS = $(LIBATTR)
LTDEPENDENCIES = $(LIBATTR)
diff --git a/getfattr/getfattr.c b/getfattr/getfattr.c
index 390a8c9..74c2d65 100644
--- a/getfattr/getfattr.c
+++ b/getfattr/getfattr.c
@@ -1,185 +1,87 @@
/*
- * Original getfattr.c:
- * Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
- * Changes to use revised EA syscall interface:
- * Copyright (C) 2001 by SGI XFS development <linux-xfs@oss.sgi.com>
- */
+ File: getfattr.c
+ (Linux Extended Attributes)
+
+ Copyright (C) 2001-2002 Andreas Gruenbacher <a.gruenbacher@computer.org>
+ Copyright (C) 2001-2002 SGI XFS development <linux-xfs@oss.sgi.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <ctype.h>
#include <getopt.h>
#include <regex.h>
#include <attr/xattr.h>
-#include "walk_tree.h"
+#include <ftw.h>
#include <locale.h>
#include <libintl.h>
#define _(String) gettext (String)
-#define CMD_LINE_OPTIONS "ade:hln:r:vR5LPV"
-#define CMD_LINE_SPEC "[-n name|-d] [-ahvR5LPV] [-e en] [-r regex] path..."
-
-int opt_dump;
-int opt_symlink;
-char *opt_encoding;
-char opt_value_only;
-int opt_strip_leading_slash = 1;
+#define CMD_LINE_OPTIONS "ade:hm:n:v:HRLP"
+#define CMD_LINE_SPEC "[-ahvRLP] [-n name|-d] [-e en] [-m pattern] path..."
+
+struct option long_options[] = {
+ { "name", 1, 0, 'n' },
+ { "dump", 0, 0, 'd' },
+ { "encoding", 1, 0, 'e' },
+ { "match", 1, 0, 'm' },
+ { "only-values", 0, 0, 'v' },
+ { "no-dereference", 0, 0, 'h' },
+ { "absolute-names", 0, 0, 'a' },
+ { "recursive", 0, 0, 'R' },
+ { "logical", 0, 0, 'L' },
+ { "physical", 0, 0, 'P' },
+ { "version", 0, 0, 'V' },
+ { "help", 0, 0, 'H' },
+ { NULL, 0, 0, 0 }
+};
+
+int opt_recursive; /* recurse into sub-directories? */
+int opt_walk_logical; /* always follow symbolic links */
+int opt_walk_physical; /* never follow symbolic links */
+int opt_dump; /* dump attribute values (or only list the names) */
+int opt_deref = 1; /* dereference symbolic links */
+char *opt_name; /* dump named attributes */
+char *opt_name_pattern = "^user\\."; /* include only matching names */
+char *opt_encoding; /* encode values automatically (NULL), or as "text",
+ "hex", or "base64" */
+char opt_value_only; /* dump the value only, without any decoration */
+int opt_strip_leading_slash = 1; /* strip leading '/' from path names */
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 *pattern = "^user\\.";
- 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': /* regular expression for filtering names */
- if (!strcmp(optarg, "-"))
- pattern = "";
- else
- pattern = optarg;
- 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;
- }
+regex_t name_regex;
- 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);
+ return (opt_deref ? getxattr : lgetxattr)(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);
+ return (opt_deref ? listxattr : llistxattr)(path, list, size);
}
-int high_water_alloc(void **buf, int *bufsize, int newsize)
+int high_water_alloc(void **buf, size_t *bufsize, size_t newsize)
{
#define CHUNK_SIZE 256
/*
@@ -188,149 +90,32 @@ int high_water_alloc(void **buf, int *bufsize, int newsize)
* Size is increased in fixed size chunks (CHUNK_SIZE).
*/
if (*bufsize < newsize) {
+ void *newbuf;
+
newsize = (newsize + CHUNK_SIZE-1) & ~(CHUNK_SIZE-1);
- *buf = realloc(*buf, newsize);
- if (!*buf) {
+ newbuf = realloc(*buf, newsize);
+ if (!newbuf) {
perror(progname);
had_errors++;
- *bufsize = 0;
return 1;
}
+
+ *buf = newbuf;
*bufsize = newsize;
}
return 0;
}
-int pstrcmp(const char **a, const char **b)
-{
- return strcmp(*a, *b);
-}
-
-int do_get_all(const char *path, struct stat *stat, void *dummy)
-{
- static char *list;
- static ssize_t bufsize;
- static char **names;
- static int ncount;
-
- char *v;
- ssize_t listsize;
- int n, count = 0;
-
- listsize = do_listxattr(path, NULL, 0);
- if (listsize < 0) {
- perror(path);
- had_errors++;
- return 1;
- } else if (listsize > 0) {
- if (high_water_alloc((void **)&list, &bufsize, listsize))
- return 1;
-
- listsize = do_listxattr(path, list, bufsize);
- 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) {
- n = count * sizeof(char *);
- if (high_water_alloc((void **)&names, &ncount, n))
- return 1;
- n = 0;
- 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)
+const char *strerror_ea(int err)
{
- int error;
-
- header_printed = 0;
- error = get_one(path, (const char *)name);
- if (header_printed)
- puts("");
- return error;
+ if (err == ENOATTR)
+ return _("No such attribute");
+ return strerror(err);
}
-int get_one(const char *path, const char *name)
+int pstrcmp(const void *a, const void *b)
{
- static char *value;
- static size_t vsize;
-
- int error, lsize = 0;
-
- 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;
- }
- if (high_water_alloc((void **)&value, &vsize, error + 1))
- return 1;
- error = do_getxattr(path, name, value, vsize);
- if (error < 0)
- goto syscall_failed;
- lsize = error;
- value[lsize] = '\0';
- }
-
- 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 (lsize) {
- const char *e = encode(value, &lsize);
-
- if (e)
- printf("%s=%s\n", name, e);
- } else
- puts(name);
-
- return 0;
+ return strcmp(*(const char **)a, *(const char **)b);
}
int well_enough_printable(const char *value, size_t size)
@@ -341,7 +126,7 @@ int well_enough_printable(const char *value, size_t size)
if (!isprint(*value++))
nonpr++;
- return (size >= nonpr*8); /* no more than 1/8 non-printable */
+ return (size >= nonpr*8); /* no more than 1/8 non-printable chars */
}
const char *encode(const char *value, size_t *size)
@@ -449,3 +234,283 @@ const char *encode(const char *value, size_t *size)
}
return encoded;
}
+
+int print_attribute(const char *path, const char *name, int *header_printed)
+{
+ static char *value;
+ static size_t value_size;
+ ssize_t length = 0;
+
+ if (opt_dump || opt_value_only) {
+ length = do_getxattr(path, name, NULL, 0);
+ if (length < 0) {
+ if (errno == ENOATTR) {
+ /*
+ * Occasionally there are attribute
+ * names in the name list that are not
+ * accessible, or don't really exist.
+ * Silently ignore this case.
+ */
+ return 0;
+ }
+ fprintf(stderr, "%s: %s: %s\n", path, name,
+ strerror_ea(errno));
+ return 1;
+ }
+ if (high_water_alloc((void **)&value, &value_size, length))
+ return 1;
+ length = do_getxattr(path, name, value, value_size);
+ if (length < 0) {
+ fprintf(stderr, "%s: %s: %s\n", path, name,
+ strerror_ea(errno));
+ return 1;
+ }
+ }
+
+ 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)
+ fwrite(value, length, 1, stdout);
+ else if (length) {
+ const char *enc = encode(value, &length);
+
+ if (enc)
+ printf("%s=%s\n", name, enc);
+ } else
+ puts(name);
+
+ return 0;
+}
+
+int list_attributes(const char *path, int *header_printed)
+{
+ static char *list;
+ static size_t list_size;
+ static char **names;
+ static size_t names_size;
+ int num_names = 0;
+ ssize_t length;
+ char *l;
+
+ length = do_listxattr(path, NULL, 0);
+ if (length < 0) {
+ if (errno != ENOTSUP || errno != ENOSYS) {
+ fprintf(stderr, "%s: %s: %s\n",
+ progname, path, strerror_ea(errno));
+ had_errors++;
+ return 1;
+ }
+ } else if (length == 0)
+ return 0;
+
+ if (high_water_alloc((void **)&list, &list_size, length))
+ return 1;
+
+ length = do_listxattr(path, list, list_size);
+ if (length < 0) {
+ perror(path);
+ had_errors++;
+ return 1;
+ }
+
+ for (l = list; l != list + length; l = strchr(l, '\0')+1) {
+ if (regexec(&name_regex, l, 0, NULL, 0) != 0)
+ continue;
+
+ if (names_size < (num_names+1) * sizeof(*names)) {
+ if (high_water_alloc((void **)&names, &names_size,
+ (num_names+1) * sizeof(*names)))
+ return 1;
+ }
+
+ names[num_names++] = l;
+ }
+
+ qsort(names, num_names, sizeof(*names), pstrcmp);
+
+ if (num_names) {
+ int n;
+
+ for (n = 0; n < num_names; n++)
+ print_attribute(path, names[n], header_printed);
+ }
+ return 0;
+}
+
+int do_print(const char *path, const struct stat *stat,
+ int flag, struct FTW *ftw)
+{
+ int header_printed = 0;
+
+ /*
+ * Process the target of a symbolic link, and traverse the
+ * link, only if doing a logical walk, or if the symbolic link
+ * was specified on the command line. Always skip symbolic
+ * links if doing a physical walk.
+ */
+
+ if (S_ISLNK(stat->st_mode) &&
+ (opt_walk_physical || (ftw->level > 0 && !opt_walk_logical)))
+ return 0;
+
+ if (opt_name)
+ print_attribute(path, opt_name, &header_printed);
+ else
+ list_attributes(path, &header_printed);
+
+ if (header_printed)
+ puts("");
+
+ /*
+ * We also get here in non-recursive mode. In that case,
+ * return something != 0 to abort nftw.
+ */
+
+ if (!opt_recursive)
+ return 1;
+ return 0;
+}
+
+void help(void)
+{
+ printf(_("%s %s -- get extended attributes\n"),
+ progname, VERSION);
+ printf(_("Usage: %s %s\n"),
+ progname, _(CMD_LINE_SPEC));
+ printf(_(
+" -n, --name=name get the named extended attribute value\n"
+" -d, --dump get all extended attribute values\n"
+" -e, --encoding=... encode values (as 'text', 'hex' or 'base64')\n"
+" --match=pattern only get attributes with names matching pattern\n"
+" --only-values print the bare values only\n"
+" -h, --no-dereference do not dereference symbolic links\n"
+" --absolute-names don't strip leading '/' in pathnames\n"
+" -R, --recursive recurse into subdirectories\n"
+" -L, --logical logical walk, follow symbolic links\n"
+" -P --physical physical walk, do not follow symbolic links\n"
+" --version print version and exit\n"
+" --help this help text\n"));
+}
+
+
+int main(int argc, char *argv[])
+{
+ int opt;
+
+ progname = basename(argv[0]);
+ setlocale(LC_ALL, "");
+
+ while ((opt = getopt_long(argc, argv, CMD_LINE_OPTIONS,
+ long_options, NULL)) != -1) {
+ switch(opt) {
+ 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 'h': /* do not dereference symlinks */
+ opt_deref = 0;
+ break;
+
+ case 'n': /* get named attribute */
+ opt_dump = 1;
+ opt_name = optarg;
+ break;
+
+ case 'm': /* regular expression for filtering names */
+ opt_name_pattern = optarg;
+ if (strcmp(opt_name_pattern, "-") == 0)
+ opt_name_pattern = "";
+ break;
+
+ case 'v': /* get attribute values only */
+ opt_value_only = 1;
+ break;
+
+ case 'L':
+ opt_walk_logical = 1;
+ opt_walk_physical = 0;
+ break;
+
+ case 'P':
+ opt_walk_logical = 0;
+ opt_walk_physical = 1;
+ break;
+
+ case 'R':
+ opt_recursive = 1;
+ break;
+
+ case 'V':
+ printf("%s " VERSION "\n", progname);
+ return 0;
+
+ case ':': /* option missing */
+ case '?': /* unknown option */
+ default:
+ goto synopsis;
+ }
+ }
+ if (optind >= argc)
+ goto synopsis;
+
+ if (regcomp(&name_regex, opt_name_pattern,
+ REG_EXTENDED | REG_NOSUB) != 0) {
+ fprintf(stderr, _("%s: invalid regular expression \"%s\"\n"),
+ progname, opt_name_pattern);
+ return 1;
+ }
+
+ while (optind < argc) {
+ if (nftw(argv[optind], do_print, 0,
+ opt_walk_physical * FTW_PHYS) < 0) {
+ fprintf(stderr, "%s: %s\n", progname,
+ strerror_ea(errno));
+ }
+ optind++;
+ }
+
+ return (had_errors ? 1 : 0);
+
+synopsis:
+ fprintf(stderr, _("Usage: %s %s\n"
+ "Try `%s --help' for more information.\n"),
+ progname, CMD_LINE_SPEC, progname);
+ return 2;
+}
+
diff --git a/getfattr/walk_tree.c b/getfattr/walk_tree.c
deleted file mode 100644
index 468fef4..0000000
--- a/getfattr/walk_tree.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
- *
- * TODO: should this be replaced by using nftw(3)?
- */
-#include <sys/stat.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#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
deleted file mode 100644
index c84c742..0000000
--- a/getfattr/walk_tree.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
- *
- * TODO: should this be replaced by using nftw(3)?
- */
-#include <sys/stat.h>
-
-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/xattr.h b/include/xattr.h
index ee17360..14752f2 100644
--- a/include/xattr.h
+++ b/include/xattr.h
@@ -47,11 +47,11 @@
__BEGIN_DECLS
extern int setxattr (const char *__path, const char *__name,
- void *__value, size_t __size, int __flags) __THROW;
+ const 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;
+ const void *__value, size_t __size, int __flags) __THROW;
extern int fsetxattr (int __filedes, const char *__name,
- void *__value, size_t __size, int __flags) __THROW;
+ const void *__value, size_t __size, int __flags) __THROW;
extern ssize_t getxattr (const char *__path, const char *__name,
void *__value, size_t __size) __THROW;
diff --git a/man/man1/getfattr.1 b/man/man1/getfattr.1
index 58642a2..7fadfc5 100644
--- a/man/man1/getfattr.1
+++ b/man/man1/getfattr.1
@@ -3,11 +3,11 @@
getfattr \- get extended attributes of filesystem objects
.SH SYNOPSIS
.nf
-\f3getfattr\f1 [\f3\-lvRLP\f1] \f3\-n name\f1 [\f3\-e en\f1] \c
+\f3getfattr\f1 [\f3\-hvRLP\f1] \f3\-n name\f1 [\f3\-e en\f1] \c
\f3pathname\f1...
-\f3getfattr\f1 [\f3\-lvRLP\f1] \f3\-d\f1 [\f3\-e en\f1] \c
-[\f3\-r regex\f1] \f3pathname\f1...
-\f3getfattr\f1 [\f3\-Vh\f1]
+\f3getfattr\f1 [\f3\-hvRLP\f1] \f3\-d\f1 [\f3\-e en\f1] \c
+[\f3\-m pattern\f1] \f3pathname\f1...
+\f3getfattr\f1 [\f3\-VH\f1]
.fi
.SH DESCRIPTION
For each file,
@@ -57,14 +57,14 @@ Valid values of
.I en
are "text", "hex", and "base64".
.TP
-.I \-l
+.I \-h
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
+.I \-m
+.I pattern
is a regular expression pattern to apply to the set of extended
attribute names being returned.
It defaults to "^user\\." if no
@@ -83,14 +83,11 @@ Dump out the extended attribute value(s) only.
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).
+Refines the \-R option - "logical walk" (do follow symbolic links).
.TP
.I \-P
-Refines the \-R or \-5 option - "physical walk" (do not follow symbolic links).
+Refines the \-R option - "physical walk" (do not follow symbolic links).
.TP
.I \-V
Print the version of
diff --git a/setfattr/setfattr.c b/setfattr/setfattr.c
index 1cc6150..f38e98f 100644
--- a/setfattr/setfattr.c
+++ b/setfattr/setfattr.c
@@ -1,9 +1,24 @@
/*
- * Original setfattr.c:
- * Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
- * Changes to use revised EA syscall interface:
- * Copyright (C) 2001 by SGI XFS development <linux-xfs@oss.sgi.com>
- */
+ File: setfattr.c
+ (Linux Extended Attributes)
+
+ Copyright (C) 2001-2002 Andreas Gruenbacher <a.gruenbacher@computer.org>
+ Copyright (C) 2001-2002 SGI XFS development <linux-xfs@oss.sgi.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
#include <limits.h>
#include <stdio.h>
@@ -18,31 +33,72 @@
#include <libintl.h>
#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;
+#define CMD_LINE_OPTIONS "n:x:v:hB:HV"
+#define CMD_LINE_SPEC "{-n name|-x name} [-v value] [-h] file..."
+
+struct option long_options[] = {
+ { "name", 1, 0, 'n' },
+ { "remove", 1, 0, 'x' },
+ { "value", 1, 0, 'v' },
+ { "no-dereference", 0, 0, 'h' },
+ { "restore", 1, 0, 'B' },
+ { "version", 0, 0, 'V' },
+ { "help", 0, 0, 'H' },
+ { NULL, 0, 0, 0 }
+};
+
+char *opt_name; /* attribute name to set */
+char *opt_value; /* attribute value */
+int opt_set; /* set an attribute */
+int opt_remove; /* remove an attribute */
+int opt_restore; /* restore has been run */
+int opt_deref = 1; /* dereference symbolic links */
int had_errors;
const char *progname;
-int do_set(const char *name, const char *value, const char *path);
+int do_set(const char *path, const char *name, const char *value);
const char *decode(const char *value, size_t *size);
-int restore(FILE *file, const char *filename);
+int restore(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)
+const char *strerror_ea(int err)
{
- char *path_p = NULL, *l;
+ if (err == ENOATTR)
+ return _("No such attribute");
+ return strerror(err);
+}
+
+int do_setxattr(const char *path, const char *name,
+ const void *value, size_t size)
+{
+ return (opt_deref ? setxattr : lsetxattr)(path, name, value, size, 0);
+}
+
+int do_removexattr(const char *path, const char *name)
+{
+ return (opt_deref ? removexattr : lremovexattr)(path, name);
+}
+
+int restore(const char *filename)
+{
+ FILE *file;
+ char *path = NULL, *l;
int line = 0, backup_line, status = 0;
+ if (strcmp(filename, "-") == 0)
+ file = stdin;
+ else {
+ file = fopen(filename, "r");
+ if (file == NULL) {
+ fprintf(stderr, "%s: %s: %s\n",
+ progname, filename, strerror_ea(errno));
+ return 1;
+ }
+ }
+
for(;;) {
backup_line = line;
while ((l = next_line(file)) != NULL && *l == '\0')
@@ -65,45 +121,48 @@ int restore(FILE *file, const char *filename)
goto cleanup;
} else
l += 8;
- if (path_p)
- free(path_p);
- path_p = (char *)malloc(strlen(l) + 1);
- if (!path_p) {
+ if (path)
+ free(path);
+ path = (char *)malloc(strlen(l) + 1);
+ if (!path) {
status = 1;
goto cleanup;
}
- strcpy(path_p, l);
+ strcpy(path, l);
while ((l = next_line(file)) != NULL && *l != '\0') {
char *name = l, *value = strchr(l, '=');
line++;
if (value)
*value++ = '\0';
- status = do_set(name, value, path_p);
+ status = do_set(path, name, value);
}
if (l != NULL)
line++;
}
cleanup:
- if (path_p)
- free(path_p);
+ if (path)
+ free(path);
+ if (file != stdin)
+ fclose(file);
+ if (status)
+ had_errors++;
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"));
+ printf(_("Usage: %s %s\n"), progname, CMD_LINE_SPEC);
+ printf(_(
+" -n, --name=name set the value of the named extended attribute\n"
+" -x, --remove=name remove the named extended attribute\n"
+" -v, --value=value use value as the attribute value\n"
+" -h, --no-dereference do not dereference symbolic links\n"
+" --restore=file restore extended attributes\n"
+" --version print version and exit\n"
+" --help this help text\n"));
}
char *next_line(FILE *file)
@@ -123,21 +182,22 @@ char *next_line(FILE *file)
int main(int argc, char *argv[])
{
- FILE *file;
- int status;
+ int opt;
progname = basename(argv[0]);
- while ((optopt = getopt(argc, argv, CMD_LINE_OPTIONS)) != -1) {
- switch(optopt) {
+ while ((opt = getopt_long(argc, argv, CMD_LINE_OPTIONS,
+ long_options, NULL)) != -1) {
+ switch(opt) {
case 'n': /* attribute name */
- if (opt_remove)
+ if (opt_name || opt_remove)
goto synopsis;
opt_name = optarg;
+ opt_set = 1;
break;
- case 'l': /* set attribute on symlink itself */
- opt_symlink = 1;
+ case 'h': /* set attribute on symlink itself */
+ opt_deref = 0;
break;
case 'v': /* attribute value */
@@ -147,37 +207,22 @@ int main(int argc, char *argv[])
break;
case 'x': /* remove attribute */
- if (opt_name)
+ if (opt_name || opt_set)
goto synopsis;
- opt_remove = optarg;
+ opt_name = optarg;
+ opt_remove = 1;
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;
+ restore(optarg);
break;
case 'V':
printf("%s " VERSION "\n", progname);
return 0;
- case 'h':
+ case 'H':
help();
return 0;
@@ -185,15 +230,11 @@ int main(int argc, char *argv[])
goto synopsis;
}
}
- if (((opt_name && opt_remove) || (!opt_name && !opt_remove) ||
- optind >= argc) && !opt_restore)
+ if (!(((opt_remove || opt_set) && optind < argc) || opt_restore))
goto synopsis;
- if (!opt_name) {
- opt_name = opt_remove;
- opt_value = NULL;
- }
+
while (optind < argc) {
- do_set(opt_name, opt_value, argv[optind]);
+ do_set(argv[optind], opt_name, opt_value);
optind++;
}
@@ -201,27 +242,12 @@ int main(int argc, char *argv[])
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);
+ "Try `%s --help' for more information.\n"),
+ progname, CMD_LINE_SPEC, 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)
+int do_set(const char *path, const char *name, const char *value)
{
size_t size = 0;
int error;
@@ -232,10 +258,14 @@ int do_set(const char *name, const char *value, const char *path)
if (!value)
return 1;
}
- error = opt_remove? do_removexattr(path, name):
- do_setxattr(path, name, (void *)value, size);
+ if (opt_set)
+ error = do_setxattr(path, name, value, size);
+ else
+ error = do_removexattr(path, name);
+
if (error < 0) {
- perror(path);
+ fprintf(stderr, "%s: %s: %s\n",
+ progname, path, strerror_ea(errno));
had_errors++;
return 1;
}
@@ -256,7 +286,8 @@ const char *decode(const char *value, size_t *size)
decoded = d = (char *)malloc(*size / 2);
if (!decoded) {
- perror("");
+ fprintf(stderr, "%s: %s\n",
+ progname, strerror_ea(errno));
had_errors++;
return NULL;
}
@@ -289,7 +320,8 @@ const char *decode(const char *value, size_t *size)
decoded = d = (char *)malloc(*size / 4 * 3);
if (!decoded) {
- perror("");
+ fprintf(stderr, "%s: %s\n",
+ progname, strerror_ea(errno));
had_errors++;
return NULL;
}
@@ -360,7 +392,8 @@ const char *decode(const char *value, size_t *size)
decoded = d = (char *)malloc(*size);
if (!decoded) {
- perror("");
+ fprintf(stderr, "%s: %s\n",
+ progname, strerror_ea(errno));
had_errors++;
return NULL;
}