diff options
author | Rich Felker <dalias@aerifal.cx> | 2014-05-27 00:44:23 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2014-05-27 00:44:23 -0400 |
commit | 2fe6579125fe042f2255afbf00fc8e4b80d6a6be (patch) | |
tree | 153294950c138c8cbef7ca3a9dd145f99f7afc6e | |
parent | 9b880a6b4112b0b3c0bd07949f7836daeea4e712 (diff) | |
download | musl-2fe6579125fe042f2255afbf00fc8e4b80d6a6be.tar.gz |
overhaul tmpfile, tmpnam, and tempnam functions
these all now use the shared __randname function internally, rather
than duplicating logic for producing a random name. incorrect usage of
the access syscall (which works with real uid/gid, not effective) has
been removed, along with unnecessary heavy dependencies like snprintf.
-rw-r--r-- | src/stdio/tempnam.c | 55 | ||||
-rw-r--r-- | src/stdio/tmpfile.c | 8 | ||||
-rw-r--r-- | src/stdio/tmpnam.c | 40 |
3 files changed, 48 insertions, 55 deletions
diff --git a/src/stdio/tempnam.c b/src/stdio/tempnam.c index f73ca9f9..9bf8c727 100644 --- a/src/stdio/tempnam.c +++ b/src/stdio/tempnam.c @@ -1,42 +1,43 @@ #include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/stat.h> +#include <limits.h> #include <string.h> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <time.h> -#include "libc.h" -#include "atomic.h" +#include "syscall.h" #define MAXTRIES 100 +char *__randname(char *); + char *tempnam(const char *dir, const char *pfx) { - static int index; - char *s; - struct timespec ts; - int pid = getpid(); - size_t l; - int n; - int try=0; + char s[PATH_MAX]; + size_t l, dl, pl; + int try; + int r; if (!dir) dir = P_tmpdir; if (!pfx) pfx = "temp"; - if (access(dir, R_OK|W_OK|X_OK) != 0) - return NULL; - - l = strlen(dir) + 1 + strlen(pfx) + 3*(sizeof(int)*3+2) + 1; - s = malloc(l); - if (!s) return s; + dl = strlen(dir); + pl = strlen(pfx); + l = dl + 1 + pl + 1 + 6; - do { - clock_gettime(CLOCK_REALTIME, &ts); - n = ts.tv_nsec ^ (uintptr_t)&s ^ (uintptr_t)s; - snprintf(s, l, "%s/%s-%d-%d-%x", dir, pfx, pid, a_fetch_add(&index, 1), n); - } while (!access(s, F_OK) && try++<MAXTRIES); - if (try>=MAXTRIES) { - free(s); + if (l >= PATH_MAX) { + errno = ENAMETOOLONG; return 0; } - return s; + + memcpy(s, dir, dl); + s[dl] = '/'; + memcpy(s+dl+1, pfx, pl); + s[dl+1+pl] = '_'; + + for (try=0; try<MAXTRIES; try++) { + __randname(s+l-6); + r = __syscall(SYS_lstat, s, &(struct stat){0}); + if (r == -ENOENT) return strdup(s); + } + return 0; } diff --git a/src/stdio/tmpfile.c b/src/stdio/tmpfile.c index b0d0ba07..c8569948 100644 --- a/src/stdio/tmpfile.c +++ b/src/stdio/tmpfile.c @@ -1,19 +1,19 @@ #include <stdio.h> #include <fcntl.h> -#include <unistd.h> #include "stdio_impl.h" #define MAXTRIES 100 +char *__randname(char *); + FILE *tmpfile(void) { - char buf[L_tmpnam], *s; + char s[] = "/tmp/tmpfile_XXXXXX"; int fd; FILE *f; int try; for (try=0; try<MAXTRIES; try++) { - s = tmpnam(buf); - if (!s) return 0; + __randname(s+13); fd = sys_open(s, O_RDWR|O_CREAT|O_EXCL, 0600); if (fd >= 0) { f = __fdopen(fd, "w+"); diff --git a/src/stdio/tmpnam.c b/src/stdio/tmpnam.c index 2bd72b3b..92f699c2 100644 --- a/src/stdio/tmpnam.c +++ b/src/stdio/tmpnam.c @@ -1,31 +1,23 @@ #include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <unistd.h> -#include <time.h> -#include "libc.h" +#include <fcntl.h> +#include <errno.h> +#include <sys/stat.h> #include "syscall.h" -#include "atomic.h" #define MAXTRIES 100 -char *tmpnam(char *s) -{ - static int index; - static char s2[L_tmpnam]; - struct timespec ts; - int try = 0; - unsigned n; - - if (!s) s = s2; +char *__randname(char *); - if (__syscall(SYS_access, P_tmpdir, R_OK|W_OK|X_OK) != 0) - return NULL; - - do { - __syscall(SYS_clock_gettime, CLOCK_REALTIME, &ts, 0); - n = ts.tv_nsec ^ (uintptr_t)&s ^ (uintptr_t)s; - snprintf(s, L_tmpnam, "/tmp/t%x-%x", a_fetch_add(&index, 1), n); - } while (!__syscall(SYS_access, s, F_OK) && try++<MAXTRIES); - return try>=MAXTRIES ? 0 : s; +char *tmpnam(char *buf) +{ + static char internal[L_tmpnam]; + char s[] = "/tmp/tmpnam_XXXXXX"; + int try; + int r; + for (try=0; try<MAXTRIES; try++) { + __randname(s+12); + r = __syscall(SYS_lstat, s, &(struct stat){0}); + if (r == -ENOENT) return strcpy(buf ? buf : internal, s); + } + return 0; } |