// import-archive.cc -- Go frontend read import data from an archive file.

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "go-system.h"

#include "go-diagnostics.h"
#include "import.h"

#ifndef O_BINARY
#define O_BINARY 0
#endif

// Archive magic numbers.

static const char armag[] =
{
  '!', '<', 'a', 'r', 'c', 'h', '>', '\n'
};

static const char armagt[] =
{
  '!', '<', 't', 'h', 'i', 'n', '>', '\n'
};

static const char armagb[] =
{
  '<', 'b', 'i', 'g', 'a', 'f', '>', '\n'
};

static const char arfmag[2] = { '`', '\n' };

// Archive fixed length header for AIX big format.

struct Archive_fl_header
{
  // Archive magic string.
  char fl_magic[8];
  // Offset to member table.
  char fl_memoff[20];
  // Offset to global symbol table.
  char fl_gstoff[20];
  // Offset to global symbol table for 64-bit objects.
  char fl_gst64off[20];
  // Offset to first archive member.
  char fl_fstmoff[20];
  // Offset to last archive member.
  char fl_lstmoff[20];
  // Offset to first member on free list.
  char fl_freeoff[20];
};

// The header of an entry in an archive.  This is all readable text,
// padded with spaces where necesary.

struct Archive_header
{
  // The entry name.
  char ar_name[16];
  // The file modification time.
  char ar_date[12];
  // The user's UID in decimal.
  char ar_uid[6];
  // The user's GID in decimal.
  char ar_gid[6];
  // The file mode in octal.
  char ar_mode[8];
  // The file size in decimal.
  char ar_size[10];
  // The final magic code.
  char ar_fmag[2];
};

// The header of an entry in an AIX big archive.
// This is followed by ar_namlen bytes + 2 bytes for arfmag.

struct Archive_big_header
{
  // The file size in decimal.
  char ar_size[20];
  // The next member offset in decimal.
  char ar_nxtmem[20];
  // The previous member offset in decimal.
  char ar_prvmem[20];
  // The file modification time in decimal.
  char ar_date[12];
  // The user's UID in decimal.
  char ar_uid[12];
  // The user's GID in decimal.
  char ar_gid[12];
  // The file mode in octal.
  char ar_mode[12];
  // The file name length in decimal.
  char ar_namlen[4];
};

// The functions in this file extract Go export data from an archive.

const int Import::archive_magic_len;

// Return true if BYTES, which are from the start of the file, are an
// archive magic number.

bool
Import::is_archive_magic(const char* bytes)
{
  return (memcmp(bytes, armag, Import::archive_magic_len) == 0
	  || memcmp(bytes, armagt, Import::archive_magic_len) == 0
	  || memcmp(bytes, armagb, Import::archive_magic_len) == 0);
}

// An object used to read an archive file.

class Archive_file
{
 public:
  Archive_file(const std::string& filename, int fd, Location location)
    : filename_(filename), fd_(fd), filesize_(-1), first_member_offset_(0),
      extended_names_(), is_thin_archive_(false), is_big_archive_(false),
      location_(location), nested_archives_()
  { }

  // Initialize.
  bool
  initialize();

  // Return the file name.
  const std::string&
  filename() const
  { return this->filename_; }

  // Get the file size.
  off_t
  filesize() const
  { return this->filesize_; }

  // Return the offset of the first member.
  off_t
  first_member_offset() const
  { return this->first_member_offset_; }

  // Return whether this is a thin archive.
  bool
  is_thin_archive() const
  { return this->is_thin_archive_; }

  // Return whether this is a big archive.
  bool
  is_big_archive() const
  { return this->is_big_archive_; }

  // Return the location of the import statement.
  Location
  location() const
  { return this->location_; }

  // Read bytes.
  bool
  read(off_t offset, off_t size, char*);

  // Parse a decimal in readable text.
  bool
  parse_decimal(const char* str, off_t size, long* res) const;

  // Read the archive header at OFF, setting *PNAME, *SIZE,
  // *NESTED_OFF and *NEXT_OFF.
  bool
  read_header(off_t off, std::string* pname, off_t* size, off_t* nested_off,
              off_t* next_off);

