- // Write the symbol table
- if (CreateSymbolTable) {
- // At this point we have written a file that is a legal archive but it
- // doesn't have a symbol table in it. To aid in faster reading and to
- // ensure compatibility with other archivers we need to put the symbol
- // table first in the file. Unfortunately, this means mapping the file
- // we just wrote back in and copying it to the destination file.
- sys::Path FinalFilePath = archPath;
-
- // Map in the archive we just wrote.
- {
- OwningPtr<MemoryBuffer> arch;
- if (error_code ec = MemoryBuffer::getFile(TmpArchive.c_str(), arch)) {
- if (ErrMsg)
- *ErrMsg = ec.message();
- return true;
- }
- const char* base = arch->getBufferStart();
-
- // Open another temporary file in order to avoid invalidating the
- // mmapped data
- if (FinalFilePath.createTemporaryFileOnDisk(ErrMsg))
- return true;
- sys::RemoveFileOnSignal(FinalFilePath.str());
-
- std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
- if (!FinalFile.is_open() || FinalFile.bad()) {
- TmpArchive.eraseFromDisk();
- if (ErrMsg)
- *ErrMsg = "Error opening archive file: " + FinalFilePath.str();
- return true;
- }
-
- // Write the file magic number
- FinalFile << ARFILE_MAGIC;
-
- // If there is a foreign symbol table, put it into the file now. Most
- // ar(1) implementations require the symbol table to be first but llvm-ar
- // can deal with it being after a foreign symbol table. This ensures
- // compatibility with other ar(1) implementations as well as allowing the
- // archive to store both native .o and LLVM .bc files, both indexed.
- if (foreignST) {
- if (writeMember(*foreignST, FinalFile, false, false, ErrMsg)) {
- FinalFile.close();
- TmpArchive.eraseFromDisk();
- return true;
- }
- }
-
- // Copy the temporary file contents being sure to skip the file's magic
- // number.
- FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
- arch->getBufferSize()-sizeof(ARFILE_MAGIC)+1);
-
- // Close up shop
- FinalFile.close();
- } // free arch.
-
- // Move the final file over top of TmpArchive
- if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg))
- return true;
- }
-