/* Copyright (C) 2002-2021 Free Software Foundation, Inc.
   Contributed by Andy Vaught

This file is part of the GNU Fortran 95 runtime library (libgfortran).

Libgfortran 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 3, or (at your option)
any later version.

Libgfortran 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.

Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.

You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
<http://www.gnu.org/licenses/>.  */

#include "io.h"
#include "unix.h"
#include "async.h"
#include <limits.h>
#if !HAVE_UNLINK_OPEN_FILE
#include <string.h>
#endif

typedef enum
{ CLOSE_INVALID = - 1, CLOSE_DELETE, CLOSE_KEEP, CLOSE_UNSPECIFIED }
close_status;

static const st_option status_opt[] = {
  {"keep", CLOSE_KEEP},
  {"delete", CLOSE_DELETE},
  {NULL, 0}
};


extern void st_close (st_parameter_close *);
export_proto(st_close);

void
st_close (st_parameter_close *clp)
{
  close_status status;
  gfc_unit *u;
#if !HAVE_UNLINK_OPEN_FILE
  char *path;

  path = NULL;
#endif

  library_start (&clp->common);

  status = !(clp->common.flags & IOPARM_CLOSE_HAS_STATUS) ? CLOSE_UNSPECIFIED :
    find_option (&clp->common, clp->status, clp->status_len,
		 status_opt, "Bad STATUS parameter in CLOSE statement");

  if (status == CLOSE_INVALID)
    {
      library_end ();
      return;
    }

  u = find_unit (clp->common.unit);

  if (ASYNC_IO && u && u->au)
    if (async_wait (&(clp->common), u->au))
      {
	library_end ();
	return;
      }

  if ((clp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
  {
    library_end ();
    return;
  }

  if (u != NULL)
    {
      if (close_share (u) < 0)
	generate_error (&clp->common, LIBERROR_OS, "Problem in CLOSE");
      if (u->flags.status == STATUS_SCRATCH)
	{
	  if (status == CLOSE_KEEP)
	    generate_error (&clp->common, LIBERROR_BAD_OPTION,
			    "Can't KEEP a scratch file on CLOSE");
#if !HAVE_UNLINK_OPEN_FILE
	  path = strdup (u->filename);
#endif
	}
      else
	{
	  if (status == CLOSE_DELETE)
	    {
	      if (u->flags.readonly)
		generate_warning (&clp->common, "STATUS set to DELETE on CLOSE"
				  " but file protected by READONLY specifier");
	      else
		{
#if HAVE_UNLINK_OPEN_FILE

		  if (remove (u->filename))
		    generate_error (&clp->common, LIBERROR_OS,
				    "File cannot be deleted");
#else
		  path = strdup (u->filename);
#endif
		}
	    }
	}

      close_unit (u);

#if !HAVE_UNLINK_OPEN_FILE
      if (path != NULL)
	{
	  if (remove (path))
	    generate_error (&clp->common, LIBERROR_OS,
			    "File cannot be deleted");
	  free (path);
	}
#endif
    }

  /* CLOSE on unconnected unit is legal and a no-op: F95 std., 9.3.5. */ 
  library_end ();
}
