1 /* Test of file timestamp modification functions.
2 Copyright (C) 2009-2017 Free Software Foundation, Inc.
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 3 of the License, or
7 (at your option) any later version.
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.
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/>. */
17 #include "test-utimens-common.h"
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. */
24 test_lutimens (int (*func
) (char const *, struct timespec
const *), bool print
)
30 bool atime_supported
= true;
32 /* Non-symlinks should be handled just like utimens. */
34 ASSERT (func ("no_such", NULL
) == -1);
35 ASSERT (errno
== ENOENT
);
37 ASSERT (func ("no_such/", NULL
) == -1);
38 ASSERT (errno
== ENOENT
|| errno
== ENOTDIR
);
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
);
47 struct timespec ts
[2] = { { Y2K
, 0 }, { Y2K
, 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
);
56 struct timespec ts
[2] = { { Y2K
, 0 }, { Y2K
, 0 } };
58 ASSERT (func (BASE
"file", ts
) == 0);
60 ASSERT (stat (BASE
"file", &st2
) == 0);
61 ASSERT (st2
.st_atime
== Y2K
);
62 ASSERT (st2
.st_mtime
== Y2K
);
64 ASSERT (ctime_compare (&st1
, &st2
) < 0);
66 /* Play with symlink timestamps. */
67 if (symlink (BASE
"file", BASE
"link"))
69 ASSERT (unlink (BASE
"file") == 0);
71 fputs ("skipping test: symlinks not supported on this file system\n",
76 result
= func (BASE
"link", NULL
);
78 /* Make sure we did not reference through link by accident. */
79 ASSERT (stat (BASE
"file", &st1
) == 0);
80 ASSERT (st1
.st_atime
== Y2K
);
81 ASSERT (st1
.st_mtime
== Y2K
);
82 ASSERT (lstat (BASE
"link", &st1
) == 0);
83 ASSERT (st1
.st_atime
!= Y2K
);
84 ASSERT (st1
.st_mtime
!= Y2K
);
85 ASSERT (unlink (BASE
"file") == 0);
86 if (result
== -1 && saved_errno
== ENOSYS
)
88 ASSERT (unlink (BASE
"link") == 0);
90 fputs ("skipping test: "
91 "setting symlink time not supported on this file system\n",
96 ASSERT (lstat (BASE
"link", &st1
) == 0);
97 /* On cygwin, lstat() changes atime of symlinks, so that lutimens
98 can only effectively modify mtime. */
100 ASSERT (lstat (BASE
"link", &st2
) == 0);
101 if (st1
.st_atime
!= st2
.st_atime
102 || get_stat_atime_ns (&st1
) != get_stat_atime_ns (&st2
))
103 atime_supported
= false;
104 ASSERT (st1
.st_ctime
== st2
.st_ctime
);
105 ASSERT (get_stat_ctime_ns (&st1
) == get_stat_ctime_ns (&st2
));
107 /* Invalid arguments. */
109 struct timespec ts
[2] = { { Y2K
, UTIME_BOGUS_POS
}, { Y2K
, 0 } };
111 ASSERT (func (BASE
"link", ts
) == -1);
112 ASSERT (errno
== EINVAL
);
115 struct timespec ts
[2] = { { Y2K
, 0 }, { Y2K
, UTIME_BOGUS_NEG
} };
117 ASSERT (func (BASE
"link", ts
) == -1);
118 ASSERT (errno
== EINVAL
);
120 ASSERT (lstat (BASE
"link", &st2
) == 0);
123 ASSERT (st1
.st_atime
== st2
.st_atime
);
124 ASSERT (get_stat_atime_ns (&st1
) == get_stat_atime_ns (&st2
));
126 ASSERT (utimecmp (BASE
"link", &st1
, &st2
, 0) == 0);
128 /* Set both times. */
130 struct timespec ts
[2] = { { Y2K
, BILLION
/ 2 - 1 }, { Y2K
, BILLION
- 1 } };
132 ASSERT (func (BASE
"link", ts
) == 0);
133 ASSERT (lstat (BASE
"link", &st2
) == 0);
136 ASSERT (st2
.st_atime
== Y2K
);
137 ASSERT (0 <= get_stat_atime_ns (&st2
));
138 ASSERT (get_stat_atime_ns (&st2
) < BILLION
/ 2);
140 ASSERT (st2
.st_mtime
== Y2K
);
141 ASSERT (0 <= get_stat_mtime_ns (&st2
));
142 ASSERT (get_stat_mtime_ns (&st2
) < BILLION
);
144 ASSERT (ctime_compare (&st1
, &st2
) < 0);
147 /* Play with UTIME_OMIT, UTIME_NOW. */
150 struct timespec ts
[2] = { { BILLION
, UTIME_OMIT
}, { 0, UTIME_NOW
} };
152 ASSERT (func (BASE
"link", ts
) == 0);
153 ASSERT (lstat (BASE
"link", &st3
) == 0);
156 ASSERT (st3
.st_atime
== Y2K
);
157 ASSERT (0 <= get_stat_atime_ns (&st3
));
158 ASSERT (get_stat_atime_ns (&st3
) < BILLION
/ 2);
160 ASSERT (utimecmp (BASE
"link", &st1
, &st3
, 0) <= 0);
162 ASSERT (ctime_compare (&st2
, &st3
) < 0);
165 ts
[1].tv_nsec
= UTIME_OMIT
;
166 ASSERT (func (BASE
"link", ts
) == 0);
167 ASSERT (lstat (BASE
"link", &st2
) == 0);
170 ASSERT (st2
.st_atime
== BILLION
);
171 ASSERT (get_stat_atime_ns (&st2
) == 0);
173 ASSERT (st3
.st_mtime
== st2
.st_mtime
);
174 ASSERT (get_stat_mtime_ns (&st3
) == get_stat_mtime_ns (&st2
));
176 ASSERT (ctime_compare (&st3
, &st2
) < 0);
179 /* Symlink to directory. */
180 ASSERT (unlink (BASE
"link") == 0);
181 ASSERT (symlink (BASE
"dir", BASE
"link") == 0);
182 ASSERT (mkdir (BASE
"dir", 0700) == 0);
184 struct timespec ts
[2] = { { Y2K
, 0 }, { Y2K
, 0 } };
185 ASSERT (func (BASE
"link/", ts
) == 0);
187 /* On cygwin 1.5, stat() changes atime of directories, so only check
189 ASSERT (stat (BASE
"dir", &st1
) == 0);
190 ASSERT (st1
.st_mtime
== Y2K
);
191 ASSERT (lstat (BASE
"link", &st1
) == 0);
192 ASSERT (st1
.st_atime
!= Y2K
);
193 ASSERT (st1
.st_mtime
!= Y2K
);
194 ASSERT (func (BASE
"link", NULL
) == 0);
195 ASSERT (stat (BASE
"dir", &st1
) == 0);
196 ASSERT (st1
.st_mtime
== Y2K
);
197 ASSERT (lstat (BASE
"link", &st1
) == 0);
198 ASSERT (st1
.st_atime
!= Y2K
);
199 ASSERT (st1
.st_mtime
!= Y2K
);
202 ASSERT (rmdir (BASE
"dir") == 0);
203 ASSERT (unlink (BASE
"link") == 0);