  // Interpret the header of HDR, the header of the archive member at
  // file offset OFF.  Return whether it succeeded.  Set *SIZE to the
  // size of the member.  Set *PNAME to the name of the member.  Set
  // *NESTED_OFF to the offset in a nested archive.
  bool
  interpret_header(const Archive_header* hdr, off_t off,
		   std::string* pname, off_t* size, off_t* nested_off) const;

  // Get the file and offset for an archive member.
  bool
  get_file_and_offset(off_t off, const std::string& hdrname,
		      off_t nested_off, int* memfd, off_t* memoff,
		      std::string* memname);

 private:
  // Initialize a big archive (AIX)
  bool
  initialize_big_archive();

  // Initialize a normal archive
  bool
  initialize_archive();

  // Read the big archive header at OFF, setting *PNAME, *SIZE and *NEXT_OFF.
  bool
  read_big_archive_header(off_t off, std::string* pname,
                          off_t* size, off_t* next_off);

  // Read the normal archive header at OFF, setting *PNAME, *SIZE,
  // *NESTED_OFF and *NEXT_OFF.
  bool
  read_archive_header(off_t off, std::string* pname, off_t* size,
                      off_t* nested_off, off_t* next_off);

  // For keeping track of open nested archives in a thin archive file.
  typedef std::map<std::string, Archive_file*> Nested_archive_table;

  // The name of the file.
  std::string filename_;
  // The file descriptor.
  int fd_;
  // The file size;
  off_t filesize_;
  // The first member offset;
  off_t first_member_offset_;
  // The extended name table.
  std::string extended_names_;
  // Whether this is a thin archive.
  bool is_thin_archive_;
  // Whether this is a big archive.
  bool is_big_archive_;
  // The location of the import statements.
  Location location_;
  // Table of nested archives.
  Nested_archive_table nested_archives_;
};

bool
Archive_file::initialize()
{
  struct stat st;
  if (fstat(this->fd_, &st) < 0)
    {
      go_error_at(this->location_, "%s: %m", this->filename_.c_str());
      return false;
    }
  this->filesize_ = st.st_size;

  char buf[sizeof(armagt)];
  if (::lseek(this->fd_, 0, SEEK_SET) < 0
      || ::read(this->fd_, buf, sizeof(armagt)) != sizeof(armagt))
    {
      go_error_at(this->location_, "%s: %m", this->filename_.c_str());
      return false;
    }
  if (memcmp(buf, armagt, sizeof(armagt)) == 0)
    this->is_thin_archive_ = true;
  else if (memcmp(buf, armagb, sizeof(armagb)) == 0)
    this->is_big_archive_ = true;

  if (this->is_big_archive_)
    return this->initialize_big_archive();
  else
    return this->initialize_archive();
}

// Initialize a big archive (AIX).

bool
Archive_file::initialize_big_archive()
{
  Archive_fl_header flhdr;

  // Read the fixed length header.
  if (::lseek(this->fd_, 0, SEEK_SET) < 0
      || ::read(this->fd_, &flhdr, sizeof(flhdr)) != sizeof(flhdr))
    {
      go_error_at(this->location_, "%s: could not read archive header",
                  this->filename_.c_str());
      return false;
    }

  // Parse offset of the first member.
  long off;
  if (!this->parse_decimal(flhdr.fl_fstmoff, sizeof(flhdr.fl_fstmoff), &off))
    {
      char* buf = new char[sizeof(flhdr.fl_fstmoff) + 1];
      memcpy(buf, flhdr.fl_fstmoff, sizeof(flhdr.fl_fstmoff));
      go_error_at(this->location_,
                  ("%s: malformed first member offset in archive header"
                   " (expected decimal, got %s)"),
                  this->filename_.c_str(), buf);
      delete[] buf;
      return false;
    }
  if (off == 0) // Empty archive.
    this->first_member_offset_ = this->filesize_;
  else
    this->first_member_offset_ = off;
  return true;
}

// Initialize a normal archive.

