You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
7.3 KiB
231 lines
7.3 KiB
/*
|
|
* Copyright (C) 2016 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.
|
|
*/
|
|
#ifndef ANDROID_OS_DUMPSTATE_UTIL_H_
|
|
#define ANDROID_OS_DUMPSTATE_UTIL_H_
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
/*
|
|
* Converts seconds to milliseconds.
|
|
*/
|
|
#define SEC_TO_MSEC(second) (second * 1000)
|
|
|
|
/*
|
|
* Converts milliseconds to seconds.
|
|
*/
|
|
#define MSEC_TO_SEC(millisecond) (millisecond / 1000)
|
|
|
|
namespace android {
|
|
namespace os {
|
|
namespace dumpstate {
|
|
|
|
/*
|
|
* Defines the Linux account that should be executing a command.
|
|
*/
|
|
enum PrivilegeMode {
|
|
/* Explicitly change the `uid` and `gid` to be `shell`.*/
|
|
DROP_ROOT,
|
|
/* Don't change the `uid` and `gid`. */
|
|
DONT_DROP_ROOT,
|
|
/* Prefix the command with `/PATH/TO/su root`. Won't work non user builds. */
|
|
SU_ROOT
|
|
};
|
|
|
|
/*
|
|
* Defines what should happen with the main output stream (`stdout` or fd) of a command.
|
|
*/
|
|
enum OutputMode {
|
|
/* Don't change main output. */
|
|
NORMAL_OUTPUT,
|
|
/* Redirect main output to `stderr`. */
|
|
REDIRECT_TO_STDERR
|
|
};
|
|
|
|
/*
|
|
* Value object used to set command options.
|
|
*
|
|
* Typically constructed using a builder with chained setters. Examples:
|
|
*
|
|
* CommandOptions::WithTimeout(20).AsRoot().Build();
|
|
* CommandOptions::WithTimeout(10).Always().RedirectStderr().Build();
|
|
*
|
|
* Although the builder could be used to dynamically set values. Example:
|
|
*
|
|
* CommandOptions::CommandOptionsBuilder options =
|
|
* CommandOptions::WithTimeout(10);
|
|
* if (!is_user_build()) {
|
|
* options.AsRoot();
|
|
* }
|
|
* RunCommand("command", {"args"}, options.Build());
|
|
*/
|
|
class CommandOptions {
|
|
private:
|
|
class CommandOptionsValues {
|
|
private:
|
|
explicit CommandOptionsValues(int64_t timeout_ms);
|
|
|
|
int64_t timeout_ms_;
|
|
bool always_;
|
|
bool close_all_fds_on_exec_;
|
|
PrivilegeMode account_mode_;
|
|
OutputMode output_mode_;
|
|
std::string logging_message_;
|
|
|
|
friend class CommandOptions;
|
|
friend class CommandOptionsBuilder;
|
|
};
|
|
|
|
explicit CommandOptions(const CommandOptionsValues& values);
|
|
|
|
const CommandOptionsValues values;
|
|
|
|
public:
|
|
class CommandOptionsBuilder {
|
|
public:
|
|
/* Sets the command to always run, even on `dry-run` mode. */
|
|
CommandOptionsBuilder& Always();
|
|
/*
|
|
* Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property
|
|
* 'dumpstate.unroot'.
|
|
*/
|
|
CommandOptionsBuilder& AsRoot();
|
|
/*
|
|
* Runs AsRoot() on userdebug builds. No-op on user builds since 'su' is
|
|
* not available. This is used for commands that return some useful information even
|
|
* when run as shell.
|
|
*/
|
|
CommandOptionsBuilder& AsRootIfAvailable();
|
|
/* Sets the command's PrivilegeMode as `DROP_ROOT` */
|
|
CommandOptionsBuilder& DropRoot();
|
|
/* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */
|
|
CommandOptionsBuilder& RedirectStderr();
|
|
/* Closes all file descriptors before exec-ing the target process. This
|
|
* includes also stdio pipes, which are dup-ed on /dev/null. It prevents
|
|
* leaking opened FDs to the target process, which in turn can hit
|
|
* selinux denials in presence of auto_trans rules.
|
|
*/
|
|
CommandOptionsBuilder& CloseAllFileDescriptorsOnExec();
|
|
|
|
/* When not empty, logs a message before executing the command.
|
|
* Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */
|
|
CommandOptionsBuilder& Log(const std::string& message);
|
|
/* Builds the command options. */
|
|
CommandOptions Build();
|
|
|
|
private:
|
|
explicit CommandOptionsBuilder(int64_t timeout_ms);
|
|
CommandOptionsValues values;
|
|
friend class CommandOptions;
|
|
};
|
|
|
|
/** Gets the command timeout in seconds. */
|
|
int64_t Timeout() const;
|
|
/** Gets the command timeout in milliseconds. */
|
|
int64_t TimeoutInMs() const;
|
|
/* Checks whether the command should always be run, even on dry-run mode. */
|
|
bool Always() const;
|
|
/* Checks whether all FDs should be closed prior to the exec() calls. */
|
|
bool ShouldCloseAllFileDescriptorsOnExec() const;
|
|
/** Gets the PrivilegeMode of the command. */
|
|
PrivilegeMode PrivilegeMode() const;
|
|
/** Gets the OutputMode of the command. */
|
|
OutputMode OutputMode() const;
|
|
/** Gets the logging message header, it any. */
|
|
std::string LoggingMessage() const;
|
|
|
|
/** Creates a builder with the requied timeout in seconds. */
|
|
static CommandOptionsBuilder WithTimeout(int64_t timeout_sec);
|
|
|
|
/** Creates a builder with the requied timeout in milliseconds. */
|
|
static CommandOptionsBuilder WithTimeoutInMs(int64_t timeout_ms);
|
|
|
|
// Common options.
|
|
static CommandOptions DEFAULT;
|
|
static CommandOptions AS_ROOT;
|
|
};
|
|
|
|
/*
|
|
* System properties helper.
|
|
*/
|
|
class PropertiesHelper {
|
|
friend class DumpstateBaseTest;
|
|
|
|
public:
|
|
/*
|
|
* Gets whether device is running a `user` build.
|
|
*/
|
|
static bool IsUserBuild();
|
|
|
|
/*
|
|
* When running in dry-run mode, skips the real dumps and just print the section headers.
|
|
*
|
|
* Useful when debugging dumpstate or other bugreport-related activities.
|
|
*
|
|
* Dry-run mode is enabled by setting the system property `dumpstate.dry_run` to true.
|
|
*/
|
|
static bool IsDryRun();
|
|
|
|
/**
|
|
* Checks whether root availability should be overridden.
|
|
*
|
|
* Useful to verify how dumpstate would work in a device with an user build.
|
|
*/
|
|
static bool IsUnroot();
|
|
|
|
/*
|
|
* Whether or not the parallel run is enabled. Setting the system property
|
|
* 'dumpstate.parallel_run' to false to disable it, otherwise it returns
|
|
* true by default.
|
|
*/
|
|
static bool IsParallelRun();
|
|
|
|
private:
|
|
static std::string build_type_;
|
|
static int dry_run_;
|
|
static int unroot_;
|
|
static int parallel_run_;
|
|
};
|
|
|
|
/*
|
|
* Forks a command, waits for it to finish, and returns its status.
|
|
*
|
|
* |fd| file descriptor that receives the command's 'stdout'.
|
|
* |title| description of the command printed on `stdout` (or empty to skip
|
|
* description).
|
|
* |full_command| array containing the command (first entry) and its arguments.
|
|
* Must contain at least one element.
|
|
* |options| optional argument defining the command's behavior.
|
|
*/
|
|
int RunCommandToFd(int fd, const std::string& title, const std::vector<std::string>& full_command,
|
|
const CommandOptions& options = CommandOptions::DEFAULT);
|
|
|
|
/*
|
|
* Dumps the contents of a file into a file descriptor.
|
|
*
|
|
* |fd| file descriptor where the file is dumped into.
|
|
* |title| description of the command printed on `stdout` (or empty to skip
|
|
* description).
|
|
* |path| location of the file to be dumped.
|
|
*/
|
|
int DumpFileToFd(int fd, const std::string& title, const std::string& path);
|
|
|
|
} // namespace dumpstate
|
|
} // namespace os
|
|
} // namespace android
|
|
|
|
#endif // ANDROID_OS_DUMPSTATE_UTIL_H_
|