Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions libs/linglong/tests/ll-tests/src/linglong/utils/file_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,38 @@ TEST_F(FileTest, EnsureDirectory)
EXPECT_TRUE(fs::is_directory(multiple_dir));
}

TEST_F(FileTest, EnsureDirectoryErrorIncludesPathWhenRemovingFileFails)
{
if (::geteuid() == 0) {
GTEST_SKIP() << "root can remove files regardless of the parent permission bits";
}

const auto parent = dest_dir / "read-only-parent";
fs::create_directory(parent);
const auto permissions = fs::status(parent).permissions();
const auto file = parent / "existing-file";
std::ofstream(file) << "content";
fs::permissions(parent, fs::perms::owner_read | fs::perms::owner_exec);

auto result = linglong::utils::ensureDirectory(file);

fs::permissions(parent, permissions);
ASSERT_FALSE(result);
EXPECT_NE(result.error().message().find(file.string()), std::string::npos);
}

TEST_F(FileTest, EnsureDirectoryErrorIncludesPathWhenCreatingDirectoryFails)
{
const auto parent = dest_dir / "regular-file";
std::ofstream(parent) << "content";
const auto directory = parent / "nested-directory";

auto result = linglong::utils::ensureDirectory(directory);

ASSERT_FALSE(result);
EXPECT_NE(result.error().message().find(directory.string()), std::string::npos);
}

TEST_F(FileTest, EnsureDirectoryWithPermissionsIgnoresUmask)
{
constexpr auto permissions = fs::perms::owner_all | fs::perms::group_read
Expand Down Expand Up @@ -532,6 +564,20 @@ TEST_F(FileTest, RelinkFile)
}
}

TEST_F(FileTest, RelinkFileErrorIncludesTemporaryPath)
{
const auto parent = dest_dir / "regular-file";
std::ofstream(parent) << "content";
const auto link = parent / "link";
const auto target = dest_dir / "target";
const auto temporary = fs::path{ link.string() + ".linyaps.tmp" };

auto result = linglong::utils::relinkFileTo(link, target);

ASSERT_FALSE(result);
EXPECT_NE(result.error().message().find(temporary.string()), std::string::npos);
}

TEST_F(FileTest, WriteFile)
{
// Test writing to a new file
Expand Down Expand Up @@ -575,6 +621,19 @@ TEST_F(FileTest, WriteFile)
EXPECT_FALSE(result.has_value()); // Should fail because parent directory doesn't exist
}

TEST_F(FileTest, WriteFileErrorIncludesPath)
{
const fs::path fullDevice{ "/dev/full" };
if (!fs::exists(fullDevice)) {
GTEST_SKIP() << "/dev/full is required to exercise a deferred write failure";
}

auto result = linglong::utils::writeFile(fullDevice, "content");

ASSERT_FALSE(result);
EXPECT_NE(result.error().message().find(fullDevice.string()), std::string::npos);
}

TEST_F(FileTest, ReadFile)
{
// Test reading an existing file
Expand Down
12 changes: 7 additions & 5 deletions libs/utils/src/linglong/utils/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ linglong::utils::error::Result<void> writeFile(const std::filesystem::path &file
out << content;
out.close();
if (!out) {
return LINGLONG_ERR(
fmt::format("failed to write file {}", common::error::errorString(errno)));
return LINGLONG_ERR(fmt::format("failed to write file {}: {}",
filepath,
common::error::errorString(errno)));
}
return LINGLONG_OK;
}
Expand Down Expand Up @@ -356,12 +357,12 @@ linglong::utils::error::Result<void> ensureDirectory(const std::filesystem::path

std::filesystem::remove(dir, ec);
if (ec) {
return LINGLONG_ERR("failed to remove directory", ec);
return LINGLONG_ERR(fmt::format("failed to remove directory {}", dir), ec);
}
}

if (!std::filesystem::create_directories(dir, ec) && ec) {
return LINGLONG_ERR("failed to create directory", ec);
return LINGLONG_ERR(fmt::format("failed to create directory {}", dir), ec);
}

return LINGLONG_OK;
Expand Down Expand Up @@ -466,7 +467,8 @@ linglong::utils::error::Result<void> relinkFileTo(const std::filesystem::path &l

std::filesystem::create_symlink(target, tmpPath, ec);
if (ec) {
return LINGLONG_ERR("failed to create symlink", ec);
return LINGLONG_ERR(
fmt::format("failed to create symlink {} -> {}", tmpPath, target), ec);
}

std::filesystem::rename(tmpPath, link, ec);
Expand Down
Loading