/* opncls.c -- open and close a BFD.
   Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 1997
   Free Software Foundation, Inc.

   Written by Cygnus Support.

This file is part of BFD, the Binary File Descriptor library.

This program 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 2 of the License, or
(at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#include "bfd.h"
#include "sysdep.h"
#include "objalloc.h"
#include "libbfd.h"

#ifndef S_IXUSR
#define S_IXUSR 0100	/* Execute by owner.  */
#endif
#ifndef S_IXGRP
#define S_IXGRP 0010	/* Execute by group.  */
#endif
#ifndef S_IXOTH
#define S_IXOTH 0001	/* Execute by others.  */
#endif

/* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
   if we do that we can't use fcntl.  */

/* FIXME: This is no longer used.  */
long _bfd_chunksize = -1;

/* Return a new BFD.  All BFD's are allocated through this routine.  */

bfd *
_bfd_new_bfd ()
{
  bfd *nbfd;

  nbfd = (bfd *) bfd_zmalloc (sizeof (bfd));
  if (nbfd == NULL)
    return NULL;

  nbfd->memory = (PTR) objalloc_create ();
  if (nbfd->memory == NULL)
    {
      bfd_set_error (bfd_error_no_memory);
      return NULL;
    }

  nbfd->arch_info = &bfd_default_arch_struct;

  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 = (PTR) NULL;
  nbfd->cacheable = false;
  nbfd->flags = BFD_NO_FLAGS;
  nbfd->mtime_set = false;

  return nbfd;
}

/* Allocate a new BFD as a member of archive OBFD.  */

bfd *
_bfd_new_bfd_contained_in (obfd)
     bfd *obfd;
{
  bfd *nbfd;

  nbfd = _bfd_new_bfd ();
  nbfd->xvec = obfd->xvec;
  nbfd->my_archive = obfd;
  nbfd->direction = read_direction;
  nbfd->target_defaulted = obfd->target_defaulted;
  return nbfd;
}

/*
SECTION
	Opening and closing BFDs

*/

/*
FUNCTION
	bfd_openr

SYNOPSIS
        bfd *bfd_openr(CONST char *filename, CONST char *target);

DESCRIPTION
	Open the file @var{filename} (using <<fopen>>) with the target
	@var{target}.  Return a pointer to the created BFD.

	Calls <<bfd_find_target>>, so @var{target} is interpreted as by
	that function.

	If <<NULL>> is returned then an error has occured.   Possible errors
	are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error.
*/

bfd *
bfd_openr (filename, target)
     CONST char *filename;
     CONST char *target;
{
  bfd *nbfd;
  const bfd_target *target_vec;

  nbfd = _bfd_new_bfd ();
  if (nbfd == NULL)
    return NULL;

  target_vec = bfd_find_target (target, nbfd);
  if (target_vec == NULL)
    {
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      bfd_set_error (bfd_error_invalid_target);
      return NULL;
    }

  nbfd->filename = filename;
  nbfd->direction = read_direction;

  if (bfd_open_file (nbfd) == NULL)
    {
      /* File didn't exist, or some such */
      bfd_set_error (bfd_error_system_call);
      objalloc_free ((struct objalloc *) nbfd->memory);
      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.
 */
/*
FUNCTION
         bfd_fdopenr

SYNOPSIS
         bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd);

DESCRIPTION
         <<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to <<fopen>>.
	 It opens a BFD on a file already described by the @var{fd}
	 supplied.

	 When the file is later <<bfd_close>>d, the file descriptor will be closed.

	 If the caller desires that this file descriptor be cached by BFD
	 (opened as needed, closed as needed to free descriptors for
	 other opens), with the supplied @var{fd} used as an initial
	 file descriptor (but subject to closure at any time), call
	 bfd_set_cacheable(bfd, 1) on the returned BFD.  The default is to
	 assume no cacheing; the file descriptor will remain open until
	 <<bfd_close>>, and will not be affected by BFD operations on other
	 files.

         Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
*/

bfd *
bfd_fdopenr (filename, target, fd)
     CONST char *filename;
     CONST char *target;
     int fd;
{
  bfd *nbfd;
  const bfd_target *target_vec;
  int fdflags;

  bfd_set_error (bfd_error_system_call);
#if ! defined(HAVE_FCNTL) || ! defined(F_GETFL)
  fdflags = O_RDWR;			/* Assume full access */
#else
  fdflags = fcntl (fd, F_GETFL, NULL);
#endif
  if (fdflags == -1) return NULL;

  nbfd = _bfd_new_bfd ();
  if (nbfd == NULL)
    return NULL;

  target_vec = bfd_find_target (target, nbfd);
  if (target_vec == NULL)
    {
      bfd_set_error (bfd_error_invalid_target);
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      return NULL;
    }

#ifndef HAVE_FDOPEN
  nbfd->iostream = (PTR) fopen (filename, FOPEN_RB);
#else
  /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
  switch (fdflags & (O_ACCMODE))
    {
    case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB);   break;
    case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB);  break;
    case O_RDWR:   nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB);  break;
    default: abort ();
    }
