bootstrap: fix handling of various perl --version formats
[gnulib.git] / tests / test-lutimens.h
1 /* Test of file timestamp modification functions.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17 #include "test-utimens-common.h"
18
19 /* This file is designed to test both lutimens(a,b) and
20    utimensat(AT_FDCWD,a,b,AT_SYMLINK_NOFOLLOW).  FUNC is the function
21    to test.  Assumes that BASE and ASSERT are already defined.  If
22    PRINT, warn before skipping tests with status 77.  */
23 static int
24 test_lutimens (int (*func) (char const *, struct timespec const *), bool print)
25 {
26   int result;
27   int saved_errno;
28   struct stat st1;
29   struct stat st2;
30   bool atime_supported = true;
31
32   /* Non-symlinks should be handled just like utimens.  */
33   errno = 0;
34   ASSERT (func ("no_such", NULL) == -1);
35   ASSERT (errno == ENOENT);
36   errno = 0;
37   ASSERT (func ("no_such/", NULL) == -1);
38   ASSERT (errno == ENOENT || errno == ENOTDIR);
39   errno = 0;
40   ASSERT (func ("", NULL) == -1);
41   ASSERT (errno == ENOENT);
42   ASSERT (close (creat (BASE "file", 0600)) == 0);
43   ASSERT (stat (BASE "file", &st1) == 0);
44   ASSERT (st1.st_atime != Y2K);
45   ASSERT (st1.st_mtime != Y2K);
46   {
47     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } };
48     errno = 0;
49     ASSERT (func (BASE "file/", ts) == -1);
50     ASSERT (errno == ENOTDIR);
51     ASSERT (stat (BASE "file", &st2) == 0);
52     ASSERT (st1.st_atime == st2.st_atime);
53     ASSERT (st1.st_mtime == st2.st_mtime);
54   }
55   {
56     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } };
57     ASSERT (func (BASE "file", ts) == 0);
58   }
59   ASSERT (stat (BASE "file", &st1) == 0);
60   ASSERT (st1.st_atime == Y2K);
61   ASSERT (st1.st_mtime == Y2K);
62
63   /* Play with symlink timestamps.  */
64   if (symlink (BASE "file", BASE "link"))
65     {
66       ASSERT (unlink (BASE "file") == 0);
67       if (print)
68         fputs ("skipping test: symlinks not supported on this file system\n",
69                stderr);
70       return 77;
71     }
72   errno = 0;
73   result = func (BASE "link", NULL);
74   saved_errno = errno;
75   /* Make sure we did not reference through link by accident.  */
76   ASSERT (stat (BASE "file", &st1) == 0);
77   ASSERT (st1.st_atime == Y2K);
78   ASSERT (st1.st_mtime == Y2K);
79   ASSERT (lstat (BASE "link", &st1) == 0);
80   ASSERT (st1.st_atime != Y2K);
81   ASSERT (st1.st_mtime != Y2K);
82   ASSERT (unlink (BASE "file") == 0);
83   if (result == -1 && saved_errno == ENOSYS)
84     {
85       ASSERT (unlink (BASE "link") == 0);
86       if (print)
87         fputs ("skipping test: "
88                "setting symlink time not supported on this file system\n",
89                stderr);
90       return 77;
91     }
92   ASSERT (!result);
93   ASSERT (lstat (BASE "link", &st1) == 0);
94   /* On cygwin, lstat() changes atime of symlinks, so that lutimens
95      can only effectively modify mtime.  */
96   nap ();
97   ASSERT (lstat (BASE "link", &st2) == 0);
98   if (st1.st_atime != st2.st_atime
99       || get_stat_atime_ns (&st1) != get_stat_atime_ns (&st2))
100     atime_supported = false;
101
102   /* Invalid arguments.  */
103   {
104     struct timespec ts[2] = { { Y2K, UTIME_BOGUS_POS }, { Y2K, 0 } };
105     errno = 0;
106     ASSERT (func (BASE "link", ts) == -1);
107     ASSERT (errno == EINVAL);
108   }
109   {
110     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, UTIME_BOGUS_NEG } };
111     errno = 0;
112     ASSERT (func (BASE "link", ts) == -1);
113     ASSERT (errno == EINVAL);
114   }
115   ASSERT (lstat (BASE "link", &st2) == 0);
116   if (atime_supported)
117     {
118       ASSERT (st1.st_atime == st2.st_atime);
119       ASSERT (get_stat_atime_ns (&st1) == get_stat_atime_ns (&st2));
120     }
121   ASSERT (utimecmp (BASE "link", &st1, &st2, 0) == 0);
122
123   /* Set both times.  */
124   {
125     struct timespec ts[2] = { { Y2K, BILLION / 2 - 1 }, { Y2K, BILLION - 1 } };
126     ASSERT (func (BASE "link", ts) == 0);
127     ASSERT (lstat (BASE "link", &st2) == 0);
128     if (atime_supported)
129       {
130         ASSERT (st2.st_atime == Y2K);
131         ASSERT (0 <= get_stat_atime_ns (&st2));
132         ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
133       }
134     ASSERT (st2.st_mtime == Y2K);
135     ASSERT (0 <= get_stat_mtime_ns (&st2));
136     ASSERT (get_stat_mtime_ns (&st2) < BILLION);
137   }
138
139   /* Play with UTIME_OMIT, UTIME_NOW.  */
140   {
141     struct timespec ts[2] = { { BILLION, UTIME_OMIT }, { 0, UTIME_NOW } };
142     ASSERT (func (BASE "link", ts) == 0);
143     ASSERT (lstat (BASE "link", &st2) == 0);
144     if (atime_supported)
145       {
146         ASSERT (st2.st_atime == Y2K);
147         ASSERT (0 <= get_stat_atime_ns (&st2));
148         ASSERT (get_stat_atime_ns (&st2) < BILLION / 2);
149       }
150     ASSERT (utimecmp (BASE "link", &st1, &st2, 0) <= 0);
151   }
152
153   /* Symlink to directory.  */
154   ASSERT (unlink (BASE "link") == 0);
155   ASSERT (symlink (BASE "dir", BASE "link") == 0);
156   ASSERT (mkdir (BASE "dir", 0700) == 0);
157   {
158     struct timespec ts[2] = { { Y2K, 0 }, { Y2K, 0 } };
159     ASSERT (func (BASE "link/", ts) == 0);
160   }
161   /* On cygwin 1.5, stat() changes atime of directories, so only check
162      mtime.  */
163   ASSERT (stat (BASE "dir", &st1) == 0);
164   ASSERT (st1.st_mtime == Y2K);
165   ASSERT (lstat (BASE "link", &st1) == 0);
166   ASSERT (st1.st_atime != Y2K);
167   ASSERT (st1.st_mtime != Y2K);
168   ASSERT (func (BASE "link", NULL) == 0);
169   ASSERT (stat (BASE "dir", &st1) == 0);
170   ASSERT (st1.st_mtime == Y2K);
171   ASSERT (lstat (BASE "link", &st1) == 0);
172   ASSERT (st1.st_atime != Y2K);
173   ASSERT (st1.st_mtime != Y2K);
174
175   /* Cleanup.  */
176   ASSERT (rmdir (BASE "dir") == 0);
177   ASSERT (unlink (BASE "link") == 0);
178   return 0;
179 }