[libcxx-commits] [PATCH] D91170: [15/N] [libcxx] Implement the canonical function for windows
Martin Storsjö via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Jan 29 04:37:49 PST 2021
mstorsjo updated this revision to Diff 320103.
mstorsjo set the repository for this revision to rG LLVM Github Monorepo.
mstorsjo added a comment.
Rebased, retriggering CI.
Compared to the older version that @amccarth approved, this is a little bit reworked to fit into the POSIX `realpath()` interface, which means it returns a `malloc()` allocated buffer, so the end of the function uses a bit of memmove/wcscpy to assemble paths, instead of the slightly simpler version before (when operating on the level of the `__canonical` function that returns a `std::filesystem::path`).
This touches the existing code a little bit to just change `char` into `path::value_type`, and add the `detail::` prefix on the calls to `realpath()`.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D91170/new/
https://reviews.llvm.org/D91170
Files:
libcxx/src/filesystem/operations.cpp
libcxx/src/filesystem/posix_compat.h
Index: libcxx/src/filesystem/posix_compat.h
===================================================================
--- libcxx/src/filesystem/posix_compat.h
+++ libcxx/src/filesystem/posix_compat.h
@@ -279,6 +279,43 @@
int chdir(const wchar_t *path) { return _wchdir(path); }
wchar_t *getcwd(wchar_t *buff, size_t size) { return _wgetcwd(buff, size); }
+
+wchar_t *realpath(const wchar_t *path, wchar_t *resolved_name) {
+ // Only expected to be used with us allocating the buffer.
+ _LIBCPP_ASSERT(resolved_name == nullptr,
+ "Windows realpath() assumes a null resolved_name");
+
+ WinHandle h(path, FILE_READ_ATTRIBUTES, 0);
+ if (!h) {
+ set_errno();
+ return nullptr;
+ }
+ size_t buff_size = MAX_PATH + 10;
+ std::unique_ptr<wchar_t, decltype(&::free)> buff(
+ static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t))), &::free);
+ DWORD retval = GetFinalPathNameByHandleW(
+ h, buff.get(), buff_size, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
+ if (retval > buff_size) {
+ buff_size = retval;
+ buff.reset(static_cast<wchar_t *>(malloc(buff_size * sizeof(wchar_t))));
+ retval = GetFinalPathNameByHandleW(h, buff.get(), buff_size,
+ FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
+ }
+ if (!retval) {
+ set_errno();
+ return nullptr;
+ }
+ wchar_t *ptr = buff.get();
+ if (!wcsncmp(ptr, L"\\\\?\\", 4)) {
+ if (ptr[5] == ':') { // \\?\X: -> X:
+ memmove(&ptr[0], &ptr[4], (wcslen(&ptr[4]) + 1) * sizeof(wchar_t));
+ } else if (!wcsncmp(&ptr[4], L"UNC\\", 4)) { // \\?\UNC\server -> \\server
+ wcscpy(&ptr[0], L"\\\\");
+ memmove(&ptr[2], &ptr[8], (wcslen(&ptr[8]) + 1) * sizeof(wchar_t));
+ }
+ }
+ return buff.release();
+}
#else
int symlink_file(const char *oldname, const char *newname) {
return ::symlink(oldname, newname);
@@ -295,6 +332,7 @@
using ::lstat;
using ::mkdir;
using ::open;
+using ::realpath;
using ::remove;
using ::rename;
using ::stat;
Index: libcxx/src/filesystem/operations.cpp
===================================================================
--- libcxx/src/filesystem/operations.cpp
+++ libcxx/src/filesystem/operations.cpp
@@ -636,20 +636,20 @@
ErrorHandler<path> err("canonical", ec, &orig_p, &cwd);
path p = __do_absolute(orig_p, &cwd, ec);
-#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112
- std::unique_ptr<char, decltype(&::free)>
- hold(::realpath(p.c_str(), nullptr), &::free);
+#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || defined(_LIBCPP_WIN32API)
+ std::unique_ptr<path::value_type, decltype(&::free)>
+ hold(detail::realpath(p.c_str(), nullptr), &::free);
if (hold.get() == nullptr)
return err.report(capture_errno());
return {hold.get()};
#else
#if defined(__MVS__) && !defined(PATH_MAX)
- char buff[ _XOPEN_PATH_MAX + 1 ];
+ path::value_type buff[ _XOPEN_PATH_MAX + 1 ];
#else
- char buff[PATH_MAX + 1];
+ path::value_type buff[PATH_MAX + 1];
#endif
- char* ret;
- if ((ret = ::realpath(p.c_str(), buff)) == nullptr)
+ path::value_type* ret;
+ if ((ret = detail::realpath(p.c_str(), buff)) == nullptr)
return err.report(capture_errno());
return {ret};
#endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D91170.320103.patch
Type: text/x-patch
Size: 3222 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20210129/57f8658d/attachment.bin>
More information about the libcxx-commits
mailing list