blob: 2e1537c2c170e0afefaa4257ab19566df4234276 [file] [log] [blame]
// 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_HPP__
#define __STOUT_OS_HPP__
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <glog/logging.h>
#include <sys/types.h>
#include <list>
#include <queue>
#include <set>
#include <string>
#include <stout/bytes.hpp>
#include <stout/duration.hpp>
#include <stout/error.hpp>
#include <stout/exit.hpp>
#include <stout/foreach.hpp>
#include <stout/none.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/path.hpp>
#include <stout/result.hpp>
#include <stout/strings.hpp>
#include <stout/try.hpp>
#include <stout/version.hpp>
#include <stout/os/access.hpp>
#include <stout/os/bootid.hpp>
#include <stout/os/chdir.hpp>
#include <stout/os/chroot.hpp>
#include <stout/os/dup.hpp>
#include <stout/os/exec.hpp>
#include <stout/os/exists.hpp>
#include <stout/os/fcntl.hpp>
#include <stout/os/getenv.hpp>
#include <stout/os/int_fd.hpp>
#include <stout/os/kill.hpp>
#include <stout/os/ls.hpp>
#include <stout/os/lseek.hpp>
#include <stout/os/lsof.hpp>
#include <stout/os/mkdir.hpp>
#include <stout/os/mkdtemp.hpp>
#include <stout/os/mktemp.hpp>
#include <stout/os/os.hpp>
#include <stout/os/pagesize.hpp>
#include <stout/os/pipe.hpp>
#include <stout/os/process.hpp>
#include <stout/os/rename.hpp>
#include <stout/os/rm.hpp>
#include <stout/os/rmdir.hpp>
#include <stout/os/shell.hpp>
#include <stout/os/stat.hpp>
#include <stout/os/su.hpp>
#include <stout/os/temp.hpp>
#include <stout/os/touch.hpp>
#include <stout/os/utime.hpp>
#include <stout/os/wait.hpp>
#include <stout/os/xattr.hpp>
#include <stout/os/raw/argv.hpp>
#include <stout/os/raw/environment.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/windows/os.hpp>
#else
#include <stout/posix/os.hpp>
#endif // __WINDOWS__
namespace os {
namespace libraries {
namespace Library {
// Library prefix; e.g., the `lib` in `libprocess`. NOTE: there is no prefix
// on Windows; `libprocess.a` would be `process.lib`.
constexpr const char* prefix =
#ifdef __WINDOWS__
"";
#else
"lib";
#endif // __WINDOWS__
// The suffix for a shared library; e.g., `.so` on Linux.
constexpr const char* extension =
#ifdef __APPLE__
".dylib";
#elif defined(__WINDOWS__)
".dll";
#else
".so";
#endif // __APPLE__
// The name of the environment variable that contains paths on which the
// linker should search for libraries. NOTE: Windows does not have an
// environment variable that controls the paths the linker searches through.
constexpr const char* ldPathEnvironmentVariable =
#ifdef __APPLE__
"DYLD_LIBRARY_PATH";
#elif defined(__WINDOWS__)
"";
#else
"LD_LIBRARY_PATH";
#endif
} // namespace Library {
// Returns the full library name by adding prefix and extension to
// library name.
inline std::string expandName(const std::string& libraryName)
{
return Library::prefix + libraryName + Library::extension;
}
// Returns the current value of LD_LIBRARY_PATH environment variable.
inline std::string paths()
{
const Option<std::string> path = getenv(Library::ldPathEnvironmentVariable);
return path.isSome() ? path.get() : std::string();
}
// Updates the value of LD_LIBRARY_PATH environment variable.
// Note that setPaths has an effect only for child processes
// launched after calling it.
inline void setPaths(const std::string& newPaths)
{
os::setenv(Library::ldPathEnvironmentVariable, newPaths);
}
// Append newPath to the current value of LD_LIBRARY_PATH environment
// variable.
inline void appendPaths(const std::string& newPaths)
{
if (paths().empty()) {
setPaths(newPaths);
} else {
setPaths(paths() + ":" + newPaths);
}
}
} // namespace libraries {
#ifdef __WINDOWS__
inline Try<std::string> sysname() = delete;
#else
// Return the operating system name (e.g. Linux).
inline Try<std::string> sysname()
{
Try<UTSInfo> info = uname();
if (info.isError()) {
return Error(info.error());
}
return info->sysname;
}
#endif // __WINDOWS__
inline Try<std::list<Process>> processes()
{
const Try<std::set<pid_t>> pids = os::pids();
if (pids.isError()) {
return Error(pids.error());
}
std::list<Process> result;
foreach (pid_t pid, pids.get()) {
const Result<Process> process = os::process(pid);
// Ignore any processes that disappear between enumeration and now.
if (process.isSome()) {
result.push_back(process.get());
}
}
return result;
}
inline Option<Process> process(
pid_t pid,
const std::list<Process>& processes)
{
foreach (const Process& process, processes) {
if (process.pid == pid) {
return process;
}
}
return None();
}
inline std::set<pid_t> children(
pid_t pid,
const std::list<Process>& processes,
bool recursive = true)
{
// Perform a breadth first search for descendants.
std::set<pid_t> descendants;
std::queue<pid_t> parents;
parents.push(pid);
do {
pid_t parent = parents.front();
parents.pop();
// Search for children of parent.
foreach (const Process& process, processes) {
if (process.parent == parent) {
// Have we seen this child yet?
if (descendants.insert(process.pid).second) {
parents.push(process.pid);
}
}
}
} while (recursive && !parents.empty());
return descendants;
}
inline Try<std::set<pid_t>> children(pid_t pid, bool recursive = true)
{
const Try<std::list<Process>> processes = os::processes();
if (processes.isError()) {
return Error(processes.error());
}
return children(pid, processes.get(), recursive);
}
} // namespace os {
#endif // __STOUT_OS_HPP__