60 lines
1.9 KiB
Diff
60 lines
1.9 KiB
Diff
From 51a25252814f8b6f88ff5999a091e47ca1dbdeb9 Mon Sep 17 00:00:00 2001
|
|
From: Alan Modra <amodra@gmail.com>
|
|
Date: Fri, 5 Feb 2021 22:33:08 +1030
|
|
Subject: [PATCH] PR27349, ar breaks symlinks
|
|
|
|
PR 27349
|
|
* rename.c (smart_rename): Test for existence and type of output
|
|
file with lstat.
|
|
---
|
|
binutils/rename.c | 17 ++++++++++-------
|
|
1 files changed, 10 insertions(+), 7 deletions(-)
|
|
|
|
diff --git a/binutils/rename.c b/binutils/rename.c
|
|
index fece31179153..e36b75132ded 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);
|
|
}
|