OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gold/] [dirsearch.cc] - Blame information for rev 328

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 khays
// dirsearch.cc -- directory searching for gold
2
 
3
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4
// Written by Ian Lance Taylor <iant@google.com>.
5
 
6
// This file is part of gold.
7
 
8
// This program is free software; you can redistribute it and/or modify
9
// it under the terms of the GNU General Public License as published by
10
// the Free Software Foundation; either version 3 of the License, or
11
// (at your option) any later version.
12
 
13
// This program is distributed in the hope that it will be useful,
14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
// GNU General Public License for more details.
17
 
18
// You should have received a copy of the GNU General Public License
19
// along with this program; if not, write to the Free Software
20
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
// MA 02110-1301, USA.
22
 
23
#include "gold.h"
24
 
25
#include <cerrno>
26
#include <cstring>
27
#include <sys/types.h>
28 166 khays
#include <sys/stat.h>
29 27 khays
#include <dirent.h>
30
 
31
#include "debug.h"
32
#include "gold-threads.h"
33
#include "options.h"
34
#include "workqueue.h"
35
#include "dirsearch.h"
36
 
37
namespace
38
{
39
 
40
// Read all the files in a directory.
41
 
42
class Dir_cache
43
{
44
 public:
45
  Dir_cache(const char* dirname)
46
    : dirname_(dirname), files_()
47
  { }
48
 
49
  // Read the files in the directory.
50
  void read_files();
51
 
52
  // Return whether a file (a base name) is present in the directory.
53
  bool find(const std::string&) const;
54
 
55
 private:
56
  // We can not copy this class.
57
  Dir_cache(const Dir_cache&);
58
  Dir_cache& operator=(const Dir_cache&);
59
 
60
  const char* dirname_;
61
  Unordered_set<std::string> files_;
62
};
63
 
64
void
65
Dir_cache::read_files()
66
{
67
  DIR* d = opendir(this->dirname_);
68
  if (d == NULL)
69
    {
70 159 khays
      // We ignore directories which do not exist or are actually file
71
      // names.
72
      if (errno != ENOENT && errno != ENOTDIR)
73 27 khays
        gold::gold_error(_("%s: can not read directory: %s"),
74
                         this->dirname_, strerror(errno));
75
      return;
76
    }
77
 
78
  dirent* de;
79
  while ((de = readdir(d)) != NULL)
80
    this->files_.insert(std::string(de->d_name));
81
 
82
  if (closedir(d) != 0)
83
    gold::gold_warning("%s: closedir failed: %s", this->dirname_,
84
                       strerror(errno));
85
}
86
 
87
bool
88
Dir_cache::find(const std::string& basename) const
89
{
90
  return this->files_.find(basename) != this->files_.end();
91
}
92
 
93
// A mapping from directory names to caches.  A lock permits
94
// concurrent update.  There is no lock for read operations--some
95
// other mechanism must be used to prevent reads from conflicting with
96
// writes.
97
 
98
class Dir_caches
99
{
100
 public:
101
  Dir_caches()
102
    : lock_(), caches_()
103
  { }
104
 
105
  ~Dir_caches();
106
 
107
  // Add a cache for a directory.
108
  void add(const char*);
109
 
110
  // Look up a directory in the cache.  This much be locked against
111
  // calls to Add.
112
  Dir_cache* lookup(const char*) const;
113
 
114
 private:
115
  // We can not copy this class.
116
  Dir_caches(const Dir_caches&);
117
  Dir_caches& operator=(const Dir_caches&);
118
 
119
  typedef Unordered_map<const char*, Dir_cache*> Cache_hash;
120
 
121
  gold::Lock lock_;
122
  Cache_hash caches_;
123
};
124
 
125
Dir_caches::~Dir_caches()
126
{
127
  for (Cache_hash::iterator p = this->caches_.begin();
128
       p != this->caches_.end();
129
       ++p)
130
    delete p->second;
131
}
132
 
133
void
134
Dir_caches::add(const char* dirname)
135
{
136
  {
137
    gold::Hold_lock hl(this->lock_);
138
    if (this->lookup(dirname) != NULL)
139
      return;
140
  }
141
 
142
  Dir_cache* cache = new Dir_cache(dirname);
143
 
144
  cache->read_files();
145
 
146
  {
147
    gold::Hold_lock hl(this->lock_);
148
 
149
    std::pair<const char*, Dir_cache*> v(dirname, cache);
150
    std::pair<Cache_hash::iterator, bool> p = this->caches_.insert(v);
151
    gold_assert(p.second);
152
  }
153
}
154
 
155
Dir_cache*
156
Dir_caches::lookup(const char* dirname) const
157
{
158
  Cache_hash::const_iterator p = this->caches_.find(dirname);
159
  if (p == this->caches_.end())
160
    return NULL;
161
  return p->second;
162
}
163
 
164
// The caches.
165
 
166
Dir_caches* caches;
167
 
168
// A Task to read the directory.
169
 
170
class Dir_cache_task : public gold::Task
171
{
172
 public:
173
  Dir_cache_task(const char* dir, gold::Task_token& token)
174
    : dir_(dir), token_(token)
175
  { }
176
 
177
  gold::Task_token*
178
  is_runnable();
179
 
180
  void
181
  locks(gold::Task_locker*);
182
 
183
  void
184
  run(gold::Workqueue*);
185
 
186
  std::string
187
  get_name() const
188
  { return std::string("Dir_cache_task ") + this->dir_; }
189
 
190
 private:
191
  const char* dir_;
192
  gold::Task_token& token_;
193
};
194
 
195
// We can always run the task to read the directory.
196
 
197
gold::Task_token*
198
Dir_cache_task::is_runnable()
199
{
200
  return NULL;
201
}
202
 
203
// Return the locks to hold.  We use a blocker lock to prevent file
204
// lookups from starting until the directory contents have been read.
205
 
206
void
207
Dir_cache_task::locks(gold::Task_locker* tl)
208
{
209
  tl->add(this, &this->token_);
210
}
211
 
212
// Run the task--read the directory contents.
213
 
214
void
215
Dir_cache_task::run(gold::Workqueue*)
216
{
217
  caches->add(this->dir_);
218
}
219
 
220
}
221
 
