diff options
author | Alan Modra <amodra@gmail.com> | 2021-02-05 22:33:08 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-02-06 07:28:21 +1030 |
commit | 51a25252814f8b6f88ff5999a091e47ca1dbdeb9 (patch) | |
tree | d6b2900260eda1738051117c6775b1f9c1dce530 /binutils/rename.c | |
parent | 9c9d63b15ad548f65f8bfd41cb7a4ef9af5ccb28 (diff) | |
download | fsf-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.c | 17 |
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); } |