// SPDX-License-Identifier: GPL-2.0-or-later #define _GNU_SOURCE #define __SANE_USERSPACE_TYPES__ #include #include #include #include #include #include "kselftest_harness.h" #ifndef O_EMPTYPATH #define O_EMPTYPATH (1 << 26) #endif #define EMPTYPATH_TEST_FILE "/tmp/emptypath_test" FIXTURE(emptypath) { int opath_fd; }; FIXTURE_SETUP(emptypath) { int fd; self->opath_fd = -1; fd = open(EMPTYPATH_TEST_FILE, O_CREAT | O_WRONLY, S_IRWXU); ASSERT_GE(fd, 0) { TH_LOG("create %s: %s", EMPTYPATH_TEST_FILE, strerror(errno)); } close(fd); self->opath_fd = open(EMPTYPATH_TEST_FILE, O_PATH); ASSERT_GE(self->opath_fd, 0) { TH_LOG("open %s O_PATH: %s", EMPTYPATH_TEST_FILE, strerror(errno)); } } FIXTURE_TEARDOWN(emptypath) { if (self->opath_fd >= 0) close(self->opath_fd); unlink(EMPTYPATH_TEST_FILE); } /* An empty path is rejected with ENOENT unless O_EMPTYPATH is set. */ TEST_F(emptypath, without_flag_returns_enoent) { int fd = openat(self->opath_fd, "", O_RDONLY); if (fd >= 0) close(fd); ASSERT_LT(fd, 0) { TH_LOG("empty path without O_EMPTYPATH unexpectedly succeeded"); } EXPECT_EQ(errno, ENOENT) { TH_LOG("expected ENOENT, got %s", strerror(errno)); } } /* O_EMPTYPATH reopens the O_PATH fd through an empty path. */ TEST_F(emptypath, reopens_opath_fd) { int fd = openat(self->opath_fd, "", O_RDONLY | O_EMPTYPATH); if (fd < 0 && errno == EINVAL) SKIP(return, "O_EMPTYPATH not supported"); ASSERT_GE(fd, 0) { TH_LOG("O_EMPTYPATH failed: %s", strerror(errno)); } close(fd); } TEST_HARNESS_MAIN