Do the Windows oldnames workaround through the C++ GNULIB_NAMESPACE.
[gnulib.git] / m4 / utimes.m4
blob877bfd2a735715869120fa6425719141120b1778
1 # Detect some bugs in glibc's implementation of utimes.
2 # serial 8
4 dnl Copyright (C) 2003-2005, 2009-2020 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_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
24   AC_CACHE_CHECK([whether the utimes function works],
25                  [gl_cv_func_working_utimes],
26     [AC_RUN_IFELSE([AC_LANG_SOURCE([[
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <sys/time.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <utime.h>
36 #include <errno.h>
37 ]GL_MDA_DEFINES[
39 static int
40 inorder (time_t a, time_t b, time_t c)
42   return a <= b && b <= c;
45 int
46 main ()
48   int result = 0;
49   char const *file = "conftest.utimes";
50   /* On OS/2, file timestamps must be on or after 1980 in local time,
51      with an even number of seconds.  */
52   static struct timeval timeval[2] = {{315620000 + 10, 10},
53                                       {315620000 + 1000000, 999998}};
55   /* Test whether utimes() essentially works.  */
56   {
57     struct stat sbuf;
58     FILE *f = fopen (file, "w");
59     if (f == NULL)
60       result |= 1;
61     else if (fclose (f) != 0)
62       result |= 1;
63     else if (utimes (file, timeval) != 0)
64       result |= 2;
65     else if (lstat (file, &sbuf) != 0)
66       result |= 1;
67     else if (!(sbuf.st_atime == timeval[0].tv_sec
68                && sbuf.st_mtime == timeval[1].tv_sec))
69       result |= 4;
70     if (unlink (file) != 0)
71       result |= 1;
72   }
74   /* Test whether utimes() with a NULL argument sets the file's timestamp
75      to the current time.  Use 'fstat' as well as 'time' to
76      determine the "current" time, to accommodate NFS file systems
77      if there is a time skew between the host and the NFS server.  */
78   {
79     int fd = open (file, O_WRONLY|O_CREAT, 0644);
80     if (fd < 0)
81       result |= 1;
82     else
83       {
84         time_t t0, t2;
85         struct stat st0, st1, st2;
86         if (time (&t0) == (time_t) -1)
87           result |= 1;
88         else if (fstat (fd, &st0) != 0)
89           result |= 1;
90         else if (utimes (file, timeval) != 0
91                  && (errno != EACCES
92                      /* OS/2 kLIBC utimes fails on opened files.  */
93                      || close (fd) != 0
94                      || utimes (file, timeval) != 0
95                      || (fd = open (file, O_WRONLY)) < 0))
96           result |= 2;
97         else if (utimes (file, NULL) != 0
98                  && (errno != EACCES
99                      /* OS/2 kLIBC utimes fails on opened files.  */
100                      || close (fd) != 0
101                      || utimes (file, NULL) != 0
102                      || (fd = open (file, O_WRONLY)) < 0))
103           result |= 8;
104         else if (fstat (fd, &st1) != 0)
105           result |= 1;
106         else if (write (fd, "\n", 1) != 1)
107           result |= 1;
108         else if (fstat (fd, &st2) != 0)
109           result |= 1;
110         else if (time (&t2) == (time_t) -1)
111           result |= 1;
112         else
113           {
114             int m_ok_POSIX = inorder (t0, st1.st_mtime, t2);
115             int m_ok_NFS = inorder (st0.st_mtime, st1.st_mtime, st2.st_mtime);
116             if (! (st1.st_atime == st1.st_mtime))
117               result |= 16;
118             if (! (m_ok_POSIX || m_ok_NFS))
119               result |= 32;
120           }
121         if (close (fd) != 0)
122           result |= 1;
123       }
124     if (unlink (file) != 0)
125       result |= 1;
126   }
128   /* Test whether utimes() with a NULL argument works on read-only files.  */
129   {
130     int fd = open (file, O_WRONLY|O_CREAT, 0444);
131     if (fd < 0)
132       result |= 1;
133     else if (close (fd) != 0)
134       result |= 1;
135     else if (utimes (file, NULL) != 0)
136       result |= 64;
137     if (unlink (file) != 0)
138       result |= 1;
139   }
141   return result;
143   ]])],
144        [gl_cv_func_working_utimes=yes],
145        [gl_cv_func_working_utimes=no],
146        [case "$host_os" in
147                    # Guess yes on musl systems.
148           *-musl*) gl_cv_func_working_utimes="guessing yes" ;;
149                    # Guess no on native Windows.
150           mingw*)  gl_cv_func_working_utimes="guessing no" ;;
151           *)       gl_cv_func_working_utimes="$gl_cross_guess_normal" ;;
152         esac
153        ])
154     ])
156   case "$gl_cv_func_working_utimes" in
157     *yes)
158       AC_DEFINE([HAVE_WORKING_UTIMES], [1], [Define if utimes works properly.])
159       ;;
160   esac