getfattr.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. //applet:IF_GETFATTR(APPLET_NOEXEC(getfattr, getfattr, BB_DIR_USR_BIN, BB_SUID_DROP, getfattr))
  14. //kbuild:lib-$(CONFIG_GETFATTR) += getfattr.o
  15. #include <stdio.h>
  16. #include <sys/xattr.h>
  17. #include "libbb.h"
  18. //usage:#define getfattr_trivial_usage
  19. //usage: "[-h] {-d|-n ATTR} FILE...\n"
  20. //usage:#define getfattr_full_usage "\n\n"
  21. //usage: "Get extended attributes"
  22. //usage: "\n"
  23. //usage: "\n -h Do not follow symlinks"
  24. //usage: "\n -d Dump all attributes"
  25. //usage: "\n -n ATTR Get attribute ATTR"
  26. enum {
  27. OPT_h = (1 << 0),
  28. OPT_d = (1 << 1),
  29. OPT_n = (1 << 2),
  30. };
  31. static int print_attr(const char *file, const char *name, char **buf, size_t *bufsize)
  32. {
  33. ssize_t len;
  34. if (*bufsize == 0)
  35. goto grow;
  36. again:
  37. len = ((option_mask32 & OPT_h) ? lgetxattr: getxattr)(file, name, *buf, *bufsize);
  38. if (len < 0) {
  39. if (errno != ERANGE)
  40. return len;
  41. grow:
  42. *bufsize = (*bufsize * 2) + 1024;
  43. *buf = xrealloc(*buf, *bufsize);
  44. goto again;
  45. }
  46. printf("%s=\"%.*s\"\n", name, len, *buf);
  47. return 0;
  48. }
  49. static ssize_t list_attr(const char *file, char **list, size_t *listsize)
  50. {
  51. ssize_t len;
  52. if (*listsize == 0)
  53. goto grow;
  54. again:
  55. len = ((option_mask32 & OPT_h) ? llistxattr : listxattr)(file, *list, *listsize);
  56. if (len < 0) {
  57. if (errno != ERANGE)
  58. return len;
  59. grow:
  60. *listsize = (*listsize * 2) + 1024;
  61. *list = xrealloc(*list, *listsize);
  62. goto again;
  63. }
  64. return len;
  65. }
  66. int getfattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  67. int getfattr_main(int argc UNUSED_PARAM, char **argv)
  68. {
  69. const char *name;
  70. exitcode_t status;
  71. int opt;
  72. char *buf = NULL;
  73. size_t bufsize = 0;
  74. char *list = NULL;
  75. size_t listsize = 0;
  76. opt = getopt32(argv, "^"
  77. "hdn:"
  78. /* Min one arg; -d and -n are exclusive */
  79. "\0" "-1:n--d:d--n"
  80. //getfattr 2.5.1 does not enforce this: ":d:n" /* exactly one of -n or -d is required */
  81. , &name
  82. );
  83. argv += optind;
  84. status = EXIT_SUCCESS;
  85. do {
  86. int r;
  87. //getfattr 2.5.1 with no -n/-d defaults to -d
  88. if (!(opt & OPT_n)) {
  89. ssize_t len = list_attr(*argv, &list, &listsize);
  90. if (len < 0)
  91. goto err;
  92. if (len > 0) {
  93. char *key;
  94. printf("# file: %s\n", *argv);
  95. key = list;
  96. while (len > 0) {
  97. ssize_t keylen;
  98. r = print_attr(*argv, key, &buf, &bufsize);
  99. if (r)
  100. goto err;
  101. keylen = strlen(key) + 1;
  102. key += keylen;
  103. len -= keylen;
  104. }
  105. bb_putchar('\n');
  106. }
  107. } else {
  108. printf("# file: %s\n", *argv);
  109. r = print_attr(*argv, name, &buf, &bufsize);
  110. if (r) {
  111. err:
  112. bb_simple_perror_msg(*argv);
  113. status = EXIT_FAILURE;
  114. continue;
  115. }
  116. bb_putchar('\n');
  117. }
  118. } while (*++argv);
  119. if (ENABLE_FEATURE_CLEAN_UP)
  120. free(buf);
  121. fflush_stdout_and_exit(status);
  122. }