Page MenuHomeFreeBSD

D44635.diff
No OneTemporary

D44635.diff

diff --git a/bin/ln/ln.c b/bin/ln/ln.c
--- a/bin/ln/ln.c
+++ b/bin/ln/ln.c
@@ -55,13 +55,14 @@
static char linkch;
static int linkit(const char *, const char *, bool);
+static void link_usage(void) __dead2;
static void usage(void) __dead2;
int
main(int argc, char *argv[])
{
struct stat sb;
- char *p, *targetdir;
+ char *targetdir;
int ch, exitval;
/*
@@ -69,17 +70,20 @@
* "link", for which the functionality provided is greatly
* simplified.
*/
- if ((p = strrchr(argv[0], '/')) == NULL)
- p = argv[0];
- else
- ++p;
- if (strcmp(p, "link") == 0) {
+ if (strcmp(getprogname(), "link") == 0) {
while (getopt(argc, argv, "") != -1)
- usage();
+ link_usage();
argc -= optind;
argv += optind;
if (argc != 2)
- usage();
+ link_usage();
+ if (lstat(argv[1], &sb) == 0)
+ errc(1, EEXIST, "%s", argv[1]);
+ /*
+ * We could simply call link(2) here, but linkit()
+ * performs additional checks and gives better
+ * diagnostics.
+ */
exit(linkit(argv[0], argv[1], false));
}
@@ -337,12 +341,18 @@
return (0);
}
+static void
+link_usage(void)
+{
+ (void)fprintf(stderr, "usage: link source_file target_file\n");
+ exit(1);
+}
+
static void
usage(void)
{
- (void)fprintf(stderr, "%s\n%s\n%s\n",
+ (void)fprintf(stderr, "%s\n%s\n",
"usage: ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file [target_file]",
- " ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file ... target_dir",
- " link source_file target_file");
+ " ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file ... target_dir");
exit(1);
}
diff --git a/bin/ln/tests/ln_test.sh b/bin/ln/tests/ln_test.sh
--- a/bin/ln/tests/ln_test.sh
+++ b/bin/ln/tests/ln_test.sh
@@ -90,7 +90,7 @@
{
atf_check touch A B
atf_check -s exit:1 -e inline:'ln: B: File exists\n' \
- ln A B
+ ln A B
}
atf_test_case target_exists_symbolic
@@ -103,7 +103,7 @@
{
atf_check touch A B
atf_check -s exit:1 -e inline:'ln: B: File exists\n' \
- ln -s A B
+ ln -s A B
}
atf_test_case shf_flag_dir
@@ -210,10 +210,65 @@
sw_flag_body()
{
atf_check -s exit:0 -e inline:'ln: warning: A: No such file or directory\n' \
- ln -sw A B
+ ln -sw A B
atf_check_symlink_to A B
}
+atf_test_case link_argc
+link_argc_head() {
+ atf_set "descr" "Verify that link(1) requires exactly two arguments"
+}
+link_argc_body() {
+ atf_check -s exit:1 -e match:"usage: link" \
+ link foo
+ atf_check -s exit:1 -e match:"No such file" \
+ link foo bar
+ atf_check -s exit:1 -e match:"No such file" \
+ link -- foo bar
+ atf_check -s exit:1 -e match:"usage: link" \
+ link foo bar baz
+}
+
+atf_test_case link_basic
+link_basic_head() {
+ atf_set "descr" "Verify that link(1) creates a link"
+}
+link_basic_body() {
+ touch foo
+ atf_check link foo bar
+ atf_check_same_file foo bar
+ rm bar
+ ln -s foo bar
+ atf_check link bar baz
+ atf_check_same_file foo baz
+}
+
+atf_test_case link_eexist
+link_eexist_head() {
+ atf_set "descr" "Verify that link(1) fails if the target exists"
+}
+link_eexist_body() {
+ touch foo bar
+ atf_check -s exit:1 -e match:"bar.*exists" \
+ link foo bar
+ ln -s non-existent baz
+ atf_check -s exit:1 -e match:"baz.*exists" \
+ link foo baz
+}
+
+atf_test_case link_eisdir
+link_eisdir_head() {
+ atf_set "descr" "Verify that link(1) fails if the source is a directory"
+}
+link_eisdir_body() {
+ mkdir foo
+ atf_check -s exit:1 -e match:"foo.*directory" \
+ link foo bar
+ ln -s foo bar
+ atf_check -s exit:1 -e match:"bar.*directory" \
+ link bar baz
+}
+
atf_init_test_cases()
{
atf_add_test_case L_flag
@@ -229,4 +284,8 @@
atf_add_test_case s_flag
atf_add_test_case s_flag_broken
atf_add_test_case sw_flag
+ atf_add_test_case link_argc
+ atf_add_test_case link_basic
+ atf_add_test_case link_eexist
+ atf_add_test_case link_eisdir
}

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 8, 11:19 AM (21 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14534024
Default Alt Text
D44635.diff (3 KB)

Event Timeline