add mkostemp, mkstemps, and mkostemps functions and reorganize temp internals
authorRich Felker <dalias@aerifal.cx>
Thu, 21 Feb 2013 03:43:23 +0000 (22:43 -0500)
committerRich Felker <dalias@aerifal.cx>
Thu, 21 Feb 2013 03:43:23 +0000 (22:43 -0500)
based on patch contributed by Anthony G. Basile (blueness)

some issues remain with the filename generation algorithm and other
small bugs, but this patch has been sitting around long enough that I
feel it's best to get it committed and then work out any remaining
issues.

include/stdlib.h
src/temp/__randname.c [new file with mode: 0644]
src/temp/mkostemp.c [new file with mode: 0644]
src/temp/mkostemps.c [new file with mode: 0644]
src/temp/mkstemp.c
src/temp/mkstemps.c [new file with mode: 0644]
src/temp/mktemp.c

index 671d188fd90f50bc04eb7bf890bd64f6891d8b2e..0bcc9f4f91abda83e719374cb31214ab1540c5da 100644 (file)
@@ -95,6 +95,7 @@ int posix_memalign (void **, size_t, size_t);
 int setenv (const char *, const char *, int);
 int unsetenv (const char *);
 int mkstemp (char *);
+int mkostemp (char *, int);
 char *mkdtemp (char *);
 int getsubopt (char **, char *const *, char **);
 int rand_r (unsigned *);
@@ -134,6 +135,8 @@ void lcong48 (unsigned short [7]);
 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 #include <alloca.h>
 char *mktemp (char *);
+int mkstemps (char *, int);
+int mkostemps (char *, int, int);
 void *valloc (size_t);
 void *memalign(size_t, size_t);
 #define WCOREDUMP(s) ((s) & 0x80)
@@ -150,6 +153,11 @@ char *gcvt(double, int, char *);
 
 #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
 #define mkstemp64 mkstemp
+#define mkostemp64 mkostemp
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define mkstemps64 mkstemps
+#define mkostemps64 mkostemps
+#endif
 #endif
 
 #ifdef __cplusplus
diff --git a/src/temp/__randname.c b/src/temp/__randname.c
new file mode 100644 (file)
index 0000000..b097576
--- /dev/null
@@ -0,0 +1,21 @@
+#include <string.h>
+#include <time.h>
+#include <stdint.h>
+
+int __clock_gettime(clockid_t, struct timespec *);
+
+/* This assumes that a check for the
+   template size has alrady been made */
+char *__randname(char *template)
+{
+       int i;
+       struct timespec ts;
+       unsigned long r;
+
+       __clock_gettime(CLOCK_REALTIME, &ts);
+       r = ts.tv_nsec*65537 ^ (uintptr_t)&ts / 16 + (uintptr_t)template;
+       for (i=0; i<6; i++, r>>=5)
+               template[i] = 'A'+(r&15)+(r&16)*2;
+
+       return template;
+}
diff --git a/src/temp/mkostemp.c b/src/temp/mkostemp.c
new file mode 100644 (file)
index 0000000..e73e22a
--- /dev/null
@@ -0,0 +1,12 @@
+#define _BSD_SOURCE
+#include <stdlib.h>
+#include "libc.h"
+
+int __mkostemps(char *, int, int);
+
+int mkostemp(char *template, int flags)
+{
+       return __mkostemps(template, 0, flags);
+}
+
+LFS64(mkostemp);
diff --git a/src/temp/mkostemps.c b/src/temp/mkostemps.c
new file mode 100644 (file)
index 0000000..804a547
--- /dev/null
@@ -0,0 +1,32 @@
+#define _BSD_SOURCE
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "libc.h"
+
+char *__randname(char *);
+
+int __mkostemps(char *template, int len, int flags)
+{
+       if (len < 0) return EINVAL;
+
+       size_t l = strlen(template)-len;
+       if (l < 6 || strncmp(template+l-6, "XXXXXX", 6)) {
+               errno = EINVAL;
+               *template = 0;
+               return -1;
+       }
+
+       int fd, retries = 100;
+       while (retries--) {
+               __randname(template+l-6);
+               if ((fd = open(template, flags | O_RDWR | O_CREAT | O_EXCL, 0600))>=0)
+                       return fd;
+               if (errno != EEXIST) return -1;
+       }
+       return -1;
+}
+
+weak_alias(__mkostemps, mkostemps);
+weak_alias(__mkostemps, mkostemps64);
index a390d4272cef638384973268ba149b99fbcf01ed..85764af7cd35daa720d41021dbc8bd2803e020e4 100644 (file)
@@ -1,28 +1,11 @@
-#include <string.h>
-#include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
 #include "libc.h"
 
-char *__mktemp(char *);
+int __mkostemps(char *, int, int);
 
 int mkstemp(char *template)
 {
-       int fd, retries = 100, t0 = *template;
-       while (retries--) {
-               if (!*__mktemp(template)) return -1;
-               if ((fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600))>=0)
-                       return fd;
-               if (errno != EEXIST) return -1;
-               /* this is safe because mktemp verified
-                * that we have a valid template string */
-               template[0] = t0;
-               strcpy(template+strlen(template)-6, "XXXXXX");
-       }
-       return -1;
+       return __mkostemps(template, 0, 0);
 }
 
 LFS64(mkstemp);
diff --git a/src/temp/mkstemps.c b/src/temp/mkstemps.c
new file mode 100644 (file)
index 0000000..fda710b
--- /dev/null
@@ -0,0 +1,12 @@
+#define _BSD_SOURCE
+#include <stdlib.h>
+#include "libc.h"
+
+int __mkostemps(char *, int, int);
+
+int mkstemps(char *template, int len)
+{
+       return __mkostemps(template, len, 0);
+}
+
+LFS64(mkstemps);
index c0e06f5ef424216c3b142999942b1146c801fa4d..ed2c103e776ea4fa84edc3f198b33aec30bfbc4e 100644 (file)
@@ -1,17 +1,14 @@
 #include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
-#include <time.h>
-#include <stdint.h>
 #include "libc.h"
 
+char *__randname(char *);
+
 char *__mktemp(char *template)
 {
-       struct timespec ts;
-       size_t i, l = strlen(template);
+       size_t l = strlen(template);
        int retries = 10000;
        unsigned long r;
 
@@ -21,10 +18,7 @@ char *__mktemp(char *template)
                return template;
        }
        while (retries--) {
-               clock_gettime(CLOCK_REALTIME, &ts);
-               r = ts.tv_nsec + (uintptr_t)&ts / 16 + (uintptr_t)template;
-               for (i=1; i<=6; i++, r>>=4)
-                       template[l-i] = 'A'+(r&15);
+               __randname(template+l-6);
                if (access(template, F_OK) < 0) return template;
        }
        *template = 0;