ln.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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 tarball for details.
  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. #include "libbb.h"
  13. /* This is a NOEXEC applet. Be very careful! */
  14. #define LN_SYMLINK 1
  15. #define LN_FORCE 2
  16. #define LN_NODEREFERENCE 4
  17. #define LN_BACKUP 8
  18. #define LN_SUFFIX 16
  19. int ln_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  20. int ln_main(int argc, char **argv)
  21. {
  22. int status = EXIT_SUCCESS;
  23. int opts;
  24. char *last;
  25. char *src_name;
  26. char *src;
  27. char *suffix = (char*)"~";
  28. struct stat statbuf;
  29. int (*link_func)(const char *, const char *);
  30. opt_complementary = "-1"; /* min one arg */
  31. opts = getopt32(argv, "sfnbS:", &suffix);
  32. last = argv[argc - 1];
  33. argv += optind;
  34. if (argc == optind + 1) {
  35. *--argv = last;
  36. last = bb_get_last_path_component_strip(xstrdup(last));
  37. }
  38. do {
  39. src_name = NULL;
  40. src = last;
  41. if (is_directory(src,
  42. (opts & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
  43. NULL)
  44. ) {
  45. src_name = xstrdup(*argv);
  46. src = concat_path_file(src, bb_get_last_path_component_strip(src_name));
  47. free(src_name);
  48. src_name = src;
  49. }
  50. if (!(opts & LN_SYMLINK) && stat(*argv, &statbuf)) {
  51. // coreutils: "ln dangling_symlink new_hardlink" works
  52. if (lstat(*argv, &statbuf) || !S_ISLNK(statbuf.st_mode)) {
  53. bb_simple_perror_msg(*argv);
  54. status = EXIT_FAILURE;
  55. free(src_name);
  56. continue;
  57. }
  58. }
  59. if (opts & LN_BACKUP) {
  60. char *backup;
  61. backup = xasprintf("%s%s", src, suffix);
  62. if (rename(src, backup) < 0 && errno != ENOENT) {
  63. bb_simple_perror_msg(src);
  64. status = EXIT_FAILURE;
  65. free(backup);
  66. continue;
  67. }
  68. free(backup);
  69. /*
  70. * When the source and dest are both hard links to the same
  71. * inode, a rename may succeed even though nothing happened.
  72. * Therefore, always unlink().
  73. */
  74. unlink(src);
  75. } else if (opts & LN_FORCE) {
  76. unlink(src);
  77. }
  78. link_func = link;
  79. if (opts & LN_SYMLINK) {
  80. link_func = symlink;
  81. }
  82. if (link_func(*argv, src) != 0) {
  83. bb_simple_perror_msg(src);
  84. status = EXIT_FAILURE;
  85. }
  86. free(src_name);
  87. } while ((++argv)[1]);
  88. return status;
  89. }