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