ln.c 2.3 KB

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