diff --git a/include/stdio.h b/include/stdio.h index 2fa99840..488b4114 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -47,6 +47,7 @@ extern "C" { #define FOPEN_MAX 16 #define L_ctermid 11 /* Fit at least /dev/pts/XX */ #define L_tmpnam 16 +#define P_tmpdir "/tmp" #define TMP_MAX 32767 typedef off_t fpos_t; @@ -194,6 +195,10 @@ extern FILE *tmpfile(void); extern char *tmpnam(char *str); +/* Generates a pathname that may be used for a temporary file. */ +extern char *tempnam(const char *dir, const char *pfx); + + /* Sends formatted output to a stream. */ extern int fprintf(FILE *stream, const char *format, ...) __attribute__((format(printf, 2, 3))); diff --git a/posix/stubs.c b/posix/stubs.c index 8c23d239..03058ad5 100644 --- a/posix/stubs.c +++ b/posix/stubs.c @@ -199,10 +199,6 @@ char *gets(char *str) return NULL; } -char *tmpnam(char *str) -{ - return NULL; -} int wctomb(char *str, wchar_t wchar) { diff --git a/stdlib/mktemp.c b/stdlib/mktemp.c index 86d347db..b5e25777 100644 --- a/stdlib/mktemp.c +++ b/stdlib/mktemp.c @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #include @@ -119,3 +121,61 @@ char *mkdtemp(char *templt) return templt; } + + +char *tmpnam(char *str) +{ + static char template[L_tmpnam]; + int err; + + if (str == NULL) { + str = template; + } + + do { + (void)strcpy(str, "/tmp/fileXXXXXX"); + err = __mktemp(str, 0); + } while ((err < 0) && errno == EEXIST); + + return (err < 0) ? NULL : str; +} + + +char *tempnam(const char *dir, const char *pfx) +{ + struct stat statbuf; + int err, dirlen, pfxlen, sep = 0; + + if (dir == NULL || stat(dir, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) { + if (access(P_tmpdir, W_OK | X_OK) < 0) { + dir = "/"; + } + else { + dir = P_tmpdir; + } + } + + dirlen = strlen(dir); + pfxlen = (pfx == NULL) ? 4 /* strlen("file") */ : strlen(pfx); + if (dir[dirlen - 1] != '/') { + sep = 1; + } + + char *name = malloc(dirlen + sep + pfxlen + 6 /* "XXXXXX" */ + 1); + if (name == NULL) { + errno = ENOMEM; + return NULL; + } + + do { + sprintf(name, "%s%s%sXXXXXX", dir, (sep != 0) ? "/" : "", (pfx == NULL) ? "file" : pfx); + err = __mktemp(name, 0); + } while ((err < 0) && errno == EEXIST); + + if (err < 0) { + free(name); + name = NULL; + } + + return name; +}