aboutsummaryrefslogtreecommitdiff
path: root/bfd/opncls.c
diff options
context:
space:
mode:
authorDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:11:25 +0000
committerDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:11:25 +0000
commit4a81b56152631cda9dc351cb4d2f61f395ee4414 (patch)
tree562bc9b14bcf414b6c301b769d4ce528c51d4703 /bfd/opncls.c
parent907621824e31daf6504860009535f03676afee4d (diff)
downloadgdb-4a81b56152631cda9dc351cb4d2f61f395ee4414.zip
gdb-4a81b56152631cda9dc351cb4d2f61f395ee4414.tar.gz
gdb-4a81b56152631cda9dc351cb4d2f61f395ee4414.tar.bz2
Initial revision
Diffstat (limited to 'bfd/opncls.c')
-rw-r--r--bfd/opncls.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/bfd/opncls.c b/bfd/opncls.c
new file mode 100644
index 0000000..63e9c51
--- /dev/null
+++ b/bfd/opncls.c
@@ -0,0 +1,281 @@
+/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Diddler.
+
+BFD is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+BFD is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with BFD; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* $Id$ */
+
+/*** opncls.c -- open and close a bfd. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+
+extern void bfd_cache_init();
+FILE *bfd_open_file();
+
+/* fdopen is a loser -- we should use stdio exclusively. Unfortunately
+ if we do that we can't use fcntl. */
+
+/** Locking
+
+ Locking is loosely controlled by the preprocessor variable
+ BFD_LOCKS. I say loosely because Unix barely understands locking
+ -- at least in BSD it doesn't affect programs which don't
+ explicitly use it! That is to say it's practically useless, though
+ if everyone uses this library you'll be OK.
+
+ From among the many and varied lock facilities available, (none of
+ which, of course, knows about any other) we use the fcntl locks,
+ because they're Posix.
+
+ The reason that bfd_openr and bfd_fdopenr exist, yet only bfd_openw
+ exists is because of locking. When we do output, we lock the
+ filename file for output, then open a temporary file which does not
+ actually get its correct filename until closing time. This is
+ safest, but requires the asymmetry in read and write entry points.
+
+ Perhaps, since unix has so many different kinds of locking anyway,
+ we should use the emacs lock scheme?... */
+
+
+bfd *new_bfd()
+{
+ bfd *nbfd = (bfd *)zalloc(sizeof(bfd));
+
+ nbfd->direction = no_direction;
+ nbfd->iostream = NULL;
+ nbfd->where = 0;
+ nbfd->sections = (asection *)NULL;
+ nbfd->format = bfd_unknown;
+ nbfd->my_archive = (bfd *)NULL;
+ nbfd->origin = 0;
+ nbfd->opened_once = false;
+ nbfd->output_has_begun = false;
+ nbfd->section_count = 0;
+ nbfd->usrdata = (void *)NULL;
+ nbfd->sections = (asection *)NULL;
+ nbfd->cacheable = false;
+ nbfd->flags = NO_FLAGS;
+ return nbfd;
+}
+bfd *new_bfd_contained_in(obfd)
+bfd *obfd;
+{
+ bfd *nbfd = new_bfd(obfd);
+ nbfd->xvec = obfd->xvec;
+ nbfd->my_archive = obfd;
+ nbfd->direction = read_direction;
+ return nbfd;
+}
+
+/** bfd_openr, bfd_fdopenr -- open for reading.
+ Returns a pointer to a freshly-allocated bfd on success, or NULL. */
+
+bfd *
+bfd_openr (filename, target)
+ char *filename;
+ char *target;
+{
+ bfd *nbfd;
+ bfd_target *target_vec;
+
+ target_vec = bfd_find_target (target);
+ if (target_vec == NULL) {
+ bfd_error = invalid_target;
+ return NULL;
+ }
+
+ bfd_error = system_call_error;
+ nbfd = new_bfd();
+ if (nbfd == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+
+ nbfd->filename = filename;
+ nbfd->xvec = target_vec;
+ nbfd->direction = read_direction;
+
+ if (bfd_open_file (nbfd) == NULL) {
+ bfd_error = system_call_error; /* File didn't exist, or some such */
+ free (nbfd);
+ return NULL;
+ }
+ return nbfd;
+}
+
+
+/* Don't try to `optimize' this function:
+
+ o - We lock using stack space so that interrupting the locking
+ won't cause a storage leak.
+ o - We open the file stream last, since we don't want to have to
+ close it if anything goes wrong. Closing the stream means closing
+ the file descriptor too, even though we didn't open it.
+ */
+
+bfd *
+bfd_fdopenr (filename, target, fd)
+ char *filename;
+ char *target;
+ int fd;
+{
+ bfd *nbfd;
+ bfd_target *target_vec;
+ int fdflags;
+#ifdef BFD_LOCKS
+ struct flock lock, *lockp = &lock;
+#endif
+
+ target_vec = bfd_find_target (target);
+ if (target_vec == NULL) {
+ bfd_error = invalid_target;
+ return NULL;
+ }
+
+ bfd_error = system_call_error;
+
+ fdflags = fcntl (fd, F_GETFL);
+ if (fdflags == -1) return NULL;
+
+#ifdef BFD_LOCKS
+ lockp->l_type = F_RDLCK;
+ if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
+#endif
+
+ nbfd = new_bfd();
+
+ if (nbfd == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+#ifdef BFD_LOCKS
+ nbfd->lock = (struct flock *) (nbfd + 1);
+#endif
+ /* if the fd were open for read only, this still would not hurt: */
+ nbfd->iostream = (char *) fdopen (fd, "r+");
+ if (nbfd->iostream == NULL) {
+ free (nbfd);
+ return NULL;
+ }
+
+ /* OK, put everything where it belongs */
+
+ nbfd->filename = filename;
+ nbfd->xvec = target_vec;
+
+ /* As a special case we allow a FD open for read/write to
+ be written through, although doing so requires that we end
+ the previous clause with a preposition. */
+ switch (fdflags & O_ACCMODE) {
+ case O_RDONLY: nbfd->direction = read_direction; break;
+ case O_WRONLY: nbfd->direction = write_direction; break;
+ case O_RDWR: nbfd->direction = both_direction; break;
+ default: abort ();
+ }
+
+#ifdef BFD_LOCKS
+ memcpy (nbfd->lock, lockp, sizeof (struct flock))
+#endif
+
+ bfd_cache_init (nbfd);
+
+ return nbfd;
+}
+
+/** bfd_openw -- open for writing.
+ Returns a pointer to a freshly-allocated bfd on success, or NULL.
+
+ See comment by bfd_fdopenr before you try to modify this function. */
+
+bfd *
+bfd_openw (filename, target)
+ char *filename;
+ char *target;
+{
+ bfd *nbfd;
+ bfd_target *target_vec;
+
+ target_vec = bfd_find_target (target);
+ if (target_vec == NULL) return NULL;
+
+ bfd_error = system_call_error;
+
+ /* nbfd has to point to head of malloc'ed block so that bfd_close may
+ reclaim it correctly. */
+
+ nbfd = new_bfd();
+ if (nbfd == NULL) {
+ bfd_error = no_memory;
+ return NULL;
+ }
+
+ nbfd->filename = filename;
+ nbfd->xvec = target_vec;
+ nbfd->direction = write_direction;
+
+ if (bfd_open_file (nbfd) == NULL) {
+ bfd_error = system_call_error; /* File not writeable, etc */
+ free (nbfd);
+ return NULL;
+ }
+ return nbfd;
+}
+
+
+
+/** Close up shop, get your deposit back. */
+boolean
+bfd_close (abfd)
+ bfd *abfd;
+{
+ if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
+
+ bfd_cache_close(abfd);
+/* If the file was open for writing and is now executable
+ make it so */
+ if (abfd->direction == write_direction
+ && abfd->flags & EXEC_P) {
+ struct stat buf;
+ stat(abfd->filename, &buf);
+ chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
+ }
+ free (abfd);
+ return true;
+}
+/*
+ called to create a bfd with no ascociated file or target
+ */
+bfd *
+bfd_create(filename, template)
+char *filename;
+bfd *template;
+{
+ bfd *nbfd = new_bfd();
+ if (nbfd == (bfd *)NULL) {
+ bfd_error = no_memory;
+ return (bfd *)NULL;
+ }
+ nbfd->filename = filename;
+ nbfd->xvec = template->xvec;
+ nbfd->direction = no_direction;
+ return nbfd;
+
+
+
+}