For PR797:

Remove exception handling from the bytecode archiver and adjust the llvm-ar
tool to accommodate the new interfaces.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29866 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Spencer 2006-08-24 23:45:08 +00:00
parent c82b3aab65
commit 0ff2d31766
8 changed files with 156 additions and 128 deletions

View File

@ -167,8 +167,9 @@ class ArchiveMember {
/// of the file specified by \p File. The contents of \p this will be /// of the file specified by \p File. The contents of \p this will be
/// updated to reflect the new data from \p File. The \p File must exist and /// updated to reflect the new data from \p File. The \p File must exist and
/// be readable on entry to this method. /// be readable on entry to this method.
/// @returns true if an error occurred, false otherwise
/// @brief Replace contents of archive member with a new file. /// @brief Replace contents of archive member with a new file.
void replaceWith(const sys::Path &aFile); bool replaceWith(const sys::Path &aFile, std::string* ErrMsg);
/// @} /// @}
/// @name ilist methods - do not use /// @name ilist methods - do not use
@ -439,8 +440,8 @@ class Archive {
/// name will be truncated at 15 characters. If \p Compress is specified, /// name will be truncated at 15 characters. If \p Compress is specified,
/// all archive members will be compressed before being written. If /// all archive members will be compressed before being written. If
/// \p PrintSymTab is true, the symbol table will be printed to std::cout. /// \p PrintSymTab is true, the symbol table will be printed to std::cout.
/// @returns false if an error occurred, \p error set to error message /// @returns true if an error occurred, \p error set to error message
/// @returns true if the writing succeeded. /// @returns false if the writing succeeded.
/// @brief Write (possibly modified) archive contents to disk /// @brief Write (possibly modified) archive contents to disk
bool writeToDisk( bool writeToDisk(
bool CreateSymbolTable=false, ///< Create Symbol table bool CreateSymbolTable=false, ///< Create Symbol table
@ -453,10 +454,13 @@ class Archive {
/// to determine just enough information to create an ArchiveMember object /// to determine just enough information to create an ArchiveMember object
/// which is then inserted into the Archive object's ilist at the location /// which is then inserted into the Archive object's ilist at the location
/// given by \p where. /// given by \p where.
/// @throws std::string if an error occurs reading the \p filename. /// @returns true if an error occured, false otherwise
/// @returns nothing
/// @brief Add a file to the archive. /// @brief Add a file to the archive.
void addFileBefore(const sys::Path& filename, iterator where); bool addFileBefore(
const sys::Path& filename, ///< The file to be added
iterator where, ///< Insertion point
std::string* ErrMsg ///< Optional error message location
);
/// @} /// @}
/// @name Implementation /// @name Implementation
@ -464,7 +468,7 @@ class Archive {
protected: protected:
/// @brief Construct an Archive for \p filename and optionally map it /// @brief Construct an Archive for \p filename and optionally map it
/// into memory. /// into memory.
Archive(const sys::Path& filename, bool map = false ); Archive(const sys::Path& filename);
/// @param error Set to address of a std::string to get error messages /// @param error Set to address of a std::string to get error messages
/// @returns false on error /// @returns false on error
@ -500,8 +504,8 @@ class Archive {
/// Writes one ArchiveMember to an ofstream. If an error occurs, returns /// Writes one ArchiveMember to an ofstream. If an error occurs, returns
/// false, otherwise true. If an error occurs and error is non-null then /// false, otherwise true. If an error occurs and error is non-null then
/// it will be set to an error message. /// it will be set to an error message.
/// @returns true Writing member succeeded /// @returns false Writing member succeeded
/// @returns false Writing member failed, \p error set to error message /// @returns true Writing member failed, \p error set to error message
bool writeMember( bool writeMember(
const ArchiveMember& member, ///< The member to be written const ArchiveMember& member, ///< The member to be written
std::ofstream& ARFile, ///< The file to write member onto std::ofstream& ARFile, ///< The file to write member onto
@ -515,6 +519,9 @@ class Archive {
bool fillHeader(const ArchiveMember&mbr, bool fillHeader(const ArchiveMember&mbr,
ArchiveMemberHeader& hdr,int sz, bool TruncateNames) const; ArchiveMemberHeader& hdr,int sz, bool TruncateNames) const;
/// @brief Maps archive into memory
bool mapToMemory(std::string* ErrMsg);
/// @brief Frees all the members and unmaps the archive file. /// @brief Frees all the members and unmaps the archive file.
void cleanUpMemory(); void cleanUpMemory();
@ -525,6 +532,7 @@ class Archive {
typedef std::map<unsigned,std::pair<ModuleProvider*,ArchiveMember*> > typedef std::map<unsigned,std::pair<ModuleProvider*,ArchiveMember*> >
ModuleMap; ModuleMap;
/// @} /// @}
/// @name Data /// @name Data
/// @{ /// @{

View File

@ -61,7 +61,7 @@ ArchiveMember::ArchiveMember(Archive* PAR)
// This method allows an ArchiveMember to be replaced with the data for a // This method allows an ArchiveMember to be replaced with the data for a
// different file, presumably as an update to the member. It also makes sure // different file, presumably as an update to the member. It also makes sure
// the flags are reset correctly. // the flags are reset correctly.
void ArchiveMember::replaceWith(const sys::Path& newFile) { bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) {
assert(newFile.exists() && "Can't replace with a non-existent file"); assert(newFile.exists() && "Can't replace with a non-existent file");
data = 0; data = 0;
path = newFile; path = newFile;
@ -110,8 +110,8 @@ void ArchiveMember::replaceWith(const sys::Path& newFile) {
path.getMagicNumber(magic,4); path.getMagicNumber(magic,4);
signature = magic.c_str(); signature = magic.c_str();
std::string err; std::string err;
if (path.getFileStatus(info, &err)) if (path.getFileStatus(info, ErrMsg))
throw err; return true;
} }
// Determine what kind of file it is // Determine what kind of file it is
@ -127,23 +127,27 @@ void ArchiveMember::replaceWith(const sys::Path& newFile) {
flags &= ~(BytecodeFlag|CompressedBytecodeFlag); flags &= ~(BytecodeFlag|CompressedBytecodeFlag);
break; break;
} }
return false;
} }
// Archive constructor - this is the only constructor that gets used for the // Archive constructor - this is the only constructor that gets used for the
// Archive class. Everything else (default,copy) is deprecated. This just // Archive class. Everything else (default,copy) is deprecated. This just
// initializes and maps the file into memory, if requested. // initializes and maps the file into memory, if requested.
Archive::Archive(const sys::Path& filename, bool map ) Archive::Archive(const sys::Path& filename)
: archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(), : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(),
symTabSize(0), firstFileOffset(0), modules(), foreignST(0) symTabSize(0), firstFileOffset(0), modules(), foreignST(0)
{ {
if (map) { }
std::string ErrMsg;
mapfile = new sys::MappedFile(); bool
if (mapfile->open(filename, sys::MappedFile::READ_ACCESS, &ErrMsg)) Archive::mapToMemory(std::string* ErrMsg)
throw ErrMsg; {
if (!(base = (char*) mapfile->map(&ErrMsg))) mapfile = new sys::MappedFile();
throw ErrMsg; if (mapfile->open(archPath, sys::MappedFile::READ_ACCESS, ErrMsg))
} return true;
if (!(base = (char*) mapfile->map(ErrMsg)))
return true;
return false;
} }
void Archive::cleanUpMemory() { void Archive::cleanUpMemory() {

View File

@ -330,7 +330,9 @@ Archive::loadArchive(std::string* error) {
Archive* Archive*
Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage) Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage)
{ {
std::auto_ptr<Archive> result ( new Archive(file, true)); std::auto_ptr<Archive> result ( new Archive(file));
if (result->mapToMemory(ErrorMessage))
return 0;
if (!result->loadArchive(ErrorMessage)) if (!result->loadArchive(ErrorMessage))
return 0; return 0;
return result.release(); return result.release();
@ -437,7 +439,9 @@ Archive::loadSymbolTable(std::string* ErrorMsg) {
// Open the archive and load just the symbol tables // Open the archive and load just the symbol tables
Archive* Archive*
Archive::OpenAndLoadSymbols(const sys::Path& file, std::string* ErrorMessage) { Archive::OpenAndLoadSymbols(const sys::Path& file, std::string* ErrorMessage) {
std::auto_ptr<Archive> result ( new Archive(file, true) ); std::auto_ptr<Archive> result ( new Archive(file) );
if (result->mapToMemory(ErrorMessage))
return 0;
if (!result->loadSymbolTable(ErrorMessage)) if (!result->loadSymbolTable(ErrorMessage))
return 0; return 0;
return result.release(); return result.release();

View File

@ -64,7 +64,7 @@ inline unsigned numVbrBytes(unsigned num) {
// Create an empty archive. // Create an empty archive.
Archive* Archive*
Archive::CreateEmpty(const sys::Path& FilePath ) { Archive::CreateEmpty(const sys::Path& FilePath ) {
Archive* result = new Archive(FilePath,false); Archive* result = new Archive(FilePath);
return result; return result;
} }
@ -151,17 +151,17 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr,
// Insert a file into the archive before some other member. This also takes care // Insert a file into the archive before some other member. This also takes care
// of extracting the necessary flags and information from the file. // of extracting the necessary flags and information from the file.
void bool
Archive::addFileBefore(const sys::Path& filePath, iterator where) { Archive::addFileBefore(const sys::Path& filePath, iterator where,
std::string* ErrMsg) {
assert(filePath.exists() && "Can't add a non-existent file"); assert(filePath.exists() && "Can't add a non-existent file");
ArchiveMember* mbr = new ArchiveMember(this); ArchiveMember* mbr = new ArchiveMember(this);
mbr->data = 0; mbr->data = 0;
mbr->path = filePath; mbr->path = filePath;
std::string err; if (mbr->path.getFileStatus(mbr->info, ErrMsg))
if (mbr->path.getFileStatus(mbr->info, &err)) return true;
throw err;
unsigned flags = 0; unsigned flags = 0;
bool hasSlash = filePath.toString().find('/') != std::string::npos; bool hasSlash = filePath.toString().find('/') != std::string::npos;
@ -183,6 +183,7 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where) {
} }
mbr->flags = flags; mbr->flags = flags;
members.insert(where,mbr); members.insert(where,mbr);
return false;
} }
// Write one member out to the file. // Write one member out to the file.
@ -193,7 +194,7 @@ Archive::writeMember(
bool CreateSymbolTable, bool CreateSymbolTable,
bool TruncateNames, bool TruncateNames,
bool ShouldCompress, bool ShouldCompress,
std::string* error std::string* ErrMsg
) { ) {
unsigned filepos = ARFile.tellp(); unsigned filepos = ARFile.tellp();
@ -205,12 +206,11 @@ Archive::writeMember(
const char* data = (const char*)member.getData(); const char* data = (const char*)member.getData();
sys::MappedFile* mFile = 0; sys::MappedFile* mFile = 0;
if (!data) { if (!data) {
std::string ErrMsg;
mFile = new sys::MappedFile(); mFile = new sys::MappedFile();
if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, &ErrMsg)) if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, ErrMsg))
throw ErrMsg; return true;
if (!(data = (const char*) mFile->map(&ErrMsg))) if (!(data = (const char*) mFile->map(ErrMsg)))
throw ErrMsg; return true;
fSize = mFile->size(); fSize = mFile->size();
} }
@ -246,8 +246,9 @@ Archive::writeMember(
mFile->close(); mFile->close();
delete mFile; delete mFile;
} }
if (error) if (ErrMsg)
*error = "Can't parse bytecode member: " + member.getPath().toString(); *ErrMsg = "Can't parse bytecode member: " + member.getPath().toString();
return true;
} }
} }
@ -274,9 +275,9 @@ Archive::writeMember(
data +=4; data +=4;
fSize -= 4; fSize -= 4;
} }
fSize = Compressor::compressToNewBuffer(data,fSize,output,error); fSize = Compressor::compressToNewBuffer(data,fSize,output,ErrMsg);
if (fSize == 0) if (fSize == 0)
return false; return true;
data = output; data = output;
if (member.isBytecode()) if (member.isBytecode())
hdrSize = -fSize-4; hdrSize = -fSize-4;
@ -320,7 +321,7 @@ Archive::writeMember(
mFile->close(); mFile->close();
delete mFile; delete mFile;
} }
return true; return false;
} }
// Write out the LLVM symbol table as an archive member to the file. // Write out the LLVM symbol table as an archive member to the file.
@ -380,7 +381,7 @@ Archive::writeSymbolTable(std::ofstream& ARFile) {
// compressing each archive member. // compressing each archive member.
bool bool
Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
std::string* error) std::string* ErrMsg)
{ {
// Make sure they haven't opened up the file, not loaded it, // 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. // but are now trying to write it which would wipe out the file.
@ -389,8 +390,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// Create a temporary file to store the archive in // Create a temporary file to store the archive in
sys::Path TmpArchive = archPath; sys::Path TmpArchive = archPath;
if (TmpArchive.createTemporaryFileOnDisk(error)) if (TmpArchive.createTemporaryFileOnDisk(ErrMsg))
return false; return true;
// Make sure the temporary gets removed if we crash // Make sure the temporary gets removed if we crash
sys::RemoveFileOnSignal(TmpArchive); sys::RemoveFileOnSignal(TmpArchive);
@ -404,9 +405,9 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
if (!ArchiveFile.is_open() || ArchiveFile.bad()) { if (!ArchiveFile.is_open() || ArchiveFile.bad()) {
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
if (error) if (ErrMsg)
*error = "Error opening archive file: " + archPath.toString(); *ErrMsg = "Error opening archive file: " + archPath.toString();
return false; return true;
} }
// If we're creating a symbol table, reset it now // If we're creating a symbol table, reset it now
@ -421,12 +422,12 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// Loop over all member files, and write them out. Note that this also // Loop over all member files, and write them out. Note that this also
// builds the symbol table, symTab. // builds the symbol table, symTab.
for (MembersList::iterator I = begin(), E = end(); I != E; ++I) { for (MembersList::iterator I = begin(), E = end(); I != E; ++I) {
if (!writeMember(*I, ArchiveFile, CreateSymbolTable, if (writeMember(*I, ArchiveFile, CreateSymbolTable,
TruncateNames, Compress, error)) { TruncateNames, Compress, ErrMsg)) {
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
ArchiveFile.close(); ArchiveFile.close();
return false; return true;
} }
} }
@ -443,27 +444,26 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// Map in the archive we just wrote. // Map in the archive we just wrote.
sys::MappedFile arch; sys::MappedFile arch;
std::string ErrMsg; if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, ErrMsg))
if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, &ErrMsg)) return true;
throw ErrMsg;
const char* base; const char* base;
if (!(base = (const char*) arch.map(&ErrMsg))) if (!(base = (const char*) arch.map(ErrMsg)))
throw ErrMsg; return true;
// Open another temporary file in order to avoid invalidating the // Open another temporary file in order to avoid invalidating the
// mmapped data // mmapped data
sys::Path FinalFilePath = archPath; sys::Path FinalFilePath = archPath;
if (FinalFilePath.createTemporaryFileOnDisk(error)) if (FinalFilePath.createTemporaryFileOnDisk(ErrMsg))
return false; return true;
sys::RemoveFileOnSignal(FinalFilePath); sys::RemoveFileOnSignal(FinalFilePath);
std::ofstream FinalFile(FinalFilePath.c_str(), io_mode); std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
if (!FinalFile.is_open() || FinalFile.bad()) { if (!FinalFile.is_open() || FinalFile.bad()) {
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
if (error) if (ErrMsg)
*error = "Error opening archive file: " + FinalFilePath.toString(); *ErrMsg = "Error opening archive file: " + FinalFilePath.toString();
return false; return true;
} }
// Write the file magic number // Write the file magic number
@ -475,11 +475,11 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// compatibility with other ar(1) implementations as well as allowing the // compatibility with other ar(1) implementations as well as allowing the
// archive to store both native .o and LLVM .bc files, both indexed. // archive to store both native .o and LLVM .bc files, both indexed.
if (foreignST) { if (foreignST) {
if (!writeMember(*foreignST, FinalFile, false, false, false, error)) { if (writeMember(*foreignST, FinalFile, false, false, false, ErrMsg)) {
FinalFile.close(); FinalFile.close();
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
return false; return true;
} }
} }
@ -496,8 +496,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
arch.close(); arch.close();
// Move the final file over top of TmpArchive // Move the final file over top of TmpArchive
if (FinalFilePath.renamePathOnDisk(TmpArchive, error)) if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg))
return false; return true;
} }
// Before we replace the actual archive, we need to forget all the // Before we replace the actual archive, we need to forget all the
@ -505,8 +505,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// this because we cannot replace an open file on Windows. // this because we cannot replace an open file on Windows.
cleanUpMemory(); cleanUpMemory();
if (TmpArchive.renamePathOnDisk(archPath, error)) if (TmpArchive.renamePathOnDisk(archPath, ErrMsg))
return false; return true;
return true; return false;
} }

