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