X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gold%2Fdirsearch.cc;h=e8c9b1203c8e80809d587ad99af85434c75379d7;hb=20955c7cb8aebd8d900441c6ff87df2123e38f54;hp=d1298d81757d1bbb218dd17382941aa938fbaa95;hpb=a3ad94edd406b9abc26493761764d4034dda69fa;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/dirsearch.cc b/gold/dirsearch.cc index d1298d8175..e8c9b1203c 100644 --- a/gold/dirsearch.cc +++ b/gold/dirsearch.cc @@ -1,12 +1,37 @@ // dirsearch.cc -- directory searching for gold +// Copyright (C) 2006-2020 Free Software Foundation, Inc. +// Written by Ian Lance Taylor . + +// 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 +#include #include +#include #include +#include "debug.h" #include "gold-threads.h" +#include "options.h" +#include "workqueue.h" #include "dirsearch.h" namespace @@ -42,14 +67,12 @@ Dir_cache::read_files() DIR* d = opendir(this->dirname_); if (d == NULL) { - // We ignore directories which do not exist. - if (errno == ENOENT) - return; - - char *s = NULL; - if (asprintf(&s, _("can not read directory %s"), this->dirname_) < 0) - gold::gold_nomem(); - gold::gold_fatal(s, true); + // 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; @@ -57,7 +80,8 @@ Dir_cache::read_files() this->files_.insert(std::string(de->d_name)); if (closedir(d) != 0) - gold::gold_fatal("closedir failed", true); + gold::gold_warning("%s: closedir failed: %s", this->dirname_, + strerror(errno)); } bool @@ -78,7 +102,7 @@ class Dir_caches : lock_(), caches_() { } - ~Dir_caches(); + ~Dir_caches() ATTRIBUTE_UNUSED; // Add a cache for a directory. void add(const char*); @@ -139,7 +163,7 @@ Dir_caches::lookup(const char* dirname) const // The caches. -Dir_caches caches; +Dir_caches* caches; // A Task to read the directory. @@ -150,11 +174,18 @@ class Dir_cache_task : public gold::Task : dir_(dir), token_(token) { } - Is_runnable_type is_runnable(gold::Workqueue*); + gold::Task_token* + is_runnable(); - gold::Task_locker* locks(gold::Workqueue*); + void + locks(gold::Task_locker*); - void run(gold::Workqueue*); + void + run(gold::Workqueue*); + + std::string + get_name() const + { return std::string("Dir_cache_task ") + this->dir_; } private: const char* dir_; @@ -163,19 +194,19 @@ class Dir_cache_task : public gold::Task // We can always run the task to read the directory. -gold::Task::Is_runnable_type -Dir_cache_task::is_runnable(gold::Workqueue*) +gold::Task_token* +Dir_cache_task::is_runnable() { - return 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. -gold::Task_locker* -Dir_cache_task::locks(gold::Workqueue* workqueue) +void +Dir_cache_task::locks(gold::Task_locker* tl) { - return new gold::Task_locker_block(this->token_, workqueue); + tl->add(this, &this->token_); } // Run the task--read the directory contents. @@ -183,7 +214,7 @@ Dir_cache_task::locks(gold::Workqueue* workqueue) void Dir_cache_task::run(gold::Workqueue*) { - caches.add(this->dir_); + caches->add(this->dir_); } } @@ -191,46 +222,84 @@ Dir_cache_task::run(gold::Workqueue*) namespace gold { -Dirsearch::Dirsearch() - : directories_(), token_() -{ -} +// Initialize. void -Dirsearch::add(Workqueue* workqueue, const char* d) +Dirsearch::initialize(Workqueue* workqueue, + const General_options::Dir_list* directories) { - this->directories_.push_back(d); - this->token_.add_blocker(); - workqueue->queue(new Dir_cache_task(d, this->token_)); -} - -void -Dirsearch::add(Workqueue* workqueue, const General_options::Dir_list& list) -{ - for (General_options::Dir_list::const_iterator p = list.begin(); - p != list.end(); + 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) - this->add(workqueue, *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::string& n1, const std::string& n2) const +Dirsearch::find(const std::vector& names, + bool* is_in_sysroot, int* pindex, + std::string *found_name) const { gold_assert(!this->token_.is_blocked()); + gold_assert(*pindex >= 0); - for (std::list::const_iterator p = this->directories_.begin(); - p != this->directories_.end(); - ++p) + for (unsigned int i = static_cast(*pindex); + i < this->directories_->size(); + ++i) { - Dir_cache* pdc = caches.lookup(*p); + const Search_directory* p = &this->directories_->at(i); + Dir_cache* pdc = caches->lookup(p->name().c_str()); gold_assert(pdc != NULL); - if (pdc->find(n1)) - return std::string(*p) + '/' + n1; - if (!n2.empty() && pdc->find(n2)) - return std::string(*p) + '/' + n2; + for (std::vector::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.