openat: don’t close (-1)
[gnulib.git] / tests / test-utime.c
blobfd87f91cd84e9d709d826fc1078d124181c55e27
1 /* Tests of utime.
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/>. */
17 #include <config.h>
19 #include <utime.h>
21 #include <stdio.h>
22 #include <stdlib.h>
24 #include "ignore-value.h"
25 #include "macros.h"
27 #define BASE "test-utime.t"
29 #include "test-utimens-common.h"
31 /* If PRINT, warn before skipping tests with status 77. */
32 static int
33 test_utime (bool print)
35 struct stat st1;
36 struct stat st2;
38 int fd = open (BASE "file", O_RDWR | O_CREAT | O_TRUNC, 0600);
39 ASSERT (0 <= fd);
40 bool check_atime = checkable_atime (fd, &st1);
41 ASSERT (close (fd) == 0);
43 nap ();
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));
47 if (check_ctime)
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
56 both times. */
57 struct utimbuf ts;
58 ts.actime = ts.modtime = time (NULL);
59 ASSERT (utime (BASE "file", &ts) == 0);
60 ASSERT (stat (BASE "file", &st1) == 0);
61 nap ();
64 /* Invalid arguments. */
65 errno = 0;
66 ASSERT (utime ("no_such", NULL) == -1);
67 ASSERT (errno == ENOENT);
68 errno = 0;
69 ASSERT (utime ("no_such/", NULL) == -1);
70 ASSERT (errno == ENOENT || errno == ENOTDIR);
71 errno = 0;
72 ASSERT (utime ("", NULL) == -1);
73 ASSERT (errno == ENOENT);
75 struct utimbuf ts;
76 ts.actime = ts.modtime = Y2K;
77 errno = 0;
78 ASSERT (utime (BASE "file/", &ts) == -1);
79 ASSERT (errno == ENOTDIR || errno == EINVAL);
81 ASSERT (stat (BASE "file", &st2) == 0);
82 if (check_atime)
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);
89 /* Set both times. */
91 struct utimbuf ts;
92 ts.actime = ts.modtime = Y2K;
93 ASSERT (utime (BASE "file", &ts) == 0);
94 ASSERT (stat (BASE "file", &st2) == 0);
95 if (check_atime)
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);
104 if (check_ctime)
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;
114 if (print)
115 fputs ("skipping test: symlinks not supported on this file system\n",
116 stderr);
117 return 77;
119 ASSERT (lstat (BASE "link", &st1) == 0);
120 ASSERT (st1.st_mtime != Y2K);
121 errno = 0;
122 ASSERT (utime (BASE "link/", NULL) == -1);
123 ASSERT (errno == ENOTDIR);
125 struct utimbuf ts;
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);
138 /* Cleanup. */
139 ASSERT (unlink (BASE "link") == 0);
140 ASSERT (unlink (BASE "file") == 0);
141 return 0;
145 main (void)
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);