//===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the writeArchive function.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/ArchiveWriter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"

#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
#endif

using namespace llvm;

NewArchiveIterator::NewArchiveIterator(const object::Archive::Child &OldMember,
                                       StringRef Name)
    : IsNewMember(false), Name(Name), OldMember(OldMember) {}

NewArchiveIterator::NewArchiveIterator(StringRef FileName)
    : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr, nullptr) {}

StringRef NewArchiveIterator::getName() const { return Name; }

bool NewArchiveIterator::isNewMember() const { return IsNewMember; }

const object::Archive::Child &NewArchiveIterator::getOld() const {
  assert(!IsNewMember);
  return OldMember;
}

StringRef NewArchiveIterator::getNew() const {
  assert(IsNewMember);
  return Name;
}

llvm::ErrorOr<int>
NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
  assert(IsNewMember);
  int NewFD;
  if (auto EC = sys::fs::openFileForRead(Name, NewFD))
    return EC;
  assert(NewFD != -1);

  if (auto EC = sys::fs::status(NewFD, NewStatus))
    return EC;

  // Opening a directory doesn't make sense. Let it fail.
  // Linux cannot open directories with open(2), although
  // cygwin and *bsd can.
  if (NewStatus.type() == sys::fs::file_type::directory_file)
    return make_error_code(errc::is_a_directory);

  return NewFD;
}

template <typename T>
static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
                                  bool MayTruncate = false) {
  uint64_t OldPos = OS.tell();
  OS << Data;
  unsigned SizeSoFar = OS.tell() - OldPos;
  if (Size > SizeSoFar) {
    OS.indent(Size - SizeSoFar);
  } else if (Size < SizeSoFar) {
    assert(MayTruncate && "Data doesn't fit in Size");
    // Some of the data this is used for (like UID) can be larger than the
    // space available in the archive format. Truncate in that case.
    OS.seek(OldPos + Size);
  }
}

static void print32(raw_ostream &Out, object::Archive::Kind Kind,
                    uint32_t Val) {
  if (Kind == object::Archive::K_GNU)
    support::endian::Writer<support::big>(Out).write(Val);
  else
    support::endian::Writer<support::little>(Out).write(Val);
}

static void printRestOfMemberHeader(raw_fd_ostream &Out,
                                    const sys::TimeValue &ModTime, unsigned UID,
                                    unsigned GID, unsigned Perms,
                                    unsigned Size) {
  printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
  printWithSpacePadding(Out, UID, 6, true);
  printWithSpacePadding(Out, GID, 6, true);
  printWithSpacePadding(Out, format("%o", Perms), 8);
  printWithSpacePadding(Out, Size, 10);
  Out << "`\n";
}

static void printGNUSmallMemberHeader(raw_fd_ostream &Out, StringRef Name,
                                      const sys::TimeValue &ModTime,
                                      unsigned UID, unsigned GID,
                                      unsigned Perms, unsigned Size) {
  printWithSpacePadding(Out, Twine(Name) + "/", 16);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
                                 const sys::TimeValue &ModTime, unsigned UID,
                                 unsigned GID, unsigned Perms, unsigned Size) {
  uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
  // Pad so that even 64 bit object files are aligned.
  unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
  unsigned NameWithPadding = Name.size() + Pad;
  printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
                          NameWithPadding + Size);
  Out << Name;
  assert(PosAfterHeader == Out.tell());
  while (Pad--)
    Out.write(uint8_t(0));
}

static bool useStringTable(bool Thin, StringRef Name) {
  return Thin || Name.size() >= 16;
}

static void
printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind, bool Thin,
                  StringRef Name,
                  std::vector<unsigned>::iterator &StringMapIndexIter,
                  const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
                  unsigned Perms, unsigned Size) {
  if (Kind == object::Archive::K_BSD)
    return printBSDMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
  if (!useStringTable(Thin, Name))
    return printGNUSmallMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
  Out << '/';
  printWithSpacePadding(Out, *StringMapIndexIter++, 15);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

// 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);

  return Relative.str();
}

