summaryrefslogtreecommitdiff
path: root/src/ln.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2004-06-27 09:41:23 +0000
committerJim Meyering <jim@meyering.net>2004-06-27 09:41:23 +0000
commit54cdcb1a1a2fe3b9b16c48427c96aa0b579d58c2 (patch)
tree56dfd7206dc1c3181639fe8396c5226b532680ba /src/ln.c
parent4e6aaa2732ee0122eb415c83094f629a5e5da38f (diff)
downloadcoreutils-54cdcb1a1a2fe3b9b16c48427c96aa0b579d58c2.tar.xz
Fix a bug: formerly, if d/x was a directory and x a file, "ln x
d/" incorrectly created a link d/x/x. It also saves some system calls. (main): Don't append basename to dest if this results in an existing directory name.
Diffstat (limited to 'src/ln.c')
-rw-r--r--src/ln.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/src/ln.c b/src/ln.c
index 9b2d73038..7801b2c27 100644
--- a/src/ln.c
+++ b/src/ln.c
@@ -550,25 +550,31 @@ main (int argc, char **argv)
else
{
struct stat source_stats;
- char *new_dest;
char const *source = file[0];
char *dest = file[1];
size_t destlen = strlen (dest);
+ char *new_dest = dest;
/* When the destination is specified with a trailing slash and the
source exists but is not a directory, convert the user's command
- `ln source dest/' to `ln source dest/basename(source)'. */
+ `ln source dest/' to `ln source dest/basename(source)'.
+ However, skip this step if dest/basename(source) is a directory. */
if (destlen != 0
&& dest[destlen - 1] == '/'
&& lstat (source, &source_stats) == 0
&& !S_ISDIR (source_stats.st_mode))
{
- PATH_BASENAME_CONCAT (new_dest, dest, source);
- }
- else
- {
- new_dest = dest;
+ struct stat dest_stats;
+ char *dest_plus_source_basename;
+
+ PATH_BASENAME_CONCAT (dest_plus_source_basename, dest, source);
+
+ if (! ((((dereference_dest_dir_symlinks ? stat : lstat)
+ (dest_plus_source_basename, &dest_stats))
+ == 0)
+ && S_ISDIR (dest_stats.st_mode)))
+ new_dest = dest_plus_source_basename;
}
errors = do_link (source, new_dest);