1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef ANDROID_OS_DUMPSTATE_UTIL_H_ 17 #define ANDROID_OS_DUMPSTATE_UTIL_H_ 18 19 #include <cstdint> 20 #include <string> 21 22 /* 23 * Converts seconds to milliseconds. 24 */ 25 #define SEC_TO_MSEC(second) (second * 1000) 26 27 /* 28 * Converts milliseconds to seconds. 29 */ 30 #define MSEC_TO_SEC(millisecond) (millisecond / 1000) 31 32 namespace android { 33 namespace os { 34 namespace dumpstate { 35 36 /* 37 * Defines the Linux account that should be executing a command. 38 */ 39 enum PrivilegeMode { 40 /* Explicitly change the `uid` and `gid` to be `shell`.*/ 41 DROP_ROOT, 42 /* Don't change the `uid` and `gid`. */ 43 DONT_DROP_ROOT, 44 /* Prefix the command with `/PATH/TO/su root`. Won't work non user builds. */ 45 SU_ROOT 46 }; 47 48 /* 49 * Defines what should happen with the main output stream (`stdout` or fd) of a command. 50 */ 51 enum OutputMode { 52 /* Don't change main output. */ 53 NORMAL_OUTPUT, 54 /* Redirect main output to `stderr`. */ 55 REDIRECT_TO_STDERR 56 }; 57 58 /* 59 * Value object used to set command options. 60 * 61 * Typically constructed using a builder with chained setters. Examples: 62 * 63 * CommandOptions::WithTimeout(20).AsRoot().Build(); 64 * CommandOptions::WithTimeout(10).Always().RedirectStderr().Build(); 65 * 66 * Although the builder could be used to dynamically set values. Example: 67 * 68 * CommandOptions::CommandOptionsBuilder options = 69 * CommandOptions::WithTimeout(10); 70 * if (!is_user_build()) { 71 * options.AsRoot(); 72 * } 73 * RunCommand("command", {"args"}, options.Build()); 74 */ 75 class CommandOptions { 76 private: 77 class CommandOptionsValues { 78 private: 79 CommandOptionsValues(int64_t timeout_ms); 80 81 int64_t timeout_ms_; 82 bool always_; 83 PrivilegeMode account_mode_; 84 OutputMode output_mode_; 85 std::string logging_message_; 86 87 friend class CommandOptions; 88 friend class CommandOptionsBuilder; 89 }; 90 91 CommandOptions(const CommandOptionsValues& values); 92 93 const CommandOptionsValues values; 94 95 public: 96 class CommandOptionsBuilder { 97 public: 98 /* Sets the command to always run, even on `dry-run` mode. */ 99 CommandOptionsBuilder& Always(); 100 /* Sets the command's PrivilegeMode as `SU_ROOT` */ 101 CommandOptionsBuilder& AsRoot(); 102 /* If !IsUserBuild(), sets the command's PrivilegeMode as `SU_ROOT` */ 103 CommandOptionsBuilder& AsRootIfAvailable(); 104 /* Sets the command's PrivilegeMode as `DROP_ROOT` */ 105 CommandOptionsBuilder& DropRoot(); 106 /* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */ 107 CommandOptionsBuilder& RedirectStderr(); 108 /* When not empty, logs a message before executing the command. 109 * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */ 110 CommandOptionsBuilder& Log(const std::string& message); 111 /* Builds the command options. */ 112 CommandOptions Build(); 113 114 private: 115 CommandOptionsBuilder(int64_t timeout_ms); 116 CommandOptionsValues values; 117 friend class CommandOptions; 118 }; 119 120 /** Gets the command timeout in seconds. */ 121 int64_t Timeout() const; 122 /** Gets the command timeout in milliseconds. */ 123 int64_t TimeoutInMs() const; 124 /* Checks whether the command should always be run, even on dry-run mode. */ 125 bool Always() const; 126 /** Gets the PrivilegeMode of the command. */ 127 PrivilegeMode PrivilegeMode() const; 128 /** Gets the OutputMode of the command. */ 129 OutputMode OutputMode() const; 130 /** Gets the logging message header, it any. */ 131 std::string LoggingMessage() const; 132 133 /** Creates a builder with the requied timeout in seconds. */ 134 static CommandOptionsBuilder WithTimeout(int64_t timeout_sec); 135 136 /** Creates a builder with the requied timeout in milliseconds. */ 137 static CommandOptionsBuilder WithTimeoutInMs(int64_t timeout_ms); 138 139 // Common options. 140 static CommandOptions DEFAULT; 141 static CommandOptions AS_ROOT; 142 }; 143 144 /* 145 * System properties helper. 146 */ 147 class PropertiesHelper { 148 friend class DumpstateBaseTest; 149 150 public: 151 /* 152 * Gets whether device is running a `user` build. 153 */ 154 static bool IsUserBuild(); 155 156 /* 157 * When running in dry-run mode, skips the real dumps and just print the section headers. 158 * 159 * Useful when debugging dumpstate or other bugreport-related activities. 160 * 161 * Dry-run mode is enabled by setting the system property `dumpstate.dry_run` to true. 162 */ 163 static bool IsDryRun(); 164 165 private: 166 static std::string build_type_; 167 static int dry_run_; 168 }; 169 170 /* 171 * Forks a command, waits for it to finish, and returns its status. 172 * 173 * |fd| file descriptor that receives the command's 'stdout'. 174 * |title| description of the command printed on `stdout` (or empty to skip 175 * description). 176 * |full_command| array containing the command (first entry) and its arguments. 177 * Must contain at least one element. 178 * |options| optional argument defining the command's behavior. 179 */ 180 int RunCommandToFd(int fd, const std::string& title, const std::vector<std::string>& full_command, 181 const CommandOptions& options = CommandOptions::DEFAULT); 182 183 /* 184 * Dumps the contents of a file into a file descriptor. 185 * 186 * |fd| file descriptor where the file is dumped into. 187 * |title| description of the command printed on `stdout` (or empty to skip 188 * description). 189 * |path| location of the file to be dumped. 190 */ 191 int DumpFileToFd(int fd, const std::string& title, const std::string& path); 192 193 /* 194 * Finds the process id by process name. 195 * |ps_name| the process name we want to search for 196 */ 197 int GetPidByName(const std::string& ps_name); 198 199 } // namespace dumpstate 200 } // namespace os 201 } // namespace android 202 203 #endif // ANDROID_OS_DUMPSTATE_UTIL_H_ 204