summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-ar/llvm-ar.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-05-09 13:31:11 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-05-09 13:31:11 +0000
commit484983f453c1c29725a02262124beea52a7bbd0b (patch)
tree6b2027092a99f8e3086bad284b9fad0bd9eab41b /llvm/tools/llvm-ar/llvm-ar.cpp
parentaf742d51ad622b158f71523369fc8998b35ffb3c (diff)
downloadbcm5719-llvm-484983f453c1c29725a02262124beea52a7bbd0b.tar.gz
bcm5719-llvm-484983f453c1c29725a02262124beea52a7bbd0b.zip
Fix bug where temporary file would be left behind every time an archive was updated.
When updating an existing archive, llvm-ar opens the old archive into a `MemoryBuffer`, does its thing, and writes the results to a temporary file. That file is then renamed to the original archive filename, thus replacing it with the updated contents. However, on Windows at least, what would happen is that the `MemoryBuffer` for the old archive would actually be an mmap'ed view of the file, so when it came time to do the rename via Win32's `ReplaceFile`, it would succeed but would be unable to fully replace the file since there would still be a handle open on it; instead, the old version got renamed to a random temporary name and left behind. Patch by Cameron! llvm-svn: 268916
Diffstat (limited to 'llvm/tools/llvm-ar/llvm-ar.cpp')
-rw-r--r--llvm/tools/llvm-ar/llvm-ar.cpp20
1 files changed, 13 insertions, 7 deletions
diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp
index 45f778b9af6..375b34d9b41 100644
--- a/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -576,7 +576,9 @@ computeNewArchiveMembers(ArchiveOperation Operation,
}
static void
-performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
+performWriteOperation(ArchiveOperation Operation,
+ object::Archive *OldArchive,
+ std::unique_ptr<MemoryBuffer> OldArchiveBuf,
std::vector<NewArchiveIterator> *NewMembersP) {
object::Archive::Kind Kind;
switch (FormatOpt) {
@@ -599,14 +601,16 @@ performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
}
if (NewMembersP) {
std::pair<StringRef, std::error_code> Result = writeArchive(
- ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin);
+ ArchiveName, *NewMembersP, Symtab, Kind, Deterministic, Thin,
+ std::move(OldArchiveBuf));
failIfError(Result.second, Result.first);
return;
}
std::vector<NewArchiveIterator> NewMembers =
computeNewArchiveMembers(Operation, OldArchive);
auto Result =
- writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin);
+ writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin,
+ std::move(OldArchiveBuf));
failIfError(Result.second, Result.first);
}
@@ -620,11 +624,12 @@ static void createSymbolTable(object::Archive *OldArchive) {
if (OldArchive->hasSymbolTable())
return;
- performWriteOperation(CreateSymTab, OldArchive, nullptr);
+ performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr);
}
static void performOperation(ArchiveOperation Operation,
object::Archive *OldArchive,
+ std::unique_ptr<MemoryBuffer> OldArchiveBuf,
std::vector<NewArchiveIterator> *NewMembers) {
switch (Operation) {
case Print:
@@ -637,7 +642,8 @@ static void performOperation(ArchiveOperation Operation,
case Move:
case QuickAppend:
case ReplaceOrInsert:
- performWriteOperation(Operation, OldArchive, NewMembers);
+ performWriteOperation(Operation, OldArchive, std::move(OldArchiveBuf),
+ NewMembers);
return;
case CreateSymTab:
createSymbolTable(OldArchive);
@@ -659,7 +665,7 @@ static int performOperation(ArchiveOperation Operation,
object::Archive Archive(Buf.get()->getMemBufferRef(), EC);
failIfError(EC,
"error loading '" + ArchiveName + "': " + EC.message() + "!");
- performOperation(Operation, &Archive, NewMembers);
+ performOperation(Operation, &Archive, std::move(Buf.get()), NewMembers);
return 0;
}
@@ -674,7 +680,7 @@ static int performOperation(ArchiveOperation Operation,
}
}
- performOperation(Operation, nullptr, NewMembers);
+ performOperation(Operation, nullptr, nullptr, NewMembers);
return 0;
}
OpenPOWER on IntegriCloud