1 /* opncls.c -- open and close a BFD.
2 Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997
3 Free Software Foundation, Inc.
5 Written by Cygnus Support.
7 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
29 #define S_IXUSR 0100 /* Execute by owner. */
32 #define S_IXGRP 0010 /* Execute by group. */
35 #define S_IXOTH 0001 /* Execute by others. */
38 /* fdopen is a loser -- we should use stdio exclusively. Unfortunately
39 if we do that we can't use fcntl. */
42 #define obstack_chunk_alloc malloc
43 #define obstack_chunk_free free
45 #ifndef HAVE_GETPAGESIZE
46 #define getpagesize() 2048
49 long _bfd_chunksize = -1;
51 /* Return a new BFD. All BFD's are allocated through this routine. */
58 nbfd = (bfd *)bfd_zmalloc (sizeof (bfd));
62 if (_bfd_chunksize <= 0)
64 _bfd_chunksize = getpagesize ();
65 if (_bfd_chunksize <= 0)
66 _bfd_chunksize = 2048;
67 /* Leave some slush space, since many malloc implementations
68 prepend a header, and may wind up wasting another page
73 if (!obstack_begin(&nbfd->memory, _bfd_chunksize))
75 bfd_set_error (bfd_error_no_memory);
79 nbfd->arch_info = &bfd_default_arch_struct;
81 nbfd->direction = no_direction;
82 nbfd->iostream = NULL;
84 nbfd->sections = (asection *)NULL;
85 nbfd->format = bfd_unknown;
86 nbfd->my_archive = (bfd *)NULL;
88 nbfd->opened_once = false;
89 nbfd->output_has_begun = false;
90 nbfd->section_count = 0;
91 nbfd->usrdata = (PTR)NULL;
92 nbfd->cacheable = false;
93 nbfd->flags = BFD_NO_FLAGS;
94 nbfd->mtime_set = false;
99 /* Allocate a new BFD as a member of archive OBFD. */
102 _bfd_new_bfd_contained_in (obfd)
107 nbfd = _bfd_new_bfd();
108 nbfd->xvec = obfd->xvec;
109 nbfd->my_archive = obfd;
110 nbfd->direction = read_direction;
111 nbfd->target_defaulted = obfd->target_defaulted;
117 Opening and closing BFDs
126 bfd *bfd_openr(CONST char *filename, CONST char *target);
129 Open the file @var{filename} (using <<fopen>>) with the target
130 @var{target}. Return a pointer to the created BFD.
132 Calls <<bfd_find_target>>, so @var{target} is interpreted as by
135 If <<NULL>> is returned then an error has occured. Possible errors
136 are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error.
140 bfd_openr (filename, target)
141 CONST char *filename;
145 const bfd_target *target_vec;
147 nbfd = _bfd_new_bfd();
151 target_vec = bfd_find_target (target, nbfd);
152 if (target_vec == NULL) {
153 bfd_set_error (bfd_error_invalid_target);
157 nbfd->filename = filename;
158 nbfd->direction = read_direction;
160 if (bfd_open_file (nbfd) == NULL) {
161 bfd_set_error (bfd_error_system_call); /* File didn't exist, or some such */
169 /* Don't try to `optimize' this function:
171 o - We lock using stack space so that interrupting the locking
172 won't cause a storage leak.
173 o - We open the file stream last, since we don't want to have to
174 close it if anything goes wrong. Closing the stream means closing
175 the file descriptor too, even though we didn't open it.
182 bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd);
185 <<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to <<fopen>>.
186 It opens a BFD on a file already described by the @var{fd}
189 When the file is later <<bfd_close>>d, the file descriptor will be closed.
191 If the caller desires that this file descriptor be cached by BFD
192 (opened as needed, closed as needed to free descriptors for
193 other opens), with the supplied @var{fd} used as an initial
194 file descriptor (but subject to closure at any time), call
195 bfd_set_cacheable(bfd, 1) on the returned BFD. The default is to
196 assume no cacheing; the file descriptor will remain open until
197 <<bfd_close>>, and will not be affected by BFD operations on other
200 Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
204 bfd_fdopenr (filename, target, fd)
205 CONST char *filename;
210 const bfd_target *target_vec;
213 bfd_set_error (bfd_error_system_call);
214 #if ! defined(HAVE_FCNTL) || ! defined(F_GETFL)
215 fdflags = O_RDWR; /* Assume full access */
217 fdflags = fcntl (fd, F_GETFL, NULL);
219 if (fdflags == -1) return NULL;
221 nbfd = _bfd_new_bfd();
226 target_vec = bfd_find_target (target, nbfd);
227 if (target_vec == NULL) {
228 bfd_set_error (bfd_error_invalid_target);
231 #if defined(VMS) || defined(__GO32__)
232 nbfd->iostream = (PTR)fopen(filename, FOPEN_RB);
234 /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
235 switch (fdflags & (O_ACCMODE)) {
236 case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB); break;
237 case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break;
238 case O_RDWR: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break;
242 if (nbfd->iostream == NULL) {
243 (void) obstack_free (&nbfd->memory, (PTR)0);
247 /* OK, put everything where it belongs */
249 nbfd->filename = filename;
251 /* As a special case we allow a FD open for read/write to
252 be written through, although doing so requires that we end
253 the previous clause with a preposition. */
254 /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
255 switch (fdflags & (O_ACCMODE)) {
256 case O_RDONLY: nbfd->direction = read_direction; break;
257 case O_WRONLY: nbfd->direction = write_direction; break;
258 case O_RDWR: nbfd->direction = both_direction; break;
262 if (! bfd_cache_init (nbfd))
264 nbfd->opened_once = true;
274 bfd *bfd_openstreamr();
278 Open a BFD for read access on an existing stdio stream. When
279 the BFD is passed to <<bfd_close>>, the stream will be closed.
283 bfd_openstreamr (filename, target, stream)
284 const char *filename;
289 const bfd_target *target_vec;
291 nbfd = _bfd_new_bfd ();
295 target_vec = bfd_find_target (target, nbfd);
296 if (target_vec == NULL)
298 bfd_set_error (bfd_error_invalid_target);
302 nbfd->iostream = (PTR) stream;
303 nbfd->filename = filename;
304 nbfd->direction = read_direction;
306 if (! bfd_cache_init (nbfd))
312 /** bfd_openw -- open for writing.
313 Returns a pointer to a freshly-allocated BFD on success, or NULL.
315 See comment by bfd_fdopenr before you try to modify this function. */
322 bfd *bfd_openw(CONST char *filename, CONST char *target);
325 Create a BFD, associated with file @var{filename}, using the
326 file format @var{target}, and return a pointer to it.
328 Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
329 <<bfd_error_invalid_target>>.
333 bfd_openw (filename, target)
334 CONST char *filename;
338 const bfd_target *target_vec;
340 bfd_set_error (bfd_error_system_call);
342 /* nbfd has to point to head of malloc'ed block so that bfd_close may
343 reclaim it correctly. */
345 nbfd = _bfd_new_bfd();
349 target_vec = bfd_find_target (target, nbfd);
350 if (target_vec == NULL) return NULL;
352 nbfd->filename = filename;
353 nbfd->direction = write_direction;
355 if (bfd_open_file (nbfd) == NULL) {
356 bfd_set_error (bfd_error_system_call); /* File not writeable, etc */
357 (void) obstack_free (&nbfd->memory, (PTR)0);
369 boolean bfd_close(bfd *abfd);
373 Close a BFD. If the BFD was open for writing,
374 then pending operations are completed and the file written out
375 and closed. If the created file is executable, then
376 <<chmod>> is called to mark it as such.
378 All memory attached to the BFD's obstacks is released.
380 The file descriptor associated with the BFD is closed (even
381 if it was passed in to BFD by <<bfd_fdopenr>>).
384 <<true>> is returned if all is ok, otherwise <<false>>.
394 if (!bfd_read_p (abfd))
396 if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
400 if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
403 ret = bfd_cache_close (abfd);
405 /* If the file was open for writing and is now executable,
408 && abfd->direction == write_direction
409 && abfd->flags & EXEC_P)
413 if (stat (abfd->filename, &buf) == 0)
415 int mask = umask (0);
417 chmod (abfd->filename,
419 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
423 (void) obstack_free (&abfd->memory, (PTR)0);
434 boolean bfd_close_all_done(bfd *);
437 Close a BFD. Differs from <<bfd_close>>
438 since it does not complete any pending operations. This
439 routine would be used if the application had just used BFD for
440 swapping and didn't want to use any of the writing code.
442 If the created file is executable, then <<chmod>> is called
445 All memory attached to the BFD's obstacks is released.
448 <<true>> is returned if all is ok, otherwise <<false>>.
453 bfd_close_all_done (abfd)
458 ret = bfd_cache_close (abfd);
460 /* If the file was open for writing and is now executable,
463 && abfd->direction == write_direction
464 && abfd->flags & EXEC_P)
468 if (stat (abfd->filename, &buf) == 0)
470 int mask = umask (0);
472 chmod (abfd->filename,
474 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
477 (void) obstack_free (&abfd->memory, (PTR)0);
488 bfd_size_type bfd_alloc_size(bfd *abfd);
491 Return the number of bytes in the obstacks connected to @var{abfd}.
496 bfd_alloc_size (abfd)
499 struct _obstack_chunk *chunk = abfd->memory.chunk;
502 size += chunk->limit - &(chunk->contents[0]);
515 bfd *bfd_create(CONST char *filename, bfd *templ);
518 Create a new BFD in the manner of
519 <<bfd_openw>>, but without opening a file. The new BFD
520 takes the target from the target used by @var{template}. The
521 format is always set to <<bfd_object>>.
526 bfd_create (filename, templ)
527 CONST char *filename;
530 bfd *nbfd = _bfd_new_bfd();
531 if (nbfd == (bfd *)NULL)
533 nbfd->filename = filename;
535 nbfd->xvec = templ->xvec;
537 nbfd->direction = no_direction;
538 bfd_set_format(nbfd, bfd_object);
547 PTR bfd_alloc (bfd *abfd, size_t wanted);
550 Allocate a block of @var{wanted} bytes of memory in the obstack
551 attached to <<abfd>> and return a pointer to it.
556 bfd_alloc (abfd, size)
562 ret = obstack_alloc (&(abfd->memory), size);
564 bfd_set_error (bfd_error_no_memory);
569 bfd_zalloc (abfd, size)
574 res = bfd_alloc(abfd, size);
576 memset(res, 0, (size_t)size);