mirror of
https://github.com/NixOS/nix.git
synced 2025-12-22 08:51:08 +01:00
libutil: Fix canonPath, makeTempPath and createTempDir on windows
This at least makes canonPath not consider the drive letter as a path component. There still some issues with it on windows, but at least this gets us through some of the libutil-tests. Also since we don't want to change which env variables nix considers we don't use std::filesystem::temp_directory_path and implement the windows version directly.
This commit is contained in:
parent
2f092870e4
commit
675656ffba
6 changed files with 49 additions and 12 deletions
|
|
@ -416,4 +416,11 @@ TEST(FdSource, restartWorks)
|
|||
EXPECT_EQ(source.drain(), "");
|
||||
}
|
||||
|
||||
TEST(createTempDir, works)
|
||||
{
|
||||
auto tmpDir = createTempDir();
|
||||
nix::AutoDelete delTmpDir(tmpDir, /*recursive=*/true);
|
||||
ASSERT_TRUE(std::filesystem::is_directory(tmpDir));
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
|
|||
|
|
@ -115,9 +115,6 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
|||
if (!isAbsolute(path))
|
||||
throw Error("not an absolute path: '%1%'", path);
|
||||
|
||||
// For Windows
|
||||
auto rootName = std::filesystem::path{path}.root_name();
|
||||
|
||||
/* This just exists because we cannot set the target of `remaining`
|
||||
(the callback parameter) directly to a newly-constructed string,
|
||||
since it is `std::string_view`. */
|
||||
|
|
@ -147,8 +144,6 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
|||
}
|
||||
});
|
||||
|
||||
if (!rootName.empty())
|
||||
ret = rootName.string() + std::move(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -672,11 +667,6 @@ void AutoUnmount::cancel()
|
|||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::filesystem::path defaultTempDir()
|
||||
{
|
||||
return getEnvNonEmpty("TMPDIR").value_or("/tmp");
|
||||
}
|
||||
|
||||
std::filesystem::path createTempDir(const std::filesystem::path & tmpRoot, const std::string & prefix, mode_t mode)
|
||||
{
|
||||
while (1) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ struct UnixPathTrait
|
|||
{
|
||||
return path.rfind('/', from);
|
||||
}
|
||||
|
||||
static size_t rootNameLen(StringView)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -83,6 +88,18 @@ struct WindowsPathTrait
|
|||
size_t p2 = path.rfind(preferredSep, from);
|
||||
return p1 == String::npos ? p2 : p2 == String::npos ? p1 : std::max(p1, p2);
|
||||
}
|
||||
|
||||
static size_t rootNameLen(StringView path)
|
||||
{
|
||||
if (path.size() >= 2 && path[1] == ':') {
|
||||
char driveLetter = path[0];
|
||||
if ((driveLetter >= 'A' && driveLetter <= 'Z') || (driveLetter >= 'a' && driveLetter <= 'z'))
|
||||
return 2;
|
||||
}
|
||||
/* TODO: This needs to also handle UNC paths.
|
||||
* https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#unc-paths */
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename CharT>
|
||||
|
|
@ -116,6 +133,11 @@ typename PathDict::String canonPathInner(typename PathDict::StringView remaining
|
|||
typename PathDict::String result;
|
||||
result.reserve(256);
|
||||
|
||||
if (auto rootNameLength = PathDict::rootNameLen(remaining)) {
|
||||
result += remaining.substr(0, rootNameLength); /* Copy drive letter verbatim. */
|
||||
remaining.remove_prefix(rootNameLength);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
||||
/* Skip slashes. */
|
||||
|
|
|
|||
|
|
@ -362,6 +362,8 @@ std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix = "nix");
|
|||
|
||||
/**
|
||||
* Return `TMPDIR`, or the default temporary directory if unset or empty.
|
||||
* Uses GetTempPathW on windows which respects TMP, TEMP, USERPROFILE env variables.
|
||||
* Does not resolve symlinks and the returned path might not be directory or exist at all.
|
||||
*/
|
||||
std::filesystem::path defaultTempDir();
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "nix/util/file-system.hh"
|
||||
#include "nix/util/environment-variables.hh"
|
||||
|
||||
#include "util-unix-config-private.hh"
|
||||
|
||||
|
|
@ -19,6 +20,11 @@ Descriptor openDirectory(const std::filesystem::path & path)
|
|||
return open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||
}
|
||||
|
||||
std::filesystem::path defaultTempDir()
|
||||
{
|
||||
return getEnvNonEmpty("TMPDIR").value_or("/tmp");
|
||||
}
|
||||
|
||||
void setWriteTime(
|
||||
const std::filesystem::path & path, time_t accessedTime, time_t modificationTime, std::optional<bool> optIsSymlink)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
#include "nix/util/file-system.hh"
|
||||
#include "nix/util/windows-error.hh"
|
||||
#include "nix/util/logging.hh"
|
||||
|
||||
#ifdef _WIN32
|
||||
namespace nix {
|
||||
|
||||
using namespace nix::windows;
|
||||
|
||||
void setWriteTime(
|
||||
const std::filesystem::path & path, time_t accessedTime, time_t modificationTime, std::optional<bool> optIsSymlink)
|
||||
{
|
||||
|
|
@ -28,5 +30,13 @@ Descriptor openDirectory(const std::filesystem::path & path)
|
|||
NULL);
|
||||
}
|
||||
|
||||
std::filesystem::path defaultTempDir()
|
||||
{
|
||||
wchar_t buf[MAX_PATH + 1];
|
||||
DWORD len = GetTempPathW(MAX_PATH + 1, buf);
|
||||
if (len == 0 || len > MAX_PATH)
|
||||
throw WinError("getting default temporary directory");
|
||||
return std::filesystem::path(buf);
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue