10f66f451Sopenharmony_ci/* getfattr.c - Read POSIX extended attributes. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2016 Android Open Source Project. 40f66f451Sopenharmony_ci * 50f66f451Sopenharmony_ci * No standard 60f66f451Sopenharmony_ci 70f66f451Sopenharmony_ciUSE_GETFATTR(NEWTOY(getfattr, "(only-values)dhn:", TOYFLAG_USR|TOYFLAG_BIN)) 80f66f451Sopenharmony_ci 90f66f451Sopenharmony_ciconfig GETFATTR 100f66f451Sopenharmony_ci bool "getfattr" 110f66f451Sopenharmony_ci default n 120f66f451Sopenharmony_ci help 130f66f451Sopenharmony_ci usage: getfattr [-d] [-h] [-n NAME] FILE... 140f66f451Sopenharmony_ci 150f66f451Sopenharmony_ci Read POSIX extended attributes. 160f66f451Sopenharmony_ci 170f66f451Sopenharmony_ci -d Show values as well as names 180f66f451Sopenharmony_ci -h Do not dereference symbolic links 190f66f451Sopenharmony_ci -n Show only attributes with the given name 200f66f451Sopenharmony_ci --only-values Don't show names 210f66f451Sopenharmony_ci*/ 220f66f451Sopenharmony_ci 230f66f451Sopenharmony_ci#define FOR_getfattr 240f66f451Sopenharmony_ci#include "toys.h" 250f66f451Sopenharmony_ci 260f66f451Sopenharmony_ciGLOBALS( 270f66f451Sopenharmony_ci char *n; 280f66f451Sopenharmony_ci) 290f66f451Sopenharmony_ci 300f66f451Sopenharmony_ci// TODO: factor out the lister and getter loops and use them in cp too. 310f66f451Sopenharmony_cistatic void do_getfattr(char *file) 320f66f451Sopenharmony_ci{ 330f66f451Sopenharmony_ci ssize_t (*getter)(const char *, const char *, void *, size_t) = getxattr; 340f66f451Sopenharmony_ci ssize_t (*lister)(const char *, char *, size_t) = listxattr; 350f66f451Sopenharmony_ci char **sorted_keys; 360f66f451Sopenharmony_ci ssize_t keys_len; 370f66f451Sopenharmony_ci char *keys, *key; 380f66f451Sopenharmony_ci int i, key_count; 390f66f451Sopenharmony_ci 400f66f451Sopenharmony_ci if (FLAG(h)) { 410f66f451Sopenharmony_ci getter = lgetxattr; 420f66f451Sopenharmony_ci lister = llistxattr; 430f66f451Sopenharmony_ci } 440f66f451Sopenharmony_ci 450f66f451Sopenharmony_ci // Collect the keys. 460f66f451Sopenharmony_ci while ((keys_len = lister(file, NULL, 0))) { 470f66f451Sopenharmony_ci if (keys_len == -1) perror_msg("listxattr failed"); 480f66f451Sopenharmony_ci keys = xmalloc(keys_len); 490f66f451Sopenharmony_ci if (lister(file, keys, keys_len) == keys_len) break; 500f66f451Sopenharmony_ci free(keys); 510f66f451Sopenharmony_ci } 520f66f451Sopenharmony_ci 530f66f451Sopenharmony_ci if (keys_len == 0) return; 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_ci // Sort the keys. 560f66f451Sopenharmony_ci for (key = keys, key_count = 0; key-keys < keys_len; key += strlen(key)+1) 570f66f451Sopenharmony_ci key_count++; 580f66f451Sopenharmony_ci sorted_keys = xmalloc(key_count * sizeof(char *)); 590f66f451Sopenharmony_ci for (key = keys, i = 0; key-keys < keys_len; key += strlen(key)+1) 600f66f451Sopenharmony_ci sorted_keys[i++] = key; 610f66f451Sopenharmony_ci qsort(sorted_keys, key_count, sizeof(char *), qstrcmp); 620f66f451Sopenharmony_ci 630f66f451Sopenharmony_ci if (!FLAG(only_values)) printf("# file: %s\n", file); 640f66f451Sopenharmony_ci 650f66f451Sopenharmony_ci for (i = 0; i < key_count; i++) { 660f66f451Sopenharmony_ci key = sorted_keys[i]; 670f66f451Sopenharmony_ci 680f66f451Sopenharmony_ci if (TT.n && strcmp(TT.n, key)) continue; 690f66f451Sopenharmony_ci 700f66f451Sopenharmony_ci if (FLAG(d) || FLAG(only_values)) { 710f66f451Sopenharmony_ci ssize_t value_len; 720f66f451Sopenharmony_ci char *value = NULL; 730f66f451Sopenharmony_ci 740f66f451Sopenharmony_ci while ((value_len = getter(file, key, NULL, 0))) { 750f66f451Sopenharmony_ci if (value_len == -1) perror_msg("getxattr failed"); 760f66f451Sopenharmony_ci value = xzalloc(value_len+1); 770f66f451Sopenharmony_ci if (getter(file, key, value, value_len) == value_len) break; 780f66f451Sopenharmony_ci free(value); 790f66f451Sopenharmony_ci } 800f66f451Sopenharmony_ci 810f66f451Sopenharmony_ci if (FLAG(only_values)) { 820f66f451Sopenharmony_ci if (value) printf("%s", value); 830f66f451Sopenharmony_ci } else if (!value) puts(key); 840f66f451Sopenharmony_ci else printf("%s=\"%s\"\n", key, value); 850f66f451Sopenharmony_ci free(value); 860f66f451Sopenharmony_ci } else puts(key); // Just list names. 870f66f451Sopenharmony_ci } 880f66f451Sopenharmony_ci 890f66f451Sopenharmony_ci if (!FLAG(only_values)) xputc('\n'); 900f66f451Sopenharmony_ci free(sorted_keys); 910f66f451Sopenharmony_ci} 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_civoid getfattr_main(void) 940f66f451Sopenharmony_ci{ 950f66f451Sopenharmony_ci char **s; 960f66f451Sopenharmony_ci 970f66f451Sopenharmony_ci for (s=toys.optargs; *s; s++) do_getfattr(*s); 980f66f451Sopenharmony_ci} 99