mirror of
https://github.com/NixOS/nix.git
synced 2025-12-22 17:01: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(), "");
|
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
|
} // namespace nix
|
||||||
|
|
|
||||||
|
|
@ -115,9 +115,6 @@ Path canonPath(PathView path, bool resolveSymlinks)
|
||||||
if (!isAbsolute(path))
|
if (!isAbsolute(path))
|
||||||
throw Error("not an absolute path: '%1%'", 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`
|
/* This just exists because we cannot set the target of `remaining`
|
||||||
(the callback parameter) directly to a newly-constructed string,
|
(the callback parameter) directly to a newly-constructed string,
|
||||||
since it is `std::string_view`. */
|
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;
|
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)
|
std::filesystem::path createTempDir(const std::filesystem::path & tmpRoot, const std::string & prefix, mode_t mode)
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,11 @@ struct UnixPathTrait
|
||||||
{
|
{
|
||||||
return path.rfind('/', from);
|
return path.rfind('/', from);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t rootNameLen(StringView)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -83,6 +88,18 @@ struct WindowsPathTrait
|
||||||
size_t p2 = path.rfind(preferredSep, from);
|
size_t p2 = path.rfind(preferredSep, from);
|
||||||
return p1 == String::npos ? p2 : p2 == String::npos ? p1 : std::max(p1, p2);
|
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>
|
template<typename CharT>
|
||||||
|
|
@ -116,6 +133,11 @@ typename PathDict::String canonPathInner(typename PathDict::StringView remaining
|
||||||
typename PathDict::String result;
|
typename PathDict::String result;
|
||||||
result.reserve(256);
|
result.reserve(256);
|
||||||
|
|
||||||
|
if (auto rootNameLength = PathDict::rootNameLen(remaining)) {
|
||||||
|
result += remaining.substr(0, rootNameLength); /* Copy drive letter verbatim. */
|
||||||
|
remaining.remove_prefix(rootNameLength);
|
||||||
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
/* Skip slashes. */
|
/* 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.
|
* 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();
|
std::filesystem::path defaultTempDir();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "nix/util/file-system.hh"
|
#include "nix/util/file-system.hh"
|
||||||
|
#include "nix/util/environment-variables.hh"
|
||||||
|
|
||||||
#include "util-unix-config-private.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);
|
return open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::filesystem::path defaultTempDir()
|
||||||
|
{
|
||||||
|
return getEnvNonEmpty("TMPDIR").value_or("/tmp");
|
||||||
|
}
|
||||||
|
|
||||||
void setWriteTime(
|
void setWriteTime(
|
||||||
const std::filesystem::path & path, time_t accessedTime, time_t modificationTime, std::optional<bool> optIsSymlink)
|
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/file-system.hh"
|
||||||
|
#include "nix/util/windows-error.hh"
|
||||||
#include "nix/util/logging.hh"
|
#include "nix/util/logging.hh"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
using namespace nix::windows;
|
||||||
|
|
||||||
void setWriteTime(
|
void setWriteTime(
|
||||||
const std::filesystem::path & path, time_t accessedTime, time_t modificationTime, std::optional<bool> optIsSymlink)
|
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);
|
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
|
} // namespace nix
|
||||||
#endif
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue