Added the `FollowSymlink` argument for `os::stat` on POSIX. Review: https://reviews.apache.org/r/56027/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/39b34d6c Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/39b34d6c Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/39b34d6c Branch: refs/heads/master Commit: 39b34d6cb7799873828434a2e5d500d34b432e97 Parents: 00d4fa0 Author: James Peach <[email protected]> Authored: Wed Mar 22 17:52:19 2017 -0700 Committer: Michael Park <[email protected]> Committed: Thu Mar 23 09:42:18 2017 -0700 ---------------------------------------------------------------------- 3rdparty/stout/include/stout/os/posix/stat.hpp | 174 +++++++++----------- 3rdparty/stout/include/stout/os/stat.hpp | 17 ++ 2 files changed, 97 insertions(+), 94 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/39b34d6c/3rdparty/stout/include/stout/os/posix/stat.hpp ---------------------------------------------------------------------- diff --git a/3rdparty/stout/include/stout/os/posix/stat.hpp b/3rdparty/stout/include/stout/os/posix/stat.hpp index e7440a4..2762c41 100644 --- a/3rdparty/stout/include/stout/os/posix/stat.hpp +++ b/3rdparty/stout/include/stout/os/posix/stat.hpp @@ -27,49 +27,58 @@ namespace os { namespace stat { -inline bool isdir(const std::string& path) -{ - struct stat s; - - if (::stat(path.c_str(), &s) < 0) { - return false; - } +namespace internal { - return S_ISDIR(s.st_mode); -} - - -inline bool isfile(const std::string& path) +inline Try<struct ::stat> stat( + const std::string& path, + const FollowSymlink follow) { - struct stat s; + struct ::stat s; - if (::stat(path.c_str(), &s) < 0) { - return false; + switch (follow) { + case DO_NOT_FOLLOW_SYMLINK: + if (::lstat(path.c_str(), &s) < 0) { + return ErrnoError("Failed to lstat '" + path + "'"); + } + return s; + case FOLLOW_SYMLINK: + if (::stat(path.c_str(), &s) < 0) { + return ErrnoError("Failed to stat '" + path + "'"); + } + return s; } - return S_ISREG(s.st_mode); + UNREACHABLE(); } +} // namespace internal { inline bool islink(const std::string& path) { - struct stat s; + // By definition, you don't followsymlinks when trying + // to find whether a path is a link. If you followed it, + // it wouldn't ever be a link. + Try<struct ::stat> s = internal::stat(path, DO_NOT_FOLLOW_SYMLINK); + return s.isSome() && S_ISLNK(s->st_mode); +} - if (::lstat(path.c_str(), &s) < 0) { - return false; - } - return S_ISLNK(s.st_mode); +inline bool isdir( + const std::string& path, + const FollowSymlink follow = FOLLOW_SYMLINK) +{ + Try<struct ::stat> s = internal::stat(path, follow); + return s.isSome() && S_ISDIR(s->st_mode); } -// Describes the different semantics supported for the implementation -// of `size` defined below. -enum FollowSymlink +inline bool isfile( + const std::string& path, + const FollowSymlink follow = FOLLOW_SYMLINK) { - DO_NOT_FOLLOW_SYMLINK, - FOLLOW_SYMLINK -}; + Try<struct ::stat> s = internal::stat(path, follow); + return s.isSome() && S_ISREG(s->st_mode); +} // Returns the size in Bytes of a given file system entry. When @@ -80,92 +89,81 @@ inline Try<Bytes> size( const std::string& path, const FollowSymlink follow = FOLLOW_SYMLINK) { - struct stat s; - - switch (follow) { - 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; - } + Try<struct ::stat> s = internal::stat(path, follow); + if (s.isError()) { + return Error(s.error()); } - UNREACHABLE(); + return Bytes(s->st_size); } -inline Try<long> mtime(const std::string& path) +inline Try<long> mtime( + const std::string& path, + const FollowSymlink follow = FOLLOW_SYMLINK) { - struct stat s; - - if (::lstat(path.c_str(), &s) < 0) { - return ErrnoError("Error invoking stat for '" + path + "'"); + Try<struct ::stat> s = internal::stat(path, follow); + if (s.isError()) { + return Error(s.error()); } - return s.st_mtime; + return s->st_mtime; } -inline Try<mode_t> mode(const std::string& path) +inline Try<mode_t> mode( + const std::string& path, + const FollowSymlink follow = FOLLOW_SYMLINK) { - struct stat s; - - if (::stat(path.c_str(), &s) < 0) { - return ErrnoError("Error invoking stat for '" + path + "'"); + Try<struct ::stat> s = internal::stat(path, follow); + if (s.isError()) { + return Error(s.error()); } - return s.st_mode; + return s->st_mode; } -inline Try<dev_t> dev(const std::string& path) +inline Try<dev_t> dev( + const std::string& path, + const FollowSymlink follow = FOLLOW_SYMLINK) { - struct stat s; - - if (::stat(path.c_str(), &s) < 0) { - return ErrnoError("Error invoking stat for '" + path + "'"); + Try<struct ::stat> s = internal::stat(path, follow); + if (s.isError()) { + return Error(s.error()); } - return s.st_dev; + return s->st_dev; } -inline Try<dev_t> rdev(const std::string& path) +inline Try<dev_t> rdev( + const std::string& path, + const FollowSymlink follow = FOLLOW_SYMLINK) { - struct stat s; - - if (::stat(path.c_str(), &s) < 0) { - return ErrnoError("Error invoking stat for '" + path + "'"); + Try<struct ::stat> s = internal::stat(path, follow); + if (s.isError()) { + return Error(s.error()); } - if (!S_ISCHR(s.st_mode) && !S_ISBLK(s.st_mode)) { + if (!S_ISCHR(s->st_mode) && !S_ISBLK(s->st_mode)) { return Error("Not a special file: " + path); } - return s.st_rdev; + return s->st_rdev; } -inline Try<ino_t> inode(const std::string& path) +inline Try<ino_t> inode( + const std::string& path, + const FollowSymlink follow = FOLLOW_SYMLINK) { - struct stat s; - - if (::stat(path.c_str(), &s) < 0) { - return ErrnoError("Error invoking stat for '" + path + "'"); + Try<struct ::stat> s = internal::stat(path, follow); + if (s.isError()) { + return Error(s.error()); } - return s.st_ino; + return s->st_ino; } @@ -173,24 +171,12 @@ inline Try<uid_t> uid( const std::string& path, const FollowSymlink follow = FOLLOW_SYMLINK) { - struct stat s; - - switch (follow) { - case DO_NOT_FOLLOW_SYMLINK: - if (::lstat(path.c_str(), &s) == 0) { - return s.st_uid; - } - break; - case FOLLOW_SYMLINK: - if (::stat(path.c_str(), &s) == 0) { - return s.st_uid; - } - break; - default: - UNREACHABLE(); + Try<struct ::stat> s = internal::stat(path, follow); + if (s.isError()) { + return Error(s.error()); } - return ErrnoError("Error invoking stat for '" + path + "'"); + return s->st_uid; } } // namespace stat { http://git-wip-us.apache.org/repos/asf/mesos/blob/39b34d6c/3rdparty/stout/include/stout/os/stat.hpp ---------------------------------------------------------------------- diff --git a/3rdparty/stout/include/stout/os/stat.hpp b/3rdparty/stout/include/stout/os/stat.hpp index 5c4fd4e..d002c98 100644 --- a/3rdparty/stout/include/stout/os/stat.hpp +++ b/3rdparty/stout/include/stout/os/stat.hpp @@ -13,6 +13,23 @@ #ifndef __STOUT_OS_STAT_HPP__ #define __STOUT_OS_STAT_HPP__ +namespace os { + +namespace stat { + +// Specify whether symlink path arguments should be followed or +// not. APIs in the os::stat family that take a FollowSymlink +// argument all provide FOLLOW_SYMLINK as the default value, +// so they will follow symlinks unless otherwise specified. +enum FollowSymlink +{ + DO_NOT_FOLLOW_SYMLINK, + FOLLOW_SYMLINK +}; + +} // namespace stat { + +} // namespace os { // For readability, we minimize the number of #ifdef blocks in the code by // splitting platform specific system calls into separate directories.
