aboutsummaryrefslogtreecommitdiff
path: root/binutils/rename.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-02-05 22:33:08 +1030
committerAlan Modra <amodra@gmail.com>2021-02-06 07:28:21 +1030
commit51a25252814f8b6f88ff5999a091e47ca1dbdeb9 (patch)
treed6b2900260eda1738051117c6775b1f9c1dce530 /binutils/rename.c
parent9c9d63b15ad548f65f8bfd41cb7a4ef9af5ccb28 (diff)
downloadfsf-binutils-gdb-51a25252814f8b6f88ff5999a091e47ca1dbdeb9.zip
fsf-binutils-gdb-51a25252814f8b6f88ff5999a091e47ca1dbdeb9.tar.gz
fsf-binutils-gdb-51a25252814f8b6f88ff5999a091e47ca1dbdeb9.tar.bz2
PR27349, ar breaks symlinks
PR 27349 * rename.c (smart_rename): Test for existence and type of output file with lstat.
Diffstat (limited to 'binutils/rename.c')
-rw-r--r--binutils/rename.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/binutils/rename.c b/binutils/rename.c
index fece311..e36b751 100644
--- a/binutils/rename.c
+++ b/binutils/rename.c
@@ -179,7 +179,10 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED,
int preserve_dates ATTRIBUTE_UNUSED)
{
int ret = 0;
- bfd_boolean exists = target_stat != NULL;
+ struct stat to_stat;
+ bfd_boolean exists;
+
+ exists = lstat (to, &to_stat) == 0;
#if defined (_WIN32) && !defined (__CYGWIN32__)
/* Win32, unlike unix, will not erase `to' in `rename(from, to)' but
@@ -214,16 +217,16 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED,
external change. */
if (! exists
|| (fd >= 0
- && !S_ISLNK (target_stat->st_mode)
- && S_ISREG (target_stat->st_mode)
- && (target_stat->st_mode & S_IWUSR)
- && target_stat->st_nlink == 1)
+ && !S_ISLNK (to_stat.st_mode)
+ && S_ISREG (to_stat.st_mode)
+ && (to_stat.st_mode & S_IWUSR)
+ && to_stat.st_nlink == 1)
)
{
ret = rename (from, to);
if (ret == 0)
{
- if (exists)
+ if (exists && target_stat != NULL)
try_preserve_permissions (fd, target_stat);
}
else
@@ -239,7 +242,7 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED,
if (ret != 0)
non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno));
- if (preserve_dates)
+ if (preserve_dates && target_stat != NULL)
set_times (to, target_stat);
unlink (from);
}