3
0

ln.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  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);
  20. int ln_main(int argc, char **argv)
  21. {
  22. int status = EXIT_SUCCESS;
  23. int flag;
  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. flag = getopt32(argv, "sfnbS:", &suffix);
  31. if (argc == optind) {
  32. bb_show_usage();
  33. }
  34. last = argv[argc - 1];
  35. argv += optind;
  36. if (argc == optind + 1) {
  37. *--argv = last;
  38. last = bb_get_last_path_component(xstrdup(last));
  39. }
  40. do {
  41. src_name = NULL;
  42. src = last;
  43. if (is_directory(src,
  44. (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
  45. NULL)
  46. ) {
  47. src_name = xstrdup(*argv);
  48. src = concat_path_file(src, bb_get_last_path_component(src_name));
  49. free(src_name);
  50. src_name = src;
  51. }
  52. if (!(flag & LN_SYMLINK) && stat(*argv, &statbuf)) {
  53. // coreutils: "ln dangling_symlink new_hardlink" works
  54. if (lstat(*argv, &statbuf) || !S_ISLNK(statbuf.st_mode)) {
  55. bb_perror_msg("%s", *argv);
  56. status = EXIT_FAILURE;
  57. free(src_name);
  58. continue;
  59. }
  60. }
  61. if (flag & LN_BACKUP) {
  62. char *backup;
  63. backup = xasprintf("%s%s", src, suffix);
  64. if (rename(src, backup) < 0 && errno != ENOENT) {
  65. bb_perror_msg("%s", src);
  66. status = EXIT_FAILURE;
  67. free(backup);
  68. continue;
  69. }
  70. free(backup);
  71. /*
  72. * When the source and dest are both hard links to the same
  73. * inode, a rename may succeed even though nothing happened.
  74. * Therefore, always unlink().
  75. */
  76. unlink(src);
  77. } else if (flag & LN_FORCE) {
  78. unlink(src);
  79. }
  80. link_func = link;
  81. if (flag & LN_SYMLINK) {
  82. link_func = symlink;
  83. }
  84. if (link_func(*argv, src) != 0) {
  85. bb_perror_msg("%s", src);
  86. status = EXIT_FAILURE;
  87. }
  88. free(src_name);
  89. } while ((++argv)[1]);
  90. return status;
  91. }