mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-07-26 02:30:35 +02:00
(do_link): Form destination file name (when DEST is a directory) before
checking whether SOURCE and DEST are the same file.
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user