Skip to content

<filesystem>: weakly_canonical fails for UNC path with \\?\UNC prefix #2823

Open
@manxorist

Description

@manxorist

Describe the bug
std::filesystem::weakly_canonical fails for UNC path with \\?\UNC prefix.

Command-line test case

C:\Users\manx\stuff>type weakly_canonical.cpp
#include <filesystem>
#include <iostream>

int main() {
    try {
        std::wcout << std::filesystem::weakly_canonical(L"\\\\?\\UNC\\server\\share\\dir\\name.ext").wstring() << std::endl;
    } catch (const std::exception & e) {
        std::wcout << std::flush;
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

C:\Users\manx\stuff>cl /std:c++20 /permissive- /EHsc /O2 /W4 weakly_canonical.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.32.31332 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

weakly_canonical.cpp
Microsoft (R) Incremental Linker Version 14.32.31332.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:weakly_canonical.exe
weakly_canonical.obj

C:\Users\manx\stuff>weakly_canonical.exe
weakly_canonical: Incorrect function.: "\\?\UNC\server\share\dir\name.ext"

C:\Users\manx\stuff>

(https://godbolt.org/z/v83fbPfrW)

Expected behavior
weakly_canonical does work for plain UNC paths without \\?\UNC prefix, so I think it should also work for prefixed ones:

#include <filesystem>
#include <iostream>

void show(std::filesystem::path p) {
    std::wcout << L"path: " << p.wstring() << std::endl;
    std::wcout << L" absolute: " << std::filesystem::absolute(p).wstring() << std::endl;
    std::wcout << L" canonical: " << std::filesystem::weakly_canonical(p).wstring() << std::endl;
    std::wcout << L" root name " << p.root_name().wstring() << std::endl;
    std::wcout << L" root directory " << p.root_directory().wstring() << std::endl;
    std::wcout << L" relative path " << p.relative_path().wstring() << std::endl;
}

int main() {
    try {
        show(std::filesystem::current_path());
        show(L"C:\\dir\\name.ext");
        show(L"\\\\.\\C:\\dir\\name.ext");
        show(L"\\\\?\\C:\\dir\\name.ext");
        show(L"\\\\server\\share\\dir\\name.ext");
        show(L"\\\\?\\UNC\\server\\share\\dir\\name.ext");
    } catch (const std::exception & e) {
        std::wcout << std::flush;
        std::cerr << e.what() << std::endl;
    }
    return 0;
}

(https://godbolt.org/z/rEdMvWs7h)

_NODISCARD inline const wchar_t* _Find_root_name_end(const wchar_t* const _First, const wchar_t* const _Last) {
talks about this prefix, so I would assume std::filesystem to be aware of it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingfilesystemC++17 filesystem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions