X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FArchive%2FArchiveWriter.cpp;h=8fcc7aa29cc853ddbe9655088e56a20f24004626;hb=1b3f9198ab3880be34b6252423b9e388b5cd6a5e;hp=07f7d88dd8215a387777483ab281216c5ff4cb87;hpb=4c71dfe356716e6bc1993ef5efdced08b68fe612;p=oota-llvm.git diff --git a/lib/Archive/ArchiveWriter.cpp b/lib/Archive/ArchiveWriter.cpp index 07f7d88dd82..8fcc7aa29cc 100644 --- a/lib/Archive/ArchiveWriter.cpp +++ b/lib/Archive/ArchiveWriter.cpp @@ -12,10 +12,14 @@ //===----------------------------------------------------------------------===// #include "ArchiveInternals.h" +#include "llvm/Module.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/System/Signals.h" -#include "llvm/System/Process.h" -#include "llvm/ModuleProvider.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Process.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" #include #include #include @@ -23,7 +27,7 @@ using namespace llvm; // Write an integer using variable bit rate encoding. This saves a few bytes // per entry in the symbol table. -inline void writeInteger(unsigned num, std::ofstream& ARFile) { +static inline void writeInteger(unsigned num, std::ofstream& ARFile) { while (1) { if (num < 0x80) { // done? ARFile << (unsigned char)num; @@ -39,7 +43,7 @@ inline void writeInteger(unsigned num, std::ofstream& ARFile) { // Compute how many bytes are taken by a given VBR encoded value. This is needed // to pre-compute the size of the symbol table. -inline unsigned numVbrBytes(unsigned num) { +static inline unsigned numVbrBytes(unsigned num) { // Note that the following nested ifs are somewhat equivalent to a binary // search. We split it in half by comparing against 2^14 first. This allows @@ -62,9 +66,8 @@ inline unsigned numVbrBytes(unsigned num) { } // Create an empty archive. -Archive* -Archive::CreateEmpty(const sys::Path& FilePath ) { - Archive* result = new Archive(FilePath); +Archive* Archive::CreateEmpty(const sys::Path& FilePath, LLVMContext& C) { + Archive* result = new Archive(FilePath, C); return result; } @@ -94,7 +97,7 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr, memcpy(hdr.date,buffer,12); // Get rid of trailing blanks in the name - std::string mbrPath = mbr.getPath().toString(); + std::string mbrPath = mbr.getPath().str(); size_t mbrLen = mbrPath.length(); while (mbrLen > 0 && mbrPath[mbrLen-1] == ' ') { mbrPath.erase(mbrLen-1,1); @@ -152,9 +155,10 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr, // Insert a file into the archive before some other member. This also takes care // of extracting the necessary flags and information from the file. bool -Archive::addFileBefore(const sys::Path& filePath, iterator where, +Archive::addFileBefore(const sys::Path& filePath, iterator where, std::string* ErrMsg) { - if (!filePath.exists()) { + bool Exists; + if (sys::fs::exists(filePath.str(), Exists) || !Exists) { if (ErrMsg) *ErrMsg = "Can not add a non-existent file to archive"; return true; @@ -165,20 +169,23 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where, mbr->data = 0; mbr->path = filePath; const sys::FileStatus *FSInfo = mbr->path.getFileStatus(false, ErrMsg); - if (FSInfo) - mbr->info = *FSInfo; - else + if (!FSInfo) { + delete mbr; return true; + } + mbr->info = *FSInfo; unsigned flags = 0; - bool hasSlash = filePath.toString().find('/') != std::string::npos; + bool hasSlash = filePath.str().find('/') != std::string::npos; if (hasSlash) flags |= ArchiveMember::HasPathFlag; - if (hasSlash || filePath.toString().length() > 15) + if (hasSlash || filePath.str().length() > 15) flags |= ArchiveMember::HasLongFilenameFlag; - std::string magic; - mbr->path.getMagicNumber(magic,4); - switch (sys::IdentifyFileType(magic.c_str(),4)) { + + sys::LLVMFileType type; + if (sys::fs::identify_magic(mbr->path.str(), type)) + type = sys::Unknown_FileType; + switch (type) { case sys::Bitcode_FileType: flags |= ArchiveMember::BitcodeFlag; break; @@ -207,30 +214,31 @@ Archive::writeMember( // Get the data and its size either from the // member's in-memory data or directly from the file. size_t fSize = member.getSize(); - const char* data = (const char*)member.getData(); - sys::MappedFile* mFile = 0; + const char *data = (const char*)member.getData(); + MemoryBuffer *mFile = 0; if (!data) { - mFile = new sys::MappedFile(); - if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, ErrMsg)) - return true; - if (!(data = (const char*) mFile->map(ErrMsg))) + OwningPtr File; + if (error_code ec = MemoryBuffer::getFile(member.getPath().c_str(), File)) { + if (ErrMsg) + *ErrMsg = ec.message(); return true; - fSize = mFile->size(); + } + mFile = File.take(); + data = mFile->getBufferStart(); + fSize = mFile->getBufferSize(); } // Now that we have the data in memory, update the - // symbol table if its a bitcode file. + // symbol table if it's a bitcode file. if (CreateSymbolTable && member.isBitcode()) { std::vector symbols; - std::string FullMemberName = archPath.toString() + "(" + - member.getPath().toString() + std::string FullMemberName = archPath.str() + "(" + member.getPath().str() + ")"; - ModuleProvider* MP = - GetBitcodeSymbols((const unsigned char*)data,fSize, - FullMemberName, symbols, ErrMsg); + Module* M = + GetBitcodeSymbols(data, fSize, FullMemberName, Context, symbols, ErrMsg); // If the bitcode parsed successfully - if ( MP ) { + if ( M ) { for (std::vector::iterator SI = symbols.begin(), SE = symbols.end(); SI != SE; ++SI) { @@ -244,14 +252,11 @@ Archive::writeMember( } } // We don't need this module any more. - delete MP; + delete M; } else { - if (mFile != 0) { - mFile->close(); - delete mFile; - } + delete mFile; if (ErrMsg) - *ErrMsg = "Can't parse bitcode member: " + member.getPath().toString() + *ErrMsg = "Can't parse bitcode member: " + member.getPath().str() + ": " + *ErrMsg; return true; } @@ -268,8 +273,8 @@ Archive::writeMember( // Write the long filename if its long if (writeLongName) { - ARFile.write(member.getPath().toString().data(), - member.getPath().toString().length()); + ARFile.write(member.getPath().str().data(), + member.getPath().str().length()); } // Write the (possibly compressed) member's content to the file. @@ -280,10 +285,7 @@ Archive::writeMember( ARFile << ARFILE_PAD; // Close the mapped file if it was opened - if (mFile != 0) { - mFile->close(); - delete mFile; - } + delete mFile; return false; } @@ -311,8 +313,10 @@ Archive::writeSymbolTable(std::ofstream& ARFile) { // Write the header ARFile.write((char*)&Hdr, sizeof(Hdr)); +#ifndef NDEBUG // Save the starting position of the symbol tables data content. unsigned startpos = ARFile.tellp(); +#endif // Write out the symbols sequentially for ( Archive::SymTabType::iterator I = symTab.begin(), E = symTab.end(); @@ -326,8 +330,10 @@ Archive::writeSymbolTable(std::ofstream& ARFile) { ARFile.write(I->first.data(), I->first.length()); } +#ifndef NDEBUG // Now that we're done with the symbol table, get the ending file position unsigned endpos = ARFile.tellp(); +#endif // Make sure that the amount we wrote is what we pre-computed. This is // critical for file integrity purposes. @@ -348,7 +354,7 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, { // Make sure they haven't opened up the file, not loaded it, // but are now trying to write it which would wipe out the file. - if (members.empty() && mapfile->size() > 8) { + if (members.empty() && mapfile && mapfile->getBufferSize() > 8) { if (ErrMsg) *ErrMsg = "Can't write an archive not opened for writing"; return true; @@ -369,10 +375,9 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // Check for errors opening or creating archive file. if (!ArchiveFile.is_open() || ArchiveFile.bad()) { - if (TmpArchive.exists()) - TmpArchive.eraseFromDisk(); + TmpArchive.eraseFromDisk(); if (ErrMsg) - *ErrMsg = "Error opening archive file: " + archPath.toString(); + *ErrMsg = "Error opening archive file: " + archPath.str(); return true; } @@ -390,8 +395,7 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, for (MembersList::iterator I = begin(), E = end(); I != E; ++I) { if (writeMember(*I, ArchiveFile, CreateSymbolTable, TruncateNames, Compress, ErrMsg)) { - if (TmpArchive.exists()) - TmpArchive.eraseFromDisk(); + TmpArchive.eraseFromDisk(); ArchiveFile.close(); return true; } @@ -407,28 +411,29 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // 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. - sys::MappedFile arch; - if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, ErrMsg)) - return true; - const char* base; - if (!(base = (const char*) arch.map(ErrMsg))) + { + OwningPtr 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 + // Open another temporary file in order to avoid invalidating the // mmapped data - sys::Path FinalFilePath = archPath; if (FinalFilePath.createTemporaryFileOnDisk(ErrMsg)) return true; sys::RemoveFileOnSignal(FinalFilePath); std::ofstream FinalFile(FinalFilePath.c_str(), io_mode); if (!FinalFile.is_open() || FinalFile.bad()) { - if (TmpArchive.exists()) - TmpArchive.eraseFromDisk(); + TmpArchive.eraseFromDisk(); if (ErrMsg) - *ErrMsg = "Error opening archive file: " + FinalFilePath.toString(); + *ErrMsg = "Error opening archive file: " + FinalFilePath.str(); return true; } @@ -443,8 +448,7 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, if (foreignST) { if (writeMember(*foreignST, FinalFile, false, false, false, ErrMsg)) { FinalFile.close(); - if (TmpArchive.exists()) - TmpArchive.eraseFromDisk(); + TmpArchive.eraseFromDisk(); return true; } } @@ -455,24 +459,31 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, // Copy the temporary file contents being sure to skip the file's magic // number. FinalFile.write(base + sizeof(ARFILE_MAGIC)-1, - arch.size()-sizeof(ARFILE_MAGIC)+1); + arch->getBufferSize()-sizeof(ARFILE_MAGIC)+1); // Close up shop FinalFile.close(); - arch.close(); - + } // free arch. + // Move the final file over top of TmpArchive if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg)) return true; } - + // Before we replace the actual archive, we need to forget all the // members, since they point to data in that old archive. We need to do // this because we cannot replace an open file on Windows. cleanUpMemory(); - + if (TmpArchive.renamePathOnDisk(archPath, ErrMsg)) return true; + // Set correct read and write permissions after temporary file is moved + // to final destination path. + if (archPath.makeReadableOnDisk(ErrMsg)) + return true; + if (archPath.makeWriteableOnDisk(ErrMsg)) + return true; + return false; }