1 /* getfattr.c - Read POSIX extended attributes. 2 * 3 * Copyright 2016 Android Open Source Project. 4 * 5 * No standard 6 7 USE_GETFATTR(NEWTOY(getfattr, "(only-values)dhn:", TOYFLAG_USR|TOYFLAG_BIN)) 8 9 config GETFATTR 10 bool "getfattr" 11 default n 12 help 13 usage: getfattr [-d] [-h] [-n NAME] FILE... 14 15 Read POSIX extended attributes. 16 17 -d Show values as well as names 18 -h Do not dereference symbolic links 19 -n Show only attributes with the given name 20 --only-values Don't show names 21 */ 22 23 #define FOR_getfattr 24 #include "toys.h" 25 26 GLOBALS( 27 char *n; 28 ) 29 30 // TODO: factor out the lister and getter loops and use them in cp too. 31 static void do_getfattr(char *file) 32 { 33 ssize_t (*getter)(const char *, const char *, void *, size_t) = getxattr; 34 ssize_t (*lister)(const char *, char *, size_t) = listxattr; 35 char **sorted_keys; 36 ssize_t keys_len; 37 char *keys, *key; 38 int i, key_count; 39 40 if (FLAG(h)) { 41 getter = lgetxattr; 42 lister = llistxattr; 43 } 44 45 // Collect the keys. 46 while ((keys_len = lister(file, NULL, 0))) { 47 if (keys_len == -1) perror_msg("listxattr failed"); 48 keys = xmalloc(keys_len); 49 if (lister(file, keys, keys_len) == keys_len) break; 50 free(keys); 51 } 52 53 if (keys_len == 0) return; 54 55 // Sort the keys. 56 for (key = keys, key_count = 0; key-keys < keys_len; key += strlen(key)+1) 57 key_count++; 58 sorted_keys = xmalloc(key_count * sizeof(char *)); 59 for (key = keys, i = 0; key-keys < keys_len; key += strlen(key)+1) 60 sorted_keys[i++] = key; 61 qsort(sorted_keys, key_count, sizeof(char *), qstrcmp); 62 63 if (!FLAG(only_values)) printf("# file: %s\n", file); 64 65 for (i = 0; i < key_count; i++) { 66 key = sorted_keys[i]; 67 68 if (TT.n && strcmp(TT.n, key)) continue; 69 70 if (FLAG(d) || FLAG(only_values)) { 71 ssize_t value_len; 72 char *value = NULL; 73 74 while ((value_len = getter(file, key, NULL, 0))) { 75 if (value_len == -1) perror_msg("getxattr failed"); 76 value = xzalloc(value_len+1); 77 if (getter(file, key, value, value_len) == value_len) break; 78 free(value); 79 } 80 81 if (FLAG(only_values)) { 82 if (value) printf("%s", value); 83 } else if (!value) puts(key); 84 else printf("%s=\"%s\"\n", key, value); 85 free(value); 86 } else puts(key); // Just list names. 87 } 88 89 if (!FLAG(only_values)) xputc('\n'); 90 free(sorted_keys); 91 } 92 93 void getfattr_main(void) 94 { 95 char **s; 96 97 for (s=toys.optargs; *s; s++) do_getfattr(*s); 98 } 99