View File

@ -61,7 +61,7 @@ ArchiveMember::ArchiveMember(Archive* PAR)
// This method allows an ArchiveMember to be replaced with the data for a // This method allows an ArchiveMember to be replaced with the data for a
// different file, presumably as an update to the member. It also makes sure // different file, presumably as an update to the member. It also makes sure
// the flags are reset correctly. // the flags are reset correctly.
void ArchiveMember::replaceWith(const sys::Path& newFile) { bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) {
assert(newFile.exists() && "Can't replace with a non-existent file"); assert(newFile.exists() && "Can't replace with a non-existent file");
data = 0; data = 0;
path = newFile; path = newFile;
@ -110,8 +110,8 @@ void ArchiveMember::replaceWith(const sys::Path& newFile) {
path.getMagicNumber(magic,4); path.getMagicNumber(magic,4);
signature = magic.c_str(); signature = magic.c_str();
std::string err; std::string err;
if (path.getFileStatus(info, &err)) if (path.getFileStatus(info, ErrMsg))
throw err; return true;
} }
// Determine what kind of file it is // Determine what kind of file it is
@ -127,23 +127,27 @@ void ArchiveMember::replaceWith(const sys::Path& newFile) {
flags &= ~(BytecodeFlag|CompressedBytecodeFlag); flags &= ~(BytecodeFlag|CompressedBytecodeFlag);
break; break;
} }
return false;
} }
// Archive constructor - this is the only constructor that gets used for the // Archive constructor - this is the only constructor that gets used for the
// Archive class. Everything else (default,copy) is deprecated. This just // Archive class. Everything else (default,copy) is deprecated. This just
// initializes and maps the file into memory, if requested. // initializes and maps the file into memory, if requested.
Archive::Archive(const sys::Path& filename, bool map ) Archive::Archive(const sys::Path& filename)
: archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(), : archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(),
symTabSize(0), firstFileOffset(0), modules(), foreignST(0) symTabSize(0), firstFileOffset(0), modules(), foreignST(0)
{ {
if (map) { }
std::string ErrMsg;
mapfile = new sys::MappedFile(); bool
if (mapfile->open(filename, sys::MappedFile::READ_ACCESS, &ErrMsg)) Archive::mapToMemory(std::string* ErrMsg)
throw ErrMsg; {
if (!(base = (char*) mapfile->map(&ErrMsg))) mapfile = new sys::MappedFile();
throw ErrMsg; if (mapfile->open(archPath, sys::MappedFile::READ_ACCESS, ErrMsg))
} return true;
if (!(base = (char*) mapfile->map(ErrMsg)))
return true;
return false;
} }
void Archive::cleanUpMemory() { void Archive::cleanUpMemory() {

View File

@ -330,7 +330,9 @@ Archive::loadArchive(std::string* error) {
Archive* Archive*
Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage) Archive::OpenAndLoad(const sys::Path& file, std::string* ErrorMessage)
{ {
std::auto_ptr<Archive> result ( new Archive(file, true)); std::auto_ptr<Archive> result ( new Archive(file));
if (result->mapToMemory(ErrorMessage))
return 0;
if (!result->loadArchive(ErrorMessage)) if (!result->loadArchive(ErrorMessage))
return 0; return 0;
return result.release(); return result.release();
@ -437,7 +439,9 @@ Archive::loadSymbolTable(std::string* ErrorMsg) {
// Open the archive and load just the symbol tables // Open the archive and load just the symbol tables
Archive* Archive*
Archive::OpenAndLoadSymbols(const sys::Path& file, std::string* ErrorMessage) { Archive::OpenAndLoadSymbols(const sys::Path& file, std::string* ErrorMessage) {
std::auto_ptr<Archive> result ( new Archive(file, true) ); std::auto_ptr<Archive> result ( new Archive(file) );
if (result->mapToMemory(ErrorMessage))
return 0;
if (!result->loadSymbolTable(ErrorMessage)) if (!result->loadSymbolTable(ErrorMessage))
return 0; return 0;
return result.release(); return result.release();

View File

@ -64,7 +64,7 @@ inline unsigned numVbrBytes(unsigned num) {
// Create an empty archive. // Create an empty archive.
Archive* Archive*
Archive::CreateEmpty(const sys::Path& FilePath ) { Archive::CreateEmpty(const sys::Path& FilePath ) {
Archive* result = new Archive(FilePath,false); Archive* result = new Archive(FilePath);
return result; return result;
} }
@ -151,17 +151,17 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr,
// Insert a file into the archive before some other member. This also takes care // Insert a file into the archive before some other member. This also takes care
// of extracting the necessary flags and information from the file. // of extracting the necessary flags and information from the file.
void bool
Archive::addFileBefore(const sys::Path& filePath, iterator where) { Archive::addFileBefore(const sys::Path& filePath, iterator where,
std::string* ErrMsg) {
assert(filePath.exists() && "Can't add a non-existent file"); assert(filePath.exists() && "Can't add a non-existent file");
ArchiveMember* mbr = new ArchiveMember(this); ArchiveMember* mbr = new ArchiveMember(this);
mbr->data = 0; mbr->data = 0;
mbr->path = filePath; mbr->path = filePath;
std::string err; if (mbr->path.getFileStatus(mbr->info, ErrMsg))
if (mbr->path.getFileStatus(mbr->info, &err)) return true;
throw err;
unsigned flags = 0; unsigned flags = 0;
bool hasSlash = filePath.toString().find('/') != std::string::npos; bool hasSlash = filePath.toString().find('/') != std::string::npos;
@ -183,6 +183,7 @@ Archive::addFileBefore(const sys::Path& filePath, iterator where) {
} }
mbr->flags = flags; mbr->flags = flags;
members.insert(where,mbr); members.insert(where,mbr);
return false;
} }
// Write one member out to the file. // Write one member out to the file.
@ -193,7 +194,7 @@ Archive::writeMember(
bool CreateSymbolTable, bool CreateSymbolTable,
bool TruncateNames, bool TruncateNames,
bool ShouldCompress, bool ShouldCompress,
std::string* error std::string* ErrMsg
) { ) {
unsigned filepos = ARFile.tellp(); unsigned filepos = ARFile.tellp();
@ -205,12 +206,11 @@ Archive::writeMember(
const char* data = (const char*)member.getData(); const char* data = (const char*)member.getData();
sys::MappedFile* mFile = 0; sys::MappedFile* mFile = 0;
if (!data) { if (!data) {
std::string ErrMsg;
mFile = new sys::MappedFile(); mFile = new sys::MappedFile();
if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, &ErrMsg)) if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, ErrMsg))
throw ErrMsg; return true;
if (!(data = (const char*) mFile->map(&ErrMsg))) if (!(data = (const char*) mFile->map(ErrMsg)))
throw ErrMsg; return true;
fSize = mFile->size(); fSize = mFile->size();
} }
@ -246,8 +246,9 @@ Archive::writeMember(
mFile->close(); mFile->close();
delete mFile; delete mFile;
} }
if (error) if (ErrMsg)
*error = "Can't parse bytecode member: " + member.getPath().toString(); *ErrMsg = "Can't parse bytecode member: " + member.getPath().toString();
return true;
} }
} }
@ -274,9 +275,9 @@ Archive::writeMember(
data +=4; data +=4;
fSize -= 4; fSize -= 4;
} }
fSize = Compressor::compressToNewBuffer(data,fSize,output,error); fSize = Compressor::compressToNewBuffer(data,fSize,output,ErrMsg);
if (fSize == 0) if (fSize == 0)
return false; return true;
data = output; data = output;
if (member.isBytecode()) if (member.isBytecode())
hdrSize = -fSize-4; hdrSize = -fSize-4;
@ -320,7 +321,7 @@ Archive::writeMember(
mFile->close(); mFile->close();
delete mFile; delete mFile;
} }
return true; return false;
} }
// Write out the LLVM symbol table as an archive member to the file. // Write out the LLVM symbol table as an archive member to the file.
@ -380,7 +381,7 @@ Archive::writeSymbolTable(std::ofstream& ARFile) {
// compressing each archive member. // compressing each archive member.
bool bool
Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress, Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
std::string* error) std::string* ErrMsg)
{ {
// Make sure they haven't opened up the file, not loaded it, // 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. // but are now trying to write it which would wipe out the file.
@ -389,8 +390,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// Create a temporary file to store the archive in // Create a temporary file to store the archive in
sys::Path TmpArchive = archPath; sys::Path TmpArchive = archPath;
if (TmpArchive.createTemporaryFileOnDisk(error)) if (TmpArchive.createTemporaryFileOnDisk(ErrMsg))
return false; return true;
// Make sure the temporary gets removed if we crash // Make sure the temporary gets removed if we crash
sys::RemoveFileOnSignal(TmpArchive); sys::RemoveFileOnSignal(TmpArchive);
@ -404,9 +405,9 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
if (!ArchiveFile.is_open() || ArchiveFile.bad()) { if (!ArchiveFile.is_open() || ArchiveFile.bad()) {
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
if (error) if (ErrMsg)
*error = "Error opening archive file: " + archPath.toString(); *ErrMsg = "Error opening archive file: " + archPath.toString();
return false; return true;
} }
// If we're creating a symbol table, reset it now // If we're creating a symbol table, reset it now
@ -421,12 +422,12 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// Loop over all member files, and write them out. Note that this also // Loop over all member files, and write them out. Note that this also
// builds the symbol table, symTab. // builds the symbol table, symTab.
for (MembersList::iterator I = begin(), E = end(); I != E; ++I) { for (MembersList::iterator I = begin(), E = end(); I != E; ++I) {
if (!writeMember(*I, ArchiveFile, CreateSymbolTable, if (writeMember(*I, ArchiveFile, CreateSymbolTable,
TruncateNames, Compress, error)) { TruncateNames, Compress, ErrMsg)) {
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
ArchiveFile.close(); ArchiveFile.close();
return false; return true;
} }
} }
@ -443,27 +444,26 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// Map in the archive we just wrote. // Map in the archive we just wrote.
sys::MappedFile arch; sys::MappedFile arch;
std::string ErrMsg; if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, ErrMsg))
if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, &ErrMsg)) return true;
throw ErrMsg;
const char* base; const char* base;
if (!(base = (const char*) arch.map(&ErrMsg))) if (!(base = (const char*) arch.map(ErrMsg)))
throw ErrMsg; return true;
// Open another temporary file in order to avoid invalidating the // Open another temporary file in order to avoid invalidating the
// mmapped data // mmapped data
sys::Path FinalFilePath = archPath; sys::Path FinalFilePath = archPath;
if (FinalFilePath.createTemporaryFileOnDisk(error)) if (FinalFilePath.createTemporaryFileOnDisk(ErrMsg))
return false; return true;
sys::RemoveFileOnSignal(FinalFilePath); sys::RemoveFileOnSignal(FinalFilePath);
std::ofstream FinalFile(FinalFilePath.c_str(), io_mode); std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
if (!FinalFile.is_open() || FinalFile.bad()) { if (!FinalFile.is_open() || FinalFile.bad()) {
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
if (error) if (ErrMsg)
*error = "Error opening archive file: " + FinalFilePath.toString(); *ErrMsg = "Error opening archive file: " + FinalFilePath.toString();
return false; return true;
} }
// Write the file magic number // Write the file magic number
@ -475,11 +475,11 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// compatibility with other ar(1) implementations as well as allowing the // compatibility with other ar(1) implementations as well as allowing the
// archive to store both native .o and LLVM .bc files, both indexed. // archive to store both native .o and LLVM .bc files, both indexed.
if (foreignST) { if (foreignST) {
if (!writeMember(*foreignST, FinalFile, false, false, false, error)) { if (writeMember(*foreignST, FinalFile, false, false, false, ErrMsg)) {
FinalFile.close(); FinalFile.close();
if (TmpArchive.exists()) if (TmpArchive.exists())
TmpArchive.eraseFromDisk(); TmpArchive.eraseFromDisk();
return false; return true;
} }
} }
@ -496,8 +496,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
arch.close(); arch.close();
// Move the final file over top of TmpArchive // Move the final file over top of TmpArchive
if (FinalFilePath.renamePathOnDisk(TmpArchive, error)) if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg))
return false; return true;
} }
// Before we replace the actual archive, we need to forget all the // Before we replace the actual archive, we need to forget all the
@ -505,8 +505,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress,
// this because we cannot replace an open file on Windows. // this because we cannot replace an open file on Windows.
cleanUpMemory(); cleanUpMemory();
if (TmpArchive.renamePathOnDisk(archPath, error)) if (TmpArchive.renamePathOnDisk(archPath, ErrMsg))
return false; return true;
return true; return false;
} }

