If fclose fails, set bfd_error to system_call_error.
[external/binutils.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 }