1*63d1fd59SEnji 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> 32*63d1fd59SEnji 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> 39*63d1fd59SEnji 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 51ff0ba872SEnji Cooper #ifdef __FreeBSD__ 52a39196afSEnji Cooper #include <netinet/in.h> 53a39196afSEnji Cooper #endif 54a39196afSEnji Cooper 5557718be8SEnji Cooper static const char *path = "stat"; 5657718be8SEnji Cooper 5757718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_chflags); 5857718be8SEnji Cooper ATF_TC_HEAD(stat_chflags, tc) 5957718be8SEnji Cooper { 6057718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test chflags(2) with stat(2)"); 6157718be8SEnji Cooper } 6257718be8SEnji Cooper 6357718be8SEnji Cooper ATF_TC_BODY(stat_chflags, tc) 6457718be8SEnji Cooper { 6557718be8SEnji Cooper struct stat sa, sb; 6657718be8SEnji Cooper int fd; 6757718be8SEnji Cooper 6857718be8SEnji Cooper (void)memset(&sa, 0, sizeof(struct stat)); 6957718be8SEnji Cooper (void)memset(&sb, 0, sizeof(struct stat)); 7057718be8SEnji Cooper 7157718be8SEnji Cooper fd = open(path, O_RDONLY | O_CREAT); 7257718be8SEnji Cooper 7357718be8SEnji Cooper ATF_REQUIRE(fd != -1); 7457718be8SEnji Cooper ATF_REQUIRE(stat(path, &sa) == 0); 7557718be8SEnji Cooper ATF_REQUIRE(chflags(path, UF_NODUMP) == 0); 7657718be8SEnji Cooper ATF_REQUIRE(stat(path, &sb) == 0); 7757718be8SEnji Cooper 7857718be8SEnji Cooper if (sa.st_flags == sb.st_flags) 7957718be8SEnji Cooper atf_tc_fail("stat(2) did not detect chflags(2)"); 8057718be8SEnji Cooper 8157718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 8257718be8SEnji Cooper ATF_REQUIRE(unlink(path) == 0); 8357718be8SEnji Cooper } 8457718be8SEnji Cooper 8557718be8SEnji Cooper ATF_TC_CLEANUP(stat_chflags, tc) 8657718be8SEnji Cooper { 8757718be8SEnji Cooper (void)unlink(path); 8857718be8SEnji Cooper } 8957718be8SEnji Cooper 9057718be8SEnji Cooper ATF_TC(stat_dir); 9157718be8SEnji Cooper ATF_TC_HEAD(stat_dir, tc) 9257718be8SEnji Cooper { 9357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test stat(2) with directories"); 9457718be8SEnji Cooper } 9557718be8SEnji Cooper 9657718be8SEnji Cooper ATF_TC_BODY(stat_dir, tc) 9757718be8SEnji Cooper { 9857718be8SEnji Cooper const short depth = 2; 9957718be8SEnji Cooper struct stat sa, sb; 10057718be8SEnji Cooper char *argv[2]; 10157718be8SEnji Cooper FTSENT *ftse; 10257718be8SEnji Cooper FTS *fts; 10357718be8SEnji Cooper int ops; 10457718be8SEnji Cooper 10557718be8SEnji Cooper argv[1] = NULL; 10657718be8SEnji Cooper argv[0] = __UNCONST("/"); 10757718be8SEnji Cooper 10857718be8SEnji Cooper ops = FTS_NOCHDIR; 10957718be8SEnji Cooper ops |= FTS_PHYSICAL; 11057718be8SEnji Cooper 11157718be8SEnji Cooper fts = fts_open(argv, ops, NULL); 11257718be8SEnji Cooper ATF_REQUIRE(fts != NULL); 11357718be8SEnji Cooper 11457718be8SEnji Cooper while ((ftse = fts_read(fts)) != NULL) { 11557718be8SEnji Cooper 11657718be8SEnji Cooper if (ftse->fts_level < 1) 11757718be8SEnji Cooper continue; 11857718be8SEnji Cooper 11957718be8SEnji Cooper if (ftse->fts_level > depth) { 12057718be8SEnji Cooper (void)fts_set(fts, ftse, FTS_SKIP); 12157718be8SEnji Cooper continue; 12257718be8SEnji Cooper } 12357718be8SEnji Cooper 12457718be8SEnji Cooper switch(ftse->fts_info) { 12557718be8SEnji Cooper 12657718be8SEnji Cooper case FTS_DP: 12757718be8SEnji Cooper 12857718be8SEnji Cooper (void)memset(&sa, 0, sizeof(struct stat)); 12957718be8SEnji Cooper (void)memset(&sb, 0, sizeof(struct stat)); 13057718be8SEnji Cooper 13157718be8SEnji Cooper ATF_REQUIRE(stat(ftse->fts_parent->fts_path,&sa) == 0); 13257718be8SEnji Cooper ATF_REQUIRE(chdir(ftse->fts_path) == 0); 13357718be8SEnji Cooper ATF_REQUIRE(stat(".", &sb) == 0); 13457718be8SEnji Cooper 13557718be8SEnji Cooper /* 13657718be8SEnji Cooper * The previous two stat(2) calls 13757718be8SEnji Cooper * should be for the same directory. 13857718be8SEnji Cooper */ 13957718be8SEnji Cooper if (sa.st_dev != sb.st_dev || sa.st_ino != sb.st_ino) 14057718be8SEnji Cooper atf_tc_fail("inconsistent stat(2)"); 14157718be8SEnji Cooper 14257718be8SEnji Cooper /* 14357718be8SEnji Cooper * Check that fts(3)'s stat(2) 14457718be8SEnji Cooper * call equals the manual one. 14557718be8SEnji Cooper */ 14657718be8SEnji Cooper if (sb.st_ino != ftse->fts_statp->st_ino) 14757718be8SEnji Cooper atf_tc_fail("stat(2) and fts(3) differ"); 14857718be8SEnji Cooper 14957718be8SEnji Cooper break; 15057718be8SEnji Cooper 15157718be8SEnji Cooper default: 15257718be8SEnji Cooper break; 15357718be8SEnji Cooper } 15457718be8SEnji Cooper } 15557718be8SEnji Cooper 15657718be8SEnji Cooper (void)fts_close(fts); 15757718be8SEnji Cooper } 15857718be8SEnji Cooper 15957718be8SEnji Cooper ATF_TC(stat_err); 16057718be8SEnji Cooper ATF_TC_HEAD(stat_err, tc) 16157718be8SEnji Cooper { 16257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test errors from the stat(2) family"); 16357718be8SEnji Cooper } 16457718be8SEnji Cooper 16557718be8SEnji Cooper ATF_TC_BODY(stat_err, tc) 16657718be8SEnji Cooper { 16757718be8SEnji Cooper char buf[NAME_MAX + 1]; 16857718be8SEnji Cooper struct stat st; 16957718be8SEnji Cooper 17057718be8SEnji Cooper (void)memset(buf, 'x', sizeof(buf)); 17157718be8SEnji Cooper 17257718be8SEnji Cooper errno = 0; 17357718be8SEnji Cooper ATF_REQUIRE_ERRNO(EBADF, fstat(-1, &st) == -1); 17457718be8SEnji Cooper 17557718be8SEnji Cooper errno = 0; 17657718be8SEnji Cooper ATF_REQUIRE_ERRNO(ENAMETOOLONG, stat(buf, &st) == -1); 17757718be8SEnji Cooper 17857718be8SEnji Cooper errno = 0; 17957718be8SEnji Cooper ATF_REQUIRE_ERRNO(ENAMETOOLONG, lstat(buf, &st) == -1); 18057718be8SEnji Cooper 18157718be8SEnji Cooper errno = 0; 18257718be8SEnji Cooper ATF_REQUIRE_ERRNO(EFAULT, stat((void *)-1, &st) == -1); 18357718be8SEnji Cooper 18457718be8SEnji Cooper errno = 0; 18557718be8SEnji Cooper ATF_REQUIRE_ERRNO(EFAULT, lstat((void *)-1, &st) == -1); 18657718be8SEnji Cooper 18757718be8SEnji Cooper errno = 0; 18857718be8SEnji Cooper ATF_REQUIRE_ERRNO(EFAULT, stat("/etc/passwd", (void *)-1) == -1); 18957718be8SEnji Cooper 19057718be8SEnji Cooper errno = 0; 19157718be8SEnji Cooper ATF_REQUIRE_ERRNO(EFAULT, lstat("/etc/passwd", (void *)-1) == -1); 19257718be8SEnji Cooper 19357718be8SEnji Cooper errno = 0; 19457718be8SEnji Cooper ATF_REQUIRE_ERRNO(ENOENT, stat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1); 19557718be8SEnji Cooper 19657718be8SEnji Cooper errno = 0; 19757718be8SEnji Cooper ATF_REQUIRE_ERRNO(ENOENT, lstat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1); 19857718be8SEnji Cooper } 19957718be8SEnji Cooper 20057718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_mtime); 20157718be8SEnji Cooper ATF_TC_HEAD(stat_mtime, tc) 20257718be8SEnji Cooper { 20357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test modification times with stat(2)"); 20457718be8SEnji Cooper } 20557718be8SEnji Cooper 20657718be8SEnji Cooper ATF_TC_BODY(stat_mtime, tc) 20757718be8SEnji Cooper { 20857718be8SEnji Cooper struct stat sa, sb; 20957718be8SEnji Cooper int fd[3]; 21057718be8SEnji Cooper size_t i; 21157718be8SEnji Cooper 21257718be8SEnji Cooper for (i = 0; i < __arraycount(fd); i++) { 21357718be8SEnji Cooper 21457718be8SEnji Cooper (void)memset(&sa, 0, sizeof(struct stat)); 21557718be8SEnji Cooper (void)memset(&sb, 0, sizeof(struct stat)); 21657718be8SEnji Cooper 21757718be8SEnji Cooper fd[i] = open(path, O_WRONLY | O_CREAT); 21857718be8SEnji Cooper 21957718be8SEnji Cooper ATF_REQUIRE(fd[i] != -1); 22057718be8SEnji Cooper ATF_REQUIRE(write(fd[i], "X", 1) == 1); 22157718be8SEnji Cooper ATF_REQUIRE(stat(path, &sa) == 0); 22257718be8SEnji Cooper 22357718be8SEnji Cooper (void)sleep(1); 22457718be8SEnji Cooper 22557718be8SEnji Cooper ATF_REQUIRE(write(fd[i], "X", 1) == 1); 22657718be8SEnji Cooper ATF_REQUIRE(stat(path, &sb) == 0); 22757718be8SEnji Cooper 22857718be8SEnji Cooper ATF_REQUIRE(close(fd[i]) == 0); 22957718be8SEnji Cooper ATF_REQUIRE(unlink(path) == 0); 23057718be8SEnji Cooper 23157718be8SEnji Cooper if (sa.st_mtime == sb.st_mtime) 23257718be8SEnji Cooper atf_tc_fail("mtimes did not change"); 23357718be8SEnji Cooper } 23457718be8SEnji Cooper } 23557718be8SEnji Cooper 23657718be8SEnji Cooper ATF_TC_CLEANUP(stat_mtime, tc) 23757718be8SEnji Cooper { 23857718be8SEnji Cooper (void)unlink(path); 23957718be8SEnji Cooper } 24057718be8SEnji Cooper 24157718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_perm); 24257718be8SEnji Cooper ATF_TC_HEAD(stat_perm, tc) 24357718be8SEnji Cooper { 24457718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test permissions with stat(2)"); 24557718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root"); 24657718be8SEnji Cooper } 24757718be8SEnji Cooper 24857718be8SEnji Cooper ATF_TC_BODY(stat_perm, tc) 24957718be8SEnji Cooper { 25057718be8SEnji Cooper struct stat sa, sb; 25157718be8SEnji Cooper gid_t gid; 25257718be8SEnji Cooper uid_t uid; 25357718be8SEnji Cooper int fd; 25457718be8SEnji Cooper 25557718be8SEnji Cooper (void)memset(&sa, 0, sizeof(struct stat)); 25657718be8SEnji Cooper (void)memset(&sb, 0, sizeof(struct stat)); 25757718be8SEnji Cooper 25857718be8SEnji Cooper uid = getuid(); 25957718be8SEnji Cooper gid = getgid(); 26057718be8SEnji Cooper 26157718be8SEnji Cooper fd = open(path, O_RDONLY | O_CREAT); 26257718be8SEnji Cooper 26357718be8SEnji Cooper ATF_REQUIRE(fd != -1); 26457718be8SEnji Cooper ATF_REQUIRE(fstat(fd, &sa) == 0); 26557718be8SEnji Cooper ATF_REQUIRE(stat(path, &sb) == 0); 26657718be8SEnji Cooper 26757718be8SEnji Cooper if (gid != sa.st_gid || sa.st_gid != sb.st_gid) 26857718be8SEnji Cooper atf_tc_fail("invalid GID"); 26957718be8SEnji Cooper 27057718be8SEnji Cooper if (uid != sa.st_uid || sa.st_uid != sb.st_uid) 27157718be8SEnji Cooper atf_tc_fail("invalid UID"); 27257718be8SEnji Cooper 27357718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 27457718be8SEnji Cooper ATF_REQUIRE(unlink(path) == 0); 27557718be8SEnji Cooper } 27657718be8SEnji Cooper 27757718be8SEnji Cooper ATF_TC_CLEANUP(stat_perm, tc) 27857718be8SEnji Cooper { 27957718be8SEnji Cooper (void)unlink(path); 28057718be8SEnji Cooper } 28157718be8SEnji Cooper 28257718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_size); 28357718be8SEnji Cooper ATF_TC_HEAD(stat_size, tc) 28457718be8SEnji Cooper { 28557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test file sizes with stat(2)"); 28657718be8SEnji Cooper } 28757718be8SEnji Cooper 28857718be8SEnji Cooper ATF_TC_BODY(stat_size, tc) 28957718be8SEnji Cooper { 29057718be8SEnji Cooper struct stat sa, sb, sc; 29157718be8SEnji Cooper const size_t n = 10; 29257718be8SEnji Cooper size_t i; 29357718be8SEnji Cooper int fd; 29457718be8SEnji Cooper 29557718be8SEnji Cooper fd = open(path, O_WRONLY | O_CREAT); 29657718be8SEnji Cooper ATF_REQUIRE(fd >= 0); 29757718be8SEnji Cooper 29857718be8SEnji Cooper for (i = 0; i < n; i++) { 29957718be8SEnji Cooper 30057718be8SEnji Cooper (void)memset(&sa, 0, sizeof(struct stat)); 30157718be8SEnji Cooper (void)memset(&sb, 0, sizeof(struct stat)); 30257718be8SEnji Cooper (void)memset(&sc, 0, sizeof(struct stat)); 30357718be8SEnji Cooper 30457718be8SEnji Cooper ATF_REQUIRE(fstat(fd, &sa) == 0); 30557718be8SEnji Cooper ATF_REQUIRE(write(fd, "X", 1) == 1); 30657718be8SEnji Cooper ATF_REQUIRE(fstat(fd, &sb) == 0); 30757718be8SEnji Cooper ATF_REQUIRE(stat(path, &sc) == 0); 30857718be8SEnji Cooper 30957718be8SEnji Cooper if (sa.st_size + 1 != sb.st_size) 31057718be8SEnji Cooper atf_tc_fail("invalid file size"); 31157718be8SEnji Cooper 31257718be8SEnji Cooper if (sb.st_size != sc.st_size) 31357718be8SEnji Cooper atf_tc_fail("stat(2) and fstat(2) mismatch"); 31457718be8SEnji Cooper } 31557718be8SEnji Cooper 31657718be8SEnji Cooper ATF_REQUIRE(close(fd) == 0); 31757718be8SEnji Cooper ATF_REQUIRE(unlink(path) == 0); 31857718be8SEnji Cooper } 31957718be8SEnji Cooper 32057718be8SEnji Cooper ATF_TC_CLEANUP(stat_size, tc) 32157718be8SEnji Cooper { 32257718be8SEnji Cooper (void)unlink(path); 32357718be8SEnji Cooper } 32457718be8SEnji Cooper 32557718be8SEnji Cooper ATF_TC(stat_socket); 32657718be8SEnji Cooper ATF_TC_HEAD(stat_socket, tc) 32757718be8SEnji Cooper { 32857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test fstat(2) with " 32957718be8SEnji Cooper "a socket (PR kern/46077)"); 33057718be8SEnji Cooper } 33157718be8SEnji Cooper 33257718be8SEnji Cooper ATF_TC_BODY(stat_socket, tc) 33357718be8SEnji Cooper { 33457718be8SEnji Cooper struct sockaddr_in addr; 33557718be8SEnji Cooper struct stat st; 33657718be8SEnji Cooper uint32_t iaddr; 33757718be8SEnji Cooper int fd, flags; 33857718be8SEnji Cooper 33957718be8SEnji Cooper (void)memset(&st, 0, sizeof(struct stat)); 34057718be8SEnji Cooper (void)memset(&addr, 0, sizeof(struct sockaddr_in)); 34157718be8SEnji Cooper 34257718be8SEnji Cooper fd = socket(AF_INET, SOCK_STREAM, 0); 34357718be8SEnji Cooper ATF_REQUIRE(fd >= 0); 34457718be8SEnji Cooper 34557718be8SEnji Cooper flags = fcntl(fd, F_GETFL); 34657718be8SEnji Cooper 34757718be8SEnji Cooper ATF_REQUIRE(flags != -1); 34857718be8SEnji Cooper ATF_REQUIRE(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1); 34957718be8SEnji Cooper ATF_REQUIRE(inet_pton(AF_INET, "127.0.0.1", &iaddr) == 1); 35057718be8SEnji Cooper 35157718be8SEnji Cooper addr.sin_port = htons(42); 35257718be8SEnji Cooper addr.sin_family = AF_INET; 35357718be8SEnji Cooper addr.sin_addr.s_addr = iaddr; 35457718be8SEnji Cooper 35557718be8SEnji Cooper errno = 0; 35657718be8SEnji Cooper 35757718be8SEnji Cooper ATF_REQUIRE_ERRNO(EINPROGRESS, 35857718be8SEnji Cooper connect(fd, (struct sockaddr *)&addr, 35957718be8SEnji Cooper sizeof(struct sockaddr_in)) == -1); 36057718be8SEnji Cooper 36157718be8SEnji Cooper errno = 0; 36257718be8SEnji Cooper 36357718be8SEnji Cooper if (fstat(fd, &st) != 0 || errno != 0) 36457718be8SEnji Cooper atf_tc_fail("fstat(2) failed for a EINPROGRESS socket"); 36557718be8SEnji Cooper 36657718be8SEnji Cooper (void)close(fd); 36757718be8SEnji Cooper } 36857718be8SEnji Cooper 36957718be8SEnji Cooper ATF_TC_WITH_CLEANUP(stat_symlink); 37057718be8SEnji Cooper ATF_TC_HEAD(stat_symlink, tc) 37157718be8SEnji Cooper { 37257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test symbolic links with stat(2)"); 37357718be8SEnji Cooper } 37457718be8SEnji Cooper 37557718be8SEnji Cooper ATF_TC_BODY(stat_symlink, tc) 37657718be8SEnji Cooper { 37757718be8SEnji Cooper const char *pathlink = "pathlink"; 37857718be8SEnji Cooper struct stat sa, sb; 37957718be8SEnji Cooper int fd; 38057718be8SEnji Cooper 38157718be8SEnji Cooper (void)memset(&sa, 0, sizeof(struct stat)); 38257718be8SEnji Cooper (void)memset(&sb, 0, sizeof(struct stat)); 38357718be8SEnji Cooper 38457718be8SEnji Cooper fd = open(path, O_WRONLY | O_CREAT); 38557718be8SEnji Cooper 38657718be8SEnji Cooper ATF_REQUIRE(fd >= 0); 38757718be8SEnji Cooper ATF_REQUIRE(symlink(path, pathlink) == 0); 38857718be8SEnji Cooper ATF_REQUIRE(stat(pathlink, &sa) == 0); 38957718be8SEnji Cooper ATF_REQUIRE(lstat(pathlink, &sb) == 0); 39057718be8SEnji Cooper 39157718be8SEnji Cooper if (S_ISLNK(sa.st_mode) != 0) 39257718be8SEnji Cooper atf_tc_fail("stat(2) detected symbolic link"); 39357718be8SEnji Cooper 39457718be8SEnji Cooper if (S_ISLNK(sb.st_mode) == 0) 39557718be8SEnji Cooper atf_tc_fail("lstat(2) did not detect symbolic link"); 39657718be8SEnji Cooper 39757718be8SEnji Cooper if (sa.st_mode == sb.st_mode) 39857718be8SEnji Cooper atf_tc_fail("inconsistencies between stat(2) and lstat(2)"); 39957718be8SEnji Cooper 400*63d1fd59SEnji Cooper (void)close(fd); 40157718be8SEnji Cooper ATF_REQUIRE(unlink(path) == 0); 40257718be8SEnji Cooper ATF_REQUIRE(unlink(pathlink) == 0); 403621b0f13SEnji Cooper #ifdef __FreeBSD__ 404621b0f13SEnji Cooper (void)close(fd); 405621b0f13SEnji Cooper #endif 40657718be8SEnji Cooper } 40757718be8SEnji Cooper 40857718be8SEnji Cooper ATF_TC_CLEANUP(stat_symlink, tc) 40957718be8SEnji Cooper { 41057718be8SEnji Cooper (void)unlink(path); 41157718be8SEnji Cooper } 41257718be8SEnji Cooper 41357718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 41457718be8SEnji Cooper { 41557718be8SEnji Cooper 41657718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_chflags); 41757718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_dir); 41857718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_err); 41957718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_mtime); 42057718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_perm); 42157718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_size); 42257718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_socket); 42357718be8SEnji Cooper ATF_TP_ADD_TC(tp, stat_symlink); 42457718be8SEnji Cooper 42557718be8SEnji Cooper return atf_no_error(); 42657718be8SEnji Cooper } 427