From 7846f71fb36fcb96216718d8b2bdd957c1f31c43 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 7 Aug 2008 13:02:45 +0000 Subject: [PATCH] add the mkstemp module from gnulib * bootstrap (modules): Add mkstemp. The remainder of these changes are the result of running ./bootstrap, adding new files, and committing the result. * gnulib/lib/gettimeofday.c: New file. * gnulib/lib/mkstemp.c: New file. * gnulib/lib/tempname.c: New file. * gnulib/lib/tempname.h: New file. * gnulib/m4/gettimeofday.m4: New file. * gnulib/m4/mkstemp.m4: New file. * gnulib/m4/tempname.m4: New file. * gnulib/tests/test-gettimeofday.c: New file. * gnulib/lib/Makefile.am: Update. * gnulib/m4/gnulib-cache.m4: Likewise. * gnulib/m4/gnulib-comp.m4: Likewise. * gnulib/m4/inet_pton.m4: Likewise. * gnulib/tests/Makefile.am: Likewise. --- ChangeLog | 20 ++ bootstrap | 1 + gnulib/lib/Makefile.am | 29 ++- gnulib/lib/gettimeofday.c | 142 ++++++++++++++ gnulib/lib/mkstemp.c | 44 +++++ gnulib/lib/tempname.c | 314 +++++++++++++++++++++++++++++++ gnulib/lib/tempname.h | 39 ++++ gnulib/m4/gettimeofday.m4 | 101 ++++++++++ gnulib/m4/gnulib-cache.m4 | 3 +- gnulib/m4/gnulib-comp.m4 | 12 ++ gnulib/m4/inet_pton.m4 | 2 +- gnulib/m4/mkstemp.m4 | 56 ++++++ gnulib/m4/tempname.m4 | 22 +++ gnulib/tests/Makefile.am | 9 + gnulib/tests/test-gettimeofday.c | 45 +++++ 15 files changed, 836 insertions(+), 3 deletions(-) create mode 100644 gnulib/lib/gettimeofday.c create mode 100644 gnulib/lib/mkstemp.c create mode 100644 gnulib/lib/tempname.c create mode 100644 gnulib/lib/tempname.h create mode 100644 gnulib/m4/gettimeofday.m4 create mode 100644 gnulib/m4/mkstemp.m4 create mode 100644 gnulib/m4/tempname.m4 create mode 100644 gnulib/tests/test-gettimeofday.c diff --git a/ChangeLog b/ChangeLog index c83b9af5dc..78a8f213b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +Wed Aug 7 15:02:06 CEST 2008 Jim Meyering + + add the mkstemp module from gnulib + * bootstrap (modules): Add mkstemp. + The remainder of these changes are the result of running + ./bootstrap, adding new files, and committing the result. + * gnulib/lib/gettimeofday.c: New file. + * gnulib/lib/mkstemp.c: New file. + * gnulib/lib/tempname.c: New file. + * gnulib/lib/tempname.h: New file. + * gnulib/m4/gettimeofday.m4: New file. + * gnulib/m4/mkstemp.m4: New file. + * gnulib/m4/tempname.m4: New file. + * gnulib/tests/test-gettimeofday.c: New file. + * gnulib/lib/Makefile.am: Update. + * gnulib/m4/gnulib-cache.m4: Likewise. + * gnulib/m4/gnulib-comp.m4: Likewise. + * gnulib/m4/inet_pton.m4: Likewise. + * gnulib/tests/Makefile.am: Likewise. + Thu Aug 7 12:21:31 CEST 2008 Daniel Veillard * src/bridge.c: fix a build failure on RHEL4 diff --git a/bootstrap b/bootstrap index 70b9a05680..f8fcb30dd5 100755 --- a/bootstrap +++ b/bootstrap @@ -70,6 +70,7 @@ getaddrinfo getpass gettext inet_pton +mkstemp mktempd physmem poll diff --git a/gnulib/lib/Makefile.am b/gnulib/lib/Makefile.am index 576b951231..3a7ba31a84 100644 --- a/gnulib/lib/Makefile.am +++ b/gnulib/lib/Makefile.am @@ -9,7 +9,7 @@ # the same distribution terms as the rest of that program. # # Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --doc-base=doc --aux-dir=build-aux --with-tests --lgpl=2 --libtool --macro-prefix=gl c-ctype getaddrinfo getpass gettext inet_pton mktempd physmem poll posix-shell strndup strsep sys_stat useless-if-before-free vasprintf vc-list-files verify +# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --doc-base=doc --aux-dir=build-aux --with-tests --lgpl=2 --libtool --macro-prefix=gl c-ctype getaddrinfo getpass gettext inet_pton mkstemp mktempd physmem poll posix-shell strndup strsep sys_stat useless-if-before-free vasprintf vc-list-files verify AUTOMAKE_OPTIONS = 1.5 gnits @@ -172,6 +172,15 @@ libgnu_la_SOURCES += gettext.h ## end gnulib module gettext-h +## begin gnulib module gettimeofday + + +EXTRA_DIST += gettimeofday.c + +EXTRA_libgnu_la_SOURCES += gettimeofday.c + +## end gnulib module gettimeofday + ## begin gnulib module havelib @@ -223,6 +232,15 @@ EXTRA_libgnu_la_SOURCES += malloc.c ## end gnulib module malloc-posix +## begin gnulib module mkstemp + + +EXTRA_DIST += mkstemp.c + +EXTRA_libgnu_la_SOURCES += mkstemp.c + +## end gnulib module mkstemp + ## begin gnulib module mktempd @@ -702,6 +720,15 @@ EXTRA_DIST += sys_time.in.h ## end gnulib module sys_time +## begin gnulib module tempname + + +EXTRA_DIST += tempname.c tempname.h + +EXTRA_libgnu_la_SOURCES += tempname.c + +## end gnulib module tempname + ## begin gnulib module unistd BUILT_SOURCES += unistd.h diff --git a/gnulib/lib/gettimeofday.c b/gnulib/lib/gettimeofday.c new file mode 100644 index 0000000000..75339c46a1 --- /dev/null +++ b/gnulib/lib/gettimeofday.c @@ -0,0 +1,142 @@ +/* Provide gettimeofday for systems that don't have it or for which it's broken. + + Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, or (at your option) + any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* written by Jim Meyering */ + +#include + +/* Specification. */ +#include + +#include + +#if HAVE_SYS_TIMEB_H +# include +#endif + +#if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME + +/* Work around the bug in some systems whereby gettimeofday clobbers + the static buffer that localtime uses for its return value. The + gettimeofday function from Mac OS X 10.0.4 (i.e., Darwin 1.3.7) has + this problem. The tzset replacement is necessary for at least + Solaris 2.5, 2.5.1, and 2.6. */ + +static struct tm tm_zero_buffer; +static struct tm *localtime_buffer_addr = &tm_zero_buffer; + +/* This is a wrapper for localtime. It is used only on systems for which + gettimeofday clobbers the static buffer used for localtime's result. + + On the first call, record the address of the static buffer that + localtime uses for its result. */ + +struct tm * +rpl_localtime (time_t const *timep) +{ +#undef localtime + extern struct tm *localtime (time_t const *); + struct tm *tm = localtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +/* Same as above, since gmtime and localtime use the same buffer. */ +struct tm * +rpl_gmtime (time_t const *timep) +{ +#undef gmtime + extern struct tm *gmtime (time_t const *); + struct tm *tm = gmtime (timep); + + if (localtime_buffer_addr == &tm_zero_buffer) + localtime_buffer_addr = tm; + + return tm; +} + +#endif /* GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME */ + +#if TZSET_CLOBBERS_LOCALTIME +/* This is a wrapper for tzset, for systems on which tzset may clobber + the static buffer used for localtime's result. */ +void +rpl_tzset (void) +{ +#undef tzset + extern void tzset (void); + + /* Save and restore the contents of the buffer used for localtime's + result around the call to tzset. */ + struct tm save = *localtime_buffer_addr; + tzset (); + *localtime_buffer_addr = save; +} +#endif + +/* This is a wrapper for gettimeofday. It is used only on systems + that lack this function, or whose implementation of this function + causes problems. */ + +int +rpl_gettimeofday (struct timeval *restrict tv, void *restrict tz) +{ +#undef gettimeofday +#if HAVE_GETTIMEOFDAY +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + /* Save and restore the contents of the buffer used for localtime's + result around the call to gettimeofday. */ + struct tm save = *localtime_buffer_addr; +# endif + + int result = gettimeofday (tv, tz); + +# if GETTIMEOFDAY_CLOBBERS_LOCALTIME + *localtime_buffer_addr = save; +# endif + + return result; + +#else + +# if HAVE__FTIME + + struct _timeb timebuf; + _ftime (&timebuf); + tv->tv_sec = timebuf.time; + tv->tv_usec = timebuf.millitm * 1000; + +# else + +# if !defined OK_TO_USE_1S_CLOCK +# error "Only 1-second nominal clock resolution found. Is that intended?" \ + "If so, compile with the -DOK_TO_USE_1S_CLOCK option." +# endif + tv->tv_sec = time (NULL); + tv->tv_usec = 0; + +# endif + + return 0; + +#endif +} diff --git a/gnulib/lib/mkstemp.c b/gnulib/lib/mkstemp.c new file mode 100644 index 0000000000..fcd44d993f --- /dev/null +++ b/gnulib/lib/mkstemp.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1998, 1999, 2001, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is derived from the one in the GNU C Library. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +#if !_LIBC +# include +#endif + +#include + +#if !_LIBC +# include "tempname.h" +# define __gen_tempname gen_tempname +# define __GT_FILE GT_FILE +#endif + +#include + +#ifndef __GT_FILE +# define __GT_FILE 0 +#endif + +/* 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 file name unique. + Then open the file and return a fd. */ +int +mkstemp (template) + char *template; +{ + return __gen_tempname (template, __GT_FILE); +} diff --git a/gnulib/lib/tempname.c b/gnulib/lib/tempname.c new file mode 100644 index 0000000000..2d5e5edb08 --- /dev/null +++ b/gnulib/lib/tempname.c @@ -0,0 +1,314 @@ +/* tempname.c - generate the name of a temporary file. + + Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2005, 2006, 2007 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* Extracted from glibc sysdeps/posix/tempname.c. See also tmpdir.c. */ + +#if !_LIBC +# include +# include "tempname.h" +#endif + +#include +#include + +#include +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +#include +#ifndef P_tmpdir +# define P_tmpdir "/tmp" +#endif +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif +#ifndef __GT_FILE +# define __GT_FILE 0 +# define __GT_BIGFILE 1 +# define __GT_DIR 2 +# define __GT_NOCREATE 3 +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#if _LIBC +# define struct_stat64 struct stat64 +# define small_open __open +# define large_open __open64 +#else +# define struct_stat64 struct stat +# define small_open open +# define large_open open +# define __gen_tempname gen_tempname +# define __getpid getpid +# define __gettimeofday gettimeofday +# define __mkdir mkdir +# define __lxstat64(version, file, buf) lstat (file, buf) +# define __xstat64(version, file, buf) stat (file, buf) +#endif + +#if ! (HAVE___SECURE_GETENV || _LIBC) +# define __secure_getenv getenv +#endif + +#ifdef _LIBC +# include +# if HP_TIMING_AVAIL +# define RANDOM_BITS(Var) \ + if (__builtin_expect (value == UINT64_C (0), 0)) \ + { \ + /* If this is the first time this function is used initialize \ + the variable we accumulate the value in to some somewhat \ + random value. If we'd not do this programs at startup time \ + might have a reduced set of possible names, at least on slow \ + machines. */ \ + struct timeval tv; \ + __gettimeofday (&tv, NULL); \ + value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ + } \ + HP_TIMING_NOW (Var) +# endif +#endif + +/* Use the widest available unsigned type if uint64_t is not + available. The algorithm below extracts a number less than 62**6 + (approximately 2**35.725) from uint64_t, so ancient hosts where + uintmax_t is only 32 bits lose about 3.725 bits of randomness, + which is better than not having mkstemp at all. */ +#if !defined UINT64_MAX && !defined uint64_t +# define uint64_t uintmax_t +#endif + +#if _LIBC +/* Return nonzero if DIR is an existent directory. */ +static int +direxists (const char *dir) +{ + struct_stat64 buf; + return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + 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) +{ + const char *d; + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + if (try_tmpdir) + { + d = __secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int) dlen, dir, (int) plen, pfx); + return 0; +} +#endif /* _LIBC */ + +/* These are the characters used in temporary file names. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* 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. + + 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 kind) +{ + int len; + char *XXXXXX; + static uint64_t value; + uint64_t random_time_bits; + unsigned int count; + int fd = -1; + int save_errno = errno; + struct_stat64 st; + + /* 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 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. */ +#define ATTEMPTS_MIN (62 * 62 * 62) + + /* The number of times to attempt to generate a temporary file. To + conform to POSIX, this must be no smaller than TMP_MAX. */ +#if ATTEMPTS_MIN < TMP_MAX + unsigned int attempts = TMP_MAX; +#else + unsigned int attempts = ATTEMPTS_MIN; +#endif + + len = strlen (tmpl); + if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX")) + { + __set_errno (EINVAL); + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - 6]; + + /* 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 (); + + for (count = 0; count < attempts; value += 7777, ++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]; + + switch (kind) + { + case __GT_FILE: + fd = small_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; + + case __GT_BIGFILE: + fd = large_open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + break; + + case __GT_DIR: + fd = __mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR); + break; + + case __GT_NOCREATE: + /* This case is backward from the other three. __gen_tempname + succeeds if __xstat fails because the name does not exist. + Note the continue to bypass the common logic at the bottom + of the loop. */ + if (__lxstat64 (_STAT_VER, tmpl, &st) < 0) + { + if (errno == ENOENT) + { + __set_errno (save_errno); + return 0; + } + else + /* Give up now. */ + return -1; + } + continue; + + default: + assert (! "invalid KIND in __gen_tempname"); + } + + if (fd >= 0) + { + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} diff --git a/gnulib/lib/tempname.h b/gnulib/lib/tempname.h new file mode 100644 index 0000000000..e04a99d70d --- /dev/null +++ b/gnulib/lib/tempname.h @@ -0,0 +1,39 @@ +/* Create a temporary file or directory. + + Copyright (C) 2006 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . */ + +/* header written by Eric Blake */ + +/* In gnulib, always prefer large files. GT_FILE maps to + __GT_BIGFILE, not __GT_FILE, for a reason. */ +#define GT_FILE 1 +#define GT_DIR 2 +#define GT_NOCREATE 3 + +/* 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. + + KIND may be one of: + GT_NOCREATE: simply verify that the name does not exist + at the time of the call. + GT_FILE: create a large file using open(O_CREAT|O_EXCL) + and return a read-write fd. The file is mode 0600. + GT_DIR: create a directory, which will be mode 0700. + + We use a clever algorithm to get hard-to-predict names. */ +extern int gen_tempname (char *tmpl, int kind); diff --git a/gnulib/m4/gettimeofday.m4 b/gnulib/m4/gettimeofday.m4 new file mode 100644 index 0000000000..b9bbb1081b --- /dev/null +++ b/gnulib/m4/gettimeofday.m4 @@ -0,0 +1,101 @@ +#serial 11 + +# Copyright (C) 2001, 2002, 2003, 2005, 2007 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +dnl From Jim Meyering. + +AC_DEFUN([gl_FUNC_GETTIMEOFDAY], +[ + AC_REQUIRE([AC_C_RESTRICT]) + AC_REQUIRE([gl_HEADER_SYS_TIME_H]) + AC_CHECK_FUNCS_ONCE([gettimeofday]) + + AC_CACHE_CHECK([for gettimeofday with POSIX signature], + [gl_cv_func_gettimeofday_posix_signature], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + struct timeval c; + ]], + [[ + int (*f) (struct timeval *restrict, void *restrict) = gettimeofday; + int x = f (&c, 0); + return !(x | c.tv_sec | c.tv_usec); + ]])], + [gl_cv_func_gettimeofday_posix_signature=yes], + [gl_cv_func_gettimeofday_posix_signature=no])]) + + gl_FUNC_GETTIMEOFDAY_CLOBBER + + if test $gl_cv_func_gettimeofday_posix_signature != yes; then + REPLACE_GETTIMEOFDAY=1 + SYS_TIME_H=sys/time.h + if test $gl_cv_func_gettimeofday_clobber != yes; then + AC_LIBOBJ(gettimeofday) + gl_PREREQ_GETTIMEOFDAY + fi + fi +]) + + +dnl See if gettimeofday clobbers the static buffer that localtime uses +dnl for its return value. The gettimeofday function from Mac OS X 10.0.4 +dnl (i.e., Darwin 1.3.7) has this problem. +dnl +dnl If it does, then arrange to use gettimeofday and localtime only via +dnl the wrapper functions that work around the problem. + +AC_DEFUN([gl_FUNC_GETTIMEOFDAY_CLOBBER], +[ + AC_REQUIRE([gl_HEADER_SYS_TIME_H]) + + AC_CACHE_CHECK([whether gettimeofday clobbers localtime buffer], + [gl_cv_func_gettimeofday_clobber], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + ]], + [[ + time_t t = 0; + struct tm *lt; + struct tm saved_lt; + struct timeval tv; + lt = localtime (&t); + saved_lt = *lt; + gettimeofday (&tv, NULL); + return memcmp (lt, &saved_lt, sizeof (struct tm)) != 0; + ]])], + [gl_cv_func_gettimeofday_clobber=no], + [gl_cv_func_gettimeofday_clobber=yes], + dnl When crosscompiling, assume it is broken. + [gl_cv_func_gettimeofday_clobber=yes])]) + + if test $gl_cv_func_gettimeofday_clobber = yes; then + REPLACE_GETTIMEOFDAY=1 + SYS_TIME_H=sys/time.h + gl_GETTIMEOFDAY_REPLACE_LOCALTIME + AC_DEFINE([GETTIMEOFDAY_CLOBBERS_LOCALTIME], 1, + [Define if gettimeofday clobbers the localtime buffer.]) + fi +]) + +AC_DEFUN([gl_GETTIMEOFDAY_REPLACE_LOCALTIME], [ + AC_LIBOBJ(gettimeofday) + gl_PREREQ_GETTIMEOFDAY + AC_DEFINE([gmtime], [rpl_gmtime], + [Define to rpl_gmtime if the replacement function should be used.]) + AC_DEFINE([localtime], [rpl_localtime], + [Define to rpl_localtime if the replacement function should be used.]) +]) + +# Prerequisites of lib/gettimeofday.c. +AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [ + AC_CHECK_HEADERS([sys/timeb.h]) + AC_CHECK_FUNCS([_ftime]) +]) diff --git a/gnulib/m4/gnulib-cache.m4 b/gnulib/m4/gnulib-cache.m4 index d26e7f05d5..ac9e993fc7 100644 --- a/gnulib/m4/gnulib-cache.m4 +++ b/gnulib/m4/gnulib-cache.m4 @@ -15,7 +15,7 @@ # Specification in the form of a command-line invocation: -# gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --doc-base=doc --aux-dir=build-aux --with-tests --lgpl=2 --libtool --macro-prefix=gl c-ctype getaddrinfo getpass gettext inet_pton mktempd physmem poll posix-shell strndup strsep sys_stat useless-if-before-free vasprintf vc-list-files verify +# gnulib-tool --import --dir=. --lib=libgnu --source-base=gnulib/lib --m4-base=gnulib/m4 --doc-base=doc --aux-dir=build-aux --with-tests --lgpl=2 --libtool --macro-prefix=gl c-ctype getaddrinfo getpass gettext inet_pton mkstemp mktempd physmem poll posix-shell strndup strsep sys_stat useless-if-before-free vasprintf vc-list-files verify # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -25,6 +25,7 @@ gl_MODULES([ getpass gettext inet_pton + mkstemp mktempd physmem poll diff --git a/gnulib/m4/gnulib-comp.m4 b/gnulib/m4/gnulib-comp.m4 index 239eb7a5f5..dbbaaa6299 100644 --- a/gnulib/m4/gnulib-comp.m4 +++ b/gnulib/m4/gnulib-comp.m4 @@ -60,6 +60,7 @@ AC_DEFUN([gl_INIT], AM_GNU_GETTEXT_VERSION([0.17]) AC_SUBST([LIBINTL]) AC_SUBST([LTLIBINTL]) + gl_FUNC_GETTIMEOFDAY gl_INET_NTOP gl_ARPA_INET_MODULE_INDICATOR([inet_ntop]) gl_INET_PTON @@ -68,6 +69,8 @@ AC_DEFUN([gl_INIT], gl_UNISTD_MODULE_INDICATOR([lseek]) gl_FUNC_MALLOC_POSIX gl_STDLIB_MODULE_INDICATOR([malloc-posix]) + gl_FUNC_MKSTEMP + gl_STDLIB_MODULE_INDICATOR([mkstemp]) gl_HEADER_NETINET_IN AC_PROG_MKDIR_P gl_PHYSMEM @@ -102,6 +105,7 @@ AC_DEFUN([gl_INIT], AC_PROG_MKDIR_P gl_HEADER_SYS_TIME_H AC_PROG_MKDIR_P + gl_FUNC_GEN_TEMPNAME gl_UNISTD_H gl_FUNC_VASNPRINTF gl_FUNC_VASPRINTF @@ -268,10 +272,12 @@ AC_DEFUN([gl_FILE_LIST], [ lib/getpass.c lib/getpass.h lib/gettext.h + lib/gettimeofday.c lib/inet_ntop.c lib/inet_pton.c lib/lseek.c lib/malloc.c + lib/mkstemp.c lib/netinet_in.in.h lib/physmem.c lib/physmem.h @@ -299,6 +305,8 @@ AC_DEFUN([gl_FILE_LIST], [ lib/sys_socket.in.h lib/sys_stat.in.h lib/sys_time.in.h + lib/tempname.c + lib/tempname.h lib/unistd.in.h lib/vasnprintf.c lib/vasnprintf.h @@ -318,6 +326,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/getline.m4 m4/getpass.m4 m4/gettext.m4 + m4/gettimeofday.m4 m4/glibc2.m4 m4/glibc21.m4 m4/gnulib-common.m4 @@ -341,6 +350,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/longlong.m4 m4/lseek.m4 m4/malloc.m4 + m4/mkstemp.m4 m4/netinet_in_h.m4 m4/nls.m4 m4/onceonly.m4 @@ -371,6 +381,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/sys_socket_h.m4 m4/sys_stat_h.m4 m4/sys_time_h.m4 + m4/tempname.m4 m4/uintmax_t.m4 m4/unistd_h.m4 m4/vasnprintf.m4 @@ -389,6 +400,7 @@ AC_DEFUN([gl_FILE_LIST], [ tests/test-getaddrinfo.c tests/test-getdelim.c tests/test-getline.c + tests/test-gettimeofday.c tests/test-lseek.c tests/test-lseek.sh tests/test-netinet_in.c diff --git a/gnulib/m4/inet_pton.m4 b/gnulib/m4/inet_pton.m4 index a57e4c6cba..a72cd2383c 100644 --- a/gnulib/m4/inet_pton.m4 +++ b/gnulib/m4/inet_pton.m4 @@ -6,7 +6,7 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_INET_PTON], [ - dnl Persuade Solaris to declare inet_ntop. + dnl Persuade Solaris to declare inet_pton. AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_REQUIRE([gl_ARPA_INET_H_DEFAULTS]) diff --git a/gnulib/m4/mkstemp.m4 b/gnulib/m4/mkstemp.m4 new file mode 100644 index 0000000000..20d8a1b701 --- /dev/null +++ b/gnulib/m4/mkstemp.m4 @@ -0,0 +1,56 @@ +#serial 17 + +# Copyright (C) 2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# On some hosts (e.g., HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a +# silly limit that it can create no more than 26 files from a given template. +# Other systems lack mkstemp altogether. +# On OSF1/Tru64 V4.0F, the system-provided mkstemp function can create +# only 32 files per process. +# On systems like the above, arrange to use the replacement function. +AC_DEFUN([gl_FUNC_MKSTEMP], +[ + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + AC_REQUIRE([AC_SYS_LARGEFILE]) + + AC_CACHE_CHECK([for working mkstemp], + [gl_cv_func_working_mkstemp], + [ + mkdir conftest.mkstemp + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [AC_INCLUDES_DEFAULT], + [[int i; + off_t large = (off_t) 4294967295u; + if (large < 0) + large = 2147483647; + for (i = 0; i < 70; i++) + { + char templ[] = "conftest.mkstemp/coXXXXXX"; + int (*mkstemp_function) (char *) = mkstemp; + int fd = mkstemp_function (templ); + if (fd < 0 || lseek (fd, large, SEEK_SET) != large) + return 1; + close (fd); + } + return 0;]])], + [gl_cv_func_working_mkstemp=yes], + [gl_cv_func_working_mkstemp=no], + [gl_cv_func_working_mkstemp=no]) + rm -rf conftest.mkstemp + ]) + + if test $gl_cv_func_working_mkstemp != yes; then + REPLACE_MKSTEMP=1 + AC_LIBOBJ([mkstemp]) + gl_PREREQ_MKSTEMP + fi +]) + +# Prerequisites of lib/mkstemp.c. +AC_DEFUN([gl_PREREQ_MKSTEMP], +[ +]) diff --git a/gnulib/m4/tempname.m4 b/gnulib/m4/tempname.m4 new file mode 100644 index 0000000000..4c44d37da9 --- /dev/null +++ b/gnulib/m4/tempname.m4 @@ -0,0 +1,22 @@ +#serial 3 + +# Copyright (C) 2006-2007 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# glibc provides __gen_tempname as a wrapper for mk[ds]temp. Expose +# it as a public API, and provide it on systems that are lacking. +AC_DEFUN([gl_FUNC_GEN_TEMPNAME], +[ + AC_REQUIRE([AC_SYS_LARGEFILE]) + + AC_LIBOBJ([tempname]) + gl_PREREQ_TEMPNAME +]) + +# Prerequisites of lib/tempname.c. +AC_DEFUN([gl_PREREQ_TEMPNAME], +[ + : +]) diff --git a/gnulib/tests/Makefile.am b/gnulib/tests/Makefile.am index 6692c7f47e..6995840b17 100644 --- a/gnulib/tests/Makefile.am +++ b/gnulib/tests/Makefile.am @@ -114,6 +114,15 @@ EXTRA_DIST += test-getline.c ## end gnulib module getline-tests +## begin gnulib module gettimeofday-tests + +TESTS += test-gettimeofday +check_PROGRAMS += test-gettimeofday + +EXTRA_DIST += test-gettimeofday.c + +## end gnulib module gettimeofday-tests + ## begin gnulib module intprops diff --git a/gnulib/tests/test-gettimeofday.c b/gnulib/tests/test-gettimeofday.c new file mode 100644 index 0000000000..892b18829c --- /dev/null +++ b/gnulib/tests/test-gettimeofday.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005, 2007 Free Software Foundation + * Written by Jim Meyering. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ + +#include + +#include +#include + +#include +#include + +int +main (int argc, char *argv[]) +{ + time_t t = 0; + struct tm *lt; + struct tm saved_lt; + struct timeval tv; + lt = localtime (&t); + saved_lt = *lt; + gettimeofday (&tv, NULL); + if (memcmp (lt, &saved_lt, sizeof (struct tm)) != 0) + { + fprintf (stderr, "gettimeofday still clobbers the localtime buffer!\n"); + return 1; + } + else + { + return 0; + } +} -- GitLab