1 /* opncls.c -- open and close a bfd. */
3 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Diddler.
7 BFD 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 1, or (at your option)
12 BFD 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 BFD; see the file COPYING. If not, write to
19 the Free Software Foundation, 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 bfd_openr and bfd_fdopenr exist, yet only bfd_openw
46 exists is because of locking. When we do output, we lock the
47 filename file for output, then open a temporary file which does not
48 actually get its correct filename until closing time. This is
49 safest, but requires the asymmetry in read and write entry points.
51 Perhaps, since unix has so many different kinds of locking anyway,
52 we should use the emacs lock scheme?... */
54 #define obstack_chunk_alloc malloc
55 #define obstack_chunk_free free
57 /* Return a new BFD. All BFD's are allocated through this routine. */
63 nbfd = (bfd *)zalloc (sizeof (bfd));
67 obstack_begin((PTR)&nbfd->memory, 128);
69 nbfd->direction = no_direction;
70 nbfd->iostream = NULL;
72 nbfd->sections = (asection *)NULL;
73 nbfd->format = bfd_unknown;
74 nbfd->my_archive = (bfd *)NULL;
76 nbfd->opened_once = false;
77 nbfd->output_has_begun = false;
78 nbfd->section_count = 0;
79 nbfd->usrdata = (PTR)NULL;
80 nbfd->sections = (asection *)NULL;
81 nbfd->cacheable = false;
82 nbfd->flags = NO_FLAGS;
87 /* Allocate a new BFD as a member of archive OBFD. */
89 bfd *new_bfd_contained_in(obfd)
92 bfd *nbfd = new_bfd();
93 nbfd->xvec = obfd->xvec;
94 nbfd->my_archive = obfd;
95 nbfd->direction = read_direction;
100 @section Opening and Closing BFDs
105 Opens the file supplied (using fopen) with the target supplied, it
106 returns a pointer to the created bfd.
108 If NULL is returned then an error has occured.
109 Possible errors are no_memory, invalid_target or system_call error.
110 *; PROTO(bfd*, bfd_openr, (CONST char *filename,CONST char*target));
114 DEFUN(bfd_openr, (filename, target),
115 CONST char *filename AND
119 bfd_target *target_vec;
123 bfd_error = no_memory;
127 target_vec = bfd_find_target (target, nbfd);
128 if (target_vec == NULL) {
129 bfd_error = invalid_target;
133 nbfd->filename = filename;
134 nbfd->direction = read_direction;
136 if (bfd_open_file (nbfd) == NULL) {
137 bfd_error = system_call_error; /* File didn't exist, or some such */
145 /* Don't try to `optimize' this function:
147 o - We lock using stack space so that interrupting the locking
148 won't cause a storage leak.
149 o - We open the file stream last, since we don't want to have to
150 close it if anything goes wrong. Closing the stream means closing
151 the file descriptor too, even though we didn't open it.
155 bfd_fdopenr is to bfd_fopenr much like fdopen is to fopen. It opens a bfd on
156 a file already described by the @var{fd} supplied.
158 Possible errors are no_memory, invalid_target and system_call error.
159 *; PROTO(bfd *, bfd_fdopenr,
160 (CONST char *filename, CONST char *target, int fd));
164 DEFUN(bfd_fdopenr,(filename, target, fd),
165 CONST char *filename AND
166 CONST char *target AND
170 bfd_target *target_vec;
173 struct flock lock, *lockp = &lock;
176 bfd_error = system_call_error;
178 fdflags = fcntl (fd, F_GETFL, NULL);
179 if (fdflags == -1) return NULL;
182 lockp->l_type = F_RDLCK;
183 if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
189 bfd_error = no_memory;
193 target_vec = bfd_find_target (target, nbfd);
194 if (target_vec == NULL) {
195 bfd_error = invalid_target;
200 nbfd->lock = (struct flock *) (nbfd + 1);
202 /* if the fd were open for read only, this still would not hurt: */
203 nbfd->iostream = (char *) fdopen (fd, "r+");
204 if (nbfd->iostream == NULL) {
205 (void) obstack_free (&nbfd->memory, (PTR)0);
209 /* OK, put everything where it belongs */
211 nbfd->filename = filename;
213 /* As a special case we allow a FD open for read/write to
214 be written through, although doing so requires that we end
215 the previous clause with a preposition. */
216 switch (fdflags & O_ACCMODE) {
217 case O_RDONLY: nbfd->direction = read_direction; break;
218 case O_WRONLY: nbfd->direction = write_direction; break;
219 case O_RDWR: nbfd->direction = both_direction; break;
224 memcpy (nbfd->lock, lockp, sizeof (struct flock))
227 bfd_cache_init (nbfd);
232 /** bfd_openw -- open for writing.
233 Returns a pointer to a freshly-allocated bfd on success, or NULL.
235 See comment by bfd_fdopenr before you try to modify this function. */
238 Creates a bfd, associated with file @var{filename}, using the file
239 format @var{target}, and returns a pointer to it.
241 Possible errors are system_call_error, no_memory, invalid_target.
242 *; PROTO(bfd *, bfd_openw, (CONST char *filename, CONST char *target));
246 DEFUN(bfd_openw,(filename, target),
247 CONST char *filename AND
251 bfd_target *target_vec;
253 bfd_error = system_call_error;
255 /* nbfd has to point to head of malloc'ed block so that bfd_close may
256 reclaim it correctly. */
260 bfd_error = no_memory;
264 target_vec = bfd_find_target (target, nbfd);
265 if (target_vec == NULL) return NULL;
267 nbfd->filename = filename;
268 nbfd->direction = write_direction;
270 if (bfd_open_file (nbfd) == NULL) {
271 bfd_error = system_call_error; /* File not writeable, etc */
272 (void) obstack_free (&nbfd->memory, (PTR)0);
279 This function closes a bfd. If the bfd was open for writing, then
280 pending operations are completed and the file written out and closed.
281 If the created file is executable, then @code{chmod} is called to mark
284 All memory attatched to the bfd's obstacks is released.
286 @code{true} is returned if all is ok, otherwise @code{false}.
287 *; PROTO(boolean, bfd_close,(bfd *));
291 DEFUN(bfd_close,(abfd),
294 if (!bfd_read_p(abfd))
295 if (BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)) != true)
298 if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
300 bfd_cache_close(abfd);
302 /* If the file was open for writing and is now executable,
304 if (abfd->direction == write_direction
305 && abfd->flags & EXEC_P) {
307 stat(abfd->filename, &buf);
309 #define S_IXUSR 0100 /* Execute by owner. */
312 #define S_IXGRP 0010 /* Execute by group. */
315 #define S_IXOTH 0001 /* Execute by others. */
318 chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
320 (void) obstack_free (&abfd->memory, (PTR)0);
321 /* FIXME, shouldn't we de-allocate the bfd as well? */
326 This routine creates a new bfd in the manner of bfd_openw, but without
327 opening a file. The new bfd takes the target from the target used by
328 @var{template}. The format is always set to @code{bfd_object}.
330 *; PROTO(bfd *, bfd_create, (CONST char *filename, bfd *template));
334 DEFUN(bfd_create,(filename, template),
335 CONST char *filename AND
338 bfd *nbfd = new_bfd();
339 if (nbfd == (bfd *)NULL) {
340 bfd_error = no_memory;
343 nbfd->filename = filename;
345 nbfd->xvec = template->xvec;
347 nbfd->direction = no_direction;
348 bfd_set_format(nbfd, bfd_object);
352 /* Memory allocation */
354 DEFUN(PTR bfd_alloc_by_size_t,(abfd, size),
358 PTR res = obstack_alloc(&(abfd->memory), size);
362 DEFUN(void bfd_alloc_grow,(abfd, ptr, size),
367 obstack_grow(&(abfd->memory), ptr, size);
369 DEFUN(PTR bfd_alloc_finish,(abfd),
372 return obstack_finish(&(abfd->memory));
375 DEFUN(PTR bfd_alloc, (abfd, size),
379 return bfd_alloc_by_size_t(abfd, (size_t)size);
382 DEFUN(PTR bfd_zalloc,(abfd, size),
386 PTR res = bfd_alloc(abfd, size);
387 memset(res, 0, (size_t)size);
391 DEFUN(PTR bfd_realloc,(abfd, old, size),
396 PTR res = bfd_alloc(abfd, size);
397 memcpy(res, old, (size_t)size);
401 /*proto* bfd_alloc_size
402 Return the number of bytes in the obstacks connected to the supplied
404 *; PROTO(bfd_size_type,bfd_alloc_size,(bfd *abfd));
408 DEFUN( bfd_alloc_size,(abfd),
411 struct _obstack_chunk *chunk = abfd->memory.chunk;
414 size += chunk->limit - &(chunk->contents[0]);