bool
Archive_file::initialize_archive()
{
  this->first_member_offset_ = sizeof(armag);
  if (this->first_member_offset_ == this->filesize_)
    {
      // Empty archive.
      return true;
    }

  // Look for the extended name table.
  std::string filename;
  off_t size;
  off_t next_off;
  if (!this->read_header(this->first_member_offset_, &filename,
                         &size, NULL, &next_off))
    return false;
  if (filename.empty())
    {
      // We found the symbol table.
      if (!this->read_header(next_off, &filename, &size, NULL, NULL))
	filename.clear();
    }
  if (filename == "/")
    {
      char* rdbuf = new char[size];
      if (::read(this->fd_, rdbuf, size) != size)
	{
	  go_error_at(this->location_, "%s: could not read extended names",
		   filename.c_str());
	  delete[] rdbuf;
	  return false;
	}
      this->extended_names_.assign(rdbuf, size);
      delete[] rdbuf;
    }

  return true;
}

// Read bytes from the file.

bool
Archive_file::read(off_t offset, off_t size, char* buf)
{
  if (::lseek(this->fd_, offset, SEEK_SET) < 0
      || ::read(this->fd_, buf, size) != size)
    {
      go_error_at(this->location_, "%s: %m", this->filename_.c_str());
      return false;
    }
  return true;
}

// Parse a decimal in readable text.

bool
Archive_file::parse_decimal(const char* str, off_t size, long* res) const
{
  char* buf = new char[size + 1];
  memcpy(buf, str, size);
  char* ps = buf + size;
  while (ps > buf && ps[-1] == ' ')
    --ps;
  *ps = '\0';

  errno = 0;
  char* end;
  *res = strtol(buf, &end, 10);
  if (*end != '\0'
      || *res < 0
      || (*res == LONG_MAX && errno == ERANGE))
    {
      delete[] buf;
      return false;
    }
  delete[] buf;
  return true;
}

// Read the header at OFF.  Set *PNAME to the name, *SIZE to the size,
// *NESTED_OFF to the nested offset, and *NEXT_OFF to the next member offset.

bool
Archive_file::read_header(off_t off, std::string* pname, off_t* size,
			  off_t* nested_off, off_t* next_off)
{
  if (::lseek(this->fd_, off, SEEK_SET) < 0)
    {
      go_error_at(this->location_, "%s: %m", this->filename_.c_str());
      return false;
    }
  if (this->is_big_archive_)
    return this->read_big_archive_header(off, pname, size, next_off);
  else
    return this->read_archive_header(off, pname, size, nested_off, next_off);
}

// Read the big archive header at OFF, setting *PNAME, *SIZE and *NEXT_OFF.

bool
Archive_file::read_big_archive_header(off_t off, std::string* pname,
                                      off_t* size, off_t* next_off)
{
  Archive_big_header hdr;
  ssize_t got;

  got = ::read(this->fd_, &hdr, sizeof hdr);
  if (got != sizeof hdr)
    {
      if (got < 0)
        go_error_at(this->location_, "%s: %m", this->filename_.c_str());
      else if (got > 0)
        go_error_at(this->location_, "%s: short entry header at %ld",
                    this->filename_.c_str(), static_cast<long>(off));
      else
        go_error_at(this->location_, "%s: unexpected EOF at %ld",
                    this->filename_.c_str(), static_cast<long>(off));
    }

  long local_size;
  if (!this->parse_decimal(hdr.ar_size, sizeof(hdr.ar_size), &local_size))
    {
      char* buf = new char[sizeof(hdr.ar_size) + 1];
      memcpy(buf, hdr.ar_size, sizeof(hdr.ar_size));
      go_error_at(this->location_,
                  ("%s: malformed ar_size in entry header at %ld"
                   " (expected decimal, got %s)"),
                  this->filename_.c_str(), static_cast<long>(off), buf);
      delete[] buf;
      return false;
    }
  *size = local_size;

  long namlen;
  if (!this->parse_decimal(hdr.ar_namlen, sizeof(hdr.ar_namlen), &namlen))
    {
      char* buf = new char[sizeof(hdr.ar_namlen) + 1];
      memcpy(buf, hdr.ar_namlen, sizeof(hdr.ar_namlen));
      go_error_at(this->location_,
                  ("%s: malformed ar_namlen in entry header at %ld"
                   " (expected decimal, got %s)"),
                  this->filename_.c_str(), static_cast<long>(off), buf);
      delete[] buf;
      return false;
    }
  // Read member name following member header.
  char* rdbuf = new char[namlen];
  got = ::read(this->fd_, rdbuf, namlen);
  if (got != namlen)
    {
      go_error_at(this->location_,
                  "%s: malformed member name in entry header at %ld",
                  this->filename_.c_str(), static_cast<long>(off));
      delete[] rdbuf;
      return false;
    }
  pname->assign(rdbuf, namlen);
  delete[] rdbuf;

  long local_next_off;
  if (!this->parse_decimal(hdr.ar_nxtmem, sizeof(hdr.ar_nxtmem), &local_next_off))
    {
      char* buf = new char[sizeof(hdr.ar_nxtmem) + 1];
      memcpy(buf, hdr.ar_nxtmem, sizeof(hdr.ar_nxtmem));
      go_error_at(this->location_,
                  ("%s: malformed ar_nxtmem in entry header at %ld"
                   " (expected decimal, got %s)"),
                  this->filename_.c_str(), static_cast<long>(off), buf);
      delete[] buf;
      return false;
    }
  if (next_off != NULL)
    {
      if (local_next_off == 0) // Last member.
        *next_off = this->filesize_;
      else
        *next_off = local_next_off;
    }
  return true;
}

