| /* | 
 |  * 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_ |