You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by an...@apache.org on 2018/01/16 21:35:02 UTC

[2/3] mesos git commit: Ported `os::which` to Windows.

Ported `os::which` to Windows.

Because `os::which` still lived in `posix/os.hpp`, it was refactored
into its own `os/which.hpp` (which the respective `os/posix/which.hpp`
and `os/windows/which.hpp`. Consumers of this will need additionally
include the new header, instead of just `os.hpp`.

The differences in implementation from POSIX to Windows are:

* Split the `PATH` on `;` not `:`.
* Also loop over `PATHEXT` because executables on Windows end with one
  of a set of extensions.
* Removed the permissions check because it is not applicable on
  Windows (instead, an executable ends with an extension in `PATHEXT`,
  see above).

Review: https://reviews.apache.org/r/65144


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/c8594dcc
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/c8594dcc
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/c8594dcc

Branch: refs/heads/master
Commit: c8594dcc31b75d67c5f72488479cf7c7baac98e1
Parents: de508d9
Author: Andrew Schwartzmeyer <an...@schwartzmeyer.com>
Authored: Fri Jan 12 15:14:43 2018 -0800
Committer: Andrew Schwartzmeyer <an...@schwartzmeyer.com>
Committed: Tue Jan 16 11:53:43 2018 -0800

----------------------------------------------------------------------
 3rdparty/stout/include/Makefile.am              |  3 +
 3rdparty/stout/include/stout/os/posix/which.hpp | 72 ++++++++++++++++
 3rdparty/stout/include/stout/os/which.hpp       | 24 ++++++
 .../stout/include/stout/os/windows/which.hpp    | 90 ++++++++++++++++++++
 3rdparty/stout/include/stout/posix/os.hpp       | 39 ---------
 3rdparty/stout/tests/os_tests.cpp               |  6 +-
 6 files changed, 191 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c8594dcc/3rdparty/stout/include/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/Makefile.am b/3rdparty/stout/include/Makefile.am
index e5f1104..742bfc4 100644
--- a/3rdparty/stout/include/Makefile.am
+++ b/3rdparty/stout/include/Makefile.am
@@ -115,6 +115,7 @@ nobase_include_HEADERS =			\
   stout/os/touch.hpp				\
   stout/os/utime.hpp				\
   stout/os/wait.hpp				\
+  stout/os/which.hpp				\
   stout/os/write.hpp				\
   stout/os/xattr.hpp				\
   stout/os/posix/bootid.hpp			\
@@ -152,6 +153,7 @@ nobase_include_HEADERS =			\
   stout/os/posix/stat.hpp			\
   stout/os/posix/su.hpp				\
   stout/os/posix/temp.hpp			\
+  stout/os/posix/which.hpp			\
   stout/os/posix/write.hpp			\
   stout/os/posix/xattr.hpp			\
   stout/os/raw/argv.hpp				\
@@ -191,6 +193,7 @@ nobase_include_HEADERS =			\
   stout/os/windows/stat.hpp			\
   stout/os/windows/su.hpp			\
   stout/os/windows/temp.hpp			\
+  stout/os/windows/which.hpp			\
   stout/os/windows/write.hpp			\
   stout/os/windows/xattr.hpp			\
   stout/path.hpp				\

http://git-wip-us.apache.org/repos/asf/mesos/blob/c8594dcc/3rdparty/stout/include/stout/os/posix/which.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/posix/which.hpp b/3rdparty/stout/include/stout/os/posix/which.hpp
new file mode 100644
index 0000000..96586dd
--- /dev/null
+++ b/3rdparty/stout/include/stout/os/posix/which.hpp
@@ -0,0 +1,72 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __STOUT_OS_POSIX_WHICH_HPP__
+#define __STOUT_OS_POSIX_WHICH_HPP__
+
+#include <string>
+#include <vector>
+
+#include <stout/none.hpp>
+#include <stout/option.hpp>
+#include <stout/os.hpp>
+#include <stout/path.hpp>
+#include <stout/strings.hpp>
+
+#include <stout/os/exists.hpp>
+#include <stout/os/permissions.hpp>
+
+
+namespace os {
+
+inline Option<std::string> which(
+    const std::string& command,
+    const Option<std::string>& _path = None())
+{
+  Option<std::string> path = _path;
+
+  if (path.isNone()) {
+    path = getenv("PATH");
+
+    if (path.isNone()) {
+      return None();
+    }
+  }
+
+  std::vector<std::string> tokens = strings::tokenize(path.get(), ":");
+  foreach (const std::string& token, tokens) {
+    const std::string commandPath = path::join(token, command);
+    if (!os::exists(commandPath)) {
+      continue;
+    }
+
+    Try<os::Permissions> permissions = os::permissions(commandPath);
+    if (permissions.isError()) {
+      continue;
+    }
+
+    if (!permissions.get().owner.x &&
+        !permissions.get().group.x &&
+        !permissions.get().others.x) {
+      continue;
+    }
+
+    return commandPath;
+  }
+
+  return None();
+}
+
+} // namespace os {
+
+
+#endif // __STOUT_OS_POSIX_WHICH_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/c8594dcc/3rdparty/stout/include/stout/os/which.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/which.hpp b/3rdparty/stout/include/stout/os/which.hpp
new file mode 100644
index 0000000..af0a7e8
--- /dev/null
+++ b/3rdparty/stout/include/stout/os/which.hpp
@@ -0,0 +1,24 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __STOUT_OS_WHICH_HPP__
+#define __STOUT_OS_WHICH_HPP__
+
+// For readability, we minimize the number of #ifdef blocks in the code by
+// splitting platform specific system calls into separate directories.
+#ifdef __WINDOWS__
+#include <stout/os/windows/which.hpp>
+#else
+#include <stout/os/posix/which.hpp>
+#endif // __WINDOWS__
+
+#endif // __STOUT_OS_WHICH_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/c8594dcc/3rdparty/stout/include/stout/os/windows/which.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/os/windows/which.hpp b/3rdparty/stout/include/stout/os/windows/which.hpp
new file mode 100644
index 0000000..fc541cc
--- /dev/null
+++ b/3rdparty/stout/include/stout/os/windows/which.hpp
@@ -0,0 +1,90 @@
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __STOUT_OS_WINDOWS_WHICH_HPP__
+#define __STOUT_OS_WINDOWS_WHICH_HPP__
+
+#include <string>
+#include <vector>
+
+#include <stout/none.hpp>
+#include <stout/option.hpp>
+#include <stout/os.hpp>
+#include <stout/path.hpp>
+#include <stout/strings.hpp>
+
+#include <stout/os/exists.hpp>
+
+
+namespace os {
+
+// This behaves "like the user expects" of POSIX `which`, but on Windows. That
+// is, if a path is not specified, we search through the `PATH` environment
+// variable, but explicitly do not search the current working directory (which
+// `CreateProcess` and Windows' `where` would do).
+//
+// Because the executable permission does not work on Windows, the closest
+// equivalent is to check the path extension against those listed in `PATHEXT`.
+// However, we first search for exactly the file name the user specified with
+// `command`, regardless of extension, because it could be an executable. If an
+// exact match is not found, we continue the search with the environment's
+// "executable" extensions.
+inline Option<std::string> which(
+    const std::string& command,
+    const Option<std::string>& _path = None())
+{
+  Option<std::string> path = _path;
+
+  if (path.isNone()) {
+    path = os::getenv("PATH");
+
+    if (path.isNone()) {
+      return None();
+    }
+  }
+
+  Option<std::string> pathext = os::getenv("PATHEXT");
+
+  if (pathext.isNone()) {
+    pathext = ".COM;.EXE;.BAT;.CMD";
+  }
+
+  std::vector<std::string> tokens = strings::tokenize(path.get(), ";");
+  std::vector<std::string> exts = strings::tokenize(pathext.get(), ";");
+
+  // NOTE: This handles the edge case of `command` already having an extension,
+  // e.g. `docker.exe`. By starting with the case of "", we don't have to
+  // special case the loops below.
+  exts.insert(exts.begin(), "");
+
+  // Nested loops, but fairly finite. This is how `where` works on Windows
+  // (which is the equivalent of `which`). The loops are nested such that we
+  // first search through `PATH` for `command`, then through `PATH` for
+  // `command.COM` and so on.
+  foreach (const std::string& ext, exts) {
+    foreach (const std::string& token, tokens) {
+      const std::string commandPath = path::join(token, command + ext);
+      if (!os::exists(commandPath)) {
+        continue;
+      }
+
+      return commandPath;
+    }
+  }
+
+  return None();
+}
+
+} // namespace os {
+
+
+#endif // __STOUT_OS_WINDOWS_WHICH_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/c8594dcc/3rdparty/stout/include/stout/posix/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/posix/os.hpp b/3rdparty/stout/include/stout/posix/os.hpp
index 7427bd7..3c52a49 100644
--- a/3rdparty/stout/include/stout/posix/os.hpp
+++ b/3rdparty/stout/include/stout/posix/os.hpp
@@ -403,45 +403,6 @@ inline Try<Version> release()
 }
 
 
