about summary refs log tree commit diff
path: root/sysdeps/posix/tempname.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/posix/tempname.c')
-rw-r--r--sysdeps/posix/tempname.c90
1 files changed, 41 insertions, 49 deletions
diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c
index 3aa11b044b..b3d4ae7b66 100644
--- a/sysdeps/posix/tempname.c
+++ b/sysdeps/posix/tempname.c
@@ -180,25 +180,22 @@ static const char letters[] =
    The name constructed does not exist at the time of the call to
    __gen_tempname.  TMPL is overwritten with the result.
 
-   KIND may be one of:
-   __GT_NOCREATE:	simply verify that the name does not exist
-			at the time of the call.
-   __GT_FILE:		create the file using open(O_CREAT|O_EXCL)
-			and return a read-write fd.  The file is mode 0600.
-   __GT_DIR:		create a directory, which will be mode 0700.
+   The *TRY_NAME function is called repeatedly on candidate names until
+   it returns >= 0.  If it returns -2, the next candidate name is tried.
+   If it returns -1 (with errno set), __gen_tempname fails immediately.
 
    We use a clever algorithm to get hard-to-predict names. */
 int
-__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
+__gen_tempname (char *tmpl, int suffixlen,
+                int (*try_name) (const char *name, void *arg),
+                void *try_name_arg)
 {
   int len;
   char *XXXXXX;
   static uint64_t value;
   uint64_t random_time_bits;
   unsigned int count;
-  int fd = -1;
   int save_errno = errno;
-  struct_stat64 st;
 
   /* A lower bound on the number of temporary files to attempt to
      generate.  The maximum total number of temporary file names that
@@ -255,51 +252,46 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
       v /= 62;
       XXXXXX[5] = letters[v % 62];
 
-      switch (kind)
-	{
-	case __GT_FILE:
-	  fd = __open (tmpl,
-		       (flags & ~O_ACCMODE)
-		       | O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
-	  break;
-
-	case __GT_DIR:
-	  fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR);
-	  break;
-
-	case __GT_NOCREATE:
-	  /* This case is backward from the other three.  __gen_tempname
-	     succeeds if __xstat fails because the name does not exist.
-	     Note the continue to bypass the common logic at the bottom
-	     of the loop.  */
-	  if (__lxstat64 (_STAT_VER, tmpl, &st) < 0)
-	    {
-	      if (errno == ENOENT)
-		{
-		  __set_errno (save_errno);
-		  return 0;
-		}
-	      else
-		/* Give up now. */
-		return -1;
-	    }
-	  continue;
-
-	default:
-	  assert (! "invalid KIND in __gen_tempname");
-	  abort ();
-	}
-
-      if (fd >= 0)
-	{
-	  __set_errno (save_errno);
+      int fd = (*try_name) (tmpl, try_name_arg);
+      if (fd != -2)
+        {
+          if (fd >= 0)
+            __set_errno (save_errno);
 	  return fd;
 	}
-      else if (errno != EEXIST)
-	return -1;
     }
 
   /* We got out of the loop because we ran out of combinations to try.  */
   __set_errno (EEXIST);
   return -1;
 }
+
+
+int
+__gen_tempname_try_nocreate (const char *name, void *arg)
+{
+  struct stat64 st;
+  if (__lxstat64 (_STAT_VER, name, &st) == 0)
+    /* This name exists.  Try another.  */
+    return -2;
+  return 0;
+}
+
+
+/* ARG is int[2] of {flags, mode}.  */
+int
+__gen_tempname_try_file (const char *name, void *arg)
+{
+  const int *args = arg;
+  int flags = args[0];
+  mode_t mode = args[1];
+
+  int fd = __open (name,
+                   (flags & ~O_ACCMODE) | O_RDWR | O_CREAT | O_EXCL,
+                   mode);
+  if (fd < 0 && errno == EEXIST)
+    /* Nothing funny went wrong, it just already exists.  Keep looking.  */
+    fd = -2;
+
+  return fd;
+}