MCPcopy Create free account
hub / github.com/clechasseur/pathcopycopy / FollowSymlinkIfRequired

Method FollowSymlinkIfRequired

PathCopyCopy/src/PluginUtils.cpp:145–191  ·  view source on GitHub ↗

If the provided path or one of its parents points to a symbolic link, follow the symlink and return the path to its target. @param p_rPath Path to follow symlink for, if required. @return true if p_rPath or one of its parents pointed to a symlink.

Source from the content-addressed store, hash-verified

143 // @return true if p_rPath or one of its parents pointed to a symlink.
144 //
145 bool PluginUtils::FollowSymlinkIfRequired(std::wstring& p_rPath)
146 {
147 using namespace coveo::linq;
148
149 // Check if path or one of its parent points to a symlink.
150 const auto isSymlink = [](const std::wstring& path) noexcept {
151 const auto attributes = ::GetFileAttributesW(path.c_str());
152 return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
153 };
154 const bool symlink = from(coveo::enumerate_one(p_rPath))
155 | concat(EnumerateParents(p_rPath))
156 | any(isSymlink);
157 if (symlink) {
158 // In order to follow the symlink, we need a handle.
159 DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
160 if ((::GetFileAttributesW(p_rPath.c_str()) & FILE_ATTRIBUTE_DIRECTORY) != 0) {
161 // Need this flag to open directory handles according to MSDN
162 flagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
163 }
164 StHandle hFile = ::CreateFileW(p_rPath.c_str(),
165 GENERIC_READ,
166 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
167 nullptr,
168 OPEN_EXISTING,
169 flagsAndAttributes,
170 nullptr);
171 if (hFile != nullptr) {
172 const auto bufferSize = ::GetFinalPathNameByHandleW(hFile, nullptr, 0, FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
173 if (bufferSize != 0) {
174 std::wstring finalPath(bufferSize + 1, L'\0');
175 const auto finalPathRes = ::GetFinalPathNameByHandleW(hFile,
176 &*finalPath.begin(),
177 bufferSize + 1,
178 FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
179 if (finalPathRes != 0) {
180 p_rPath = finalPath.c_str();
181
182 // Fetching symlink target probably left us with a weird path, fix it
183 // because Explorer can't handle paths with \\?\ in them.
184 StringUtils::ReplaceAll(p_rPath, UNC_DRIVE_SYMLINK_PREFIX, L"");
185 StringUtils::ReplaceAll(p_rPath, LOCAL_DRIVE_SYMLINK_PREFIX, L"");
186 }
187 }
188 }
189 }
190 return symlink;
191 }
192
193 //
194 // Checks if the given path is a UNC path in the form

Callers

nothing calls this directly

Calls 5

fromFunction · 0.85
enumerate_oneFunction · 0.85
concatFunction · 0.85
anyFunction · 0.85
beginMethod · 0.45

Tested by

no test coverage detected