// Read the normal archive header at OFF, setting *PNAME, *SIZE,
// *NESTED_OFF and *NEXT_OFF.

bool
Archive_file::read_archive_header(off_t off, std::string* pname, off_t* size,
                                  off_t* nested_off, off_t* next_off)
{
  Archive_header hdr;
  ssize_t got = ::read(this->fd_, &hdr, sizeof hdr);
  if (got != sizeof hdr)
    {
      if (got < 0)
	go_error_at(this->location_, "%s: %m", this->filename_.c_str());
      else if (got > 0)
	go_error_at(this->location_, "%s: short archive header at %ld",
		    this->filename_.c_str(), static_cast<long>(off));
      else
	go_error_at(this->location_, "%s: unexpected EOF at %ld",
		    this->filename_.c_str(), static_cast<long>(off));
    }
  off_t local_nested_off;
  if (!this->interpret_header(&hdr, off, pname, size, &local_nested_off))
    return false;
  if (nested_off != NULL)
    *nested_off = local_nested_off;

  off_t local_next_off;
  local_next_off = off + sizeof(Archive_header);
  if (!this->is_thin_archive_ || pname->empty() || *pname == "/")
    local_next_off += *size;
  if ((local_next_off & 1) != 0)
    ++local_next_off;
  if (local_next_off > this->filesize_) // Last member.
    local_next_off = this->filesize_;
  if (next_off != NULL)
    *next_off = local_next_off;
  return true;
}

// Interpret the header of HDR, the header of the archive member at
// file offset OFF.

bool
Archive_file::interpret_header(const Archive_header* hdr, off_t off,
			       std::string* pname, off_t* size,
			       off_t* nested_off) const
{
  if (memcmp(hdr->ar_fmag, arfmag, sizeof arfmag) != 0)
    {
      go_error_at(this->location_, "%s: malformed archive header at %lu",
		  this->filename_.c_str(), static_cast<unsigned long>(off));
      return false;
    }

  long local_size;
  if (!this->parse_decimal(hdr->ar_size, sizeof hdr->ar_size, &local_size))
    {
      go_error_at(this->location_, "%s: malformed archive header size at %lu",
		  this->filename_.c_str(), static_cast<unsigned long>(off));
      return false;
    }
  *size = local_size;

  *nested_off = 0;
  if (hdr->ar_name[0] != '/')
    {
      const char* name_end = strchr(hdr->ar_name, '/');
      if (name_end == NULL
	  || name_end - hdr->ar_name >= static_cast<int>(sizeof hdr->ar_name))
	{
	  go_error_at(this->location_,
		      "%s: malformed archive header name at %lu",
		      this->filename_.c_str(), static_cast<unsigned long>(off));
	  return false;
	}
      pname->assign(hdr->ar_name, name_end - hdr->ar_name);
    }
  else if (hdr->ar_name[1] == ' ')
    {
      // This is the symbol table.
      pname->clear();
    }
  else if (hdr->ar_name[1] == 'S' && hdr->ar_name[2] == 'Y'
	   && hdr->ar_name[3] == 'M' && hdr->ar_name[4] == '6'
	   && hdr->ar_name[5] == '4' && hdr->ar_name[6] == '/'
	   && hdr->ar_name[7] == ' '
	  )
    {
      // 64-bit symbol table.
      pname->clear();
    }
  else if (hdr->ar_name[1] == '/')
    {
      // This is the extended name table.
      pname->assign(1, '/');
    }
  else
    {
      char* end;
      errno = 0;
      long x = strtol(hdr->ar_name + 1, &end, 10);
      long y = 0;
      if (*end == ':')
        y = strtol(end + 1, &end, 10);
      if (*end != ' '
	  || x < 0
	  || (x == LONG_MAX && errno == ERANGE)
	  || static_cast<size_t>(x) >= this->extended_names_.size())
	{
	  go_error_at(this->location_, "%s: bad extended name index at %lu",
		      this->filename_.c_str(), static_cast<unsigned long>(off));
	  return false;
	}

      const char* name = this->extended_names_.data() + x;
      const char* name_end = strchr(name, '\n');
      if (static_cast<size_t>(name_end - name) > this->extended_names_.size()
	  || name_end[-1] != '/')
	{
	  go_error_at(this->location_,
		      "%s: bad extended name entry at header %lu",
		      this->filename_.c_str(), static_cast<unsigned long>(off));
	  return false;
	}
      pname->assign(name, name_end - 1 - name);
      *nested_off = y;
    }

  return true;
}

