1 /* opncls.c -- open and close a BFD.
2 Copyright (C) 1990 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
3 Written by Cygnus Support.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
27 #define S_IXUSR 0100 /* Execute by owner. */
30 #define S_IXGRP 0010 /* Execute by group. */
33 #define S_IXOTH 0001 /* Execute by others. */
36 /* fdopen is a loser -- we should use stdio exclusively. Unfortunately
37 if we do that we can't use fcntl. */
40 #define obstack_chunk_alloc malloc
41 #define obstack_chunk_free free
43 #ifndef HAVE_GETPAGESIZE
44 #define getpagesize() 2048
47 long _bfd_chunksize = -1;
49 /* Return a new BFD. All BFD's are allocated through this routine. */
56 nbfd = (bfd *)bfd_zmalloc (sizeof (bfd));
60 if (_bfd_chunksize <= 0)
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
71 if (!obstack_begin(&nbfd->memory, _bfd_chunksize))
73 bfd_set_error (bfd_error_no_memory);
77 nbfd->arch_info = &bfd_default_arch_struct;
79 nbfd->direction = no_direction;
80 nbfd->iostream = NULL;
82 nbfd->sections = (asection *)NULL;
83 nbfd->format = bfd_unknown;
84 nbfd->my_archive = (bfd *)NULL;
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 = BFD_NO_FLAGS;
92 nbfd->mtime_set = false;
97 /* Allocate a new BFD as a member of archive OBFD. */
100 _bfd_new_bfd_contained_in (obfd)
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;
115 Opening and closing BFDs
124 bfd *bfd_openr(CONST char *filename, CONST char *target);
127 Open the file @var{filename} (using <<fopen>>) with the target
128 @var{target}. Return a pointer to the created BFD.
130 Calls <<bfd_find_target>>, so @var{target} is interpreted as by
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.
138 bfd_openr (filename, target)
139 CONST char *filename;
143 const bfd_target *target_vec;
145 nbfd = _bfd_new_bfd();
149 target_vec = bfd_find_target (target, nbfd);
150 if (target_vec == NULL) {
151 bfd_set_error (bfd_error_invalid_target);
155 nbfd->filename = filename;
156 nbfd->direction = read_direction;
158 if (bfd_open_file (nbfd) == NULL) {
159 bfd_set_error (bfd_error_system_call); /* File didn't exist, or some such */
167 /* Don't try to `optimize' this function:
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.
180 bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd);
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}
187 When the file is later <<bfd_close>>d, the file descriptor will be closed.
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
198 Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
202 bfd_fdopenr (filename, target, fd)
203 CONST char *filename;
208 const bfd_target *target_vec;
211 bfd_set_error (bfd_error_system_call);
212 #if ! defined(HAVE_FCNTL) || ! defined(F_GETFL)
213 fdflags = O_RDWR; /* Assume full access */
215 fdflags = fcntl (fd, F_GETFL, NULL);
217 if (fdflags == -1) return NULL;
219 nbfd = _bfd_new_bfd();
224 target_vec = bfd_find_target (target, nbfd);
225 if (target_vec == NULL) {
226 bfd_set_error (bfd_error_invalid_target);
229 #if defined(VMS) || defined(__GO32__) || defined (WINGDB)
230 nbfd->iostream = (PTR)fopen(filename, FOPEN_RB);
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;
240 if (nbfd->iostream == NULL) {
241 (void) obstack_free (&nbfd->memory, (PTR)0);
245 /* OK, put everything where it belongs */
247 nbfd->filename = filename;
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;
260 if (! bfd_cache_init (nbfd))
262 nbfd->opened_once = true;
272 bfd *bfd_openstreamr();
276 Open a BFD for read access on an existing stdio stream. When
277 the BFD is passed to <<bfd_close>>, the stream will be closed.
281 bfd_openstreamr (filename, target, stream)
282 const char *filename;
287 const bfd_target *target_vec;
289 nbfd = _bfd_new_bfd ();
293 target_vec = bfd_find_target (target, nbfd);
294 if (target_vec == NULL)
296 bfd_set_error (bfd_error_invalid_target);
300 nbfd->iostream = (PTR) stream;
301 nbfd->filename = filename;
302 nbfd->direction = read_direction;
304 if (! bfd_cache_init (nbfd))
310 /** bfd_openw -- open for writing.
311 Returns a pointer to a freshly-allocated BFD on success, or NULL.
313 See comment by bfd_fdopenr before you try to modify this function. */
320 bfd *bfd_openw(CONST char *filename, CONST char *target);
323 Create a BFD, associated with file @var{filename}, using the
324 file format @var{target}, and return a pointer to it.
326 Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
327 <<bfd_error_invalid_target>>.
331 bfd_openw (filename, target)
332 CONST char *filename;
336 const bfd_target *target_vec;
338 bfd_set_error (bfd_error_system_call);
340 /* nbfd has to point to head of malloc'ed block so that bfd_close may
341 reclaim it correctly. */
343 nbfd = _bfd_new_bfd();
347 target_vec = bfd_find_target (target, nbfd);
348 if (target_vec == NULL) return NULL;
350 nbfd->filename = filename;
351 nbfd->direction = write_direction;
353 if (bfd_open_file (nbfd) == NULL) {
354 bfd_set_error (bfd_error_system_call); /* File not writeable, etc */
355 (void) obstack_free (&nbfd->memory, (PTR)0);
367 boolean bfd_close(bfd *abfd);
371 Close a BFD. If the BFD was open for writing,
372 then pending operations are completed and the file written out
373 and closed. If the created file is executable, then
374 <<chmod>> is called to mark it as such.
376 All memory attached to the BFD's obstacks is released.
378 The file descriptor associated with the BFD is closed (even
379 if it was passed in to BFD by <<bfd_fdopenr>>).
382 <<true>> is returned if all is ok, otherwise <<false>>.
392 if (!bfd_read_p (abfd))
394 if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
398 if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
401 ret = bfd_cache_close (abfd);
403 /* If the file was open for writing and is now executable,
406 && abfd->direction == write_direction
407 && abfd->flags & EXEC_P)
411 if (stat (abfd->filename, &buf) == 0)
413 int mask = umask (0);
415 chmod (abfd->filename,
417 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
421 (void) obstack_free (&abfd->memory, (PTR)0);
432 boolean bfd_close_all_done(bfd *);
435 Close a BFD. Differs from <<bfd_close>>
436 since it does not complete any pending operations. This
437 routine would be used if the application had just used BFD for
438 swapping and didn't want to use any of the writing code.
440 If the created file is executable, then <<chmod>> is called
443 All memory attached to the BFD's obstacks is released.
446 <<true>> is returned if all is ok, otherwise <<false>>.
451 bfd_close_all_done (abfd)
456 ret = bfd_cache_close (abfd);
458 /* If the file was open for writing and is now executable,
461 && abfd->direction == write_direction
462 && abfd->flags & EXEC_P)
466 if (stat (abfd->filename, &buf) == 0)
468 int mask = umask (0);
470 chmod (abfd->filename,
472 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
475 (void) obstack_free (&abfd->memory, (PTR)0);
486 bfd_size_type bfd_alloc_size(bfd *abfd);
489 Return the number of bytes in the obstacks connected to @var{abfd}.
494 bfd_alloc_size (abfd)
497 struct _obstack_chunk *chunk = abfd->memory.chunk;
500 size += chunk->limit - &(chunk->contents[0]);
513 bfd *bfd_create(CONST char *filename, bfd *templ);
516 Create a new BFD in the manner of
517 <<bfd_openw>>, but without opening a file. The new BFD
518 takes the target from the target used by @var{template}. The
519 format is always set to <<bfd_object>>.
524 bfd_create (filename, templ)
525 CONST char *filename;
528 bfd *nbfd = _bfd_new_bfd();
529 if (nbfd == (bfd *)NULL)
531 nbfd->filename = filename;
533 nbfd->xvec = templ->xvec;
535 nbfd->direction = no_direction;
536 bfd_set_format(nbfd, bfd_object);
545 PTR bfd_alloc_by_size_t(bfd *abfd, size_t wanted);
548 Allocate a block of @var{wanted} bytes of memory in the obstack
549 attatched to <<abfd>> and return a pointer to it.
554 bfd_alloc_by_size_t (abfd, size)
560 ret = obstack_alloc (&(abfd->memory), size);
562 bfd_set_error (bfd_error_no_memory);
567 bfd_alloc_grow (abfd, ptr, size)
572 (void) obstack_grow(&(abfd->memory), ptr, size);
576 bfd_alloc_finish (abfd)
581 ret = obstack_finish (&(abfd->memory));
583 bfd_set_error (bfd_error_no_memory);
588 bfd_alloc (abfd, size)
592 return bfd_alloc_by_size_t(abfd, (size_t)size);
596 bfd_zalloc (abfd, size)
601 res = bfd_alloc(abfd, size);
603 memset(res, 0, (size_t)size);