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 #include <vector> 22 23 /* 24 * Converts seconds to milliseconds. 25 */ 26 #define SEC_TO_MSEC(second) (second * 1000) 27 28 /* 29 * Converts milliseconds to seconds. 30 */ 31 #define MSEC_TO_SEC(millisecond) (millisecond / 1000) 32 33 namespace android { 34 namespace os { 35 namespace dumpstate { 36 37 /* 38 * Defines the Linux account that should be executing a command. 39 */ 40 enum PrivilegeMode { 41 /* Explicitly change the `uid` and `gid` to be `shell`.*/ 42 DROP_ROOT, 43 /* Don't change the `uid` and `gid`. */ 44 DONT_DROP_ROOT, 45 /* Prefix the command with `/PATH/TO/su root`. Won't work non user builds. */ 46 SU_ROOT 47 }; 48 49 /* 50 * Defines what should happen with the main output stream (`stdout` or fd) of a command. 51 */ 52 enum OutputMode { 53 /* Don't change main output. */ 54 NORMAL_OUTPUT, 55 /* Redirect main output to `stderr`. */ 56 REDIRECT_TO_STDERR 57 }; 58 59 /* 60 * Value object used to set command options. 61 * 62 * Typically constructed using a builder with chained setters. Examples: 63 * 64 * CommandOptions::WithTimeout(20).AsRoot().Build(); 65 * CommandOptions::WithTimeout(10).Always().RedirectStderr().Build(); 66 * 67 * Although the builder could be used to dynamically set values. Example: 68 * 69 * CommandOptions::CommandOptionsBuilder options = 70 * CommandOptions::WithTimeout(10); 71 * if (!is_user_build()) { 72 * options.AsRoot(); 73 * } 74 * RunCommand("command", {"args"}, options.Build()); 75 */ 76 class CommandOptions { 77 private: 78 class CommandOptionsValues { 79 private: 80 explicit CommandOptionsValues(int64_t timeout_ms); 81 82 int64_t timeout_ms_; 83 bool always_; 84 bool close_all_fds_on_exec_; 85 PrivilegeMode account_mode_; 86 OutputMode output_mode_; 87 std::string logging_message_; 88 89 friend class CommandOptions; 90 friend class CommandOptionsBuilder; 91 }; 92 93 explicit CommandOptions(const CommandOptionsValues& values); 94 95 const CommandOptionsValues values; 96 97 public: 98 class CommandOptionsBuilder { 99 public: 100 /* Sets the command to always run, even on `dry-run` mode. */ 101 CommandOptionsBuilder& Always(); 102 /* 103 * Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property 104 * 'dumpstate.unroot'. 105 */ 106 CommandOptionsBuilder& AsRoot(); 107 /* 108 * Runs AsRoot() on userdebug builds. No-op on user builds since 'su' is 109 * not available. This is used for commands that return some useful information even 110 * when run as shell. 111 */ 112 CommandOptionsBuilder& AsRootIfAvailable(); 113 /* Sets the command's PrivilegeMode as `DROP_ROOT` */ 114 CommandOptionsBuilder& DropRoot(); 115 /* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */ 116 CommandOptionsBuilder& RedirectStderr(); 117 /* Closes all file descriptors before exec-ing the target process. This 118 * includes also stdio pipes, which are dup-ed on /dev/null. It prevents 119 * leaking opened FDs to the target process, which in turn can hit 120 * selinux denials in presence of auto_trans rules. 121 */ 122 CommandOptionsBuilder& CloseAllFileDescriptorsOnExec(); 123 124 /* When not empty, logs a message before executing the command. 125 * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */ 126 CommandOptionsBuilder& Log(const std::string& message); 127 /* Builds the command options. */ 128 CommandOptions Build(); 129 130 private: 131 explicit CommandOptionsBuilder(int64_t timeout_ms); 132 CommandOptionsValues values; 133 friend class CommandOptions; 134 }; 135 136 /** Gets the command timeout in seconds. */ 137 int64_t Timeout() const; 138 /** Gets the command timeout in milliseconds. */ 139 int64_t TimeoutInMs() const; 140 /* Checks whether the command should always be run, even on dry-run mode. */ 141 bool Always() const; 142 /* Checks whether all FDs should be closed prior to the exec() calls. */ 143 bool ShouldCloseAllFileDescriptorsOnExec() const; 144 /** Gets the PrivilegeMode of the command. */ 145 PrivilegeMode PrivilegeMode() const; 146 /** Gets the OutputMode of the command. */ 147 OutputMode OutputMode() const; 148 /** Gets the logging message header, it any. */ 149 std::string LoggingMessage() const; 150 151 /** Creates a builder with the requied timeout in seconds. */ 152 static CommandOptionsBuilder WithTimeout(int64_t timeout_sec); 153 154 /** Creates a builder with the requied timeout in milliseconds. */ 155 static CommandOptionsBuilder WithTimeoutInMs(int64_t timeout_ms); 156 157 // Common options. 158 static CommandOptions DEFAULT; 159 static CommandOptions AS_ROOT; 160 }; 161 162 /* 163 * System properties helper. 164 */ 165 class PropertiesHelper { 166 friend class DumpstateBaseTest; 167 168 public: 169 /* 170 * Gets whether device is running a `user` build. 171 */ 172 static bool IsUserBuild(); 173 174 /* 175 * When running in dry-run mode, skips the real dumps and just print the section headers. 176 * 177 * Useful when debugging dumpstate or other bugreport-related activities. 178 * 179 * Dry-run mode is enabled by setting the system property `dumpstate.dry_run` to true. 180 */ 181 static bool IsDryRun(); 182 183 /** 184 * Checks whether root availability should be overridden. 185 * 186 * Useful to verify how dumpstate would work in a device with an user build. 187 */ 188 static bool IsUnroot(); 189 190 /* 191 * Whether or not the parallel run is enabled. Setting the system property 192 * 'dumpstate.parallel_run' to false to disable it, otherwise it returns 193 * true by default. 194 */ 195 static bool IsParallelRun(); 196 197 /* 198 * Strict-run mode is determined by the `dumpstate.strict_run` sysprop which 199 * will default to true. This results in shortened timeouts for flaky 200 * sections. 201 */ 202 static bool IsStrictRun(); 203 204 private: 205 static std::string build_type_; 206 static int dry_run_; 207 static int unroot_; 208 static int parallel_run_; 209 static int strict_run_; 210 }; 211 212 /* 213 * Forks a command, waits for it to finish, and returns its status. 214 * 215 * |fd| file descriptor that receives the command's 'stdout'. 216 * |title| description of the command printed on `stdout` (or empty to skip 217 * description). 218 * |full_command| array containing the command (first entry) and its arguments. 219 * Must contain at least one element. 220 * |options| optional argument defining the command's behavior. 221 */ 222 int RunCommandToFd(int fd, const std::string& title, const std::vector<std::string>& full_command, 223 const CommandOptions& options = CommandOptions::DEFAULT); 224 225 /* 226 * Dumps the contents of a file into a file descriptor. 227 * 228 * |fd| file descriptor where the file is dumped into. 229 * |title| description of the command printed on `stdout` (or empty to skip 230 * description). 231 * |path| location of the file to be dumped. 232 */ 233 int DumpFileToFd(int fd, const std::string& title, const std::string& path); 234 235 } // namespace dumpstate 236 } // namespace os 237 } // namespace android 238 239 #endif // ANDROID_OS_DUMPSTATE_UTIL_H_ 240