#endif

  if (nbfd->iostream == NULL)
    {
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      return NULL;
    }

  /* OK, put everything where it belongs */

  nbfd->filename = filename;

  /* 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.  */
  /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
  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 ();
    }

  if (! bfd_cache_init (nbfd))
    {
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      return NULL;
    }
  nbfd->opened_once = true;

  return nbfd;
}

/*
FUNCTION
	bfd_openstreamr

SYNOPSIS
	bfd *bfd_openstreamr(const char *, const char *, PTR);

DESCRIPTION

	Open a BFD for read access on an existing stdio stream.  When
	the BFD is passed to <<bfd_close>>, the stream will be closed.
*/

bfd *
bfd_openstreamr (filename, target, streamarg)
     const char *filename;
     const char *target;
     PTR streamarg;
{
  FILE *stream = (FILE *) streamarg;
  bfd *nbfd;
  const bfd_target *target_vec;

  nbfd = _bfd_new_bfd ();
  if (nbfd == NULL)
    return NULL;

  target_vec = bfd_find_target (target, nbfd);
  if (target_vec == NULL)
    {
      bfd_set_error (bfd_error_invalid_target);
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      return NULL;
    }

  nbfd->iostream = (PTR) stream;
  nbfd->filename = filename;
  nbfd->direction = read_direction;
				
  if (! bfd_cache_init (nbfd))
    {
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      return NULL;
    }

  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. */

/*
FUNCTION
	bfd_openw

SYNOPSIS
	bfd *bfd_openw(CONST char *filename, CONST char *target);

DESCRIPTION
	Create a BFD, associated with file @var{filename}, using the
	file format @var{target}, and return a pointer to it.

	Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
	<<bfd_error_invalid_target>>.
*/

bfd *
bfd_openw (filename, target)
     CONST char *filename;
     CONST char *target;
{
  bfd *nbfd;
  const bfd_target *target_vec;

  bfd_set_error (bfd_error_system_call);

  /* nbfd has to point to head of malloc'ed block so that bfd_close may
     reclaim it correctly. */

  nbfd = _bfd_new_bfd ();
  if (nbfd == NULL)
    return NULL;

  target_vec = bfd_find_target (target, nbfd);
  if (target_vec == NULL)
    {
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      return NULL;
    }

  nbfd->filename = filename;
  nbfd->direction = write_direction;

  if (bfd_open_file (nbfd) == NULL)
    {
      bfd_set_error (bfd_error_system_call);	/* File not writeable, etc */
      objalloc_free ((struct objalloc *) nbfd->memory);
      free (nbfd);
      return NULL;
  }

  return nbfd;
}

/*

FUNCTION
	bfd_close

SYNOPSIS
	boolean bfd_close(bfd *abfd);

DESCRIPTION

	Close a BFD. If the BFD was open for writing,
	then pending operations are completed and the file written out
	and closed. If the created file is executable, then
	<<chmod>> is called to mark it as such.

	All memory attached to the BFD is released.

	The file descriptor associated with the BFD is closed (even
	if it was passed in to BFD by <<bfd_fdopenr>>).

RETURNS
	<<true>> is returned if all is ok, otherwise <<false>>.
*/


boolean
bfd_close (abfd)
     bfd *abfd;
{
  boolean ret;

  if (!bfd_read_p (abfd))
    {
      if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
	return false;
    }

  if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
    return false;

  ret = bfd_cache_close (abfd);

  /* If the file was open for writing and is now executable,
     make it so */
  if (ret
      && abfd->direction == write_direction
      && abfd->flags & EXEC_P)
    {
      struct stat buf;

      if (stat (abfd->filename, &buf) == 0)
	{
 	  int mask = umask (0);
	  umask (mask);
	  chmod (abfd->filename,
		 (0777
		  & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
	}
    }

  objalloc_free ((struct objalloc *) abfd->memory);
  free (abfd);

  return ret;
}

/*
FUNCTION
	bfd_close_all_done

SYNOPSIS
	boolean bfd_close_all_done(bfd *);

DESCRIPTION
	Close a BFD.  Differs from <<bfd_close>>
	since it does not complete any pending operations.  This
	routine would be used if the application had just used BFD for
	swapping and didn't want to use any of the writing code.

	If the created file is executable, then <<chmod>> is called
	to mark it as such.

	All memory attached to the BFD is released.

RETURNS
	<<true>> is returned if all is ok, otherwise <<false>>.

*/

boolean
bfd_close_all_done (abfd)
     bfd *abfd;
{
  boolean ret;

  ret = bfd_cache_close (abfd);

  /* If the file was open for writing and is now executable,
     make it so */
  if (ret
      && abfd->direction == write_direction
      && abfd->flags & EXEC_P)
    {
      struct stat buf;

      if (stat (abfd->filename, &buf) == 0)
	{
	  int mask = umask (0);
	  umask (mask);
	  chmod (abfd->filename,
		 (0x777
		  & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
	}
    }

  objalloc_free ((struct objalloc *) abfd->memory);
  free (abfd);

  return ret;
}

/*
FUNCTION
	bfd_create

SYNOPSIS
	bfd *bfd_create(CONST char *filename, bfd *templ);

DESCRIPTION
	Create a new BFD in the manner of
	<<bfd_openw>>, but without opening a file. The new BFD
	takes the target from the target used by @var{template}. The
	format is always set to <<bfd_object>>.

*/

bfd *
bfd_create (filename, templ)
     CONST char *filename;
     bfd *templ;
{
  bfd *nbfd;

  nbfd = _bfd_new_bfd ();
  if (nbfd == NULL)
    return NULL;
  nbfd->filename = filename;
  if (templ)
    nbfd->xvec = templ->xvec;
  nbfd->direction = no_direction;
  bfd_set_format (nbfd, bfd_object);
  return nbfd;
}

/*
FUNCTION
	bfd_make_writable

SYNOPSIS
	boolean bfd_make_writable(bfd *abfd);

DESCRIPTION
	Takes a BFD as created by <<bfd_create>> and converts it
	into one like as returned by <<bfd_openw>>.  It does this
	by converting the BFD to BFD_IN_MEMORY.  It's assumed that
	you will call <<bfd_make_readable>> on this bfd later.

RETURNS
	<<true>> is returned if all is ok, otherwise <<false>>.
*/

boolean
bfd_make_writable(abfd)
     bfd *abfd;
{
  struct bfd_in_memory *bim;

  if (abfd->direction != no_direction)
    {
      bfd_set_error (bfd_error_invalid_operation);
      return false;
    }

  bim = (struct bfd_in_memory *) bfd_malloc (sizeof (struct bfd_in_memory));
  abfd->iostream = (PTR) bim;
  /* bfd_write will grow these as needed */
  bim->size = 0;
  bim->buffer = 0;

  abfd->flags |= BFD_IN_MEMORY;
  abfd->direction = write_direction;
  abfd->where = 0;

  return true;
}

/*
FUNCTION
	bfd_make_readable

SYNOPSIS
	boolean bfd_make_readable(bfd *abfd);

DESCRIPTION
	Takes a BFD as created by <<bfd_create>> and
	<<bfd_make_writable>> and converts it into one like as
	returned by <<bfd_openr>>.  It does this by writing the
	contents out to the memory buffer, then reversing the
	direction.

RETURNS
	<<true>> is returned if all is ok, otherwise <<false>>.  */

boolean
bfd_make_readable(abfd)
     bfd *abfd;
{
  if (abfd->direction != write_direction || !(abfd->flags & BFD_IN_MEMORY))
    {
      bfd_set_error (bfd_error_invalid_operation);
      return false;
    }

  if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
    return false;

  if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
    return false;


  abfd->arch_info = &bfd_default_arch_struct;

  abfd->where = 0;
  abfd->sections = (asection *) NULL;
  abfd->format = bfd_unknown;
  abfd->my_archive = (bfd *) NULL;
  abfd->origin = 0;				
  abfd->opened_once = false;
  abfd->output_has_begun = false;
  abfd->section_count = 0;
  abfd->usrdata = (PTR) NULL;
  abfd->cacheable = false;
  abfd->flags = BFD_IN_MEMORY;
  abfd->mtime_set = false;

  abfd->target_defaulted = true;
  abfd->direction = read_direction;
  abfd->sections = 0;
  abfd->symcount = 0;
  abfd->outsymbols = 0;
  abfd->tdata.any = 0;

  bfd_check_format(abfd, bfd_object);

  return true;
}

/*
INTERNAL_FUNCTION
	bfd_alloc

SYNOPSIS
	PTR bfd_alloc (bfd *abfd, size_t wanted);

DESCRIPTION
	Allocate a block of @var{wanted} bytes of memory attached to
	<<abfd>> and return a pointer to it.
*/


PTR
bfd_alloc (abfd, size)
     bfd *abfd;
     size_t size;
{
  PTR ret;

  ret = objalloc_alloc (abfd->memory, (unsigned long) size);
  if (ret == NULL)
    bfd_set_error (bfd_error_no_memory);
  return ret;
}

PTR
bfd_zalloc (abfd, size)
     bfd *abfd;
     size_t size;
{
  PTR res;

  res = bfd_alloc (abfd, size);
  if (res)
    memset (res, 0, size);
  return res;
}

/* Free a block allocated for a BFD.  */

void
bfd_release (abfd, block)
     bfd *abfd;
     PTR block;
{
  objalloc_free_block ((struct objalloc *) abfd->memory, block);
}
