1/* futimesat basic tests.
2 Copyright (C) 2021-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <dirent.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <sys/stat.h>
27#include <sys/time.h>
28
29#include <support/test-driver.h>
30#include <support/temp_file.h>
31
32#ifndef struct_stat
33# define struct_stat struct stat64
34# define fstat fstat64
35# define fstatat fstatat64
36#endif
37
38static int dir_fd;
39
40static void
41prepare (int argc, char *argv[])
42{
43 size_t test_dir_len = strlen (test_dir);
44 static const char dir_name[] = "/tst-futimesat.XXXXXX";
45
46 size_t dirbuflen = test_dir_len + sizeof (dir_name);
47 char *dirbuf = malloc (size: dirbuflen);
48 if (dirbuf == NULL)
49 {
50 puts (s: "out of memory");
51 exit (1);
52 }
53
54 snprintf (s: dirbuf, maxlen: dirbuflen, format: "%s%s", test_dir, dir_name);
55 if (mkdtemp (template: dirbuf) == NULL)
56 {
57 puts (s: "cannot create temporary directory");
58 exit (1);
59 }
60
61 add_temp_file (name: dirbuf);
62
63 dir_fd = open (file: dirbuf, O_RDONLY | O_DIRECTORY);
64 if (dir_fd == -1)
65 {
66 puts (s: "cannot open directory");
67 exit (1);
68 }
69}
70#define PREPARE prepare
71
72static int
73do_test (void)
74{
75 /* fdopendir takes over the descriptor, make a copy. */
76 int dupfd = dup (fd: dir_fd);
77 if (dupfd == -1)
78 {
79 puts (s: "dup failed");
80 return 1;
81 }
82 if (lseek (fd: dupfd, offset: 0, SEEK_SET) != 0)
83 {
84 puts (s: "1st lseek failed");
85 return 1;
86 }
87
88 /* The directory should be empty safe the . and .. files. */
89 DIR *dir = fdopendir (fd: dupfd);
90 if (dir == NULL)
91 {
92 puts (s: "fdopendir failed");
93 return 1;
94 }
95 struct dirent64 *d;
96 while ((d = readdir64 (dirp: dir)) != NULL)
97 if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
98 {
99 printf (format: "temp directory contains file \"%s\"\n", d->d_name);
100 return 1;
101 }
102 closedir (dirp: dir);
103
104 /* Try to create a file. */
105 int fd = openat (fd: dir_fd, file: "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
106 if (fd == -1)
107 {
108 if (errno == ENOSYS)
109 {
110 puts (s: "*at functions not supported");
111 return 0;
112 }
113
114 puts (s: "file creation failed");
115 return 1;
116 }
117 write (fd, "hello", 5);
118 puts (s: "file created");
119
120 struct_stat st1;
121 if (fstat (fd: fd, buf: &st1) != 0)
122 {
123 puts (s: "fstat64 failed");
124 return 1;
125 }
126
127 close (fd: fd);
128
129 struct timeval tv[2];
130 tv[0].tv_sec = st1.st_atime + 1;
131 tv[0].tv_usec = 0;
132 tv[1].tv_sec = st1.st_mtime + 1;
133 tv[1].tv_usec = 0;
134 if (futimesat (fd: dir_fd, file: "some-file", tvp: tv) != 0)
135 {
136 puts (s: "futimesat failed");
137 return 1;
138 }
139
140 struct_stat st2;
141 if (fstatat (fd: dir_fd, file: "some-file", buf: &st2, flag: 0) != 0)
142 {
143 puts (s: "fstatat64 failed");
144 return 1;
145 }
146
147 if (st2.st_mtime != tv[1].tv_sec
148#ifdef _STATBUF_ST_NSEC
149 || st2.st_mtim.tv_nsec != 0
150#endif
151 )
152 {
153 puts (s: "stat shows different mtime");
154 return 1;
155 }
156
157
158 if (unlinkat (fd: dir_fd, name: "some-file", flag: 0) != 0)
159 {
160 puts (s: "unlinkat failed");
161 return 1;
162 }
163
164 close (fd: dir_fd);
165
166 return 0;
167}
168
169#include <support/test-driver.c>
170

source code of glibc/io/tst-futimesat.c