readlink.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini readlink implementation for busybox
  4. *
  5. * Copyright (C) 2000,2001 Matt Kraai <kraai@alumni.carnegiemellon.edu>
  6. *
  7. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  8. */
  9. //config:config READLINK
  10. //config: bool "readlink (4 kb)"
  11. //config: default y
  12. //config: help
  13. //config: This program reads a symbolic link and returns the name
  14. //config: of the file it points to
  15. //config:
  16. //config:config FEATURE_READLINK_FOLLOW
  17. //config: bool "Enable canonicalization by following all symlinks (-f)"
  18. //config: default y
  19. //config: depends on READLINK
  20. //config: help
  21. //config: Enable the readlink option (-f).
  22. //applet:IF_READLINK(APPLET_NOFORK(readlink, readlink, BB_DIR_USR_BIN, BB_SUID_DROP, readlink))
  23. //kbuild:lib-$(CONFIG_READLINK) += readlink.o
  24. //usage:#define readlink_trivial_usage
  25. //usage: IF_FEATURE_READLINK_FOLLOW("[-fnv] ") "FILE"
  26. //usage:#define readlink_full_usage "\n\n"
  27. //usage: "Display the value of a symlink"
  28. //usage: IF_FEATURE_READLINK_FOLLOW( "\n"
  29. //usage: "\n -f Canonicalize by following all symlinks"
  30. //usage: "\n -n Don't add newline"
  31. //usage: "\n -v Verbose"
  32. //usage: )
  33. #include "libbb.h"
  34. /*
  35. * # readlink --version
  36. * readlink (GNU coreutils) 6.10
  37. * # readlink --help
  38. * -f, --canonicalize
  39. * canonicalize by following every symlink in
  40. * every component of the given name recursively;
  41. * all but the last component must exist
  42. * -e, --canonicalize-existing
  43. * canonicalize by following every symlink in
  44. * every component of the given name recursively,
  45. * all components must exist
  46. * -m, --canonicalize-missing
  47. * canonicalize by following every symlink in
  48. * every component of the given name recursively,
  49. * without requirements on components existence
  50. * -n, --no-newline do not output the trailing newline
  51. * -q, --quiet, -s, --silent suppress most error messages
  52. * -v, --verbose report error messages
  53. *
  54. * bbox supports: -f (partially) -n -v (fully), -q -s (accepts but ignores)
  55. * Note: we export the -f flag, but our -f behaves like coreutils' -e.
  56. * Unfortunately, there isn't a C lib function we can leverage to get this
  57. * behavior which means we'd have to implement the full stack ourselves :(.
  58. */
  59. int readlink_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  60. int readlink_main(int argc UNUSED_PARAM, char **argv)
  61. {
  62. char *buf;
  63. char *fname;
  64. IF_FEATURE_READLINK_FOLLOW(
  65. unsigned opt;
  66. /* We need exactly one non-option argument. */
  67. opt = getopt32(argv, "^" "fnvsq" "\0" "=1");
  68. fname = argv[optind];
  69. )
  70. IF_NOT_FEATURE_READLINK_FOLLOW(
  71. const unsigned opt = 0;
  72. if (argc != 2) bb_show_usage();
  73. fname = argv[1];
  74. )
  75. /* compat: coreutils readlink reports errors silently via exit code */
  76. if (!(opt & 4)) /* not -v */
  77. logmode = LOGMODE_NONE;
  78. /* NOFORK: only one alloc is allowed; must free */
  79. if (opt & 1) { /* -f */
  80. buf = xmalloc_realpath_coreutils(fname);
  81. } else {
  82. buf = xmalloc_readlink_or_warn(fname);
  83. }
  84. if (!buf)
  85. return EXIT_FAILURE;
  86. printf((opt & 2) ? "%s" : "%s\n", buf);
  87. free(buf);
  88. fflush_stdout_and_exit(EXIT_SUCCESS);
  89. }