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. */
35 Locking is loosely controlled by the preprocessor variable
36 BFD_LOCKS. I say loosely because Unix barely understands locking
37 -- at least in BSD it doesn't affect programs which don't
38 explicitly use it! That is to say it's practically useless, though
39 if everyone uses this library you'll be OK.
41 From among the many and varied lock facilities available, (none of
42 which, of course, knows about any other) we use the fcntl locks,
43 because they're Posix.
45 The reason that @code{bfd_openr} and @code{bfd_fdopenr} exist, yet
46 only @code{bfd_openw} exists is because of locking. When we do
47 output, we lock the filename file for output, then open a temporary
48 file which does not actually get its correct filename until closing
49 time. This is safest, but requires the asymmetry in read and write
52 Perhaps, since unix has so many different kinds of locking anyway,
53 we should use the emacs lock scheme?... */
55 #define obstack_chunk_alloc malloc
56 #define obstack_chunk_free free
58 /* Return a new BFD. All BFD's are allocated through this routine. */
64 nbfd = (bfd *)zalloc (sizeof (bfd));
68 obstack_begin((PTR)&nbfd->memory, 128);
70 nbfd->direction = no_direction;
71 nbfd->iostream = NULL;
73 nbfd->sections = (asection *)NULL;
74 nbfd->format = bfd_unknown;
75 nbfd->my_archive = (bfd *)NULL;
77 nbfd->opened_once = false;
78 nbfd->output_has_begun = false;
79 nbfd->section_count = 0;
80 nbfd->usrdata = (PTR)NULL;
81 nbfd->sections = (asection *)NULL;
82 nbfd->cacheable = false;
83 nbfd->flags = NO_FLAGS;
88 /* Allocate a new BFD as a member of archive OBFD. */
90 bfd *new_bfd_contained_in(obfd)
93 bfd *nbfd = new_bfd();
94 nbfd->xvec = obfd->xvec;
95 nbfd->my_archive = obfd;
96 nbfd->direction = read_direction;
101 @section Opening and Closing BFDs
106 Opens the file supplied (using @code{fopen}) with the target supplied, it
107 returns a pointer to the created BFD.
109 If NULL is returned then an error has occured.
110 Possible errors are no_memory, invalid_target or system_call error.
111 *; PROTO(bfd*, bfd_openr, (CONST char *filename,CONST char*target));
115 DEFUN(bfd_openr, (filename, target),
116 CONST char *filename AND
120 bfd_target *target_vec;
124 bfd_error = no_memory;
128 target_vec = bfd_find_target (target, nbfd);
129 if (target_vec == NULL) {
130 bfd_error = invalid_target;
134 nbfd->filename = filename;
135 nbfd->direction = read_direction;
137 if (bfd_open_file (nbfd) == NULL) {
138 bfd_error = system_call_error; /* File didn't exist, or some such */
146 /* Don't try to `optimize' this function:
148 o - We lock using stack space so that interrupting the locking
149 won't cause a storage leak.
150 o - We open the file stream last, since we don't want to have to
151 close it if anything goes wrong. Closing the stream means closing
152 the file descriptor too, even though we didn't open it.
156 bfd_fdopenr is to bfd_fopenr much like fdopen is to fopen. It opens a BFD on
157 a file already described by the @var{fd} supplied.
159 Possible errors are no_memory, invalid_target and system_call error.
160 *; PROTO(bfd *, bfd_fdopenr,
161 (CONST char *filename, CONST char *target, int fd));
165 DEFUN(bfd_fdopenr,(filename, target, fd),
166 CONST char *filename AND
167 CONST char *target AND
171 bfd_target *target_vec;
174 struct flock lock, *lockp = &lock;
177 bfd_error = system_call_error;
179 fdflags = fcntl (fd, F_GETFL, NULL);
180 if (fdflags == -1) return NULL;
183 lockp->l_type = F_RDLCK;
184 if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
190 bfd_error = no_memory;
194 target_vec = bfd_find_target (target, nbfd);
195 if (target_vec == NULL) {
196 bfd_error = invalid_target;
201 nbfd->lock = (struct flock *) (nbfd + 1);
203 /* if the fd were open for read only, this still would not hurt: */
204 nbfd->iostream = (char *) fdopen (fd, "r+");
205 if (nbfd->iostream == NULL) {
206 (void) obstack_free (&nbfd->memory, (PTR)0);
210 /* OK, put everything where it belongs */
212 nbfd->filename = filename;
214 /* As a special case we allow a FD open for read/write to
215 be written through, although doing so requires that we end
216 the previous clause with a preposition. */
217 switch (fdflags & O_ACCMODE) {
218 case O_RDONLY: nbfd->direction = read_direction; break;
219 case O_WRONLY: nbfd->direction = write_direction; break;
220 case O_RDWR: nbfd->direction = both_direction; break;
225 memcpy (nbfd->lock, lockp, sizeof (struct flock))
228 bfd_cache_init (nbfd);
233 /** bfd_openw -- open for writing.
234 Returns a pointer to a freshly-allocated BFD on success, or NULL.
236 See comment by bfd_fdopenr before you try to modify this function. */
239 Creates a BFD, associated with file @var{filename}, using the file
240 format @var{target}, and returns a pointer to it.
242 Possible errors are system_call_error, no_memory, invalid_target.
243 *; PROTO(bfd *, bfd_openw, (CONST char *filename, CONST char *target));
247 DEFUN(bfd_openw,(filename, target),
248 CONST char *filename AND
252 bfd_target *target_vec;
254 bfd_error = system_call_error;
256 /* nbfd has to point to head of malloc'ed block so that bfd_close may
257 reclaim it correctly. */
261 bfd_error = no_memory;
265 target_vec = bfd_find_target (target, nbfd);
266 if (target_vec == NULL) return NULL;
268 nbfd->filename = filename;
269 nbfd->direction = write_direction;
271 if (bfd_open_file (nbfd) == NULL) {
272 bfd_error = system_call_error; /* File not writeable, etc */
273 (void) obstack_free (&nbfd->memory, (PTR)0);
280 This function closes a BFD. If the BFD was open for writing, then
281 pending operations are completed and the file written out and closed.
282 If the created file is executable, then @code{chmod} is called to mark
285 All memory attatched to the BFD's obstacks is released.
287 @code{true} is returned if all is ok, otherwise @code{false}.
288 *; PROTO(boolean, bfd_close,(bfd *));
292 DEFUN(bfd_close,(abfd),
295 if (!bfd_read_p(abfd))
296 if (BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)) != true)
299 if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
301 bfd_cache_close(abfd);
303 /* If the file was open for writing and is now executable,
305 if (abfd->direction == write_direction
306 && abfd->flags & EXEC_P) {
308 stat(abfd->filename, &buf);
310 #define S_IXUSR 0100 /* Execute by owner. */
313 #define S_IXGRP 0010 /* Execute by group. */
316 #define S_IXOTH 0001 /* Execute by others. */
319 chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
321 (void) obstack_free (&abfd->memory, (PTR)0);
322 /* FIXME, shouldn't we de-allocate the bfd as well? */
327 This routine creates a new BFD in the manner of @code{bfd_openw}, but without
328 opening a file. The new BFD takes the target from the target used by
329 @var{template}. The format is always set to @code{bfd_object}.
331 *; PROTO(bfd *, bfd_create, (CONST char *filename, bfd *template));
335 DEFUN(bfd_create,(filename, template),
336 CONST char *filename AND
339 bfd *nbfd = new_bfd();
340 if (nbfd == (bfd *)NULL) {
341 bfd_error = no_memory;
344 nbfd->filename = filename;
346 nbfd->xvec = template->xvec;
348 nbfd->direction = no_direction;
349 bfd_set_format(nbfd, bfd_object);
353 /* Memory allocation */
355 DEFUN(PTR bfd_alloc_by_size_t,(abfd, size),
359 PTR res = obstack_alloc(&(abfd->memory), size);
363 DEFUN(void bfd_alloc_grow,(abfd, ptr, size),
368 (void) obstack_grow(&(abfd->memory), ptr, size);
370 DEFUN(PTR bfd_alloc_finish,(abfd),
373 return obstack_finish(&(abfd->memory));
376 DEFUN(PTR bfd_alloc, (abfd, size),
380 return bfd_alloc_by_size_t(abfd, (size_t)size);
383 DEFUN(PTR bfd_zalloc,(abfd, size),
387 PTR res = bfd_alloc(abfd, size);
388 memset(res, 0, (size_t)size);
392 DEFUN(PTR bfd_realloc,(abfd, old, size),
397 PTR res = bfd_alloc(abfd, size);
398 memcpy(res, old, (size_t)size);
402 /*proto* bfd_alloc_size
403 Return the number of bytes in the obstacks connected to the supplied
405 *; PROTO(bfd_size_type,bfd_alloc_size,(bfd *abfd));
409 DEFUN( bfd_alloc_size,(abfd),
412 struct _obstack_chunk *chunk = abfd->memory.chunk;
415 size += chunk->limit - &(chunk->contents[0]);