X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-ar%2FArchiveWriter.cpp;h=bdccf3e0d91d1ecfef0c75feb7b2a5ac00da98d9;hb=11eb51e23935e22e1cb7b346c45713e8c9169c84;hp=5b74b26110263e4218281d964cdd7da15d3151a7;hpb=b4900b132eb899671b6ea7ca9f185d493cf0c564;p=oota-llvm.git diff --git a/tools/llvm-ar/ArchiveWriter.cpp b/tools/llvm-ar/ArchiveWriter.cpp index 5b74b261102..bdccf3e0d91 100644 --- a/tools/llvm-ar/ArchiveWriter.cpp +++ b/tools/llvm-ar/ArchiveWriter.cpp @@ -80,7 +80,7 @@ Archive* Archive::CreateEmpty(StringRef FilePath, LLVMContext& C) { // compressed. bool Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr, - int sz, bool TruncateNames) const { + int sz) const { // Set the permissions mode, uid and gid hdr.init(); @@ -97,13 +97,7 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr, sprintf(buffer,"%-12u", unsigned(secondsSinceEpoch)); memcpy(hdr.date,buffer,12); - // Get rid of trailing blanks in the name - std::string mbrPath = mbr.getPath().str(); - size_t mbrLen = mbrPath.length(); - while (mbrLen > 0 && mbrPath[mbrLen-1] == ' ') { - mbrPath.erase(mbrLen-1,1); - mbrLen--; - } + std::string mbrPath = sys::path::filename(mbr.getPath()); // Set the name field in one of its various flavors. bool writeLongName = false; @@ -113,18 +107,6 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr, memcpy(hdr.name,ARFILE_SVR4_SYMTAB_NAME,16); } else if (mbr.isBSD4SymbolTable()) { memcpy(hdr.name,ARFILE_BSD4_SYMTAB_NAME,16); - } else if (TruncateNames) { - const char* nm = mbrPath.c_str(); - unsigned len = mbrPath.length(); - size_t slashpos = mbrPath.rfind('/'); - if (slashpos != std::string::npos) { - nm += slashpos + 1; - len -= slashpos +1; - } - if (len > 15) - len = 15; - memcpy(hdr.name,nm,len); - hdr.name[len] = '/'; } else if (mbrPath.length() < 16 && mbrPath.find('/') == std::string::npos) { memcpy(hdr.name,mbrPath.c_str(),mbrPath.length()); hdr.name[mbrPath.length()] = '/'; @@ -155,8 +137,7 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr, // of extracting the necessary flags and information from the file. bool Archive::addFileBefore(StringRef filePath, iterator where, std::string *ErrMsg) { - bool Exists; - if (sys::fs::exists(filePath.str(), Exists) || !Exists) { + if (!sys::fs::exists(filePath)) { if (ErrMsg) *ErrMsg = "Can not add a non-existent file to archive"; return true; @@ -165,36 +146,31 @@ bool Archive::addFileBefore(StringRef filePath, iterator where, ArchiveMember* mbr = new ArchiveMember(this); mbr->data = 0; - mbr->path = filePath.str(); - sys::PathWithStatus PWS(mbr->path); - const sys::FileStatus *FSInfo = PWS.getFileStatus(false, ErrMsg); - if (!FSInfo) { + mbr->path = filePath; + sys::fs::file_status Status; + error_code EC = sys::fs::status(filePath, Status); + if (EC) { + delete mbr; + return true; + } + mbr->User = Status.getUser(); + mbr->Group = Status.getGroup(); + mbr->Mode = Status.permissions(); + mbr->ModTime = Status.getLastModificationTime(); + // FIXME: On posix this is a second stat. + EC = sys::fs::file_size(filePath, mbr->Size); + if (EC) { delete mbr; return true; } - mbr->User = FSInfo->getUser(); - mbr->Group = FSInfo->getGroup(); - mbr->Mode = FSInfo->getMode(); - mbr->ModTime = FSInfo->getTimestamp(); - mbr->Size = FSInfo->getSize(); unsigned flags = 0; - bool hasSlash = filePath.str().find('/') != std::string::npos; - if (hasSlash) - flags |= ArchiveMember::HasPathFlag; - if (hasSlash || filePath.str().length() > 15) + if (sys::path::filename(filePath).size() > 15) flags |= ArchiveMember::HasLongFilenameFlag; sys::fs::file_magic type; if (sys::fs::identify_magic(mbr->path, type)) type = sys::fs::file_magic::unknown; - switch (type) { - case sys::fs::file_magic::bitcode: - flags |= ArchiveMember::BitcodeFlag; - break; - default: - break; - } mbr->flags = flags; members.insert(where,mbr); return false; @@ -204,13 +180,11 @@ bool Archive::addFileBefore(StringRef filePath, iterator where, bool Archive::writeMember( const ArchiveMember& member, - std::ofstream& ARFile, - bool CreateSymbolTable, - bool TruncateNames, + raw_fd_ostream& ARFile, std::string* ErrMsg ) { - unsigned filepos = ARFile.tellp(); + uint64_t filepos = ARFile.tell(); filepos -= 8; // Get the data and its size either from the @@ -230,60 +204,26 @@ Archive::writeMember( fSize = mFile->getBufferSize(); } - // Now that we have the data in memory, update the - // symbol table if it's a bitcode file. - if (CreateSymbolTable && member.isBitcode()) { - std::vector symbols; - std::string FullMemberName = - (archPath + "(" + member.getPath() + ")").str(); - Module* M = - GetBitcodeSymbols(data, fSize, FullMemberName, Context, symbols, ErrMsg); - - // If the bitcode parsed successfully - if ( M ) { - for (std::vector::iterator SI = symbols.begin(), - SE = symbols.end(); SI != SE; ++SI) { - - std::pair Res = - symTab.insert(std::make_pair(*SI,filepos)); - - if (Res.second) { - symTabSize += SI->length() + - numVbrBytes(SI->length()) + - numVbrBytes(filepos); - } - } - // We don't need this module any more. - delete M; - } else { - delete mFile; - if (ErrMsg) - *ErrMsg = "Can't parse bitcode member: " + member.getPath().str() - + ": " + *ErrMsg; - return true; - } - } - int hdrSize = fSize; // Compute the fields of the header ArchiveMemberHeader Hdr; - bool writeLongName = fillHeader(member,Hdr,hdrSize,TruncateNames); + bool writeLongName = fillHeader(member,Hdr,hdrSize); // Write header to archive file ARFile.write((char*)&Hdr, sizeof(Hdr)); // Write the long filename if its long if (writeLongName) { - ARFile.write(member.getPath().str().data(), - member.getPath().str().length()); + StringRef Name = sys::path::filename(member.getPath()); + ARFile.write(Name.data(), Name.size()); } // Write the (possibly compressed) member's content to the file. ARFile.write(data,fSize); // Make sure the member is an even length - if ((ARFile.tellp() & 1) == 1) + if ((ARFile.tell() & 1) == 1) ARFile << ARFILE_PAD; // Close the mapped file if it was opened @@ -295,10 +235,7 @@ Archive::writeMember( // This writes to a temporary file first. Options are for creating a symbol // table, flattening the file names (no directories, 15 chars max) and // compressing each archive member. -bool -Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, - std::string* ErrMsg) -{ +bool Archive::writeToDisk(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. if (members.empty() && mapfile && mapfile->getBufferSize() > 8) { @@ -308,31 +245,18 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, } // Create a temporary file to store the archive in - sys::Path TmpArchive(archPath); - if (TmpArchive.createTemporaryFileOnDisk(ErrMsg)) + int TmpArchiveFD; + SmallString<128> TmpArchive; + error_code EC = sys::fs::createUniqueFile( + archPath + ".temp-archive-%%%%%%%.a", TmpArchiveFD, TmpArchive); + if (EC) return true; // Make sure the temporary gets removed if we crash - sys::RemoveFileOnSignal(TmpArchive.str()); + sys::RemoveFileOnSignal(TmpArchive); // Create archive file for output. - std::ios::openmode io_mode = std::ios::out | std::ios::trunc | - std::ios::binary; - std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode); - - // Check for errors opening or creating archive file. - if (!ArchiveFile.is_open() || ArchiveFile.bad()) { - TmpArchive.eraseFromDisk(); - if (ErrMsg) - *ErrMsg = "Error opening archive file: " + archPath; - return true; - } - - // If we're creating a symbol table, reset it now - if (CreateSymbolTable) { - symTabSize = 0; - symTab.clear(); - } + raw_fd_ostream ArchiveFile(TmpArchiveFD, true); // Write magic string to archive. ArchiveFile << ARFILE_MAGIC; @@ -340,9 +264,8 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, // 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, ErrMsg)) { - TmpArchive.eraseFromDisk(); + if (writeMember(*I, ArchiveFile, ErrMsg)) { + sys::fs::remove(Twine(TmpArchive)); ArchiveFile.close(); return true; } @@ -351,83 +274,15 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, // Close archive file. ArchiveFile.close(); - // 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 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; - } - // 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(sys::Path(archPath), ErrMsg)) - return true; - - // Set correct read and write permissions after temporary file is moved - // to final destination path. - if (sys::Path(archPath).makeReadableOnDisk(ErrMsg)) - return true; - if (sys::Path(archPath).makeWriteableOnDisk(ErrMsg)) + if (sys::fs::rename(Twine(TmpArchive), archPath)) { + *ErrMsg = EC.message(); return true; + } return false; }