about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--dirent/tst-scandir.c1
-rw-r--r--posix/tst-exec.c50
-rw-r--r--posix/tst-pathconf.c6
-rw-r--r--posix/tst-spawn.c74
-rw-r--r--posix/tst-vfork3.c3
-rw-r--r--support/temp_file.c18
7 files changed, 81 insertions, 93 deletions
diff --git a/ChangeLog b/ChangeLog
index 603587bc80..e47da2a7c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,27 @@
 2017-05-08  Florian Weimer  <fweimer@redhat.com>
 
+	Prevent multiple deletion of temporary files.
+	* support/temp_file.c (struct temp_name_list): Add owner member.
+	(add_temp_file): Record owner.
+	(support_delete_temp_files): Delete file only if owner matches.
+	* posix/tst-exec.c (temp_fd1, temp_fd2): Define.
+	(do_prepare): Use create_temp_file instead of add_temp_file.
+	Initialize temp_fd1, temp_fd2.
+	(do_test): Use global temp_fd1, temp_fd2 variables.  Let the test
+	framework remove the temporary files.
+	* posix/tst-exec.c (temp_fd1, temp_fd2, temp_fd3): Define.
+	(do_prepare): Use create_temp_file instead of add_temp_file.
+	Initialize temp_fd1, temp_fd2, temp_fd3.
+	(do_test): Use global temp_fd1, temp_fd2, temp_fd3 variables.  Let
+	the test framework remove the temporary files.
+	* posix/tst-vfork3.c (do_prepare): Adjust for LIFO order of file
+	deletion.
+	* posix/tst-pathconf.c (do_test): Do not call rmdir on the
+	temporary directory.  It is removed by the test framework.
+	* dirent/tst-scandir.c (do_test): Likewise.
+
+2017-05-08  Florian Weimer  <fweimer@redhat.com>
+
 	Delete temporary files in LIFO order.
 	* support/temp_file.c (struct temp_name_list): Replace q member
 	with next.
diff --git a/dirent/tst-scandir.c b/dirent/tst-scandir.c
index 09d19ab4e4..4ecfd7b932 100644
--- a/dirent/tst-scandir.c
+++ b/dirent/tst-scandir.c
@@ -293,7 +293,6 @@ do_test (void)
   remove_file (scandir_test_dir, "aa");
   remove_file (scandir_test_dir, "b");
   remove_file (scandir_test_dir, "a");
-  rmdir (scandir_test_dir);
 
   return 0;
 }
diff --git a/posix/tst-exec.c b/posix/tst-exec.c
index be0114e1f9..12a0f57114 100644
--- a/posix/tst-exec.c
+++ b/posix/tst-exec.c
@@ -47,6 +47,10 @@ extern int do_test (int argc, char *argv[]);
 static char *name1;
 static char *name2;
 
+/* File descriptors for these temporary files.  */
+static int temp_fd1 = -1;
+static int temp_fd2 = -1;
+
 /* The contents of our files.  */
 static const char fd1string[] = "This file should get closed";
 static const char fd2string[] = "This file should stay opened";
@@ -56,18 +60,14 @@ static const char fd2string[] = "This file should stay opened";
 void
 do_prepare (int argc, char *argv[])
 {
-   size_t name_len;
-
-   name_len = strlen (test_dir);
-   name1 = xmalloc (name_len + sizeof ("/execXXXXXX"));
-   mempcpy (mempcpy (name1, test_dir, name_len),
-	    "/execXXXXXX", sizeof ("/execXXXXXX"));
-   add_temp_file (name1);
-
-   name2 = xmalloc (name_len + sizeof ("/execXXXXXX"));
-   mempcpy (mempcpy (name2, test_dir, name_len),
-	    "/execXXXXXX", sizeof ("/execXXXXXX"));
-   add_temp_file (name2);
+  /* We must not open any files in the restart case.  */
+  if (restart)
+    return;
+
+  temp_fd1 = create_temp_file ("exec", &name1);
+  temp_fd2 = create_temp_file ("exec", &name2);
+  if (temp_fd1 < 0 || temp_fd2 < 0)
+    exit (1);
 }
 
 
