blob: ba800e0715df8fe019a9dfcf5e481bd3a4f35768 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// 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.
#pragma once
#include "android/base/Compiler.h"
#include "android/base/EnumFlags.h"
#include "android/base/StringView.h"
#include <string>
#include <vector>
#include <limits.h>
#include <stdint.h>
#include <time.h>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#undef ERROR // necessary to compile LOG(ERROR) statements
#else // !_WIN32
#include <unistd.h>
#endif // !_WIN32
namespace android {
namespace base {
// Type of the current operating system
enum class OsType {
Windows,
Mac,
Linux
};
std::string toString(OsType osType);
enum class RunOptions {
// Can't use None here: X.h defines None to 0L.
Empty = 0,
// some pseudo flags to just state the default behavior
DontWait = 0,
HideAllOutput = 0,
// Wait for the launched shell command to finish, and return true only if
// the command was successful.
WaitForCompletion = 1,
// Attempt to terminate the launched process if it doesn't finish in time.
// Note that terminating a mid-flight process can leave the whole system in
// a weird state.
// Only make sense with |WaitForCompletion|.
TerminateOnTimeout = 2,
// These flags and RunOptions::HideAllOutput are mutually exclusive.
ShowOutput = 4,
DumpOutputToFile = 8,
Default = 0, // don't wait, hide all output
};
// Interface class to the underlying operating system.
class System {
public:
typedef int64_t Duration;
typedef uint64_t WallDuration;
using FileSize = uint64_t;
// Information about user, system and wall clock times for some process,
// in milliseconds
struct Times {
Duration userMs;
Duration systemMs;
WallDuration wallClockMs;
};
enum { RunFailed = -1 };
using RunOptions = android::base::RunOptions;
#ifdef _WIN32
using Pid = DWORD;
using ProcessExitCode = DWORD;
#else
using Pid = pid_t;
using ProcessExitCode = int;
#endif
public:
// Call this function to get the instance
static System* get();
// Default constructor doesn't do anything.
System() = default;
// Default destructor is empty but virtual.
virtual ~System() = default;
// Return the host bitness as an integer, either 32 or 64.
// Note that this is different from the program's bitness. I.e. if
// a 32-bit program runs under a 64-bit host, getProgramBitness()
// shall return 32, but getHostBitness() shall return 64.
virtual int getHostBitness() const = 0;
// Return the current OS type
virtual OsType getOsType() const = 0;
// Check if we're running under Wine;
// returns false for non-Windows builds
virtual bool isRunningUnderWine() const = 0;
// Get the current process ID
virtual Pid getCurrentProcessId() const = 0;
// Return the program bitness as an integer, either 32 or 64.
#ifdef __x86_64__
static const int kProgramBitness = 64;
#else
static const int kProgramBitness = 32;
#endif
#ifdef _WIN32
static const char kDirSeparator = '\\';
#else
static const char kDirSeparator = '/';
#endif
// The character used to separator directories in path-related
// environment variables.
#ifdef _WIN32
static const char kPathSeparator = ';';
#else
static const char kPathSeparator = ':';
#endif
// Environment variable name corresponding to the library search
// list for shared libraries.
static const char* kLibrarySearchListEnvVarName;
// Return the name of the sub-directory containing libraries
// for the current platform, i.e. "lib" or "lib64" depending
// on the value of kProgramBitness.
static const char* kLibSubDir;
// Return the name of the sub-directory containing executables
// for the current platform, i.e. "bin" or "bin64" depending
// on the value of kProgramBitness.
static const char* kBinSubDir;
// Name of the 32-bit binaries subdirectory
static const char* kBin32SubDir;
// Return program's bitness, either 32 or 64.
static int getProgramBitness() { return kProgramBitness; }
// /////////////////////////////////////////////////////////////////////////
// Environment variables.
// /////////////////////////////////////////////////////////////////////////
// Retrieve the value of a given environment variable.
// Equivalent to getenv() but returns a std::string instance.
// If the variable is not defined, return an empty string.
// NOTE: On Windows, this uses _wgetenv() and returns the corresponding
// UTF-8 text string.
virtual std::string envGet(StringView varname) const = 0;
// Set the value of a given environment variable.
// If |varvalue| is NULL or empty, this unsets the variable.
// Equivalent to setenv().
virtual void envSet(StringView varname, StringView varvalue) = 0;
// Returns true if environment variable |varname| is set and non-empty.
virtual bool envTest(StringView varname) const = 0;
// Returns all environment variables from the current process in a
// "name=value" form
virtual std::vector<std::string> envGetAll() const = 0;
// Prepend a new directory to the system's library search path. This
// only alters an environment variable like PATH or LD_LIBRARY_PATH,
// and thus typically takes effect only after spawning/executing a new
// process.
static void addLibrarySearchDir(StringView dirPath);
// /////////////////////////////////////////////////////////////////////////
// Path functions that interact with the file system.
// Pure path manipulation functions are in android::base::PathUtils.
// /////////////////////////////////////////////////////////////////////////
// Return true iff |path| exists on the file system.
virtual bool pathExists(StringView path) const = 0;
// Return true iff |path| exists and is a regular file on the file system.
virtual bool pathIsFile(StringView path) const = 0;
// Return true iff |path| exists and is a directory on the file system.
virtual bool pathIsDir(StringView path) const = 0;
// Return true iff |path| exists and can be read by the current user.
virtual bool pathCanRead(StringView path) const = 0;
// Return true iff |path| exists and can be written to by the current
// user.
virtual bool pathCanWrite(StringView path) const = 0;
// Return true iff |path| exists and can be executed to by the current
// user.
virtual bool pathCanExec(StringView path) const = 0;
// Function for deleting files. Return true iff
// (|path| is a file and we have successfully deleted it)
virtual bool deleteFile(StringView path) const = 0;
// Get the size of file at |path|.
// Fails if path is not a file or not readable, and in case of other errors.
virtual bool pathFileSize(StringView path, FileSize* outFileSize) const = 0;
// Scan directory |dirPath| for entries, and return them as a sorted
// vector or entries. If |fullPath| is true, then each item of the
// result vector contains a full path.
virtual std::vector<std::string> scanDirEntries(
StringView dirPath,
bool fullPath = false) const = 0;
// Find a bundled executable named |programName|, it must appear in the
// kBinSubDir of getLauncherDirectory(). The name should not include the
// executable extension (.exe) on Windows.
// Return an empty string if the file doesn't exist.
static std::string findBundledExecutable(StringView programName);
// Return the path of the current program's directory.
virtual const std::string& getProgramDirectory() const = 0;
// Return the path of the emulator launcher's directory.
virtual const std::string& getLauncherDirectory() const = 0;
// Return the path to user's home directory (as defined in the
// underlying platform) or an empty string if it can't be found
virtual const std::string& getHomeDirectory() const = 0;
// Return the path to user's App Data directory (only applies
// in Microsoft Windows) or an empty string if it can't be found
virtual const std::string& getAppDataDirectory() const = 0;
// Return the current directory path. Because this can change at
// runtime, this returns a new std::string instance, not a const-reference
// to a constant one held by the object. Return an empty string if there is
// a problem with the system when getting the current directory.
virtual std::string getCurrentDirectory() const = 0;
// Return the path of a temporary directory appropriate for the system.
virtual std::string getTempDir() const = 0;
// /////////////////////////////////////////////////////////////////////////
// Time related functions.
// /////////////////////////////////////////////////////////////////////////
// Checks the system to see if it is running under a remoting session
// like Nomachine's NX, Chrome Remote Desktop or Windows Terminal Services.
// On success, return true and sets |*sessionType| to the detected
// session type. Otherwise, just return false.
virtual bool isRemoteSession(std::string* sessionType) const = 0;
// Returns Times structure for the current process
virtual Times getProcessTimes() const = 0;
// Returns the current Unix timestamp
virtual time_t getUnixTime() const = 0;
// Returns the current Unix timestamp with microsecond resolution
virtual Duration getUnixTimeUs() const = 0;
// Returns the OS-specific high resolution timestamp.
virtual WallDuration getHighResTimeUs() const = 0;
// Sleep for |n| milliseconds
virtual void sleepMs(unsigned n) const = 0;
// Yield the remaining part of current thread's CPU time slice to another
// thread that's ready to run.
virtual void yield() const = 0;
// /////////////////////////////////////////////////////////////////////////
// Execute commands.
// /////////////////////////////////////////////////////////////////////////
// Run a shell command.
// Args:
// commandLine: Set of command to run + its arguments
// options: options to controls shell behaviour in various ways.
// timeoutMs: If |options| includes WaitForCompletion, this argument
// specifies the maximum time to wait before aborting the
// command. Waits forever if set to 0.
// outExitCode: An optional pointer to an existing location where the
// exit code for the launched process is returned.
// outChildPid: An optional pointer to an existing location where the
// pid for the launched child process is returned. Only valid
// if function returns true.
// outTempFile: An optional string containing the name of a file to
// redirect stdout and stderr to. Only used if |options|
// includes DumpOutputToFile.
//
// Returns true if the function succeeded in running the command. If you
// request |RunOptions::WaitForCompletion|, this does not mean that the
// command finished with "success" exit status, just that we succeeded in
// running it, cf |outExitCode|.
static const System::Duration kInfinite = 0;
virtual bool runCommand(const std::vector<std::string>& commandLine,
RunOptions options = RunOptions::Default,
System::Duration timeoutMs = kInfinite,
System::ProcessExitCode* outExitCode = nullptr,
System::Pid* outChildPid = nullptr,
const std::string& outputFile = "") = 0;
protected:
static System* setForTesting(System* system);
// Internal implementation of scanDirEntries() that can be used by
// mock implementation using a fake file system rooted into a temporary
// directory or something like that. Always returns short paths.
static std::vector<std::string> scanDirInternal(StringView dirPath);
static bool pathExistsInternal(StringView path);
static bool pathIsFileInternal(StringView path);
static bool pathIsDirInternal(StringView path);
static bool pathCanReadInternal(StringView path);
static bool pathCanWriteInternal(StringView path);
static bool pathCanExecInternal(StringView path);
static bool deleteFileInternal(StringView path);
static bool pathFileSizeInternal(StringView path, FileSize* outFileSize);
private:
DISALLOW_COPY_AND_ASSIGN(System);
};
} // namespace base
} // namespace android