ln.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini ln implementation for busybox
  4. *
  5. * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  6. *
  7. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  8. */
  9. /* BB_AUDIT SUSv3 compliant */
  10. /* BB_AUDIT GNU options missing: -d, -F, -i, and -v. */
  11. /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
  12. //usage:#define ln_trivial_usage
  13. //usage: "[OPTIONS] TARGET... LINK|DIR"
  14. //usage:#define ln_full_usage "\n\n"
  15. //usage: "Create a link LINK or DIR/TARGET to the specified TARGET(s)\n"
  16. //usage: "\n -s Make symlinks instead of hardlinks"
  17. //usage: "\n -f Remove existing destinations"
  18. //usage: "\n -n Don't dereference symlinks - treat like normal file"
  19. //usage: "\n -b Make a backup of the target (if exists) before link operation"
  20. //usage: "\n -S suf Use suffix instead of ~ when making backup files"
  21. //usage: "\n -T 2nd arg must be a DIR"
  22. //usage: "\n -v Verbose"
  23. //usage:
  24. //usage:#define ln_example_usage
  25. //usage: "$ ln -s BusyBox /tmp/ls\n"
  26. //usage: "$ ls -l /tmp/ls\n"
  27. //usage: "lrwxrwxrwx 1 root root 7 Apr 12 18:39 ls -> BusyBox*\n"
  28. #include "libbb.h"
  29. /* This is a NOEXEC applet. Be very careful! */
  30. #define LN_SYMLINK (1 << 0)
  31. #define LN_FORCE (1 << 1)
  32. #define LN_NODEREFERENCE (1 << 2)
  33. #define LN_BACKUP (1 << 3)
  34. #define LN_SUFFIX (1 << 4)
  35. #define LN_VERBOSE (1 << 5)
  36. #define LN_LINKFILE (1 << 6)
  37. int ln_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  38. int ln_main(int argc, char **argv)
  39. {
  40. int status = EXIT_SUCCESS;
  41. int opts;
  42. char *last;
  43. char *src_name;
  44. char *src;
  45. char *suffix = (char*)"~";
  46. struct stat statbuf;
  47. int (*link_func)(const char *, const char *);
  48. opt_complementary = "-1"; /* min one arg */
  49. opts = getopt32(argv, "sfnbS:vT", &suffix);
  50. last = argv[argc - 1];
  51. argv += optind;
  52. argc -= optind;
  53. if ((opts & LN_LINKFILE) && argc > 2) {
  54. bb_error_msg_and_die("-T accepts 2 args max");
  55. }
  56. if (!argv[1]) {
  57. /* "ln PATH/TO/FILE" -> "ln PATH/TO/FILE FILE" */
  58. *--argv = last;
  59. /* xstrdup is needed: "ln -s PATH/TO/FILE/" is equivalent to
  60. * "ln -s PATH/TO/FILE/ FILE", not "ln -s PATH/TO/FILE FILE"
  61. */
  62. last = bb_get_last_path_component_strip(xstrdup(last));
  63. }
  64. do {
  65. src_name = NULL;
  66. src = last;
  67. if (is_directory(src,
  68. (opts & LN_NODEREFERENCE) ^ LN_NODEREFERENCE
  69. )
  70. ) {
  71. if (opts & LN_LINKFILE) {
  72. bb_error_msg_and_die("'%s' is a directory", src);
  73. }
  74. src_name = xstrdup(*argv);
  75. src = concat_path_file(src, bb_get_last_path_component_strip(src_name));
  76. free(src_name);
  77. src_name = src;
  78. }
  79. if (!(opts & LN_SYMLINK) && stat(*argv, &statbuf)) {
  80. // coreutils: "ln dangling_symlink new_hardlink" works
  81. if (lstat(*argv, &statbuf) || !S_ISLNK(statbuf.st_mode)) {
  82. bb_simple_perror_msg(*argv);
  83. status = EXIT_FAILURE;
  84. free(src_name);
  85. continue;
  86. }
  87. }
  88. if (opts & LN_BACKUP) {
  89. char *backup;
  90. backup = xasprintf("%s%s", src, suffix);
  91. if (rename(src, backup) < 0 && errno != ENOENT) {
  92. bb_simple_perror_msg(src);
  93. status = EXIT_FAILURE;
  94. free(backup);
  95. continue;
  96. }
  97. free(backup);
  98. /*
  99. * When the source and dest are both hard links to the same
  100. * inode, a rename may succeed even though nothing happened.
  101. * Therefore, always unlink().
  102. */
  103. unlink(src);
  104. } else if (opts & LN_FORCE) {
  105. unlink(src);
  106. }
  107. link_func = link;
  108. if (opts & LN_SYMLINK) {
  109. link_func = symlink;
  110. }
  111. if (opts & LN_VERBOSE) {
  112. printf("'%s' -> '%s'\n", src, *argv);
  113. }
  114. if (link_func(*argv, src) != 0) {
  115. bb_simple_perror_msg(src);
  116. status = EXIT_FAILURE;
  117. }
  118. free(src_name);
  119. } while ((++argv)[1]);
  120. return status;
  121. }