Merge in changes from gdb-3.95 release into mainstream of BFD development.
[platform/upstream/binutils.git] / bfd / opncls.c
1 /* opncls.c -- open and close a bfd. */
2
3 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Diddler.
6
7 BFD 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 1, or (at your option)
10 any later version.
11
12 BFD 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 BFD; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* $Id$ */
22
23 #include <sysdep.h>
24 #include "bfd.h"
25 #include "libbfd.h"
26
27 extern void bfd_cache_init();
28 FILE *bfd_open_file();
29
30 /* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
31    if we do that we can't use fcntl.  */
32 \f
33 /** Locking 
34
35    Locking is loosely controlled by the preprocessor variable
36    BFD_LOCKS.  I say loosely because Unix barely understands locking
37    -- at least in BSD it doesn't affect programs which don't
38    explicitly use it!  That is to say it's practically useless, though
39    if everyone uses this library you'll be OK.
40
41    From among the many and varied lock facilities available, (none of
42    which, of course, knows about any other) we use the fcntl locks,
43    because they're Posix.
44
45    The reason that bfd_openr and bfd_fdopenr exist, yet only bfd_openw
46    exists is because of locking.  When we do output, we lock the
47    filename file for output, then open a temporary file which does not
48    actually get its correct filename until closing time.  This is
49    safest, but requires the asymmetry in read and write entry points.
50
51    Perhaps, since unix has so many different kinds of locking anyway,
52    we should use the emacs lock scheme?... */
53
54 #define obstack_chunk_alloc malloc
55 #define obstack_chunk_free free
56
57 /* Return a new BFD.  All BFD's are allocated through this routine.  */
58
59 bfd *new_bfd()
60 {
61   bfd *nbfd;
62
63   nbfd = (bfd *)zalloc (sizeof (bfd));
64   if (!nbfd)
65     return 0;
66
67   obstack_begin((PTR)&nbfd->memory, 128);
68   
69   nbfd->direction = no_direction;
70   nbfd->iostream = NULL;
71   nbfd->where = 0;
72   nbfd->sections = (asection *)NULL;
73   nbfd->format = bfd_unknown;
74   nbfd->my_archive = (bfd *)NULL;
75   nbfd->origin = 0;                                
76   nbfd->opened_once = false;
77   nbfd->output_has_begun = false;
78   nbfd->section_count = 0;
79   nbfd->usrdata = (PTR)NULL;
80   nbfd->sections = (asection *)NULL;
81   nbfd->cacheable = false;
82   nbfd->flags = NO_FLAGS;
83   nbfd->mtime_set = 0;
84   return nbfd;
85 }
86
87 /* Allocate a new BFD as a member of archive OBFD.  */
88
89 bfd *new_bfd_contained_in(obfd)
90 bfd *obfd;
91 {
92         bfd *nbfd = new_bfd();
93         nbfd->xvec = obfd->xvec;
94         nbfd->my_archive = obfd;
95         nbfd->direction = read_direction;
96         return nbfd;
97 }
98
99 /** bfd_openr, bfd_fdopenr -- open for reading.
100   Returns a pointer to a freshly-allocated bfd on success, or NULL. */
101
102 bfd *
103 DEFUN(bfd_openr, (filename, target),
104       CONST char *filename AND
105       CONST char *target)
106 {
107   bfd *nbfd;
108   bfd_target *target_vec;
109
110   nbfd = new_bfd();
111   if (nbfd == NULL) {
112     bfd_error = no_memory;
113     return NULL;
114   }
115
116   target_vec = bfd_find_target (target, nbfd);
117   if (target_vec == NULL) {
118     bfd_error = invalid_target;
119     return NULL;
120   }
121
122   nbfd->filename = filename;
123   nbfd->direction = read_direction; 
124
125   if (bfd_open_file (nbfd) == NULL) {
126     bfd_error = system_call_error;      /* File didn't exist, or some such */
127     bfd_release(nbfd,0);
128     return NULL;
129   }
130   return nbfd;
131 }
132
133
134 /* Don't try to `optimize' this function:
135
136    o - We lock using stack space so that interrupting the locking
137        won't cause a storage leak.
138    o - We open the file stream last, since we don't want to have to
139        close it if anything goes wrong.  Closing the stream means closing
140        the file descriptor too, even though we didn't open it.
141  */
142
143 bfd *
144 DEFUN(bfd_fdopenr,(filename, target, fd),
145       CONST char *filename AND
146       CONST char *target AND
147       int fd)
148 {
149   bfd *nbfd;
150   bfd_target *target_vec;
151   int fdflags;
152 #ifdef BFD_LOCKS
153   struct flock lock, *lockp = &lock;
154 #endif
155
156   bfd_error = system_call_error;
157   
158   fdflags = fcntl (fd, F_GETFL);
159   if (fdflags == -1) return NULL;
160
161 #ifdef BFD_LOCKS
162   lockp->l_type = F_RDLCK;
163   if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
164 #endif
165
166   nbfd = new_bfd();
167
168   if (nbfd == NULL) {
169     bfd_error = no_memory;
170     return NULL;
171   }
172
173   target_vec = bfd_find_target (target, nbfd);
174   if (target_vec == NULL) {
175     bfd_error = invalid_target;
176     return NULL;
177   }
178
179 #ifdef BFD_LOCKS
180   nbfd->lock = (struct flock *) (nbfd + 1);
181 #endif
182   /* if the fd were open for read only, this still would not hurt: */
183   nbfd->iostream = (char *) fdopen (fd, "r+"); 
184   if (nbfd->iostream == NULL) {
185     (void) obstack_free (&nbfd->memory, (PTR)0);
186     return NULL;
187   }
188   
189   /* OK, put everything where it belongs */
190
191   nbfd->filename = filename;
192
193   /* As a special case we allow a FD open for read/write to
194      be written through, although doing so requires that we end
195      the previous clause with a preposition.  */
196   switch (fdflags & O_ACCMODE) {
197   case O_RDONLY: nbfd->direction = read_direction; break;
198   case O_WRONLY: nbfd->direction = write_direction; break;  
199   case O_RDWR: nbfd->direction = both_direction; break;
200   default: abort ();
201   }
202                                    
203 #ifdef BFD_LOCKS
204   memcpy (nbfd->lock, lockp, sizeof (struct flock))
205 #endif
206
207   bfd_cache_init (nbfd);
208
209   return nbfd;
210 }
211 \f
212 /** bfd_openw -- open for writing.
213   Returns a pointer to a freshly-allocated bfd on success, or NULL.
214
215   See comment by bfd_fdopenr before you try to modify this function. */
216
217 bfd *
218 DEFUN(bfd_openw,(filename, target),
219       CONST char *filename AND
220       CONST char *target)
221 {
222   bfd *nbfd;
223   bfd_target *target_vec;
224   
225   bfd_error = system_call_error;
226
227   /* nbfd has to point to head of malloc'ed block so that bfd_close may
228      reclaim it correctly. */
229
230   nbfd = new_bfd();
231   if (nbfd == NULL) {
232     bfd_error = no_memory;
233     return NULL;
234   }
235
236   target_vec = bfd_find_target (target, nbfd);
237   if (target_vec == NULL) return NULL;
238
239   nbfd->filename = filename;
240   nbfd->direction = write_direction;
241
242   if (bfd_open_file (nbfd) == NULL) {
243     bfd_error = system_call_error;      /* File not writeable, etc */
244     (void) obstack_free (&nbfd->memory, (PTR)0);
245     return NULL;
246   }
247   return nbfd;
248 }
249 \f
250 /* Close up shop, get your deposit back. */
251 boolean
252 bfd_close (abfd)
253      bfd *abfd;
254 {
255   if (!bfd_read_p(abfd))
256     if (BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)) != true)
257       return false;
258
259   if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
260
261   bfd_cache_close(abfd);
262
263   /* If the file was open for writing and is now executable,
264      make it so */
265   if (abfd->direction == write_direction 
266       && abfd->flags & EXEC_P) {
267     struct stat buf;
268     stat(abfd->filename, &buf);
269 #ifndef S_IXUSR
270 #define S_IXUSR 0100    /* Execute by owner.  */
271 #endif
272 #ifndef S_IXGRP
273 #define S_IXGRP 0010    /* Execute by group.  */
274 #endif
275 #ifndef S_IXOTH
276 #define S_IXOTH 0001    /* Execute by others.  */
277 #endif
278
279     chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
280   }
281   (void) obstack_free (&abfd->memory, (PTR)0);
282   /* FIXME, shouldn't we de-allocate the bfd as well? */
283   return true;
284 }
285
286 /* Create a bfd with no associated file or target.  */
287
288 bfd *
289 DEFUN(bfd_create,(filename, template),
290       CONST char *filename AND
291       CONST bfd *template)
292 {
293   bfd *nbfd = new_bfd();
294   if (nbfd == (bfd *)NULL) {
295     bfd_error = no_memory;
296     return (bfd *)NULL;
297   }
298   nbfd->filename = filename;
299   if(template) {
300     nbfd->xvec = template->xvec;
301   }
302   nbfd->direction = no_direction;
303   bfd_set_format(nbfd, bfd_object);
304   return nbfd;
305 }
306
307 /* Memory allocation */
308
309 DEFUN(PTR bfd_alloc_by_size_t,(abfd, size),
310       bfd *abfd AND
311       size_t size)
312 {
313   PTR res = obstack_alloc(&(abfd->memory), size);
314   return res;
315 }
316 DEFUN(PTR bfd_alloc, (abfd, size),
317       bfd *abfd AND
318       bfd_size_type size)
319 {
320   return bfd_alloc_by_size_t(abfd, (size_t)size);
321 }
322
323 DEFUN(PTR bfd_zalloc,(abfd, size),
324       bfd *abfd AND
325       bfd_size_type size)
326 {
327   PTR res = bfd_alloc(abfd, size);
328   memset(res, 0, (size_t)size);
329   return res;
330 }
331
332 DEFUN(PTR bfd_realloc,(abfd, old, size),
333       bfd *abfd AND
334       PTR old AND
335       bfd_size_type size)
336 {
337   PTR res = bfd_alloc(abfd, size);
338   memcpy(res, old, (size_t)size);
339   return res;
340 }
341
342
343 DEFUN(bfd_size_type bfd_alloc_size,(abfd),
344       bfd *abfd)
345 {
346   struct _obstack_chunk *chunk = abfd->memory.chunk;
347   size_t size = 0;
348   while (chunk) {
349     size += chunk->limit - &(chunk->contents[0]);
350     chunk = chunk->prev;
351   }
352   return size;
353 }