Patch from Matthew S. Wood:
authorRob Landley <rob@landley.net>
Fri, 29 Apr 2005 22:13:04 +0000 (22:13 -0000)
committerRob Landley <rob@landley.net>
Fri, 29 Apr 2005 22:13:04 +0000 (22:13 -0000)
> The following patch adds support for the -S and -b flags to `ln'.  These
> flags [especially -b] are used extensively in Debian pre and post
> installation scripts.

Comments from Vladimir Oleynik influenced the final patch, and I also ripped
out the in-file changelog since it belongs here.  At the time, it said:

/* Apr 15, 2004      Matthew S. Wood    (mwood@realmsys.com)
 *
 * Implement '-b' (backup) flag.
 * Implement '-S' (backup suffix) flag.
 *
 *
 * Mar 16, 2003      Manuel Novoa III   (mjn3@codepoet.org)
 *
 * Fixed bug involving -n option.  Essentially, -n was always in effect.
 */

coreutils/ln.c

index 885ba61dbd9c3febc70fbb51605135f8cd077042..274e0d06cbbae8abb3566a8346f2a376c309b0cf 100644 (file)
  */
 
 /* BB_AUDIT SUSv3 compliant */
-/* BB_AUDIT GNU options missing: -b, -d, -F, -i, -S, and -v. */
+/* BB_AUDIT GNU options missing: -d, -F, -i, and -v. */
 /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
 
-/* Mar 16, 2003      Manuel Novoa III   (mjn3@codepoet.org)
- *
- * Fixed bug involving -n option.  Essentially, -n was always in effect.
- */
-
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <errno.h>
 #include "busybox.h"
 
 #define LN_SYMLINK          1
 #define LN_FORCE            2
 #define LN_NODEREFERENCE    4
+#define LN_BACKUP           8
+#define LN_SUFFIX           16
 
 extern int ln_main(int argc, char **argv)
 {
@@ -44,10 +43,11 @@ extern int ln_main(int argc, char **argv)
        char *last;
        char *src_name;
        char *src;
+       char *suffix = "~";
        struct stat statbuf;
        int (*link_func)(const char *, const char *);
 
-       flag = bb_getopt_ulflags(argc, argv, "sfn");
+       flag = bb_getopt_ulflags(argc, argv, "sfnbS:", &suffix);
 
        if (argc == optind) {
                bb_show_usage();
@@ -80,7 +80,23 @@ extern int ln_main(int argc, char **argv)
                        continue;
                }
 
-               if (flag & LN_FORCE) {
+               if (flag & LN_BACKUP) {
+                               char *backup = NULL;
+                               bb_xasprintf(&backup, "%s%s", src, suffix);
+                               if (rename(src, backup) < 0 && errno != ENOENT) {
+                                               bb_perror_msg(src);
+                                               status = EXIT_FAILURE;
+                                               free(backup);
+                                               continue;
+                               }
+                               free(backup);
+                               /*
+                                * When the source and dest are both hard links to the same
+                                * inode, a rename may succeed even though nothing happened.
+                                * Therefore, always unlink().
+                                */
+                               unlink(src);
+               } else if (flag & LN_FORCE) {
                        unlink(src);
                }