-inline Option<std::string> which(
-    const std::string& command,
-    const Option<std::string>& _path = None())
-{
-  Option<std::string> path = _path;
-
-  if (path.isNone()) {
-    path = getenv("PATH");
-
-    if (path.isNone()) {
-      return None();
-    }
-  }
-
-  std::vector<std::string> tokens = strings::tokenize(path.get(), ":");
-  foreach (const std::string& token, tokens) {
-    const std::string commandPath = path::join(token, command);
-    if (!os::exists(commandPath)) {
-      continue;
-    }
-
-    Try<os::Permissions> permissions = os::permissions(commandPath);
-    if (permissions.isError()) {
-      continue;
-    }
-
-    if (!permissions.get().owner.x &&
-        !permissions.get().group.x &&
-        !permissions.get().others.x) {
-      continue;
-    }
-
-    return commandPath;
-  }
-
-  return None();
-}
-
-
 inline Try<std::string> var()
 {
   return "/var";

http://git-wip-us.apache.org/repos/asf/mesos/blob/c8594dcc/3rdparty/stout/tests/os_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/tests/os_tests.cpp b/3rdparty/stout/tests/os_tests.cpp
index de41077..11f1720 100644
--- a/3rdparty/stout/tests/os_tests.cpp
+++ b/3rdparty/stout/tests/os_tests.cpp
@@ -50,6 +50,7 @@
 #include <stout/os/killtree.hpp>
 #include <stout/os/realpath.hpp>
 #include <stout/os/stat.hpp>
+#include <stout/os/which.hpp>
 #include <stout/os/write.hpp>
 
 #if defined(__APPLE__) || defined(__FreeBSD__)
@@ -1035,15 +1036,12 @@ TEST_F(OsTest, SYMLINK_Realpath)
 }
 
 
-// NOTE: Disabled on Windows because `which` doesn't exist.
-#ifndef __WINDOWS__
 TEST_F(OsTest, Which)
 {
   // TODO(jieyu): Test PATH search ordering and file execution bit.
-  Option<string> which = os::which("ls");
+  Option<string> which = os::which("ping");
   ASSERT_SOME(which);
 
   which = os::which("bar");
   EXPECT_NONE(which);
 }
-#endif // __WINDOWS__