Don't crash if with_minimal_bfd is the empty string.
[deliverable/binutils-gdb.git] / bfd / cache.c
1 /* BFD library -- caching of file descriptors.
2 Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
3 Hacked by Steve Chamberlain of Cygnus Support (steve@cygnus.com).
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /*
22 SECTION
23 File Caching
24
25 The file caching mechanism is embedded within BFD and allows
26 the application to open as many BFDs as it wants without
27 regard to the underlying operating system's file descriptor
28 limit (often as low as 20 open files). The module in
29 <<cache.c>> maintains a least recently used list of
30 <<BFD_CACHE_MAX_OPEN>> files, and exports the name
31 <<bfd_cache_lookup>> which runs around and makes sure that
32 the required BFD is open. If not, then it chooses a file to
33 close, closes it and opens the one wanted, returning its file
34 handle.
35
36 */
37
38 #include "bfd.h"
39 #include "sysdep.h"
40 #include "libbfd.h"
41
42 /*
43 INTERNAL_FUNCTION
44 BFD_CACHE_MAX_OPEN macro
45
46 DESCRIPTION
47 The maximum number of files which the cache will keep open at
48 one time.
49
50 .#define BFD_CACHE_MAX_OPEN 10
51
52 */
53
54
55 static int open_files;
56
57 static bfd *cache_sentinel; /* Chain of BFDs with active fds we've
58 opened */
59
60 /*
61 INTERNAL_FUNCTION
62 bfd_last_cache
63
64 SYNOPSIS
65 extern bfd *bfd_last_cache;
66
67 DESCRIPTION
68 Zero, or a pointer to the topmost BFD on the chain. This is
69 used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
70 determine when it can avoid a function call.
71 */
72
73 bfd *bfd_last_cache;
74
75 /*
76 * INTERNAL_FUNCTION
77 * bfd_cache_lookup
78 *
79 * DESCRIPTION
80 * Checks to see if the required BFD is the same as the last one
81 * looked up. If so then it can use the iostream in the BFD with
82 * impunity, since it can't have changed since the last lookup,
83 * otherwise it has to perform the complicated lookup function
84 *
85 * .#define bfd_cache_lookup(x) \
86 * . ((x)==bfd_last_cache? \
87 * . (FILE*)(bfd_last_cache->iostream): \
88 * . bfd_cache_lookup_worker(x))
89 *
90 *
91 */
92
93 static boolean EXFUN(bfd_cache_delete,(bfd *));
94
95
96 static void
97 DEFUN_VOID(close_one)
98 {
99 bfd *kill = cache_sentinel;
100 if (kill == 0) /* Nothing in the cache */
101 return ;
102
103 /* We can only close files that want to play this game. */
104 while (!kill->cacheable) {
105 kill = kill->lru_prev;
106 if (kill == cache_sentinel) /* Nobody wants to play */
107 return ;
108 }
109
110 kill->where = ftell((FILE *)(kill->iostream));
111 (void) bfd_cache_delete(kill);
112 }
113
114 /* Cuts the BFD abfd out of the chain in the cache */
115 static void
116 DEFUN(snip,(abfd),
117 bfd *abfd)
118 {
119 abfd->lru_prev->lru_next = abfd->lru_next;
120 abfd->lru_next->lru_prev = abfd->lru_prev;
121 if (cache_sentinel == abfd) cache_sentinel = (bfd *)NULL;
122 }
123
124 static boolean
125 DEFUN(bfd_cache_delete,(abfd),
126 bfd *abfd)
127 {
128 boolean ret;
129
130 if (fclose ((FILE *)(abfd->iostream)) == 0)
131 ret = true;
132 else
133 {
134 ret = false;
135 bfd_error = system_call_error;
136 }
137 snip (abfd);
138 abfd->iostream = NULL;
139 open_files--;
140 bfd_last_cache = 0;
141 return ret;
142 }
143
144 static bfd *
145 DEFUN(insert,(x,y),
146 bfd *x AND
147 bfd *y)
148 {
149 if (y) {
150 x->lru_next = y;
151 x->lru_prev = y->lru_prev;
152 y->lru_prev->lru_next = x;
153 y->lru_prev = x;
154
155 }
156 else {
157 x->lru_prev = x;
158 x->lru_next = x;
159 }
160 return x;
161 }
162 \f
163
164 /*
165 INTERNAL_FUNCTION
166 bfd_cache_init
167
168 SYNOPSIS
169 void bfd_cache_init (bfd *);
170
171 DESCRIPTION
172 Initialize a BFD by putting it on the cache LRU.
173 */
174
175 void
176 DEFUN(bfd_cache_init,(abfd),
177 bfd *abfd)
178 {
179 cache_sentinel = insert(abfd, cache_sentinel);
180 }
181
182
183 /*
184 INTERNAL_FUNCTION
185 bfd_cache_close
186
187 DESCRIPTION
188 Remove the BFD from the cache. If the attached file is open,
189 then close it too.
190
191 SYNOPSIS
192 boolean bfd_cache_close (bfd *);
193
194 RETURNS
195 <<false>> is returned if closing the file fails, <<true>> is
196 returned if all is well.
197 */
198 boolean
199 DEFUN(bfd_cache_close,(abfd),
200 bfd *abfd)
201 {
202 /* If this file is open then remove from the chain */
203 if (abfd->iostream)
204 {
205 return bfd_cache_delete(abfd);
206 }
207 else
208 {
209 return true;
210 }
211 }
212
213 /*
214 INTERNAL_FUNCTION
215 bfd_open_file
216
217 DESCRIPTION
218 Call the OS to open a file for this BFD. Returns the FILE *
219 (possibly null) that results from this operation. Sets up the
220 BFD so that future accesses know the file is open. If the FILE
221 * returned is null, then there is won't have been put in the
222 cache, so it won't have to be removed from it.
223
224 SYNOPSIS
225 FILE* bfd_open_file(bfd *);
226 */
227
228 FILE *
229 DEFUN(bfd_open_file, (abfd),
230 bfd *abfd)
231 {
232 abfd->cacheable = true; /* Allow it to be closed later. */
233
234 if(open_files >= BFD_CACHE_MAX_OPEN) {
235 close_one();
236 }
237
238 switch (abfd->direction) {
239 case read_direction:
240 case no_direction:
241 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RB);
242 break;
243 case both_direction:
244 case write_direction:
245 if (abfd->opened_once == true) {
246 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_RUB);
247 if (!abfd->iostream) {
248 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WUB);
249 }
250 } else {
251 /*open for creat */
252 abfd->iostream = (char *) fopen(abfd->filename, FOPEN_WB);
253 abfd->opened_once = true;
254 }
255 break;
256 }
257
258 if (abfd->iostream) {
259 open_files++;
260 bfd_cache_init (abfd);
261 }
262
263 return (FILE *)(abfd->iostream);
264 }
265
266 /*
267 INTERNAL_FUNCTION
268 bfd_cache_lookup_worker
269
270 DESCRIPTION
271 Called when the macro <<bfd_cache_lookup>> fails to find a
272 quick answer. Finds a file descriptor for this BFD. If
273 necessary, it open it. If there are already more than
274 BFD_CACHE_MAX_OPEN files open, it trys to close one first, to
275 avoid running out of file descriptors.
276
277 SYNOPSIS
278 FILE *bfd_cache_lookup_worker(bfd *);
279
280 */
281
282 FILE *
283 DEFUN(bfd_cache_lookup_worker,(abfd),
284 bfd *abfd)
285 {
286 if (abfd->my_archive)
287 {
288 abfd = abfd->my_archive;
289 }
290 /* Is this file already open .. if so then quick exit */
291 if (abfd->iostream)
292 {
293 if (abfd != cache_sentinel) {
294 /* Place onto head of lru chain */
295 snip (abfd);
296 cache_sentinel = insert(abfd, cache_sentinel);
297 }
298 }
299 /* This is a BFD without a stream -
300 so it must have been closed or never opened.
301 find an empty cache entry and use it. */
302 else
303 {
304
305 if (open_files >= BFD_CACHE_MAX_OPEN)
306 {
307 close_one();
308 }
309
310 BFD_ASSERT(bfd_open_file (abfd) != (FILE *)NULL) ;
311 fseek((FILE *)(abfd->iostream), abfd->where, false);
312 }
313 bfd_last_cache = abfd;
314 return (FILE *)(abfd->iostream);
315 }
This page took 0.035574 seconds and 4 git commands to generate.