@@ -120,8 +120,6 @@ int
 do_test (int argc, char *argv[])
 {
   pid_t pid;
-  int fd1;
-  int fd2;
   int flags;
   int status;
 
@@ -151,26 +149,18 @@ do_test (int argc, char *argv[])
   /* Prepare the test.  We are creating two files: one which file descriptor
      will be marked with FD_CLOEXEC, another which is not.  */
 
-   /* Open our test files.   */
-   fd1 = mkstemp (name1);
-   if (fd1 == -1)
-     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name1);
-   fd2 = mkstemp (name2);
-   if (fd2 == -1)
-     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name2);
-
    /* Set the bit.  */
-   flags = fcntl (fd1, F_GETFD, 0);
+   flags = fcntl (temp_fd1, F_GETFD, 0);
    if (flags < 0)
      error (EXIT_FAILURE, errno, "cannot get flags");
    flags |= FD_CLOEXEC;
-   if (fcntl (fd1, F_SETFD, flags) < 0)
+   if (fcntl (temp_fd1, F_SETFD, flags) < 0)
      error (EXIT_FAILURE, errno, "cannot set flags");
 
    /* Write something in the files.  */
-   if (write (fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
+   if (write (temp_fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
      error (EXIT_FAILURE, errno, "cannot write to first file");
-   if (write (fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
+   if (write (temp_fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
      error (EXIT_FAILURE, errno, "cannot write to second file");
 
   /* We want to test the `exec' function.  To do this we restart the program
@@ -181,8 +171,8 @@ do_test (int argc, char *argv[])
       char fd1name[18];
       char fd2name[18];
 
-      snprintf (fd1name, sizeof fd1name, "%d", fd1);
-      snprintf (fd2name, sizeof fd2name, "%d", fd2);
+      snprintf (fd1name, sizeof fd1name, "%d", temp_fd1);
+      snprintf (fd2name, sizeof fd2name, "%d", temp_fd2);
 
       /* This is the child.  Construct the command line.  */
       if (argc == 5)
@@ -205,9 +195,5 @@ do_test (int argc, char *argv[])
     error (EXIT_FAILURE, 0, "Child terminated incorrectly");
   status = WEXITSTATUS (status);
 
-  /* Remove the test files.  */
-  unlink (name1);
-  unlink (name2);
-
   return status;
 }
diff --git a/posix/tst-pathconf.c b/posix/tst-pathconf.c
index cce59e6d47..88df792ab3 100644
--- a/posix/tst-pathconf.c
+++ b/posix/tst-pathconf.c
@@ -162,11 +162,5 @@ out_nofifo:
       ret = 1;
     }
 
-  if (rmdir (dirbuf) != 0)
-    {
-      printf ("Could not remove directory (%s)\n", strerror (errno));
-      ret = 1;
-    }
-
   return ret;
 }
diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c
index 2f960ba223..08d92bd7a7 100644
--- a/posix/tst-spawn.c
+++ b/posix/tst-spawn.c
@@ -50,6 +50,11 @@ static char *name1;
 static char *name2;
 static char *name3;
 
+/* Descriptors for the temporary files.  */
+static int temp_fd1 = -1;
+static int temp_fd2 = -1;
+static int temp_fd3 = -1;
+
 /* The contents of our files.  */
 static const char fd1string[] = "This file should get closed";
 static const char fd2string[] = "This file should stay opened";
@@ -60,23 +65,15 @@ static const char fd3string[] = "This file will be opened";
 void
 do_prepare (int argc, char *argv[])
 {
-   size_t name_len;
-
-   name_len = strlen (test_dir);
-   name1 = (char *) xmalloc (name_len + sizeof ("/spawnXXXXXX"));
-   mempcpy (mempcpy (name1, test_dir, name_len),
-	    "/spawnXXXXXX", sizeof ("/spawnXXXXXX"));
-   add_temp_file (name1);
-
-   name2 = (char *) xmalloc (name_len + sizeof ("/spawnXXXXXX"));
-   mempcpy (mempcpy (name2, test_dir, name_len),
-	    "/spawnXXXXXX", sizeof ("/spawnXXXXXX"));
-   add_temp_file (name2);
-
-   name3 = (char *) xmalloc (name_len + sizeof ("/spawnXXXXXX"));
-   mempcpy (mempcpy (name3, test_dir, name_len),
-	    "/spawnXXXXXX", sizeof ("/spawnXXXXXX"));
-   add_temp_file (name3);
+  /* We must not open any files in the restart case.  */
+  if (restart)
+    return;
+
+  temp_fd1 = create_temp_file ("spawn", &name1);
+  temp_fd2 = create_temp_file ("spawn", &name2);
+  temp_fd3 = create_temp_file ("spawn", &name3);
+  if (temp_fd1 < 0 || temp_fd2 < 0 || temp_fd3 < 0)
+    exit (1);
 }
 
 
@@ -158,9 +155,6 @@ int
 do_test (int argc, char *argv[])
 {
   pid_t pid;
-  int fd1;
-  int fd2;
-  int fd3;
   int fd4;
   int status;
   posix_spawn_file_actions_t actions;
@@ -194,53 +188,42 @@ do_test (int argc, char *argv[])
   /* Prepare the test.  We are creating two files: one which file descriptor
      will be marked with FD_CLOEXEC, another which is not.  */
 
-   /* Open our test files.   */
-   fd1 = mkstemp (name1);
-   if (fd1 == -1)
-     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name1);
-   fd2 = mkstemp (name2);
-   if (fd2 == -1)
-     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name2);
-   fd3 = mkstemp (name3);
-   if (fd3 == -1)
-     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name3);
-
    /* Write something in the files.  */
-   if (write (fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
+   if (write (temp_fd1, fd1string, strlen (fd1string)) != strlen (fd1string))
      error (EXIT_FAILURE, errno, "cannot write to first file");
-   if (write (fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
+   if (write (temp_fd2, fd2string, strlen (fd2string)) != strlen (fd2string))
      error (EXIT_FAILURE, errno, "cannot write to second file");
-   if (write (fd3, fd3string, strlen (fd3string)) != strlen (fd3string))
+   if (write (temp_fd3, fd3string, strlen (fd3string)) != strlen (fd3string))
      error (EXIT_FAILURE, errno, "cannot write to third file");
 
    /* Close the third file.  It'll be opened by `spawn'.  */
-   close (fd3);
+   close (temp_fd3);
 
    /* Tell `spawn' what to do.  */
    if (posix_spawn_file_actions_init (&actions) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_init");
-   /* Close `fd1'.  */
-   if (posix_spawn_file_actions_addclose (&actions, fd1) != 0)
+   /* Close `temp_fd1'.  */
+   if (posix_spawn_file_actions_addclose (&actions, temp_fd1) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addclose");
    /* We want to open the third file.  */
    name3_copy = strdup (name3);
    if (name3_copy == NULL)
      error (EXIT_FAILURE, errno, "strdup");
-   if (posix_spawn_file_actions_addopen (&actions, fd3, name3_copy,
+   if (posix_spawn_file_actions_addopen (&actions, temp_fd3, name3_copy,
 					 O_RDONLY, 0666) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addopen");
    /* Overwrite the name to check that a copy has been made.  */
    memset (name3_copy, 'X', strlen (name3_copy));
 
    /* We dup the second descriptor.  */
-   fd4 = MAX (2, MAX (fd1, MAX (fd2, fd3))) + 1;
-   if (posix_spawn_file_actions_adddup2 (&actions, fd2, fd4) != 0)
+   fd4 = MAX (2, MAX (temp_fd1, MAX (temp_fd2, temp_fd3))) + 1;
+   if (posix_spawn_file_actions_adddup2 (&actions, temp_fd2, fd4) != 0)
      error (EXIT_FAILURE, errno, "posix_spawn_file_actions_adddup2");
 
    /* Now spawn the process.  */
-   snprintf (fd1name, sizeof fd1name, "%d", fd1);
-   snprintf (fd2name, sizeof fd2name, "%d", fd2);
-   snprintf (fd3name, sizeof fd3name, "%d", fd3);
+   snprintf (fd1name, sizeof fd1name, "%d", temp_fd1);
+   snprintf (fd2name, sizeof fd2name, "%d", temp_fd2);
+   snprintf (fd3name, sizeof fd3name, "%d", temp_fd3);
    snprintf (fd4name, sizeof fd4name, "%d", fd4);
 
    for (i = 0; i < (argc == (restart ? 6 : 5) ? 4 : 1); i++)
@@ -274,10 +257,5 @@ do_test (int argc, char *argv[])
     error (EXIT_FAILURE, 0, "Child terminated incorrectly");
   status = WEXITSTATUS (status);
 
-  /* Remove the test files.  */
-  unlink (name1);
-  unlink (name2);
-  unlink (name3);
-
   return status;
 }
diff --git a/posix/tst-vfork3.c b/posix/tst-vfork3.c
index c104271c44..80898b3e41 100644
--- a/posix/tst-vfork3.c
+++ b/posix/tst-vfork3.c
@@ -159,11 +159,10 @@ do_prepare (void)
   strcpy (stpcpy (script1, tmpdirname), "/script1.sh");
   strcpy (stpcpy (script2, tmpdirname), "/script2.sh");
 
+  add_temp_file (tmpdirname);
   add_temp_file (script0);
   add_temp_file (script1);
   add_temp_file (script2);
-  /* Need to make sure tmpdirname is at the end of the linked list.  */
-  add_temp_file (tmpdirname);
 
   const char content0[] = "#!/bin/sh\necho empty\n";
   create_script (script0, content0, sizeof content0);
diff --git a/support/temp_file.c b/support/temp_file.c
index 50cbae606b..fdb2477ab9 100644
--- a/support/temp_file.c
+++ b/support/temp_file.c
@@ -28,12 +28,14 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 /* List of temporary files.  */
 static struct temp_name_list
 {
   struct temp_name_list *next;
   char *name;
+  pid_t owner;
 } *temp_name_list;
 
 /* Location of the temporary files.  Set by the test skeleton via
@@ -50,6 +52,7 @@ add_temp_file (const char *name)
     {
       newp->name = newname;
       newp->next = temp_name_list;
+      newp->owner = getpid ();
       temp_name_list = newp;
     }
   else
@@ -94,12 +97,19 @@ support_set_test_dir (const char *path)
 void
 support_delete_temp_files (void)
 {
+  pid_t pid = getpid ();
   while (temp_name_list != NULL)
     {
-      /* For some tests, the temporary file removal runs multiple
-	 times (in the parent processes and the subprocess), so do not
-	 report a failed removal attempt.  */
-      (void) remove (temp_name_list->name);
+      /* Only perform the removal if the path was registed in the same
+	 process, as identified by the PID.  (This assumes that the
+	 parent process which registered the temporary file sticks
+	 around, to prevent PID reuse.)  */
+      if (temp_name_list->owner == pid)
+	{
+	  if (remove (temp_name_list->name) != 0)
+	    printf ("warning: could not remove temporary file: %s: %m\n",
+		    temp_name_list->name);
+	}
       free (temp_name_list->name);
 
       struct temp_name_list *next = temp_name_list->next;