222
namespace gold
223
{
224
 
225
// Initialize.
226
 
227
void
228
Dirsearch::initialize(Workqueue* workqueue,
229
                      const General_options::Dir_list* directories)
230
{
231
  gold_assert(caches == NULL);
232
  caches = new Dir_caches;
233
  this->directories_ = directories;
234
  this->token_.add_blockers(directories->size());
235
  for (General_options::Dir_list::const_iterator p = directories->begin();
236
       p != directories->end();
237
       ++p)
238
    workqueue->queue(new Dir_cache_task(p->name().c_str(), this->token_));
239
}
240
 
241
// Search for a file.  NOTE: we only log failed file-lookup attempts
242
// here.  Successfully lookups will eventually get logged in
243
// File_read::open.
244
 
245
std::string
246
Dirsearch::find(const std::vector<std::string>& names,
247
                bool* is_in_sysroot, int* pindex,
248
                std::string *found_name) const
249
{
250
  gold_assert(!this->token_.is_blocked());
251
  gold_assert(*pindex >= 0);
252
 
253
  for (unsigned int i = static_cast<unsigned int>(*pindex);
254
       i < this->directories_->size();
255
       ++i)
256
    {
257
      const Search_directory* p = &this->directories_->at(i);
258
      Dir_cache* pdc = caches->lookup(p->name().c_str());
259
      gold_assert(pdc != NULL);
260
      for (std::vector<std::string>::const_iterator n = names.begin();
261
           n != names.end();
262
           ++n)
263
        {
264
          if (pdc->find(*n))
265
            {
266
              *is_in_sysroot = p->is_in_sysroot();
267
              *pindex = i;
268
              *found_name = *n;
269
              return p->name() + '/' + *n;
270
            }
271
          else
272
            gold_debug(DEBUG_FILES, "Attempt to open %s/%s failed",
273
                       p->name().c_str(), (*n).c_str());
274
        }
275
    }
276
 
277
  *pindex = -2;
278
  return std::string();
279
}
280
 
281 166 khays
// Search for a file in a directory list.  This is a low-level function and
282
// therefore can be used before options and parameters are set.
283
 
284
std::string
285
Dirsearch::find_file_in_dir_list(const std::string& name,
286
                                 const General_options::Dir_list& directories,
287
                                 const std::string& extra_search_dir)
288
{
289
  struct stat buf;
290
  std::string extra_name = extra_search_dir + '/' + name;
291
 
292
  if (stat(extra_name.c_str(), &buf) == 0)
293
    return extra_name;
294
  for (General_options::Dir_list::const_iterator dir = directories.begin();
295
       dir != directories.end();
296
       ++dir)
297
    {
298
      std::string full_name = dir->name() + '/' + name;
299
      if (stat(full_name.c_str(), &buf) == 0)
300
        return full_name;
301
    }
302
  return name;
303
}
304
 
305 27 khays
} // End namespace gold.

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.