summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_stat.c
diff options
context:
space:
mode:
authorbluhm <>2019-11-19 19:57:04 +0000
committerbluhm <>2019-11-19 19:57:04 +0000
commitab72e3a6f7e8d5c71bbba034410468781d5923b6 (patch)
treeda100b3712514c566fe948116f7926ad7f725401 /src/regress/lib/libc/sys/t_stat.c
parentb927c8bafda5c010ea09be8970798ecb83848e85 (diff)
downloadopenbsd-ab72e3a6f7e8d5c71bbba034410468781d5923b6.tar.gz
openbsd-ab72e3a6f7e8d5c71bbba034410468781d5923b6.tar.bz2
openbsd-ab72e3a6f7e8d5c71bbba034410468781d5923b6.zip
Import NetBSD system call regression tests. They were written with
ATF (Automated Testing Framework), so we use a small wrapper to map it to our bsd.regress.mk framework. Only half of the 80 NetBSD tests have been taken, the others need more work to adapt. Of them 34 syscall tests pass. Moritz Buhl ported the tests to OpenBSD.
Diffstat (limited to 'src/regress/lib/libc/sys/t_stat.c')
-rw-r--r--src/regress/lib/libc/sys/t_stat.c423
1 files changed, 423 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_stat.c b/src/regress/lib/libc/sys/t_stat.c
new file mode 100644
index 0000000000..ea7f4b24a2
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_stat.c
@@ -0,0 +1,423 @@
1/* $OpenBSD: t_stat.c,v 1.1.1.1 2019/11/19 19:57:04 bluhm Exp $ */
2/* $NetBSD: t_stat.c,v 1.5 2017/01/13 20:06:50 christos Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/cdefs.h>
36__RCSID("$NetBSD: t_stat.c,v 1.5 2017/01/13 20:06:50 christos Exp $");
37
38#include <sys/stat.h>
39#include <sys/socket.h>
40#include <sys/types.h>
41
42#include <arpa/inet.h>
43#include <netinet/in.h>
44
45#include "atf-c.h"
46#include <errno.h>
47#include <fcntl.h>
48#include <fts.h>
49#include <limits.h>
50#include <string.h>
51#include <unistd.h>
52
53#include <stdio.h>
54
55static const char *path = "stat";
56
57ATF_TC_WITH_CLEANUP(stat_chflags);
58ATF_TC_HEAD(stat_chflags, tc)
59{
60 atf_tc_set_md_var(tc, "descr", "Test chflags(2) with stat(2)");
61}
62
63ATF_TC_BODY(stat_chflags, tc)
64{
65 struct stat sa, sb;
66 int fd;
67
68 (void)memset(&sa, 0, sizeof(struct stat));
69 (void)memset(&sb, 0, sizeof(struct stat));
70
71 fd = open(path, O_RDONLY | O_CREAT);
72
73 ATF_REQUIRE(fd != -1);
74 ATF_REQUIRE(stat(path, &sa) == 0);
75 ATF_REQUIRE(chflags(path, UF_NODUMP) == 0);
76 ATF_REQUIRE(stat(path, &sb) == 0);
77
78 if (sa.st_flags == sb.st_flags)
79 atf_tc_fail("stat(2) did not detect chflags(2)");
80
81 ATF_REQUIRE(close(fd) == 0);
82 ATF_REQUIRE(unlink(path) == 0);
83}
84
85ATF_TC_CLEANUP(stat_chflags, tc)
86{
87 (void)unlink(path);
88}
89
90ATF_TC(stat_dir);
91ATF_TC_HEAD(stat_dir, tc)
92{
93 atf_tc_set_md_var(tc, "descr", "Test stat(2) with directories");
94}
95
96ATF_TC_BODY(stat_dir, tc)
97{
98 const short depth = 2;
99 struct stat sa, sb;
100 char *argv[2];
101 FTSENT *ftse;
102 FTS *fts;
103 int ops;
104
105 argv[1] = NULL;
106 argv[0] = __UNCONST("/");
107
108 ops = FTS_NOCHDIR;
109 ops |= FTS_PHYSICAL;
110
111 fts = fts_open(argv, ops, NULL);
112 ATF_REQUIRE(fts != NULL);
113
114 while ((ftse = fts_read(fts)) != NULL) {
115
116 if (ftse->fts_level < 1)
117 continue;
118
119 if (ftse->fts_level > depth) {
120 (void)fts_set(fts, ftse, FTS_SKIP);
121 continue;
122 }
123
124 switch(ftse->fts_info) {
125
126 case FTS_DP:
127
128 (void)memset(&sa, 0, sizeof(struct stat));
129 (void)memset(&sb, 0, sizeof(struct stat));
130
131 ATF_REQUIRE(stat(ftse->fts_parent->fts_path,&sa) == 0);
132 ATF_REQUIRE(chdir(ftse->fts_path) == 0);
133 ATF_REQUIRE(stat(".", &sb) == 0);
134
135 /*
136 * The previous two stat(2) calls
137 * should be for the same directory.
138 */
139 if (sa.st_dev != sb.st_dev || sa.st_ino != sb.st_ino)
140 atf_tc_fail("inconsistent stat(2)");
141
142 /*
143 * Check that fts(3)'s stat(2)
144 * call equals the manual one.
145 */
146 if (sb.st_ino != ftse->fts_statp->st_ino)
147 atf_tc_fail("stat(2) and fts(3) differ");
148
149 break;
150
151 default:
152 break;
153 }
154 }
155
156 (void)fts_close(fts);
157}
158
159ATF_TC(stat_err);
160ATF_TC_HEAD(stat_err, tc)
161{
162 atf_tc_set_md_var(tc, "descr", "Test errors from the stat(2) family");
163}
164
165ATF_TC_BODY(stat_err, tc)
166{
167 char buf[NAME_MAX + 1];
168 struct stat st;
169
170 (void)memset(buf, 'x', sizeof(buf));
171
172 errno = 0;
173 ATF_REQUIRE_ERRNO(EBADF, fstat(-1, &st) == -1);
174
175 errno = 0;
176 ATF_REQUIRE_ERRNO(ENAMETOOLONG, stat(buf, &st) == -1);
177
178 errno = 0;
179 ATF_REQUIRE_ERRNO(ENAMETOOLONG, lstat(buf, &st) == -1);
180
181 errno = 0;
182 ATF_REQUIRE_ERRNO(EFAULT, stat((void *)-1, &st) == -1);
183
184 errno = 0;
185 ATF_REQUIRE_ERRNO(EFAULT, lstat((void *)-1, &st) == -1);
186
187 errno = 0;
188 ATF_REQUIRE_ERRNO(EFAULT, stat("/etc/passwd", (void *)-1) == -1);
189
190 errno = 0;
191 ATF_REQUIRE_ERRNO(EFAULT, lstat("/etc/passwd", (void *)-1) == -1);
192
193 errno = 0;
194 ATF_REQUIRE_ERRNO(ENOENT, stat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
195
196 errno = 0;
197 ATF_REQUIRE_ERRNO(ENOENT, lstat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
198}
199
200ATF_TC_WITH_CLEANUP(stat_mtime);
201ATF_TC_HEAD(stat_mtime, tc)
202{
203 atf_tc_set_md_var(tc, "descr", "Test modification times with stat(2)");
204}
205
206ATF_TC_BODY(stat_mtime, tc)
207{
208 struct stat sa, sb;
209 int fd[3];
210 size_t i;
211
212 for (i = 0; i < __arraycount(fd); i++) {
213
214 (void)memset(&sa, 0, sizeof(struct stat));
215 (void)memset(&sb, 0, sizeof(struct stat));
216
217 fd[i] = open(path, O_WRONLY | O_CREAT);
218
219 ATF_REQUIRE(fd[i] != -1);
220 ATF_REQUIRE(write(fd[i], "X", 1) == 1);
221 ATF_REQUIRE(stat(path, &sa) == 0);
222
223 (void)sleep(1);
224
225 ATF_REQUIRE(write(fd[i], "X", 1) == 1);
226 ATF_REQUIRE(stat(path, &sb) == 0);
227
228 ATF_REQUIRE(close(fd[i]) == 0);
229 ATF_REQUIRE(unlink(path) == 0);
230
231 if (sa.st_mtime == sb.st_mtime)
232 atf_tc_fail("mtimes did not change");
233 }
234}
235
236ATF_TC_CLEANUP(stat_mtime, tc)
237{
238 (void)unlink(path);
239}
240
241ATF_TC_WITH_CLEANUP(stat_perm);
242ATF_TC_HEAD(stat_perm, tc)
243{
244 atf_tc_set_md_var(tc, "descr", "Test permissions with stat(2)");
245 atf_tc_set_md_var(tc, "require.user", "root");
246}
247
248ATF_TC_BODY(stat_perm, tc)
249{
250 struct stat sa, sb;
251 gid_t gid;
252 uid_t uid;
253 int fd;
254
255 (void)memset(&sa, 0, sizeof(struct stat));
256 (void)memset(&sb, 0, sizeof(struct stat));
257
258 uid = getuid();
259 gid = getgid();
260
261 fd = open(path, O_RDONLY | O_CREAT);
262
263 ATF_REQUIRE(fd != -1);
264 ATF_REQUIRE(fstat(fd, &sa) == 0);
265 ATF_REQUIRE(stat(path, &sb) == 0);
266
267 if (gid != sa.st_gid || sa.st_gid != sb.st_gid)
268 atf_tc_fail("invalid GID");
269
270 if (uid != sa.st_uid || sa.st_uid != sb.st_uid)
271 atf_tc_fail("invalid UID");
272
273 ATF_REQUIRE(close(fd) == 0);
274 ATF_REQUIRE(unlink(path) == 0);
275}
276
277ATF_TC_CLEANUP(stat_perm, tc)
278{
279 (void)unlink(path);
280}
281
282ATF_TC_WITH_CLEANUP(stat_size);
283ATF_TC_HEAD(stat_size, tc)
284{
285 atf_tc_set_md_var(tc, "descr", "Test file sizes with stat(2)");
286}
287
288ATF_TC_BODY(stat_size, tc)
289{
290 struct stat sa, sb, sc;
291 const size_t n = 10;
292 size_t i;
293 int fd;
294
295 fd = open(path, O_WRONLY | O_CREAT);
296 ATF_REQUIRE(fd >= 0);
297
298 for (i = 0; i < n; i++) {
299
300 (void)memset(&sa, 0, sizeof(struct stat));
301 (void)memset(&sb, 0, sizeof(struct stat));
302 (void)memset(&sc, 0, sizeof(struct stat));
303
304 ATF_REQUIRE(fstat(fd, &sa) == 0);
305 ATF_REQUIRE(write(fd, "X", 1) == 1);
306 ATF_REQUIRE(fstat(fd, &sb) == 0);
307 ATF_REQUIRE(stat(path, &sc) == 0);
308
309 if (sa.st_size + 1 != sb.st_size)
310 atf_tc_fail("invalid file size");
311
312 if (sb.st_size != sc.st_size)
313 atf_tc_fail("stat(2) and fstat(2) mismatch");
314 }
315
316 ATF_REQUIRE(close(fd) == 0);
317 ATF_REQUIRE(unlink(path) == 0);
318}
319
320ATF_TC_CLEANUP(stat_size, tc)
321{
322 (void)unlink(path);
323}
324
325ATF_TC(stat_socket);
326ATF_TC_HEAD(stat_socket, tc)
327{
328 atf_tc_set_md_var(tc, "descr", "Test fstat(2) with "
329 "a socket (PR kern/46077)");
330}
331
332ATF_TC_BODY(stat_socket, tc)
333{
334 struct sockaddr_in addr;
335 struct stat st;
336 uint32_t iaddr;
337 int fd, flags;
338
339 (void)memset(&st, 0, sizeof(struct stat));
340 (void)memset(&addr, 0, sizeof(struct sockaddr_in));
341
342 fd = socket(AF_INET, SOCK_STREAM, 0);
343 ATF_REQUIRE(fd >= 0);
344
345 flags = fcntl(fd, F_GETFL);
346
347 ATF_REQUIRE(flags != -1);
348 ATF_REQUIRE(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1);
349 ATF_REQUIRE(inet_pton(AF_INET, "127.0.0.1", &iaddr) == 1);
350
351 addr.sin_port = htons(42);
352 addr.sin_family = AF_INET;
353 addr.sin_addr.s_addr = iaddr;
354
355 errno = 0;
356
357 ATF_REQUIRE_ERRNO(EINPROGRESS,
358 connect(fd, (struct sockaddr *)&addr,
359 sizeof(struct sockaddr_in)) == -1);
360
361 errno = 0;
362
363 if (fstat(fd, &st) != 0 || errno != 0)
364 atf_tc_fail("fstat(2) failed for a EINPROGRESS socket");
365
366 (void)close(fd);
367}
368
369ATF_TC_WITH_CLEANUP(stat_symlink);
370ATF_TC_HEAD(stat_symlink, tc)
371{
372 atf_tc_set_md_var(tc, "descr", "Test symbolic links with stat(2)");
373}
374
375ATF_TC_BODY(stat_symlink, tc)
376{
377 const char *pathlink = "pathlink";
378 struct stat sa, sb;
379 int fd;
380
381 (void)memset(&sa, 0, sizeof(struct stat));
382 (void)memset(&sb, 0, sizeof(struct stat));
383
384 fd = open(path, O_WRONLY | O_CREAT);
385
386 ATF_REQUIRE(fd >= 0);
387 ATF_REQUIRE(symlink(path, pathlink) == 0);
388 ATF_REQUIRE(stat(pathlink, &sa) == 0);
389 ATF_REQUIRE(lstat(pathlink, &sb) == 0);
390
391 if (S_ISLNK(sa.st_mode) != 0)
392 atf_tc_fail("stat(2) detected symbolic link");
393
394 if (S_ISLNK(sb.st_mode) == 0)
395 atf_tc_fail("lstat(2) did not detect symbolic link");
396
397 if (sa.st_mode == sb.st_mode)
398 atf_tc_fail("inconsistencies between stat(2) and lstat(2)");
399
400 (void)close(fd);
401 ATF_REQUIRE(unlink(path) == 0);
402 ATF_REQUIRE(unlink(pathlink) == 0);
403}
404
405ATF_TC_CLEANUP(stat_symlink, tc)
406{
407 (void)unlink(path);
408}
409
410ATF_TP_ADD_TCS(tp)
411{
412
413 ATF_TP_ADD_TC(tp, stat_chflags);
414 ATF_TP_ADD_TC(tp, stat_dir);
415 ATF_TP_ADD_TC(tp, stat_err);
416 ATF_TP_ADD_TC(tp, stat_mtime);
417 ATF_TP_ADD_TC(tp, stat_perm);
418 ATF_TP_ADD_TC(tp, stat_size);
419 ATF_TP_ADD_TC(tp, stat_socket);
420 ATF_TP_ADD_TC(tp, stat_symlink);
421
422 return atf_no_error();
423}