mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
This includes a change to require --with-libmount to be used with configure, due to the many libmount dependencies. * bootstrap: Sync with gnulib to exit early on gnulib-tool error. * gl/lib/tempname.c.diff: Adjust for gnulib changes. * gl/lib/tempname.h.diff: Likewise. * gl/modules/tempname: Likewise. * doc/.gitignore: Add new gendocs_template_min gnulib script.
190 lines
5.4 KiB
Diff
190 lines
5.4 KiB
Diff
diff --git a/lib/tempname.c b/lib/tempname.c
|
|
index 49c7df1..84a45d4 100644
|
|
--- a/lib/tempname.c
|
|
+++ b/lib/tempname.c
|
|
@@ -20,6 +20,7 @@
|
|
#if !_LIBC
|
|
# include <config.h>
|
|
# include "tempname.h"
|
|
+# include "randint.h"
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
@@ -47,6 +48,7 @@
|
|
# error report this to bug-gnulib@gnu.org
|
|
#endif
|
|
|
|
+#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
@@ -173,28 +175,34 @@ __path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
|
|
}
|
|
#endif /* _LIBC */
|
|
|
|
+static inline bool _GL_ATTRIBUTE_PURE
|
|
+check_x_suffix (char const *s, size_t len)
|
|
+{
|
|
+ return len <= strspn (s, "X");
|
|
+}
|
|
+
|
|
/* These are the characters used in temporary file names. */
|
|
static const char letters[] =
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
|
|
int
|
|
-__try_tempname (char *tmpl, int suffixlen, void *args,
|
|
- int (*try) (char *, void *))
|
|
+try_tempname_len (char *tmpl, int suffixlen, void *args,
|
|
+ int (*try) (char *, void *), size_t x_suffix_len)
|
|
{
|
|
- int len;
|
|
+ size_t len;
|
|
char *XXXXXX;
|
|
- static uint64_t value;
|
|
- uint64_t random_time_bits;
|
|
unsigned int count;
|
|
int fd = -1;
|
|
int save_errno = errno;
|
|
+ struct randint_source *rand_src;
|
|
|
|
/* A lower bound on the number of temporary files to attempt to
|
|
generate. The maximum total number of temporary file names that
|
|
can exist for a given template is 62**6. It should never be
|
|
necessary to try all of these combinations. Instead if a reasonable
|
|
number of names is tried (we define reasonable as 62**3) fail to
|
|
- give the system administrator the chance to remove the problems. */
|
|
+ give the system administrator the chance to remove the problems.
|
|
+ This value requires that X_SUFFIX_LEN be at least 3. */
|
|
#define ATTEMPTS_MIN (62 * 62 * 62)
|
|
|
|
/* The number of times to attempt to generate a temporary file. To
|
|
@@ -206,57 +214,55 @@ __try_tempname (char *tmpl, int suffixlen, void *args,
|
|
#endif
|
|
|
|
len = strlen (tmpl);
|
|
- if (len < 6 + suffixlen || memcmp (&tmpl[len - 6 - suffixlen], "XXXXXX", 6))
|
|
+ if (len < x_suffix_len + suffixlen
|
|
+ || ! check_x_suffix (&tmpl[len - x_suffix_len - suffixlen],
|
|
+ x_suffix_len))
|
|
{
|
|
__set_errno (EINVAL);
|
|
return -1;
|
|
}
|
|
|
|
/* This is where the Xs start. */
|
|
- XXXXXX = &tmpl[len - 6 - suffixlen];
|
|
+ XXXXXX = &tmpl[len - x_suffix_len - suffixlen];
|
|
|
|
/* Get some more or less random data. */
|
|
-#ifdef RANDOM_BITS
|
|
- RANDOM_BITS (random_time_bits);
|
|
-#else
|
|
- {
|
|
- struct timeval tv;
|
|
- __gettimeofday (&tv, NULL);
|
|
- random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec;
|
|
- }
|
|
-#endif
|
|
- value += random_time_bits ^ __getpid ();
|
|
+ rand_src = randint_all_new (NULL, x_suffix_len);
|
|
+ if (! rand_src)
|
|
+ return -1;
|
|
|
|
- for (count = 0; count < attempts; value += 7777, ++count)
|
|
+ for (count = 0; count < attempts; ++count)
|
|
{
|
|
- uint64_t v = value;
|
|
-
|
|
- /* Fill in the random bits. */
|
|
- XXXXXX[0] = letters[v % 62];
|
|
- v /= 62;
|
|
- XXXXXX[1] = letters[v % 62];
|
|
- v /= 62;
|
|
- XXXXXX[2] = letters[v % 62];
|
|
- v /= 62;
|
|
- XXXXXX[3] = letters[v % 62];
|
|
- v /= 62;
|
|
- XXXXXX[4] = letters[v % 62];
|
|
- v /= 62;
|
|
- XXXXXX[5] = letters[v % 62];
|
|
+ size_t i;
|
|
+
|
|
+ for (i = 0; i < x_suffix_len; i++)
|
|
+ XXXXXX[i] = letters[randint_genmax (rand_src, sizeof letters - 2)];
|
|
|
|
fd = try (tmpl, args);
|
|
if (fd >= 0)
|
|
{
|
|
__set_errno (save_errno);
|
|
- return fd;
|
|
+ goto done;
|
|
}
|
|
else if (errno != EEXIST)
|
|
- return -1;
|
|
+ {
|
|
+ fd = -1;
|
|
+ goto done;
|
|
+ }
|
|
}
|
|
|
|
+ randint_all_free (rand_src);
|
|
+
|
|
/* We got out of the loop because we ran out of combinations to try. */
|
|
__set_errno (EEXIST);
|
|
return -1;
|
|
+
|
|
+ done:
|
|
+ {
|
|
+ int saved_errno = errno;
|
|
+ randint_all_free (rand_src);
|
|
+ __set_errno (saved_errno);
|
|
+ }
|
|
+ return fd;
|
|
}
|
|
|
|
static int
|
|
@@ -285,9 +291,10 @@ try_nocreate (char *tmpl, void *flags)
|
|
}
|
|
|
|
/* 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).
|
|
+ rules for mk[s]temp (i.e., end in at least X_SUFFIX_LEN "X"s,
|
|
+ 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.
|
|
+ this function. TMPL is overwritten with the result.
|
|
|
|
KIND may be one of:
|
|
__GT_NOCREATE: simply verify that the name does not exist
|
|
@@ -298,7 +305,8 @@ try_nocreate (char *tmpl, void *flags)
|
|
|
|
We use a clever algorithm to get hard-to-predict names. */
|
|
int
|
|
-__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
|
|
+gen_tempname_len (char *tmpl, int suffixlen, int flags, int kind,
|
|
+ size_t x_suffix_len)
|
|
{
|
|
int (*try) (char *, void *);
|
|
|
|
@@ -320,5 +328,18 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
|
|
assert (! "invalid KIND in __gen_tempname");
|
|
abort ();
|
|
}
|
|
- return __try_tempname (tmpl, suffixlen, &flags, try);
|
|
+ return try_tempname_len (tmpl, suffixlen, &flags, try, x_suffix_len);
|
|
+}
|
|
+
|
|
+int
|
|
+__gen_tempname (char *tmpl, int suffixlen, int flags, int kind)
|
|
+{
|
|
+ return gen_tempname_len (tmpl, suffixlen, flags, kind, 6);
|
|
+}
|
|
+
|
|
+int
|
|
+__try_tempname (char *tmpl, int suffixlen, void *args,
|
|
+ int (*try) (char *, void *))
|
|
+{
|
|
+ return try_tempname_len (tmpl, suffixlen, args, try, 6);
|
|
}
|