1 // fileread.cc -- read files for gold
12 #include "dirsearch.h"
18 // Class File_read::View.
20 File_read::View::~View()
22 assert(!this->is_locked());
27 File_read::View::lock()
33 File_read::View::unlock()
35 assert(this->lock_count_
> 0);
40 File_read::View::is_locked()
42 return this->lock_count_
> 0;
47 // The File_read class is designed to support file descriptor caching,
48 // but this is not currently implemented.
50 File_read::~File_read()
52 assert(this->lock_count_
== 0);
53 if (this->descriptor_
>= 0)
55 if (close(this->descriptor_
) < 0)
56 fprintf(stderr
, _("%s: warning: close(%s) failed: %s"),
57 program_name
, this->name_
.c_str(), strerror(errno
));
58 this->descriptor_
= -1;
61 this->clear_views(true);
65 File_read::open(const std::string
& name
)
67 assert(this->lock_count_
== 0
68 && this->descriptor_
< 0
69 && this->name_
.empty());
71 this->descriptor_
= ::open(this->name_
.c_str(), O_RDONLY
);
73 return this->descriptor_
>= 0;
77 File_read::get_descriptor()
79 assert(this->lock_count_
> 0);
80 return this->descriptor_
;
92 assert(this->lock_count_
> 0);
97 File_read::is_locked()
99 return this->lock_count_
> 0;
102 // See if we have a view which covers the file starting at START for
103 // SIZE bytes. Return a pointer to the View if found, NULL if not.
106 File_read::find_view(off_t start
, off_t size
)
108 for (std::list
<File_read::View
*>::iterator p
= this->view_list_
.begin();
109 p
!= this->view_list_
.end();
112 if ((*p
)->start() <= start
113 && (*p
)->start() + (*p
)->size() >= start
+ size
)
119 // Read data from the file. Return the number of bytes read. If
120 // PBYTES is not NULL, store the number of bytes in *PBYTES, otherwise
121 // require that we read exactly the number of bytes requested.
124 File_read::do_read(off_t start
, off_t size
, void* p
, off_t
* pbytes
)
126 assert(this->lock_count_
> 0);
127 int o
= this->descriptor_
;
129 if (lseek(o
, start
, SEEK_SET
) < 0)
131 fprintf(stderr
, _("%s: %s: lseek to %lld failed: %s"),
132 program_name
, this->filename().c_str(),
133 static_cast<long long>(start
),
138 off_t bytes
= ::read(o
, p
, size
);
141 fprintf(stderr
, _("%s: %s: read failed: %s\n"),
142 program_name
, this->filename().c_str(), strerror(errno
));
148 else if (bytes
!= size
)
151 _("%s: %s: file too short: read only %lld of %lld "
153 program_name
, this->filename().c_str(),
154 static_cast<long long>(bytes
),
155 static_cast<long long>(size
),
156 static_cast<long long>(start
));
164 File_read::read(off_t start
, off_t size
, void* p
, off_t
* pbytes
)
166 assert(this->lock_count_
> 0);
168 File_read::View
* pv
= this->find_view(start
, size
);
171 memcpy(p
, pv
->data() + (start
- pv
->start()), size
);
177 this->do_read(start
, size
, p
, pbytes
);
180 // Find an existing view or make a new one.
183 File_read::find_or_make_view(off_t start
, off_t size
, off_t
* pbytes
)
185 assert(this->lock_count_
> 0);
187 File_read::View
* pv
= this->find_view(start
, size
);
191 unsigned char* p
= new unsigned char[size
];
192 off_t bytes
= this->do_read(start
, size
, p
, pbytes
);
193 pv
= new File_read::View(start
, bytes
, p
);
194 this->view_list_
.push_back(pv
);
198 // This implementation of get_view just reads into a memory buffer,
199 // which we store on view_list_. At some point we should support
203 File_read::get_view(off_t start
, off_t size
, off_t
* pbytes
)
205 assert(this->lock_count_
> 0);
206 File_read::View
* pv
= this->find_or_make_view(start
, size
, pbytes
);
207 return pv
->data() + (start
- pv
->start());
211 File_read::get_lasting_view(off_t start
, off_t size
, off_t
* pbytes
)
213 assert(this->lock_count_
> 0);
214 File_read::View
* pv
= this->find_or_make_view(start
, size
, pbytes
);
216 return new File_view(*this, pv
, pv
->data() + (start
- pv
->start()));
219 // Remove all the file views.
222 File_read::clear_views(bool destroying
)
224 std::list
<File_read::View
*>::iterator p
= this->view_list_
.begin();
225 while (p
!= this->view_list_
.end())
227 if ((*p
)->is_locked())
235 p
= this->view_list_
.erase(p
);
242 File_view::~File_view()
244 assert(this->file_
.is_locked());
245 this->view_
->unlock();
251 Input_file::open(const General_options
& options
, const Dirsearch
& dirpath
)
254 if (!this->input_argument_
.is_lib())
255 name
= this->input_argument_
.name();
258 std::string
n1("lib");
259 n1
+= this->input_argument_
.lib_basename();
261 if (options
.is_static())
264 name
= dirpath
.find(n1
, n2
);
267 fprintf(stderr
, _("%s: cannot find %s"), program_name
,
268 this->input_argument_
.name());
273 if (!this->file_
.open(name
))
275 fprintf(stderr
, _("%s: cannot open %s: %s"), program_name
, name
.c_str(),
281 } // End namespace gold.