cache.c revision 33965
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
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21/*
22SECTION
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
42static void insert PARAMS ((bfd *));
43static void snip PARAMS ((bfd *));
44static boolean close_one PARAMS ((void));
45static boolean bfd_cache_delete PARAMS ((bfd *));
46
47/*
48INTERNAL_FUNCTION
49	BFD_CACHE_MAX_OPEN macro
50
51DESCRIPTION
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
61static int open_files;
62
63/*
64INTERNAL_FUNCTION
65	bfd_last_cache
66
67SYNOPSIS
68	extern bfd *bfd_last_cache;
69
70DESCRIPTION
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
76bfd *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
98static INLINE void
99insert (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
119static INLINE void
120snip (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
136static boolean
137close_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
170static boolean
171bfd_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/*
193INTERNAL_FUNCTION
194	bfd_cache_init
195
196SYNOPSIS
197	boolean bfd_cache_init (bfd *abfd);
198
199DESCRIPTION
200	Add a newly opened BFD to the cache.
201*/
202
203boolean
204bfd_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/*
219INTERNAL_FUNCTION
220	bfd_cache_close
221
222SYNOPSIS
223	boolean bfd_cache_close (bfd *abfd);
224
225DESCRIPTION
226	Remove the BFD @var{abfd} from the cache. If the attached file is open,
227	then close it too.
228
229RETURNS
230	<<false>> is returned if closing the file fails, <<true>> is
231	returned if all is well.
232*/
233
234boolean
235bfd_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/*
246INTERNAL_FUNCTION
247	bfd_open_file
248
249SYNOPSIS
250	FILE* bfd_open_file(bfd *abfd);
251
252DESCRIPTION
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
260FILE *
261bfd_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/*
308INTERNAL_FUNCTION
309	bfd_cache_lookup_worker
310
311SYNOPSIS
312	FILE *bfd_cache_lookup_worker(bfd *abfd);
313
314DESCRIPTION
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
322FILE *
323bfd_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}
351