This is an automated email from the ASF dual-hosted git repository. jieyu pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 516c0bd70c50ae5aa6682b3b8675ef75d99dfc3f Author: Jason Lai <ja...@jasonlai.net> AuthorDate: Sun Nov 18 21:12:06 2018 -0800 Added Stout `path::normalize` function for POSIX paths. Added `path::normalize` to normalize a given pathname and remove redundant separators and up-level references. This function follows the rules described in `path_resolution(7)` for Linux. However, it only performs pure lexical processing without touching the actual filesystem. Review: https://reviews.apache.org/r/65811/ --- 3rdparty/stout/include/stout/path.hpp | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/3rdparty/stout/include/stout/path.hpp b/3rdparty/stout/include/stout/path.hpp index ef5a2f3..ba1f665 100644 --- a/3rdparty/stout/include/stout/path.hpp +++ b/3rdparty/stout/include/stout/path.hpp @@ -52,6 +52,63 @@ inline std::string from_uri(const std::string& uri) } +// Normalizes a given pathname and removes redundant separators and up-level +// references. +// +// Pathnames like `A/B/`, `A///B`, `A/./B`, 'A/foobar/../B` are all normalized +// to `A/B`. An empty pathname is normalized to `.`. Up-level entry also cannot +// escape a root path, in which case an error will be returned. +// +// This function follows the rules described in path_resolution(7) for Linux. +// However, it only performs pure lexical processing without touching the +// actual filesystem. +inline Try<std::string> normalize( + const std::string& path, + const char _separator = os::PATH_SEPARATOR) +{ + if (path.empty()) { + return "."; + } + + std::vector<std::string> components; + const bool isAbs = (path[0] == _separator); + const std::string separator(1, _separator); + + // TODO(jasonlai): Handle pathnames (including absolute paths) in Windows. + + foreach (const std::string& component, strings::tokenize(path, separator)) { + // Skips empty components and "." (current directory). + if (component == "." || component.empty()) { + continue; + } + + if (component == "..") { + if (components.empty()) { + if (isAbs) { + return Error("Absolute path '" + path + "' tries to escape root"); + } + components.push_back(component); + } else if (components.back() == "..") { + components.push_back(component); + } else { + components.pop_back(); + } + } else { + components.push_back(component); + } + } + + if (components.empty()) { + return isAbs ? separator : "."; + } else if (isAbs) { + // Make sure that a separator is prepended if it is an absolute path. + components.insert(components.begin(), ""); + } + + return strings::join(separator, components); +} + + // Base case. inline std::string join( const std::string& path1,