diff options
author | Elliott Hughes <enh@google.com> | 2016-07-17 10:42:31 -0700 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2016-07-18 14:14:22 -0500 |
commit | bd471f67cc6eff4abf47f027edbace707065bc6b (patch) | |
tree | 2c7e2c3edcca3a588b650d33c115d9335c09b163 /toys/pending | |
parent | 48ea55969907286d1a125fcd655be9d8307a3449 (diff) | |
download | toybox-bd471f67cc6eff4abf47f027edbace707065bc6b.tar.gz |
Add getfattr(1) and setfattr(1).
Plus basic tests.
Diffstat (limited to 'toys/pending')
-rw-r--r-- | toys/pending/getfattr.c | 95 | ||||
-rw-r--r-- | toys/pending/setfattr.c | 56 |
2 files changed, 151 insertions, 0 deletions
diff --git a/toys/pending/getfattr.c b/toys/pending/getfattr.c new file mode 100644 index 00000000..efec53a8 --- /dev/null +++ b/toys/pending/getfattr.c @@ -0,0 +1,95 @@ +/* getfattr.c - Read POSIX extended attributes. + * + * Copyright 2016 Android Open Source Project. + * + * No standard + +USE_GETFATTR(NEWTOY(getfattr, "dhn:", TOYFLAG_USR|TOYFLAG_BIN)) + +config GETFATTR + bool "getfattr" + default y + help + usage: getfattr [-d] [-h] [-n NAME] FILE... + + Read POSIX extended attributes. + + -d Show values as well as names. + -h Do not dereference symbolic links. + -n Show only attributes with the given name. +*/ + +#define FOR_getfattr +#include "toys.h" + +GLOBALS( + char *n; +) + +// TODO: factor out the lister and getter loops and use them in cp too. +static void do_getfattr(char *file) +{ + ssize_t (*getter)(const char *, const char *, void *, size_t) = getxattr; + ssize_t (*lister)(const char *, char *, size_t) = listxattr; + char **sorted_keys; + ssize_t keys_len; + char *keys, *key; + int i, key_count; + + if (toys.optflags&FLAG_h) { + getter = lgetxattr; + lister = llistxattr; + } + + // Collect the keys. + while ((keys_len = lister(file, NULL, 0))) { + if (keys_len == -1) perror_msg("listxattr failed"); + keys = xmalloc(keys_len); + if (lister(file, keys, keys_len) == keys_len) break; + free(keys); + } + + if (keys_len == 0) return; + + // Sort the keys. + for (key = keys, key_count = 0; key-keys < keys_len; key += strlen(key)+1) + key_count++; + sorted_keys = xmalloc(key_count * sizeof(char *)); + for (key = keys, i = 0; key-keys < keys_len; key += strlen(key)+1) + sorted_keys[i++] = key; + qsort(sorted_keys, key_count, sizeof(char *), qstrcmp); + + printf("# file: %s\n", file); + + for (i = 0; i < key_count; i++) { + key = sorted_keys[i]; + + if (TT.n && strcmp(TT.n, key)) continue; + + if (toys.optflags&FLAG_d) { + ssize_t value_len; + char *value = NULL; + + while ((value_len = getter(file, key, NULL, 0))) { + if (value_len == -1) perror_msg("getxattr failed"); + value = xzalloc(value_len+1); + if (getter(file, key, value, value_len) == value_len) break; + free(value); + } + + if (!value) puts(key); + else printf("%s=\"%s\"\n", key, value); + free(value); + } else puts(key); // Just list names. + } + + xputc('\n'); + free(sorted_keys); +} + +void getfattr_main(void) +{ + char **s; + + for (s=toys.optargs; *s; s++) do_getfattr(*s); +} diff --git a/toys/pending/setfattr.c b/toys/pending/setfattr.c new file mode 100644 index 00000000..9f17ce05 --- /dev/null +++ b/toys/pending/setfattr.c @@ -0,0 +1,56 @@ +/* setfattr.c - Write POSIX extended attributes. + * + * Copyright 2016 Android Open Source Project. + * + * No standard + +USE_SETFATTR(NEWTOY(setfattr, "hn:v:x:[!xv]", TOYFLAG_USR|TOYFLAG_BIN)) + +config SETFATTR + bool "setfattr" + default y + help + usage: setfattr [-h] -n NAME [-v VALUE] FILE... + usage: setfattr [-h] -x NAME FILE... + + Write POSIX extended attributes. + + -h Do not dereference symbolic links. + -n Set value of given attribute. + -x Remove value of given attribute. + -v Value to use with -n (default is empty). +*/ + +#define FOR_setfattr +#include "toys.h" + +GLOBALS( + char *x, *v, *n; +) + +static void do_setfattr(char *file) +{ + int (*setter)(const char *, const char *, const void *, size_t, int) = + setxattr; + int (*remover)(const char *, const char *) = removexattr; + + if (toys.optflags&FLAG_h) { + setter = lsetxattr; + remover = lremovexattr; + } + + if (toys.optflags&FLAG_x) { + if (remover(file, TT.x)) perror_msg("removexattr failed"); + } else { + if (setter(file, TT.n, TT.v, TT.v ? strlen(TT.v) : 0, 0)) + perror_msg("setxattr failed"); + } +} + +void setfattr_main(void) +{ + char **s; + + if (!(toys.optflags&(FLAG_n|FLAG_x))) error_exit("need 'n' or 'x'"); + for (s=toys.optargs; *s; s++) do_setfattr(*s); +} |