1 # Detect some bugs in glibc's implementation of utimes.
4 dnl Copyright (C) 2003-2005, 2009-2017 Free Software Foundation, Inc.
5 dnl This file is free software; the Free Software Foundation
6 dnl gives unlimited permission to copy and/or distribute it,
7 dnl with or without modifications, as long as this notice is preserved.
9 # See if we need to work around bugs in glibc's implementation of
10 # utimes from 2003-07-12 to 2003-09-17.
11 # First, there was a bug that would make utimes set mtime
12 # and atime to zero (1970-01-01) unconditionally.
13 # Then, there was code to round rather than truncate.
14 # Then, there was an implementation (sparc64, Linux-2.4.28, glibc-2.3.3)
15 # that didn't honor the NULL-means-set-to-current-time semantics.
16 # Finally, there was also a version of utimes that failed on read-only
17 # files, while utime worked fine (linux-2.2.20, glibc-2.2.5).
19 # From Jim Meyering, with suggestions from Paul Eggert.
21 AC_DEFUN([gl_FUNC_UTIMES],
23 AC_CACHE_CHECK([whether the utimes function works],
24 [gl_cv_func_working_utimes],
26 AC_RUN_IFELSE([AC_LANG_SOURCE([[
27 #include <sys/types.h>
39 inorder (time_t a, time_t b, time_t c)
41 return a <= b && b <= c;
48 char const *file = "conftest.utimes";
49 /* On OS/2, file timestamps must be on or after 1980 in local time,
50 with an even number of seconds. */
51 static struct timeval timeval[2] = {{315620000 + 10, 10},
52 {315620000 + 1000000, 999998}};
54 /* Test whether utimes() essentially works. */
57 FILE *f = fopen (file, "w");
60 else if (fclose (f) != 0)
62 else if (utimes (file, timeval) != 0)
64 else if (lstat (file, &sbuf) != 0)
66 else if (!(sbuf.st_atime == timeval[0].tv_sec
67 && sbuf.st_mtime == timeval[1].tv_sec))
69 if (unlink (file) != 0)
73 /* Test whether utimes() with a NULL argument sets the file's timestamp
74 to the current time. Use 'fstat' as well as 'time' to
75 determine the "current" time, to accommodate NFS file systems
76 if there is a time skew between the host and the NFS server. */
78 int fd = open (file, O_WRONLY|O_CREAT, 0644);
84 struct stat st0, st1, st2;
85 if (time (&t0) == (time_t) -1)
87 else if (fstat (fd, &st0) != 0)
89 else if (utimes (file, timeval) != 0
91 /* OS/2 kLIBC utimes fails on opened files. */
93 || utimes (file, timeval) != 0
94 || (fd = open (file, O_WRONLY)) < 0))
96 else if (utimes (file, NULL) != 0
98 /* OS/2 kLIBC utimes fails on opened files. */
100 || utimes (file, NULL) != 0
101 || (fd = open (file, O_WRONLY)) < 0))
103 else if (fstat (fd, &st1) != 0)
105 else if (write (fd, "\n", 1) != 1)
107 else if (fstat (fd, &st2) != 0)
109 else if (time (&t2) == (time_t) -1)
113 int m_ok_POSIX = inorder (t0, st1.st_mtime, t2);
114 int m_ok_NFS = inorder (st0.st_mtime, st1.st_mtime, st2.st_mtime);
115 if (! (st1.st_atime == st1.st_mtime))
117 if (! (m_ok_POSIX || m_ok_NFS))
123 if (unlink (file) != 0)
127 /* Test whether utimes() with a NULL argument works on read-only files. */
129 int fd = open (file, O_WRONLY|O_CREAT, 0444);
132 else if (close (fd) != 0)
134 else if (utimes (file, NULL) != 0)
136 if (unlink (file) != 0)
143 [gl_cv_func_working_utimes=yes],
144 [gl_cv_func_working_utimes=no],
145 [gl_cv_func_working_utimes=no])])
147 if test $gl_cv_func_working_utimes = yes; then
148 AC_DEFINE([HAVE_WORKING_UTIMES], [1], [Define if utimes works properly.])