]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Generalize __gen_tempname.
authorRoland McGrath <roland@hack.frob.com>
Mon, 24 Nov 2014 19:30:36 +0000 (11:30 -0800)
committerRoland McGrath <roland@hack.frob.com>
Tue, 25 Nov 2014 00:18:17 +0000 (16:18 -0800)
19 files changed:
ChangeLog
include/stdio.h
libio/oldtmpfile.c
misc/mkdtemp.c
misc/mkostemp.c
misc/mkostemp64.c
misc/mkostemps.c
misc/mkostemps64.c
misc/mkstemp.c
misc/mkstemp64.c
misc/mkstemps.c
misc/mkstemps64.c
misc/mktemp.c
stdio-common/tempnam.c
stdio-common/tempname.c
stdio-common/tmpfile.c
stdio-common/tmpnam.c
stdio-common/tmpnam_r.c
sysdeps/posix/tempname.c

index dac4ad15de7c6f261dec5b76785137996c0d6a7d..e37e0f487a4e92cf90298335c8f8c377ade2dca3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2014-11-24  Roland McGrath  <roland@hack.frob.com>
+
+       * sysdeps/posix/tempname.c (__gen_tempname): Instead of FLAGS and KIND
+       arguments, take a function pointer TRY_NAME and void *TRY_NAME_ARG.
+       Call that *TRY_NAME to try a candidate name.
+       (__gen_tempname_try_nocreate, __gen_tempname_try_file): New functions.
+       * stdio-common/tempname.c (__gen_tempname): Update signature.
+       * include/stdio.h: Update decl.
+       (__GT_FILE, __GT_NOCREATE, __GT_DIR): Macros removed.
+       (__GT_FILE_DEFAULTS): New macro.
+       * stdio-common/tmpnam.c: Update caller.
+       * stdio-common/tmpnam_r.c: Likewise.
+       * stdio-common/tmpfile.c: Likewise.
+       * misc/mktemp.c (__mktemp): Prototypify.  Update caller.
+       * libio/oldtmpfile.c (__old_tmpfile): Update caller.
+       * misc/mkostemp.c: Prototypify.  Update caller.
+       * misc/mkstemp.c: Likewise.
+       * misc/mkostemps.c: Likewise.
+       * misc/mkstemp64.c: Likewise.
+       * misc/mkdtemp.c (try_mkdir): New function.
+       (mkdtemp): Use it with new __gen_tempname signature.  Prototypify.
+       * misc/mkostemp.c: Prototypify.  Just call mkostemps.
+       * misc/mkstemps.c: Likewise.
+       * misc/mkstemps64.c: Likewise.
+       * misc/mkostemp64.c: Prototypify.
+       Just call mkostemp with modified flags.
+       * misc/mkostemps64.c: Prototypify.
+       Just call mkostemps with modified flags.
+
 2014-11-24  Ryan Cumming  <etaoins@gmail.com>
 
        [BZ #17608]
index 00106079499ffd4fbd32da0fb50d9521b2eb798c..327c7525a146013a87e896f917653b6c2bf8b38b 100644 (file)
@@ -82,12 +82,22 @@ extern int __path_search (char *__tmpl, size_t __tmpl_len,
                          const char *__dir, const char *__pfx,
                          int __try_tempdir);
 
-extern int __gen_tempname (char *__tmpl, int __suffixlen, int __flags,
-                          int __kind);
-/* The __kind argument to __gen_tempname may be one of: */
-#  define __GT_FILE    0       /* create a file */
-#  define __GT_DIR     1       /* create a directory */
-#  define __GT_NOCREATE        2       /* just find a name not currently in use */
+/* 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.  */
+extern int __gen_tempname (char *__tmpl, int __suffixlen,
+                           int (*__try_name) (const char *__name, void *__arg),
+                           void *__try_name_arg);
+
+/* These are the common TRY_NAME functions.  */
+
+/* ARG is ignored.  */
+extern int __gen_tempname_try_nocreate (const char *__name, void *__arg);
+
+/* ARG is int[2] of {flags, mode}.  */
+extern int __gen_tempname_try_file (const char *__name, void *__arg);
+#define __GT_FILE_DEFAULTS     (&((int[2]) { 0, 0600 }))
+
 
 /* Print out MESSAGE on the error output and abort.  */
 extern void __libc_fatal (const char *__message)
index a6a5e71ae579ac1e296bd0c1aae4aa89f7c2abd2..3c3af9c3ad6ef9ba892570f8f7ce70ca7af4cc24 100644 (file)
@@ -37,7 +37,9 @@ __old_tmpfile (void)
 
   if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0))
     return NULL;
