return BufOrErr.takeError();
NewArchiveMember M;
+ assert(M.IsNew == false);
M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
M.MemberName = M.Buf->getBufferIdentifier();
if (!Deterministic) {
return errorCodeToError(std::error_code(errno, std::generic_category()));
NewArchiveMember M;
+ M.IsNew = true;
M.Buf = std::move(*MemberBufferOrErr);
M.MemberName = M.Buf->getBufferIdentifier();
if (!Deterministic) {
return Thin || Name.size() >= 16 || Name.contains('/');
}
+// Compute the relative path from From to To.
+static std::string computeRelativePath(StringRef From, StringRef To) {
+ if (sys::path::is_absolute(From) || sys::path::is_absolute(To))
+ return To;
+
+ StringRef DirFrom = sys::path::parent_path(From);
+ auto FromI = sys::path::begin(DirFrom);
+ auto ToI = sys::path::begin(To);
+ while (*FromI == *ToI) {
+ ++FromI;
+ ++ToI;
+ }
+
+ SmallString<128> Relative;
+ for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
+ sys::path::append(Relative, "..");
+
+ for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI)
+ sys::path::append(Relative, *ToI);
+
+#ifdef _WIN32
+ // Replace backslashes with slashes so that the path is portable between *nix
+ // and Windows.
+ std::replace(Relative.begin(), Relative.end(), '\\', '/');
+#endif
+
+ return Relative.str();
+}
+
static bool is64BitKind(object::Archive::Kind Kind) {
switch (Kind) {
case object::Archive::K_GNU:
llvm_unreachable("not supported for writting");
}
-static void
-printMemberHeader(raw_ostream &Out, uint64_t Pos, raw_ostream &StringTable,
- StringMap<uint64_t> &MemberNames, object::Archive::Kind Kind,
- bool Thin, const NewArchiveMember &M,
- sys::TimePoint<std::chrono::seconds> ModTime, unsigned Size) {
+static void addToStringTable(raw_ostream &Out, StringRef ArcName,
+ const NewArchiveMember &M, bool Thin) {
+ StringRef ID = M.Buf->getBufferIdentifier();
+ if (Thin) {
+ if (M.IsNew)
+ Out << computeRelativePath(ArcName, ID);
+ else
+ Out << ID;
+ } else
+ Out << M.MemberName;
+ Out << "/\n";
+}
+
+static void printMemberHeader(raw_ostream &Out, uint64_t Pos,
+ raw_ostream &StringTable,
+ StringMap<uint64_t> &MemberNames,
+ object::Archive::Kind Kind, bool Thin,
+ StringRef ArcName, const NewArchiveMember &M,
+ sys::TimePoint<std::chrono::seconds> ModTime,
+ unsigned Size) {
+
if (isBSDLike(Kind))
return printBSDMemberHeader(Out, Pos, M.MemberName, ModTime, M.UID, M.GID,
M.Perms, Size);
uint64_t NamePos;
if (Thin) {
NamePos = StringTable.tell();
- StringTable << M.MemberName << "/\n";
+ addToStringTable(StringTable, ArcName, M, Thin);
} else {
auto Insertion = MemberNames.insert({M.MemberName, uint64_t(0)});
if (Insertion.second) {
Insertion.first->second = StringTable.tell();
- StringTable << M.MemberName << "/\n";
+ addToStringTable(StringTable, ArcName, M, Thin);
}
NamePos = Insertion.first->second;
}
static Expected<std::vector<MemberData>>
computeMemberData(raw_ostream &StringTable, raw_ostream &SymNames,
- object::Archive::Kind Kind, bool Thin, bool Deterministic,
- ArrayRef<NewArchiveMember> NewMembers) {
+ object::Archive::Kind Kind, bool Thin, StringRef ArcName,
+ bool Deterministic, ArrayRef<NewArchiveMember> NewMembers) {
static char PaddingData[8] = {'\n', '\n', '\n', '\n', '\n', '\n', '\n', '\n'};
// This ignores the symbol table, but we only need the value mod 8 and the
ModTime = sys::toTimePoint(FilenameCount[M.MemberName]++);
else
ModTime = M.ModTime;
- printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, M,
- ModTime, Buf.getBufferSize() + MemberPadding);
+ printMemberHeader(Out, Pos, StringTable, MemberNames, Kind, Thin, ArcName,
+ M, ModTime, Buf.getBufferSize() + MemberPadding);
Out.flush();
Expected<std::vector<unsigned>> Symbols =
raw_svector_ostream StringTable(StringTableBuf);
Expected<std::vector<MemberData>> DataOrErr = computeMemberData(
- StringTable, SymNames, Kind, Thin, Deterministic, NewMembers);
+ StringTable, SymNames, Kind, Thin, ArcName, Deterministic, NewMembers);
if (Error E = DataOrErr.takeError())
return E;
std::vector<MemberData> &Data = *DataOrErr;
// on the command line.
static std::vector<StringRef> Members;
-// Static buffer to hold StringRefs.
-static BumpPtrAllocator Alloc;
-
// Extract the member filename from the command line for the [relpos] argument
// associated with a, b, and i modifiers
static void getRelPos() {
exit(1);
}
-// Compute the relative path from From to To.
-static std::string computeRelativePath(StringRef From, StringRef To) {
- if (sys::path::is_absolute(From) || sys::path::is_absolute(To))
- return To;
-
- StringRef DirFrom = sys::path::parent_path(From);
- auto FromI = sys::path::begin(DirFrom);
- auto ToI = sys::path::begin(To);
- while (*FromI == *ToI) {
- ++FromI;
- ++ToI;
- }
-
- SmallString<128> Relative;
- for (auto FromE = sys::path::end(DirFrom); FromI != FromE; ++FromI)
- sys::path::append(Relative, "..");
-
- for (auto ToE = sys::path::end(To); ToI != ToE; ++ToI)
- sys::path::append(Relative, *ToI);
-
-#ifdef _WIN32
- // Replace backslashes with slashes so that the path is portable between *nix
- // and Windows.
- std::replace(Relative.begin(), Relative.end(), '\\', '/');
-#endif
-
- return Relative.str();
-}
-
static void addChildMember(std::vector<NewArchiveMember> &Members,
const object::Archive::Child &M,
bool FlattenArchive = false) {
Expected<NewArchiveMember> NMOrErr =
NewArchiveMember::getOldMember(M, Deterministic);
failIfError(NMOrErr.takeError());
- // If the child member we're trying to add is thin, use the path relative to
- // the archive it's in, so the file resolves correctly.
- if (Thin && FlattenArchive) {
- StringSaver Saver(Alloc);
- Expected<std::string> FileNameOrErr = M.getFullName();
- failIfError(FileNameOrErr.takeError());
- NMOrErr->MemberName =
- Saver.save(computeRelativePath(ArchiveName, *FileNameOrErr));
- }
if (FlattenArchive &&
identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
Expected<std::string> FileNameOrErr = M.getFullName();
Expected<NewArchiveMember> NMOrErr =
NewArchiveMember::getFile(FileName, Deterministic);
failIfError(NMOrErr.takeError(), FileName);
- StringSaver Saver(Alloc);
- // For regular archives, use the basename of the object path for the member
- // name. For thin archives, use the full relative paths so the file resolves
- // correctly.
- NMOrErr->MemberName =
- Thin ? Saver.save(computeRelativePath(ArchiveName, FileName))
- : sys::path::filename(NMOrErr->MemberName);
if (FlattenArchive &&
identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
object::Archive &Lib = readLibrary(FileName);
return;
}
}
+ // Use the basename of the object path for the member name.
+ NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
Members.push_back(std::move(*NMOrErr));
}
computeInsertAction(Operation, Child, Name, MemberI);
switch (Action) {
case IA_AddOldMember:
- addChildMember(Ret, Child, /*FlattenArchive=*/Thin);
+ addChildMember(Ret, Child);
break;
case IA_AddNewMember:
addMember(Ret, *MemberI);
case IA_Delete:
break;
case IA_MoveOldMember:
- addChildMember(Moved, Child, /*FlattenArchive=*/Thin);
+ addChildMember(Moved, Child);
break;
case IA_MoveNewMember:
addMember(Moved, *MemberI);
{
Error Err = Error::success();
for (auto &Member : Lib.children(Err))
- addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin);
+ addChildMember(NewMembers, Member);
failIfError(std::move(Err));
}
break;
static int ar_main(int argc, char **argv) {
SmallVector<const char *, 0> Argv(argv, argv + argc);
+ BumpPtrAllocator Alloc;
StringSaver Saver(Alloc);
cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
for (size_t i = 1; i < Argv.size(); ++i) {