// 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, std::string* ErrMsg) { if (!filePath.exists()) { if (ErrMsg) *ErrMsg = "Can not add a non-existent file to archive"; return true; } ArchiveMember* mbr = new ArchiveMember(this); mbr->data = 0; mbr->path = filePath; const sys::FileStatus *FSInfo = mbr->path.getFileStatus(false, ErrMsg); if (!FSInfo) { delete mbr; return true; } mbr->info = *FSInfo; unsigned flags = 0; bool hasSlash = filePath.str().find('/') != std::string::npos; if (hasSlash) flags |= ArchiveMember::HasPathFlag; if (hasSlash || filePath.str().length() > 15) flags |= ArchiveMember::HasLongFilenameFlag; std::string magic; mbr->path.getMagicNumber(magic,4); switch (sys::IdentifyFileType(magic.c_str(),4)) { case sys::Bitcode_FileType: flags |= ArchiveMember::BitcodeFlag; break; default: break; } mbr->flags = flags; members.insert(where,mbr); 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. bool ArchiveMember::replaceWith(const sys::Path& newFile, std::string* ErrMsg) { if (!newFile.exists()) { if (ErrMsg) *ErrMsg = "Can not replace an archive member with a non-existent file"; return true; } data = 0; path = newFile; // SVR4 symbol tables have an empty name if (path.str() == ARFILE_SVR4_SYMTAB_NAME) flags |= SVR4SymbolTableFlag; else flags &= ~SVR4SymbolTableFlag; // BSD4.4 symbol tables have a special name if (path.str() == ARFILE_BSD4_SYMTAB_NAME) flags |= BSD4SymbolTableFlag; else flags &= ~BSD4SymbolTableFlag; // LLVM symbol tables have a very specific name if (path.str() == ARFILE_LLVM_SYMTAB_NAME) flags |= LLVMSymbolTableFlag; else flags &= ~LLVMSymbolTableFlag; // String table name if (path.str() == ARFILE_STRTAB_NAME) flags |= StringTableFlag; else flags &= ~StringTableFlag; // If it has a slash then it has a path bool hasSlash = path.str().find('/') != std::string::npos; if (hasSlash) flags |= HasPathFlag; else flags &= ~HasPathFlag; // If it has a slash or its over 15 chars then its a long filename format if (hasSlash || path.str().length() > 15) flags |= HasLongFilenameFlag; else flags &= ~HasLongFilenameFlag; // Get the signature and status info const char* signature = (const char*) data; std::string magic; if (!signature) { path.getMagicNumber(magic,4); signature = magic.c_str(); std::string err; const sys::FileStatus *FSinfo = path.getFileStatus(false, ErrMsg); if (FSinfo) info = *FSinfo; else return true; } // Determine what kind of file it is. switch (sys::IdentifyFileType(signature,4)) { case sys::Bitcode_FileType: flags |= BitcodeFlag; break; default: flags &= ~BitcodeFlag; break; } return false; }