// dirsearch.cc -- directory searching for gold

// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.

// This file is part of gold.

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.

#include "gold.h"

#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>

#include "debug.h"
#include "gold-threads.h"
#include "options.h"
#include "workqueue.h"
#include "dirsearch.h"

namespace
{

// Read all the files in a directory.

class Dir_cache
{
 public:
  Dir_cache(const char* dirname)
    : dirname_(dirname), files_()
  { }

  // Read the files in the directory.
  void read_files();

  // Return whether a file (a base name) is present in the directory.
  bool find(const std::string&) const;

 private:
  // We can not copy this class.
  Dir_cache(const Dir_cache&);
  Dir_cache& operator=(const Dir_cache&);

  const char* dirname_;
  Unordered_set<std::string> files_;
};

void
Dir_cache::read_files()
{
  DIR* d = opendir(this->dirname_);
  if (d == NULL)
    {
      // We ignore directories which do not exist or are actually file
      // names.
      if (errno != ENOENT && errno != ENOTDIR)
	gold::gold_error(_("%s: can not read directory: %s"),
			 this->dirname_, strerror(errno));
      return;
    }

  dirent* de;
  while ((de = readdir(d)) != NULL)
    this->files_.insert(std::string(de->d_name));

  if (closedir(d) != 0)
    gold::gold_warning("%s: closedir failed: %s", this->dirname_,
		       strerror(errno));
}

bool
Dir_cache::find(const std::string& basename) const
{
  return this->files_.find(basename) != this->files_.end();
}

// A mapping from directory names to caches.  A lock permits
// concurrent update.  There is no lock for read operations--some
// other mechanism must be used to prevent reads from conflicting with
// writes.

class Dir_caches
{
 public:
  Dir_caches()
    : lock_(), caches_()
  { }

  ~Dir_caches();

  // Add a cache for a directory.
  void add(const char*);

  // Look up a directory in the cache.  This much be locked against
  // calls to Add.
  Dir_cache* lookup(const char*) const;

 private:
  // We can not copy this class.
  Dir_caches(const Dir_caches&);
  Dir_caches& operator=(const Dir_caches&);

  typedef Unordered_map<const char*, Dir_cache*> Cache_hash;

  gold::Lock lock_;
  Cache_hash caches_;
};

Dir_caches::~Dir_caches()
{
  for (Cache_hash::iterator p = this->caches_.begin();
       p != this->caches_.end();
       ++p)
    delete p->second;
}

void
Dir_caches::add(const char* dirname)
{
  {
    gold::Hold_lock hl(this->lock_);
    if (this->lookup(dirname) != NULL)
      return;
  }

  Dir_cache* cache = new Dir_cache(dirname);

  cache->read_files();

  {
    gold::Hold_lock hl(this->lock_);

    std::pair<const char*, Dir_cache*> v(dirname, cache);
    std::pair<Cache_hash::iterator, bool> p = this->caches_.insert(v);
    gold_assert(p.second);
  }
}

Dir_cache*
Dir_caches::lookup(const char* dirname) const
{
  Cache_hash::const_iterator p = this->caches_.find(dirname);
  if (p == this->caches_.end())
    return NULL;
  return p->second;
}

// The caches.

Dir_caches* caches;

// A Task to read the directory.

class Dir_cache_task : public gold::Task
{
 public:
  Dir_cache_task(const char* dir, gold::Task_token& token)
    : dir_(dir), token_(token)
  { }

  gold::Task_token*
  is_runnable();

  void
  locks(gold::Task_locker*);

  void
  run(gold::Workqueue*);

  std::string
  get_name() const
  { return std::string("Dir_cache_task ") + this->dir_; }

 private:
  const char* dir_;
  gold::Task_token& token_;
};

// We can always run the task to read the directory.

gold::Task_token*
Dir_cache_task::is_runnable()
{
  return NULL;
}

// Return the locks to hold.  We use a blocker lock to prevent file
// lookups from starting until the directory contents have been read.

void
Dir_cache_task::locks(gold::Task_locker* tl)
{
  tl->add(this, &this->token_);
}

// Run the task--read the directory contents.

void
Dir_cache_task::run(gold::Workqueue*)
{
  caches->add(this->dir_);
}

}

namespace gold
{

// Initialize.

void
Dirsearch::initialize(Workqueue* workqueue,
		      const General_options::Dir_list* directories)
{
  gold_assert(caches == NULL);
  caches = new Dir_caches;
  this->directories_ = directories;
  this->token_.add_blockers(directories->size());
  for (General_options::Dir_list::const_iterator p = directories->begin();
       p != directories->end();
       ++p)
    workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_));
}

// Search for a file.  NOTE: we only log failed file-lookup attempts
// here.  Successfully lookups will eventually get logged in
// File_read::open.

std::string
Dirsearch::find(const std::vector<std::string>& names,
		bool* is_in_sysroot, int* pindex,
		std::string *found_name) const
{
  gold_assert(!this->token_.is_blocked());
  gold_assert(*pindex >= 0);

  for (unsigned int i = static_cast<unsigned int>(*pindex);
       i < this->directories_->size();
       ++i)
    {
      const Search_directory* p = &this->directories_->at(i);
      Dir_cache* pdc = caches->lookup(p->name().c_str());
      gold_assert(pdc != NULL);
      for (std::vector<std::string>::const_iterator n = names.begin();
	   n != names.end();
	   ++n)
	{
	  if (pdc->find(*n))
	    {
	      *is_in_sysroot = p->is_in_sysroot();
	      *pindex = i;
	      *found_name = *n;
	      return p->name() + '/' + *n;
	    }
	  else
	    gold_debug(DEBUG_FILES, "Attempt to open %s/%s failed",
		       p->name().c_str(), (*n).c_str());
	}
    }

  *pindex = -2;
  return std::string();
}

// Search for a file in a directory list.  This is a low-level function and
// therefore can be used before options and parameters are set.

std::string
Dirsearch::find_file_in_dir_list(const std::string& name,
                                 const General_options::Dir_list& directories,
                                 const std::string& extra_search_dir)
{
  struct stat buf;
  std::string extra_name = extra_search_dir + '/' + name;

  if (stat(extra_name.c_str(), &buf) == 0)
    return extra_name;
  for (General_options::Dir_list::const_iterator dir = directories.begin();
       dir != directories.end();
       ++dir)
    {
      std::string full_name = dir->name() + '/' + name;
      if (stat(full_name.c_str(), &buf) == 0)
        return full_name;
    }
  return name;
}

} // End namespace gold.
