OSDN Git Service

Initial revision
[pf3gnuchains/pf3gnuchains3x.git] / bfd / cache.c
1 /* BFD library -- caching of file descriptors.
2    Copyright 1990, 91, 92, 93, 94, 95, 1996 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 static void insert PARAMS ((bfd *));
43 static void snip PARAMS ((bfd *));
44 static boolean close_one PARAMS ((void));
45 static boolean bfd_cache_delete PARAMS ((bfd *));
46
47 /*
48 INTERNAL_FUNCTION
49         BFD_CACHE_MAX_OPEN macro
50
51 DESCRIPTION
52         The maximum number of files which the cache will keep open at
53         one time.
54
55 .#define BFD_CACHE_MAX_OPEN 10
56
57 */
58
59 /* The number of BFD files we have open.  */
60
61 static int open_files;
62
63 /*
64 INTERNAL_FUNCTION
65         bfd_last_cache
66
67 SYNOPSIS
68         extern bfd *bfd_last_cache;
69
70 DESCRIPTION
71         Zero, or a pointer to the topmost BFD on the chain.  This is
72         used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
73         determine when it can avoid a function call.
74 */
75
76 bfd *bfd_last_cache;
77
78 /*
79   INTERNAL_FUNCTION
80         bfd_cache_lookup
81  
82   DESCRIPTION
83         Check to see if the required BFD is the same as the last one
84         looked up. If so, then it can use the stream in the BFD with
85         impunity, since it can't have changed since the last lookup;
86         otherwise, it has to perform the complicated lookup function.
87  
88   .#define bfd_cache_lookup(x) \
89   .    ((x)==bfd_last_cache? \
90   .      (FILE*)(bfd_last_cache->iostream): \
91   .       bfd_cache_lookup_worker(x))
92  
93  
94  */
95
96 /* Insert a BFD into the cache.  */
97
98 static INLINE void
99 insert (abfd)
100      bfd *abfd;
101 {
102   if (bfd_last_cache == NULL)
103     {
104       abfd->lru_next = abfd;
105       abfd->lru_prev = abfd;
106     }
107   else
108     {
109       abfd->lru_next = bfd_last_cache;
110       abfd->lru_prev = bfd_last_cache->lru_prev;
111       abfd->lru_prev->lru_next = abfd;
112       abfd->lru_next->lru_prev = abfd;
113     }
114   bfd_last_cache = abfd;
115 }
116
117 /* Remove a BFD from the cache.  */
118
119 static INLINE void
120 snip (abfd)
121      bfd *abfd;
122 {
123   abfd->lru_prev->lru_next = abfd->lru_next;
124   abfd->lru_next->lru_prev = abfd->lru_prev;
125   if (abfd == bfd_last_cache)
126     {
127       bfd_last_cache = abfd->lru_next;
128       if (abfd == bfd_last_cache)
129         bfd_last_cache = NULL;
130     }
131 }
132
133 /* We need to open a new file, and the cache is full.  Find the least
134    recently used cacheable BFD and close it.  */
135
136 static boolean
137 close_one ()
138 {
139   register bfd *kill;
140
141   if (bfd_last_cache == NULL)
142     kill = NULL;
143   else
144     {
145       for (kill = bfd_last_cache->lru_prev;
146            ! kill->cacheable;
147            kill = kill->lru_prev)
148         {
149           if (kill == bfd_last_cache)
150             {
151               kill = NULL;
152               break;
153             }
154         }
155     }
156
157   if (kill == NULL)
158     {
159       /* There are no open cacheable BFD's.  */
160       return true;
161     }
162
163   kill->where = ftell ((FILE *) kill->iostream);
164
165   return bfd_cache_delete (kill);
166 }
167
168 /* Close a BFD and remove it from the cache.  */
169
170 static boolean
171 bfd_cache_delete (abfd)
172      bfd *abfd;
173 {
174   boolean ret;
175
176   if (fclose ((FILE *) abfd->iostream) == 0)
177     ret = true;
178   else
179     {
180       ret = false;
181       bfd_set_error (bfd_error_system_call);
182     }
183
184   snip (abfd);
185
186   abfd->iostream = NULL;
187   --open_files;
188
189   return ret;
190 }
191
192 /*
193 INTERNAL_FUNCTION
194         bfd_cache_init
195
196 SYNOPSIS
197         boolean bfd_cache_init (bfd *abfd);
198
199 DESCRIPTION
200         Add a newly opened BFD to the cache.
201 */
202
203 boolean
204 bfd_cache_init (abfd)
205      bfd *abfd;
206 {
207   BFD_ASSERT (abfd->iostream != NULL);
208   if (open_files >= BFD_CACHE_MAX_OPEN)
209     {
210       if (! close_one ())
211         return false;
212     }
213   insert (abfd);
214   ++open_files;
215   return true;
216 }
217
218 /*
219 INTERNAL_FUNCTION
220         bfd_cache_close
221
222 SYNOPSIS
223         boolean bfd_cache_close (bfd *abfd);
224
225 DESCRIPTION
226         Remove the BFD @var{abfd} from the cache. If the attached file is open,
227         then close it too.
228
229 RETURNS
230         <<false>> is returned if closing the file fails, <<true>> is
231         returned if all is well.
232 */
233
234 boolean
235 bfd_cache_close (abfd)
236      bfd *abfd;
237 {
238   if (abfd->iostream == NULL
239       || (abfd->flags & BFD_IN_MEMORY) != 0)
240     return true;
241
242   return bfd_cache_delete (abfd);
243 }
244
245 /*
246 INTERNAL_FUNCTION
247         bfd_open_file
248
249 SYNOPSIS
250         FILE* bfd_open_file(bfd *abfd);
251
252 DESCRIPTION
253         Call the OS to open a file for @var{abfd}.  Return the <<FILE *>>
254         (possibly <<NULL>>) that results from this operation.  Set up the
255         BFD so that future accesses know the file is open. If the <<FILE *>>
256         returned is <<NULL>>, then it won't have been put in the
257         cache, so it won't have to be removed from it.
258 */
259
260 FILE *
261 bfd_open_file (abfd)
262      bfd *abfd;
263 {
264   abfd->cacheable = true;       /* Allow it to be closed later. */
265
266   if (open_files >= BFD_CACHE_MAX_OPEN)
267     {
268       if (! close_one ())
269         return NULL;
270     }
271
272   switch (abfd->direction)
273     {
274     case read_direction:
275     case no_direction:
276       abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB);
277       break;
278     case both_direction:
279     case write_direction:
280       if (abfd->opened_once == true)
281         {
282           abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB);
283           if (abfd->iostream == NULL)
284             abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
285         }
286       else
287         {
288           /* Create the file.  Unlink it first, for the convenience of
289              operating systems which worry about overwriting running
290              binaries.  */
291           unlink (abfd->filename);
292           abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WB);
293           abfd->opened_once = true;
294         }
295       break;
296     }
297
298   if (abfd->iostream != NULL)
299     {
300       if (! bfd_cache_init (abfd))
301         return NULL;
302     }
303
304   return (FILE *) abfd->iostream;
305 }
306
307 /*
308 INTERNAL_FUNCTION
309         bfd_cache_lookup_worker
310
311 SYNOPSIS
312         FILE *bfd_cache_lookup_worker(bfd *abfd);
313
314 DESCRIPTION
315         Called when the macro <<bfd_cache_lookup>> fails to find a
316         quick answer.  Find a file descriptor for @var{abfd}.  If
317         necessary, it open it.  If there are already more than
318         <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
319         avoid running out of file descriptors.  
320 */
321
322 FILE *
323 bfd_cache_lookup_worker (abfd)
324      bfd *abfd;
325 {
326   if ((abfd->flags & BFD_IN_MEMORY) != 0)
327     abort ();
328
329   if (abfd->my_archive) 
330     abfd = abfd->my_archive;
331
332   if (abfd->iostream != NULL)
333     {
334       /* Move the file to the start of the cache.  */
335       if (abfd != bfd_last_cache)
336         {
337           snip (abfd);
338           insert (abfd);
339         }
340     }
341   else
342     {
343       if (bfd_open_file (abfd) == NULL)
344         return NULL;
345       if (fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0)
346         return NULL;
347     }
348
349   return (FILE *) abfd->iostream;
350 }