1 /*
2 * Check decoding of utimensat syscall.
3 *
4 * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2015-2023 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include <fcntl.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 #include <unistd.h>
18 #include "scno.h"
19
20 #if defined __NR_utimensat && defined UTIME_NOW && defined UTIME_OMIT
21
22 # if SIZEOF_KERNEL_LONG_T == 4
23 # define big_tv_sec "-559038737"
24 # define huge_tv_sec "-559038737"
25 # else
26 # define big_tv_sec "3735928559"
27 # define huge_tv_sec "-3819351491602432273"
28 # endif
29
30 # if XLAT_RAW
31 # define str_at_fdcwd "-100"
32 # define str_at_symlink_nofollow "0x100"
33 # define str_at_removedir "0x200"
34 # define str_flags1 "0x600"
35 # define str_flags2 "0xffffffff"
36 # define str_utime_now_omit \
37 "[{tv_sec=" big_tv_sec ", tv_nsec=1073741823}, " \
38 "{tv_sec=" huge_tv_sec ", tv_nsec=1073741822}]"
39 # elif XLAT_VERBOSE
40 # define str_at_fdcwd "-100 /* AT_FDCWD */"
41 # define str_at_symlink_nofollow "0x100 /* AT_SYMLINK_NOFOLLOW */"
42 # define str_at_removedir "0x200 /* AT_REMOVEDIR */"
43 # define str_flags1 \
44 "0x600 /* AT_REMOVEDIR|AT_SYMLINK_FOLLOW */"
45 # define str_flags2 \
46 "0xffffffff /* AT_SYMLINK_NOFOLLOW|AT_REMOVEDIR|AT_SYMLINK_FOLLOW" \
47 "|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|AT_RECURSIVE|0xffff60ff */"
48 # define str_utime_now_omit \
49 "[{tv_sec=" big_tv_sec ", tv_nsec=1073741823} /* UTIME_NOW */, " \
50 "{tv_sec=" huge_tv_sec ", tv_nsec=1073741822} /* UTIME_OMIT */]"
51 # else
52 # define str_at_fdcwd "AT_FDCWD"
53 # define str_at_symlink_nofollow "AT_SYMLINK_NOFOLLOW"
54 # define str_at_removedir "AT_REMOVEDIR"
55 # define str_flags1 "AT_REMOVEDIR|AT_SYMLINK_FOLLOW"
56 # define str_flags2 \
57 "AT_SYMLINK_NOFOLLOW|AT_REMOVEDIR|AT_SYMLINK_FOLLOW" \
58 "|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|AT_RECURSIVE|0xffff60ff"
59 # define str_utime_now_omit "[UTIME_NOW, UTIME_OMIT]"
60 # endif
61
62 static void
63 print_ts(const kernel_old_timespec_t *ts)
64 {
65 printf("{tv_sec=%lld, tv_nsec=%llu}", (long long) ts->tv_sec,
66 zero_extend_signed_to_ull(ts->tv_nsec));
67 print_time_t_nsec(ts->tv_sec,
68 zero_extend_signed_to_ull(ts->tv_nsec), 1);
69 }
70
71 static const char *errstr;
72
73 static long
74 k_utimensat(const kernel_ulong_t dirfd,
75 const kernel_ulong_t pathname,
76 const kernel_ulong_t times,
77 const kernel_ulong_t flags)
78 {
79 long rc = syscall(__NR_utimensat, dirfd, pathname, times, flags);
80 errstr = sprintrc(rc);
81 return rc;
82 }
83
84 int
85 main(void)
86 {
87 static const kernel_ulong_t bogus_fd =
88 (kernel_ulong_t) 0xbadc0deddeadbeef;
89 static const kernel_ulong_t kfdcwd =
90 (kernel_ulong_t) 0xdefaced00000000 | -100U;
91 static const char proto_fname[] = "utimensat\nfilename";
92 static const char qname[] = "\"utimensat\\nfilename\"";
93
94 char *const fname = tail_memdup(proto_fname, sizeof(proto_fname));
95 const kernel_ulong_t kfname = (uintptr_t) fname;
96 kernel_old_timespec_t *const ts = tail_alloc(sizeof(*ts) * 2);
97
98 (void) close(0);
99
100 /* dirfd */
101 k_utimensat(0, kfname, 0, 0);
102 printf("utimensat(0, %s, NULL, 0) = %s\n", qname, errstr);
103
104 k_utimensat(bogus_fd, kfname, 0, 0);
105 printf("utimensat(%d, %s, NULL, 0) = %s\n",
106 (int) bogus_fd, qname, errstr);
107
108 k_utimensat(-100U, kfname, 0, 0);
109 printf("utimensat(" str_at_fdcwd ", %s, NULL, 0) = %s\n", qname, errstr);
110
111 k_utimensat(kfdcwd, kfname, 0, 0);
112 printf("utimensat(" str_at_fdcwd ", %s, NULL, 0) = %s\n", qname, errstr);
113
114 /* pathname */
115 k_utimensat(kfdcwd, 0, 0, 0);
116 printf("utimensat(" str_at_fdcwd ", NULL, NULL, 0) = %s\n", errstr);
117
118 k_utimensat(kfdcwd, kfname + sizeof(proto_fname) - 1, 0, 0);
119 printf("utimensat(" str_at_fdcwd ", \"\", NULL, 0) = %s\n", errstr);
120
121 fname[sizeof(proto_fname) - 1] = '+';
122 k_utimensat(kfdcwd, kfname, 0, 0);
123 fname[sizeof(proto_fname) - 1] = '\0';
124 printf("utimensat(" str_at_fdcwd ", %p, NULL, 0) = %s\n", fname, errstr);
125
126 if (F8ILL_KULONG_SUPPORTED) {
127 k_utimensat(kfdcwd, f8ill_ptr_to_kulong(fname), 0, 0);
128 printf("utimensat(" str_at_fdcwd ", %#jx, NULL, 0) = %s\n",
129 (uintmax_t) f8ill_ptr_to_kulong(fname), errstr);
130 }
131
132 /* times */
133 k_utimensat(kfdcwd, kfname, (uintptr_t) (ts + 1), 0);
134 printf("utimensat(" str_at_fdcwd ", %s, %p, 0) = %s\n",
135 qname, ts + 1, errstr);
136
137 k_utimensat(kfdcwd, kfname, (uintptr_t) (ts + 2), 0);
138 printf("utimensat(" str_at_fdcwd ", %s, %p, 0)"
139 " = %s\n", qname, ts + 2, errstr);
140
141 ts[0].tv_sec = 1492358706;
142 ts[0].tv_nsec = 123456789;
143 ts[1].tv_sec = 1492357068;
144 ts[1].tv_nsec = 234567890;
145
146 k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
147 printf("utimensat(" str_at_fdcwd ", %s, [", qname);
148 print_ts(&ts[0]);
149 printf(", ");
150 print_ts(&ts[1]);
151 printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
152
153 ts[0].tv_sec = -1;
154 ts[0].tv_nsec = 2000000000;
155 ts[1].tv_sec = (typeof(ts[1].tv_sec)) -0x100000001LL;
156 ts[1].tv_nsec = 2345678900U;
157
158 k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
159 printf("utimensat(" str_at_fdcwd ", %s, [", qname);
160 print_ts(&ts[0]);
161 printf(", ");
162 print_ts(&ts[1]);
163 printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
164
165 ts[0].tv_sec = 0;
166 ts[0].tv_nsec = 0;
167 ts[1].tv_sec = (typeof(ts[1].tv_sec)) 0xcafef00ddeadbeefLL;
168 ts[1].tv_nsec = 0;
169
170 k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
171 printf("utimensat(" str_at_fdcwd ", %s, [", qname);
172 print_ts(&ts[0]);
173 printf(", ");
174 print_ts(&ts[1]);
175 printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
176
177 ts[0].tv_sec = 0xdeadbeefU;
178 ts[0].tv_nsec = 0xfacefeedU;
179 ts[1].tv_sec = (typeof(ts[1].tv_sec)) 0xcafef00ddeadbeefLL;
180 ts[1].tv_nsec = (long) 0xbadc0dedfacefeedLL;
181
182 k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
183 printf("utimensat(" str_at_fdcwd ", %s, [", qname);
184 print_ts(&ts[0]);
185 printf(", ");
186 print_ts(&ts[1]);
187 printf("], " str_at_symlink_nofollow ") = %s\n", errstr);
188
189 ts[0].tv_nsec = UTIME_NOW;
190 ts[1].tv_nsec = UTIME_OMIT;
191 k_utimensat(kfdcwd, kfname, (uintptr_t) ts, 0x100);
192 printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
193 ", " str_at_symlink_nofollow ") = %s\n", qname, errstr);
194
195 if (F8ILL_KULONG_SUPPORTED) {
196 k_utimensat(kfdcwd, kfname, f8ill_ptr_to_kulong(ts), 0);
197 printf("utimensat(" str_at_fdcwd ", %s, %#jx, 0) = %s\n",
198 qname, (uintmax_t) f8ill_ptr_to_kulong(ts), errstr);
199 }
200
201 /* flags */
202 k_utimensat(kfdcwd, kfname, (uintptr_t) ts,
203 (kernel_ulong_t) 0xdefaced00000200);
204 printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
205 ", " str_at_removedir ") = %s\n",
206 qname, errstr);
207
208 k_utimensat(kfdcwd, kfname, (uintptr_t) ts,
209 (kernel_ulong_t) 0xdefaced00000600);
210 printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
211 ", " str_flags1 ") = %s\n",
212 qname, errstr);
213
214 k_utimensat(kfdcwd, kfname, (uintptr_t) ts, (kernel_ulong_t) -1ULL);
215 printf("utimensat(" str_at_fdcwd ", %s, " str_utime_now_omit
216 ", " str_flags2 ") = %s\n",
217 qname, errstr);
218
219 puts("+++ exited with 0 +++");
220 return 0;
221 }
222
223 #else
224
225 SKIP_MAIN_UNDEFINED("__NR_utimensat && UTIME_NOW && UTIME_OMIT")
226
227 #endif