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 explicit CommandOptionsValues(int64_t timeout_ms); 80 81 int64_t timeout_ms_; 82 bool always_; 83 bool close_all_fds_on_exec_; 84 PrivilegeMode account_mode_; 85 OutputMode output_mode_; 86 std::string logging_message_; 87 88 friend class CommandOptions; 89 friend class CommandOptionsBuilder; 90 }; 91 92 explicit CommandOptions(const CommandOptionsValues& values); 93 94 const CommandOptionsValues values; 95 96 public: 97 class CommandOptionsBuilder { 98 public: 99 /* Sets the command to always run, even on `dry-run` mode. */ 100 CommandOptionsBuilder& Always(); 101 /* 102 * Sets the command's PrivilegeMode as `SU_ROOT` unless overridden by system property 103 * 'dumpstate.unroot'. 104 */ 105 CommandOptionsBuilder& AsRoot(); 106 /* 107 * Runs AsRoot() on userdebug builds. No-op on user builds since 'su' is 108 * not available. This is used for commands that return some useful information even 109 * when run as shell. 110 */ 111 CommandOptionsBuilder& AsRootIfAvailable(); 112 /* Sets the command's PrivilegeMode as `DROP_ROOT` */ 113 CommandOptionsBuilder& DropRoot(); 114 /* Sets the command's OutputMode as `REDIRECT_TO_STDERR` */ 115 CommandOptionsBuilder& RedirectStderr(); 116 /* Closes all file descriptors before exec-ing the target process. This 117 * includes also stdio pipes, which are dup-ed on /dev/null. It prevents 118 * leaking opened FDs to the target process, which in turn can hit 119 * selinux denials in presence of auto_trans rules. 120 */ 121 CommandOptionsBuilder& CloseAllFileDescriptorsOnExec(); 122 123 /* When not empty, logs a message before executing the command. 124 * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */ 125 CommandOptionsBuilder& Log(const std::string& message); 126 /* Builds the command options. */ 127 CommandOptions Build(); 128 129 private: 130 explicit CommandOptionsBuilder(int64_t timeout_ms); 131 CommandOptionsValues values; 132 friend class CommandOptions; 133 }; 134 135 /** Gets the command timeout in seconds. */ 136 int64_t Timeout() const; 137 /** Gets the command timeout in milliseconds. */ 138 int64_t TimeoutInMs() const; 139 /* Checks whether the command should always be run, even on dry-run mode. */ 140 bool Always() const; 141 /* Checks whether all FDs should be closed prior to the exec() calls. */ 142 bool ShouldCloseAllFileDescriptorsOnExec() const; 143 /** Gets the PrivilegeMode of the command. */ 144 PrivilegeMode PrivilegeMode() const; 145 /** Gets the OutputMode of the command. */ 146 OutputMode OutputMode() const; 147 /** Gets the logging message header, it any. */ 148 std::string LoggingMessage() const; 149 150 /** Creates a builder with the requied timeout in seconds. */ 151 static CommandOptionsBuilder WithTimeout(int64_t timeout_sec); 152 153 /** Creates a builder with the requied timeout in milliseconds. */ 154 static CommandOptionsBuilder WithTimeoutInMs(int64_t timeout_ms); 155 156 // Common options. 157 static CommandOptions DEFAULT; 158 static CommandOptions AS_ROOT; 159 }; 160 161 /* 162 * System properties helper. 163 */ 164 class PropertiesHelper { 165 friend class DumpstateBaseTest; 166 167 public: 168 /* 169 * Gets whether device is running a `user` build. 170 */ 171 static bool IsUserBuild(); 172 173 /* 174 * When running in dry-run mode, skips the real dumps and just print the section headers. 175 * 176 * Useful when debugging dumpstate or other bugreport-related activities. 177 * 178 * Dry-run mode is enabled by setting the system property `dumpstate.dry_run` to true. 179 */ 180 static bool IsDryRun(); 181 182 /** 183 * Checks whether root availability should be overridden. 184 * 185 * Useful to verify how dumpstate would work in a device with an user build. 186 */ 187 static bool IsUnroot(); 188 189 /* 190 * Whether or not the parallel run is enabled. Setting the system property 191 * 'dumpstate.parallel_run' to false to disable it, otherwise it returns 192 * true by default. 193 */ 194 static bool IsParallelRun(); 195 196 private: 197 static std::string build_type_; 198 static int dry_run_; 199 static int unroot_; 200 static int parallel_run_; 201 }; 202 203 /* 204 * Forks a command, waits for it to finish, and returns its status. 205 * 206 * |fd| file descriptor that receives the command's 'stdout'. 207 * |title| description of the command printed on `stdout` (or empty to skip 208 * description). 209 * |full_command| array containing the command (first entry) and its arguments. 210 * Must contain at least one element. 211 * |options| optional argument defining the command's behavior. 212 */ 213 int RunCommandToFd(int fd, const std::string& title, const std::vector<std::string>& full_command, 214 const CommandOptions& options = CommandOptions::DEFAULT); 215 216 /* 217 * Dumps the contents of a file into a file descriptor. 218 * 219 * |fd| file descriptor where the file is dumped into. 220 * |title| description of the command printed on `stdout` (or empty to skip 221 * description). 222 * |path| location of the file to be dumped. 223 */ 224 int DumpFileToFd(int fd, const std::string& title, const std::string& path); 225 226 } // namespace dumpstate 227 } // namespace os 228 } // namespace android 229 230 #endif // ANDROID_OS_DUMPSTATE_UTIL_H_ 231