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