Blame support/temp_file.c

Packit 6c4009
/* Temporary file handling for tests.
Packit 6c4009
   Copyright (C) 1998-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* This is required to get an mkstemp which can create large files on
Packit 6c4009
   some 32-bit platforms. */
Packit 6c4009
#define _FILE_OFFSET_BITS 64
Packit 6c4009
Packit 6c4009
#include <support/temp_file.h>
Packit 6c4009
#include <support/temp_file-internal.h>
Packit 6c4009
#include <support/support.h>
Packit 6c4009
Packit 6c4009
#include <paths.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
Packit 6c4009
/* List of temporary files.  */
Packit 6c4009
static struct temp_name_list
Packit 6c4009
{
Packit 6c4009
  struct temp_name_list *next;
Packit 6c4009
  char *name;
Packit 6c4009
  pid_t owner;
Packit 6c4009
} *temp_name_list;
Packit 6c4009
Packit 6c4009
/* Location of the temporary files.  Set by the test skeleton via
Packit 6c4009
   support_set_test_dir.  The string is not be freed.  */
Packit 6c4009
static const char *test_dir = _PATH_TMP;
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
add_temp_file (const char *name)
Packit 6c4009
{
Packit 6c4009
  struct temp_name_list *newp
Packit 6c4009
    = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
Packit 6c4009
  char *newname = strdup (name);
Packit 6c4009
  if (newname != NULL)
Packit 6c4009
    {
Packit 6c4009
      newp->name = newname;
Packit 6c4009
      newp->next = temp_name_list;
Packit 6c4009
      newp->owner = getpid ();
Packit 6c4009
      temp_name_list = newp;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    free (newp);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
int
Packit 6c4009
create_temp_file (const char *base, char **filename)
Packit 6c4009
{
Packit 6c4009
  char *fname;
Packit 6c4009
  int fd;
Packit 6c4009
Packit 6c4009
  fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base)
Packit 6c4009
			    + sizeof ("XXXXXX"));
Packit 6c4009
  strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX");
Packit 6c4009
Packit 6c4009
  fd = mkstemp (fname);
Packit 6c4009
  if (fd == -1)
Packit 6c4009
    {
Packit 6c4009
      printf ("cannot open temporary file '%s': %m\n", fname);
Packit 6c4009
      free (fname);
Packit 6c4009
      return -1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  add_temp_file (fname);
Packit 6c4009
  if (filename != NULL)
Packit 6c4009
    *filename = fname;
Packit 6c4009
  else
Packit 6c4009
    free (fname);
Packit 6c4009
Packit 6c4009
  return fd;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
char *
Packit 6c4009
support_create_temp_directory (const char *base)
Packit 6c4009
{
Packit 6c4009
  char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
Packit 6c4009
  if (mkdtemp (path) == NULL)
Packit 6c4009
    {
Packit 6c4009
      printf ("error: mkdtemp (\"%s\"): %m", path);
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
  add_temp_file (path);
Packit 6c4009
  return path;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Helper functions called by the test skeleton follow.  */
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
support_set_test_dir (const char *path)
Packit 6c4009
{
Packit 6c4009
  test_dir = path;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
support_delete_temp_files (void)
Packit 6c4009
{
Packit 6c4009
  pid_t pid = getpid ();
Packit 6c4009
  while (temp_name_list != NULL)
Packit 6c4009
    {
Packit 6c4009
      /* Only perform the removal if the path was registed in the same
Packit 6c4009
	 process, as identified by the PID.  (This assumes that the
Packit 6c4009
	 parent process which registered the temporary file sticks
Packit 6c4009
	 around, to prevent PID reuse.)  */
Packit 6c4009
      if (temp_name_list->owner == pid)
Packit 6c4009
	{
Packit 6c4009
	  if (remove (temp_name_list->name) != 0)
Packit 6c4009
	    printf ("warning: could not remove temporary file: %s: %m\n",
Packit 6c4009
		    temp_name_list->name);
Packit 6c4009
	}
Packit 6c4009
      free (temp_name_list->name);
Packit 6c4009
Packit 6c4009
      struct temp_name_list *next = temp_name_list->next;
Packit 6c4009
      free (temp_name_list);
Packit 6c4009
      temp_name_list = next;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
support_print_temp_files (FILE *f)
Packit 6c4009
{
Packit 6c4009
  if (temp_name_list != NULL)
Packit 6c4009
    {
Packit 6c4009
      struct temp_name_list *n;
Packit 6c4009
      fprintf (f, "temp_files=(\n");
Packit 6c4009
      for (n = temp_name_list; n != NULL; n = n->next)
Packit 6c4009
        fprintf (f, "  '%s'\n", n->name);
Packit 6c4009
      fprintf (f, ")\n");
Packit 6c4009
    }
Packit 6c4009
}