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