aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-10-10 06:29:10 +0000
committerIan Lance Taylor <iant@google.com>2007-10-10 06:29:10 +0000
commit4e9d858638034246a4ab4595f5497c7393c3bfbf (patch)
treece12b58bbbdfaeb83860f343f6c8b0c5227e50d0 /gold
parentcf0d1c8e4d67e3236e0a977cd6933ef5ed1a06e4 (diff)
downloadfsf-binutils-gdb-4e9d858638034246a4ab4595f5497c7393c3bfbf.zip
fsf-binutils-gdb-4e9d858638034246a4ab4595f5497c7393c3bfbf.tar.gz
fsf-binutils-gdb-4e9d858638034246a4ab4595f5497c7393c3bfbf.tar.bz2
From Craig Silverstein: delete the output file first if it exists and
is non-empty.
Diffstat (limited to 'gold')
-rw-r--r--gold/output.cc20
1 files changed, 20 insertions, 0 deletions
diff --git a/gold/output.cc b/gold/output.cc
index f217b03..f539dea 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -27,6 +27,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include <algorithm>
#include "parameters.h"
@@ -1672,6 +1673,25 @@ Output_file::open(off_t file_size)
{
this->file_size_ = file_size;
+ // Unlink the file first; otherwise the open() may fail if the file
+ // is busy (e.g. it's an executable that's currently being executed).
+ //
+ // However, the linker may be part of a system where a zero-length
+ // file is created for it to write to, with tight permissions (gcc
+ // 2.95 did something like this). Unlinking the file would work
+ // around those permission controls, so we only unlink if the file
+ // has a non-zero size. We also unlink only regular files to avoid
+ // trouble with directories/etc.
+ //
+ // If we fail, continue; this command is merely a best-effort attempt
+ // to improve the odds for open().
+
+ // FIXME: unlink the file if it's a symlink, even a symlink to a dir.
+ // Or do we want to follow the symlink and unlink its target?
+ struct stat s;
+ if (::stat(this->name_, &s) == 0 && s.st_size != 0 && S_ISREG(s.st_mode))
+ ::unlink(this->name_);
+
int mode = parameters->output_is_object() ? 0666 : 0777;
int o = ::open(this->name_, O_RDWR | O_CREAT | O_TRUNC, mode);
if (o < 0)