/// 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
/// 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.
- void replaceWith(const sys::Path &aFile);
+ bool replaceWith(const sys::Path &aFile, std::string* ErrMsg);
/// @}
/// @name ilist methods - do not use
/// name will be truncated at 15 characters. If \p Compress is specified,
/// all archive members will be compressed before being written. If
/// \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 the writing succeeded.
+ /// @returns true if an error occurred, \p error set to error message
+ /// @returns false if the writing succeeded.
/// @brief Write (possibly modified) archive contents to disk
bool writeToDisk(
bool CreateSymbolTable=false, ///< Create Symbol table
/// to determine just enough information to create an ArchiveMember object
/// which is then inserted into the Archive object's ilist at the location
/// given by \p where.
- /// @throws std::string if an error occurs reading the \p filename.
- /// @returns nothing
+ /// @returns true if an error occured, false otherwise
/// @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
protected:
/// @brief Construct an Archive for \p filename and optionally map it
/// 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
/// @returns false on error
/// Writes one ArchiveMember to an ofstream. If an error occurs, returns
/// false, otherwise true. If an error occurs and error is non-null then
/// it will be set to an error message.
- /// @returns true Writing member succeeded
- /// @returns false Writing member failed, \p error set to error message
+ /// @returns false Writing member succeeded
+ /// @returns true Writing member failed, \p error set to error message
bool writeMember(
const ArchiveMember& member, ///< The member to be written
std::ofstream& ARFile, ///< The file to write member onto
bool fillHeader(const ArchiveMember&mbr,
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.
void cleanUpMemory();
typedef std::map<unsigned,std::pair<ModuleProvider*,ArchiveMember*> >
ModuleMap;
+
/// @}
/// @name Data
/// @{
// 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
// 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");
data = 0;
path = newFile;
path.getMagicNumber(magic,4);
signature = magic.c_str();
std::string err;
- if (path.getFileStatus(info, &err))
- throw err;
+ if (path.getFileStatus(info, ErrMsg))
+ return true;
}
// Determine what kind of file it is
flags &= ~(BytecodeFlag|CompressedBytecodeFlag);
break;
}
+ return false;
}
// Archive constructor - this is the only constructor that gets used for the
// Archive class. Everything else (default,copy) is deprecated. This just
// 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(),
symTabSize(0), firstFileOffset(0), modules(), foreignST(0)
{
- if (map) {
- std::string ErrMsg;
- mapfile = new sys::MappedFile();
- if (mapfile->open(filename, sys::MappedFile::READ_ACCESS, &ErrMsg))
- throw ErrMsg;
- if (!(base = (char*) mapfile->map(&ErrMsg)))
- throw ErrMsg;
- }
+}
+
+bool
+Archive::mapToMemory(std::string* ErrMsg)
+{
+ mapfile = new sys::MappedFile();
+ if (mapfile->open(archPath, sys::MappedFile::READ_ACCESS, ErrMsg))
+ return true;
+ if (!(base = (char*) mapfile->map(ErrMsg)))
+ return true;
+ return false;
}
void Archive::cleanUpMemory() {
Archive*
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))
return 0;
return result.release();
// Open the archive and load just the symbol tables
Archive*
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))
return 0;
return result.release();
// Create an empty archive.
Archive*
Archive::CreateEmpty(const sys::Path& FilePath ) {
- Archive* result = new Archive(FilePath,false);
+ Archive* result = new Archive(FilePath);
return result;
}
// Insert a file into the archive before some other member. This also takes care
// of extracting the necessary flags and information from the file.
-void
-Archive::addFileBefore(const sys::Path& filePath, iterator where) {
+bool
+Archive::addFileBefore(const sys::Path& filePath, iterator where,
+ std::string* ErrMsg) {
assert(filePath.exists() && "Can't add a non-existent file");
ArchiveMember* mbr = new ArchiveMember(this);
mbr->data = 0;
mbr->path = filePath;
- std::string err;
- if (mbr->path.getFileStatus(mbr->info, &err))
- throw err;
+ if (mbr->path.getFileStatus(mbr->info, ErrMsg))
+ return true;
unsigned flags = 0;
bool hasSlash = filePath.toString().find('/') != std::string::npos;
}
mbr->flags = flags;
members.insert(where,mbr);
+ return false;
}
// Write one member out to the file.
bool CreateSymbolTable,
bool TruncateNames,
bool ShouldCompress,
- std::string* error
+ std::string* ErrMsg
) {
unsigned filepos = ARFile.tellp();
const char* data = (const char*)member.getData();
sys::MappedFile* mFile = 0;
if (!data) {
- std::string ErrMsg;
mFile = new sys::MappedFile();
- if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, &ErrMsg))
- throw ErrMsg;
- if (!(data = (const char*) mFile->map(&ErrMsg)))
- throw ErrMsg;
+ if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, ErrMsg))
+ return true;
+ if (!(data = (const char*) mFile->map(ErrMsg)))
+ return true;
fSize = mFile->size();
}
mFile->close();
delete mFile;
}
- if (error)
- *error = "Can't parse bytecode member: " + member.getPath().toString();
+ if (ErrMsg)
+ *ErrMsg = "Can't parse bytecode member: " + member.getPath().toString();
+ return true;
}
}
data +=4;
fSize -= 4;
}
- fSize = Compressor::compressToNewBuffer(data,fSize,output,error);
+ fSize = Compressor::compressToNewBuffer(data,fSize,output,ErrMsg);
if (fSize == 0)
- return false;
+ return true;
data = output;
if (member.isBytecode())
hdrSize = -fSize-4;
mFile->close();
delete mFile;
}
- return true;
+ return false;
}
// Write out the LLVM symbol table as an archive member to the file.
// compressing each archive member.
bool
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,
// but are now trying to write it which would wipe out the file.
// Create a temporary file to store the archive in
sys::Path TmpArchive = archPath;
- if (TmpArchive.createTemporaryFileOnDisk(error))
- return false;
+ if (TmpArchive.createTemporaryFileOnDisk(ErrMsg))
+ return true;
// Make sure the temporary gets removed if we crash
sys::RemoveFileOnSignal(TmpArchive);
if (!ArchiveFile.is_open() || ArchiveFile.bad()) {
if (TmpArchive.exists())
TmpArchive.eraseFromDisk();
- if (error)
- *error = "Error opening archive file: " + archPath.toString();
- return false;
+ if (ErrMsg)
+ *ErrMsg = "Error opening archive file: " + archPath.toString();
+ return true;
}
// If we're creating a symbol table, reset it now
// Loop over all member files, and write them out. Note that this also
// builds the symbol table, symTab.
for (MembersList::iterator I = begin(), E = end(); I != E; ++I) {
- if (!writeMember(*I, ArchiveFile, CreateSymbolTable,
- TruncateNames, Compress, error)) {
+ if (writeMember(*I, ArchiveFile, CreateSymbolTable,
+ TruncateNames, Compress, ErrMsg)) {
if (TmpArchive.exists())
TmpArchive.eraseFromDisk();
ArchiveFile.close();
- return false;
+ return true;
}
}
// Map in the archive we just wrote.
sys::MappedFile arch;
- std::string ErrMsg;
- if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, &ErrMsg))
- throw ErrMsg;
+ if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, ErrMsg))
+ return true;
const char* base;
- if (!(base = (const char*) arch.map(&ErrMsg)))
- throw ErrMsg;
+ if (!(base = (const char*) arch.map(ErrMsg)))
+ return true;
// Open another temporary file in order to avoid invalidating the
// mmapped data
sys::Path FinalFilePath = archPath;
- if (FinalFilePath.createTemporaryFileOnDisk(error))
- return false;
+ 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();
- if (error)
- *error = "Error opening archive file: " + FinalFilePath.toString();
- return false;
+ if (ErrMsg)
+ *ErrMsg = "Error opening archive file: " + FinalFilePath.toString();
+ return true;
}
// Write the file magic number
// 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, false, error)) {
+ if (writeMember(*foreignST, FinalFile, false, false, false, ErrMsg)) {
FinalFile.close();
if (TmpArchive.exists())
TmpArchive.eraseFromDisk();
- return false;
+ return true;
}
}
arch.close();
// Move the final file over top of TmpArchive
- if (FinalFilePath.renamePathOnDisk(TmpArchive, error))
- return false;
+ if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg))
+ return true;
}
// Before we replace the actual archive, we need to forget all the
// this because we cannot replace an open file on Windows.
cleanUpMemory();
- if (TmpArchive.renamePathOnDisk(archPath, error))
- return false;
+ if (TmpArchive.renamePathOnDisk(archPath, ErrMsg))
+ return true;
- return true;
+ return false;
}
// 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
// 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");
data = 0;
path = newFile;
path.getMagicNumber(magic,4);
signature = magic.c_str();
std::string err;
- if (path.getFileStatus(info, &err))
- throw err;
+ if (path.getFileStatus(info, ErrMsg))
+ return true;
}
// Determine what kind of file it is
flags &= ~(BytecodeFlag|CompressedBytecodeFlag);
break;
}
+ return false;
}
// Archive constructor - this is the only constructor that gets used for the
// Archive class. Everything else (default,copy) is deprecated. This just
// 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(),
symTabSize(0), firstFileOffset(0), modules(), foreignST(0)
{
- if (map) {
- std::string ErrMsg;
- mapfile = new sys::MappedFile();
- if (mapfile->open(filename, sys::MappedFile::READ_ACCESS, &ErrMsg))
- throw ErrMsg;
- if (!(base = (char*) mapfile->map(&ErrMsg)))
- throw ErrMsg;
- }
+}
+
+bool
+Archive::mapToMemory(std::string* ErrMsg)
+{
+ mapfile = new sys::MappedFile();
+ if (mapfile->open(archPath, sys::MappedFile::READ_ACCESS, ErrMsg))
+ return true;
+ if (!(base = (char*) mapfile->map(ErrMsg)))
+ return true;
+ return false;
}
void Archive::cleanUpMemory() {
Archive*
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))
return 0;
return result.release();
// Open the archive and load just the symbol tables
Archive*
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))
return 0;
return result.release();
// Create an empty archive.
Archive*
Archive::CreateEmpty(const sys::Path& FilePath ) {
- Archive* result = new Archive(FilePath,false);
+ Archive* result = new Archive(FilePath);
return result;
}
// Insert a file into the archive before some other member. This also takes care
// of extracting the necessary flags and information from the file.
-void
-Archive::addFileBefore(const sys::Path& filePath, iterator where) {
+bool
+Archive::addFileBefore(const sys::Path& filePath, iterator where,
+ std::string* ErrMsg) {
assert(filePath.exists() && "Can't add a non-existent file");
ArchiveMember* mbr = new ArchiveMember(this);
mbr->data = 0;
mbr->path = filePath;
- std::string err;
- if (mbr->path.getFileStatus(mbr->info, &err))
- throw err;
+ if (mbr->path.getFileStatus(mbr->info, ErrMsg))
+ return true;
unsigned flags = 0;
bool hasSlash = filePath.toString().find('/') != std::string::npos;
}
mbr->flags = flags;
members.insert(where,mbr);
+ return false;
}
// Write one member out to the file.
bool CreateSymbolTable,
bool TruncateNames,
bool ShouldCompress,
- std::string* error
+ std::string* ErrMsg
) {
unsigned filepos = ARFile.tellp();
const char* data = (const char*)member.getData();
sys::MappedFile* mFile = 0;
if (!data) {
- std::string ErrMsg;
mFile = new sys::MappedFile();
- if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, &ErrMsg))
- throw ErrMsg;
- if (!(data = (const char*) mFile->map(&ErrMsg)))
- throw ErrMsg;
+ if (mFile->open(member.getPath(), sys::MappedFile::READ_ACCESS, ErrMsg))
+ return true;
+ if (!(data = (const char*) mFile->map(ErrMsg)))
+ return true;
fSize = mFile->size();
}
mFile->close();
delete mFile;
}
- if (error)
- *error = "Can't parse bytecode member: " + member.getPath().toString();
+ if (ErrMsg)
+ *ErrMsg = "Can't parse bytecode member: " + member.getPath().toString();
+ return true;
}
}
data +=4;
fSize -= 4;
}
- fSize = Compressor::compressToNewBuffer(data,fSize,output,error);
+ fSize = Compressor::compressToNewBuffer(data,fSize,output,ErrMsg);
if (fSize == 0)
- return false;
+ return true;
data = output;
if (member.isBytecode())
hdrSize = -fSize-4;
mFile->close();
delete mFile;
}
- return true;
+ return false;
}
// Write out the LLVM symbol table as an archive member to the file.
// compressing each archive member.
bool
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,
// but are now trying to write it which would wipe out the file.
// Create a temporary file to store the archive in
sys::Path TmpArchive = archPath;
- if (TmpArchive.createTemporaryFileOnDisk(error))
- return false;
+ if (TmpArchive.createTemporaryFileOnDisk(ErrMsg))
+ return true;
// Make sure the temporary gets removed if we crash
sys::RemoveFileOnSignal(TmpArchive);
if (!ArchiveFile.is_open() || ArchiveFile.bad()) {
if (TmpArchive.exists())
TmpArchive.eraseFromDisk();
- if (error)
- *error = "Error opening archive file: " + archPath.toString();
- return false;
+ if (ErrMsg)
+ *ErrMsg = "Error opening archive file: " + archPath.toString();
+ return true;
}
// If we're creating a symbol table, reset it now
// Loop over all member files, and write them out. Note that this also
// builds the symbol table, symTab.
for (MembersList::iterator I = begin(), E = end(); I != E; ++I) {
- if (!writeMember(*I, ArchiveFile, CreateSymbolTable,
- TruncateNames, Compress, error)) {
+ if (writeMember(*I, ArchiveFile, CreateSymbolTable,
+ TruncateNames, Compress, ErrMsg)) {
if (TmpArchive.exists())
TmpArchive.eraseFromDisk();
ArchiveFile.close();
- return false;
+ return true;
}
}
// Map in the archive we just wrote.
sys::MappedFile arch;
- std::string ErrMsg;
- if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, &ErrMsg))
- throw ErrMsg;
+ if (arch.open(TmpArchive, sys::MappedFile::READ_ACCESS, ErrMsg))
+ return true;
const char* base;
- if (!(base = (const char*) arch.map(&ErrMsg)))
- throw ErrMsg;
+ if (!(base = (const char*) arch.map(ErrMsg)))
+ return true;
// Open another temporary file in order to avoid invalidating the
// mmapped data
sys::Path FinalFilePath = archPath;
- if (FinalFilePath.createTemporaryFileOnDisk(error))
- return false;
+ 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();
- if (error)
- *error = "Error opening archive file: " + FinalFilePath.toString();
- return false;
+ if (ErrMsg)
+ *ErrMsg = "Error opening archive file: " + FinalFilePath.toString();
+ return true;
}
// Write the file magic number
// 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, false, error)) {
+ if (writeMember(*foreignST, FinalFile, false, false, false, ErrMsg)) {
FinalFile.close();
if (TmpArchive.exists())
TmpArchive.eraseFromDisk();
- return false;
+ return true;
}
}
arch.close();
// Move the final file over top of TmpArchive
- if (FinalFilePath.renamePathOnDisk(TmpArchive, error))
- return false;
+ if (FinalFilePath.renamePathOnDisk(TmpArchive, ErrMsg))
+ return true;
}
// Before we replace the actual archive, we need to forget all the
// this because we cannot replace an open file on Windows.
cleanUpMemory();
- if (TmpArchive.renamePathOnDisk(archPath, error))
- return false;
+ if (TmpArchive.renamePathOnDisk(archPath, ErrMsg))
+ return true;
- return true;
+ return false;
}
// Append them quickly.
for (std::set<sys::Path>::iterator PI = Paths.begin(), PE = Paths.end();
PI != PE; ++PI) {
- TheArchive->addFileBefore(*PI,TheArchive->end());
+ if (TheArchive->addFileBefore(*PI,TheArchive->end(),ErrMsg))
+ return true;
}
// We're done editting, reconstruct the archive.
sys::FileStatus si;
std::string Err;
if (found->getFileStatus(si, &Err))
- throw Err;
+ return true;
if (si.isDir) {
if (OnlyUpdate) {
// Replace the item only if it is newer.
if (si.modTime > I->getModTime())
- I->replaceWith(*found);
+ if (I->replaceWith(*found, ErrMsg))
+ return true;
} else {
// Replace the item regardless of time stamp
- I->replaceWith(*found);
+ if (I->replaceWith(*found, ErrMsg))
+ return true;
}
} else {
// We purposefully ignore directories.
if (!remaining.empty()) {
for (std::set<sys::Path>::iterator PI = remaining.begin(),
PE = remaining.end(); PI != PE; ++PI) {
- TheArchive->addFileBefore(*PI,insert_spot);
+ if (TheArchive->addFileBefore(*PI,insert_spot, ErrMsg))
+ return true;
}
}