Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 1 | /* |
Mark Salyzyn | 1114f18 | 2014-02-21 13:54:07 -0800 | [diff] [blame] | 2 | * Copyright (C) 2012-2014 The Android Open Source Project |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 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 | |
| 17 | #include <arpa/inet.h> |
| 18 | #include <dirent.h> |
| 19 | #include <errno.h> |
| 20 | #include <fcntl.h> |
| 21 | #include <netinet/in.h> |
| 22 | #include <string.h> |
| 23 | #include <stdlib.h> |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 24 | #include <sys/prctl.h> |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 25 | #include <sys/socket.h> |
| 26 | #include <sys/types.h> |
| 27 | |
Mark Salyzyn | dfc47e8 | 2014-03-24 10:26:47 -0700 | [diff] [blame] | 28 | #include <cutils/sockets.h> |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 29 | #include <private/android_filesystem_config.h> |
Mark Salyzyn | 1114f18 | 2014-02-21 13:54:07 -0800 | [diff] [blame] | 30 | #include <sysutils/SocketClient.h> |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 31 | |
| 32 | #include "CommandListener.h" |
Mark Salyzyn | 1114f18 | 2014-02-21 13:54:07 -0800 | [diff] [blame] | 33 | #include "LogCommand.h" |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 34 | |
| 35 | CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, |
| 36 | LogListener * /*swl*/) |
Mark Salyzyn | dfc47e8 | 2014-03-24 10:26:47 -0700 | [diff] [blame] | 37 | : FrameworkListener(getLogSocket()) |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 38 | , mBuf(*buf) { |
| 39 | // registerCmd(new ShutdownCmd(buf, writer, swl)); |
| 40 | registerCmd(new ClearCmd(buf)); |
| 41 | registerCmd(new GetBufSizeCmd(buf)); |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 42 | registerCmd(new SetBufSizeCmd(buf)); |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 43 | registerCmd(new GetBufSizeUsedCmd(buf)); |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 44 | registerCmd(new GetStatisticsCmd(buf)); |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 45 | registerCmd(new SetPruneListCmd(buf)); |
| 46 | registerCmd(new GetPruneListCmd(buf)); |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader, |
| 50 | LogListener *swl) |
| 51 | : LogCommand("shutdown") |
| 52 | , mBuf(*buf) |
| 53 | , mReader(*reader) |
| 54 | , mSwl(*swl) |
| 55 | { } |
| 56 | |
| 57 | int CommandListener::ShutdownCmd::runCommand(SocketClient * /*cli*/, |
| 58 | int /*argc*/, |
| 59 | char ** /*argv*/) { |
| 60 | mSwl.stopListener(); |
| 61 | mReader.stopListener(); |
| 62 | exit(0); |
| 63 | } |
| 64 | |
| 65 | CommandListener::ClearCmd::ClearCmd(LogBuffer *buf) |
| 66 | : LogCommand("clear") |
| 67 | , mBuf(*buf) |
| 68 | { } |
| 69 | |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 70 | static void setname() { |
| 71 | prctl(PR_SET_NAME, "logd.control"); |
| 72 | } |
| 73 | |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 74 | int CommandListener::ClearCmd::runCommand(SocketClient *cli, |
| 75 | int argc, char **argv) { |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 76 | setname(); |
Mark Salyzyn | 1a240b4 | 2014-06-12 11:16:16 -0700 | [diff] [blame] | 77 | uid_t uid = cli->getUid(); |
| 78 | if (clientHasLogCredentials(cli)) { |
| 79 | uid = AID_ROOT; |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | if (argc < 2) { |
| 83 | cli->sendMsg("Missing Argument"); |
| 84 | return 0; |
| 85 | } |
| 86 | |
| 87 | int id = atoi(argv[1]); |
Mark Salyzyn | 1114f18 | 2014-02-21 13:54:07 -0800 | [diff] [blame] | 88 | if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 89 | cli->sendMsg("Range Error"); |
| 90 | return 0; |
| 91 | } |
| 92 | |
Mark Salyzyn | 1a240b4 | 2014-06-12 11:16:16 -0700 | [diff] [blame] | 93 | mBuf.clear((log_id_t) id, uid); |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 94 | cli->sendMsg("success"); |
| 95 | return 0; |
| 96 | } |
| 97 | |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 98 | CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer *buf) |
| 99 | : LogCommand("getLogSize") |
| 100 | , mBuf(*buf) |
| 101 | { } |
| 102 | |
| 103 | int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli, |
| 104 | int argc, char **argv) { |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 105 | setname(); |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 106 | if (argc < 2) { |
| 107 | cli->sendMsg("Missing Argument"); |
| 108 | return 0; |
| 109 | } |
| 110 | |
| 111 | int id = atoi(argv[1]); |
Mark Salyzyn | 1114f18 | 2014-02-21 13:54:07 -0800 | [diff] [blame] | 112 | if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 113 | cli->sendMsg("Range Error"); |
| 114 | return 0; |
| 115 | } |
| 116 | |
| 117 | unsigned long size = mBuf.getSize((log_id_t) id); |
| 118 | char buf[512]; |
| 119 | snprintf(buf, sizeof(buf), "%lu", size); |
| 120 | cli->sendMsg(buf); |
| 121 | return 0; |
| 122 | } |
| 123 | |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 124 | CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer *buf) |
| 125 | : LogCommand("setLogSize") |
| 126 | , mBuf(*buf) |
| 127 | { } |
| 128 | |
| 129 | int CommandListener::SetBufSizeCmd::runCommand(SocketClient *cli, |
| 130 | int argc, char **argv) { |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 131 | setname(); |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 132 | if (!clientHasLogCredentials(cli)) { |
| 133 | cli->sendMsg("Permission Denied"); |
| 134 | return 0; |
| 135 | } |
| 136 | |
| 137 | if (argc < 3) { |
| 138 | cli->sendMsg("Missing Argument"); |
| 139 | return 0; |
| 140 | } |
| 141 | |
| 142 | int id = atoi(argv[1]); |
| 143 | if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { |
| 144 | cli->sendMsg("Range Error"); |
| 145 | return 0; |
| 146 | } |
| 147 | |
| 148 | unsigned long size = atol(argv[2]); |
| 149 | if (mBuf.setSize((log_id_t) id, size)) { |
| 150 | cli->sendMsg("Range Error"); |
| 151 | return 0; |
| 152 | } |
| 153 | |
| 154 | cli->sendMsg("success"); |
| 155 | return 0; |
| 156 | } |
| 157 | |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 158 | CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer *buf) |
| 159 | : LogCommand("getLogSizeUsed") |
| 160 | , mBuf(*buf) |
| 161 | { } |
| 162 | |
| 163 | int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient *cli, |
| 164 | int argc, char **argv) { |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 165 | setname(); |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 166 | if (argc < 2) { |
| 167 | cli->sendMsg("Missing Argument"); |
| 168 | return 0; |
| 169 | } |
| 170 | |
| 171 | int id = atoi(argv[1]); |
Mark Salyzyn | 1114f18 | 2014-02-21 13:54:07 -0800 | [diff] [blame] | 172 | if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { |
Mark Salyzyn | 0175b07 | 2014-02-26 09:50:16 -0800 | [diff] [blame] | 173 | cli->sendMsg("Range Error"); |
| 174 | return 0; |
| 175 | } |
| 176 | |
| 177 | unsigned long size = mBuf.getSizeUsed((log_id_t) id); |
| 178 | char buf[512]; |
| 179 | snprintf(buf, sizeof(buf), "%lu", size); |
| 180 | cli->sendMsg(buf); |
| 181 | return 0; |
| 182 | } |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 183 | |
| 184 | CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer *buf) |
| 185 | : LogCommand("getStatistics") |
| 186 | , mBuf(*buf) |
| 187 | { } |
| 188 | |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 189 | static void package_string(char **strp) { |
| 190 | const char *a = *strp; |
| 191 | if (!a) { |
| 192 | a = ""; |
| 193 | } |
| 194 | |
| 195 | // Calculate total buffer size prefix, count is the string length w/o nul |
| 196 | char fmt[32]; |
| 197 | for(size_t l = strlen(a), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) { |
| 198 | snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x); |
| 199 | } |
| 200 | |
| 201 | char *b = *strp; |
| 202 | *strp = NULL; |
| 203 | asprintf(strp, fmt, a); |
| 204 | free(b); |
| 205 | } |
| 206 | |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 207 | int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli, |
| 208 | int argc, char **argv) { |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 209 | setname(); |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 210 | uid_t uid = cli->getUid(); |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 211 | if (clientHasLogCredentials(cli)) { |
| 212 | uid = AID_ROOT; |
| 213 | } |
| 214 | |
| 215 | unsigned int logMask = -1; |
| 216 | if (argc > 1) { |
| 217 | logMask = 0; |
| 218 | for (int i = 1; i < argc; ++i) { |
| 219 | int id = atoi(argv[i]); |
| 220 | if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { |
| 221 | cli->sendMsg("Range Error"); |
| 222 | return 0; |
| 223 | } |
| 224 | logMask |= 1 << id; |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | char *buf = NULL; |
| 229 | |
| 230 | mBuf.formatStatistics(&buf, uid, logMask); |
| 231 | if (!buf) { |
| 232 | cli->sendMsg("Failed"); |
| 233 | } else { |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 234 | package_string(&buf); |
Mark Salyzyn | 34facab | 2014-02-06 14:48:50 -0800 | [diff] [blame] | 235 | cli->sendMsg(buf); |
| 236 | free(buf); |
| 237 | } |
| 238 | return 0; |
| 239 | } |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 240 | |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 241 | CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer *buf) |
| 242 | : LogCommand("getPruneList") |
| 243 | , mBuf(*buf) |
| 244 | { } |
| 245 | |
| 246 | int CommandListener::GetPruneListCmd::runCommand(SocketClient *cli, |
| 247 | int /*argc*/, char ** /*argv*/) { |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 248 | setname(); |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 249 | char *buf = NULL; |
| 250 | mBuf.formatPrune(&buf); |
| 251 | if (!buf) { |
| 252 | cli->sendMsg("Failed"); |
| 253 | } else { |
| 254 | package_string(&buf); |
| 255 | cli->sendMsg(buf); |
| 256 | free(buf); |
| 257 | } |
| 258 | return 0; |
| 259 | } |
| 260 | |
| 261 | CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer *buf) |
| 262 | : LogCommand("setPruneList") |
| 263 | , mBuf(*buf) |
| 264 | { } |
| 265 | |
| 266 | int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli, |
| 267 | int argc, char **argv) { |
Mark Salyzyn | 8daa9af | 2014-04-28 14:07:23 -0700 | [diff] [blame] | 268 | setname(); |
Mark Salyzyn | dfa7a07 | 2014-02-11 12:29:31 -0800 | [diff] [blame] | 269 | if (!clientHasLogCredentials(cli)) { |
| 270 | cli->sendMsg("Permission Denied"); |
| 271 | return 0; |
| 272 | } |
| 273 | |
| 274 | char *cp = NULL; |
| 275 | for (int i = 1; i < argc; ++i) { |
| 276 | char *p = cp; |
| 277 | if (p) { |
| 278 | cp = NULL; |
| 279 | asprintf(&cp, "%s %s", p, argv[i]); |
| 280 | free(p); |
| 281 | } else { |
| 282 | asprintf(&cp, "%s", argv[i]); |
| 283 | } |
| 284 | } |
| 285 | |
| 286 | int ret = mBuf.initPrune(cp); |
| 287 | free(cp); |
| 288 | |
| 289 | if (ret) { |
| 290 | cli->sendMsg("Invalid"); |
| 291 | return 0; |
| 292 | } |
| 293 | |
| 294 | cli->sendMsg("success"); |
| 295 | |
| 296 | return 0; |
| 297 | } |
Mark Salyzyn | dfc47e8 | 2014-03-24 10:26:47 -0700 | [diff] [blame] | 298 | |
| 299 | int CommandListener::getLogSocket() { |
| 300 | static const char socketName[] = "logd"; |
| 301 | int sock = android_get_control_socket(socketName); |
| 302 | |
| 303 | if (sock < 0) { |
| 304 | sock = socket_local_server(socketName, |
| 305 | ANDROID_SOCKET_NAMESPACE_RESERVED, |
| 306 | SOCK_STREAM); |
| 307 | } |
| 308 | |
| 309 | return sock; |
| 310 | } |