1 /* opncls.c -- open and close a BFD.
2 Copyright (C) 1990-1991 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
27 extern void bfd_cache_init();
28 FILE *bfd_open_file();
30 /* fdopen is a loser -- we should use stdio exclusively. Unfortunately
31 if we do that we can't use fcntl. */
34 #define obstack_chunk_alloc bfd_xmalloc
35 #define obstack_chunk_free free
37 /* Return a new BFD. All BFD's are allocated through this routine. */
43 nbfd = (bfd *)zalloc (sizeof (bfd));
48 obstack_begin((PTR)&nbfd->memory, 128);
50 nbfd->arch_info = &bfd_default_arch_struct;
52 nbfd->direction = no_direction;
53 nbfd->iostream = NULL;
55 nbfd->sections = (asection *)NULL;
56 nbfd->format = bfd_unknown;
57 nbfd->my_archive = (bfd *)NULL;
59 nbfd->opened_once = false;
60 nbfd->output_has_begun = false;
61 nbfd->section_count = 0;
62 nbfd->usrdata = (PTR)NULL;
63 nbfd->sections = (asection *)NULL;
64 nbfd->cacheable = false;
65 nbfd->flags = NO_FLAGS;
70 /* Allocate a new BFD as a member of archive OBFD. */
72 bfd *new_bfd_contained_in(obfd)
75 bfd *nbfd = new_bfd();
76 nbfd->xvec = obfd->xvec;
77 nbfd->my_archive = obfd;
78 nbfd->direction = read_direction;
83 @section Opening and Closing BFDs
88 Opens the file supplied (using @code{fopen}) with the target supplied, it
89 returns a pointer to the created BFD.
91 If NULL is returned then an error has occured.
92 Possible errors are no_memory, invalid_target or system_call error.
93 *; PROTO(bfd*, bfd_openr, (CONST char *filename,CONST char*target));
97 DEFUN(bfd_openr, (filename, target),
98 CONST char *filename AND
102 bfd_target *target_vec;
106 bfd_error = no_memory;
110 target_vec = bfd_find_target (target, nbfd);
111 if (target_vec == NULL) {
112 bfd_error = invalid_target;
116 nbfd->filename = filename;
117 nbfd->direction = read_direction;
119 if (bfd_open_file (nbfd) == NULL) {
120 bfd_error = system_call_error; /* File didn't exist, or some such */
128 /* Don't try to `optimize' this function:
130 o - We lock using stack space so that interrupting the locking
131 won't cause a storage leak.
132 o - We open the file stream last, since we don't want to have to
133 close it if anything goes wrong. Closing the stream means closing
134 the file descriptor too, even though we didn't open it.
138 bfd_fdopenr is to bfd_fopenr much like fdopen is to fopen. It opens a BFD on
139 a file already described by the @var{fd} supplied.
141 Possible errors are no_memory, invalid_target and system_call error.
142 *; PROTO(bfd *, bfd_fdopenr,
143 (CONST char *filename, CONST char *target, int fd));
147 DEFUN(bfd_fdopenr,(filename, target, fd),
148 CONST char *filename AND
149 CONST char *target AND
153 bfd_target *target_vec;
156 bfd_error = system_call_error;
159 fdflags = O_RDWR; /* Assume full access */
161 fdflags = fcntl (fd, F_GETFL, NULL);
163 if (fdflags == -1) return NULL;
168 bfd_error = no_memory;
172 target_vec = bfd_find_target (target, nbfd);
173 if (target_vec == NULL) {
174 bfd_error = invalid_target;
178 #ifdef FASCIST_FDOPEN
179 nbfd->iostream = (char *) fdopen (fd, "r");
181 /* if the fd were open for read only, this still would not hurt: */
182 nbfd->iostream = (char *) fdopen (fd, "r+");
184 if (nbfd->iostream == NULL) {
185 (void) obstack_free (&nbfd->memory, (PTR)0);
189 /* OK, put everything where it belongs */
191 nbfd->filename = filename;
193 /* As a special case we allow a FD open for read/write to
194 be written through, although doing so requires that we end
195 the previous clause with a preposition. */
196 /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
197 switch (fdflags & (O_ACCMODE)) {
198 case O_RDONLY: nbfd->direction = read_direction; break;
199 case O_WRONLY: nbfd->direction = write_direction; break;
200 case O_RDWR: nbfd->direction = both_direction; break;
204 bfd_cache_init (nbfd);
209 /** bfd_openw -- open for writing.
210 Returns a pointer to a freshly-allocated BFD on success, or NULL.
212 See comment by bfd_fdopenr before you try to modify this function. */
215 Creates a BFD, associated with file @var{filename}, using the file
216 format @var{target}, and returns a pointer to it.
218 Possible errors are system_call_error, no_memory, invalid_target.
219 *; PROTO(bfd *, bfd_openw, (CONST char *filename, CONST char *target));
223 DEFUN(bfd_openw,(filename, target),
224 CONST char *filename AND
228 bfd_target *target_vec;
230 bfd_error = system_call_error;
232 /* nbfd has to point to head of malloc'ed block so that bfd_close may
233 reclaim it correctly. */
237 bfd_error = no_memory;
241 target_vec = bfd_find_target (target, nbfd);
242 if (target_vec == NULL) return NULL;
244 nbfd->filename = filename;
245 nbfd->direction = write_direction;
247 if (bfd_open_file (nbfd) == NULL) {
248 bfd_error = system_call_error; /* File not writeable, etc */
249 (void) obstack_free (&nbfd->memory, (PTR)0);
256 This function closes a BFD. If the BFD was open for writing, then
257 pending operations are completed and the file written out and closed.
258 If the created file is executable, then @code{chmod} is called to mark
261 All memory attached to the BFD's obstacks is released.
263 @code{true} is returned if all is ok, otherwise @code{false}.
264 *; PROTO(boolean, bfd_close,(bfd *));
268 DEFUN(bfd_close,(abfd),
271 if (!bfd_read_p(abfd))
272 if (BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)) != true)
275 if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
277 bfd_cache_close(abfd);
279 /* If the file was open for writing and is now executable,
281 if (abfd->direction == write_direction
282 && abfd->flags & EXEC_P) {
284 stat(abfd->filename, &buf);
286 #define S_IXUSR 0100 /* Execute by owner. */
289 #define S_IXGRP 0010 /* Execute by group. */
292 #define S_IXOTH 0001 /* Execute by others. */
295 chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
297 (void) obstack_free (&abfd->memory, (PTR)0);
302 /*proto* bfd_close_all_done
303 This function closes a BFD. It differs from @code{bfd_close} since it
304 does not complete any pending operations. This routine would be used
305 if the application had just used BFD for swapping and didn't want to
306 use any of the writing code.
308 If the created file is executable, then @code{chmod} is called to mark
311 All memory attached to the BFD's obstacks is released.
313 @code{true} is returned if all is ok, otherwise @code{false}.
314 *; PROTO(boolean, bfd_close_all_done,(bfd *));
318 DEFUN(bfd_close_all_done,(abfd),
321 bfd_cache_close(abfd);
323 /* If the file was open for writing and is now executable,
325 if (abfd->direction == write_direction
326 && abfd->flags & EXEC_P) {
328 stat(abfd->filename, &buf);
330 #define S_IXUSR 0100 /* Execute by owner. */
333 #define S_IXGRP 0010 /* Execute by group. */
336 #define S_IXOTH 0001 /* Execute by others. */
339 chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
341 (void) obstack_free (&abfd->memory, (PTR)0);
347 This routine creates a new BFD in the manner of @code{bfd_openw}, but without
348 opening a file. The new BFD takes the target from the target used by
349 @var{template}. The format is always set to @code{bfd_object}.
351 *; PROTO(bfd *, bfd_create, (CONST char *filename, bfd *template));
355 DEFUN(bfd_create,(filename, template),
356 CONST char *filename AND
359 bfd *nbfd = new_bfd();
360 if (nbfd == (bfd *)NULL) {
361 bfd_error = no_memory;
364 nbfd->filename = filename;
366 nbfd->xvec = template->xvec;
368 nbfd->direction = no_direction;
369 bfd_set_format(nbfd, bfd_object);
373 /* Memory allocation */
375 DEFUN(PTR bfd_alloc_by_size_t,(abfd, size),
379 PTR res = obstack_alloc(&(abfd->memory), size);
383 DEFUN(void bfd_alloc_grow,(abfd, ptr, size),
388 (void) obstack_grow(&(abfd->memory), ptr, size);
390 DEFUN(PTR bfd_alloc_finish,(abfd),
393 return obstack_finish(&(abfd->memory));
396 DEFUN(PTR bfd_alloc, (abfd, size),
400 return bfd_alloc_by_size_t(abfd, (size_t)size);
403 DEFUN(PTR bfd_zalloc,(abfd, size),
407 PTR res = bfd_alloc(abfd, size);
408 memset(res, 0, (size_t)size);
412 DEFUN(PTR bfd_realloc,(abfd, old, size),
417 PTR res = bfd_alloc(abfd, size);
418 memcpy(res, old, (size_t)size);
422 /*proto* bfd_alloc_size
423 Return the number of bytes in the obstacks connected to the supplied
425 *; PROTO(bfd_size_type,bfd_alloc_size,(bfd *abfd));
429 DEFUN( bfd_alloc_size,(abfd),
432 struct _obstack_chunk *chunk = abfd->memory.chunk;
435 size += chunk->limit - &(chunk->contents[0]);