| /* |
| * 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(); |
| |
| /* |
| * Strict-run mode is determined by the `dumpstate.strict_run` sysprop which |
| * will default to true. This results in shortened timeouts for flaky |
| * sections. |
| */ |
| static bool IsStrictRun(); |
| |
| private: |
| static std::string build_type_; |
| static int dry_run_; |
| static int unroot_; |
| static int parallel_run_; |
| static int strict_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_ |