You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2016/01/16 22:10:02 UTC
[1/3] mesos git commit: Moved filesystems tests to their own file.
Repository: mesos
Updated Branches:
refs/heads/master 1b56d99bf -> a465c45cd
Moved filesystems tests to their own file.
Review: https://reviews.apache.org/r/39805/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/a465c45c
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/a465c45c
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/a465c45c
Branch: refs/heads/master
Commit: a465c45cd12d1d0b1e9aaba1d7702e773ff23fc0
Parents: a4aa314
Author: Alex Clemmer <cl...@gmail.com>
Authored: Sat Jan 16 15:44:37 2016 -0500
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Sat Jan 16 16:09:51 2016 -0500
----------------------------------------------------------------------
3rdparty/libprocess/3rdparty/stout/Makefile.am | 1 +
.../stout/include/stout/tests/utils.hpp | 6 +-
.../3rdparty/stout/tests/CMakeLists.txt | 1 +
.../stout/tests/os/filesystem_tests.cpp | 142 +++++++++++++++++++
.../3rdparty/stout/tests/path_tests.cpp | 3 +
5 files changed, 152 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/a465c45c/3rdparty/libprocess/3rdparty/stout/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/Makefile.am b/3rdparty/libprocess/3rdparty/stout/Makefile.am
index 206489c..0bddd00 100644
--- a/3rdparty/libprocess/3rdparty/stout/Makefile.am
+++ b/3rdparty/libprocess/3rdparty/stout/Makefile.am
@@ -44,6 +44,7 @@ EXTRA_DIST = \
tests/numify_tests.cpp \
tests/option_tests.cpp \
tests/os_tests.cpp \
+ tests/os/filesystem_tests.cpp \
tests/os/sendfile_tests.cpp \
tests/os/signals_tests.cpp \
tests/os/strerror_tests.cpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/a465c45c/3rdparty/libprocess/3rdparty/stout/include/stout/tests/utils.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/tests/utils.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/tests/utils.hpp
index 3cff837..4e5359c 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/tests/utils.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/tests/utils.hpp
@@ -18,9 +18,13 @@
#include <gtest/gtest.h>
#include <stout/gtest.hpp>
-#include <stout/os.hpp>
#include <stout/try.hpp>
+#include <stout/os/chdir.hpp>
+#include <stout/os/getcwd.hpp>
+#include <stout/os/mkdtemp.hpp>
+#include <stout/os/rmdir.hpp>
+
class TemporaryDirectoryTest : public ::testing::Test
{
protected:
http://git-wip-us.apache.org/repos/asf/mesos/blob/a465c45c/3rdparty/libprocess/3rdparty/stout/tests/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/CMakeLists.txt b/3rdparty/libprocess/3rdparty/stout/tests/CMakeLists.txt
index ebf9795..3c65d04 100644
--- a/3rdparty/libprocess/3rdparty/stout/tests/CMakeLists.txt
+++ b/3rdparty/libprocess/3rdparty/stout/tests/CMakeLists.txt
@@ -36,6 +36,7 @@ set(STOUT_TESTS_SRC
none_tests.cpp
numify_tests.cpp
option_tests.cpp
+ os/filesystem_tests.cpp
protobuf_tests.pb.h
protobuf_tests.proto
result_tests.cpp
http://git-wip-us.apache.org/repos/asf/mesos/blob/a465c45c/3rdparty/libprocess/3rdparty/stout/tests/os/filesystem_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/os/filesystem_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/os/filesystem_tests.cpp
new file mode 100644
index 0000000..c5ffd01
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/tests/os/filesystem_tests.cpp
@@ -0,0 +1,142 @@
+// 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
+
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+
+#include <stout/foreach.hpp>
+#include <stout/hashset.hpp>
+#include <stout/path.hpp>
+#include <stout/try.hpp>
+#include <stout/uuid.hpp>
+
+#include <stout/os/find.hpp>
+#include <stout/os/getcwd.hpp>
+#include <stout/os/ls.hpp>
+#include <stout/os/mkdir.hpp>
+#include <stout/os/read.hpp>
+#include <stout/os/touch.hpp>
+#include <stout/os/write.hpp>
+
+#include <stout/tests/utils.hpp>
+
+using std::list;
+using std::set;
+using std::string;
+
+
+static hashset<string> listfiles(const string& directory)
+{
+ hashset<string> fileset;
+ Try<std::list<std::string>> entries = os::ls(directory);
+ if (entries.isSome()) {
+ foreach (const string& entry, entries.get()) {
+ fileset.insert(entry);
+ }
+ }
+ return fileset;
+}
+
+
+class FsTest : public TemporaryDirectoryTest {};
+
+
+TEST_F(FsTest, Find)
+{
+ const string testdir = path::join(os::getcwd(), UUID::random().toString());
+ const string subdir = testdir + "/test1";
+ ASSERT_SOME(os::mkdir(subdir)); // Create the directories.
+
+ // Now write some files.
+ const string file1 = testdir + "/file1.txt";
+ const string file2 = subdir + "/file2.txt";
+ const string file3 = subdir + "/file3.jpg";
+
+ ASSERT_SOME(os::touch(file1));
+ ASSERT_SOME(os::touch(file2));
+ ASSERT_SOME(os::touch(file3));
+
+ // Find "*.txt" files.
+ Try<std::list<string>> result = os::find(testdir, ".txt");
+ ASSERT_SOME(result);
+
+ hashset<string> files;
+ foreach (const string& file, result.get()) {
+ files.insert(file);
+ }
+
+ ASSERT_EQ(2u, files.size());
+ ASSERT_TRUE(files.contains(file1));
+ ASSERT_TRUE(files.contains(file2));
+}
+
+
+TEST_F(FsTest, ReadWriteString)
+{
+ const string testfile = path::join(os::getcwd(), UUID::random().toString());
+ const string teststr = "line1\nline2";
+
+ ASSERT_SOME(os::write(testfile, teststr));
+
+ Try<string> readstr = os::read(testfile);
+
+ EXPECT_SOME_EQ(teststr, readstr);
+}
+
+
+TEST_F(FsTest, Rmdir)
+{
+ const hashset<string> EMPTY;
+ const string tmpdir = os::getcwd();
+
+ hashset<string> expectedListing = EMPTY;
+ EXPECT_EQ(expectedListing, listfiles(tmpdir));
+
+ os::mkdir(tmpdir + "/a/b/c");
+ os::mkdir(tmpdir + "/a/b/d");
+ os::mkdir(tmpdir + "/e/f");
+
+ expectedListing = EMPTY;
+ expectedListing.insert("a");
+ expectedListing.insert("e");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir));
+
+ expectedListing = EMPTY;
+ expectedListing.insert("b");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a"));
+
+ expectedListing = EMPTY;
+ expectedListing.insert("c");
+ expectedListing.insert("d");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a/b"));
+
+ expectedListing = EMPTY;
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a/b/c"));
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/a/b/d"));
+
+ expectedListing.insert("f");
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/e"));
+
+ expectedListing = EMPTY;
+ EXPECT_EQ(expectedListing, listfiles(tmpdir + "/e/f"));
+}
+
+
+TEST_F(FsTest, Touch)
+{
+ const string testfile = path::join(os::getcwd(), UUID::random().toString());
+
+ ASSERT_SOME(os::touch(testfile));
+ ASSERT_TRUE(os::exists(testfile));
+}
http://git-wip-us.apache.org/repos/asf/mesos/blob/a465c45c/3rdparty/libprocess/3rdparty/stout/tests/path_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/tests/path_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/path_tests.cpp
index 79cda84..4568d20 100644
--- a/3rdparty/libprocess/3rdparty/stout/tests/path_tests.cpp
+++ b/3rdparty/libprocess/3rdparty/stout/tests/path_tests.cpp
@@ -17,6 +17,9 @@
#include <stout/path.hpp>
+#include <stout/os/rm.hpp>
+#include <stout/os/touch.hpp>
+
#include <stout/tests/utils.hpp>
using std::string;
[2/3] mesos git commit: Windows: Implemented `os::rmdir.hpp`.
Posted by jo...@apache.org.
Windows: Implemented `os::rmdir.hpp`.
Review: https://reviews.apache.org/r/39584/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/a4aa3145
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/a4aa3145
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/a4aa3145
Branch: refs/heads/master
Commit: a4aa31451e8db580db768ca7ca20b58ac2c1bdf9
Parents: e6db388
Author: Alex Clemmer <cl...@gmail.com>
Authored: Sat Jan 16 15:29:49 2016 -0500
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Sat Jan 16 16:09:51 2016 -0500
----------------------------------------------------------------------
.../3rdparty/stout/include/Makefile.am | 3 +
.../3rdparty/stout/include/stout/os.hpp | 1 +
.../stout/include/stout/os/posix/rmdir.hpp | 86 ++++++++++++
.../3rdparty/stout/include/stout/os/rmdir.hpp | 26 ++++
.../stout/include/stout/os/windows/rmdir.hpp | 137 +++++++++++++++++++
.../3rdparty/stout/include/stout/posix/os.hpp | 57 --------
.../3rdparty/stout/include/stout/windows/os.hpp | 9 --
7 files changed, 253 insertions(+), 66 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/a4aa3145/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/Makefile.am b/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
index 06aa662..0459cb8 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
+++ b/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
@@ -84,6 +84,7 @@ nobase_include_HEADERS = \
stout/os/realpath.hpp \
stout/os/rename.hpp \
stout/os/rm.hpp \
+ stout/os/rmdir.hpp \
stout/os/sendfile.hpp \
stout/os/shell.hpp \
stout/os/signals.hpp \
@@ -102,6 +103,7 @@ nobase_include_HEADERS = \
stout/os/posix/killtree.hpp \
stout/os/posix/mkdtemp.hpp \
stout/os/posix/pstree.hpp \
+ stout/os/posix/rmdir.hpp \
stout/os/posix/sendfile.hpp \
stout/os/posix/shell.hpp \
stout/os/posix/signals.hpp \
@@ -116,6 +118,7 @@ nobase_include_HEADERS = \
stout/os/windows/killtree.hpp \
stout/os/windows/mkdtemp.hpp \
stout/os/windows/pstree.hpp \
+ stout/os/windows/rmdir.hpp \
stout/os/windows/sendfile.hpp \
stout/os/windows/shell.hpp \
stout/os/windows/signals.hpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/a4aa3145/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp
index 486a632..ed3bb2c 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/os.hpp
@@ -90,6 +90,7 @@
#include <stout/os/realpath.hpp>
#include <stout/os/rename.hpp>
#include <stout/os/rm.hpp>
+#include <stout/os/rmdir.hpp>
#include <stout/os/sendfile.hpp>
#include <stout/os/shell.hpp>
#include <stout/os/signals.hpp>
http://git-wip-us.apache.org/repos/asf/mesos/blob/a4aa3145/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/rmdir.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/rmdir.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/rmdir.hpp
new file mode 100644
index 0000000..bc420c9
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/rmdir.hpp
@@ -0,0 +1,86 @@
+// 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_RMDIR_HPP__
+#define __STOUT_OS_POSIX_RMDIR_HPP__
+
+#include <fts.h>
+#include <unistd.h>
+#include <string>
+
+#include <stout/error.hpp>
+#include <stout/nothing.hpp>
+#include <stout/try.hpp>
+
+
+namespace os {
+
+// By default, recursively deletes a directory akin to: 'rm -r'. If the
+// programmer sets recursive to false, it deletes a directory akin to: 'rmdir'.
+// Note that this function expects an absolute path.
+#ifndef __sun // FTS is not available on Solaris.
+inline Try<Nothing> rmdir(const std::string& directory, bool recursive = true)
+{
+ if (!recursive) {
+ if (::rmdir(directory.c_str()) < 0) {
+ return ErrnoError();
+ }
+ } else {
+ char* paths[] = {const_cast<char*>(directory.c_str()), NULL};
+
+ FTS* tree = fts_open(paths, FTS_NOCHDIR, NULL);
+ if (tree == NULL) {
+ return ErrnoError();
+ }
+
+ FTSENT* node;
+ while ((node = fts_read(tree)) != NULL) {
+ switch (node->fts_info) {
+ case FTS_DP:
+ if (::rmdir(node->fts_path) < 0 && errno != ENOENT) {
+ Error error = ErrnoError();
+ fts_close(tree);
+ return error;
+ }
+ break;
+ case FTS_F:
+ case FTS_SL:
+ if (::unlink(node->fts_path) < 0 && errno != ENOENT) {
+ Error error = ErrnoError();
+ fts_close(tree);
+ return error;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (errno != 0) {
+ Error error = ErrnoError();
+ fts_close(tree);
+ return error;
+ }
+
+ if (fts_close(tree) < 0) {
+ return ErrnoError();
+ }
+ }
+
+ return Nothing();
+}
+#endif // __sun
+
+} // namespace os {
+
+
+#endif // __STOUT_OS_POSIX_RMDIR_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/a4aa3145/3rdparty/libprocess/3rdparty/stout/include/stout/os/rmdir.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/os/rmdir.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/os/rmdir.hpp
new file mode 100644
index 0000000..9f662fc
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/os/rmdir.hpp
@@ -0,0 +1,26 @@
+// 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_RMDIR_HPP__
+#define __STOUT_OS_RMDIR_HPP__
+
+
+// For readability, we minimize the number of #ifdef blocks in the code by
+// splitting platform specifc system calls into separate directories.
+#ifdef __WINDOWS__
+#include <stout/os/windows/rmdir.hpp>
+#else
+#include <stout/os/posix/rmdir.hpp>
+#endif // __WINDOWS__
+
+
+#endif // __STOUT_OS_RMDIR_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/a4aa3145/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/rmdir.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/rmdir.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/rmdir.hpp
new file mode 100644
index 0000000..6decdc5
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/rmdir.hpp
@@ -0,0 +1,137 @@
+// 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_RMDIR_HPP__
+#define __STOUT_OS_WINDOWS_RMDIR_HPP__
+
+#include <stout/nothing.hpp>
+#include <stout/strings.hpp>
+#include <stout/try.hpp>
+#include <stout/windows.hpp>
+
+#include <stout/os/realpath.hpp>
+#include <stout/os/stat.hpp>
+
+#include <stout/windows/error.hpp>
+
+
+namespace os {
+namespace internal {
+
+// Recursive version of `RemoveDirectory`. NOTE: unlike `rmdir`, this requires
+// Windows-formatted paths, and therefore should be in the `internal` namespace.
+Try<Nothing> recursive_remove_directory(const std::string& path)
+{
+ // Appending a slash here if the path doesn't already have one simplifies
+ // path join logic later, because (unlike Unix) Windows doesn't like double
+ // slashes in paths.
+ std::string current_path;
+
+ if (!strings::endsWith(path, "\\")) {
+ current_path = path + "\\";
+ } else {
+ current_path = path;
+ }
+
+ // Get first file matching pattern `X:\path\to\wherever\*`.
+ WIN32_FIND_DATA found;
+ const std::string search_pattern = current_path + "*";
+ const SharedHandle search_handle(
+ FindFirstFile(search_pattern.c_str(), &found),
+ FindClose);
+
+ if (search_handle.get() == INVALID_HANDLE_VALUE) {
+ return WindowsError(
+ "`os::internal::recursive_remove_directory` failed when searching "
+ "for files with pattern '" + search_pattern + "'");
+ }
+
+ do {
+ // NOTE: do-while is appropriate here because folder is guaranteed to have
+ // at least a file called `.` (and probably also one called `..`).
+ const std::string current_file(found.cFileName);
+
+ const bool is_current_directory = current_file.compare(".") == 0;
+ const bool is_parent_directory = current_file.compare("..") == 0;
+
+ // Don't try to delete `.` and `..` files in directory.
+ if (is_current_directory || is_parent_directory) {
+ continue;
+ }
+
+ // Path to remove.
+ const std::string current_absolute_path = current_path + current_file;
+
+ const bool is_directory = os::stat::isdir(current_absolute_path);
+
+ // Delete current path, whether it's a directory, file, or symlink.
+ if (is_directory) {
+ Try<Nothing> removed = recursive_remove_directory(current_absolute_path);
+
+ if (removed.isError()) {
+ return Error(removed.error());
+ }
+ } else {
+ // NOTE: this also handles symbolic links.
+ if (::remove(current_absolute_path.c_str()) != 0) {
+ return WindowsError(
+ "`os::internal::recursive_remove_directory` attempted to delete "
+ "file '" + current_absolute_path + "', but failed");
+ }
+ }
+ } while (FindNextFile(search_handle.get(), &found));
+
+ // Finally, remove current directory.
+ if (::_rmdir(current_path.c_str()) == -1) {
+ return ErrnoError(
+ "`os::internal::recursive_remove_directory` attempted to delete file " +
+ "'" + current_path + "', but failed");
+ }
+
+ return Nothing();
+}
+
+} // namespace internal {
+
+
+// By default, recursively deletes a directory akin to: 'rm -r'. If the
+// programmer sets recursive to false, it deletes a directory akin to: 'rmdir'.
+// Note that this function expects an absolute path.
+inline Try<Nothing> rmdir(const std::string& directory, bool recursive = true)
+{
+ // Canonicalize the path to Windows style for the call to
+ // `recursive_remove_directory`.
+ Result<std::string> root = os::realpath(directory);
+
+ if (root.isError()) {
+ return Error(root.error());
+ } else if (root.isNone()) {
+ return Error(
+ "Argument to `os::rmdir` is not a valid directory or file: '" +
+ directory + "'");
+ }
+
+ if (!recursive) {
+ if (::_rmdir(directory.c_str()) < 0) {
+ return ErrnoError();
+ } else {
+ return Nothing();
+ }
+ } else {
+ return os::internal::recursive_remove_directory(root.get());
+ }
+}
+
+} // namespace os {
+
+
+#endif // __STOUT_OS_WINDOWS_RMDIR_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/a4aa3145/3rdparty/libprocess/3rdparty/stout/include/stout/posix/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/posix/os.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/posix/os.hpp
index 4cf693f..c2b9e3d 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/posix/os.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/posix/os.hpp
@@ -109,63 +109,6 @@ inline void unsetenv(const std::string& key)
}
-// By default, recursively deletes a directory akin to: 'rm -r'. If the
-// programmer sets recursive to false, it deletes a directory akin to: 'rmdir'.
-// Note that this function expects an absolute path.
-#ifndef __sun // FTS is not available on Solaris.
-inline Try<Nothing> rmdir(const std::string& directory, bool recursive = true)
-{
- if (!recursive) {
- if (::rmdir(directory.c_str()) < 0) {
- return ErrnoError();
- }
- } else {
- char* paths[] = {const_cast<char*>(directory.c_str()), NULL};
-
- FTS* tree = fts_open(paths, FTS_NOCHDIR, NULL);
- if (tree == NULL) {
- return ErrnoError();
- }
-
- FTSENT* node;
- while ((node = fts_read(tree)) != NULL) {
- switch (node->fts_info) {
- case FTS_DP:
- if (::rmdir(node->fts_path) < 0 && errno != ENOENT) {
- Error error = ErrnoError();
- fts_close(tree);
- return error;
- }
- break;
- case FTS_F:
- case FTS_SL:
- if (::unlink(node->fts_path) < 0 && errno != ENOENT) {
- Error error = ErrnoError();
- fts_close(tree);
- return error;
- }
- break;
- default:
- break;
- }
- }
-
- if (errno != 0) {
- Error error = ErrnoError();
- fts_close(tree);
- return error;
- }
-
- if (fts_close(tree) < 0) {
- return ErrnoError();
- }
- }
-
- return Nothing();
-}
-#endif // __sun
-
-
// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
http://git-wip-us.apache.org/repos/asf/mesos/blob/a4aa3145/3rdparty/libprocess/3rdparty/stout/include/stout/windows/os.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/windows/os.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/windows/os.hpp
index e738cdb..c224e9e 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/windows/os.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/windows/os.hpp
@@ -55,15 +55,6 @@ inline void unsetenv(const std::string& key)
}
-// By default, recursively deletes a directory akin to: 'rm -r'. If the
-// programmer sets recursive to false, it deletes a directory akin to: 'rmdir'.
-// Note that this function expects an absolute path.
-inline Try<Nothing> rmdir(const std::string& directory, bool recursive = true)
-{
- UNIMPLEMENTED;
-}
-
-
// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
[3/3] mesos git commit: Windows: Implemented stout/os/stat.hpp`.
Posted by jo...@apache.org.
Windows: Implemented stout/os/stat.hpp`.
Review: https://reviews.apache.org/r/39803/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/e6db3880
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/e6db3880
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/e6db3880
Branch: refs/heads/master
Commit: e6db3880b6ddf6b2cae6786eb206fcc0cf8ac7c6
Parents: 1b56d99
Author: Alex Clemmer <cl...@gmail.com>
Authored: Sat Jan 16 15:13:32 2016 -0500
Committer: Joris Van Remoortere <jo...@gmail.com>
Committed: Sat Jan 16 16:09:51 2016 -0500
----------------------------------------------------------------------
.../3rdparty/stout/include/Makefile.am | 2 +
.../stout/internal/windows/reparsepoint.hpp | 250 +++++++++++++++++++
.../include/stout/internal/windows/symlink.hpp | 87 +++++++
.../stout/include/stout/os/posix/stat.hpp | 12 +-
.../stout/include/stout/os/windows/stat.hpp | 103 +++++++-
.../3rdparty/stout/include/stout/windows.hpp | 77 +++++-
6 files changed, 507 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/e6db3880/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/Makefile.am b/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
index e6d5b42..06aa662 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
+++ b/3rdparty/libprocess/3rdparty/stout/include/Makefile.am
@@ -39,6 +39,8 @@ nobase_include_HEADERS = \
stout/internal/windows/dirent.hpp \
stout/internal/windows/grp.hpp \
stout/internal/windows/pwd.hpp \
+ stout/internal/windows/symlink.hpp \
+ stout/internal/windows/reparsepoint.hpp \
stout/interval.hpp \
stout/ip.hpp \
stout/json.hpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/e6db3880/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/reparsepoint.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/reparsepoint.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/reparsepoint.hpp
new file mode 100644
index 0000000..36b0068
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/reparsepoint.hpp
@@ -0,0 +1,250 @@
+// 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_INTERNAL_WINDOWS_REPARSEPOINT_HPP__
+#define __STOUT_INTERNAL_WINDOWS_REPARSEPOINT_HPP__
+
+#include <string>
+
+#include <stout/try.hpp>
+#include <stout/windows.hpp>
+
+
+namespace internal {
+namespace windows {
+
+// We pass this struct to `DeviceIoControl` to get information about a reparse
+// point (including things like whether it's a symlink). It is normally part of
+// the Device Driver Kit (DDK), specifically `nitfs.h`, but rather than taking
+// a dependency on the DDK, we choose to simply copy the struct here. This is a
+// well-worn path used by Boost FS[1], among others. See documentation
+// here[2].
+//
+// [1] http://www.boost.org/doc/libs/1_46_1/libs/filesystem/v3/src/operations.cpp
+// [2] https://msdn.microsoft.com/en-us/library/cc232007.aspx
+typedef struct _REPARSE_DATA_BUFFER
+{
+ // Describes, among other things, which type of reparse point this is (e.g.,
+ // a symlink).
+ ULONG ReparseTag;
+ // Size in bytes of common portion of the `REPARSE_DATA_BUFFER`.
+ USHORT ReparseDataLength;
+ // Unused. Ignore.
+ USHORT Reserved;
+ union
+ {
+ // Holds symlink data.
+ struct
+ {
+ // Byte offset in `PathBuffer` where the substitute name begins.
+ // Calculated as an offset from 0.
+ USHORT SubstituteNameOffset;
+ // Length in bytes of the substitute name.
+ USHORT SubstituteNameLength;
+ // Byte offset in `PathBuffer` where the print name begins. Calculated as
+ // an offset from 0.
+ USHORT PrintNameOffset;
+ // Length in bytes of the print name.
+ USHORT PrintNameLength;
+ // Indicates whether symlink is absolute or relative. If flags containing
+ // `SYMLINK_FLAG_RELATIVE`, then the substitute name is a relative
+ // symlink.
+ ULONG Flags;
+ // The first byte of the path string -- according to the documentation[1],
+ // this is followed in memory by the rest of the path string. The "path
+ // string" itself is a unicode char array containing both substitute name
+ // and print name. They can occur in any order. Use the offset and length
+ // of each in this struct to calculate where each starts and ends.
+ //
+ // [1] https://msdn.microsoft.com/en-us/library/windows/hardware/ff552012(v=vs.85).aspx
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+
+ // Unused: holds mount point data.
+ struct
+ {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct
+ {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER;
+
+#define REPARSE_MOUNTPOINT_HEADER_SIZE 8
+
+
+// Convenience struct for holding symlink data, meant purely for internal use.
+// We pass this around instead of the extremely inelegant `REPARSE_DATA_BUFFER`
+// struct, simply because this struct is easier to deal with and reason about.
+struct SymbolicLink
+{
+ std::wstring substitute_name;
+ std::wstring print_name;
+ ULONG flags;
+};
+
+
+// Checks file/folder attributes for a path to see if the reparse point
+// attribute is set; this indicates whether the path points at a reparse point,
+// rather than a "normal" file or folder.
+inline Try<bool> reparse_point_attribute_set(const std::string& absolute_path)
+{
+ const DWORD attributes = GetFileAttributes(absolute_path.c_str());
+ if (attributes == INVALID_FILE_ATTRIBUTES) {
+ return WindowsError(
+ "Failed to get attributes for file '" + absolute_path + "'");
+ }
+
+ return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
+}
+
+
+// Attempts to extract symlink data out of a `REPARSE_DATA_BUFFER` (which could
+// hold other things, e.g., mount point data).
+inline Try<SymbolicLink> build_symbolic_link(const REPARSE_DATA_BUFFER& data)
+{
+ const bool is_symLink = (data.ReparseTag & IO_REPARSE_TAG_SYMLINK) != 0;
+ if (!is_symLink) {
+ return Error("Data buffer is not a symlink");
+ }
+
+ // NOTE: This buffer is not null terminated.
+ const WCHAR* substitute_name =
+ data.SymbolicLinkReparseBuffer.PathBuffer +
+ data.SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR);
+ const size_t substitute_name_length =
+ data.SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR);
+
+ // NOTE: This buffer is not null terminated.
+ const WCHAR* print_name =
+ data.SymbolicLinkReparseBuffer.PathBuffer +
+ data.SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR);
+ const size_t print_name_length =
+ data.SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR);
+
+ return SymbolicLink{
+ std::wstring(substitute_name, substitute_name_length),
+ std::wstring(print_name, print_name_length),
+ data.SymbolicLinkReparseBuffer.Flags};
+}
+
+
+// Attempts to get a file or folder handle for an absolute path, and does not
+// follow symlinks. That is, if the path points at a symlink, the handle will
+// refer to the symlink rather than the file or folder the symlink points at.
+inline Try<SharedHandle> get_handle_no_follow(const std::string& absolute_path)
+{
+ struct _stat s;
+ bool resolved_path_is_directory = false;
+ if (::_stat(absolute_path.c_str(), &s) >= 0) {
+ resolved_path_is_directory = S_ISDIR(s.st_mode);
+ }
+
+ // NOTE: The `CreateFile` documentation[1] tells us which flags we need to
+ // invoke to open a handle that will point at the symlink instead of the
+ // folder or file it points at. The short answer is that you need to be sure
+ // to pass in `OPEN_EXISTING` and `FILE_FLAG_OPEN_REPARSE_POINT` to get a
+ // handle for the symlink and not the file the symlink points to.
+ //
+ // Note also that `CreateFile` will appropriately generate a handle for
+ // either a folder or a file (they are different!), as long as you
+ // appropriately set a magic flag, `FILE_FLAG_BACKUP_SEMANTICS`. It is not
+ // clear why, or what this flag means, the documentation[1] only says it's
+ // necessary.
+ //
+ // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
+ const DWORD access_flags = resolved_path_is_directory
+ ? (FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)
+ : FILE_FLAG_OPEN_REPARSE_POINT;
+
+ const HANDLE handle = CreateFile(
+ absolute_path.c_str(),
+ 0, // Ignored.
+ 0, // Ignored.
+ NULL, // Ignored.
+ OPEN_EXISTING, // Open existing symlink.
+ access_flags, // Open symlink, not the file it points to.
+ NULL); // Ignored.
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ return WindowsError(
+ "Could not open handle for symlink at path '" + absolute_path + "'");
+ }
+
+ return SharedHandle(handle, CloseHandle);
+}
+
+
+// Attempts to get the symlink data for a file or folder handle.
+inline Try<SymbolicLink> get_symbolic_link_data(const HANDLE handle)
+{
+ // To get the symlink data, we call `DeviceIoControl`. This function is part
+ // of the Device Driver Kit (DDK), and buried away in a corner of the
+ // DDK documentation[1] is an incomplete explanation of how to twist API to
+ // get it to emit information about reparse points (and, thus, symlinks,
+ // since symlinks are implemented with reparse points). This technique is a
+ // hack, but it is used pretty much everywhere, including the Boost FS code,
+ // though it's worth noting that they seem to use it incorrectly[2].
+ //
+ // Summarized, the documentation tells us that we need to pass in the magic
+ // flag `FSCTL_GET_REPARSE_POINT` to get the function to populate a
+ // `REPARSE_DATA_BUFFER` struct with data about a reparse point. What it
+ // doesn't tell you is that this struct is in a header in the DDK, so in
+ // order to get information about the reparse point, you must either take a
+ // dependency on the DDK, or copy the struct from the header into your code.
+ // We take a cue from Boost FS, and copy the struct into this header (see
+ // above).
+ //
+ // Finally, for context, it may be worth looking at the (sparse)
+ // documentation for `DeviceIoControl` itself.
+ //
+ // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa364571(v=vs.85).aspx
+ // [2] https://svn.boost.org/trac/boost/ticket/4663
+ // [3] https://msdn.microsoft.com/en-us/library/windows/desktop/aa363216(v=vs.85).aspx
+
+ const size_t reparse_point_data_size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
+ BYTE buffer[reparse_point_data_size];
+ REPARSE_DATA_BUFFER* reparse_point_data =
+ reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
+
+ DWORD ignored = 0;
+
+ // The semantics of this function are: get the reparse data associated with
+ // the `handle` of some open directory or file, and that data in
+ // `reparse_point_data`.
+ const BOOL reparse_data_obtained = DeviceIoControl(
+ handle, // handle to file or directory
+ FSCTL_GET_REPARSE_POINT, // Gets reparse point data for file/folder handle.
+ NULL, // Ignored.
+ 0, // Ignored.
+ reparse_point_data,
+ reparse_point_data_size,
+ &ignored, // Ignored.
+ NULL); // Ignored.
+
+ if (!reparse_data_obtained) {
+ return WindowsError("Failed to obtain reparse point data for handle");
+ }
+
+ return build_symbolic_link(*reparse_point_data);
+}
+
+} // namespace windows {
+} // namespace internal {
+
+#endif // __STOUT_INTERNAL_WINDOWS_REPARSEPOINT_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/e6db3880/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/symlink.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/symlink.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/symlink.hpp
new file mode 100644
index 0000000..5dc022b
--- /dev/null
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/internal/windows/symlink.hpp
@@ -0,0 +1,87 @@
+// 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_INTERNAL_WINDOWS_SYMLINK_HPP__
+#define __STOUT_INTERNAL_WINDOWS_SYMLINK_HPP__
+
+#include <string>
+
+#include <stout/try.hpp>
+#include <stout/windows.hpp>
+
+#include <stout/internal/windows/reparsepoint.hpp>
+
+#include <stout/os/realpath.hpp>
+
+
+namespace internal {
+namespace windows {
+
+// Gets symlink data for a given path, if it exists.
+//
+// This turns out to be a very complicated task on Windows. The gist of it is
+// that we know that symlinks on Windows are implemented with the Reparse Point
+// API, and so the process is a matter of:
+//
+// 1. Checking whether the attributes for the file/folder specified by the
+// path have the reparse point bit set; all symlinks are implemented with
+// reparse points, so this bit should be on all symlinks.
+// 2. Opening a file/folder handle for that path, instructing it specifically
+// to open a handle for the symlink (if the path points at a symlink) and
+// *not* the file the symlink points at (as is the default). Note that
+// file and folder handles are different, so we have a function that
+// chooses appropriately.
+// 3. Using `DeviceIoControl` to obtain information about the handle for this
+// reparse point, which we can then query to figure out if it's a reparse
+// point that is owned by the symlink filesystem filter driver.
+// 4. If it is, then we report that this path does point at a symlink.
+//
+// NOTE: it may be helpful to consult the documentation for each of these
+// functions, as they give you sources that justify the arguments to the
+// obscure APIs we call to get this all working.
+inline Try<SymbolicLink> query_symbolic_link_data(const std::string& path)
+{
+ // Convert to absolute path because Windows APIs expect it.
+ const Result<std::string> absolute_path = os::realpath(path);
+ if (!absolute_path.isSome()) {
+ return Error(absolute_path.error());
+ }
+
+ // Windows has no built-in way to tell whether a path points at a symbolic
+ // link; but, we know that symbolic links are implemented with reparse
+ // points, so we begin by checking that.
+ Try<bool> is_reparse_point =
+ reparse_point_attribute_set(absolute_path.get());
+
+ if (is_reparse_point.isError()) {
+ return Error(is_reparse_point.error());
+ } else if (!is_reparse_point.get()) {
+ return Error(
+ "Reparse point attribute is not set for path '" + absolute_path.get() +
+ "', and therefore it is not a symbolic link");
+ }
+
+ const Try<SharedHandle> symlink_handle =
+ get_handle_no_follow(absolute_path.get());
+
+ if (symlink_handle.isError()) {
+ return Error(symlink_handle.error());
+ }
+
+ // Finally, retrieve symlink data for the handle, if any.
+ return get_symbolic_link_data(symlink_handle.get().get_handle());
+}
+
+} // namespace windows {
+} // namespace internal {
+
+#endif // __STOUT_INTERNAL_WINDOWS_SYMLINK_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/e6db3880/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/stat.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/stat.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/stat.hpp
index ffe0748..32fa426 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/stat.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/os/posix/stat.hpp
@@ -34,6 +34,7 @@ inline bool isdir(const std::string& path)
if (::stat(path.c_str(), &s) < 0) {
return false;
}
+
return S_ISDIR(s.st_mode);
}
@@ -45,6 +46,7 @@ inline bool isfile(const std::string& path)
if (::stat(path.c_str(), &s) < 0) {
return false;
}
+
return S_ISREG(s.st_mode);
}
@@ -56,6 +58,7 @@ inline bool islink(const std::string& path)
if (::lstat(path.c_str(), &s) < 0) {
return false;
}
+
return S_ISLNK(s.st_mode);
}
@@ -83,21 +86,22 @@ inline Try<Bytes> size(
case DO_NOT_FOLLOW_SYMLINK: {
if (::lstat(path.c_str(), &s) < 0) {
return ErrnoError("Error invoking lstat for '" + path + "'");
+ } else {
+ return Bytes(s.st_size);
}
break;
}
case FOLLOW_SYMLINK: {
if (::stat(path.c_str(), &s) < 0) {
return ErrnoError("Error invoking stat for '" + path + "'");
+ } else {
+ return Bytes(s.st_size);
}
break;
}
- default: {
- UNREACHABLE();
- }
}
- return Bytes(s.st_size);
+ UNREACHABLE();
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/e6db3880/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/stat.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/stat.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/stat.hpp
index 5b38b9a..a2a5d0b 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/stat.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/os/windows/stat.hpp
@@ -15,29 +15,52 @@
#include <string>
+#include <stout/bytes.hpp>
#include <stout/try.hpp>
+#include <stout/unreachable.hpp>
+#include <stout/windows.hpp>
+#include <stout/internal/windows/reparsepoint.hpp>
+#include <stout/internal/windows/symlink.hpp>
+
+#ifdef _USE_32BIT_TIME_T
+#error "Implementation of `os::stat::mtime` assumes 64-bit `time_t`."
+#endif // _USE_32BIT_TIME_T
-namespace os {
+namespace os {
namespace stat {
inline bool isdir(const std::string& path)
{
- UNIMPLEMENTED;
+ struct _stat s;
+
+ if (::_stat(path.c_str(), &s) < 0) {
+ return false;
+ }
+
+ return S_ISDIR(s.st_mode);
}
inline bool isfile(const std::string& path)
{
- UNIMPLEMENTED;
-}
+ struct _stat s;
+
+ if (::_stat(path.c_str(), &s) < 0) {
+ return false;
+ }
+ return S_ISREG(s.st_mode);
+}
inline bool islink(const std::string& path)
{
- UNIMPLEMENTED;
+ Try<internal::windows::SymbolicLink> symlink =
+ internal::windows::query_symbolic_link_data(path);
+
+ return symlink.isSome();
}
@@ -58,35 +81,91 @@ inline Try<Bytes> size(
const std::string& path,
const FollowSymlink follow = FOLLOW_SYMLINK)
{
- UNIMPLEMENTED;
+ switch (follow) {
+ case DO_NOT_FOLLOW_SYMLINK: {
+ Try<internal::windows::SymbolicLink> symlink =
+ internal::windows::query_symbolic_link_data(path);
+
+ if (symlink.isError()) {
+ return Error(symlink.error());
+ } else {
+ return Bytes(symlink.get().substitute_name.length());
+ }
+ break;
+ }
+ case FOLLOW_SYMLINK: {
+ struct _stat s;
+
+ if (::_stat(path.c_str(), &s) < 0) {
+ return ErrnoError("Error invoking stat for '" + path + "'");
+ } else {
+ return Bytes(s.st_size);
+ }
+ break;
+ }
+ }
+
+ UNREACHABLE();
}
inline Try<long> mtime(const std::string& path)
{
- UNIMPLEMENTED;
+ Try<internal::windows::SymbolicLink> symlink =
+ internal::windows::query_symbolic_link_data(path);
+
+ if (symlink.isSome()) {
+ return Error(
+ "Requested mtime for '" + path +
+ "', but symbolic links don't have an mtime on Windows");
+ }
+
+ struct _stat s;
+
+ if (::_stat(path.c_str(), &s) < 0) {
+ return ErrnoError("Error invoking stat for '" + path + "'");
+ }
+
+ return s.st_mtime;
}
inline Try<mode_t> mode(const std::string& path)
{
- UNIMPLEMENTED;
+ struct _stat s;
+
+ if (::_stat(path.c_str(), &s) < 0) {
+ return ErrnoError("Error invoking stat for '" + path + "'");
+ }
+
+ return s.st_mode;
}
-inline Try<dev_t> rdev(const std::string& path)
+inline Try<dev_t> dev(const std::string& path)
{
- UNIMPLEMENTED;
+ struct _stat s;
+
+ if (::_stat(path.c_str(), &s) < 0) {
+ return ErrnoError("Error invoking stat for '" + path + "'");
+ }
+
+ return s.st_dev;
}
inline Try<ino_t> inode(const std::string& path)
{
- UNIMPLEMENTED;
+ struct _stat s;
+
+ if (::_stat(path.c_str(), &s) < 0) {
+ return ErrnoError("Error invoking stat for '" + path + "'");
+ }
+
+ return s.st_ino;
}
} // namespace stat {
-
} // namespace os {
#endif // __STOUT_OS_WINDOWS_STAT_HPP__
http://git-wip-us.apache.org/repos/asf/mesos/blob/e6db3880/3rdparty/libprocess/3rdparty/stout/include/stout/windows.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/windows.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/windows.hpp
index 27edf1b..061bb4a 100644
--- a/3rdparty/libprocess/3rdparty/stout/include/stout/windows.hpp
+++ b/3rdparty/libprocess/3rdparty/stout/include/stout/windows.hpp
@@ -27,6 +27,37 @@
#include <Winsock2.h>
#include <Windows.h>
+#include <memory>
+
+
+#ifdef _UNICODE
+// Much of the core Windows API is available both in `string` and `wstring`
+// varieties. To avoid polluting the namespace with two versions of every
+// function, a common pattern in the Windows headers is to offer a single macro
+// that expands to the `string` or `wstring` version, depending on whether the
+// `_UNICODE` preprocessor symbol is set. For example, `GetMessage` will expand
+// to either `GetMessageA` (the `string` version) or `GetMessageW` (the
+// `wstring` version) depending on whether this symbol is defined.
+//
+// The downside of this is that it makes POSIX interop really hard. Hence, we
+// refuse to compile if such a symbol is passed in during compilation.
+#error "Mesos doesn't currently support the `_UNICODE` Windows header constant"
+#endif // _UNICODE
+
+// An RAII `HANDLE`.
+class SharedHandle : public std::shared_ptr<void>
+{
+ static_assert(std::is_same<HANDLE, void*>::value,
+ "Expected `HANDLE` to be of type `void*`.");
+
+public:
+ template <typename Deleter>
+ SharedHandle(HANDLE handle, Deleter deleter)
+ : std::shared_ptr<void>(handle, deleter) {}
+
+ HANDLE get_handle() const { return this->get(); }
+};
+
// Definitions and constants used for Windows compat.
//
@@ -137,14 +168,44 @@ typedef SSIZE_T ssize_t;
// have to change any socket code.
constexpr int SHUT_RD = SD_RECEIVE;
-// Macros that test whether a `stat` struct represents a directory or a file.
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) // Directory.
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) // File.
-#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) // Character device.
-#define S_ISFIFO(mode) (((mode) & S_IFMT) == _S_IFIFO) // Pipe.
-#define S_ISBLK(mode) 0 // Block special device.
-#define S_ISSOCK(mode) 0 // Socket.
-#define S_ISLNK(mode) 0 // Symbolic link.
+// The following functions are usually macros on POSIX; we provide them here as
+// functions to avoid having global macros lying around. Note that these
+// operate on the `_stat` struct (a Windows version of the standard POSIX
+// `stat` struct), of which the `st_mode` field is known to be an `int`.
+inline bool S_ISDIR(const int mode)
+{
+ return (mode & S_IFMT) == S_IFDIR; // Directory.
+}
+
+inline bool S_ISREG(const int mode)
+{
+ return (mode & S_IFMT) == S_IFREG; // File.
+}
+
+inline bool S_ISCHR(const int mode)
+{
+ return (mode & S_IFMT) == S_IFCHR; // Character device.
+}
+
+inline bool S_ISFIFO(const int mode)
+{
+ return (mode & S_IFMT) == _S_IFIFO; // Pipe.
+}
+
+inline bool S_ISBLK(const int mode)
+{
+ return false; // Block special device.
+}
+
+inline bool S_ISSOCK(const int mode)
+{
+ return false; // Socket.
+}
+
+inline bool S_ISLNK(const int mode)
+{
+ return false; // Symbolic link.
+}
// Permissions API. (cf. MESOS-3176 to track ongoing permissions work.)
//