blob: d0ceb9fcab91d2d06c4497b854780149a5227cc0 [file] [log] [blame]
Mark Salyzyndfa7a072014-02-11 12:29:31 -08001/*
2 * Copyright (C) 2014 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
17#ifdef USERDEBUG_BUILD
18
19#include <ctype.h>
20
21#include <utils/String8.h>
22
23#include "LogWhiteBlackList.h"
24
25// White and Black list
26
27Prune::Prune(uid_t uid, pid_t pid)
28 : mUid(uid)
29 , mPid(pid)
30{ }
31
32int Prune::cmp(uid_t uid, pid_t pid) const {
33 if ((mUid == uid_all) || (mUid == uid)) {
34 if (mPid == pid_all) {
35 return 0;
36 }
37 return pid - mPid;
38 }
39 return uid - mUid;
40}
41
42void Prune::format(char **strp) {
43 if (mUid != uid_all) {
44 asprintf(strp, (mPid != pid_all) ? "%u/%u" : "%u", mUid, mPid);
45 } else {
46 // NB: mPid == pid_all can not happen if mUid == uid_all
47 asprintf(strp, (mPid != pid_all) ? "/%u" : "/", mPid);
48 }
49}
50
51PruneList::PruneList()
52 : mWorstUidEnabled(true) {
53 mNaughty.clear();
54 mNice.clear();
55}
56
57PruneList::~PruneList() {
58 PruneCollection::iterator it;
59 for (it = mNice.begin(); it != mNice.end();) {
60 delete (*it);
61 it = mNice.erase(it);
62 }
63 for (it = mNaughty.begin(); it != mNaughty.end();) {
64 delete (*it);
65 it = mNaughty.erase(it);
66 }
67}
68
69int PruneList::init(char *str) {
70 mWorstUidEnabled = true;
71 PruneCollection::iterator it;
72 for (it = mNice.begin(); it != mNice.end();) {
73 delete (*it);
74 it = mNice.erase(it);
75 }
76 for (it = mNaughty.begin(); it != mNaughty.end();) {
77 delete (*it);
78 it = mNaughty.erase(it);
79 }
80
81 if (!str) {
82 return 0;
83 }
84
85 mWorstUidEnabled = false;
86
87 for(; *str; ++str) {
88 if (isspace(*str)) {
89 continue;
90 }
91
92 PruneCollection *list;
93 if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented
94 ++str;
95 // special case, translates to worst UID at priority in blacklist
96 if (*str == '!') {
97 mWorstUidEnabled = true;
98 ++str;
99 if (!*str) {
100 break;
101 }
102 if (!isspace(*str)) {
103 return 1;
104 }
105 continue;
106 }
107 if (!*str) {
108 return 1;
109 }
110 list = &mNaughty;
111 } else {
112 list = &mNice;
113 }
114
115 uid_t uid = Prune::uid_all;
116 if (isdigit(*str)) {
117 uid = 0;
118 do {
119 uid = uid * 10 + *str++ - '0';
120 } while (isdigit(*str));
121 }
122
123 pid_t pid = Prune::pid_all;
124 if (*str == '/') {
125 ++str;
126 if (isdigit(*str)) {
127 pid = 0;
128 do {
129 pid = pid * 10 + *str++ - '0';
130 } while (isdigit(*str));
131 }
132 }
133
134 if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {
135 return 1;
136 }
137
138 if (*str && !isspace(*str)) {
139 return 1;
140 }
141
142 // insert sequentially into list
143 PruneCollection::iterator it = list->begin();
144 while (it != list->end()) {
145 Prune *p = *it;
146 int m = uid - p->mUid;
147 if (m == 0) {
148 if (p->mPid == p->pid_all) {
149 break;
150 }
151 if ((pid == p->pid_all) && (p->mPid != p->pid_all)) {
152 it = list->erase(it);
153 continue;
154 }
155 m = pid - p->mPid;
156 }
157 if (m >= 0) {
158 if (m > 0) {
159 list->insert(it, new Prune(uid,pid));
160 }
161 break;
162 }
163 ++it;
164 }
165 if (it == list->end()) {
166 list->push_back(new Prune(uid,pid));
167 }
168 if (!*str) {
169 break;
170 }
171 }
172
173 return 0;
174}
175
176void PruneList::format(char **strp) {
177 if (*strp) {
178 free(*strp);
179 *strp = NULL;
180 }
181
182 static const char nice_format[] = " %s";
183 const char *fmt = nice_format + 1;
184
185 android::String8 string;
186
187 if (mWorstUidEnabled) {
188 string.setTo("~!");
189 fmt = nice_format;
190 }
191
192 PruneCollection::iterator it;
193
194 for (it = mNice.begin(); it != mNice.end(); ++it) {
195 char *a = NULL;
196 (*it)->format(&a);
197
198 string.appendFormat(fmt, a);
199 fmt = nice_format;
200
201 free(a);
202 }
203
204 static const char naughty_format[] = " ~%s";
205 fmt = naughty_format + (*fmt != ' ');
206 for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
207 char *a = NULL;
208 (*it)->format(&a);
209
210 string.appendFormat(fmt, a);
211 fmt = naughty_format;
212
213 free(a);
214 }
215
216 *strp = strdup(string.string());
217}
218
219// ToDo: Lists are in sorted order, Prune->cmp() returns + or -
220// If there is scaling issues, resort to a better algorithm than linear
221// based on these assumptions.
222
223bool PruneList::naughty(LogBufferElement *element) {
224 PruneCollection::iterator it;
225 for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
226 if (!(*it)->cmp(element)) {
227 return true;
228 }
229 }
230 return false;
231}
232
233bool PruneList::nice(LogBufferElement *element) {
234 PruneCollection::iterator it;
235 for (it = mNice.begin(); it != mNice.end(); ++it) {
236 if (!(*it)->cmp(element)) {
237 return true;
238 }
239 }
240 return false;
241}
242
243#endif // USERDEBUG_BUILD