aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/getfattr.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/miscutils/getfattr.c b/miscutils/getfattr.c
new file mode 100644
index 000000000..59b6f6bca
--- /dev/null
+++ b/miscutils/getfattr.c
@@ -0,0 +1,131 @@
1/*
2 * getfattr - get extended attributes of filesystem objects.
3 *
4 * Copyright (C) 2023 by LoveSy <lovesykun@gmail.com>
5 *
6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */
8//config:config GETFATTR
9//config: bool "getfattr (12.3 kb)"
10//config: default y
11//config: help
12//config: Get extended attributes on files
13
14//applet:IF_GETFATTR(APPLET_NOEXEC(getfattr, getfattr, BB_DIR_USR_BIN, BB_SUID_DROP, getfattr))
15
16//kbuild:lib-$(CONFIG_GETFATTR) += getfattr.o
17
18#include <stdio.h>
19#include <sys/xattr.h>
20#include "libbb.h"
21
22//usage:#define getfattr_trivial_usage
23//usage: "[-h] {-d|-n ATTR} FILE...\n"
24//usage:#define getfattr_full_usage "\n\n"
25//usage: "Get extended attributes"
26//usage: "\n"
27//usage: "\n -h Do not follow symlinks"
28//usage: "\n -d Dump all attributes"
29//usage: "\n -n ATTR Get attribute ATTR"
30
31enum {
32 OPT_h = (1 << 0),
33 OPT_d = (1 << 1),
34};
35
36static int print_attr(const char *file, const char *name, char **buf, size_t *bufsize)
37{
38 ssize_t len;
39
40 if (*bufsize == 0)
41 goto grow;
42 again:
43 len = ((option_mask32 & OPT_h) ? lgetxattr: getxattr)(file, name, *buf, *bufsize);
44 if (len < 0) {
45 if (errno != ERANGE)
46 return len;
47 grow:
48 *bufsize = (*bufsize * 2) + 1024;
49 *buf = xrealloc(*buf, *bufsize);
50 goto again;
51 }
52 printf("%s=\"%.*s\"\n", name, len, *buf);
53 return 0;
54}
55
56static ssize_t list_attr(const char *file, char **list, size_t *listsize)
57{
58 ssize_t len;
59
60 if (*listsize == 0)
61 goto grow;
62 again:
63 len = ((option_mask32 & OPT_h) ? llistxattr : listxattr)(file, *list, *listsize);
64 if (len < 0) {
65 if (errno != ERANGE)
66 return len;
67 grow:
68 *listsize = (*listsize * 2) + 1024;
69 *list = xrealloc(*list, *listsize);
70 goto again;
71 }
72 return len;
73}
74
75int getfattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
76int getfattr_main(int argc UNUSED_PARAM, char **argv)
77{
78 const char *name;
79 int status;
80 int opt;
81 char *buf = NULL;
82 size_t bufsize = 0;
83 char *list = NULL;
84 size_t listsize = 0;
85
86 opt = getopt32(argv, "^"
87 "hdn:"
88 /* Min one arg; exactly one of -n or -d is required. */
89 "\0" "-1:d:n:n--d:d--n"
90 , &name
91 );
92 argv += optind;
93 status = EXIT_SUCCESS;
94
95 do {
96 int r;
97 if (opt & OPT_d) {
98 ssize_t len = list_attr(*argv, &list, &listsize);
99 if (len > 0) {
100 char *key;
101 printf("# file: %s\n", *argv);
102 key = list;
103 while (len > 0) {
104 ssize_t keylen;
105 r = print_attr(*argv, key, &buf, &bufsize);
106 if (r)
107 goto err;
108 keylen = strlen(key) + 1;
109 key += keylen;
110 len -= keylen;
111 }
112 bb_putchar('\n');
113 }
114 } else {
115 printf("# file: %s\n", *argv);
116 r = print_attr(*argv, name, &buf, &bufsize);
117 if (r) {
118 err:
119 bb_simple_perror_msg(*argv);
120 status = EXIT_FAILURE;
121 // continue; maybe?
122 }
123 bb_putchar('\n');
124 }
125 } while (*++argv);
126
127 if (ENABLE_FEATURE_CLEAN_UP)
128 free(buf);
129
130 fflush_stdout_and_exit(status);
131}