Path: blob/main/tests/sys/kern/getdirentries_test.c
39483 views
/*-1* Copyright (c) 2025 Klara, Inc.2*3* SPDX-License-Identifier: BSD-2-Clause4*/56#include <sys/stat.h>7#include <sys/mount.h>89#include <dirent.h>10#include <fcntl.h>11#include <errno.h>12#include <stdint.h>1314#include <atf-c.h>1516ATF_TC(getdirentries_ok);17ATF_TC_HEAD(getdirentries_ok, tc)18{19atf_tc_set_md_var(tc, "descr", "Successfully read a directory.");20}21ATF_TC_BODY(getdirentries_ok, tc)22{23char dbuf[4096];24struct dirent *d;25off_t base;26ssize_t ret;27int dd, n;2829ATF_REQUIRE_EQ(0, mkdir("dir", 0755));30ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);31ATF_REQUIRE((ret = getdirentries(dd, dbuf, sizeof(dbuf), &base)) > 0);32ATF_REQUIRE_EQ(0, getdirentries(dd, dbuf, sizeof(dbuf), &base));33ATF_REQUIRE_EQ(base, lseek(dd, 0, SEEK_CUR));34ATF_CHECK_EQ(0, close(dd));35for (n = 0, d = (struct dirent *)dbuf;36d < (struct dirent *)(dbuf + ret);37d = (struct dirent *)((char *)d + d->d_reclen), n++)38/* nothing */ ;39ATF_CHECK_EQ((struct dirent *)(dbuf + ret), d);40ATF_CHECK_EQ(2, n);41}4243ATF_TC(getdirentries_ebadf);44ATF_TC_HEAD(getdirentries_ebadf, tc)45{46atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "47"from an invalid descriptor.");48}49ATF_TC_BODY(getdirentries_ebadf, tc)50{51char dbuf[4096];52off_t base;53int fd;5455ATF_REQUIRE((fd = open("file", O_CREAT | O_WRONLY, 0644)) >= 0);56ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base));57ATF_CHECK_EQ(EBADF, errno);58ATF_REQUIRE_EQ(0, close(fd));59ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base));60ATF_CHECK_EQ(EBADF, errno);61}6263ATF_TC(getdirentries_efault);64ATF_TC_HEAD(getdirentries_efault, tc)65{66atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "67"to an invalid buffer.");68}69ATF_TC_BODY(getdirentries_efault, tc)70{71char dbuf[4096];72off_t base, *basep;73int dd;7475ATF_REQUIRE_EQ(0, mkdir("dir", 0755));76ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);77ATF_REQUIRE_EQ(-1, getdirentries(dd, NULL, sizeof(dbuf), &base));78ATF_CHECK_EQ(EFAULT, errno);79basep = NULL;80basep++;81ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), basep));82ATF_CHECK_EQ(EFAULT, errno);83ATF_CHECK_EQ(0, close(dd));84}8586ATF_TC(getdirentries_einval);87ATF_TC_HEAD(getdirentries_einval, tc)88{89atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "90"with various invalid parameters.");91}92ATF_TC_BODY(getdirentries_einval, tc)93{94struct statfs fsb;95char dbuf[4096];96off_t base;97ssize_t ret;98int dd;99100ATF_REQUIRE_EQ(0, mkdir("dir", 0755));101ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);102ATF_REQUIRE_EQ(0, fstatfs(dd, &fsb));103/* nbytes too small */104ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, 8, &base));105ATF_CHECK_EQ(EINVAL, errno);106/* nbytes too big */107ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, SIZE_MAX, &base));108ATF_CHECK_EQ(EINVAL, errno);109/* invalid position */110ATF_REQUIRE((ret = getdirentries(dd, dbuf, sizeof(dbuf), &base)) > 0);111ATF_REQUIRE_EQ(0, getdirentries(dd, dbuf, sizeof(dbuf), &base));112ATF_REQUIRE(base > 0);113ATF_REQUIRE_EQ(base + 3, lseek(dd, 3, SEEK_CUR));114/* known to fail on ufs (FFS2) and zfs, and work on tmpfs */115if (strcmp(fsb.f_fstypename, "ufs") == 0 ||116strcmp(fsb.f_fstypename, "zfs") == 0) {117atf_tc_expect_fail("incorrectly returns 0 instead of EINVAL "118"on %s", fsb.f_fstypename);119}120ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), &base));121ATF_CHECK_EQ(EINVAL, errno);122ATF_CHECK_EQ(0, close(dd));123}124125ATF_TC(getdirentries_enoent);126ATF_TC_HEAD(getdirentries_enoent, tc)127{128atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "129"after it is deleted.");130}131ATF_TC_BODY(getdirentries_enoent, tc)132{133char dbuf[4096];134off_t base;135int dd;136137ATF_REQUIRE_EQ(0, mkdir("dir", 0755));138ATF_REQUIRE((dd = open("dir", O_DIRECTORY | O_RDONLY)) >= 0);139ATF_REQUIRE_EQ(0, rmdir("dir"));140ATF_REQUIRE_EQ(-1, getdirentries(dd, dbuf, sizeof(dbuf), &base));141ATF_CHECK_EQ(ENOENT, errno);142}143144ATF_TC(getdirentries_enotdir);145ATF_TC_HEAD(getdirentries_enotdir, tc)146{147atf_tc_set_md_var(tc, "descr", "Attempt to read a directory "148"from a descriptor not associated with a directory.");149}150ATF_TC_BODY(getdirentries_enotdir, tc)151{152char dbuf[4096];153off_t base;154int fd;155156ATF_REQUIRE((fd = open("file", O_CREAT | O_RDWR, 0644)) >= 0);157ATF_REQUIRE_EQ(-1, getdirentries(fd, dbuf, sizeof(dbuf), &base));158ATF_CHECK_EQ(ENOTDIR, errno);159ATF_CHECK_EQ(0, close(fd));160}161162ATF_TP_ADD_TCS(tp)163{164ATF_TP_ADD_TC(tp, getdirentries_ok);165ATF_TP_ADD_TC(tp, getdirentries_ebadf);166ATF_TP_ADD_TC(tp, getdirentries_efault);167ATF_TP_ADD_TC(tp, getdirentries_einval);168ATF_TP_ADD_TC(tp, getdirentries_enoent);169ATF_TP_ADD_TC(tp, getdirentries_enotdir);170return (atf_no_error());171}172173174