This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / bfd / opncls.c
1 /* opncls.c -- open and close a BFD.
2    Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997
3    Free Software Foundation, Inc.
4
5    Written by Cygnus Support.
6
7 This file is part of BFD, the Binary File Descriptor library.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "objalloc.h"
26 #include "libbfd.h"
27
28 #ifndef S_IXUSR
29 #define S_IXUSR 0100    /* Execute by owner.  */
30 #endif
31 #ifndef S_IXGRP
32 #define S_IXGRP 0010    /* Execute by group.  */
33 #endif
34 #ifndef S_IXOTH
35 #define S_IXOTH 0001    /* Execute by others.  */
36 #endif
37
38 /* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
39    if we do that we can't use fcntl.  */
40
41 /* FIXME: This is no longer used.  */
42 long _bfd_chunksize = -1;
43
44 /* Return a new BFD.  All BFD's are allocated through this routine.  */
45
46 bfd *
47 _bfd_new_bfd ()
48 {
49   bfd *nbfd;
50
51   nbfd = (bfd *) bfd_zmalloc (sizeof (bfd));
52   if (nbfd == NULL)
53     return NULL;
54
55   nbfd->memory = (PTR) objalloc_create ();
56   if (nbfd->memory == NULL)
57     {
58       bfd_set_error (bfd_error_no_memory);
59       return NULL;
60     }
61
62   nbfd->arch_info = &bfd_default_arch_struct;
63
64   nbfd->direction = no_direction;
65   nbfd->iostream = NULL;
66   nbfd->where = 0;
67   nbfd->sections = (asection *) NULL;
68   nbfd->format = bfd_unknown;
69   nbfd->my_archive = (bfd *) NULL;
70   nbfd->origin = 0;                             
71   nbfd->opened_once = false;
72   nbfd->output_has_begun = false;
73   nbfd->section_count = 0;
74   nbfd->usrdata = (PTR) NULL;
75   nbfd->cacheable = false;
76   nbfd->flags = BFD_NO_FLAGS;
77   nbfd->mtime_set = false;
78
79   return nbfd;
80 }
81
82 /* Allocate a new BFD as a member of archive OBFD.  */
83
84 bfd *
85 _bfd_new_bfd_contained_in (obfd)
86      bfd *obfd;
87 {
88   bfd *nbfd;
89
90   nbfd = _bfd_new_bfd ();
91   nbfd->xvec = obfd->xvec;
92   nbfd->my_archive = obfd;
93   nbfd->direction = read_direction;
94   nbfd->target_defaulted = obfd->target_defaulted;
95   return nbfd;
96 }
97
98 /*
99 SECTION
100         Opening and closing BFDs
101
102 */
103
104 /*
105 FUNCTION
106         bfd_openr
107
108 SYNOPSIS
109         bfd *bfd_openr(CONST char *filename, CONST char *target);
110
111 DESCRIPTION
112         Open the file @var{filename} (using <<fopen>>) with the target
113         @var{target}.  Return a pointer to the created BFD.
114
115         Calls <<bfd_find_target>>, so @var{target} is interpreted as by
116         that function.
117
118         If <<NULL>> is returned then an error has occured.   Possible errors
119         are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error.
120 */
121
122 bfd *
123 bfd_openr (filename, target)
124      CONST char *filename;
125      CONST char *target;
126 {
127   bfd *nbfd;
128   const bfd_target *target_vec;
129
130   nbfd = _bfd_new_bfd ();
131   if (nbfd == NULL)
132     return NULL;
133
134   target_vec = bfd_find_target (target, nbfd);
135   if (target_vec == NULL)
136     {
137       objalloc_free ((struct objalloc *) nbfd->memory);
138       free (nbfd);
139       bfd_set_error (bfd_error_invalid_target);
140       return NULL;
141     }
142
143   nbfd->filename = filename;
144   nbfd->direction = read_direction;
145
146   if (bfd_open_file (nbfd) == NULL)
147     {
148       /* File didn't exist, or some such */
149       bfd_set_error (bfd_error_system_call);
150       objalloc_free ((struct objalloc *) nbfd->memory);
151       free (nbfd);
152       return NULL;
153     }
154
155   return nbfd;
156 }
157
158 /* Don't try to `optimize' this function:
159
160    o - We lock using stack space so that interrupting the locking
161        won't cause a storage leak.
162    o - We open the file stream last, since we don't want to have to
163        close it if anything goes wrong.  Closing the stream means closing
164        the file descriptor too, even though we didn't open it.
165  */
166 /*
167 FUNCTION
168          bfd_fdopenr
169
170 SYNOPSIS
171          bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd);
172
173 DESCRIPTION
174          <<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to <<fopen>>.
175          It opens a BFD on a file already described by the @var{fd}
176          supplied.
177
178          When the file is later <<bfd_close>>d, the file descriptor will be closed.
179
180          If the caller desires that this file descriptor be cached by BFD
181          (opened as needed, closed as needed to free descriptors for
182          other opens), with the supplied @var{fd} used as an initial
183          file descriptor (but subject to closure at any time), call
184          bfd_set_cacheable(bfd, 1) on the returned BFD.  The default is to
185          assume no cacheing; the file descriptor will remain open until
186          <<bfd_close>>, and will not be affected by BFD operations on other
187          files.
188
189          Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
190 */
191
192 bfd *
193 bfd_fdopenr (filename, target, fd)
194      CONST char *filename;
195      CONST char *target;
196      int fd;
197 {
198   bfd *nbfd;
199   const bfd_target *target_vec;
200   int fdflags;
201
202   bfd_set_error (bfd_error_system_call);
203 #if ! defined(HAVE_FCNTL) || ! defined(F_GETFL)
204   fdflags = O_RDWR;                     /* Assume full access */
205 #else
206   fdflags = fcntl (fd, F_GETFL, NULL);
207 #endif
208   if (fdflags == -1) return NULL;
209
210   nbfd = _bfd_new_bfd ();
211   if (nbfd == NULL)
212     return NULL;
213
214   target_vec = bfd_find_target (target, nbfd);
215   if (target_vec == NULL)
216     {
217       bfd_set_error (bfd_error_invalid_target);
218       objalloc_free ((struct objalloc *) nbfd->memory);
219       free (nbfd);
220       return NULL;
221     }
222
223 #ifndef HAVE_FDOPEN
224   nbfd->iostream = (PTR) fopen (filename, FOPEN_RB);
225 #else
226   /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
227   switch (fdflags & (O_ACCMODE))
228     {
229     case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB);   break;
230     case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB);  break;
231     case O_RDWR:   nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB);  break;
232     default: abort ();
233     }
234 #endif
235
236   if (nbfd->iostream == NULL)
237     {
238       objalloc_free ((struct objalloc *) nbfd->memory);
239       free (nbfd);
240       return NULL;
241     }
242
243   /* OK, put everything where it belongs */
244
245   nbfd->filename = filename;
246
247   /* As a special case we allow a FD open for read/write to
248      be written through, although doing so requires that we end
249      the previous clause with a preposition.  */
250   /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
251   switch (fdflags & O_ACCMODE)
252     {
253     case O_RDONLY: nbfd->direction = read_direction; break;
254     case O_WRONLY: nbfd->direction = write_direction; break;
255     case O_RDWR: nbfd->direction = both_direction; break;
256     default: abort ();
257     }
258
259   if (! bfd_cache_init (nbfd))
260     {
261       objalloc_free ((struct objalloc *) nbfd->memory);
262       free (nbfd);
263       return NULL;
264     }
265   nbfd->opened_once = true;
266
267   return nbfd;
268 }
269
270 /*
271 FUNCTION
272         bfd_openstreamr
273
274 SYNOPSIS
275         bfd *bfd_openstreamr(const char *, const char *, PTR);
276
277 DESCRIPTION
278
279         Open a BFD for read access on an existing stdio stream.  When
280         the BFD is passed to <<bfd_close>>, the stream will be closed.
281 */
282
283 bfd *
284 bfd_openstreamr (filename, target, streamarg)
285      const char *filename;
286      const char *target;
287      PTR streamarg;
288 {
289   FILE *stream = (FILE *) streamarg;
290   bfd *nbfd;
291   const bfd_target *target_vec;
292
293   nbfd = _bfd_new_bfd ();
294   if (nbfd == NULL)
295     return NULL;
296
297   target_vec = bfd_find_target (target, nbfd);
298   if (target_vec == NULL)
299     {
300       bfd_set_error (bfd_error_invalid_target);
301       objalloc_free ((struct objalloc *) nbfd->memory);
302       free (nbfd);
303       return NULL;
304     }
305
306   nbfd->iostream = (PTR) stream;
307   nbfd->filename = filename;
308   nbfd->direction = read_direction;
309                                 
310   if (! bfd_cache_init (nbfd))
311     {
312       objalloc_free ((struct objalloc *) nbfd->memory);
313       free (nbfd);
314       return NULL;
315     }
316
317   return nbfd;
318 }
319 \f
320 /** bfd_openw -- open for writing.
321   Returns a pointer to a freshly-allocated BFD on success, or NULL.
322
323   See comment by bfd_fdopenr before you try to modify this function. */
324
325 /*
326 FUNCTION
327         bfd_openw
328
329 SYNOPSIS
330         bfd *bfd_openw(CONST char *filename, CONST char *target);
331
332 DESCRIPTION
333         Create a BFD, associated with file @var{filename}, using the
334         file format @var{target}, and return a pointer to it.
335
336         Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
337         <<bfd_error_invalid_target>>.
338 */
339
340 bfd *
341 bfd_openw (filename, target)
342      CONST char *filename;
343      CONST char *target;
344 {
345   bfd *nbfd;
346   const bfd_target *target_vec;
347
348   bfd_set_error (bfd_error_system_call);
349
350   /* nbfd has to point to head of malloc'ed block so that bfd_close may
351      reclaim it correctly. */
352
353   nbfd = _bfd_new_bfd ();
354   if (nbfd == NULL)
355     return NULL;
356
357   target_vec = bfd_find_target (target, nbfd);
358   if (target_vec == NULL)
359     {
360       objalloc_free ((struct objalloc *) nbfd->memory);
361       free (nbfd);
362       return NULL;
363     }
364
365   nbfd->filename = filename;
366   nbfd->direction = write_direction;
367
368   if (bfd_open_file (nbfd) == NULL)
369     {
370       bfd_set_error (bfd_error_system_call);    /* File not writeable, etc */
371       objalloc_free ((struct objalloc *) nbfd->memory);
372       free (nbfd);
373       return NULL;
374   }
375
376   return nbfd;
377 }
378
379 /*
380
381 FUNCTION
382         bfd_close
383
384 SYNOPSIS
385         boolean bfd_close(bfd *abfd);
386
387 DESCRIPTION
388
389         Close a BFD. If the BFD was open for writing,
390         then pending operations are completed and the file written out
391         and closed. If the created file is executable, then
392         <<chmod>> is called to mark it as such.
393
394         All memory attached to the BFD is released.
395
396         The file descriptor associated with the BFD is closed (even
397         if it was passed in to BFD by <<bfd_fdopenr>>).
398
399 RETURNS
400         <<true>> is returned if all is ok, otherwise <<false>>.
401 */
402
403
404 boolean
405 bfd_close (abfd)
406      bfd *abfd;
407 {
408   boolean ret;
409
410   if (!bfd_read_p (abfd))
411     {
412       if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
413         return false;
414     }
415
416   if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
417     return false;
418
419   ret = bfd_cache_close (abfd);
420
421   /* If the file was open for writing and is now executable,
422      make it so */
423   if (ret
424       && abfd->direction == write_direction
425       && abfd->flags & EXEC_P)
426     {
427       struct stat buf;
428
429       if (stat (abfd->filename, &buf) == 0)
430         {
431           int mask = umask (0);
432           umask (mask);
433           chmod (abfd->filename,
434                  (0777
435                   & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
436         }
437     }
438
439   objalloc_free ((struct objalloc *) abfd->memory);
440   free (abfd);
441
442   return ret;
443 }
444
445 /*
446 FUNCTION
447         bfd_close_all_done
448
449 SYNOPSIS
450         boolean bfd_close_all_done(bfd *);
451
452 DESCRIPTION
453         Close a BFD.  Differs from <<bfd_close>>
454         since it does not complete any pending operations.  This
455         routine would be used if the application had just used BFD for
456         swapping and didn't want to use any of the writing code.
457
458         If the created file is executable, then <<chmod>> is called
459         to mark it as such.
460
461         All memory attached to the BFD is released.
462
463 RETURNS
464         <<true>> is returned if all is ok, otherwise <<false>>.
465
466 */
467
468 boolean
469 bfd_close_all_done (abfd)
470      bfd *abfd;
471 {
472   boolean ret;
473
474   ret = bfd_cache_close (abfd);
475
476   /* If the file was open for writing and is now executable,
477      make it so */
478   if (ret
479       && abfd->direction == write_direction
480       && abfd->flags & EXEC_P)
481     {
482       struct stat buf;
483
484       if (stat (abfd->filename, &buf) == 0)
485         {
486           int mask = umask (0);
487           umask (mask);
488           chmod (abfd->filename,
489                  (0x777
490                   & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
491         }
492     }
493
494   objalloc_free ((struct objalloc *) abfd->memory);
495   free (abfd);
496
497   return ret;
498 }
499
500 /*
501 FUNCTION
502         bfd_create
503
504 SYNOPSIS
505         bfd *bfd_create(CONST char *filename, bfd *templ);
506
507 DESCRIPTION
508         Create a new BFD in the manner of
509         <<bfd_openw>>, but without opening a file. The new BFD
510         takes the target from the target used by @var{template}. The
511         format is always set to <<bfd_object>>.
512
513 */
514
515 bfd *
516 bfd_create (filename, templ)
517      CONST char *filename;
518      bfd *templ;
519 {
520   bfd *nbfd;
521
522   nbfd = _bfd_new_bfd ();
523   if (nbfd == NULL)
524     return NULL;
525   nbfd->filename = filename;
526   if (templ)
527     nbfd->xvec = templ->xvec;
528   nbfd->direction = no_direction;
529   bfd_set_format (nbfd, bfd_object);
530   return nbfd;
531 }
532
533 /*
534 FUNCTION
535         bfd_make_writable
536
537 SYNOPSIS
538         boolean bfd_make_writable(bfd *abfd);
539
540 DESCRIPTION
541         Takes a BFD as created by <<bfd_create>> and converts it
542         into one like as returned by <<bfd_openw>>.  It does this
543         by converting the BFD to BFD_IN_MEMORY.  It's assumed that
544         you will call <<bfd_make_readable>> on this bfd later.
545
546 RETURNS
547         <<true>> is returned if all is ok, otherwise <<false>>.
548 */
549
550 boolean
551 bfd_make_writable(abfd)
552      bfd *abfd;
553 {
554   struct bfd_in_memory *bim;
555
556   if (abfd->direction != no_direction)
557     {
558       bfd_set_error (bfd_error_invalid_operation);
559       return false;
560     }
561
562   bim = (struct bfd_in_memory *) bfd_malloc (sizeof (struct bfd_in_memory));
563   abfd->iostream = (PTR) bim;
564   /* bfd_write will grow these as needed */
565   bim->size = 0;
566   bim->buffer = 0;
567
568   abfd->flags |= BFD_IN_MEMORY;
569   abfd->direction = write_direction;
570   abfd->where = 0;
571
572   return true;
573 }
574
575 /*
576 FUNCTION
577         bfd_make_readable
578
579 SYNOPSIS
580         boolean bfd_make_readable(bfd *abfd);
581
582 DESCRIPTION
583         Takes a BFD as created by <<bfd_create>> and
584         <<bfd_make_writable>> and converts it into one like as
585         returned by <<bfd_openr>>.  It does this by writing the
586         contents out to the memory buffer, then reversing the
587         direction.
588
589 RETURNS
590         <<true>> is returned if all is ok, otherwise <<false>>.  */
591
592 boolean
593 bfd_make_readable(abfd)
594      bfd *abfd;
595 {
596   if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY))
597     {
598       bfd_set_error (bfd_error_invalid_operation);
599       return false;
600     }
601
602   if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
603     return false;
604
605   if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
606     return false;
607
608
609   abfd->arch_info = &bfd_default_arch_struct;
610
611   abfd->where = 0;
612   abfd->sections = (asection *) NULL;
613   abfd->format = bfd_unknown;
614   abfd->my_archive = (bfd *) NULL;
615   abfd->origin = 0;                             
616   abfd->opened_once = false;
617   abfd->output_has_begun = false;
618   abfd->section_count = 0;
619   abfd->usrdata = (PTR) NULL;
620   abfd->cacheable = false;
621   abfd->flags = BFD_IN_MEMORY;
622   abfd->mtime_set = false;
623
624   abfd->target_defaulted = true;
625   abfd->direction = read_direction;
626   abfd->sections = 0;
627   abfd->symcount = 0;
628   abfd->outsymbols = 0;
629   abfd->tdata.any = 0;
630
631   bfd_check_format(abfd, bfd_object);
632
633   return true;
634 }
635
636 /*
637 INTERNAL_FUNCTION
638         bfd_alloc
639
640 SYNOPSIS
641         PTR bfd_alloc (bfd *abfd, size_t wanted);
642
643 DESCRIPTION
644         Allocate a block of @var{wanted} bytes of memory attached to
645         <<abfd>> and return a pointer to it.
646 */
647
648
649 PTR
650 bfd_alloc (abfd, size)
651      bfd *abfd;
652      size_t size;
653 {
654   PTR ret;
655
656   ret = objalloc_alloc (abfd->memory, (unsigned long) size);
657   if (ret == NULL)
658     bfd_set_error (bfd_error_no_memory);
659   return ret;
660 }
661
662 PTR
663 bfd_zalloc (abfd, size)
664      bfd *abfd;
665      size_t size;
666 {
667   PTR res;
668
669   res = bfd_alloc (abfd, size);
670   if (res)
671     memset (res, 0, size);
672   return res;
673 }
674
675 /* Free a block allocated for a BFD.  */
676
677 void
678 bfd_release (abfd, block)
679      bfd *abfd;
680      PTR block;
681 {
682   objalloc_free_block ((struct objalloc *) abfd->memory, block);
683 }