cut: code shrink
[busybox-git.git] / miscutils / getfattr.c
blobcb42fdac0a5a9ef17d80eb1f1647962896948121
1 /*
2 * getfattr - get extended attributes of filesystem objects.
4 * Copyright (C) 2023 by LoveSy <lovesykun@gmail.com>
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
14 //applet:IF_GETFATTR(APPLET_NOEXEC(getfattr, getfattr, BB_DIR_USR_BIN, BB_SUID_DROP, getfattr))
16 //kbuild:lib-$(CONFIG_GETFATTR) += getfattr.o
18 #include <stdio.h>
19 #include <sys/xattr.h>
20 #include "libbb.h"
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"
31 enum {
32 OPT_h = (1 << 0),
33 OPT_d = (1 << 1),
34 OPT_n = (1 << 2),
37 static int print_attr(const char *file, const char *name, char **buf, size_t *bufsize)
39 ssize_t len;
41 if (*bufsize == 0)
42 goto grow;
43 again:
44 len = ((option_mask32 & OPT_h) ? lgetxattr: getxattr)(file, name, *buf, *bufsize);
45 if (len < 0) {
46 if (errno != ERANGE)
47 return len;
48 grow:
49 *bufsize = (*bufsize * 2) + 1024;
50 *buf = xrealloc(*buf, *bufsize);
51 goto again;
53 printf("%s=\"%.*s\"\n", name, len, *buf);
54 return 0;
57 static ssize_t list_attr(const char *file, char **list, size_t *listsize)
59 ssize_t len;
61 if (*listsize == 0)
62 goto grow;
63 again:
64 len = ((option_mask32 & OPT_h) ? llistxattr : listxattr)(file, *list, *listsize);
65 if (len < 0) {
66 if (errno != ERANGE)
67 return len;
68 grow:
69 *listsize = (*listsize * 2) + 1024;
70 *list = xrealloc(*list, *listsize);
71 goto again;
73 return len;
76 int getfattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
77 int getfattr_main(int argc UNUSED_PARAM, char **argv)
79 const char *name;
80 exitcode_t status;
81 int opt;
82 char *buf = NULL;
83 size_t bufsize = 0;
84 char *list = NULL;
85 size_t listsize = 0;
87 opt = getopt32(argv, "^"
88 "hdn:"
89 /* Min one arg; -d and -n are exclusive */
90 "\0" "-1:n--d:d--n"
91 //getfattr 2.5.1 does not enforce this: ":d:n" /* exactly one of -n or -d is required */
92 , &name
94 argv += optind;
95 status = EXIT_SUCCESS;
97 do {
98 int r;
99 //getfattr 2.5.1 with no -n/-d defaults to -d
100 if (!(opt & OPT_n)) {
101 ssize_t len = list_attr(*argv, &list, &listsize);
102 if (len < 0)
103 goto err;
104 if (len > 0) {
105 char *key;
106 printf("# file: %s\n", *argv);
107 key = list;
108 while (len > 0) {
109 ssize_t keylen;
110 r = print_attr(*argv, key, &buf, &bufsize);
111 if (r)
112 goto err;
113 keylen = strlen(key) + 1;
114 key += keylen;
115 len -= keylen;
117 bb_putchar('\n');
119 } else {
120 printf("# file: %s\n", *argv);
121 r = print_attr(*argv, name, &buf, &bufsize);
122 if (r) {
123 err:
124 bb_simple_perror_msg(*argv);
125 status = EXIT_FAILURE;
126 continue;
128 bb_putchar('\n');
130 } while (*++argv);
132 if (ENABLE_FEATURE_CLEAN_UP)
133 free(buf);
135 fflush_stdout_and_exit(status);