xref: /freebsd/contrib/netbsd-tests/lib/libc/sys/t_stat.c (revision 95c75073d3d1ca9dcae41784453172f199bb2c0f)
163d1fd59SEnji Cooper /* $NetBSD: t_stat.c,v 1.5 2017/01/13 20:06:50 christos Exp $ */
257718be8SEnji Cooper 
357718be8SEnji Cooper /*-
457718be8SEnji Cooper  * Copyright (c) 2011 The NetBSD Foundation, Inc.
557718be8SEnji Cooper  * All rights reserved.
657718be8SEnji Cooper  *
757718be8SEnji Cooper  * This code is derived from software contributed to The NetBSD Foundation
857718be8SEnji Cooper  * by Jukka Ruohonen.
957718be8SEnji Cooper  *
1057718be8SEnji Cooper  * Redistribution and use in source and binary forms, with or without
1157718be8SEnji Cooper  * modification, are permitted provided that the following conditions
1257718be8SEnji Cooper  * are met:
1357718be8SEnji Cooper  * 1. Redistributions of source code must retain the above copyright
1457718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer.
1557718be8SEnji Cooper  * 2. Redistributions in binary form must reproduce the above copyright
1657718be8SEnji Cooper  *    notice, this list of conditions and the following disclaimer in the
1757718be8SEnji Cooper  *    documentation and/or other materials provided with the distribution.
1857718be8SEnji Cooper  *
1957718be8SEnji Cooper  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2057718be8SEnji Cooper  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2157718be8SEnji Cooper  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2257718be8SEnji Cooper  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2357718be8SEnji Cooper  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2457718be8SEnji Cooper  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2557718be8SEnji Cooper  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2657718be8SEnji Cooper  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2757718be8SEnji Cooper  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2857718be8SEnji Cooper  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2957718be8SEnji Cooper  * POSSIBILITY OF SUCH DAMAGE.
3057718be8SEnji Cooper  */
3157718be8SEnji Cooper #include <sys/cdefs.h>
3263d1fd59SEnji Cooper __RCSID("$NetBSD: t_stat.c,v 1.5 2017/01/13 20:06:50 christos Exp $");
3357718be8SEnji Cooper 
3457718be8SEnji Cooper #include <sys/stat.h>
3557718be8SEnji Cooper #include <sys/socket.h>
3657718be8SEnji Cooper #include <sys/types.h>
3757718be8SEnji Cooper 
3857718be8SEnji Cooper #include <arpa/inet.h>
3963d1fd59SEnji Cooper #include <netinet/in.h>
4057718be8SEnji Cooper 
4157718be8SEnji Cooper #include <atf-c.h>
4257718be8SEnji Cooper #include <errno.h>
4357718be8SEnji Cooper #include <fcntl.h>
4457718be8SEnji Cooper #include <fts.h>
4557718be8SEnji Cooper #include <limits.h>
4657718be8SEnji Cooper #include <string.h>
4757718be8SEnji Cooper #include <unistd.h>
4857718be8SEnji Cooper 
4957718be8SEnji Cooper #include <stdio.h>
5057718be8SEnji Cooper 
5157718be8SEnji Cooper static const char *path = "stat";
5257718be8SEnji Cooper 
5357718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_chflags);
ATF_TC_HEAD(stat_chflags,tc)5457718be8SEnji Cooper ATF_TC_HEAD(stat_chflags, tc)
5557718be8SEnji Cooper {
5657718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test chflags(2) with stat(2)");
5757718be8SEnji Cooper }
5857718be8SEnji Cooper 
ATF_TC_BODY(stat_chflags,tc)5957718be8SEnji Cooper ATF_TC_BODY(stat_chflags, tc)
6057718be8SEnji Cooper {
6157718be8SEnji Cooper 	struct stat sa, sb;
6257718be8SEnji Cooper 	int fd;
6357718be8SEnji Cooper 
6457718be8SEnji Cooper 	(void)memset(&sa, 0, sizeof(struct stat));
6557718be8SEnji Cooper 	(void)memset(&sb, 0, sizeof(struct stat));
6657718be8SEnji Cooper 
671575a795SBrooks Davis 	fd = open(path, O_RDONLY | O_CREAT, 0600);
6857718be8SEnji Cooper 
6957718be8SEnji Cooper 	ATF_REQUIRE(fd != -1);
7057718be8SEnji Cooper 	ATF_REQUIRE(stat(path, &sa) == 0);
7157718be8SEnji Cooper 	ATF_REQUIRE(chflags(path, UF_NODUMP) == 0);
7257718be8SEnji Cooper 	ATF_REQUIRE(stat(path, &sb) == 0);
7357718be8SEnji Cooper 
7457718be8SEnji Cooper 	if (sa.st_flags == sb.st_flags)
7557718be8SEnji Cooper 		atf_tc_fail("stat(2) did not detect chflags(2)");
7657718be8SEnji Cooper 
7757718be8SEnji Cooper 	ATF_REQUIRE(close(fd) == 0);
7857718be8SEnji Cooper 	ATF_REQUIRE(unlink(path) == 0);
7957718be8SEnji Cooper }
8057718be8SEnji Cooper 
ATF_TC_CLEANUP(stat_chflags,tc)8157718be8SEnji Cooper ATF_TC_CLEANUP(stat_chflags, tc)
8257718be8SEnji Cooper {
8357718be8SEnji Cooper 	(void)unlink(path);
8457718be8SEnji Cooper }
8557718be8SEnji Cooper 
8657718be8SEnji Cooper ATF_TC(stat_dir);
ATF_TC_HEAD(stat_dir,tc)8757718be8SEnji Cooper ATF_TC_HEAD(stat_dir, tc)
8857718be8SEnji Cooper {
8957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test stat(2) with directories");
9057718be8SEnji Cooper }
9157718be8SEnji Cooper 
ATF_TC_BODY(stat_dir,tc)9257718be8SEnji Cooper ATF_TC_BODY(stat_dir, tc)
9357718be8SEnji Cooper {
9457718be8SEnji Cooper 	const short depth = 2;
9557718be8SEnji Cooper 	struct stat sa, sb;
9657718be8SEnji Cooper 	char *argv[2];
9757718be8SEnji Cooper 	FTSENT *ftse;
9857718be8SEnji Cooper 	FTS *fts;
9957718be8SEnji Cooper 	int ops;
10057718be8SEnji Cooper 
10157718be8SEnji Cooper 	argv[1] = NULL;
10257718be8SEnji Cooper 	argv[0] = __UNCONST("/");
10357718be8SEnji Cooper 
10457718be8SEnji Cooper 	ops = FTS_NOCHDIR;
10557718be8SEnji Cooper 	ops |= FTS_PHYSICAL;
10657718be8SEnji Cooper 
10757718be8SEnji Cooper 	fts = fts_open(argv, ops, NULL);
10857718be8SEnji Cooper 	ATF_REQUIRE(fts != NULL);
10957718be8SEnji Cooper 
11057718be8SEnji Cooper 	while ((ftse = fts_read(fts)) != NULL) {
11157718be8SEnji Cooper 
11257718be8SEnji Cooper 		if (ftse->fts_level < 1)
11357718be8SEnji Cooper 			continue;
11457718be8SEnji Cooper 
11557718be8SEnji Cooper 		if (ftse->fts_level > depth) {
11657718be8SEnji Cooper 			(void)fts_set(fts, ftse, FTS_SKIP);
11757718be8SEnji Cooper 			continue;
11857718be8SEnji Cooper 		}
11957718be8SEnji Cooper 
12057718be8SEnji Cooper 		switch(ftse->fts_info) {
12157718be8SEnji Cooper 
12257718be8SEnji Cooper 		case FTS_DP:
12357718be8SEnji Cooper 
12457718be8SEnji Cooper 			(void)memset(&sa, 0, sizeof(struct stat));
12557718be8SEnji Cooper 			(void)memset(&sb, 0, sizeof(struct stat));
12657718be8SEnji Cooper 
12757718be8SEnji Cooper 			ATF_REQUIRE(stat(ftse->fts_parent->fts_path,&sa) == 0);
12857718be8SEnji Cooper 			ATF_REQUIRE(chdir(ftse->fts_path) == 0);
12957718be8SEnji Cooper 			ATF_REQUIRE(stat(".", &sb) == 0);
13057718be8SEnji Cooper 
13157718be8SEnji Cooper 			/*
13257718be8SEnji Cooper 			 * The previous two stat(2) calls
13357718be8SEnji Cooper 			 * should be for the same directory.
13457718be8SEnji Cooper 			 */
13557718be8SEnji Cooper 			if (sa.st_dev != sb.st_dev || sa.st_ino != sb.st_ino)
13657718be8SEnji Cooper 				atf_tc_fail("inconsistent stat(2)");
13757718be8SEnji Cooper 
13857718be8SEnji Cooper 			/*
13957718be8SEnji Cooper 			 * Check that fts(3)'s stat(2)
14057718be8SEnji Cooper 			 * call equals the manual one.
14157718be8SEnji Cooper 			 */
14257718be8SEnji Cooper 			if (sb.st_ino != ftse->fts_statp->st_ino)
14357718be8SEnji Cooper 				atf_tc_fail("stat(2) and fts(3) differ");
14457718be8SEnji Cooper 
14557718be8SEnji Cooper 			break;
14657718be8SEnji Cooper 
14757718be8SEnji Cooper 		default:
14857718be8SEnji Cooper 			break;
14957718be8SEnji Cooper 		}
15057718be8SEnji Cooper 	}
15157718be8SEnji Cooper 
15257718be8SEnji Cooper 	(void)fts_close(fts);
15357718be8SEnji Cooper }
15457718be8SEnji Cooper 
15557718be8SEnji Cooper ATF_TC(stat_err);
ATF_TC_HEAD(stat_err,tc)15657718be8SEnji Cooper ATF_TC_HEAD(stat_err, tc)
15757718be8SEnji Cooper {
15857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test errors from the stat(2) family");
15957718be8SEnji Cooper }
16057718be8SEnji Cooper 
ATF_TC_BODY(stat_err,tc)16157718be8SEnji Cooper ATF_TC_BODY(stat_err, tc)
16257718be8SEnji Cooper {
16357718be8SEnji Cooper 	char buf[NAME_MAX + 1];
16457718be8SEnji Cooper 	struct stat st;
16557718be8SEnji Cooper 
16657718be8SEnji Cooper 	(void)memset(buf, 'x', sizeof(buf));
16757718be8SEnji Cooper 
16857718be8SEnji Cooper 	errno = 0;
16957718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(EBADF, fstat(-1, &st) == -1);
17057718be8SEnji Cooper 
17157718be8SEnji Cooper 	errno = 0;
17257718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(ENAMETOOLONG, stat(buf, &st) == -1);
17357718be8SEnji Cooper 
17457718be8SEnji Cooper 	errno = 0;
17557718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(ENAMETOOLONG, lstat(buf, &st) == -1);
17657718be8SEnji Cooper 
17757718be8SEnji Cooper 	errno = 0;
17857718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(EFAULT, stat((void *)-1, &st) == -1);
17957718be8SEnji Cooper 
18057718be8SEnji Cooper 	errno = 0;
18157718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(EFAULT, lstat((void *)-1, &st) == -1);
18257718be8SEnji Cooper 
18357718be8SEnji Cooper 	errno = 0;
18457718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(EFAULT, stat("/etc/passwd", (void *)-1) == -1);
18557718be8SEnji Cooper 
18657718be8SEnji Cooper 	errno = 0;
18757718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(EFAULT, lstat("/etc/passwd", (void *)-1) == -1);
18857718be8SEnji Cooper 
18957718be8SEnji Cooper 	errno = 0;
19057718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOENT, stat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
19157718be8SEnji Cooper 
19257718be8SEnji Cooper 	errno = 0;
19357718be8SEnji Cooper 	ATF_REQUIRE_ERRNO(ENOENT, lstat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
19457718be8SEnji Cooper }
19557718be8SEnji Cooper 
19657718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_mtime);
ATF_TC_HEAD(stat_mtime,tc)19757718be8SEnji Cooper ATF_TC_HEAD(stat_mtime, tc)
19857718be8SEnji Cooper {
19957718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test modification times with stat(2)");
20057718be8SEnji Cooper }
20157718be8SEnji Cooper 
ATF_TC_BODY(stat_mtime,tc)20257718be8SEnji Cooper ATF_TC_BODY(stat_mtime, tc)
20357718be8SEnji Cooper {
20457718be8SEnji Cooper 	struct stat sa, sb;
20557718be8SEnji Cooper 	int fd[3];
20657718be8SEnji Cooper 	size_t i;
20757718be8SEnji Cooper 
20857718be8SEnji Cooper 	for (i = 0; i < __arraycount(fd); i++) {
20957718be8SEnji Cooper 
21057718be8SEnji Cooper 		(void)memset(&sa, 0, sizeof(struct stat));
21157718be8SEnji Cooper 		(void)memset(&sb, 0, sizeof(struct stat));
21257718be8SEnji Cooper 
2131575a795SBrooks Davis 		fd[i] = open(path, O_WRONLY | O_CREAT, 0600);
21457718be8SEnji Cooper 
21557718be8SEnji Cooper 		ATF_REQUIRE(fd[i] != -1);
21657718be8SEnji Cooper 		ATF_REQUIRE(write(fd[i], "X", 1) == 1);
21757718be8SEnji Cooper 		ATF_REQUIRE(stat(path, &sa) == 0);
21857718be8SEnji Cooper 
21957718be8SEnji Cooper 		(void)sleep(1);
22057718be8SEnji Cooper 
22157718be8SEnji Cooper 		ATF_REQUIRE(write(fd[i], "X", 1) == 1);
22257718be8SEnji Cooper 		ATF_REQUIRE(stat(path, &sb) == 0);
22357718be8SEnji Cooper 
22457718be8SEnji Cooper 		ATF_REQUIRE(close(fd[i]) == 0);
22557718be8SEnji Cooper 		ATF_REQUIRE(unlink(path) == 0);
22657718be8SEnji Cooper 
22757718be8SEnji Cooper 		if (sa.st_mtime == sb.st_mtime)
22857718be8SEnji Cooper 			atf_tc_fail("mtimes did not change");
22957718be8SEnji Cooper 	}
23057718be8SEnji Cooper }
23157718be8SEnji Cooper 
ATF_TC_CLEANUP(stat_mtime,tc)23257718be8SEnji Cooper ATF_TC_CLEANUP(stat_mtime, tc)
23357718be8SEnji Cooper {
23457718be8SEnji Cooper 	(void)unlink(path);
23557718be8SEnji Cooper }
23657718be8SEnji Cooper 
23757718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_perm);
ATF_TC_HEAD(stat_perm,tc)23857718be8SEnji Cooper ATF_TC_HEAD(stat_perm, tc)
23957718be8SEnji Cooper {
24057718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test permissions with stat(2)");
24157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "require.user", "root");
24257718be8SEnji Cooper }
24357718be8SEnji Cooper 
ATF_TC_BODY(stat_perm,tc)24457718be8SEnji Cooper ATF_TC_BODY(stat_perm, tc)
24557718be8SEnji Cooper {
24657718be8SEnji Cooper 	struct stat sa, sb;
24757718be8SEnji Cooper 	gid_t gid;
24857718be8SEnji Cooper 	uid_t uid;
24957718be8SEnji Cooper 	int fd;
25057718be8SEnji Cooper 
25157718be8SEnji Cooper 	(void)memset(&sa, 0, sizeof(struct stat));
25257718be8SEnji Cooper 	(void)memset(&sb, 0, sizeof(struct stat));
25357718be8SEnji Cooper 
25457718be8SEnji Cooper 	uid = getuid();
25557718be8SEnji Cooper 	gid = getgid();
25657718be8SEnji Cooper 
2571575a795SBrooks Davis 	fd = open(path, O_RDONLY | O_CREAT, 0600);
25857718be8SEnji Cooper 
25957718be8SEnji Cooper 	ATF_REQUIRE(fd != -1);
26057718be8SEnji Cooper 	ATF_REQUIRE(fstat(fd, &sa) == 0);
26157718be8SEnji Cooper 	ATF_REQUIRE(stat(path, &sb) == 0);
26257718be8SEnji Cooper 
26357718be8SEnji Cooper 	if (gid != sa.st_gid || sa.st_gid != sb.st_gid)
26457718be8SEnji Cooper 		atf_tc_fail("invalid GID");
26557718be8SEnji Cooper 
26657718be8SEnji Cooper 	if (uid != sa.st_uid || sa.st_uid != sb.st_uid)
26757718be8SEnji Cooper 		atf_tc_fail("invalid UID");
26857718be8SEnji Cooper 
26957718be8SEnji Cooper 	ATF_REQUIRE(close(fd) == 0);
27057718be8SEnji Cooper 	ATF_REQUIRE(unlink(path) == 0);
27157718be8SEnji Cooper }
27257718be8SEnji Cooper 
ATF_TC_CLEANUP(stat_perm,tc)27357718be8SEnji Cooper ATF_TC_CLEANUP(stat_perm, tc)
27457718be8SEnji Cooper {
27557718be8SEnji Cooper 	(void)unlink(path);
27657718be8SEnji Cooper }
27757718be8SEnji Cooper 
27857718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_size);
ATF_TC_HEAD(stat_size,tc)27957718be8SEnji Cooper ATF_TC_HEAD(stat_size, tc)
28057718be8SEnji Cooper {
28157718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test file sizes with stat(2)");
28257718be8SEnji Cooper }
28357718be8SEnji Cooper 
ATF_TC_BODY(stat_size,tc)28457718be8SEnji Cooper ATF_TC_BODY(stat_size, tc)
28557718be8SEnji Cooper {
28657718be8SEnji Cooper 	struct stat sa, sb, sc;
28757718be8SEnji Cooper 	const size_t n = 10;
28857718be8SEnji Cooper 	size_t i;
28957718be8SEnji Cooper 	int fd;
29057718be8SEnji Cooper 
2911575a795SBrooks Davis 	fd = open(path, O_WRONLY | O_CREAT, 0600);
29257718be8SEnji Cooper 	ATF_REQUIRE(fd >= 0);
29357718be8SEnji Cooper 
29457718be8SEnji Cooper 	for (i = 0; i < n; i++) {
29557718be8SEnji Cooper 
29657718be8SEnji Cooper 		(void)memset(&sa, 0, sizeof(struct stat));
29757718be8SEnji Cooper 		(void)memset(&sb, 0, sizeof(struct stat));
29857718be8SEnji Cooper 		(void)memset(&sc, 0, sizeof(struct stat));
29957718be8SEnji Cooper 
30057718be8SEnji Cooper 		ATF_REQUIRE(fstat(fd, &sa) == 0);
30157718be8SEnji Cooper 		ATF_REQUIRE(write(fd, "X", 1) == 1);
30257718be8SEnji Cooper 		ATF_REQUIRE(fstat(fd, &sb) == 0);
30357718be8SEnji Cooper 		ATF_REQUIRE(stat(path, &sc) == 0);
30457718be8SEnji Cooper 
30557718be8SEnji Cooper 		if (sa.st_size + 1 != sb.st_size)
30657718be8SEnji Cooper 			atf_tc_fail("invalid file size");
30757718be8SEnji Cooper 
30857718be8SEnji Cooper 		if (sb.st_size != sc.st_size)
30957718be8SEnji Cooper 			atf_tc_fail("stat(2) and fstat(2) mismatch");
31057718be8SEnji Cooper 	}
31157718be8SEnji Cooper 
31257718be8SEnji Cooper 	ATF_REQUIRE(close(fd) == 0);
31357718be8SEnji Cooper 	ATF_REQUIRE(unlink(path) == 0);
31457718be8SEnji Cooper }
31557718be8SEnji Cooper 
ATF_TC_CLEANUP(stat_size,tc)31657718be8SEnji Cooper ATF_TC_CLEANUP(stat_size, tc)
31757718be8SEnji Cooper {
31857718be8SEnji Cooper 	(void)unlink(path);
31957718be8SEnji Cooper }
32057718be8SEnji Cooper 
32157718be8SEnji Cooper ATF_TC(stat_socket);
ATF_TC_HEAD(stat_socket,tc)32257718be8SEnji Cooper ATF_TC_HEAD(stat_socket, tc)
32357718be8SEnji Cooper {
32457718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test fstat(2) with "
32557718be8SEnji Cooper 	    "a socket (PR kern/46077)");
32657718be8SEnji Cooper }
32757718be8SEnji Cooper 
ATF_TC_BODY(stat_socket,tc)32857718be8SEnji Cooper ATF_TC_BODY(stat_socket, tc)
32957718be8SEnji Cooper {
33057718be8SEnji Cooper 	struct sockaddr_in addr;
33157718be8SEnji Cooper 	struct stat st;
33257718be8SEnji Cooper 	uint32_t iaddr;
33357718be8SEnji Cooper 	int fd, flags;
33457718be8SEnji Cooper 
33557718be8SEnji Cooper 	(void)memset(&st, 0, sizeof(struct stat));
33657718be8SEnji Cooper 	(void)memset(&addr, 0, sizeof(struct sockaddr_in));
33757718be8SEnji Cooper 
33857718be8SEnji Cooper 	fd = socket(AF_INET, SOCK_STREAM, 0);
33957718be8SEnji Cooper 	ATF_REQUIRE(fd >= 0);
34057718be8SEnji Cooper 
34157718be8SEnji Cooper 	flags = fcntl(fd, F_GETFL);
34257718be8SEnji Cooper 
34357718be8SEnji Cooper 	ATF_REQUIRE(flags != -1);
34457718be8SEnji Cooper 	ATF_REQUIRE(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1);
34557718be8SEnji Cooper 	ATF_REQUIRE(inet_pton(AF_INET, "127.0.0.1", &iaddr) == 1);
34657718be8SEnji Cooper 
34757718be8SEnji Cooper 	addr.sin_port = htons(42);
34857718be8SEnji Cooper 	addr.sin_family = AF_INET;
34957718be8SEnji Cooper 	addr.sin_addr.s_addr = iaddr;
35057718be8SEnji Cooper 
35157718be8SEnji Cooper 	errno = 0;
35257718be8SEnji Cooper 
353*95c75073SMark Johnston 	ATF_REQUIRE(connect(fd, (struct sockaddr *)&addr,
35457718be8SEnji Cooper 	    sizeof(struct sockaddr_in)) == -1);
355*95c75073SMark Johnston 	ATF_REQUIRE(errno == EINPROGRESS || errno == ECONNREFUSED);
35657718be8SEnji Cooper 
35757718be8SEnji Cooper 	errno = 0;
35857718be8SEnji Cooper 
35957718be8SEnji Cooper 	if (fstat(fd, &st) != 0 || errno != 0)
360*95c75073SMark Johnston 		atf_tc_fail("fstat(2) failed for a socket");
36157718be8SEnji Cooper 
36257718be8SEnji Cooper 	(void)close(fd);
36357718be8SEnji Cooper }
36457718be8SEnji Cooper 
36557718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_symlink);
ATF_TC_HEAD(stat_symlink,tc)36657718be8SEnji Cooper ATF_TC_HEAD(stat_symlink, tc)
36757718be8SEnji Cooper {
36857718be8SEnji Cooper 	atf_tc_set_md_var(tc, "descr", "Test symbolic links with stat(2)");
36957718be8SEnji Cooper }
37057718be8SEnji Cooper 
ATF_TC_BODY(stat_symlink,tc)37157718be8SEnji Cooper ATF_TC_BODY(stat_symlink, tc)
37257718be8SEnji Cooper {
37357718be8SEnji Cooper 	const char *pathlink = "pathlink";
37457718be8SEnji Cooper 	struct stat sa, sb;
37557718be8SEnji Cooper 	int fd;
37657718be8SEnji Cooper 
37757718be8SEnji Cooper 	(void)memset(&sa, 0, sizeof(struct stat));
37857718be8SEnji Cooper 	(void)memset(&sb, 0, sizeof(struct stat));
37957718be8SEnji Cooper 
3801575a795SBrooks Davis 	fd = open(path, O_WRONLY | O_CREAT, 0600);
38157718be8SEnji Cooper 
38257718be8SEnji Cooper 	ATF_REQUIRE(fd >= 0);
38357718be8SEnji Cooper 	ATF_REQUIRE(symlink(path, pathlink) == 0);
38457718be8SEnji Cooper 	ATF_REQUIRE(stat(pathlink, &sa) == 0);
38557718be8SEnji Cooper 	ATF_REQUIRE(lstat(pathlink, &sb) == 0);
38657718be8SEnji Cooper 
38757718be8SEnji Cooper 	if (S_ISLNK(sa.st_mode) != 0)
38857718be8SEnji Cooper 		atf_tc_fail("stat(2) detected symbolic link");
38957718be8SEnji Cooper 
39057718be8SEnji Cooper 	if (S_ISLNK(sb.st_mode) == 0)
39157718be8SEnji Cooper 		atf_tc_fail("lstat(2) did not detect symbolic link");
39257718be8SEnji Cooper 
39357718be8SEnji Cooper 	if (sa.st_mode == sb.st_mode)
39457718be8SEnji Cooper 		atf_tc_fail("inconsistencies between stat(2) and lstat(2)");
39557718be8SEnji Cooper 
39663d1fd59SEnji Cooper 	(void)close(fd);
39757718be8SEnji Cooper 	ATF_REQUIRE(unlink(path) == 0);
39857718be8SEnji Cooper 	ATF_REQUIRE(unlink(pathlink) == 0);
39957718be8SEnji Cooper }
40057718be8SEnji Cooper 
ATF_TC_CLEANUP(stat_symlink,tc)40157718be8SEnji Cooper ATF_TC_CLEANUP(stat_symlink, tc)
40257718be8SEnji Cooper {
40357718be8SEnji Cooper 	(void)unlink(path);
40457718be8SEnji Cooper }
40557718be8SEnji Cooper 
ATF_TP_ADD_TCS(tp)40657718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
40757718be8SEnji Cooper {
40857718be8SEnji Cooper 
40957718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_chflags);
41057718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_dir);
41157718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_err);
41257718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_mtime);
41357718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_perm);
41457718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_size);
41557718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_socket);
41657718be8SEnji Cooper 	ATF_TP_ADD_TC(tp, stat_symlink);
41757718be8SEnji Cooper 
41857718be8SEnji Cooper 	return atf_no_error();
41957718be8SEnji Cooper }
420