static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
                             ArrayRef<NewArchiveIterator> Members,
                             std::vector<unsigned> &StringMapIndexes,
                             bool Thin) {
  unsigned StartOffset = 0;
  for (const NewArchiveIterator &I : Members) {
    StringRef Name = sys::path::filename(I.getName());
    if (!useStringTable(Thin, Name))
      continue;
    if (StartOffset == 0) {
      printWithSpacePadding(Out, "//", 58);
      Out << "`\n";
      StartOffset = Out.tell();
    }
    StringMapIndexes.push_back(Out.tell() - StartOffset);

    if (Thin)
      Out << computeRelativePath(ArcName, I.getName());
    else
      Out << Name;

    Out << "/\n";
  }
  if (StartOffset == 0)
    return;
  if (Out.tell() % 2)
    Out << '\n';
  int Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(Pos);
}

static sys::TimeValue now(bool Deterministic) {
  if (!Deterministic)
    return sys::TimeValue::now();
  sys::TimeValue TV;
  TV.fromEpochTime(0);
  return TV;
}

// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
                 ArrayRef<NewArchiveIterator> Members,
                 ArrayRef<MemoryBufferRef> Buffers,
                 std::vector<unsigned> &MemberOffsetRefs, bool Deterministic) {
  unsigned HeaderStartOffset = 0;
  unsigned BodyStartOffset = 0;
  SmallString<128> NameBuf;
  raw_svector_ostream NameOS(NameBuf);
  LLVMContext Context;
  for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) {
    MemoryBufferRef MemberBuffer = Buffers[MemberNum];
    ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
        object::SymbolicFile::createSymbolicFile(
            MemberBuffer, sys::fs::file_magic::unknown, &Context);
    if (!ObjOrErr)
      continue;  // FIXME: check only for "not an object file" errors.
    object::SymbolicFile &Obj = *ObjOrErr.get();

    if (!HeaderStartOffset) {
      HeaderStartOffset = Out.tell();
      if (Kind == object::Archive::K_GNU)
        printGNUSmallMemberHeader(Out, "", now(Deterministic), 0, 0, 0, 0);
      else
        printBSDMemberHeader(Out, "__.SYMDEF", now(Deterministic), 0, 0, 0, 0);
      BodyStartOffset = Out.tell();
      print32(Out, Kind, 0); // number of entries or bytes
    }

    for (const object::BasicSymbolRef &S : Obj.symbols()) {
      uint32_t Symflags = S.getFlags();
      if (Symflags & object::SymbolRef::SF_FormatSpecific)
        continue;
      if (!(Symflags & object::SymbolRef::SF_Global))
        continue;
      if (Symflags & object::SymbolRef::SF_Undefined)
        continue;

      unsigned NameOffset = NameOS.tell();
      if (auto EC = S.printName(NameOS))
        return EC;
      NameOS << '\0';
      MemberOffsetRefs.push_back(MemberNum);
      if (Kind == object::Archive::K_BSD)
        print32(Out, Kind, NameOffset);
      print32(Out, Kind, 0); // member offset
    }
  }

  if (HeaderStartOffset == 0)
    return 0;

  StringRef StringTable = NameOS.str();
  if (Kind == object::Archive::K_BSD)
    print32(Out, Kind, StringTable.size()); // byte count of the string table
  Out << StringTable;

  // ld64 requires the next member header to start at an offset that is
  // 4 bytes aligned.
  unsigned Pad = OffsetToAlignment(Out.tell(), 4);
  while (Pad--)
    Out.write(uint8_t(0));

  // Patch up the size of the symbol table now that we know how big it is.
  unsigned Pos = Out.tell();
  const unsigned MemberHeaderSize = 60;
  Out.seek(HeaderStartOffset + 48); // offset of the size field.
  printWithSpacePadding(Out, Pos - MemberHeaderSize - HeaderStartOffset, 10);

  // Patch up the number of symbols.
  Out.seek(BodyStartOffset);
  unsigned NumSyms = MemberOffsetRefs.size();
  if (Kind == object::Archive::K_GNU)
    print32(Out, Kind, NumSyms);
  else
    print32(Out, Kind, NumSyms * 8);

  Out.seek(Pos);
  return BodyStartOffset + 4;
}

