/* * libfud * Copyright 2024 Dominick Allen * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "fud_file.hpp" #include "fud_string.hpp" #include "test_common.hpp" #include "gtest/gtest.h" #include #include #include #include #include namespace fud { TEST(FudFile, Basic) { constexpr const char* testDirCName = "/tmp/fud_directory_test"; const auto testDirName{String::makeFromCString(testDirCName).takeOkay()}; ASSERT_TRUE(testDirName.utf8Valid()); constexpr mode_t pathMode = 0777; ASSERT_EQ(removeRecursive(testDirName), FudStatus::Success); auto mkdirResult = mkdir(testDirName.c_str(), pathMode); EXPECT_EQ(mkdirResult, 0); if (mkdirResult != 0) { ASSERT_EQ(removeRecursive(testDirName), FudStatus::Success); return; } String testName1{String::makeFromCStrings(testDirCName, "/", "test1").takeOkay()}; String testName2{String::makeFromCStrings(testDirCName, "/", "test2").takeOkay()}; auto rmFile = [](const auto& filename) -> int { auto result = unlink(filename.c_str()); if (result == -1) { if (errno == ENOENT) { return 0; } } return result; }; ASSERT_EQ(rmFile(testName1), 0); ASSERT_EQ(rmFile(testName2), 0); auto fileResult{RegularFile::open(testName1.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt)}; EXPECT_EQ(fileResult.takeErrorOr(FudStatus::Success), FudStatus::NotFound); /* The irony of the ability for TOCTOU bugs to be present in the test does * not escape me. */ auto createFile = [](const auto& filename) -> int { constexpr int allPerms = 0777; auto handleResult = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, allPerms); if (handleResult >= 0) { close(handleResult); } return handleResult; }; ASSERT_GE(createFile(testName1), 0); fileResult = std::move(RegularFile::open(testName1.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt)); ASSERT_TRUE(fileResult.isOkay()); auto file{fileResult.takeOkay()}; ASSERT_EQ(file.close(), FudStatus::Success); ASSERT_EQ(rmFile(testName1), 0); ASSERT_GE(createFile(testName2), 0); ASSERT_EQ(symlink(testName2.c_str(), testName1.c_str()), 0); fileResult = RegularFile::open(testName2.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt); ASSERT_TRUE(fileResult.isOkay()); file = fileResult.takeOkay(); ASSERT_EQ(file.close(), FudStatus::Success); fileResult = RegularFile::open(testName1.asView(), FileAccessMode::Read, OpenFlags{}, NullOpt); ASSERT_TRUE(fileResult.isError()); EXPECT_EQ(fileResult.getError(), FudStatus::Failure); } } // namespace fud