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