blob: d7088b4dbeed9ca976f5e09749ddd050db1d91b9 [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
Mark Salyzyn1114f182014-02-21 13:54:07 -08002 * Copyright (C) 2012-2014 The Android Open Source Project
Mark Salyzyn0175b072014-02-26 09:50:16 -08003 *
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 Salyzyn8daa9af2014-04-28 14:07:23 -070024#include <sys/prctl.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080025#include <sys/socket.h>
26#include <sys/types.h>
27
Mark Salyzyndfc47e82014-03-24 10:26:47 -070028#include <cutils/sockets.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080029#include <private/android_filesystem_config.h>
Mark Salyzyn1114f182014-02-21 13:54:07 -080030#include <sysutils/SocketClient.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080031
32#include "CommandListener.h"
Mark Salyzyn1114f182014-02-21 13:54:07 -080033#include "LogCommand.h"
Mark Salyzyn0175b072014-02-26 09:50:16 -080034
35CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
36 LogListener * /*swl*/)
Mark Salyzyndfc47e82014-03-24 10:26:47 -070037 : FrameworkListener(getLogSocket())
Mark Salyzyn0175b072014-02-26 09:50:16 -080038 , mBuf(*buf) {
39 // registerCmd(new ShutdownCmd(buf, writer, swl));
40 registerCmd(new ClearCmd(buf));
41 registerCmd(new GetBufSizeCmd(buf));
Mark Salyzyndfa7a072014-02-11 12:29:31 -080042 registerCmd(new SetBufSizeCmd(buf));
Mark Salyzyn0175b072014-02-26 09:50:16 -080043 registerCmd(new GetBufSizeUsedCmd(buf));
Mark Salyzyn34facab2014-02-06 14:48:50 -080044 registerCmd(new GetStatisticsCmd(buf));
Mark Salyzyndfa7a072014-02-11 12:29:31 -080045 registerCmd(new SetPruneListCmd(buf));
46 registerCmd(new GetPruneListCmd(buf));
Mark Salyzyn0175b072014-02-26 09:50:16 -080047}
48
49CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader,
50 LogListener *swl)
51 : LogCommand("shutdown")
52 , mBuf(*buf)
53 , mReader(*reader)
54 , mSwl(*swl)
55{ }
56
57int CommandListener::ShutdownCmd::runCommand(SocketClient * /*cli*/,
58 int /*argc*/,
59 char ** /*argv*/) {
60 mSwl.stopListener();
61 mReader.stopListener();
62 exit(0);
63}
64
65CommandListener::ClearCmd::ClearCmd(LogBuffer *buf)
66 : LogCommand("clear")
67 , mBuf(*buf)
68{ }
69
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070070static void setname() {
71 prctl(PR_SET_NAME, "logd.control");
72}
73
Mark Salyzyn0175b072014-02-26 09:50:16 -080074int CommandListener::ClearCmd::runCommand(SocketClient *cli,
75 int argc, char **argv) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070076 setname();
Mark Salyzyn1a240b42014-06-12 11:16:16 -070077 uid_t uid = cli->getUid();
78 if (clientHasLogCredentials(cli)) {
79 uid = AID_ROOT;
Mark Salyzyn0175b072014-02-26 09:50:16 -080080 }
81
82 if (argc < 2) {
83 cli->sendMsg("Missing Argument");
84 return 0;
85 }
86
87 int id = atoi(argv[1]);
Mark Salyzyn1114f182014-02-21 13:54:07 -080088 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
Mark Salyzyn0175b072014-02-26 09:50:16 -080089 cli->sendMsg("Range Error");
90 return 0;
91 }
92
Mark Salyzyn1a240b42014-06-12 11:16:16 -070093 mBuf.clear((log_id_t) id, uid);
Mark Salyzyn0175b072014-02-26 09:50:16 -080094 cli->sendMsg("success");
95 return 0;
96}
97
Mark Salyzyn0175b072014-02-26 09:50:16 -080098CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer *buf)
99 : LogCommand("getLogSize")
100 , mBuf(*buf)
101{ }
102
103int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli,
104 int argc, char **argv) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700105 setname();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800106 if (argc < 2) {
107 cli->sendMsg("Missing Argument");
108 return 0;
109 }
110
111 int id = atoi(argv[1]);
Mark Salyzyn1114f182014-02-21 13:54:07 -0800112 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800113 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 Salyzyndfa7a072014-02-11 12:29:31 -0800124CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer *buf)
125 : LogCommand("setLogSize")
126 , mBuf(*buf)
127{ }
128
129int CommandListener::SetBufSizeCmd::runCommand(SocketClient *cli,
130 int argc, char **argv) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700131 setname();
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800132 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 Salyzyn0175b072014-02-26 09:50:16 -0800158CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer *buf)
159 : LogCommand("getLogSizeUsed")
160 , mBuf(*buf)
161{ }
162
163int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient *cli,
164 int argc, char **argv) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700165 setname();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800166 if (argc < 2) {
167 cli->sendMsg("Missing Argument");
168 return 0;
169 }
170
171 int id = atoi(argv[1]);
Mark Salyzyn1114f182014-02-21 13:54:07 -0800172 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
Mark Salyzyn0175b072014-02-26 09:50:16 -0800173 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 Salyzyn34facab2014-02-06 14:48:50 -0800183
184CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer *buf)
185 : LogCommand("getStatistics")
186 , mBuf(*buf)
187{ }
188
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800189static 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 Salyzyn34facab2014-02-06 14:48:50 -0800207int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
208 int argc, char **argv) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700209 setname();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800210 uid_t uid = cli->getUid();
Mark Salyzyn34facab2014-02-06 14:48:50 -0800211 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 Salyzyndfa7a072014-02-11 12:29:31 -0800234 package_string(&buf);
Mark Salyzyn34facab2014-02-06 14:48:50 -0800235 cli->sendMsg(buf);
236 free(buf);
237 }
238 return 0;
239}
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800240
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800241CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer *buf)
242 : LogCommand("getPruneList")
243 , mBuf(*buf)
244{ }
245
246int CommandListener::GetPruneListCmd::runCommand(SocketClient *cli,
247 int /*argc*/, char ** /*argv*/) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700248 setname();
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800249 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
261CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer *buf)
262 : LogCommand("setPruneList")
263 , mBuf(*buf)
264{ }
265
266int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,
267 int argc, char **argv) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -0700268 setname();
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800269 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 Salyzyndfc47e82014-03-24 10:26:47 -0700298
299int 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}