| /* 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 n |
| 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); |
| } |