| 227 | } |
| 228 | |
| 229 | Control ImplBase::ResolveSymlink(Root root, std::string::size_type slash, |
| 230 | std::string::size_type next_slash, |
| 231 | std::string symlink_target) |
| 232 | { |
| 233 | std::replace(symlink_target.begin(), symlink_target.end(), '\\', '/'); |
| 234 | Root const symlink_target_root = ClassifyRoot(symlink_target); |
| 235 | if (symlink_target_root == Root::None) { |
| 236 | // This is a symlink to a relative path. |
| 237 | // Resolve the symlink, while preserving the leading and |
| 238 | // trailing (if any) slash: |
| 239 | // "*/link/" => "*/dest/" |
| 240 | // ^slash ^slash |
| 241 | P.replace(slash + 1, next_slash - slash - 1, symlink_target); |
| 242 | return Control::Continue(slash); |
| 243 | } |
| 244 | |
| 245 | #ifdef _WIN32 |
| 246 | if (root == Root::Drive && symlink_target_root == Root::POSIX) { |
| 247 | // This is a symlink to a POSIX absolute path, |
| 248 | // but the current path is on a drive letter. Resolve the |
| 249 | // symlink while preserving the drive letter, and start over: |
| 250 | // "C:/*/link/" => "C:/dest/" |
| 251 | // ^slash (restart) |
| 252 | P.replace(2, next_slash - 2, symlink_target); |
| 253 | return Control::Restart(); |
| 254 | } |
| 255 | #else |
| 256 | static_cast<void>(root); |
| 257 | #endif |
| 258 | |
| 259 | // This is a symlink to an absolute path. |
| 260 | // Resolve it and start over: |
| 261 | // "*/link/" => "/dest/" |
| 262 | // ^slash (restart) |
| 263 | P.replace(0, next_slash, symlink_target); |
| 264 | return Control::Restart(); |
| 265 | } |
| 266 | |
| 267 | template <class Policy> |
| 268 | Control Impl<Policy>::ResolveRoot(Root root) |
no test coverage detected