-  fd = __gen_tempname (buf, 0, 0, __GT_FILE);
+
+  int flags_and_mode[2] = { 0, 0 };
+  fd = __gen_tempname (buf, 0, &__gen_tempname_try_file, __GT_FILE_DEFAULTS);
   if (fd < 0)
     return NULL;
 
index 6bd72cab49f8b15320cdb7fb8788faee71506d39..302d2730f89a831a649eea7b4c27d4aa127d789c 100644 (file)
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/stat.h>
+
+
+static int
+try_mkdir (const char *name, void *arg __attribute__ ((unused)))
+{
+  int result = __mkdir (name, S_IRUSR | S_IWUSR | S_IXUSR);
+  if (result < 0 && errno == EEXIST)
+    /* Nothing funny went wrong, it just already exists.  Keep looking.  */
+    result = -2;
+  return result;
+}
 
 /* Generate a unique temporary directory from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
    The directory is created, mode 700, and its name is returned.
    (This function comes from OpenBSD.) */
 char *
-mkdtemp (template)
-     char *template;
+mkdtemp (char *template)
 {
-  if (__gen_tempname (template, 0, 0, __GT_DIR))
+  if (__gen_tempname (template, 0, &try_mkdir, NULL))
     return NULL;
   else
     return template;
index f0dc3c1b0d08f98c5f43090829bcab3e3593b203..695e87a95e8ac73863755335205582a4e5c35d63 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
-
-#ifndef __GT_FILE
-# define __GT_FILE 0
-#endif
+#include <sys/stat.h>
 
 /* Generate a unique temporary file name from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
    they are replaced with a string that makes the filename unique.
    Then open the file and return a fd. */
 int
-mkostemp (template, flags)
-     char *template;
-     int flags;
+mkostemp (char *template, int flags)
 {
-  return __gen_tempname (template, 0, flags, __GT_FILE);
+  return mkostemps (template, 0, flags);
 }
 
 #if !defined O_LARGEFILE || O_LARGEFILE == 0
index c68e03dff5c52abe30a55e4d1d3f8ffac46f03a7..a7bf00d9ef2cee94e99443af8c4cfc77de2000bc 100644 (file)
    they are replaced with a string that makes the filename unique.
    Then open the file and return a fd. */
 int
-mkostemp64 (template, flags)
-     char *template;
-     int flags;
+mkostemp64 (char *template, int flags)
 {
-  return __gen_tempname (template, 0, flags | O_LARGEFILE, __GT_FILE);
+  return mkostemp (template, flags | O_LARGEFILE);
 }
 
 #endif
index 2f9745ce14f783daed3f0558fe93afffb79caebe..330ff6c53da0f4f230f7842a2a4b7e96a1ce6820 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
-#ifndef __GT_FILE
-# define __GT_FILE 0
-#endif
-
 /* Generate a unique temporary file name from TEMPLATE.  The last six
    characters before a suffix of length SUFFIXLEN of TEMPLATE must be
    "XXXXXX"; they are replaced with a string that makes the filename
    unique.  Then open the file and return a fd. */
 int
-mkostemps (template, suffixlen, flags)
-     char *template;
-     int suffixlen;
-     int flags;
+mkostemps (char *template, int suffixlen, int flags)
 {
   if (suffixlen < 0)
     {
@@ -39,7 +32,8 @@ mkostemps (template, suffixlen, flags)
       return -1;
     }
 
-  return __gen_tempname (template, suffixlen, flags, __GT_FILE);
+  return __gen_tempname (template, suffixlen, &__gen_tempname_try_file,
+                         &((int[2]) { flags, S_IRUSR | S_IWUSR }));
 }
 
 #if !defined O_LARGEFILE || O_LARGEFILE == 0
index 1d1d3faf2f582a2fb2e852a5ba3d16e3f2f3d468..971afc22e91820b38e7adc90c854bb35efa24266 100644 (file)
    "XXXXXX"; they are replaced with a string that makes the filename
    unique.  Then open the file and return a fd. */
 int
-mkostemps64 (template, suffixlen, flags)
-     char *template;
-     int suffixlen;
-     int flags;
+mkostemps64 (char *template, int suffixlen, int flags)
 {
-  if (suffixlen < 0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  return __gen_tempname (template, suffixlen, flags | O_LARGEFILE, __GT_FILE);
+  return mkostemps (template, sufflixen, flags | O_LARGEFILE);
 }
 
 #endif
index a01095b3b7375e688259126ab565f42ccc9370ab..86579248063f64d46dd07f32e947d5992a9c28c8 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
-#ifndef __GT_FILE
-# define __GT_FILE 0
-#endif
-
 /* Generate a unique temporary file name from TEMPLATE.
    The last six characters of TEMPLATE must be "XXXXXX";
    they are replaced with a string that makes the filename unique.
    Then open the file and return a fd. */
 int
-mkstemp (template)
-     char *template;
+mkstemp (char *template)
 {
-  return __gen_tempname (template, 0, 0, __GT_FILE);
+  return __gen_tempname (template, 0,
+                         &__gen_tempname_try_file, __GT_FILE_DEFAULTS);
 }
 
 #if !defined O_LARGEFILE || O_LARGEFILE == 0
index 3ca465722f1a6eff66c9bb97bf1239889c7117a2..e15c7d6ad36d7a7779ecde5643eb51005e753987 100644 (file)
    they are replaced with a string that makes the filename unique.
    Then open the file and return a fd. */
 int
-mkstemp64 (template)
-     char *template;
+mkstemp64 (char *template)
 {
-  return __gen_tempname (template, 0, O_LARGEFILE, __GT_FILE);
+  return __gen_tempname (template, 0, &__gen_tempname_try_file,
+                         (&((int[2]) { O_LARGEFILE, 0600 })));
 }
 
 #endif
index d58fce36da436c658c2475f10c6791b56d80c5ad..3f2c01e488f2f7d43c6685acfef901c01ff96260 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 
-#ifndef __GT_FILE
-# define __GT_FILE 0
-#endif
-
 /* Generate a unique temporary file name from TEMPLATE.  The last six
    characters before a suffix of length SUFFIXLEN of TEMPLATE must be
    "XXXXXX"; they are replaced with a string that makes the filename
    unique.  Then open the file and return a fd. */
 int
-mkstemps (template, suffixlen)
-     char *template;
-     int suffixlen;
+mkstemps (char *template, int suffixlen)
 {
-  if (suffixlen < 0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  return __gen_tempname (template, suffixlen, 0, __GT_FILE);
+  return mkostemps (template, suffixlen, 0);
 }
 
 #if !defined O_LARGEFILE || O_LARGEFILE == 0
index 1b0f0242576dbafa02ee53a4052c4fa39bcfe189..d3d7013504e48d81bc4f871c9077765bee45666f 100644 (file)
    "XXXXXX"; they are replaced with a string that makes the filename
    unique.  Then open the file and return a fd. */
 int
-mkstemps64 (template, suffixlen)
-     char *template;
-     int suffixlen;
+mkstemps64 (char *template, int suffixlen)
 {
-  if (suffixlen < 0)
-    {
-      __set_errno (EINVAL);
-      return -1;
-    }
-
-  return __gen_tempname (template, suffixlen, O_LARGEFILE, __GT_FILE);
+  return mkostemps (template, suffixlen, O_LARGEFILE);
 }
 
 #endif
index a60f95c06710eeb908610aa1378f828de67e4f7f..737e329fc3574060b74b1370e85db44719d9dc2c 100644 (file)
    The last six characters of TEMPLATE must be "XXXXXX";
    they are replaced with a string that makes the filename unique.  */
 char *
-__mktemp (template)
-     char *template;
+__mktemp (char *template)
 {
-  if (__gen_tempname (template, 0, 0, __GT_NOCREATE) < 0)
+  if (__gen_tempname (template, 0, &__gen_tempname_try_nocreate, NULL) < 0)
     /* We return the null string if we can't find a unique file name.  */
     template[0] = '\0';
 
index dcbb0a92eef7cc5c2be5f5873850426a5b6ad7c7..1c17a467bd20a46a33f19ee6ced6bec8058523cd 100644 (file)
@@ -30,10 +30,11 @@ tempnam (const char *dir, const char *pfx)
 {
   char buf[FILENAME_MAX];
 
-  if (__path_search (buf, FILENAME_MAX, dir, pfx, 1))
+  if (__glibc_unlikely (__path_search (buf, sizeof buf, dir, pfx, 1)))
     return NULL;
 
-  if (__gen_tempname (buf, 0, 0, __GT_NOCREATE))
+  if (__glibc_unlikely (__gen_tempname (buf, 0,
+                                        __gen_tempname_try_nocreate, NULL)))
     return NULL;
 
   return __strdup (buf);
index 7eeb089f14093c836b09fc18fc2be74e0c30ee4b..18e6d35237dfb00c9830bb08849a6f2ee5afce89 100644 (file)
@@ -36,21 +36,18 @@ __path_search (tmpl, tmpl_len, dir, pfx, try_tmpdir)
 }
 stub_warning (__path_search)
 
-/* Generate a (hopefully) unique temporary filename
-   in DIR (if applicable), using template TMPL.
-   KIND determines what to do with that name.  It may be one of:
-     __GT_FILE:                create a file and return a read-write fd.
-     __GT_BIGFILE:     same, but use open64() (or equivalent).
-     __GT_DIR:         create a directory.
-     __GT_NOCREATE:    just find a name not currently in use.
- */
-
+/* Generate a temporary file name based on TMPL.  TMPL must match the
+   rules for mk[s]temp (i.e. end in "XXXXXX", possibly with a suffix).
+   The name constructed does not exist at the time of the call to
+   __gen_tempname.  TMPL is overwritten with the result.
+
+   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.  */
 int
-__gen_tempname (tmpl, suffixlen, flags, kind)
-     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)
 {
   __set_errno (ENOSYS);
   return -1;
index 022c2f650bc97ac467b5a5019552e6a6ae882c94..89689a625f51ab753988561e9460faf5e114cf00 100644 (file)
@@ -44,7 +44,8 @@ tmpfile (void)
 #ifdef FLAGS
   flags = FLAGS;
 #endif
-  fd = __gen_tempname (buf, 0, flags, __GT_FILE);
+  fd = __gen_tempname (buf, 0, &__gen_tempname_try_file,
+                       &((int[2]) { flags, S_IRUSR | S_IWUSR }));
   if (fd < 0)
     return NULL;
 
index d8cd50907fb29d46c7a6e758300cbcdae416813d..810d0ff176d336b36bf7d1ed59da7ff2320c8296 100644 (file)
@@ -34,11 +34,11 @@ tmpnam (char *s)
   /* In the following call we use the buffer pointed to by S if
      non-NULL although we don't know the size.  But we limit the size
      to L_tmpnam characters in any case.  */
-  if (__builtin_expect (__path_search (tmpbuf, L_tmpnam, NULL, NULL, 0),
-                       0))
+  if (__glibc_unlikely (__path_search (tmpbuf, L_tmpnam, NULL, NULL, 0)))
     return NULL;
 
-  if (__glibc_unlikely (__gen_tempname (tmpbuf, 0, 0, __GT_NOCREATE)))
+  if (__glibc_unlikely (__gen_tempname (tmpbuf, 0,
+                                        __gen_tempname_try_nocreate, NULL)))
     return NULL;
 
   if (s == NULL)
index aa2e24e7323b764cb4be4ec631c4263d23d470c9..ad7cc543f329e03cb591015f0123fa1393267c0f 100644 (file)
@@ -25,9 +25,10 @@ tmpnam_r (char *s)
   if (s == NULL)
     return NULL;
 
-  if (__path_search (s, L_tmpnam, NULL, NULL, 0))
+  if (__glibc_unlikely (__path_search (s, L_tmpnam, NULL, NULL, 0)))
     return NULL;
-  if (__gen_tempname (s, 0, 0, __GT_NOCREATE))
+  if (__glibc_unlikely (__gen_tempname (s, 0,
+                                        __gen_tempname_try_nocreate, NULL)))
     return NULL;
 
   return s;
index 3aa11b044b680a8307a04faa59862d7f44bf05d6..b3d4ae7b66a3a6310be023f6c278953075a128f7 100644 (file)
@@ -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;
+}