Return AutoCloseFD in open-like functions

This reflects the fact that it is returning a new, "owned" file
descriptor, that it is the caller's responsibility to close.

Co-authored-by: Amaan Qureshi <git@amaanq.com>
This commit is contained in:
John Ericson
2026-02-20 09:49:43 -05:00
committed by Amaan Qureshi
parent 02bb3d032d
commit 89dd96efbf
13 changed files with 32 additions and 32 deletions

View File

@@ -137,7 +137,7 @@ public:
: state(state)
, sampleInterval(period)
, profileFd([&]() {
AutoCloseFD fd = openNewFileForWrite(
auto fd = openNewFileForWrite(
profileFile,
0660,
{

View File

@@ -554,7 +554,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
by another process. We need to be sure that we can acquire an
exclusive lock before deleting them. */
if (baseName.find("tmp-", 0) == 0) {
AutoCloseFD tmpDirFd = openDirectory(realPath);
auto tmpDirFd = openDirectory(realPath);
if (!tmpDirFd || !lockFile(tmpDirFd.get(), ltWrite, false)) {
debug("skipping locked tempdir %s", PathFmt(realPath));
return;

View File

@@ -45,7 +45,7 @@ TEST(readLinkAt, works)
sink.createDirectory(CanonPath("dir"));
}
AutoCloseFD dirFd = openDirectory(tmpDir);
auto dirFd = openDirectory(tmpDir);
EXPECT_EQ(readLinkAt(dirFd.get(), CanonPath("link")), OS_STR("target"));
EXPECT_EQ(readLinkAt(dirFd.get(), CanonPath("relative")), OS_STR("../relative/path"));
@@ -54,7 +54,7 @@ TEST(readLinkAt, works)
EXPECT_EQ(readLinkAt(dirFd.get(), CanonPath("long")), string_to_os_string(longTarget));
EXPECT_EQ(readLinkAt(dirFd.get(), CanonPath("a/b/link")), OS_STR("nested_target"));
AutoCloseFD subDirFd = openDirectory(tmpDir / "a");
auto subDirFd = openDirectory(tmpDir / "a");
EXPECT_EQ(readLinkAt(subDirFd.get(), CanonPath("b/link")), OS_STR("nested_target"));
// Test error cases - expect SystemError on both platforms
@@ -107,7 +107,7 @@ TEST(openFileEnsureBeneathNoSymlinks, works)
SymlinkNotAllowed);
}
AutoCloseFD dirFd = openDirectory(tmpDir);
auto dirFd = openDirectory(tmpDir);
// Helper to open files with platform-specific arguments
auto openRead = [&](std::string_view path) -> AutoCloseFD {

View File

@@ -39,7 +39,7 @@ TEST(fchmodatTryNoFollow, works)
ASSERT_NO_THROW(chmod(tmpDir / "file", 0644));
ASSERT_NO_THROW(chmod(tmpDir / "dir", 0755));
AutoCloseFD dirFd = openDirectory(tmpDir);
auto dirFd = openDirectory(tmpDir);
ASSERT_TRUE(dirFd);
struct ::stat st;
@@ -104,7 +104,7 @@ TEST(fchmodatTryNoFollow, fallbackWithoutProc)
if (mount("tmpfs", "/proc", "tmpfs", 0, 0) == -1)
_exit(1);
AutoCloseFD dirFd = openDirectory(tmpDir);
auto dirFd = openDirectory(tmpDir);
if (!dirFd)
exit(1);

View File

@@ -263,7 +263,7 @@ std::filesystem::path readLink(const std::filesystem::path & path)
std::string readFile(const std::filesystem::path & path)
{
AutoCloseFD fd = openFileReadonly(path);
auto fd = openFileReadonly(path);
if (!fd)
throw NativeSysError("opening file %1%", PathFmt(path));
return readFile(fd.get());
@@ -286,7 +286,7 @@ void readFile(const std::filesystem::path & path, Sink & sink, bool memory_map)
}
// Stream the file instead if memory-mapping fails or is disabled.
AutoCloseFD fd = openFileReadonly(std::filesystem::path(path));
auto fd = openFileReadonly(std::filesystem::path(path));
if (!fd)
throw NativeSysError("opening file %s", PathFmt(path));
drainFD(fd.get(), sink);

View File

@@ -168,14 +168,14 @@ std::filesystem::path descriptorToPath(Descriptor fd);
/**
* Open a `Descriptor` with read-only access to the given directory.
*/
Descriptor openDirectory(const std::filesystem::path & path);
AutoCloseFD openDirectory(const std::filesystem::path & path);
/**
* Open a `Descriptor` with read-only access to the given file.
*
* @note For directories use @ref openDirectory.
*/
Descriptor openFileReadonly(const std::filesystem::path & path);
AutoCloseFD openFileReadonly(const std::filesystem::path & path);
struct OpenNewFileForWriteParams
{
@@ -198,7 +198,7 @@ struct OpenNewFileForWriteParams
*
* @todo Reparse points on Windows.
*/
Descriptor openNewFileForWrite(const std::filesystem::path & path, mode_t mode, OpenNewFileForWriteParams params);
AutoCloseFD openNewFileForWrite(const std::filesystem::path & path, mode_t mode, OpenNewFileForWriteParams params);
/**
* Read the contents of a file into a string.

View File

@@ -153,7 +153,7 @@ ref<NarAccessor> makeLazyNarAccessor(NarListing listing, GetNarBytes getNarBytes
GetNarBytes seekableGetNarBytes(const std::filesystem::path & path)
{
AutoCloseFD fd = openFileReadonly(path);
auto fd = openFileReadonly(path);
if (!fd)
throw NativeSysError("opening NAR cache file %s", PathFmt(path));

View File

@@ -23,17 +23,17 @@
namespace nix {
Descriptor openDirectory(const std::filesystem::path & path)
AutoCloseFD openDirectory(const std::filesystem::path & path)
{
return open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
return AutoCloseFD{open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC)};
}
Descriptor openFileReadonly(const std::filesystem::path & path)
AutoCloseFD openFileReadonly(const std::filesystem::path & path)
{
return open(path.c_str(), O_RDONLY | O_CLOEXEC);
return AutoCloseFD{open(path.c_str(), O_RDONLY | O_CLOEXEC)};
}
Descriptor openNewFileForWrite(const std::filesystem::path & path, mode_t mode, OpenNewFileForWriteParams params)
AutoCloseFD openNewFileForWrite(const std::filesystem::path & path, mode_t mode, OpenNewFileForWriteParams params)
{
auto flags = O_WRONLY | O_CREAT | O_CLOEXEC;
if (params.truncateExisting) {
@@ -43,7 +43,7 @@ Descriptor openNewFileForWrite(const std::filesystem::path & path, mode_t mode,
} else {
flags |= O_EXCL; /* O_CREAT | O_EXCL already ensures that symlinks are not followed. */
}
return open(path.c_str(), flags, mode);
return AutoCloseFD{open(path.c_str(), flags, mode)};
}
std::filesystem::path descriptorToPath(Descriptor fd)

View File

@@ -23,41 +23,41 @@ void setWriteTime(
warn("Changing file times is not yet implemented on Windows, path is %s", PathFmt(path));
}
Descriptor openDirectory(const std::filesystem::path & path)
AutoCloseFD openDirectory(const std::filesystem::path & path)
{
return CreateFileW(
return AutoCloseFD{CreateFileW(
path.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
/*lpSecurityAttributes=*/nullptr,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
/*hTemplateFile=*/nullptr);
/*hTemplateFile=*/nullptr)};
}
Descriptor openFileReadonly(const std::filesystem::path & path)
AutoCloseFD openFileReadonly(const std::filesystem::path & path)
{
return CreateFileW(
return AutoCloseFD{CreateFileW(
path.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_DELETE,
/*lpSecurityAttributes=*/nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
/*hTemplateFile=*/nullptr);
/*hTemplateFile=*/nullptr)};
}
Descriptor
AutoCloseFD
openNewFileForWrite(const std::filesystem::path & path, [[maybe_unused]] mode_t mode, OpenNewFileForWriteParams params)
{
return CreateFileW(
return AutoCloseFD{CreateFileW(
path.c_str(),
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_DELETE,
/*lpSecurityAttributes=*/nullptr,
params.truncateExisting ? CREATE_ALWAYS : CREATE_NEW, /* TODO: Reparse points. */
FILE_ATTRIBUTE_NORMAL,
/*hTemplateFile=*/nullptr);
/*hTemplateFile=*/nullptr)};
}
std::filesystem::path defaultTempDir()

View File

@@ -78,7 +78,7 @@ struct CmdCatNar : StoreCommand, MixCat
void run(ref<Store> store) override
{
AutoCloseFD fd = openFileReadonly(narPath);
auto fd = openFileReadonly(narPath);
if (!fd)
throw NativeSysError("opening NAR file %s", PathFmt(narPath));
auto source = FdSource{fd.get()};

View File

@@ -150,7 +150,7 @@ struct CmdLsNar : Command, MixLs
void run() override
{
AutoCloseFD fd = openFileReadonly(narPath);
auto fd = openFileReadonly(narPath);
if (!fd)
throw NativeSysError("opening NAR file %s", PathFmt(narPath));
auto source = FdSource{fd.get()};

View File

@@ -45,7 +45,7 @@ static void readChannels()
// Writes the list of channels.
static void writeChannels()
{
AutoCloseFD channelsFD = openNewFileForWrite(
auto channelsFD = openNewFileForWrite(
channelsList,
0644,
{

View File

@@ -112,7 +112,7 @@ std::tuple<StorePath, Hash> prefetchFile(
if (executable)
mode = 0700;
AutoCloseFD fd = openNewFileForWrite(tmpFile, mode, {.truncateExisting = false});
auto fd = openNewFileForWrite(tmpFile, mode, {.truncateExisting = false});
if (!fd)
throw SysError("creating temporary file %s", PathFmt(tmpFile));