1 /* Test of file timestamp modification functions.
2 Copyright (C) 2009-2020 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 <https://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];
52 ASSERT (func (BASE
"file/", ts
) == -1);
53 ASSERT (errno
== ENOTDIR
);
54 ASSERT (stat (BASE
"file", &st2
) == 0);
55 ASSERT (st1
.st_atime
== st2
.st_atime
);
56 ASSERT (st1
.st_mtime
== st2
.st_mtime
);
59 struct timespec ts
[2];
64 ASSERT (func (BASE
"file", ts
) == 0);
66 ASSERT (stat (BASE
"file", &st2
) == 0);
67 ASSERT (st2
.st_atime
== Y2K
);
68 ASSERT (st2
.st_mtime
== Y2K
);
70 ASSERT (ctime_compare (&st1
, &st2
) < 0);
72 /* Play with symlink timestamps. */
73 if (symlink (BASE
"file", BASE
"link"))
75 ASSERT (unlink (BASE
"file") == 0);
77 fputs ("skipping test: symlinks not supported on this file system\n",
82 result
= func (BASE
"link", NULL
);
84 /* Make sure we did not reference through link by accident. */
85 ASSERT (stat (BASE
"file", &st1
) == 0);
86 ASSERT (st1
.st_atime
== Y2K
);
87 ASSERT (st1
.st_mtime
== Y2K
);
88 ASSERT (lstat (BASE
"link", &st1
) == 0);
89 ASSERT (st1
.st_atime
!= Y2K
);
90 ASSERT (st1
.st_mtime
!= Y2K
);
91 ASSERT (unlink (BASE
"file") == 0);
92 if (result
== -1 && saved_errno
== ENOSYS
)
94 ASSERT (unlink (BASE
"link") == 0);
96 fputs ("skipping test: "
97 "setting symlink time not supported on this file system\n",
102 ASSERT (lstat (BASE
"link", &st1
) == 0);
103 /* On cygwin, lstat() changes atime of symlinks, so that lutimens
104 can only effectively modify mtime. */
106 ASSERT (lstat (BASE
"link", &st2
) == 0);
107 if (st1
.st_atime
!= st2
.st_atime
108 || get_stat_atime_ns (&st1
) != get_stat_atime_ns (&st2
))
109 atime_supported
= false;
110 ASSERT (st1
.st_ctime
== st2
.st_ctime
);
111 ASSERT (get_stat_ctime_ns (&st1
) == get_stat_ctime_ns (&st2
));
113 /* Invalid arguments. */
115 struct timespec ts
[2];
117 ts
[0].tv_nsec
= UTIME_BOGUS_POS
;
121 ASSERT (func (BASE
"link", ts
) == -1);
122 ASSERT (errno
== EINVAL
);
125 struct timespec ts
[2];
129 ts
[1].tv_nsec
= UTIME_BOGUS_NEG
;
131 ASSERT (func (BASE
"link", ts
) == -1);
132 ASSERT (errno
== EINVAL
);
134 ASSERT (lstat (BASE
"link", &st2
) == 0);
137 ASSERT (st1
.st_atime
== st2
.st_atime
);
138 ASSERT (get_stat_atime_ns (&st1
) == get_stat_atime_ns (&st2
));
140 ASSERT (utimecmp (BASE
"link", &st1
, &st2
, 0) == 0);
142 /* Set both times. */
144 struct timespec ts
[2];
146 ts
[0].tv_nsec
= BILLION
/ 2 - 1;
148 ts
[1].tv_nsec
= BILLION
- 1;
150 ASSERT (func (BASE
"link", ts
) == 0);
151 ASSERT (lstat (BASE
"link", &st2
) == 0);
154 ASSERT (st2
.st_atime
== Y2K
);
155 ASSERT (0 <= get_stat_atime_ns (&st2
));
156 ASSERT (get_stat_atime_ns (&st2
) < BILLION
/ 2);
158 ASSERT (st2
.st_mtime
== Y2K
);
159 ASSERT (0 <= get_stat_mtime_ns (&st2
));
160 ASSERT (get_stat_mtime_ns (&st2
) < BILLION
);
162 ASSERT (ctime_compare (&st1
, &st2
) < 0);
165 /* Play with UTIME_OMIT, UTIME_NOW. */
168 struct timespec ts
[2];
169 ts
[0].tv_sec
= BILLION
;
170 ts
[0].tv_nsec
= UTIME_OMIT
;
172 ts
[1].tv_nsec
= UTIME_NOW
;
174 ASSERT (func (BASE
"link", ts
) == 0);
175 ASSERT (lstat (BASE
"link", &st3
) == 0);
178 ASSERT (st3
.st_atime
== Y2K
);
179 ASSERT (0 <= get_stat_atime_ns (&st3
));
180 ASSERT (get_stat_atime_ns (&st3
) < BILLION
/ 2);
182 ASSERT (utimecmp (BASE
"link", &st1
, &st3
, 0) <= 0);
184 ASSERT (ctime_compare (&st2
, &st3
) < 0);
187 ts
[1].tv_nsec
= UTIME_OMIT
;
188 ASSERT (func (BASE
"link", ts
) == 0);
189 ASSERT (lstat (BASE
"link", &st2
) == 0);
192 ASSERT (st2
.st_atime
== BILLION
);
193 ASSERT (get_stat_atime_ns (&st2
) == 0);
195 ASSERT (st3
.st_mtime
== st2
.st_mtime
);
196 ASSERT (get_stat_mtime_ns (&st3
) == get_stat_mtime_ns (&st2
));
198 ASSERT (ctime_compare (&st3
, &st2
) < 0);
201 /* Symlink to directory. */
202 ASSERT (unlink (BASE
"link") == 0);
203 ASSERT (symlink (BASE
"dir", BASE
"link") == 0);
204 ASSERT (mkdir (BASE
"dir", 0700) == 0);
206 struct timespec ts
[2];
210 ASSERT (func (BASE
"link/", ts
) == 0);
212 /* On cygwin 1.5, stat() changes atime of directories, so only check
214 ASSERT (stat (BASE
"dir", &st1
) == 0);
215 ASSERT (st1
.st_mtime
== Y2K
);
216 ASSERT (lstat (BASE
"link", &st1
) == 0);
217 ASSERT (st1
.st_atime
!= Y2K
);
218 ASSERT (st1
.st_mtime
!= Y2K
);
219 ASSERT (func (BASE
"link", NULL
) == 0);
220 ASSERT (stat (BASE
"dir", &st1
) == 0);
221 ASSERT (st1
.st_mtime
== Y2K
);
222 ASSERT (lstat (BASE
"link", &st1
) == 0);
223 ASSERT (st1
.st_atime
!= Y2K
);
224 ASSERT (st1
.st_mtime
!= Y2K
);
227 ASSERT (rmdir (BASE
"dir") == 0);
228 ASSERT (unlink (BASE
"link") == 0);