// Get the file and offset for an archive member.

bool
Archive_file::get_file_and_offset(off_t off, const std::string& hdrname,
				  off_t nested_off, int* memfd, off_t* memoff,
				  std::string* memname)
{
  if (this->is_big_archive_)
    {
      *memfd = this->fd_;
      *memoff = (off + sizeof(Archive_big_header) + hdrname.length()
                 + sizeof(arfmag));
      if ((*memoff & 1) != 0)
        ++*memoff;
      *memname = this->filename_ + '(' + hdrname + ')';
      return true;
    }
  else if (!this->is_thin_archive_)
    {
      *memfd = this->fd_;
      *memoff = off + sizeof(Archive_header);
      *memname = this->filename_ + '(' + hdrname + ')';
      return true;
    }

  std::string filename = hdrname;
  if (!IS_ABSOLUTE_PATH(filename.c_str()))
    {
      const char* archive_path = this->filename_.c_str();
      const char* basename = lbasename(archive_path);
      if (basename > archive_path)
	filename.replace(0, 0,
			 this->filename_.substr(0, basename - archive_path));
    }

  if (nested_off > 0)
    {
      // This is a member of a nested archive.
      Archive_file* nfile;
      Nested_archive_table::const_iterator p =
	this->nested_archives_.find(filename);
      if (p != this->nested_archives_.end())
	nfile = p->second;
      else
	{
	  int nfd = open(filename.c_str(), O_RDONLY | O_BINARY);
	  if (nfd < 0)
	    {
	      go_error_at(this->location_, "%s: can't open nested archive %s",
			  this->filename_.c_str(), filename.c_str());
	      return false;
	    }
	  nfile = new Archive_file(filename, nfd, this->location_);
	  if (!nfile->initialize())
	    {
	      delete nfile;
	      return false;
	    }
	  this->nested_archives_[filename] = nfile;
	}

      std::string nname;
      off_t nsize;
      off_t nnested_off;
      if (!nfile->read_header(nested_off, &nname, &nsize, &nnested_off, NULL))
	return false;
      return nfile->get_file_and_offset(nested_off, nname, nnested_off,
					memfd, memoff, memname);
    }

  // An external member of a thin archive.
  *memfd = open(filename.c_str(), O_RDONLY | O_BINARY);
  if (*memfd < 0)
    {
      go_error_at(this->location_, "%s: %m", filename.c_str());
      return false;
    }
  *memoff = 0;
  *memname = filename;
  return true;
}

// An archive member iterator.  This is more-or-less copied from gold.

class Archive_iterator
{
 public:
  // The header of an archive member.  This is what this iterator
  // points to.
  struct Header
  {
    // The name of the member.
    std::string name;
    // The file offset of the member.
    off_t off;
    // The file offset of a nested archive member.
    off_t nested_off;
    // The size of the member.
    off_t size;
  };

  Archive_iterator(Archive_file* afile, off_t off)
    : afile_(afile), off_(off)
  { this->read_next_header(); }

