From ba1852e6f1ea32b91ffe731bdfc0fdc7920dc792 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 1 Sep 1997 20:31:00 +0000 Subject: (do_link): Form destination file name (when DEST is a directory) before checking whether SOURCE and DEST are the same file. --- src/ln.c | 62 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'src/ln.c') 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)) -- cgit v1.2.3-54-g00ecf