]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/opncls.c
19990502 sourceware import
[thirdparty/binutils-gdb.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 }