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,

Reply via email to