Sun Jan 15 13:57:45 1995 Steve Chamberlain <sac@splat>
[platform/upstream/binutils.git] / bfd / opncls.c
1 /* opncls.c -- open and close a BFD.
2    Copyright (C) 1990 91, 92, 93, 94 Free Software Foundation, Inc.
3    Written by Cygnus Support.
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 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "obstack.h"
25
26 #ifndef S_IXUSR
27 #define S_IXUSR 0100    /* Execute by owner.  */
28 #endif
29 #ifndef S_IXGRP
30 #define S_IXGRP 0010    /* Execute by group.  */
31 #endif
32 #ifndef S_IXOTH
33 #define S_IXOTH 0001    /* Execute by others.  */
34 #endif
35
36 /* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
37    if we do that we can't use fcntl.  */
38
39
40 #define obstack_chunk_alloc malloc
41 #define obstack_chunk_free free
42
43 /* Return a new BFD.  All BFD's are allocated through this routine.  */
44
45 bfd *
46 _bfd_new_bfd ()
47 {
48   bfd *nbfd;
49
50   nbfd = (bfd *)bfd_zmalloc (sizeof (bfd));
51   if (!nbfd)
52     {
53       bfd_set_error (bfd_error_no_memory);
54       return 0;
55     }
56
57   bfd_check_init();
58   if (!obstack_begin(&nbfd->memory, 128))
59     {
60       bfd_set_error (bfd_error_no_memory);
61       return 0;
62     }
63
64   nbfd->arch_info = &bfd_default_arch_struct;
65
66   nbfd->direction = no_direction;
67   nbfd->iostream = NULL;
68   nbfd->where = 0;
69   nbfd->sections = (asection *)NULL;
70   nbfd->format = bfd_unknown;
71   nbfd->my_archive = (bfd *)NULL;
72   nbfd->origin = 0;                             
73   nbfd->opened_once = false;
74   nbfd->output_has_begun = false;
75   nbfd->section_count = 0;
76   nbfd->usrdata = (PTR)NULL;
77   nbfd->cacheable = false;
78   nbfd->flags = NO_FLAGS;
79   nbfd->mtime_set = false;
80
81   return nbfd;
82 }
83
84 /* Allocate a new BFD as a member of archive OBFD.  */
85
86 bfd *
87 _bfd_new_bfd_contained_in (obfd)
88      bfd *obfd;
89 {
90   bfd *nbfd;
91
92   nbfd = _bfd_new_bfd();
93   nbfd->xvec = obfd->xvec;
94   nbfd->my_archive = obfd;
95   nbfd->direction = read_direction;
96   nbfd->target_defaulted = obfd->target_defaulted;
97   return nbfd;
98 }
99
100 /*
101 SECTION
102         Opening and closing BFDs
103
104 */
105
106 /*
107 FUNCTION
108         bfd_openr
109
110 SYNOPSIS
111         bfd *bfd_openr(CONST char *filename, CONST char *target);
112
113 DESCRIPTION
114         Open the file @var{filename} (using <<fopen>>) with the target
115         @var{target}.  Return a pointer to the created BFD.
116
117         Calls <<bfd_find_target>>, so @var{target} is interpreted as by
118         that function.
119
120         If <<NULL>> is returned then an error has occured.   Possible errors
121         are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error.
122 */
123
124 bfd *
125 bfd_openr (filename, target)
126      CONST char *filename;
127      CONST char *target;
128 {
129   bfd *nbfd;
130   const bfd_target *target_vec;
131
132   nbfd = _bfd_new_bfd();
133   if (nbfd == NULL) {
134     bfd_set_error (bfd_error_no_memory);
135     return NULL;
136   }
137
138   target_vec = bfd_find_target (target, nbfd);
139   if (target_vec == NULL) {
140     bfd_set_error (bfd_error_invalid_target);
141     return NULL;
142   }
143
144   nbfd->filename = filename;
145   nbfd->direction = read_direction;
146
147   if (bfd_open_file (nbfd) == NULL) {
148     bfd_set_error (bfd_error_system_call);      /* File didn't exist, or some such */
149     bfd_release(nbfd,0);
150     return NULL;
151   }
152   return nbfd;
153 }
154
155
156 /* Don't try to `optimize' this function:
157
158    o - We lock using stack space so that interrupting the locking
159        won't cause a storage leak.
160    o - We open the file stream last, since we don't want to have to
161        close it if anything goes wrong.  Closing the stream means closing
162        the file descriptor too, even though we didn't open it.
163  */
164 /*
165 FUNCTION
166          bfd_fdopenr
167
168 SYNOPSIS
169          bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd);
170
171 DESCRIPTION
172          <<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to <<fopen>>.
173          It opens a BFD on a file already described by the @var{fd}
174          supplied.
175
176          When the file is later <<bfd_close>>d, the file descriptor will be closed.
177
178          If the caller desires that this file descriptor be cached by BFD
179          (opened as needed, closed as needed to free descriptors for
180          other opens), with the supplied @var{fd} used as an initial
181          file descriptor (but subject to closure at any time), call
182          bfd_set_cacheable(bfd, 1) on the returned BFD.  The default is to
183          assume no cacheing; the file descriptor will remain open until
184          <<bfd_close>>, and will not be affected by BFD operations on other
185          files.
186
187          Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
188 */
189
190 bfd *
191 bfd_fdopenr (filename, target, fd)
192      CONST char *filename;
193      CONST char *target;
194      int fd;
195 {
196   bfd *nbfd;
197   const bfd_target *target_vec;
198   int fdflags;
199
200   bfd_set_error (bfd_error_system_call);
201
202 #ifdef NO_FCNTL
203   fdflags = O_RDWR;                     /* Assume full access */
204 #else
205   fdflags = fcntl (fd, F_GETFL, NULL);
206 #endif
207   if (fdflags == -1) return NULL;
208
209   nbfd = _bfd_new_bfd();
210
211   if (nbfd == NULL) {
212     bfd_set_error (bfd_error_no_memory);
213     return NULL;
214   }
215
216   target_vec = bfd_find_target (target, nbfd);
217   if (target_vec == NULL) {
218     bfd_set_error (bfd_error_invalid_target);
219     return NULL;
220   }
221 #if defined(VMS) || defined(__GO32__) || defined (WIN32)
222   nbfd->iostream = (char *)fopen(filename, FOPEN_RB);
223 #else
224   /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
225   switch (fdflags & (O_ACCMODE)) {
226   case O_RDONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RB);   break;
227   case O_WRONLY: nbfd->iostream = (char *) fdopen (fd, FOPEN_RUB);  break;
228   case O_RDWR:   nbfd->iostream = (char *) fdopen (fd, FOPEN_RUB);  break;
229   default: abort ();
230   }
231 #endif
232   if (nbfd->iostream == NULL) {
233     (void) obstack_free (&nbfd->memory, (PTR)0);
234     return NULL;
235   }
236
237   /* OK, put everything where it belongs */
238
239   nbfd->filename = filename;
240
241   /* As a special case we allow a FD open for read/write to
242      be written through, although doing so requires that we end
243      the previous clause with a preposition.  */
244   /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
245   switch (fdflags & (O_ACCMODE)) {
246   case O_RDONLY: nbfd->direction = read_direction; break;
247   case O_WRONLY: nbfd->direction = write_direction; break;
248   case O_RDWR: nbfd->direction = both_direction; break;
249   default: abort ();
250   }
251                                 
252   if (! bfd_cache_init (nbfd))
253     return NULL;
254
255   return nbfd;
256 }
257 \f
258 /** bfd_openw -- open for writing.
259   Returns a pointer to a freshly-allocated BFD on success, or NULL.
260
261   See comment by bfd_fdopenr before you try to modify this function. */
262
263 /*
264 FUNCTION
265         bfd_openw
266
267 SYNOPSIS
268         bfd *bfd_openw(CONST char *filename, CONST char *target);
269
270 DESCRIPTION
271         Create a BFD, associated with file @var{filename}, using the
272         file format @var{target}, and return a pointer to it.
273
274         Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
275         <<bfd_error_invalid_target>>.
276 */
277
278 bfd *
279 bfd_openw (filename, target)
280      CONST char *filename;
281      CONST char *target;
282 {
283   bfd *nbfd;
284   const bfd_target *target_vec;
285
286   bfd_set_error (bfd_error_system_call);
287
288   /* nbfd has to point to head of malloc'ed block so that bfd_close may
289      reclaim it correctly. */
290
291   nbfd = _bfd_new_bfd();
292   if (nbfd == NULL) {
293     bfd_set_error (bfd_error_no_memory);
294     return NULL;
295   }
296
297   target_vec = bfd_find_target (target, nbfd);
298   if (target_vec == NULL) return NULL;
299
300   nbfd->filename = filename;
301   nbfd->direction = write_direction;
302
303   if (bfd_open_file (nbfd) == NULL) {
304     bfd_set_error (bfd_error_system_call);      /* File not writeable, etc */
305     (void) obstack_free (&nbfd->memory, (PTR)0);
306     return NULL;
307   }
308   return nbfd;
309 }
310
311 /*
312
313 FUNCTION
314         bfd_close
315
316 SYNOPSIS
317         boolean bfd_close(bfd *abfd);
318
319 DESCRIPTION
320
321         Close a BFD. If the BFD was open for writing,
322         then pending operations are completed and the file written out
323         and closed. If the created file is executable, then
324         <<chmod>> is called to mark it as such.
325
326         All memory attached to the BFD's obstacks is released.
327
328         The file descriptor associated with the BFD is closed (even
329         if it was passed in to BFD by <<bfd_fdopenr>>).
330
331 RETURNS
332         <<true>> is returned if all is ok, otherwise <<false>>.
333 */
334
335
336 boolean
337 bfd_close (abfd)
338      bfd *abfd;
339 {
340   boolean ret;
341
342   if (!bfd_read_p (abfd))
343     {
344       if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
345         return false;
346     }
347
348   if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
349     return false;
350
351   ret = bfd_cache_close (abfd);
352
353   /* If the file was open for writing and is now executable,
354      make it so */
355   if (ret
356       && abfd->direction == write_direction
357       && abfd->flags & EXEC_P)
358     {
359       struct stat buf;
360
361       if (stat (abfd->filename, &buf) == 0)
362         {
363           int mask = umask (0);
364           umask (mask);
365           chmod (abfd->filename,
366                  (0777
367                   & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
368         }
369     }
370
371   (void) obstack_free (&abfd->memory, (PTR)0);
372   (void) free (abfd);
373
374   return ret;
375 }
376
377 /*
378 FUNCTION
379         bfd_close_all_done
380
381 SYNOPSIS
382         boolean bfd_close_all_done(bfd *);
383
384 DESCRIPTION
385         Close a BFD.  Differs from <<bfd_close>>
386         since it does not complete any pending operations.  This
387         routine would be used if the application had just used BFD for
388         swapping and didn't want to use any of the writing code.
389
390         If the created file is executable, then <<chmod>> is called
391         to mark it as such.
392
393         All memory attached to the BFD's obstacks is released.
394
395 RETURNS
396         <<true>> is returned if all is ok, otherwise <<false>>.
397
398 */
399
400 boolean
401 bfd_close_all_done (abfd)
402      bfd *abfd;
403 {
404   boolean ret;
405
406   ret = bfd_cache_close (abfd);
407
408   /* If the file was open for writing and is now executable,
409      make it so */
410   if (ret
411       && abfd->direction == write_direction
412       && abfd->flags & EXEC_P)
413     {
414       struct stat buf;
415
416       if (stat (abfd->filename, &buf) == 0)
417         {
418           int mask = umask (0);
419           umask (mask);
420           chmod (abfd->filename,
421                  (0x777
422                   & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
423         }
424     }
425   (void) obstack_free (&abfd->memory, (PTR)0);
426   (void) free(abfd);
427   return ret;
428 }
429
430
431 /*
432 FUNCTION        
433         bfd_alloc_size
434
435 SYNOPSIS
436         bfd_size_type bfd_alloc_size(bfd *abfd);
437
438 DESCRIPTION
439         Return the number of bytes in the obstacks connected to @var{abfd}.
440
441 */
442
443 bfd_size_type
444 bfd_alloc_size (abfd)
445      bfd *abfd;
446 {
447   struct _obstack_chunk *chunk = abfd->memory.chunk;
448   size_t size = 0;
449   while (chunk) {
450     size += chunk->limit - &(chunk->contents[0]);
451     chunk = chunk->prev;
452   }
453   return size;
454 }
455
456
457
458 /*
459 FUNCTION
460         bfd_create
461
462 SYNOPSIS
463         bfd *bfd_create(CONST char *filename, bfd *templ);
464
465 DESCRIPTION
466         Create a new BFD in the manner of
467         <<bfd_openw>>, but without opening a file. The new BFD
468         takes the target from the target used by @var{template}. The
469         format is always set to <<bfd_object>>.
470
471 */
472
473 bfd *
474 bfd_create (filename, templ)
475      CONST char *filename;
476      bfd *templ;
477 {
478   bfd *nbfd = _bfd_new_bfd();
479   if (nbfd == (bfd *)NULL) {
480     bfd_set_error (bfd_error_no_memory);
481     return (bfd *)NULL;
482   }
483   nbfd->filename = filename;
484   if(templ) {
485     nbfd->xvec = templ->xvec;
486   }
487   nbfd->direction = no_direction;
488   bfd_set_format(nbfd, bfd_object);
489   return nbfd;
490 }
491
492 /*
493 INTERNAL_FUNCTION
494         bfd_alloc_by_size_t
495
496 SYNOPSIS
497         PTR bfd_alloc_by_size_t(bfd *abfd, size_t wanted);
498
499 DESCRIPTION
500         Allocate a block of @var{wanted} bytes of memory in the obstack
501         attatched to <<abfd>> and return a pointer to it.
502 */
503
504
505 PTR
506 bfd_alloc_by_size_t (abfd, size)
507      bfd *abfd;
508      size_t size;
509 {
510   return obstack_alloc(&(abfd->memory), size);
511 }
512
513 void
514 bfd_alloc_grow (abfd, ptr, size)
515      bfd *abfd;
516      PTR ptr;
517      size_t size;
518 {
519   (void) obstack_grow(&(abfd->memory), ptr, size);
520 }
521
522 PTR
523 bfd_alloc_finish (abfd)
524      bfd *abfd;
525 {
526   return obstack_finish(&(abfd->memory));
527 }
528
529 PTR
530 bfd_alloc (abfd, size)
531      bfd *abfd;
532      size_t size;
533 {
534   return bfd_alloc_by_size_t(abfd, (size_t)size);
535 }
536
537 PTR
538 bfd_zalloc (abfd, size)
539      bfd *abfd;
540      size_t size;
541 {
542   PTR res;
543   res = bfd_alloc(abfd, size);
544   if (res)
545     memset(res, 0, (size_t)size);
546   return res;
547 }