diff options
author | Jim Meyering <jim@meyering.net> | 1997-09-01 20:31:00 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 1997-09-01 20:31:00 +0000 |
commit | ba1852e6f1ea32b91ffe731bdfc0fdc7920dc792 (patch) | |
tree | 02b10572f5215f8f565e88f33aa5cf671c06fa51 | |
parent | 3f27c2b654d71ec7a17588dee5f28a590fcf9090 (diff) | |
download | coreutils-ba1852e6f1ea32b91ffe731bdfc0fdc7920dc792.tar.xz |
(do_link): Form destination file name (when DEST is a directory) before
checking whether SOURCE and DEST are the same file.
-rw-r--r-- | src/ln.c | 62 |
1 files changed, 35 insertions, 27 deletions
@@ -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)) |