From cdb29e3ea6c22f0c0358f0414e3ddb615b1c394f Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Sun, 31 Mar 2002 04:17:44 +0000 Subject: Rework __gen_tempname() to better match glibc, and add mkstemp64(), which is needed for busybox ash when using largefile support. -Erik --- include/features.h | 13 +++++ libc/misc/internals/tempname.c | 106 +++++++++++++++++++++++++---------------- libc/stdio/tempnam.c | 7 +-- libc/stdio/tmpfile.c | 6 +-- libc/stdio/tmpnam.c | 10 ++-- libc/stdio/tmpnam_r.c | 6 +-- libc/stdlib/Makefile | 4 +- libc/stdlib/mkstemp.c | 4 +- libc/stdlib/mkstemp64.c | 29 +++++++++++ libc/stdlib/mktemp.c | 4 +- 10 files changed, 116 insertions(+), 73 deletions(-) create mode 100644 libc/stdlib/mkstemp64.c diff --git a/include/features.h b/include/features.h index 98e575dca..e1060ce3e 100644 --- a/include/features.h +++ b/include/features.h @@ -417,6 +417,19 @@ uClibc was built without large file support enabled. /* --- this is added to integrate linuxthreads */ #define __USE_UNIX98 1 +/* For want of a better place, here are some function prototypes + * for things from libc/misc/internals */ +#define __need_size_t +#include +extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, + const char *pfx, int try_tmpdir); +extern int __gen_tempname (char *__tmpl, int __kind); +/* The __kind argument to __gen_tempname may be one of: */ +#define __GT_FILE 0 /* create a file */ +#define __GT_BIGFILE 1 /* create a file, using open64 */ +#define __GT_DIR 2 /* create a directory */ +#define __GT_NOCREATE 3 /* just find a name not currently in use */ + #endif /* _LIBC only stuff */ diff --git a/libc/misc/internals/tempname.c b/libc/misc/internals/tempname.c index 41325d998..427c16cb5 100644 --- a/libc/misc/internals/tempname.c +++ b/libc/misc/internals/tempname.c @@ -27,12 +27,14 @@ #include #include #include -#include -#include #include #include +#include +#include +#include #include + /* Return nonzero if DIR is an existent directory. */ static int direxists (const char *dir) { @@ -46,8 +48,8 @@ static int direxists (const char *dir) for use with mk[s]temp. Will fail (-1) if DIR is non-null and doesn't exist, none of the searched dirs exists, or there's not enough space in TMPL. */ -int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir) +int __path_search (char *tmpl, size_t tmpl_len, const char *dir, + const char *pfx, int try_tmpdir) { //const char *d; size_t dlen, plen; @@ -111,22 +113,28 @@ static const char letters[] = /* Generate a temporary file name based on TMPL. TMPL must match the rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed does not exist at the time of the call to __gen_tempname. TMPL is - overwritten with the result. If OPENIT is nonzero, creates the - file and returns a read-write fd; the file is mode 0600 modulo - umask. If LARGEFILE is nonzero, uses open64() instead of open(). + 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_BIGFILE: same as __GT_FILE but use open64(). + __GT_DIR: create a directory, which will be mode 0700. We use a clever algorithm to get hard-to-predict names. */ -int __gen_tempname (char *tmpl, int openit) +int __gen_tempname (char *tmpl, int kind) { int len; char *XXXXXX; static uint64_t value; struct timeval tv; - uint32_t high, low, rh; - unsigned int k; + uint32_t high, low, rh; + unsigned int k; int count, fd; int save_errno = errno; - int i; + int i; len = strlen (tmpl); if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) @@ -148,46 +156,60 @@ int __gen_tempname (char *tmpl, int openit) high = value >> 32; for (i = 0 ; i < 6 ; i++) { - rh = high % 62; - high /= 62; + rh = high % 62; + high /= 62; #define L ((UINT32_MAX % 62 + 1) % 62) - k = (low % 62) + (L * rh); + k = (low % 62) + (L * rh); #undef L #define H ((UINT32_MAX / 62) + ((UINT32_MAX % 62 + 1) / 62)) - low = (low / 62) + (H * rh) + (k / 62); + low = (low / 62) + (H * rh) + (k / 62); #undef H - k %= 62; - XXXXXX[i] = letters[k]; + k %= 62; + XXXXXX[i] = letters[k]; } - if (openit) - { - fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd >= 0) - { - __set_errno (save_errno); - return fd; - } - else if (errno != EEXIST) - /* Any other error will apply also to other names we might - try, and there are 2^32 or so of them, so give up now. */ - return -1; - } - else - { - struct stat st; - if (stat (tmpl, &st) < 0) - { - if (errno == ENOENT) + switch(kind) { + case __GT_NOCREATE: { - __set_errno (save_errno); - return 0; + struct stat st; + if (stat (tmpl, &st) < 0) + { + if (errno == ENOENT) + { + __set_errno (save_errno); + return 0; + } + else + /* Give up now. */ + return -1; + } + else + continue; } - else - /* Give up now. */ - return -1; - } + case __GT_FILE: + fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; +#if defined __UCLIBC_HAVE_LFS__ + case __GT_BIGFILE: + fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; +#endif + case __GT_DIR: + fd = mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + break; + default: + fd = -1; + assert (! "invalid KIND in __gen_tempname"); } + + if (fd >= 0) { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + /* Any other error will apply also to other names we might + try, and there are 2^32 or so of them, so give up now. */ + return -1; } /* We got out of the loop because we ran out of combinations to try. */ diff --git a/libc/stdio/tempnam.c b/libc/stdio/tempnam.c index 4beb5af83..109276de7 100644 --- a/libc/stdio/tempnam.c +++ b/libc/stdio/tempnam.c @@ -19,11 +19,6 @@ #include #include -extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir); -extern int __gen_tempname (char *tmpl, int openit); - - /* Generate a unique temporary filename using up to five characters of PFX if it is not NULL. The directory to put this file in is searched for as follows: First the environment variable "TMPDIR" is checked. @@ -39,7 +34,7 @@ tempnam (const char *dir, const char *pfx) if (__path_search (buf, FILENAME_MAX, dir, pfx, 1)) return NULL; - if (__gen_tempname (buf, 0)) + if (__gen_tempname (buf, __GT_NOCREATE)) return NULL; return strdup (buf); diff --git a/libc/stdio/tmpfile.c b/libc/stdio/tmpfile.c index 7669e46db..f19c497a4 100644 --- a/libc/stdio/tmpfile.c +++ b/libc/stdio/tmpfile.c @@ -20,10 +20,6 @@ #include #include -extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir); -extern int __gen_tempname (char *tmpl, int openit); - /* This returns a new stream opened on a temporary file (generated by tmpnam). The file is opened with mode "w+b" (binary read/write). If we couldn't generate a unique filename or the file couldn't @@ -36,7 +32,7 @@ FILE * tmpfile (void) if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0)) return NULL; - fd = __gen_tempname (buf, 1); + fd = __gen_tempname (buf, __GT_FILE); if (fd < 0) return NULL; diff --git a/libc/stdio/tmpnam.c b/libc/stdio/tmpnam.c index 296f67f27..23cba46ed 100644 --- a/libc/stdio/tmpnam.c +++ b/libc/stdio/tmpnam.c @@ -19,15 +19,11 @@ #include #include -extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir); -extern int __gen_tempname (char *tmpl, int openit); - static char tmpnam_buffer[L_tmpnam]; /* Generate a unique filename in P_tmpdir. - - This function is *not* thread safe when S == NULL! */ + This function is *not* thread safe when S == NULL! +*/ char * tmpnam (char *s) { /* By using two buffers we manage to be thread safe in the case @@ -40,7 +36,7 @@ char * tmpnam (char *s) if (__path_search (s ? : tmpbuf, L_tmpnam, NULL, NULL, 0)) return NULL; - if (__gen_tempname (s ? : tmpbuf, 0)) + if (__gen_tempname (s ? : tmpbuf, __GT_NOCREATE)) return NULL; if (s == NULL) diff --git a/libc/stdio/tmpnam_r.c b/libc/stdio/tmpnam_r.c index 630d96eb3..6309aac06 100644 --- a/libc/stdio/tmpnam_r.c +++ b/libc/stdio/tmpnam_r.c @@ -18,10 +18,6 @@ #include -extern int __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx, - int try_tmpdir); -extern int __gen_tempname (char *tmpl, int openit); - /* Generate a unique filename in P_tmpdir. If S is NULL return NULL. This makes this function thread safe. */ char * tmpnam_r (char *s) @@ -31,7 +27,7 @@ char * tmpnam_r (char *s) if (__path_search (s, L_tmpnam, NULL, NULL, 0)) return NULL; - if (__gen_tempname (s, 0)) + if (__gen_tempname (s, __GT_NOCREATE)) return NULL; return s; diff --git a/libc/stdlib/Makefile b/libc/stdlib/Makefile index 71136c2fa..44a359434 100644 --- a/libc/stdlib/Makefile +++ b/libc/stdlib/Makefile @@ -38,8 +38,8 @@ MSRC2=atexit.c MOBJ2=atexit.o on_exit.o __exit_handler.o exit.o CSRC = abort.c getenv.c mktemp.c qsort.c realpath.c bsearch.c \ - mkstemp.c putenv.c rand.c random.c random_r.c setenv.c system.c div.c \ - ldiv.c getpt.c ptsname.c grantpt.c unlockpt.c gcvt.c + mkstemp.c mkstemp64.c putenv.c rand.c random.c random_r.c setenv.c \ + system.c div.c ldiv.c getpt.c ptsname.c grantpt.c unlockpt.c gcvt.c CSRC+= drand48.c drand48-iter.c drand48_r.c erand48.c erand48_r.c \ jrand48.c jrand48_r.c lrand48.c lrand48_r.c mrand48.c mrand48_r.c \ nrand48.c nrand48_r.c rand_r.c srand48.c srand48_r.c diff --git a/libc/stdlib/mkstemp.c b/libc/stdlib/mkstemp.c index d0104c8f3..de5d557f4 100644 --- a/libc/stdlib/mkstemp.c +++ b/libc/stdlib/mkstemp.c @@ -19,13 +19,11 @@ #include #include -extern int __gen_tempname (char *tmpl, int openit); - /* 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 (char *template) { - return __gen_tempname (template, 1); + return __gen_tempname (template, __GT_FILE); } diff --git a/libc/stdlib/mkstemp64.c b/libc/stdlib/mkstemp64.c new file mode 100644 index 000000000..5762da79d --- /dev/null +++ b/libc/stdlib/mkstemp64.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* 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 mkstemp64 (char *template) +{ + return __gen_tempname (template, __GT_BIGFILE); +} diff --git a/libc/stdlib/mktemp.c b/libc/stdlib/mktemp.c index 432d64f2a..4faa3e671 100644 --- a/libc/stdlib/mktemp.c +++ b/libc/stdlib/mktemp.c @@ -19,14 +19,12 @@ #include #include -extern int __gen_tempname (char *tmpl, int openit); - /* 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. */ char * mktemp (char *template) { - if (__gen_tempname (template, 0) < 0) + if (__gen_tempname (template, __GT_NOCREATE) < 0) /* We return the null string if we can't find a unique file name. */ template[0] = '\0'; -- cgit v1.2.3