mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
Add gnulib files to support higher-resolution time stamps.
Fixes: debbugs:9000
This commit is contained in:
parent
36cec983d4
commit
c8fff86301
24 changed files with 2734 additions and 0 deletions
69
lib/dtotimespec.c
Normal file
69
lib/dtotimespec.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* Convert double to timespec.
|
||||
|
||||
Copyright (C) 2011-2012 Free Software Foundation, Inc.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* written by Paul Eggert */
|
||||
|
||||
/* Convert the double value SEC to a struct timespec. Round toward
|
||||
positive infinity. On overflow, return an extremal value. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "timespec.h"
|
||||
|
||||
#include "intprops.h"
|
||||
|
||||
struct timespec
|
||||
dtotimespec (double sec)
|
||||
{
|
||||
enum { BILLION = 1000 * 1000 * 1000 };
|
||||
double min_representable = TYPE_MINIMUM (time_t);
|
||||
double max_representable =
|
||||
((TYPE_MAXIMUM (time_t) * (double) BILLION + (BILLION - 1))
|
||||
/ BILLION);
|
||||
struct timespec r;
|
||||
|
||||
if (! (min_representable < sec))
|
||||
{
|
||||
r.tv_sec = TYPE_MINIMUM (time_t);
|
||||
r.tv_nsec = 0;
|
||||
}
|
||||
else if (! (sec < max_representable))
|
||||
{
|
||||
r.tv_sec = TYPE_MAXIMUM (time_t);
|
||||
r.tv_nsec = BILLION - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t s = sec;
|
||||
double frac = BILLION * (sec - s);
|
||||
long ns = frac;
|
||||
ns += ns < frac;
|
||||
s += ns / BILLION;
|
||||
ns %= BILLION;
|
||||
|
||||
if (ns < 0)
|
||||
{
|
||||
s--;
|
||||
ns += BILLION;
|
||||
}
|
||||
|
||||
r.tv_sec = s;
|
||||
r.tv_nsec = ns;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
48
lib/gettime.c
Normal file
48
lib/gettime.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/* gettime -- get the system clock
|
||||
|
||||
Copyright (C) 2002, 2004-2007, 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "timespec.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
/* Get the system time into *TS. */
|
||||
|
||||
void
|
||||
gettime (struct timespec *ts)
|
||||
{
|
||||
#if HAVE_NANOTIME
|
||||
nanotime (ts);
|
||||
#else
|
||||
|
||||
# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
|
||||
if (clock_gettime (CLOCK_REALTIME, ts) == 0)
|
||||
return;
|
||||
# endif
|
||||
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday (&tv, NULL);
|
||||
ts->tv_sec = tv.tv_sec;
|
||||
ts->tv_nsec = tv.tv_usec * 1000;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
154
lib/gettimeofday.c
Normal file
154
lib/gettimeofday.c
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/* Provide gettimeofday for systems that don't have it or for which it's broken.
|
||||
|
||||
Copyright (C) 2001-2003, 2005-2007, 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* written by Jim Meyering */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if HAVE_SYS_TIMEB_H
|
||||
# include <sys/timeb.h>
|
||||
#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;
|
||||
|
||||
# undef localtime
|
||||
extern struct tm *localtime (time_t const *);
|
||||
|
||||
# undef gmtime
|
||||
extern struct tm *gmtime (time_t const *);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
# undef tzset
|
||||
extern void tzset (void);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* 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
|
||||
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
|
||||
|
||||
# if defined timeval /* 'struct timeval' overridden by gnulib? */
|
||||
# undef timeval
|
||||
struct timeval otv;
|
||||
int result = gettimeofday (&otv, (struct timezone *) tz);
|
||||
if (result == 0)
|
||||
{
|
||||
tv->tv_sec = otv.tv_sec;
|
||||
tv->tv_usec = otv.tv_usec;
|
||||
}
|
||||
# else
|
||||
int result = gettimeofday (tv, (struct timezone *) tz);
|
||||
# endif
|
||||
|
||||
# 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
|
||||
}
|
||||
76
lib/pselect.c
Normal file
76
lib/pselect.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/* pselect - synchronous I/O multiplexing
|
||||
|
||||
Copyright 2011-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of gnulib.
|
||||
|
||||
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, 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* written by Paul Eggert */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* Examine the size-NFDS file descriptor sets in RFDS, WFDS, and XFDS
|
||||
to see whether some of their descriptors are ready for reading,
|
||||
ready for writing, or have exceptions pending. Wait for at most
|
||||
TIMEOUT seconds, and use signal mask SIGMASK while waiting. A null
|
||||
pointer parameter stands for no descriptors, an infinite timeout,
|
||||
or an unaffected signal mask. */
|
||||
|
||||
int
|
||||
pselect (int nfds, fd_set *restrict rfds,
|
||||
fd_set *restrict wfds, fd_set *restrict xfds,
|
||||
struct timespec const *restrict timeout,
|
||||
sigset_t const *restrict sigmask)
|
||||
{
|
||||
int select_result;
|
||||
sigset_t origmask;
|
||||
struct timeval tv, *tvp;
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
if (! (0 <= timeout->tv_nsec && timeout->tv_nsec < 1000000000))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tv.tv_sec = timeout->tv_sec;
|
||||
tv.tv_usec = (timeout->tv_nsec + 999) / 1000;
|
||||
tvp = &tv;
|
||||
}
|
||||
else
|
||||
tvp = NULL;
|
||||
|
||||
/* Signal mask munging should be atomic, but this is the best we can
|
||||
do in this emulation. */
|
||||
if (sigmask)
|
||||
pthread_sigmask (SIG_SETMASK, sigmask, &origmask);
|
||||
|
||||
select_result = select (nfds, rfds, wfds, xfds, tvp);
|
||||
|
||||
if (sigmask)
|
||||
{
|
||||
int select_errno = errno;
|
||||
pthread_sigmask (SIG_SETMASK, &origmask, NULL);
|
||||
errno = select_errno;
|
||||
}
|
||||
|
||||
return select_result;
|
||||
}
|
||||
189
lib/stat-time.h
Normal file
189
lib/stat-time.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/* stat-related time functions.
|
||||
|
||||
Copyright (C) 2005, 2007, 2009-2012 Free Software Foundation, Inc.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#ifndef STAT_TIME_H
|
||||
#define STAT_TIME_H 1
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
/* STAT_TIMESPEC (ST, ST_XTIM) is the ST_XTIM member for *ST of type
|
||||
struct timespec, if available. If not, then STAT_TIMESPEC_NS (ST,
|
||||
ST_XTIM) is the nanosecond component of the ST_XTIM member for *ST,
|
||||
if available. ST_XTIM can be st_atim, st_ctim, st_mtim, or st_birthtim
|
||||
for access, status change, data modification, or birth (creation)
|
||||
time respectively.
|
||||
|
||||
These macros are private to stat-time.h. */
|
||||
#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
|
||||
# ifdef TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
|
||||
# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
|
||||
# else
|
||||
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
|
||||
# endif
|
||||
#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
|
||||
# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
|
||||
#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
|
||||
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
|
||||
#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
|
||||
# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
|
||||
#endif
|
||||
|
||||
/* Return the nanosecond component of *ST's access time. */
|
||||
static inline long int
|
||||
get_stat_atime_ns (struct stat const *st)
|
||||
{
|
||||
# if defined STAT_TIMESPEC
|
||||
return STAT_TIMESPEC (st, st_atim).tv_nsec;
|
||||
# elif defined STAT_TIMESPEC_NS
|
||||
return STAT_TIMESPEC_NS (st, st_atim);
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Return the nanosecond component of *ST's status change time. */
|
||||
static inline long int
|
||||
get_stat_ctime_ns (struct stat const *st)
|
||||
{
|
||||
# if defined STAT_TIMESPEC
|
||||
return STAT_TIMESPEC (st, st_ctim).tv_nsec;
|
||||
# elif defined STAT_TIMESPEC_NS
|
||||
return STAT_TIMESPEC_NS (st, st_ctim);
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Return the nanosecond component of *ST's data modification time. */
|
||||
static inline long int
|
||||
get_stat_mtime_ns (struct stat const *st)
|
||||
{
|
||||
# if defined STAT_TIMESPEC
|
||||
return STAT_TIMESPEC (st, st_mtim).tv_nsec;
|
||||
# elif defined STAT_TIMESPEC_NS
|
||||
return STAT_TIMESPEC_NS (st, st_mtim);
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Return the nanosecond component of *ST's birth time. */
|
||||
static inline long int
|
||||
get_stat_birthtime_ns (struct stat const *st)
|
||||
{
|
||||
# if defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC
|
||||
return STAT_TIMESPEC (st, st_birthtim).tv_nsec;
|
||||
# elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
|
||||
return STAT_TIMESPEC_NS (st, st_birthtim);
|
||||
# else
|
||||
/* Avoid a "parameter unused" warning. */
|
||||
(void) st;
|
||||
return 0;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Return *ST's access time. */
|
||||
static inline struct timespec
|
||||
get_stat_atime (struct stat const *st)
|
||||
{
|
||||
#ifdef STAT_TIMESPEC
|
||||
return STAT_TIMESPEC (st, st_atim);
|
||||
#else
|
||||
struct timespec t;
|
||||
t.tv_sec = st->st_atime;
|
||||
t.tv_nsec = get_stat_atime_ns (st);
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return *ST's status change time. */
|
||||
static inline struct timespec
|
||||
get_stat_ctime (struct stat const *st)
|
||||
{
|
||||
#ifdef STAT_TIMESPEC
|
||||
return STAT_TIMESPEC (st, st_ctim);
|
||||
#else
|
||||
struct timespec t;
|
||||
t.tv_sec = st->st_ctime;
|
||||
t.tv_nsec = get_stat_ctime_ns (st);
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return *ST's data modification time. */
|
||||
static inline struct timespec
|
||||
get_stat_mtime (struct stat const *st)
|
||||
{
|
||||
#ifdef STAT_TIMESPEC
|
||||
return STAT_TIMESPEC (st, st_mtim);
|
||||
#else
|
||||
struct timespec t;
|
||||
t.tv_sec = st->st_mtime;
|
||||
t.tv_nsec = get_stat_mtime_ns (st);
|
||||
return t;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return *ST's birth time, if available; otherwise return a value
|
||||
with tv_sec and tv_nsec both equal to -1. */
|
||||
static inline struct timespec
|
||||
get_stat_birthtime (struct stat const *st)
|
||||
{
|
||||
struct timespec t;
|
||||
|
||||
#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
|
||||
|| defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
|
||||
t = STAT_TIMESPEC (st, st_birthtim);
|
||||
#elif defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC
|
||||
t.tv_sec = st->st_birthtime;
|
||||
t.tv_nsec = st->st_birthtimensec;
|
||||
#elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
|
||||
/* Native Windows platforms (but not Cygwin) put the "file creation
|
||||
time" in st_ctime (!). See
|
||||
<http://msdn2.microsoft.com/de-de/library/14h5k7ff(VS.80).aspx>. */
|
||||
t.tv_sec = st->st_ctime;
|
||||
t.tv_nsec = 0;
|
||||
#else
|
||||
/* Birth time is not supported. */
|
||||
t.tv_sec = -1;
|
||||
t.tv_nsec = -1;
|
||||
/* Avoid a "parameter unused" warning. */
|
||||
(void) st;
|
||||
#endif
|
||||
|
||||
#if (defined HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC \
|
||||
|| defined HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC \
|
||||
|| defined HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
|
||||
/* FreeBSD and NetBSD sometimes signal the absence of knowledge by
|
||||
using zero. Attempt to work around this problem. Alas, this can
|
||||
report failure even for valid time stamps. Also, NetBSD
|
||||
sometimes returns junk in the birth time fields; work around this
|
||||
bug if it is detected. */
|
||||
if (! (t.tv_sec && 0 <= t.tv_nsec && t.tv_nsec < 1000000000))
|
||||
{
|
||||
t.tv_sec = -1;
|
||||
t.tv_nsec = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
#endif
|
||||
298
lib/sys_select.in.h
Normal file
298
lib/sys_select.in.h
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
/* Substitute for <sys/select.h>.
|
||||
Copyright (C) 2007-2012 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
# if __GNUC__ >= 3
|
||||
@PRAGMA_SYSTEM_HEADER@
|
||||
# endif
|
||||
@PRAGMA_COLUMNS@
|
||||
|
||||
/* On OSF/1, <sys/types.h> and <sys/time.h> include <sys/select.h>.
|
||||
Simply delegate to the system's header in this case. */
|
||||
#if @HAVE_SYS_SELECT_H@ && defined __osf__ && (defined _SYS_TYPES_H_ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H) && defined _OSF_SOURCE
|
||||
|
||||
# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TYPES_H
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
|
||||
|
||||
#elif @HAVE_SYS_SELECT_H@ && defined __osf__ && (defined _SYS_TIME_H_ && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H) && defined _OSF_SOURCE
|
||||
|
||||
# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_TIME_H
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
|
||||
|
||||
/* On IRIX 6.5, <sys/timespec.h> includes <sys/types.h>, which includes
|
||||
<sys/bsd_types.h>, which includes <sys/select.h>. At this point we cannot
|
||||
include <signal.h>, because that includes <internal/signal_core.h>, which
|
||||
gives a syntax error because <sys/timespec.h> has not been completely
|
||||
processed. Simply delegate to the system's header in this case. */
|
||||
#elif @HAVE_SYS_SELECT_H@ && defined __sgi && (defined _SYS_BSD_TYPES_H && !defined _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H)
|
||||
|
||||
# define _GL_SYS_SELECT_H_REDIRECT_FROM_SYS_BSD_TYPES_H
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
|
||||
|
||||
/* On OpenBSD 5.0, <pthread.h> includes <sys/types.h>, which includes
|
||||
<sys/select.h>. At this point we cannot include <signal.h>, because that
|
||||
includes gnulib's pthread.h override, which gives a syntax error because
|
||||
/usr/include/pthread.h has not been completely processed. Simply delegate
|
||||
to the system's header in this case. */
|
||||
#elif @HAVE_SYS_SELECT_H@ && defined __OpenBSD__ && (defined _PTHREAD_H_ && !defined PTHREAD_MUTEX_INITIALIZER)
|
||||
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
|
||||
|
||||
#else
|
||||
|
||||
#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
|
||||
|
||||
/* On many platforms, <sys/select.h> assumes prior inclusion of
|
||||
<sys/types.h>. Also, mingw defines sigset_t there, instead of
|
||||
in <signal.h> where it belongs. */
|
||||
#include <sys/types.h>
|
||||
|
||||
#if @HAVE_SYS_SELECT_H@
|
||||
|
||||
/* On OSF/1 4.0, <sys/select.h> provides only a forward declaration
|
||||
of 'struct timeval', and no definition of this type.
|
||||
Also, Mac OS X, AIX, HP-UX, IRIX, Solaris, Interix declare select()
|
||||
in <sys/time.h>.
|
||||
But avoid namespace pollution on glibc systems. */
|
||||
# ifndef __GLIBC__
|
||||
# include <sys/time.h>
|
||||
# endif
|
||||
|
||||
/* On AIX 7 and Solaris 10, <sys/select.h> provides an FD_ZERO implementation
|
||||
that relies on memset(), but without including <string.h>.
|
||||
But in any case avoid namespace pollution on glibc systems. */
|
||||
# if (defined __OpenBSD__ || defined _AIX || defined __sun || defined __osf__ || defined __BEOS__) \
|
||||
&& ! defined __GLIBC__
|
||||
# include <string.h>
|
||||
# endif
|
||||
|
||||
/* The include_next requires a split double-inclusion guard. */
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_SELECT_H@
|
||||
|
||||
#endif
|
||||
|
||||
/* Get definition of 'sigset_t'.
|
||||
But avoid namespace pollution on glibc systems.
|
||||
Do this after the include_next (for the sake of OpenBSD 5.0) but before
|
||||
the split double-inclusion guard (for the sake of Solaris). */
|
||||
#if !(defined __GLIBC__ && !defined __UCLIBC__)
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifndef _@GUARD_PREFIX@_SYS_SELECT_H
|
||||
#define _@GUARD_PREFIX@_SYS_SELECT_H
|
||||
|
||||
#if !@HAVE_SYS_SELECT_H@
|
||||
/* A platform that lacks <sys/select.h>. */
|
||||
/* Get the 'struct timeval' and 'fd_set' types and the FD_* macros
|
||||
on most platforms. */
|
||||
# include <sys/time.h>
|
||||
/* On HP-UX 11, <sys/time.h> provides an FD_ZERO implementation
|
||||
that relies on memset(), but without including <string.h>. */
|
||||
# if defined __hpux
|
||||
# include <string.h>
|
||||
# endif
|
||||
/* On native Windows platforms:
|
||||
Get the 'fd_set' type.
|
||||
Get the close() declaration before we override it. */
|
||||
# if @HAVE_WINSOCK2_H@
|
||||
# if !defined _GL_INCLUDING_WINSOCK2_H
|
||||
# define _GL_INCLUDING_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
# undef _GL_INCLUDING_WINSOCK2_H
|
||||
# endif
|
||||
# include <io.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
|
||||
|
||||
/* The definition of _GL_WARN_ON_USE is copied here. */
|
||||
|
||||
|
||||
/* Fix some definitions from <winsock2.h>. */
|
||||
|
||||
#if @HAVE_WINSOCK2_H@
|
||||
|
||||
# if !GNULIB_defined_rpl_fd_isset
|
||||
|
||||
/* Re-define FD_ISSET to avoid a WSA call while we are not using
|
||||
network sockets. */
|
||||
static inline int
|
||||
rpl_fd_isset (SOCKET fd, fd_set * set)
|
||||
{
|
||||
u_int i;
|
||||
if (set == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < set->fd_count; i++)
|
||||
if (set->fd_array[i] == fd)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
# define GNULIB_defined_rpl_fd_isset 1
|
||||
# endif
|
||||
|
||||
# undef FD_ISSET
|
||||
# define FD_ISSET(fd, set) rpl_fd_isset(fd, set)
|
||||
|
||||
#endif
|
||||
|
||||
/* Hide some function declarations from <winsock2.h>. */
|
||||
|
||||
#if @HAVE_WINSOCK2_H@
|
||||
# if !defined _@GUARD_PREFIX@_UNISTD_H
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef close
|
||||
# define close close_used_without_including_unistd_h
|
||||
# else
|
||||
_GL_WARN_ON_USE (close,
|
||||
"close() used without including <unistd.h>");
|
||||
# endif
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef gethostname
|
||||
# define gethostname gethostname_used_without_including_unistd_h
|
||||
# else
|
||||
_GL_WARN_ON_USE (gethostname,
|
||||
"gethostname() used without including <unistd.h>");
|
||||
# endif
|
||||
# endif
|
||||
# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef socket
|
||||
# define socket socket_used_without_including_sys_socket_h
|
||||
# undef connect
|
||||
# define connect connect_used_without_including_sys_socket_h
|
||||
# undef accept
|
||||
# define accept accept_used_without_including_sys_socket_h
|
||||
# undef bind
|
||||
# define bind bind_used_without_including_sys_socket_h
|
||||
# undef getpeername
|
||||
# define getpeername getpeername_used_without_including_sys_socket_h
|
||||
# undef getsockname
|
||||
# define getsockname getsockname_used_without_including_sys_socket_h
|
||||
# undef getsockopt
|
||||
# define getsockopt getsockopt_used_without_including_sys_socket_h
|
||||
# undef listen
|
||||
# define listen listen_used_without_including_sys_socket_h
|
||||
# undef recv
|
||||
# define recv recv_used_without_including_sys_socket_h
|
||||
# undef send
|
||||
# define send send_used_without_including_sys_socket_h
|
||||
# undef recvfrom
|
||||
# define recvfrom recvfrom_used_without_including_sys_socket_h
|
||||
# undef sendto
|
||||
# define sendto sendto_used_without_including_sys_socket_h
|
||||
# undef setsockopt
|
||||
# define setsockopt setsockopt_used_without_including_sys_socket_h
|
||||
# undef shutdown
|
||||
# define shutdown shutdown_used_without_including_sys_socket_h
|
||||
# else
|
||||
_GL_WARN_ON_USE (socket,
|
||||
"socket() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (connect,
|
||||
"connect() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (accept,
|
||||
"accept() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (bind,
|
||||
"bind() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (getpeername,
|
||||
"getpeername() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (getsockname,
|
||||
"getsockname() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (getsockopt,
|
||||
"getsockopt() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (listen,
|
||||
"listen() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (recv,
|
||||
"recv() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (send,
|
||||
"send() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (recvfrom,
|
||||
"recvfrom() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (sendto,
|
||||
"sendto() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (setsockopt,
|
||||
"setsockopt() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (shutdown,
|
||||
"shutdown() used without including <sys/socket.h>");
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#if @GNULIB_PSELECT@
|
||||
# if @REPLACE_PSELECT@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef pselect
|
||||
# define pselect rpl_pselect
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (pselect, int,
|
||||
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
|
||||
struct timespec const *restrict, const sigset_t *restrict));
|
||||
_GL_CXXALIAS_RPL (pselect, int,
|
||||
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
|
||||
struct timespec const *restrict, const sigset_t *restrict));
|
||||
# else
|
||||
# if !@HAVE_PSELECT@
|
||||
_GL_FUNCDECL_SYS (pselect, int,
|
||||
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
|
||||
struct timespec const *restrict, const sigset_t *restrict));
|
||||
# endif
|
||||
_GL_CXXALIAS_SYS (pselect, int,
|
||||
(int, fd_set *restrict, fd_set *restrict, fd_set *restrict,
|
||||
struct timespec const *restrict, const sigset_t *restrict));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (pselect);
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
# undef pselect
|
||||
# if HAVE_RAW_DECL_PSELECT
|
||||
_GL_WARN_ON_USE (pselect, "pselect is not portable - "
|
||||
"use gnulib module pselect for portability");
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if @GNULIB_SELECT@
|
||||
# if @REPLACE_SELECT@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef select
|
||||
# define select rpl_select
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (select, int,
|
||||
(int, fd_set *, fd_set *, fd_set *, struct timeval *));
|
||||
_GL_CXXALIAS_RPL (select, int,
|
||||
(int, fd_set *, fd_set *, fd_set *, struct timeval *));
|
||||
# else
|
||||
_GL_CXXALIAS_SYS (select, int,
|
||||
(int, fd_set *, fd_set *, fd_set *, struct timeval *));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (select);
|
||||
#elif @HAVE_WINSOCK2_H@
|
||||
# undef select
|
||||
# define select select_used_without_requesting_gnulib_module_select
|
||||
#elif defined GNULIB_POSIXCHECK
|
||||
# undef select
|
||||
# if HAVE_RAW_DECL_SELECT
|
||||
_GL_WARN_ON_USE (select, "select is not always POSIX compliant - "
|
||||
"use gnulib module select for portability");
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
|
||||
#endif /* _@GUARD_PREFIX@_SYS_SELECT_H */
|
||||
#endif /* OSF/1 */
|
||||
205
lib/sys_time.in.h
Normal file
205
lib/sys_time.in.h
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/* Provide a more complete sys/time.h.
|
||||
|
||||
Copyright (C) 2007-2012 Free Software Foundation, Inc.
|
||||
|
||||
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, 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#if __GNUC__ >= 3
|
||||
@PRAGMA_SYSTEM_HEADER@
|
||||
#endif
|
||||
@PRAGMA_COLUMNS@
|
||||
|
||||
#if defined _@GUARD_PREFIX@_SYS_TIME_H
|
||||
|
||||
/* Simply delegate to the system's header, without adding anything. */
|
||||
# if @HAVE_SYS_TIME_H@
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
# define _@GUARD_PREFIX@_SYS_TIME_H
|
||||
|
||||
# if @HAVE_SYS_TIME_H@
|
||||
# @INCLUDE_NEXT@ @NEXT_SYS_TIME_H@
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
|
||||
/* On native Windows with MSVC, get the 'struct timeval' type.
|
||||
Also, on native Windows with a 64-bit time_t, where we are overriding the
|
||||
'struct timeval' type, get all declarations of system functions whose
|
||||
signature contains 'struct timeval'. */
|
||||
# if (defined _MSC_VER || @REPLACE_STRUCT_TIMEVAL@) && @HAVE_WINSOCK2_H@ && !defined _GL_INCLUDING_WINSOCK2_H
|
||||
# define _GL_INCLUDING_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
# undef _GL_INCLUDING_WINSOCK2_H
|
||||
# endif
|
||||
|
||||
/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */
|
||||
|
||||
/* The definition of _GL_ARG_NONNULL is copied here. */
|
||||
|
||||
/* The definition of _GL_WARN_ON_USE is copied here. */
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
# if !@HAVE_STRUCT_TIMEVAL@ || @REPLACE_STRUCT_TIMEVAL@
|
||||
|
||||
# if @REPLACE_STRUCT_TIMEVAL@
|
||||
# define timeval rpl_timeval
|
||||
# endif
|
||||
|
||||
# if !GNULIB_defined_struct_timeval
|
||||
struct timeval
|
||||
{
|
||||
time_t tv_sec;
|
||||
long int tv_usec;
|
||||
};
|
||||
# define GNULIB_defined_struct_timeval 1
|
||||
# endif
|
||||
|
||||
# endif
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
# if @GNULIB_GETTIMEOFDAY@
|
||||
# if @REPLACE_GETTIMEOFDAY@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef gettimeofday
|
||||
# define gettimeofday rpl_gettimeofday
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (gettimeofday, int,
|
||||
(struct timeval *restrict, void *restrict)
|
||||
_GL_ARG_NONNULL ((1)));
|
||||
_GL_CXXALIAS_RPL (gettimeofday, int,
|
||||
(struct timeval *restrict, void *restrict));
|
||||
# else
|
||||
# if !@HAVE_GETTIMEOFDAY@
|
||||
_GL_FUNCDECL_SYS (gettimeofday, int,
|
||||
(struct timeval *restrict, void *restrict)
|
||||
_GL_ARG_NONNULL ((1)));
|
||||
# endif
|
||||
/* Need to cast, because on glibc systems, by default, the second argument is
|
||||
struct timezone *. */
|
||||
_GL_CXXALIAS_SYS_CAST (gettimeofday, int,
|
||||
(struct timeval *restrict, void *restrict));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (gettimeofday);
|
||||
# elif defined GNULIB_POSIXCHECK
|
||||
# undef gettimeofday
|
||||
# if HAVE_RAW_DECL_GETTIMEOFDAY
|
||||
_GL_WARN_ON_USE (gettimeofday, "gettimeofday is unportable - "
|
||||
"use gnulib module gettimeofday for portability");
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Hide some function declarations from <winsock2.h>. */
|
||||
|
||||
# if defined _MSC_VER && @HAVE_WINSOCK2_H@
|
||||
# if !defined _@GUARD_PREFIX@_UNISTD_H
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef close
|
||||
# define close close_used_without_including_unistd_h
|
||||
# else
|
||||
_GL_WARN_ON_USE (close,
|
||||
"close() used without including <unistd.h>");
|
||||
# endif
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef gethostname
|
||||
# define gethostname gethostname_used_without_including_unistd_h
|
||||
# else
|
||||
_GL_WARN_ON_USE (gethostname,
|
||||
"gethostname() used without including <unistd.h>");
|
||||
# endif
|
||||
# endif
|
||||
# if !defined _@GUARD_PREFIX@_SYS_SOCKET_H
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef socket
|
||||
# define socket socket_used_without_including_sys_socket_h
|
||||
# undef connect
|
||||
# define connect connect_used_without_including_sys_socket_h
|
||||
# undef accept
|
||||
# define accept accept_used_without_including_sys_socket_h
|
||||
# undef bind
|
||||
# define bind bind_used_without_including_sys_socket_h
|
||||
# undef getpeername
|
||||
# define getpeername getpeername_used_without_including_sys_socket_h
|
||||
# undef getsockname
|
||||
# define getsockname getsockname_used_without_including_sys_socket_h
|
||||
# undef getsockopt
|
||||
# define getsockopt getsockopt_used_without_including_sys_socket_h
|
||||
# undef listen
|
||||
# define listen listen_used_without_including_sys_socket_h
|
||||
# undef recv
|
||||
# define recv recv_used_without_including_sys_socket_h
|
||||
# undef send
|
||||
# define send send_used_without_including_sys_socket_h
|
||||
# undef recvfrom
|
||||
# define recvfrom recvfrom_used_without_including_sys_socket_h
|
||||
# undef sendto
|
||||
# define sendto sendto_used_without_including_sys_socket_h
|
||||
# undef setsockopt
|
||||
# define setsockopt setsockopt_used_without_including_sys_socket_h
|
||||
# undef shutdown
|
||||
# define shutdown shutdown_used_without_including_sys_socket_h
|
||||
# else
|
||||
_GL_WARN_ON_USE (socket,
|
||||
"socket() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (connect,
|
||||
"connect() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (accept,
|
||||
"accept() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (bind,
|
||||
"bind() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (getpeername,
|
||||
"getpeername() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (getsockname,
|
||||
"getsockname() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (getsockopt,
|
||||
"getsockopt() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (listen,
|
||||
"listen() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (recv,
|
||||
"recv() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (send,
|
||||
"send() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (recvfrom,
|
||||
"recvfrom() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (sendto,
|
||||
"sendto() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (setsockopt,
|
||||
"setsockopt() used without including <sys/socket.h>");
|
||||
_GL_WARN_ON_USE (shutdown,
|
||||
"shutdown() used without including <sys/socket.h>");
|
||||
# endif
|
||||
# endif
|
||||
# if !defined _@GUARD_PREFIX@_SYS_SELECT_H
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef select
|
||||
# define select select_used_without_including_sys_select_h
|
||||
# else
|
||||
_GL_WARN_ON_USE (select,
|
||||
"select() used without including <sys/select.h>");
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif /* _@GUARD_PREFIX@_SYS_TIME_H */
|
||||
71
lib/timespec-add.c
Normal file
71
lib/timespec-add.c
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* Add two struct timespec values.
|
||||
|
||||
Copyright (C) 2011-2012 Free Software Foundation, Inc.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
/* Return the sum of two timespec values A and B. On overflow, return
|
||||
an extremal value. This assumes 0 <= tv_nsec <= 999999999. */
|
||||
|
||||
#include <config.h>
|
||||
#include "timespec.h"
|
||||
|
||||
#include "intprops.h"
|
||||
|
||||
struct timespec
|
||||
timespec_add (struct timespec a, struct timespec b)
|
||||
{
|
||||
struct timespec r;
|
||||
time_t rs = a.tv_sec;
|
||||
time_t bs = b.tv_sec;
|
||||
int ns = a.tv_nsec + b.tv_nsec;
|
||||
int nsd = ns - 1000000000;
|
||||
int rns = ns;
|
||||
|
||||
if (0 <= nsd)
|
||||
{
|
||||
rns = nsd;
|
||||
if (rs == TYPE_MAXIMUM (time_t))
|
||||
{
|
||||
if (0 <= bs)
|
||||
goto high_overflow;
|
||||
bs++;
|
||||
}
|
||||
else
|
||||
rs++;
|
||||
}
|
||||
|
||||
if (INT_ADD_OVERFLOW (rs, bs))
|
||||
{
|
||||
if (rs < 0)
|
||||
{
|
||||
rs = TYPE_MINIMUM (time_t);
|
||||
rns = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
high_overflow:
|
||||
rs = TYPE_MAXIMUM (time_t);
|
||||
rns = 999999999;
|
||||
}
|
||||
}
|
||||
else
|
||||
rs += bs;
|
||||
|
||||
r.tv_sec = rs;
|
||||
r.tv_nsec = rns;
|
||||
return r;
|
||||
}
|
||||
72
lib/timespec-sub.c
Normal file
72
lib/timespec-sub.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* Subtract two struct timespec values.
|
||||
|
||||
Copyright (C) 2011-2012 Free Software Foundation, Inc.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
/* Return the difference between two timespec values A and B. On
|
||||
overflow, return an extremal value. This assumes 0 <= tv_nsec <=
|
||||
999999999. */
|
||||
|
||||
#include <config.h>
|
||||
#include <config.h>
|
||||
#include "timespec.h"
|
||||
|
||||
#include "intprops.h"
|
||||
|
||||
struct timespec
|
||||
timespec_sub (struct timespec a, struct timespec b)
|
||||
{
|
||||
struct timespec r;
|
||||
time_t rs = a.tv_sec;
|
||||
time_t bs = b.tv_sec;
|
||||
int ns = a.tv_nsec - b.tv_nsec;
|
||||
int rns = ns;
|
||||
|
||||
if (ns < 0)
|
||||
{
|
||||
rns = ns + 1000000000;
|
||||
if (rs == TYPE_MINIMUM (time_t))
|
||||
{
|
||||
if (bs <= 0)
|
||||
goto low_overflow;
|
||||
bs--;
|
||||
}
|
||||
else
|
||||
rs--;
|
||||
}
|
||||
|
||||
if (INT_SUBTRACT_OVERFLOW (rs, bs))
|
||||
{
|
||||
if (rs < 0)
|
||||
{
|
||||
low_overflow:
|
||||
rs = TYPE_MINIMUM (time_t);
|
||||
rns = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rs = TYPE_MAXIMUM (time_t);
|
||||
rns = 999999999;
|
||||
}
|
||||
}
|
||||
else
|
||||
rs -= bs;
|
||||
|
||||
r.tv_sec = rs;
|
||||
r.tv_nsec = rns;
|
||||
return r;
|
||||
}
|
||||
82
lib/timespec.h
Normal file
82
lib/timespec.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/* timespec -- System time interface
|
||||
|
||||
Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2012 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if ! defined TIMESPEC_H
|
||||
# define TIMESPEC_H
|
||||
|
||||
# include <time.h>
|
||||
|
||||
/* Return negative, zero, positive if A < B, A == B, A > B, respectively.
|
||||
|
||||
For each time stamp T, this code assumes that either:
|
||||
|
||||
* T.tv_nsec is in the range 0..999999999; or
|
||||
* T.tv_sec corresponds to a valid leap second on a host that supports
|
||||
leap seconds, and T.tv_nsec is in the range 1000000000..1999999999; or
|
||||
* T.tv_sec is the minimum time_t value and T.tv_nsec is -1; or
|
||||
T.tv_sec is the maximum time_t value and T.tv_nsec is 2000000000.
|
||||
This allows for special struct timespec values that are less or
|
||||
greater than all possible valid time stamps.
|
||||
|
||||
In all these cases, it is safe to subtract two tv_nsec values and
|
||||
convert the result to integer without worrying about overflow on
|
||||
any platform of interest to the GNU project, since all such
|
||||
platforms have 32-bit int or wider.
|
||||
|
||||
Replacing "(int) (a.tv_nsec - b.tv_nsec)" with something like
|
||||
"a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec" would cause
|
||||
this function to work in some cases where the above assumption is
|
||||
violated, but not in all cases (e.g., a.tv_sec==1, a.tv_nsec==-2,
|
||||
b.tv_sec==0, b.tv_nsec==999999999) and is arguably not worth the
|
||||
extra instructions. Using a subtraction has the advantage of
|
||||
detecting some invalid cases on platforms that detect integer
|
||||
overflow.
|
||||
|
||||
The (int) cast avoids a gcc -Wconversion warning. */
|
||||
|
||||
static inline int
|
||||
timespec_cmp (struct timespec a, struct timespec b)
|
||||
{
|
||||
return (a.tv_sec < b.tv_sec ? -1
|
||||
: a.tv_sec > b.tv_sec ? 1
|
||||
: (int) (a.tv_nsec - b.tv_nsec));
|
||||
}
|
||||
|
||||
/* Return -1, 0, 1, depending on the sign of A. A.tv_nsec must be
|
||||
nonnegative. */
|
||||
static inline int
|
||||
timespec_sign (struct timespec a)
|
||||
{
|
||||
return a.tv_sec < 0 ? -1 : a.tv_sec || a.tv_nsec;
|
||||
}
|
||||
|
||||
struct timespec timespec_add (struct timespec, struct timespec);
|
||||
struct timespec timespec_sub (struct timespec, struct timespec);
|
||||
struct timespec dtotimespec (double);
|
||||
|
||||
/* Return an approximation to A, of type 'double'. */
|
||||
static inline double
|
||||
timespectod (struct timespec a)
|
||||
{
|
||||
return a.tv_sec + a.tv_nsec / 1e9;
|
||||
}
|
||||
|
||||
void gettime (struct timespec *);
|
||||
int settime (struct timespec const *);
|
||||
|
||||
#endif
|
||||
533
lib/utimens.c
Normal file
533
lib/utimens.c
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
/* Set file access and modification times.
|
||||
|
||||
Copyright (C) 2003-2012 Free Software Foundation, Inc.
|
||||
|
||||
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 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 <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
/* derived from a function in touch.c */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "utimens.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "stat-time.h"
|
||||
#include "timespec.h"
|
||||
|
||||
#if HAVE_UTIME_H
|
||||
# include <utime.h>
|
||||
#endif
|
||||
|
||||
/* Some systems (even some that do have <utime.h>) don't declare this
|
||||
structure anywhere. */
|
||||
#ifndef HAVE_STRUCT_UTIMBUF
|
||||
struct utimbuf
|
||||
{
|
||||
long actime;
|
||||
long modtime;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Avoid recursion with rpl_futimens or rpl_utimensat. */
|
||||
#undef futimens
|
||||
#undef utimensat
|
||||
|
||||
/* Solaris 9 mistakenly succeeds when given a non-directory with a
|
||||
trailing slash. Force the use of rpl_stat for a fix. */
|
||||
#ifndef REPLACE_FUNC_STAT_FILE
|
||||
# define REPLACE_FUNC_STAT_FILE 0
|
||||
#endif
|
||||
|
||||
#if HAVE_UTIMENSAT || HAVE_FUTIMENS
|
||||
/* Cache variables for whether the utimensat syscall works; used to
|
||||
avoid calling the syscall if we know it will just fail with ENOSYS,
|
||||
and to avoid unnecessary work in massaging timestamps if the
|
||||
syscall will work. Multiple variables are needed, to distinguish
|
||||
between the following scenarios on Linux:
|
||||
utimensat doesn't exist, or is in glibc but kernel 2.6.18 fails with ENOSYS
|
||||
kernel 2.6.22 and earlier rejects AT_SYMLINK_NOFOLLOW
|
||||
kernel 2.6.25 and earlier reject UTIME_NOW/UTIME_OMIT with non-zero tv_sec
|
||||
kernel 2.6.32 used with xfs or ntfs-3g fail to honor UTIME_OMIT
|
||||
utimensat completely works
|
||||
For each cache variable: 0 = unknown, 1 = yes, -1 = no. */
|
||||
static int utimensat_works_really;
|
||||
static int lutimensat_works_really;
|
||||
#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
|
||||
|
||||
/* Validate the requested timestamps. Return 0 if the resulting
|
||||
timespec can be used for utimensat (after possibly modifying it to
|
||||
work around bugs in utimensat). Return a positive value if the
|
||||
timespec needs further adjustment based on stat results: 1 if any
|
||||
adjustment is needed for utimes, and 2 if any adjustment is needed
|
||||
for Linux utimensat. Return -1, with errno set to EINVAL, if
|
||||
timespec is out of range. */
|
||||
static int
|
||||
validate_timespec (struct timespec timespec[2])
|
||||
{
|
||||
int result = 0;
|
||||
int utime_omit_count = 0;
|
||||
assert (timespec);
|
||||
if ((timespec[0].tv_nsec != UTIME_NOW
|
||||
&& timespec[0].tv_nsec != UTIME_OMIT
|
||||
&& (timespec[0].tv_nsec < 0 || 1000000000 <= timespec[0].tv_nsec))
|
||||
|| (timespec[1].tv_nsec != UTIME_NOW
|
||||
&& timespec[1].tv_nsec != UTIME_OMIT
|
||||
&& (timespec[1].tv_nsec < 0 || 1000000000 <= timespec[1].tv_nsec)))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
/* Work around Linux kernel 2.6.25 bug, where utimensat fails with
|
||||
EINVAL if tv_sec is not 0 when using the flag values of tv_nsec.
|
||||
Flag a Linux kernel 2.6.32 bug, where an mtime of UTIME_OMIT
|
||||
fails to bump ctime. */
|
||||
if (timespec[0].tv_nsec == UTIME_NOW
|
||||
|| timespec[0].tv_nsec == UTIME_OMIT)
|
||||
{
|
||||
timespec[0].tv_sec = 0;
|
||||
result = 1;
|
||||
if (timespec[0].tv_nsec == UTIME_OMIT)
|
||||
utime_omit_count++;
|
||||
}
|
||||
if (timespec[1].tv_nsec == UTIME_NOW
|
||||
|| timespec[1].tv_nsec == UTIME_OMIT)
|
||||
{
|
||||
timespec[1].tv_sec = 0;
|
||||
result = 1;
|
||||
if (timespec[1].tv_nsec == UTIME_OMIT)
|
||||
utime_omit_count++;
|
||||
}
|
||||
return result + (utime_omit_count == 1);
|
||||
}
|
||||
|
||||
/* Normalize any UTIME_NOW or UTIME_OMIT values in *TS, using stat
|
||||
buffer STATBUF to obtain the current timestamps of the file. If
|
||||
both times are UTIME_NOW, set *TS to NULL (as this can avoid some
|
||||
permissions issues). If both times are UTIME_OMIT, return true
|
||||
(nothing further beyond the prior collection of STATBUF is
|
||||
necessary); otherwise return false. */
|
||||
static bool
|
||||
update_timespec (struct stat const *statbuf, struct timespec *ts[2])
|
||||
{
|
||||
struct timespec *timespec = *ts;
|
||||
if (timespec[0].tv_nsec == UTIME_OMIT
|
||||
&& timespec[1].tv_nsec == UTIME_OMIT)
|
||||
return true;
|
||||
if (timespec[0].tv_nsec == UTIME_NOW
|
||||
&& timespec[1].tv_nsec == UTIME_NOW)
|
||||
{
|
||||
*ts = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timespec[0].tv_nsec == UTIME_OMIT)
|
||||
timespec[0] = get_stat_atime (statbuf);
|
||||
else if (timespec[0].tv_nsec == UTIME_NOW)
|
||||
gettime (×pec[0]);
|
||||
|
||||
if (timespec[1].tv_nsec == UTIME_OMIT)
|
||||
timespec[1] = get_stat_mtime (statbuf);
|
||||
else if (timespec[1].tv_nsec == UTIME_NOW)
|
||||
gettime (×pec[1]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
|
||||
TIMESPEC[0] and TIMESPEC[1], respectively.
|
||||
FD must be either negative -- in which case it is ignored --
|
||||
or a file descriptor that is open on FILE.
|
||||
If FD is nonnegative, then FILE can be NULL, which means
|
||||
use just futimes (or equivalent) instead of utimes (or equivalent),
|
||||
and fail if on an old system without futimes (or equivalent).
|
||||
If TIMESPEC is null, set the time stamps to the current time.
|
||||
Return 0 on success, -1 (setting errno) on failure. */
|
||||
|
||||
int
|
||||
fdutimens (int fd, char const *file, struct timespec const timespec[2])
|
||||
{
|
||||
struct timespec adjusted_timespec[2];
|
||||
struct timespec *ts = timespec ? adjusted_timespec : NULL;
|
||||
int adjustment_needed = 0;
|
||||
struct stat st;
|
||||
|
||||
if (ts)
|
||||
{
|
||||
adjusted_timespec[0] = timespec[0];
|
||||
adjusted_timespec[1] = timespec[1];
|
||||
adjustment_needed = validate_timespec (ts);
|
||||
}
|
||||
if (adjustment_needed < 0)
|
||||
return -1;
|
||||
|
||||
/* Require that at least one of FD or FILE are potentially valid, to avoid
|
||||
a Linux bug where futimens (AT_FDCWD, NULL) changes "." rather
|
||||
than failing. */
|
||||
if (fd < 0 && !file)
|
||||
{
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Some Linux-based NFS clients are buggy, and mishandle time stamps
|
||||
of files in NFS file systems in some cases. We have no
|
||||
configure-time test for this, but please see
|
||||
<http://bugs.gentoo.org/show_bug.cgi?id=132673> for references to
|
||||
some of the problems with Linux 2.6.16. If this affects you,
|
||||
compile with -DHAVE_BUGGY_NFS_TIME_STAMPS; this is reported to
|
||||
help in some cases, albeit at a cost in performance. But you
|
||||
really should upgrade your kernel to a fixed version, since the
|
||||
problem affects many applications. */
|
||||
|
||||
#if HAVE_BUGGY_NFS_TIME_STAMPS
|
||||
if (fd < 0)
|
||||
sync ();
|
||||
else
|
||||
fsync (fd);
|
||||
#endif
|
||||
|
||||
/* POSIX 2008 added two interfaces to set file timestamps with
|
||||
nanosecond resolution; newer Linux implements both functions via
|
||||
a single syscall. We provide a fallback for ENOSYS (for example,
|
||||
compiling against Linux 2.6.25 kernel headers and glibc 2.7, but
|
||||
running on Linux 2.6.18 kernel). */
|
||||
#if HAVE_UTIMENSAT || HAVE_FUTIMENS
|
||||
if (0 <= utimensat_works_really)
|
||||
{
|
||||
int result;
|
||||
# if __linux__
|
||||
/* As recently as Linux kernel 2.6.32 (Dec 2009), several file
|
||||
systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
|
||||
but work if both times are either explicitly specified or
|
||||
UTIME_NOW. Work around it with a preparatory [f]stat prior
|
||||
to calling futimens/utimensat; fortunately, there is not much
|
||||
timing impact due to the extra syscall even on file systems
|
||||
where UTIME_OMIT would have worked. FIXME: Simplify this in
|
||||
2012, when file system bugs are no longer common. */
|
||||
if (adjustment_needed == 2)
|
||||
{
|
||||
if (fd < 0 ? stat (file, &st) : fstat (fd, &st))
|
||||
return -1;
|
||||
if (ts[0].tv_nsec == UTIME_OMIT)
|
||||
ts[0] = get_stat_atime (&st);
|
||||
else if (ts[1].tv_nsec == UTIME_OMIT)
|
||||
ts[1] = get_stat_mtime (&st);
|
||||
/* Note that st is good, in case utimensat gives ENOSYS. */
|
||||
adjustment_needed++;
|
||||
}
|
||||
# endif /* __linux__ */
|
||||
# if HAVE_UTIMENSAT
|
||||
if (fd < 0)
|
||||
{
|
||||
result = utimensat (AT_FDCWD, file, ts, 0);
|
||||
# ifdef __linux__
|
||||
/* Work around a kernel bug:
|
||||
http://bugzilla.redhat.com/442352
|
||||
http://bugzilla.redhat.com/449910
|
||||
It appears that utimensat can mistakenly return 280 rather
|
||||
than -1 upon ENOSYS failure.
|
||||
FIXME: remove in 2010 or whenever the offending kernels
|
||||
are no longer in common use. */
|
||||
if (0 < result)
|
||||
errno = ENOSYS;
|
||||
# endif /* __linux__ */
|
||||
if (result == 0 || errno != ENOSYS)
|
||||
{
|
||||
utimensat_works_really = 1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
# endif /* HAVE_UTIMENSAT */
|
||||
# if HAVE_FUTIMENS
|
||||
if (0 <= fd)
|
||||
{
|
||||
result = futimens (fd, ts);
|
||||
# ifdef __linux__
|
||||
/* Work around the same bug as above. */
|
||||
if (0 < result)
|
||||
errno = ENOSYS;
|
||||
# endif /* __linux__ */
|
||||
if (result == 0 || errno != ENOSYS)
|
||||
{
|
||||
utimensat_works_really = 1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
# endif /* HAVE_FUTIMENS */
|
||||
}
|
||||
utimensat_works_really = -1;
|
||||
lutimensat_works_really = -1;
|
||||
#endif /* HAVE_UTIMENSAT || HAVE_FUTIMENS */
|
||||
|
||||
/* The platform lacks an interface to set file timestamps with
|
||||
nanosecond resolution, so do the best we can, discarding any
|
||||
fractional part of the timestamp. */
|
||||
|
||||
if (adjustment_needed || (REPLACE_FUNC_STAT_FILE && fd < 0))
|
||||
{
|
||||
if (adjustment_needed != 3
|
||||
&& (fd < 0 ? stat (file, &st) : fstat (fd, &st)))
|
||||
return -1;
|
||||
if (ts && update_timespec (&st, &ts))
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
#if HAVE_FUTIMESAT || HAVE_WORKING_UTIMES
|
||||
struct timeval timeval[2];
|
||||
struct timeval *t;
|
||||
if (ts)
|
||||
{
|
||||
timeval[0].tv_sec = ts[0].tv_sec;
|
||||
timeval[0].tv_usec = ts[0].tv_nsec / 1000;
|
||||
timeval[1].tv_sec = ts[1].tv_sec;
|
||||
timeval[1].tv_usec = ts[1].tv_nsec / 1000;
|
||||
t = timeval;
|
||||
}
|
||||
else
|
||||
t = NULL;
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
# if HAVE_FUTIMESAT
|
||||
return futimesat (AT_FDCWD, file, t);
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If futimesat or futimes fails here, don't try to speed things
|
||||
up by returning right away. glibc can incorrectly fail with
|
||||
errno == ENOENT if /proc isn't mounted. Also, Mandrake 10.0
|
||||
in high security mode doesn't allow ordinary users to read
|
||||
/proc/self, so glibc incorrectly fails with errno == EACCES.
|
||||
If errno == EIO, EPERM, or EROFS, it's probably safe to fail
|
||||
right away, but these cases are rare enough that they're not
|
||||
worth optimizing, and who knows what other messed-up systems
|
||||
are out there? So play it safe and fall back on the code
|
||||
below. */
|
||||
|
||||
# if (HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) || HAVE_FUTIMES
|
||||
# if HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG
|
||||
# undef futimes
|
||||
# define futimes(fd, t) futimesat (fd, NULL, t)
|
||||
# endif
|
||||
if (futimes (fd, t) == 0)
|
||||
{
|
||||
# if __linux__ && __GLIBC__
|
||||
/* Work around a longstanding glibc bug, still present as
|
||||
of 2010-12-27. On older Linux kernels that lack both
|
||||
utimensat and utimes, glibc's futimes rounds instead of
|
||||
truncating when falling back on utime. The same bug
|
||||
occurs in futimesat with a null 2nd arg. */
|
||||
if (t)
|
||||
{
|
||||
bool abig = 500000 <= t[0].tv_usec;
|
||||
bool mbig = 500000 <= t[1].tv_usec;
|
||||
if ((abig | mbig) && fstat (fd, &st) == 0)
|
||||
{
|
||||
/* If these two subtractions overflow, they'll
|
||||
track the overflows inside the buggy glibc. */
|
||||
time_t adiff = st.st_atime - t[0].tv_sec;
|
||||
time_t mdiff = st.st_mtime - t[1].tv_sec;
|
||||
|
||||
struct timeval *tt = NULL;
|
||||
struct timeval truncated_timeval[2];
|
||||
truncated_timeval[0] = t[0];
|
||||
truncated_timeval[1] = t[1];
|
||||
if (abig && adiff == 1 && get_stat_atime_ns (&st) == 0)
|
||||
{
|
||||
tt = truncated_timeval;
|
||||
tt[0].tv_usec = 0;
|
||||
}
|
||||
if (mbig && mdiff == 1 && get_stat_mtime_ns (&st) == 0)
|
||||
{
|
||||
tt = truncated_timeval;
|
||||
tt[1].tv_usec = 0;
|
||||
}
|
||||
if (tt)
|
||||
futimes (fd, tt);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif /* HAVE_FUTIMESAT || HAVE_WORKING_UTIMES */
|
||||
|
||||
if (!file)
|
||||
{
|
||||
#if ! ((HAVE_FUTIMESAT && !FUTIMESAT_NULL_BUG) \
|
||||
|| (HAVE_WORKING_UTIMES && HAVE_FUTIMES))
|
||||
errno = ENOSYS;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if HAVE_WORKING_UTIMES
|
||||
return utimes (file, t);
|
||||
#else
|
||||
{
|
||||
struct utimbuf utimbuf;
|
||||
struct utimbuf *ut;
|
||||
if (ts)
|
||||
{
|
||||
utimbuf.actime = ts[0].tv_sec;
|
||||
utimbuf.modtime = ts[1].tv_sec;
|
||||
ut = &utimbuf;
|
||||
}
|
||||
else
|
||||
ut = NULL;
|
||||
|
||||
return utime (file, ut);
|
||||
}
|
||||
#endif /* !HAVE_WORKING_UTIMES */
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the access and modification time stamps of FILE to be
|
||||
TIMESPEC[0] and TIMESPEC[1], respectively. */
|
||||
int
|
||||
utimens (char const *file, struct timespec const timespec[2])
|
||||
{
|
||||
return fdutimens (-1, file, timespec);
|
||||
}
|
||||
|
||||
/* Set the access and modification time stamps of FILE to be
|
||||
TIMESPEC[0] and TIMESPEC[1], respectively, without dereferencing
|
||||
symlinks. Fail with ENOSYS if the platform does not support
|
||||
changing symlink timestamps, but FILE was a symlink. */
|
||||
int
|
||||
lutimens (char const *file, struct timespec const timespec[2])
|
||||
{
|
||||
struct timespec adjusted_timespec[2];
|
||||
struct timespec *ts = timespec ? adjusted_timespec : NULL;
|
||||
int adjustment_needed = 0;
|
||||
struct stat st;
|
||||
|
||||
if (ts)
|
||||
{
|
||||
adjusted_timespec[0] = timespec[0];
|
||||
adjusted_timespec[1] = timespec[1];
|
||||
adjustment_needed = validate_timespec (ts);
|
||||
}
|
||||
if (adjustment_needed < 0)
|
||||
return -1;
|
||||
|
||||
/* The Linux kernel did not support symlink timestamps until
|
||||
utimensat, in version 2.6.22, so we don't need to mimic
|
||||
fdutimens' worry about buggy NFS clients. But we do have to
|
||||
worry about bogus return values. */
|
||||
|
||||
#if HAVE_UTIMENSAT
|
||||
if (0 <= lutimensat_works_really)
|
||||
{
|
||||
int result;
|
||||
# if __linux__
|
||||
/* As recently as Linux kernel 2.6.32 (Dec 2009), several file
|
||||
systems (xfs, ntfs-3g) have bugs with a single UTIME_OMIT,
|
||||
but work if both times are either explicitly specified or
|
||||
UTIME_NOW. Work around it with a preparatory lstat prior to
|
||||
calling utimensat; fortunately, there is not much timing
|
||||
impact due to the extra syscall even on file systems where
|
||||
UTIME_OMIT would have worked. FIXME: Simplify this in 2012,
|
||||
when file system bugs are no longer common. */
|
||||
if (adjustment_needed == 2)
|
||||
{
|
||||
if (lstat (file, &st))
|
||||
return -1;
|
||||
if (ts[0].tv_nsec == UTIME_OMIT)
|
||||
ts[0] = get_stat_atime (&st);
|
||||
else if (ts[1].tv_nsec == UTIME_OMIT)
|
||||
ts[1] = get_stat_mtime (&st);
|
||||
/* Note that st is good, in case utimensat gives ENOSYS. */
|
||||
adjustment_needed++;
|
||||
}
|
||||
# endif /* __linux__ */
|
||||
result = utimensat (AT_FDCWD, file, ts, AT_SYMLINK_NOFOLLOW);
|
||||
# ifdef __linux__
|
||||
/* Work around a kernel bug:
|
||||
http://bugzilla.redhat.com/442352
|
||||
http://bugzilla.redhat.com/449910
|
||||
It appears that utimensat can mistakenly return 280 rather
|
||||
than -1 upon ENOSYS failure.
|
||||
FIXME: remove in 2010 or whenever the offending kernels
|
||||
are no longer in common use. */
|
||||
if (0 < result)
|
||||
errno = ENOSYS;
|
||||
# endif
|
||||
if (result == 0 || errno != ENOSYS)
|
||||
{
|
||||
utimensat_works_really = 1;
|
||||
lutimensat_works_really = 1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
lutimensat_works_really = -1;
|
||||
#endif /* HAVE_UTIMENSAT */
|
||||
|
||||
/* The platform lacks an interface to set file timestamps with
|
||||
nanosecond resolution, so do the best we can, discarding any
|
||||
fractional part of the timestamp. */
|
||||
|
||||
if (adjustment_needed || REPLACE_FUNC_STAT_FILE)
|
||||
{
|
||||
if (adjustment_needed != 3 && lstat (file, &st))
|
||||
return -1;
|
||||
if (ts && update_timespec (&st, &ts))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* On Linux, lutimes is a thin wrapper around utimensat, so there is
|
||||
no point trying lutimes if utimensat failed with ENOSYS. */
|
||||
#if HAVE_LUTIMES && !HAVE_UTIMENSAT
|
||||
{
|
||||
struct timeval timeval[2];
|
||||
struct timeval *t;
|
||||
int result;
|
||||
if (ts)
|
||||
{
|
||||
timeval[0].tv_sec = ts[0].tv_sec;
|
||||
timeval[0].tv_usec = ts[0].tv_nsec / 1000;
|
||||
timeval[1].tv_sec = ts[1].tv_sec;
|
||||
timeval[1].tv_usec = ts[1].tv_nsec / 1000;
|
||||
t = timeval;
|
||||
}
|
||||
else
|
||||
t = NULL;
|
||||
|
||||
result = lutimes (file, t);
|
||||
if (result == 0 || errno != ENOSYS)
|
||||
return result;
|
||||
}
|
||||
#endif /* HAVE_LUTIMES && !HAVE_UTIMENSAT */
|
||||
|
||||
/* Out of luck for symlinks, but we still handle regular files. */
|
||||
if (!(adjustment_needed || REPLACE_FUNC_STAT_FILE) && lstat (file, &st))
|
||||
return -1;
|
||||
if (!S_ISLNK (st.st_mode))
|
||||
return fdutimens (-1, file, ts);
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
19
lib/utimens.h
Normal file
19
lib/utimens.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include <time.h>
|
||||
int fdutimens (int, char const *, struct timespec const [2]);
|
||||
int utimens (char const *, struct timespec const [2]);
|
||||
int lutimens (char const *, struct timespec const [2]);
|
||||
|
||||
#if GNULIB_FDUTIMENSAT
|
||||
# include <fcntl.h>
|
||||
# include <sys/stat.h>
|
||||
|
||||
int fdutimensat (int fd, int dir, char const *name, struct timespec const [2],
|
||||
int atflag);
|
||||
|
||||
/* Using this function makes application code slightly more readable. */
|
||||
static inline int
|
||||
lutimensat (int dir, char const *file, struct timespec const times[2])
|
||||
{
|
||||
return utimensat (dir, file, times, AT_SYMLINK_NOFOLLOW);
|
||||
}
|
||||
#endif
|
||||
31
m4/clock_time.m4
Normal file
31
m4/clock_time.m4
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# clock_time.m4 serial 10
|
||||
dnl Copyright (C) 2002-2006, 2009-2012 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# Check for clock_gettime and clock_settime, and set LIB_CLOCK_GETTIME.
|
||||
# For a program named, say foo, you should add a line like the following
|
||||
# in the corresponding Makefile.am file:
|
||||
# foo_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
|
||||
|
||||
AC_DEFUN([gl_CLOCK_TIME],
|
||||
[
|
||||
dnl Persuade glibc and Solaris <time.h> to declare these functions.
|
||||
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
|
||||
|
||||
# Solaris 2.5.1 needs -lposix4 to get the clock_gettime function.
|
||||
# Solaris 7 prefers the library name -lrt to the obsolescent name -lposix4.
|
||||
|
||||
# Save and restore LIBS so e.g., -lrt, isn't added to it. Otherwise, *all*
|
||||
# programs in the package would end up linked with that potentially-shared
|
||||
# library, inducing unnecessary run-time overhead.
|
||||
LIB_CLOCK_GETTIME=
|
||||
AC_SUBST([LIB_CLOCK_GETTIME])
|
||||
gl_saved_libs=$LIBS
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt posix4],
|
||||
[test "$ac_cv_search_clock_gettime" = "none required" ||
|
||||
LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime])
|
||||
AC_CHECK_FUNCS([clock_gettime clock_settime])
|
||||
LIBS=$gl_saved_libs
|
||||
])
|
||||
13
m4/gettime.m4
Normal file
13
m4/gettime.m4
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# gettime.m4 serial 8
|
||||
dnl Copyright (C) 2002, 2004-2006, 2009-2012 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
AC_DEFUN([gl_GETTIME],
|
||||
[
|
||||
dnl Prerequisites of lib/gettime.c.
|
||||
AC_REQUIRE([gl_CLOCK_TIME])
|
||||
AC_REQUIRE([gl_TIMESPEC])
|
||||
AC_CHECK_FUNCS_ONCE([gettimeofday nanotime])
|
||||
])
|
||||
140
m4/gettimeofday.m4
Normal file
140
m4/gettimeofday.m4
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
# serial 20
|
||||
|
||||
# Copyright (C) 2001-2003, 2005, 2007, 2009-2012 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_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
|
||||
AC_CHECK_FUNCS_ONCE([gettimeofday])
|
||||
|
||||
gl_gettimeofday_timezone=void
|
||||
if test $ac_cv_func_gettimeofday != yes; then
|
||||
HAVE_GETTIMEOFDAY=0
|
||||
else
|
||||
gl_FUNC_GETTIMEOFDAY_CLOBBER
|
||||
AC_CACHE_CHECK([for gettimeofday with POSIX signature],
|
||||
[gl_cv_func_gettimeofday_posix_signature],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <sys/time.h>
|
||||
struct timeval c;
|
||||
int gettimeofday (struct timeval *restrict, void *restrict);
|
||||
]],
|
||||
[[/* glibc uses struct timezone * rather than the POSIX void *
|
||||
if _GNU_SOURCE is defined. However, since the only portable
|
||||
use of gettimeofday uses NULL as the second parameter, and
|
||||
since the glibc definition is actually more typesafe, it is
|
||||
not worth wrapping this to get a compliant signature. */
|
||||
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],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <sys/time.h>
|
||||
int gettimeofday (struct timeval *restrict, struct timezone *restrict);
|
||||
]])],
|
||||
[gl_cv_func_gettimeofday_posix_signature=almost],
|
||||
[gl_cv_func_gettimeofday_posix_signature=no])])])
|
||||
if test $gl_cv_func_gettimeofday_posix_signature = almost; then
|
||||
gl_gettimeofday_timezone='struct timezone'
|
||||
elif test $gl_cv_func_gettimeofday_posix_signature != yes; then
|
||||
REPLACE_GETTIMEOFDAY=1
|
||||
fi
|
||||
dnl If we override 'struct timeval', we also have to override gettimeofday.
|
||||
if test $REPLACE_STRUCT_TIMEVAL = 1; then
|
||||
REPLACE_GETTIMEOFDAY=1
|
||||
fi
|
||||
m4_ifdef([gl_FUNC_TZSET_CLOBBER], [
|
||||
gl_FUNC_TZSET_CLOBBER
|
||||
case "$gl_cv_func_tzset_clobber" in
|
||||
*yes)
|
||||
REPLACE_GETTIMEOFDAY=1
|
||||
gl_GETTIMEOFDAY_REPLACE_LOCALTIME
|
||||
AC_DEFINE([tzset], [rpl_tzset],
|
||||
[Define to rpl_tzset if the wrapper function should be used.])
|
||||
AC_DEFINE([TZSET_CLOBBERS_LOCALTIME], [1],
|
||||
[Define if tzset clobbers localtime's static buffer.])
|
||||
;;
|
||||
esac
|
||||
])
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([GETTIMEOFDAY_TIMEZONE], [$gl_gettimeofday_timezone],
|
||||
[Define this to 'void' or 'struct timezone' to match the system's
|
||||
declaration of the second argument to gettimeofday.])
|
||||
])
|
||||
|
||||
|
||||
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_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
|
||||
|
||||
AC_CACHE_CHECK([whether gettimeofday clobbers localtime buffer],
|
||||
[gl_cv_func_gettimeofday_clobber],
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
]],
|
||||
[[
|
||||
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],
|
||||
[# When cross-compiling:
|
||||
case "$host_os" in
|
||||
# Guess all is fine on glibc systems.
|
||||
*-gnu*) gl_cv_func_gettimeofday_clobber="guessing no" ;;
|
||||
# If we don't know, assume the worst.
|
||||
*) gl_cv_func_gettimeofday_clobber="guessing yes" ;;
|
||||
esac
|
||||
])])
|
||||
|
||||
case "$gl_cv_func_gettimeofday_clobber" in
|
||||
*yes)
|
||||
REPLACE_GETTIMEOFDAY=1
|
||||
gl_GETTIMEOFDAY_REPLACE_LOCALTIME
|
||||
AC_DEFINE([GETTIMEOFDAY_CLOBBERS_LOCALTIME], [1],
|
||||
[Define if gettimeofday clobbers the localtime buffer.])
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_GETTIMEOFDAY_REPLACE_LOCALTIME], [
|
||||
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])
|
||||
])
|
||||
31
m4/pselect.m4
Normal file
31
m4/pselect.m4
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# pselect.m4
|
||||
dnl Copyright (C) 2011-2012 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
AC_DEFUN([gl_FUNC_PSELECT],
|
||||
[
|
||||
AC_REQUIRE([gl_HEADER_SYS_SELECT])
|
||||
AC_REQUIRE([AC_C_RESTRICT])
|
||||
AC_CHECK_FUNCS_ONCE([pselect])
|
||||
|
||||
if test $ac_cv_func_pselect = yes; then
|
||||
AC_CACHE_CHECK([whether signature of pselect conforms to POSIX],
|
||||
gl_cv_sig_pselect,
|
||||
[AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#include <sys/select.h>
|
||||
]],
|
||||
[[int (*p) (int, fd_set *, fd_set *, fd_set *restrict,
|
||||
struct timespec const *restrict,
|
||||
sigset_t const *restrict) = pselect;
|
||||
return !p;]])],
|
||||
[gl_cv_sig_pselect=yes],
|
||||
[gl_cv_sig_pselect=no])])
|
||||
fi
|
||||
|
||||
if test $ac_cv_func_pselect = no || test $gl_cv_sig_pselect = no; then
|
||||
REPLACE_PSELECT=1
|
||||
fi
|
||||
])
|
||||
85
m4/stat-time.m4
Normal file
85
m4/stat-time.m4
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
# Checks for stat-related time functions.
|
||||
|
||||
# Copyright (C) 1998-1999, 2001, 2003, 2005-2007, 2009-2012 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 Paul Eggert.
|
||||
|
||||
# st_atim.tv_nsec - Linux, Solaris, Cygwin
|
||||
# st_atimespec.tv_nsec - FreeBSD, NetBSD, if ! defined _POSIX_SOURCE
|
||||
# st_atimensec - FreeBSD, NetBSD, if defined _POSIX_SOURCE
|
||||
# st_atim.st__tim.tv_nsec - UnixWare (at least 2.1.2 through 7.1)
|
||||
|
||||
# st_birthtimespec - FreeBSD, NetBSD (hidden on OpenBSD 3.9, anyway)
|
||||
# st_birthtim - Cygwin 1.7.0+
|
||||
|
||||
AC_DEFUN([gl_STAT_TIME],
|
||||
[
|
||||
AC_REQUIRE([AC_C_INLINE])
|
||||
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h])
|
||||
|
||||
AC_CHECK_MEMBERS([struct stat.st_atim.tv_nsec],
|
||||
[AC_CACHE_CHECK([whether struct stat.st_atim is of type struct timespec],
|
||||
[ac_cv_typeof_struct_stat_st_atim_is_struct_timespec],
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
struct timespec ts;
|
||||
struct stat st;
|
||||
]],
|
||||
[[
|
||||
st.st_atim = ts;
|
||||
]])],
|
||||
[ac_cv_typeof_struct_stat_st_atim_is_struct_timespec=yes],
|
||||
[ac_cv_typeof_struct_stat_st_atim_is_struct_timespec=no])])
|
||||
if test $ac_cv_typeof_struct_stat_st_atim_is_struct_timespec = yes; then
|
||||
AC_DEFINE([TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC], [1],
|
||||
[Define to 1 if the type of the st_atim member of a struct stat is
|
||||
struct timespec.])
|
||||
fi],
|
||||
[AC_CHECK_MEMBERS([struct stat.st_atimespec.tv_nsec], [],
|
||||
[AC_CHECK_MEMBERS([struct stat.st_atimensec], [],
|
||||
[AC_CHECK_MEMBERS([struct stat.st_atim.st__tim.tv_nsec], [], [],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/stat.h>])],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/stat.h>])],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/stat.h>])],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/stat.h>])
|
||||
])
|
||||
|
||||
# Check for st_birthtime, a feature from UFS2 (FreeBSD, NetBSD, OpenBSD, etc.)
|
||||
# and NTFS (Cygwin).
|
||||
# There was a time when this field was named st_createtime (21 June
|
||||
# 2002 to 16 July 2002) But that window is very small and applied only
|
||||
# to development code, so systems still using that configuration are
|
||||
# not supported. See revisions 1.10 and 1.11 of FreeBSD's
|
||||
# src/sys/ufs/ufs/dinode.h.
|
||||
#
|
||||
AC_DEFUN([gl_STAT_BIRTHTIME],
|
||||
[
|
||||
AC_REQUIRE([AC_C_INLINE])
|
||||
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h])
|
||||
AC_CHECK_MEMBERS([struct stat.st_birthtimespec.tv_nsec], [],
|
||||
[AC_CHECK_MEMBERS([struct stat.st_birthtimensec], [],
|
||||
[AC_CHECK_MEMBERS([struct stat.st_birthtim.tv_nsec], [], [],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/stat.h>])],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/stat.h>])],
|
||||
[#include <sys/types.h>
|
||||
#include <sys/stat.h>])
|
||||
])
|
||||
95
m4/sys_select_h.m4
Normal file
95
m4/sys_select_h.m4
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# sys_select_h.m4 serial 20
|
||||
dnl Copyright (C) 2006-2012 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
AC_DEFUN([gl_HEADER_SYS_SELECT],
|
||||
[
|
||||
AC_REQUIRE([AC_C_RESTRICT])
|
||||
AC_REQUIRE([gl_SYS_SELECT_H_DEFAULTS])
|
||||
AC_CACHE_CHECK([whether <sys/select.h> is self-contained],
|
||||
[gl_cv_header_sys_select_h_selfcontained],
|
||||
[
|
||||
dnl Test against two bugs:
|
||||
dnl 1. On many platforms, <sys/select.h> assumes prior inclusion of
|
||||
dnl <sys/types.h>.
|
||||
dnl 2. On OSF/1 4.0, <sys/select.h> provides only a forward declaration
|
||||
dnl of 'struct timeval', and no definition of this type.
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/select.h>]],
|
||||
[[struct timeval b;]])],
|
||||
[gl_cv_header_sys_select_h_selfcontained=yes],
|
||||
[gl_cv_header_sys_select_h_selfcontained=no])
|
||||
dnl Test against another bug:
|
||||
dnl 3. On Solaris 10, <sys/select.h> provides an FD_ZERO implementation
|
||||
dnl that relies on memset(), but without including <string.h>.
|
||||
if test $gl_cv_header_sys_select_h_selfcontained = yes; then
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <sys/select.h>]],
|
||||
[[int memset; int bzero;]])
|
||||
],
|
||||
[AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <sys/select.h>]], [[
|
||||
#undef memset
|
||||
#define memset nonexistent_memset
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
void *memset (void *, int, unsigned long);
|
||||
#undef bzero
|
||||
#define bzero nonexistent_bzero
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
void bzero (void *, unsigned long);
|
||||
fd_set fds;
|
||||
FD_ZERO (&fds);
|
||||
]])
|
||||
],
|
||||
[],
|
||||
[gl_cv_header_sys_select_h_selfcontained=no])
|
||||
])
|
||||
fi
|
||||
])
|
||||
dnl <sys/select.h> is always overridden, because of GNULIB_POSIXCHECK.
|
||||
gl_CHECK_NEXT_HEADERS([sys/select.h])
|
||||
if test $ac_cv_header_sys_select_h = yes; then
|
||||
HAVE_SYS_SELECT_H=1
|
||||
else
|
||||
HAVE_SYS_SELECT_H=0
|
||||
fi
|
||||
AC_SUBST([HAVE_SYS_SELECT_H])
|
||||
gl_PREREQ_SYS_H_WINSOCK2
|
||||
|
||||
dnl Check for declarations of anything we want to poison if the
|
||||
dnl corresponding gnulib module is not in use.
|
||||
gl_WARN_ON_USE_PREPARE([[
|
||||
/* Some systems require prerequisite headers. */
|
||||
#include <sys/types.h>
|
||||
#if !(defined __GLIBC__ && !defined __UCLIBC__) && HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#include <sys/select.h>
|
||||
]], [pselect select])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_SYS_SELECT_MODULE_INDICATOR],
|
||||
[
|
||||
dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
|
||||
AC_REQUIRE([gl_SYS_SELECT_H_DEFAULTS])
|
||||
gl_MODULE_INDICATOR_SET_VARIABLE([$1])
|
||||
dnl Define it also as a C macro, for the benefit of the unit tests.
|
||||
gl_MODULE_INDICATOR_FOR_TESTS([$1])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_SYS_SELECT_H_DEFAULTS],
|
||||
[
|
||||
GNULIB_PSELECT=0; AC_SUBST([GNULIB_PSELECT])
|
||||
GNULIB_SELECT=0; AC_SUBST([GNULIB_SELECT])
|
||||
dnl Assume proper GNU behavior unless another module says otherwise.
|
||||
HAVE_PSELECT=1; AC_SUBST([HAVE_PSELECT])
|
||||
REPLACE_PSELECT=0; AC_SUBST([REPLACE_PSELECT])
|
||||
REPLACE_SELECT=0; AC_SUBST([REPLACE_SELECT])
|
||||
])
|
||||
177
m4/sys_socket_h.m4
Normal file
177
m4/sys_socket_h.m4
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
# sys_socket_h.m4 serial 22
|
||||
dnl Copyright (C) 2005-2012 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Simon Josefsson.
|
||||
|
||||
AC_DEFUN([gl_HEADER_SYS_SOCKET],
|
||||
[
|
||||
AC_REQUIRE([gl_SYS_SOCKET_H_DEFAULTS])
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([AC_C_INLINE])
|
||||
|
||||
dnl On OSF/1, the functions recv(), send(), recvfrom(), sendto() have
|
||||
dnl old-style declarations (with return type 'int' instead of 'ssize_t')
|
||||
dnl unless _POSIX_PII_SOCKET is defined.
|
||||
case "$host_os" in
|
||||
osf*)
|
||||
AC_DEFINE([_POSIX_PII_SOCKET], [1],
|
||||
[Define to 1 in order to get the POSIX compatible declarations
|
||||
of socket functions.])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_CACHE_CHECK([whether <sys/socket.h> is self-contained],
|
||||
[gl_cv_header_sys_socket_h_selfcontained],
|
||||
[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/socket.h>]], [[]])],
|
||||
[gl_cv_header_sys_socket_h_selfcontained=yes],
|
||||
[gl_cv_header_sys_socket_h_selfcontained=no])
|
||||
])
|
||||
if test $gl_cv_header_sys_socket_h_selfcontained = yes; then
|
||||
dnl If the shutdown function exists, <sys/socket.h> should define
|
||||
dnl SHUT_RD, SHUT_WR, SHUT_RDWR.
|
||||
AC_CHECK_FUNCS([shutdown])
|
||||
if test $ac_cv_func_shutdown = yes; then
|
||||
AC_CACHE_CHECK([whether <sys/socket.h> defines the SHUT_* macros],
|
||||
[gl_cv_header_sys_socket_h_shut],
|
||||
[
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <sys/socket.h>]],
|
||||
[[int a[] = { SHUT_RD, SHUT_WR, SHUT_RDWR };]])],
|
||||
[gl_cv_header_sys_socket_h_shut=yes],
|
||||
[gl_cv_header_sys_socket_h_shut=no])
|
||||
])
|
||||
if test $gl_cv_header_sys_socket_h_shut = no; then
|
||||
SYS_SOCKET_H='sys/socket.h'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# We need to check for ws2tcpip.h now.
|
||||
gl_PREREQ_SYS_H_SOCKET
|
||||
AC_CHECK_TYPES([struct sockaddr_storage, sa_family_t],,,[
|
||||
/* sys/types.h is not needed according to POSIX, but the
|
||||
sys/socket.h in i386-unknown-freebsd4.10 and
|
||||
powerpc-apple-darwin5.5 required it. */
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
if test $ac_cv_type_struct_sockaddr_storage = no; then
|
||||
HAVE_STRUCT_SOCKADDR_STORAGE=0
|
||||
fi
|
||||
if test $ac_cv_type_sa_family_t = no; then
|
||||
HAVE_SA_FAMILY_T=0
|
||||
fi
|
||||
if test $ac_cv_type_struct_sockaddr_storage != no; then
|
||||
AC_CHECK_MEMBERS([struct sockaddr_storage.ss_family],
|
||||
[],
|
||||
[HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY=0],
|
||||
[#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
fi
|
||||
if test $HAVE_STRUCT_SOCKADDR_STORAGE = 0 || test $HAVE_SA_FAMILY_T = 0 \
|
||||
|| test $HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY = 0; then
|
||||
SYS_SOCKET_H='sys/socket.h'
|
||||
fi
|
||||
gl_PREREQ_SYS_H_WINSOCK2
|
||||
|
||||
dnl Check for declarations of anything we want to poison if the
|
||||
dnl corresponding gnulib module is not in use.
|
||||
gl_WARN_ON_USE_PREPARE([[
|
||||
/* Some systems require prerequisite headers. */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
]], [socket connect accept bind getpeername getsockname getsockopt
|
||||
listen recv send recvfrom sendto setsockopt shutdown accept4])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_PREREQ_SYS_H_SOCKET],
|
||||
[
|
||||
dnl Check prerequisites of the <sys/socket.h> replacement.
|
||||
AC_REQUIRE([gl_CHECK_SOCKET_HEADERS])
|
||||
gl_CHECK_NEXT_HEADERS([sys/socket.h])
|
||||
if test $ac_cv_header_sys_socket_h = yes; then
|
||||
HAVE_SYS_SOCKET_H=1
|
||||
HAVE_WS2TCPIP_H=0
|
||||
else
|
||||
HAVE_SYS_SOCKET_H=0
|
||||
if test $ac_cv_header_ws2tcpip_h = yes; then
|
||||
HAVE_WS2TCPIP_H=1
|
||||
else
|
||||
HAVE_WS2TCPIP_H=0
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([HAVE_SYS_SOCKET_H])
|
||||
AC_SUBST([HAVE_WS2TCPIP_H])
|
||||
])
|
||||
|
||||
# Common prerequisites of the <sys/socket.h> replacement and of the
|
||||
# <sys/select.h> replacement.
|
||||
# Sets and substitutes HAVE_WINSOCK2_H.
|
||||
AC_DEFUN([gl_PREREQ_SYS_H_WINSOCK2],
|
||||
[
|
||||
m4_ifdef([gl_UNISTD_H_DEFAULTS], [AC_REQUIRE([gl_UNISTD_H_DEFAULTS])])
|
||||
m4_ifdef([gl_SYS_IOCTL_H_DEFAULTS], [AC_REQUIRE([gl_SYS_IOCTL_H_DEFAULTS])])
|
||||
AC_CHECK_HEADERS_ONCE([sys/socket.h])
|
||||
if test $ac_cv_header_sys_socket_h != yes; then
|
||||
dnl We cannot use AC_CHECK_HEADERS_ONCE here, because that would make
|
||||
dnl the check for those headers unconditional; yet cygwin reports
|
||||
dnl that the headers are present but cannot be compiled (since on
|
||||
dnl cygwin, all socket information should come from sys/socket.h).
|
||||
AC_CHECK_HEADERS([winsock2.h])
|
||||
fi
|
||||
if test "$ac_cv_header_winsock2_h" = yes; then
|
||||
HAVE_WINSOCK2_H=1
|
||||
UNISTD_H_HAVE_WINSOCK2_H=1
|
||||
SYS_IOCTL_H_HAVE_WINSOCK2_H=1
|
||||
else
|
||||
HAVE_WINSOCK2_H=0
|
||||
fi
|
||||
AC_SUBST([HAVE_WINSOCK2_H])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_SYS_SOCKET_MODULE_INDICATOR],
|
||||
[
|
||||
dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
|
||||
AC_REQUIRE([gl_SYS_SOCKET_H_DEFAULTS])
|
||||
gl_MODULE_INDICATOR_SET_VARIABLE([$1])
|
||||
dnl Define it also as a C macro, for the benefit of the unit tests.
|
||||
gl_MODULE_INDICATOR_FOR_TESTS([$1])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_SYS_SOCKET_H_DEFAULTS],
|
||||
[
|
||||
GNULIB_SOCKET=0; AC_SUBST([GNULIB_SOCKET])
|
||||
GNULIB_CONNECT=0; AC_SUBST([GNULIB_CONNECT])
|
||||
GNULIB_ACCEPT=0; AC_SUBST([GNULIB_ACCEPT])
|
||||
GNULIB_BIND=0; AC_SUBST([GNULIB_BIND])
|
||||
GNULIB_GETPEERNAME=0; AC_SUBST([GNULIB_GETPEERNAME])
|
||||
GNULIB_GETSOCKNAME=0; AC_SUBST([GNULIB_GETSOCKNAME])
|
||||
GNULIB_GETSOCKOPT=0; AC_SUBST([GNULIB_GETSOCKOPT])
|
||||
GNULIB_LISTEN=0; AC_SUBST([GNULIB_LISTEN])
|
||||
GNULIB_RECV=0; AC_SUBST([GNULIB_RECV])
|
||||
GNULIB_SEND=0; AC_SUBST([GNULIB_SEND])
|
||||
GNULIB_RECVFROM=0; AC_SUBST([GNULIB_RECVFROM])
|
||||
GNULIB_SENDTO=0; AC_SUBST([GNULIB_SENDTO])
|
||||
GNULIB_SETSOCKOPT=0; AC_SUBST([GNULIB_SETSOCKOPT])
|
||||
GNULIB_SHUTDOWN=0; AC_SUBST([GNULIB_SHUTDOWN])
|
||||
GNULIB_ACCEPT4=0; AC_SUBST([GNULIB_ACCEPT4])
|
||||
HAVE_STRUCT_SOCKADDR_STORAGE=1; AC_SUBST([HAVE_STRUCT_SOCKADDR_STORAGE])
|
||||
HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY=1;
|
||||
AC_SUBST([HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY])
|
||||
HAVE_SA_FAMILY_T=1; AC_SUBST([HAVE_SA_FAMILY_T])
|
||||
HAVE_ACCEPT4=1; AC_SUBST([HAVE_ACCEPT4])
|
||||
])
|
||||
106
m4/sys_time_h.m4
Normal file
106
m4/sys_time_h.m4
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# Configure a replacement for <sys/time.h>.
|
||||
# serial 8
|
||||
|
||||
# Copyright (C) 2007, 2009-2012 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.
|
||||
|
||||
# Written by Paul Eggert and Martin Lambers.
|
||||
|
||||
AC_DEFUN([gl_HEADER_SYS_TIME_H],
|
||||
[
|
||||
dnl Use AC_REQUIRE here, so that the REPLACE_GETTIMEOFDAY=0 statement
|
||||
dnl below is expanded once only, before all REPLACE_GETTIMEOFDAY=1
|
||||
dnl statements that occur in other macros.
|
||||
AC_REQUIRE([gl_HEADER_SYS_TIME_H_BODY])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_HEADER_SYS_TIME_H_BODY],
|
||||
[
|
||||
AC_REQUIRE([AC_C_RESTRICT])
|
||||
AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h])
|
||||
gl_CHECK_NEXT_HEADERS([sys/time.h])
|
||||
|
||||
if test $ac_cv_header_sys_time_h != yes; then
|
||||
HAVE_SYS_TIME_H=0
|
||||
fi
|
||||
|
||||
dnl On native Windows with MSVC, 'struct timeval' is defined in <winsock2.h>
|
||||
dnl only. So include that header in the list.
|
||||
gl_PREREQ_SYS_H_WINSOCK2
|
||||
AC_CACHE_CHECK([for struct timeval], [gl_cv_sys_struct_timeval],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#if HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#if HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
]],
|
||||
[[static struct timeval x; x.tv_sec = x.tv_usec;]])],
|
||||
[gl_cv_sys_struct_timeval=yes],
|
||||
[gl_cv_sys_struct_timeval=no])
|
||||
])
|
||||
if test $gl_cv_sys_struct_timeval != yes; then
|
||||
HAVE_STRUCT_TIMEVAL=0
|
||||
else
|
||||
dnl On native Windows with a 64-bit 'time_t', 'struct timeval' is defined
|
||||
dnl (in <sys/time.h> and <winsock2.h> for mingw64, in <winsock2.h> only
|
||||
dnl for MSVC) with a tv_sec field of type 'long' (32-bit!), which is
|
||||
dnl smaller than the 'time_t' type mandated by POSIX.
|
||||
AC_CACHE_CHECK([for correct struct timeval.tv_sec member],
|
||||
[gl_cv_sys_struct_timeval_tv_sec],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#if HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#if HAVE_WINSOCK2_H
|
||||
# include <winsock2.h>
|
||||
#endif
|
||||
]],
|
||||
[[static struct timeval x;
|
||||
typedef int verify_tv_sec_type[sizeof (x.tv_sec) == sizeof (time_t) ? 1 : -1];
|
||||
]])],
|
||||
[gl_cv_sys_struct_timeval_tv_sec=yes],
|
||||
[gl_cv_sys_struct_timeval_tv_sec=no])
|
||||
])
|
||||
if test $gl_cv_sys_struct_timeval_tv_sec != yes; then
|
||||
REPLACE_STRUCT_TIMEVAL=1
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Check for declarations of anything we want to poison if the
|
||||
dnl corresponding gnulib module is not in use.
|
||||
gl_WARN_ON_USE_PREPARE([[
|
||||
#if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
]], [gettimeofday])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_SYS_TIME_MODULE_INDICATOR],
|
||||
[
|
||||
dnl Use AC_REQUIRE here, so that the default settings are expanded once only.
|
||||
AC_REQUIRE([gl_HEADER_SYS_TIME_H_DEFAULTS])
|
||||
gl_MODULE_INDICATOR_SET_VARIABLE([$1])
|
||||
dnl Define it also as a C macro, for the benefit of the unit tests.
|
||||
gl_MODULE_INDICATOR_FOR_TESTS([$1])
|
||||
])
|
||||
|
||||
AC_DEFUN([gl_HEADER_SYS_TIME_H_DEFAULTS],
|
||||
[
|
||||
GNULIB_GETTIMEOFDAY=0; AC_SUBST([GNULIB_GETTIMEOFDAY])
|
||||
dnl Assume POSIX behavior unless another module says otherwise.
|
||||
HAVE_GETTIMEOFDAY=1; AC_SUBST([HAVE_GETTIMEOFDAY])
|
||||
HAVE_STRUCT_TIMEVAL=1; AC_SUBST([HAVE_STRUCT_TIMEVAL])
|
||||
HAVE_SYS_TIME_H=1; AC_SUBST([HAVE_SYS_TIME_H])
|
||||
REPLACE_GETTIMEOFDAY=0; AC_SUBST([REPLACE_GETTIMEOFDAY])
|
||||
REPLACE_STRUCT_TIMEVAL=0; AC_SUBST([REPLACE_STRUCT_TIMEVAL])
|
||||
])
|
||||
15
m4/timespec.m4
Normal file
15
m4/timespec.m4
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#serial 14
|
||||
|
||||
# Copyright (C) 2000-2001, 2003-2007, 2009-2012 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_TIMESPEC],
|
||||
[
|
||||
dnl Prerequisites of lib/timespec.h.
|
||||
AC_REQUIRE([AC_C_INLINE])
|
||||
])
|
||||
39
m4/utimbuf.m4
Normal file
39
m4/utimbuf.m4
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# serial 9
|
||||
|
||||
# Copyright (C) 1998-2001, 2003-2004, 2007, 2009-2012 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
|
||||
|
||||
dnl Define HAVE_STRUCT_UTIMBUF if 'struct utimbuf' is declared --
|
||||
dnl usually in <utime.h>.
|
||||
dnl Some systems have utime.h but don't declare the struct anywhere.
|
||||
|
||||
AC_DEFUN([gl_CHECK_TYPE_STRUCT_UTIMBUF],
|
||||
[
|
||||
AC_CHECK_HEADERS_ONCE([sys/time.h utime.h])
|
||||
AC_CACHE_CHECK([for struct utimbuf], [gl_cv_sys_struct_utimbuf],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[[#if HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UTIME_H
|
||||
#include <utime.h>
|
||||
#endif
|
||||
]],
|
||||
[[static struct utimbuf x; x.actime = x.modtime;]])],
|
||||
[gl_cv_sys_struct_utimbuf=yes],
|
||||
[gl_cv_sys_struct_utimbuf=no])])
|
||||
|
||||
if test $gl_cv_sys_struct_utimbuf = yes; then
|
||||
AC_DEFINE([HAVE_STRUCT_UTIMBUF], [1],
|
||||
[Define if struct utimbuf is declared -- usually in <utime.h>.
|
||||
Some systems have utime.h but don't declare the struct anywhere. ])
|
||||
fi
|
||||
])
|
||||
50
m4/utimens.m4
Normal file
50
m4/utimens.m4
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
dnl Copyright (C) 2003-2012 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl serial 7
|
||||
|
||||
AC_DEFUN([gl_UTIMENS],
|
||||
[
|
||||
dnl Prerequisites of lib/utimens.c.
|
||||
AC_REQUIRE([gl_FUNC_UTIMES])
|
||||
AC_REQUIRE([gl_CHECK_TYPE_STRUCT_TIMESPEC])
|
||||
AC_REQUIRE([gl_CHECK_TYPE_STRUCT_UTIMBUF])
|
||||
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
|
||||
AC_CHECK_FUNCS_ONCE([futimes futimesat futimens utimensat lutimes])
|
||||
|
||||
if test $ac_cv_func_futimens = no && test $ac_cv_func_futimesat = yes; then
|
||||
dnl FreeBSD 8.0-rc2 mishandles futimesat(fd,NULL,time). It is not
|
||||
dnl standardized, but Solaris implemented it first and uses it as
|
||||
dnl its only means to set fd time.
|
||||
AC_CACHE_CHECK([whether futimesat handles NULL file],
|
||||
[gl_cv_func_futimesat_works],
|
||||
[touch conftest.file
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stddef.h>
|
||||
#include <sys/times.h>
|
||||
#include <fcntl.h>
|
||||
]], [[ int fd = open ("conftest.file", O_RDWR);
|
||||
if (fd < 0) return 1;
|
||||
if (futimesat (fd, NULL, NULL)) return 2;
|
||||
]])],
|
||||
[gl_cv_func_futimesat_works=yes],
|
||||
[gl_cv_func_futimesat_works=no],
|
||||
[case "$host_os" in
|
||||
# Guess yes on glibc systems.
|
||||
*-gnu*) gl_cv_func_futimesat_works="guessing yes" ;;
|
||||
# If we don't know, assume the worst.
|
||||
*) gl_cv_func_futimesat_works="guessing no" ;;
|
||||
esac
|
||||
])
|
||||
rm -f conftest.file])
|
||||
case "$gl_cv_func_futimesat_works" in
|
||||
*yes) ;;
|
||||
*)
|
||||
AC_DEFINE([FUTIMESAT_NULL_BUG], [1],
|
||||
[Define to 1 if futimesat mishandles a NULL file name.])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
])
|
||||
136
m4/utimes.m4
Normal file
136
m4/utimes.m4
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
# Detect some bugs in glibc's implementation of utimes.
|
||||
# serial 3
|
||||
|
||||
dnl Copyright (C) 2003-2005, 2009-2012 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# See if we need to work around bugs in glibc's implementation of
|
||||
# utimes from 2003-07-12 to 2003-09-17.
|
||||
# First, there was a bug that would make utimes set mtime
|
||||
# and atime to zero (1970-01-01) unconditionally.
|
||||
# Then, there was code to round rather than truncate.
|
||||
# Then, there was an implementation (sparc64, Linux-2.4.28, glibc-2.3.3)
|
||||
# that didn't honor the NULL-means-set-to-current-time semantics.
|
||||
# Finally, there was also a version of utimes that failed on read-only
|
||||
# files, while utime worked fine (linux-2.2.20, glibc-2.2.5).
|
||||
#
|
||||
# From Jim Meyering, with suggestions from Paul Eggert.
|
||||
|
||||
AC_DEFUN([gl_FUNC_UTIMES],
|
||||
[
|
||||
AC_CACHE_CHECK([whether the utimes function works],
|
||||
[gl_cv_func_working_utimes],
|
||||
[
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <utime.h>
|
||||
|
||||
static int
|
||||
inorder (time_t a, time_t b, time_t c)
|
||||
{
|
||||
return a <= b && b <= c;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int result = 0;
|
||||
char const *file = "conftest.utimes";
|
||||
static struct timeval timeval[2] = {{9, 10}, {999999, 999999}};
|
||||
|
||||
/* Test whether utimes() essentially works. */
|
||||
{
|
||||
struct stat sbuf;
|
||||
FILE *f = fopen (file, "w");
|
||||
if (f == NULL)
|
||||
result |= 1;
|
||||
else if (fclose (f) != 0)
|
||||
result |= 1;
|
||||
else if (utimes (file, timeval) != 0)
|
||||
result |= 2;
|
||||
else if (lstat (file, &sbuf) != 0)
|
||||
result |= 1;
|
||||
else if (!(sbuf.st_atime == timeval[0].tv_sec
|
||||
&& sbuf.st_mtime == timeval[1].tv_sec))
|
||||
result |= 4;
|
||||
if (unlink (file) != 0)
|
||||
result |= 1;
|
||||
}
|
||||
|
||||
/* Test whether utimes() with a NULL argument sets the file's timestamp
|
||||
to the current time. Use 'fstat' as well as 'time' to
|
||||
determine the "current" time, to accommodate NFS file systems
|
||||
if there is a time skew between the host and the NFS server. */
|
||||
{
|
||||
int fd = open (file, O_WRONLY|O_CREAT, 0644);
|
||||
if (fd < 0)
|
||||
result |= 1;
|
||||
else
|
||||
{
|
||||
time_t t0, t2;
|
||||
struct stat st0, st1, st2;
|
||||
if (time (&t0) == (time_t) -1)
|
||||
result |= 1;
|
||||
else if (fstat (fd, &st0) != 0)
|
||||
result |= 1;
|
||||
else if (utimes (file, timeval) != 0)
|
||||
result |= 2;
|
||||
else if (utimes (file, NULL) != 0)
|
||||
result |= 8;
|
||||
else if (fstat (fd, &st1) != 0)
|
||||
result |= 1;
|
||||
else if (write (fd, "\n", 1) != 1)
|
||||
result |= 1;
|
||||
else if (fstat (fd, &st2) != 0)
|
||||
result |= 1;
|
||||
else if (time (&t2) == (time_t) -1)
|
||||
result |= 1;
|
||||
else
|
||||
{
|
||||
int m_ok_POSIX = inorder (t0, st1.st_mtime, t2);
|
||||
int m_ok_NFS = inorder (st0.st_mtime, st1.st_mtime, st2.st_mtime);
|
||||
if (! (st1.st_atime == st1.st_mtime))
|
||||
result |= 16;
|
||||
if (! (m_ok_POSIX || m_ok_NFS))
|
||||
result |= 32;
|
||||
}
|
||||
if (close (fd) != 0)
|
||||
result |= 1;
|
||||
}
|
||||
if (unlink (file) != 0)
|
||||
result |= 1;
|
||||
}
|
||||
|
||||
/* Test whether utimes() with a NULL argument works on read-only files. */
|
||||
{
|
||||
int fd = open (file, O_WRONLY|O_CREAT, 0444);
|
||||
if (fd < 0)
|
||||
result |= 1;
|
||||
else if (close (fd) != 0)
|
||||
result |= 1;
|
||||
else if (utimes (file, NULL) != 0)
|
||||
result |= 64;
|
||||
if (unlink (file) != 0)
|
||||
result |= 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
]])],
|
||||
[gl_cv_func_working_utimes=yes],
|
||||
[gl_cv_func_working_utimes=no],
|
||||
[gl_cv_func_working_utimes=no])])
|
||||
|
||||
if test $gl_cv_func_working_utimes = yes; then
|
||||
AC_DEFINE([HAVE_WORKING_UTIMES], [1], [Define if utimes works properly. ])
|
||||
fi
|
||||
])
|
||||
Loading…
Add table
Add a link
Reference in a new issue