View File

@ -586,7 +586,8 @@ doQuickAppend(std::string* ErrMsg) {
// Append them quickly. // Append them quickly.
for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end(); for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end();
PI != PE; ++PI) { PI != PE; ++PI) {
TheArchive->addFileBefore(*PI,TheArchive->end()); if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg))
return true;
} }
// We're done editting, reconstruct the archive. // We're done editting, reconstruct the archive.
@ -647,15 +648,17 @@ doReplaceOrInsert(std::string* ErrMsg) {
sys::FileStatus si; sys::FileStatus si;
std::string Err; std::string Err;
if (found->getFileStatus(si, &Err)) if (found->getFileStatus(si, &Err))
throw Err; return true;
if (si.isDir) { if (si.isDir) {
if (OnlyUpdate) { if (OnlyUpdate) {
// Replace the item only if it is newer. // Replace the item only if it is newer.
if (si.modTime > I->getModTime()) if (si.modTime > I->getModTime())
I->replaceWith(*found); if (I->replaceWith(*found, ErrMsg))
return true;
} else { } else {
// Replace the item regardless of time stamp // Replace the item regardless of time stamp
I->replaceWith(*found); if (I->replaceWith(*found, ErrMsg))
return true;
} }
} else { } else {
// We purposefully ignore directories. // We purposefully ignore directories.
@ -679,7 +682,8 @@ doReplaceOrInsert(std::string* ErrMsg) {
if (!remaining.empty()) { if (!remaining.empty()) {
for (std::set<sys::Path>::iterator PI = remaining.begin(), for (std::set<sys::Path>::iterator PI = remaining.begin(),
PE = remaining.end(); PI != PE; ++PI) { PE = remaining.end(); PI != PE; ++PI) {
TheArchive->addFileBefore(*PI,insert_spot); if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg))
return true;
} }
} }