2 Copyright (C) 2017-2024 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/>. */
24 #include "ignore-value.h"
27 #define BASE "test-utime.t"
29 #include "test-utimens-common.h"
31 /* If PRINT, warn before skipping tests with status 77. */
33 test_utime (bool print
)
38 int fd
= open (BASE
"file", O_RDWR
| O_CREAT
| O_TRUNC
, 0600);
40 bool check_atime
= checkable_atime (fd
, &st1
);
41 ASSERT (close (fd
) == 0);
44 ASSERT (utime (BASE
"file", NULL
) == 0);
45 ASSERT (stat (BASE
"file", &st2
) == 0);
46 ASSERT (0 <= utimecmp (BASE
"file", &st2
, &st1
, UTIMECMP_TRUNCATE_SOURCE
));
48 ASSERT (ctime_compare (&st1
, &st2
) < 0);
50 /* On some NFS systems, the 'now' timestamp of creat or a NULL
51 utimbuf is determined by the server, but the 'now' timestamp
52 determined by time() is determined by the client; since the two
53 machines are not necessarily on the same clock, this is another
54 case where time can appear to go backwards. The rest of this
55 test cares about client time, so manually use time() to set
58 ts
.actime
= ts
.modtime
= time (NULL
);
59 ASSERT (utime (BASE
"file", &ts
) == 0);
60 ASSERT (stat (BASE
"file", &st1
) == 0);
64 /* Invalid arguments. */
66 ASSERT (utime ("no_such", NULL
) == -1);
67 ASSERT (errno
== ENOENT
);
69 ASSERT (utime ("no_such/", NULL
) == -1);
70 ASSERT (errno
== ENOENT
|| errno
== ENOTDIR
);
72 ASSERT (utime ("", NULL
) == -1);
73 ASSERT (errno
== ENOENT
);
76 ts
.actime
= ts
.modtime
= Y2K
;
78 ASSERT (utime (BASE
"file/", &ts
) == -1);
79 ASSERT (errno
== ENOTDIR
|| errno
== EINVAL
);
81 ASSERT (stat (BASE
"file", &st2
) == 0);
84 ASSERT (st1
.st_atime
== st2
.st_atime
);
85 ASSERT (get_stat_atime_ns (&st1
) == get_stat_atime_ns (&st2
));
87 ASSERT (utimecmp (BASE
"file", &st1
, &st2
, 0) == 0);
92 ts
.actime
= ts
.modtime
= Y2K
;
93 ASSERT (utime (BASE
"file", &ts
) == 0);
94 ASSERT (stat (BASE
"file", &st2
) == 0);
97 ASSERT (st2
.st_atime
== Y2K
);
98 ASSERT (0 <= get_stat_atime_ns (&st2
));
99 ASSERT (get_stat_atime_ns (&st2
) < BILLION
/ 2);
101 ASSERT (st2
.st_mtime
== Y2K
);
102 ASSERT (0 <= get_stat_mtime_ns (&st2
));
103 ASSERT (get_stat_mtime_ns (&st2
) < BILLION
);
105 ASSERT (ctime_compare (&st1
, &st2
) < 0);
108 /* Make sure this dereferences symlinks. */
109 if (symlink (BASE
"file", BASE
"link"))
111 ASSERT (unlink (BASE
"file") == 0);
112 if (test_exit_status
!= EXIT_SUCCESS
)
113 return test_exit_status
;
115 fputs ("skipping test: symlinks not supported on this file system\n",
119 ASSERT (lstat (BASE
"link", &st1
) == 0);
120 ASSERT (st1
.st_mtime
!= Y2K
);
122 ASSERT (utime (BASE
"link/", NULL
) == -1);
123 ASSERT (errno
== ENOTDIR
);
126 ts
.actime
= ts
.modtime
= Y2K
;
127 ASSERT (utime (BASE
"link", &ts
) == 0);
128 ASSERT (lstat (BASE
"link", &st2
) == 0);
129 /* Make sure symlink time hasn't been modified.
130 Can't compare symlink atimes, since when utime follows the
131 symlink it might update the symlink atime. */
132 ASSERT (st1
.st_mtime
== st2
.st_mtime
);
133 ASSERT (stat (BASE
"link", &st2
) == 0);
134 ASSERT (st2
.st_mtime
== Y2K
);
135 ASSERT (get_stat_mtime_ns (&st2
) == 0);
139 ASSERT (unlink (BASE
"link") == 0);
140 ASSERT (unlink (BASE
"file") == 0);
147 int result1
; /* Skip because of no symlink support. */
149 /* Clean up any trash from prior testsuite runs. */
150 ignore_value (system ("rm -rf " BASE
"*"));
152 result1
= test_utime (true);
153 return (result1
? result1
: test_exit_status
);