  const Header&
  operator*() const
  { return this->header_; }

  const Header*
  operator->() const
  { return &this->header_; }

  Archive_iterator&
  operator++()
  {
    if (this->off_ == this->afile_->filesize())
      return *this;
    this->off_ = this->next_off_;
    this->read_next_header();
    return *this;
  }

  Archive_iterator
  operator++(int)
  {
    Archive_iterator ret = *this;
    ++*this;
    return ret;
  }

  bool
  operator==(const Archive_iterator& p) const
  { return this->off_ == p->off; }

  bool
  operator!=(const Archive_iterator& p) const
  { return this->off_ != p->off; }

 private:
  void
  read_next_header();

  // The underlying archive file.
  Archive_file* afile_;
  // The current offset in the file.
  off_t off_;
  // The offset of the next member.
  off_t next_off_;
  // The current archive header.
  Header header_;
};

// Read the next archive header.

void
Archive_iterator::read_next_header()
{
  off_t filesize = this->afile_->filesize();
  while (true)
    {
      if (this->off_ == filesize)
	{
	  this->header_.off = filesize;
	  return;
	}

      if (!this->afile_->read_header(this->off_, &this->header_.name,
                                     &this->header_.size,
                                     &this->header_.nested_off,
                                     &this->next_off_))
	{
	  this->header_.off = filesize;
	  return;
	}
      this->header_.off = this->off_;

      // Skip special members.
      if (!this->header_.name.empty() && this->header_.name != "/")
	return;

      this->off_ = this->next_off_;
    }
}

// Initial iterator.

Archive_iterator
archive_begin(Archive_file* afile)
{
  return Archive_iterator(afile, afile->first_member_offset());
}

// Final iterator.

Archive_iterator
archive_end(Archive_file* afile)
{
  return Archive_iterator(afile, afile->filesize());
}

// A type of Import_stream which concatenates other Import_streams
// together.

class Stream_concatenate : public Import::Stream
{
 public:
  Stream_concatenate()
    : inputs_()
  { }

  // Add a new stream.
  void
  add(Import::Stream* is)
  { this->inputs_.push_back(is); }

 protected:
  bool
  do_peek(size_t, const char**);

  void
  do_advance(size_t);

 private:
  std::list<Import::Stream*> inputs_;
};

// Peek ahead.

bool
Stream_concatenate::do_peek(size_t length, const char** bytes)
{
  while (true)
    {
      if (this->inputs_.empty())
	return false;
      if (this->inputs_.front()->peek(length, bytes))
	return true;
      delete this->inputs_.front();
      this->inputs_.pop_front();
    }
}

// Advance.

void
Stream_concatenate::do_advance(size_t skip)
{
  while (true)
    {
      if (this->inputs_.empty())
	return;
      if (!this->inputs_.front()->at_eof())
	{
	  // We just assume that this will do the right thing.  It
	  // should be OK since we should never want to skip past
	  // multiple streams.
	  this->inputs_.front()->advance(skip);
	  return;
	}
      delete this->inputs_.front();
      this->inputs_.pop_front();
    }
}

// Import data from an archive.  We walk through the archive and
// import data from each member.

Import::Stream*
Import::find_archive_export_data(const std::string& filename, int fd,
				 Location location)
{
  Archive_file afile(filename, fd, location);
  if (!afile.initialize())
    return NULL;

  Stream_concatenate* ret = new Stream_concatenate;

  bool any_data = false;
  bool any_members = false;
  Archive_iterator pend = archive_end(&afile);
  for (Archive_iterator p = archive_begin(&afile); p != pend; p++)
    {
      any_members = true;
      int member_fd;
      off_t member_off;
      std::string member_name;
      if (!afile.get_file_and_offset(p->off, p->name, p->nested_off,
				     &member_fd, &member_off, &member_name))
	return NULL;

      Import::Stream* is = Import::find_object_export_data(member_name,
							   member_fd,
							   member_off,
							   location);
      if (is != NULL)
	{
	  ret->add(is);
	  any_data = true;
	}
    }

  if (!any_members)
    {
      // It's normal to have an empty archive file when using gobuild.
      return new Stream_from_string("");
    }

  if (!any_data)
    {
      delete ret;
      return NULL;
    }

  return ret;
}
