[VFS] Reimplement ResolvePath. Add FindSymbolicLink, ResolveSymbolicLink.
This commit is contained in:
parent
54b0e2aff6
commit
05d2d76cff
|
@ -66,15 +66,40 @@ bool VirtualFileSystem::UnregisterSymbolicLink(const std::string& path) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VirtualFileSystem::IsSymbolicLink(const std::string& path) {
|
bool VirtualFileSystem::FindSymbolicLink(const std::string& path,
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
std::string& target) {
|
||||||
auto it = symlinks_.find(path);
|
auto it =
|
||||||
if (it == symlinks_.end()) {
|
std::find_if(symlinks_.cbegin(), symlinks_.cend(), [&](const auto& s) {
|
||||||
|
return xe::find_first_of_case(path, s.first) == 0;
|
||||||
|
});
|
||||||
|
if (it == symlinks_.cend()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
target = (*it).second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VirtualFileSystem::ResolveSymbolicLink(const std::string& path,
|
||||||
|
std::string& result) {
|
||||||
|
result = path;
|
||||||
|
bool was_resolved = false;
|
||||||
|
while (true) {
|
||||||
|
auto it =
|
||||||
|
std::find_if(symlinks_.cbegin(), symlinks_.cend(), [&](const auto& s) {
|
||||||
|
return xe::find_first_of_case(result, s.first) == 0;
|
||||||
|
});
|
||||||
|
if (it == symlinks_.cend()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Found symlink!
|
||||||
|
auto target_path = (*it).second;
|
||||||
|
auto relative_path = result.substr((*it).first.size());
|
||||||
|
result = target_path + relative_path;
|
||||||
|
was_resolved = true;
|
||||||
|
}
|
||||||
|
return was_resolved;
|
||||||
|
}
|
||||||
|
|
||||||
Entry* VirtualFileSystem::ResolvePath(const std::string& path) {
|
Entry* VirtualFileSystem::ResolvePath(const std::string& path) {
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
|
|
||||||
|
@ -82,54 +107,24 @@ Entry* VirtualFileSystem::ResolvePath(const std::string& path) {
|
||||||
std::string normalized_path(xe::filesystem::CanonicalizePath(path));
|
std::string normalized_path(xe::filesystem::CanonicalizePath(path));
|
||||||
|
|
||||||
// Resolve symlinks.
|
// Resolve symlinks.
|
||||||
std::string device_path;
|
std::string resolved_path;
|
||||||
std::string relative_path;
|
if (ResolveSymbolicLink(normalized_path, resolved_path)) {
|
||||||
for (int i = 0; i < 2; i++) {
|
normalized_path = resolved_path;
|
||||||
for (const auto& it : symlinks_) {
|
|
||||||
if (xe::find_first_of_case(normalized_path, it.first) == 0) {
|
|
||||||
// Found symlink!
|
|
||||||
device_path = it.second;
|
|
||||||
if (relative_path.empty()) {
|
|
||||||
relative_path = normalized_path.substr(it.first.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bit of a cheaty move here, but allows double symlinks to be resolved.
|
|
||||||
normalized_path = device_path;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Break as soon as we've completely resolved the symlinks to a device.
|
|
||||||
if (!IsSymbolicLink(device_path)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_path.empty()) {
|
// Find the device.
|
||||||
// Symlink wasn't passed in - Check if we've received a raw device name.
|
auto it =
|
||||||
for (auto& device : devices_) {
|
std::find_if(devices_.cbegin(), devices_.cend(), [&](const auto& d) {
|
||||||
if (xe::find_first_of_case(normalized_path, device->mount_path()) == 0) {
|
return xe::find_first_of_case(normalized_path, d->mount_path()) == 0;
|
||||||
device_path = device->mount_path();
|
});
|
||||||
relative_path = normalized_path.substr(device_path.size());
|
if (it == devices_.cend()) {
|
||||||
}
|
XELOGE("ResolvePath(%s) failed - device not found", path.c_str());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device_path.empty()) {
|
|
||||||
XELOGE("ResolvePath(%s) failed - no root found", path.c_str());
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan all devices.
|
const auto& device = *it;
|
||||||
for (auto& device : devices_) {
|
auto relative_path = normalized_path.substr(device->mount_path().size());
|
||||||
if (strcasecmp(device_path.c_str(), device->mount_path().c_str()) == 0) {
|
return device->ResolvePath(relative_path);
|
||||||
return device->ResolvePath(relative_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
XELOGE("ResolvePath(%s) failed - device not found (%s)", path.c_str(),
|
|
||||||
device_path.c_str());
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* VirtualFileSystem::ResolveBasePath(const std::string& path) {
|
Entry* VirtualFileSystem::ResolveBasePath(const std::string& path) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ class VirtualFileSystem {
|
||||||
|
|
||||||
bool RegisterSymbolicLink(const std::string& path, const std::string& target);
|
bool RegisterSymbolicLink(const std::string& path, const std::string& target);
|
||||||
bool UnregisterSymbolicLink(const std::string& path);
|
bool UnregisterSymbolicLink(const std::string& path);
|
||||||
bool IsSymbolicLink(const std::string& path);
|
bool FindSymbolicLink(const std::string& path, std::string& target);
|
||||||
|
|
||||||
Entry* ResolvePath(const std::string& path);
|
Entry* ResolvePath(const std::string& path);
|
||||||
Entry* ResolveBasePath(const std::string& path);
|
Entry* ResolveBasePath(const std::string& path);
|
||||||
|
@ -50,6 +50,8 @@ class VirtualFileSystem {
|
||||||
xe::global_critical_region global_critical_region_;
|
xe::global_critical_region global_critical_region_;
|
||||||
std::vector<std::unique_ptr<Device>> devices_;
|
std::vector<std::unique_ptr<Device>> devices_;
|
||||||
std::unordered_map<std::string, std::string> symlinks_;
|
std::unordered_map<std::string, std::string> symlinks_;
|
||||||
|
|
||||||
|
bool ResolveSymbolicLink(const std::string& path, std::string& result);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace vfs
|
} // namespace vfs
|
||||||
|
|
Loading…
Reference in New Issue