1 /* vi: set sw=4 ts=4: */
3 * Mini ln implementation for busybox
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
10 /* BB_AUDIT SUSv3 compliant */
11 /* BB_AUDIT GNU options missing: -d, -F, -i, and -v. */
12 /* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
14 //usage:#define ln_trivial_usage
15 //usage: "[OPTIONS] TARGET... LINK|DIR"
16 //usage:#define ln_full_usage "\n\n"
17 //usage: "Create a link LINK or DIR/TARGET to the specified TARGET(s)\n"
18 //usage: "\n -s Make symlinks instead of hardlinks"
19 //usage: "\n -f Remove existing destinations"
20 //usage: "\n -n Don't dereference symlinks - treat like normal file"
21 //usage: "\n -b Make a backup of the target (if exists) before link operation"
22 //usage: "\n -S suf Use suffix instead of ~ when making backup files"
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"
31 /* This is a NOEXEC applet. Be very careful! */
36 #define LN_NODEREFERENCE 4
40 int ln_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
41 int ln_main(int argc
, char **argv
)
43 int status
= EXIT_SUCCESS
;
48 char *suffix
= (char*)"~";
50 int (*link_func
)(const char *, const char *);
52 opt_complementary
= "-1"; /* min one arg */
53 opts
= getopt32(argv
, "sfnbS:", &suffix
);
55 last
= argv
[argc
- 1];
59 /* "ln PATH/TO/FILE" -> "ln PATH/TO/FILE FILE" */
61 /* xstrdup is needed: "ln -s PATH/TO/FILE/" is equivalent to
62 * "ln -s PATH/TO/FILE/ FILE", not "ln -s PATH/TO/FILE FILE"
64 last
= bb_get_last_path_component_strip(xstrdup(last
));
72 (opts
& LN_NODEREFERENCE
) ^ LN_NODEREFERENCE
75 src_name
= xstrdup(*argv
);
76 src
= concat_path_file(src
, bb_get_last_path_component_strip(src_name
));
80 if (!(opts
& LN_SYMLINK
) && stat(*argv
, &statbuf
)) {
81 // coreutils: "ln dangling_symlink new_hardlink" works
82 if (lstat(*argv
, &statbuf
) || !S_ISLNK(statbuf
.st_mode
)) {
83 bb_simple_perror_msg(*argv
);
84 status
= EXIT_FAILURE
;
90 if (opts
& LN_BACKUP
) {
92 backup
= xasprintf("%s%s", src
, suffix
);
93 if (rename(src
, backup
) < 0 && errno
!= ENOENT
) {
94 bb_simple_perror_msg(src
);
95 status
= EXIT_FAILURE
;
101 * When the source and dest are both hard links to the same
102 * inode, a rename may succeed even though nothing happened.
103 * Therefore, always unlink().
106 } else if (opts
& LN_FORCE
) {
111 if (opts
& LN_SYMLINK
) {
115 if (link_func(*argv
, src
) != 0) {
116 bb_simple_perror_msg(src
);
117 status
= EXIT_FAILURE
;
122 } while ((++argv
)[1]);