std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
                   std::vector<NewArchiveIterator> &NewMembers,
                   bool WriteSymtab, object::Archive::Kind Kind,
                   bool Deterministic, bool Thin) {
  SmallString<128> TmpArchive;
  int TmpArchiveFD;
  if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
                                          TmpArchiveFD, TmpArchive))
    return std::make_pair(ArcName, EC);

  tool_output_file Output(TmpArchive, TmpArchiveFD);
  raw_fd_ostream &Out = Output.os();
  if (Thin)
    Out << "!<thin>\n";
  else
    Out << "!<arch>\n";

  std::vector<unsigned> MemberOffsetRefs;

  std::vector<std::unique_ptr<MemoryBuffer>> Buffers;
  std::vector<MemoryBufferRef> Members;
  std::vector<sys::fs::file_status> NewMemberStatus;

  for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
    NewArchiveIterator &Member = NewMembers[I];
    MemoryBufferRef MemberRef;

    if (Member.isNewMember()) {
      StringRef Filename = Member.getNew();
      NewMemberStatus.resize(NewMemberStatus.size() + 1);
      sys::fs::file_status &Status = NewMemberStatus.back();
      ErrorOr<int> FD = Member.getFD(Status);
      if (auto EC = FD.getError())
        return std::make_pair(Filename, EC);
      ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
          MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(),
                                    false);
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair(Filename, EC);
      if (close(FD.get()) != 0)
        return std::make_pair(Filename,
                              std::error_code(errno, std::generic_category()));
      Buffers.push_back(std::move(MemberBufferOrErr.get()));
      MemberRef = Buffers.back()->getMemBufferRef();
    } else {
      const object::Archive::Child &OldMember = Member.getOld();
      assert((!Thin || OldMember.getParent()->isThin()) &&
             "Thin archives cannot refers to member of other archives");
      ErrorOr<MemoryBufferRef> MemberBufferOrErr =
          OldMember.getMemoryBufferRef();
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair("", EC);
      MemberRef = MemberBufferOrErr.get();
    }
    Members.push_back(MemberRef);
  }

  unsigned MemberReferenceOffset = 0;
  if (WriteSymtab) {
    ErrorOr<unsigned> MemberReferenceOffsetOrErr = writeSymbolTable(
        Out, Kind, NewMembers, Members, MemberOffsetRefs, Deterministic);
    if (auto EC = MemberReferenceOffsetOrErr.getError())
      return std::make_pair(ArcName, EC);
    MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
  }

  std::vector<unsigned> StringMapIndexes;
  if (Kind != object::Archive::K_BSD)
    writeStringTable(Out, ArcName, NewMembers, StringMapIndexes, Thin);

  unsigned MemberNum = 0;
  unsigned NewMemberNum = 0;
  std::vector<unsigned>::iterator StringMapIndexIter = StringMapIndexes.begin();
  std::vector<unsigned> MemberOffset;
  for (const NewArchiveIterator &I : NewMembers) {
    MemoryBufferRef File = Members[MemberNum++];

    unsigned Pos = Out.tell();
    MemberOffset.push_back(Pos);

    sys::TimeValue ModTime;
    unsigned UID;
    unsigned GID;
    unsigned Perms;
    if (Deterministic) {
      ModTime.fromEpochTime(0);
      UID = 0;
      GID = 0;
      Perms = 0644;
    } else if (I.isNewMember()) {
      const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum];
      ModTime = Status.getLastModificationTime();
      UID = Status.getUser();
      GID = Status.getGroup();
      Perms = Status.permissions();
    } else {
      const object::Archive::Child &OldMember = I.getOld();
      ModTime = OldMember.getLastModified();
      UID = OldMember.getUID();
      GID = OldMember.getGID();
      Perms = OldMember.getAccessMode();
    }

    if (I.isNewMember()) {
      StringRef FileName = I.getNew();
      const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
      printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
                        StringMapIndexIter, ModTime, UID, GID, Perms,
                        Status.getSize());
    } else {
      const object::Archive::Child &OldMember = I.getOld();
      ErrorOr<uint32_t> Size = OldMember.getSize();
      if (std::error_code EC = Size.getError())
        return std::make_pair("", EC);
      StringRef FileName = I.getName();
      printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName),
                        StringMapIndexIter, ModTime, UID, GID, Perms,
                        Size.get());
    }

    if (!Thin)
      Out << File.getBuffer();

    if (Out.tell() % 2)
      Out << '\n';
  }

  if (MemberReferenceOffset) {
    Out.seek(MemberReferenceOffset);
    for (unsigned MemberNum : MemberOffsetRefs) {
      if (Kind == object::Archive::K_BSD)
        Out.seek(Out.tell() + 4); // skip over the string offset
      print32(Out, Kind, MemberOffset[MemberNum]);
    }
  }

  Output.keep();
  Out.close();
  sys::fs::rename(TmpArchive, ArcName);
  return std::make_pair("", std::error_code());
}
