summaryrefslogtreecommitdiff
path: root/src/ln.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1997-09-01 20:31:00 +0000
committerJim Meyering <jim@meyering.net>1997-09-01 20:31:00 +0000
commitba1852e6f1ea32b91ffe731bdfc0fdc7920dc792 (patch)
tree02b10572f5215f8f565e88f33aa5cf671c06fa51 /src/ln.c
parent3f27c2b654d71ec7a17588dee5f28a590fcf9090 (diff)
downloadcoreutils-ba1852e6f1ea32b91ffe731bdfc0fdc7920dc792.tar.xz
(do_link): Form destination file name (when DEST is a directory) before
checking whether SOURCE and DEST are the same file.
Diffstat (limited to 'src/ln.c')
-rw-r--r--src/ln.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/src/ln.c b/src/ln.c
index 492d4598a..5e480a2a4 100644
--- a/src/ln.c
+++ b/src/ln.c
@@ -134,12 +134,16 @@ same_name (const char *source, const char *dest)
error (1, 0, _("virtual memory exhausted"));
if (stat (source_dirname, &source_dir_stats))
- /* Shouldn't happen. */
- error (1, errno, "%s", source_dirname);
+ {
+ /* Shouldn't happen. */
+ error (1, errno, "%s", source_dirname);
+ }
if (stat (dest_dirname, &dest_dir_stats))
- /* Shouldn't happen. */
- error (1, errno, "%s", dest_dirname);
+ {
+ /* Shouldn't happen. */
+ error (1, errno, "%s", dest_dirname);
+ }
free (source_dirname);
free (dest_dirname);
@@ -181,13 +185,39 @@ do_link (const char *source, const char *dest)
}
lstat_status = lstat (dest, &dest_stats);
-
if (lstat_status != 0 && errno != ENOENT)
{
error (0, errno, "%s", dest);
return 1;
}
+ /* If the destination is a directory or (it is a symlink to a directory
+ and the user has not specified --no-dereference), then form the
+ actual destination name by appending base_name (source) to the
+ specified destination directory. */
+ if ((lstat_status == 0
+ && S_ISDIR (dest_stats.st_mode))
+#ifdef S_ISLNK
+ || (dereference_dest_dir_symlinks
+ && (S_ISLNK (dest_stats.st_mode)
+ && isdir (dest)))
+#endif
+ )
+ {
+ /* Target is a directory; build the full filename. */
+ char *new_dest;
+ PATH_BASENAME_CONCAT (new_dest, dest, source);
+ dest = new_dest;
+
+ /* Get stats for new DEST. */
+ lstat_status = lstat (dest, &dest_stats);
+ if (lstat_status != 0 && errno != ENOENT)
+ {
+ error (0, errno, "%s", dest);
+ return 1;
+ }
+ }
+
/* If --force (-f) has been specified without --backup, then before
making a link ln must remove the destination file if it exists.
(with --backup, it just renames any existing destination file)
@@ -214,28 +244,6 @@ do_link (const char *source, const char *dest)
return 1;
}
- /* If the destination is a directory or (it is a symlink to a directory
- and the user has not specified --no-dereference), then form the
- actual destination name by appending base_name (source) to the
- specified destination directory. */
- if ((lstat_status == 0
- && S_ISDIR (dest_stats.st_mode))
-#ifdef S_ISLNK
- || (dereference_dest_dir_symlinks
- && (S_ISLNK (dest_stats.st_mode)
- && isdir (dest)))
-#endif
- )
- {
- /* Target is a directory; build the full filename. */
- char *new_dest;
- PATH_BASENAME_CONCAT (new_dest, dest, source);
- dest = new_dest;
- /* Set this to nonzero to force another call to lstat
- with the new destination. */
- lstat_status = 1;
- }
-
if (lstat_status == 0 || lstat (dest, &dest_stats) == 0)
{
if (S_ISDIR (dest_stats.st_mode))