source: trunk/src/binutils/bfd/opncls.c@ 10

Last change on this file since 10 was 10, checked in by bird, 22 years ago

Initial revision

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