diff options
author | Jim Meyering <jim@meyering.net> | 2004-06-27 09:41:23 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2004-06-27 09:41:23 +0000 |
commit | 54cdcb1a1a2fe3b9b16c48427c96aa0b579d58c2 (patch) | |
tree | 56dfd7206dc1c3181639fe8396c5226b532680ba /src | |
parent | 4e6aaa2732ee0122eb415c83094f629a5e5da38f (diff) | |
download | coreutils-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')
-rw-r--r-- | src/ln.c | 20 |
1 files changed, 13 insertions, 7 deletions
@@ -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); |