查找符号链接指向的位置(Windows)

时间:2022-11-15 16:26:24

I use FindFirstFile() and co-functions to browse the contents of C:\example\dir. I know that a file read can be a symbolic link, a junction, etc by checking whether d.dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0. However, I haven't found a way to follow the link and see the location it is pointing to. Is that even possible?

我使用FindFirstFile()和共同函数来浏览C:\ example \ dir的内容。我知道通过检查d.dwAttributes&FILE_ATTRIBUTE_REPARSE_POINT!= 0,文件读取可以是符号链接,交汇点等。但是,我还没有找到一种方法来跟踪链接并查看它指向的位置。这有可能吗?

1 个解决方案

#1


3  

To find the target of a symbolic link, you have to open the symbolic link. The object manager dereferences the link and returns a handle to the target location. Calling GetFinalPathNameByHandle on that handle returns the pathname of the target.

要查找符号链接的目标,您必须打开符号链接。对象管理器取消引用链接并返回目标位置的句柄。在该句柄上调用GetFinalPathNameByHandle将返回目标的路径名。

The following implementation returns the target location, given a symbolic link:

给定符号链接,以下实现返回目标位置:

std::wstring GetLinkTarget( const std::wstring& a_Link ) {
    // Define smart pointer type for automatic HANDLE cleanup.
    typedef std::unique_ptr<std::remove_pointer<HANDLE>::type,
                            decltype( &::CloseHandle )> FileHandle;
    // Open file for querying only (no read/write access).
    FileHandle h( ::CreateFileW( a_Link.c_str(), 0,
                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ),
                  &::CloseHandle );
    if ( h.get() == INVALID_HANDLE_VALUE ) {
        h.release();
        throw std::runtime_error( "CreateFileW() failed." );
    }

    const size_t requiredSize = ::GetFinalPathNameByHandleW( h.get(), nullptr, 0,
                                                             FILE_NAME_NORMALIZED );
    if ( requiredSize == 0 ) {
        throw std::runtime_error( "GetFinalPathNameByHandleW() failed." );
    }
    std::vector<wchar_t> buffer( requiredSize );
    ::GetFinalPathNameByHandleW( h.get(), buffer.data(),
                                 static_cast<DWORD>( buffer.size() ),
                                 FILE_NAME_NORMALIZED );

    return std::wstring( buffer.begin(), buffer.end() - 1 );
}


Note: For details about the RAII wrapper based on std::unique_ptr see std::unique_ptr, deleters and the Win32 API.

#1


3  

To find the target of a symbolic link, you have to open the symbolic link. The object manager dereferences the link and returns a handle to the target location. Calling GetFinalPathNameByHandle on that handle returns the pathname of the target.

要查找符号链接的目标,您必须打开符号链接。对象管理器取消引用链接并返回目标位置的句柄。在该句柄上调用GetFinalPathNameByHandle将返回目标的路径名。

The following implementation returns the target location, given a symbolic link:

给定符号链接,以下实现返回目标位置:

std::wstring GetLinkTarget( const std::wstring& a_Link ) {
    // Define smart pointer type for automatic HANDLE cleanup.
    typedef std::unique_ptr<std::remove_pointer<HANDLE>::type,
                            decltype( &::CloseHandle )> FileHandle;
    // Open file for querying only (no read/write access).
    FileHandle h( ::CreateFileW( a_Link.c_str(), 0,
                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                 nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr ),
                  &::CloseHandle );
    if ( h.get() == INVALID_HANDLE_VALUE ) {
        h.release();
        throw std::runtime_error( "CreateFileW() failed." );
    }

    const size_t requiredSize = ::GetFinalPathNameByHandleW( h.get(), nullptr, 0,
                                                             FILE_NAME_NORMALIZED );
    if ( requiredSize == 0 ) {
        throw std::runtime_error( "GetFinalPathNameByHandleW() failed." );
    }
    std::vector<wchar_t> buffer( requiredSize );
    ::GetFinalPathNameByHandleW( h.get(), buffer.data(),
                                 static_cast<DWORD>( buffer.size() ),
                                 FILE_NAME_NORMALIZED );

    return std::wstring( buffer.begin(), buffer.end() - 1 );
}


Note: For details about the RAII wrapper based on std::unique_ptr see std::unique_ptr, deleters and the Win32 API.