blob: 16dd6d2f015e1964f9927b5b6d96aabfb099f017 [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
Mark Salyzyn77187782015-05-12 15:21:31 -070025Prune::Prune(uid_t uid, pid_t pid) : mUid(uid), mPid(pid) {
26}
Mark Salyzyndfa7a072014-02-11 12:29:31 -080027
28int Prune::cmp(uid_t uid, pid_t pid) const {
29 if ((mUid == uid_all) || (mUid == uid)) {
30 if (mPid == pid_all) {
31 return 0;
32 }
33 return pid - mPid;
34 }
35 return uid - mUid;
36}
37
38void Prune::format(char **strp) {
39 if (mUid != uid_all) {
Chih-Hung Hsieh634118e2014-09-12 16:02:28 -070040 if (mPid != pid_all) {
41 asprintf(strp, "%u/%u", mUid, mPid);
42 } else {
43 asprintf(strp, "%u", mUid);
44 }
45 } else if (mPid != pid_all) {
46 asprintf(strp, "/%u", mPid);
47 } else { // NB: mPid == pid_all can not happen if mUid == uid_all
48 asprintf(strp, "/");
Mark Salyzyndfa7a072014-02-11 12:29:31 -080049 }
50}
51
Mark Salyzyn77187782015-05-12 15:21:31 -070052PruneList::PruneList() : mWorstUidEnabled(true) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -080053}
54
55PruneList::~PruneList() {
56 PruneCollection::iterator it;
57 for (it = mNice.begin(); it != mNice.end();) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -080058 it = mNice.erase(it);
59 }
60 for (it = mNaughty.begin(); it != mNaughty.end();) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -080061 it = mNaughty.erase(it);
62 }
63}
64
65int PruneList::init(char *str) {
Mark Salyzyn1a01f962014-05-06 13:49:28 -070066 mWorstUidEnabled = true;
Mark Salyzyndfa7a072014-02-11 12:29:31 -080067 PruneCollection::iterator it;
68 for (it = mNice.begin(); it != mNice.end();) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -080069 it = mNice.erase(it);
70 }
71 for (it = mNaughty.begin(); it != mNaughty.end();) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -080072 it = mNaughty.erase(it);
73 }
74
75 if (!str) {
76 return 0;
77 }
78
79 mWorstUidEnabled = false;
80
81 for(; *str; ++str) {
82 if (isspace(*str)) {
83 continue;
84 }
85
86 PruneCollection *list;
87 if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented
88 ++str;
89 // special case, translates to worst UID at priority in blacklist
90 if (*str == '!') {
91 mWorstUidEnabled = true;
92 ++str;
93 if (!*str) {
94 break;
95 }
96 if (!isspace(*str)) {
97 return 1;
98 }
99 continue;
100 }
101 if (!*str) {
102 return 1;
103 }
104 list = &mNaughty;
105 } else {
106 list = &mNice;
107 }
108
109 uid_t uid = Prune::uid_all;
110 if (isdigit(*str)) {
111 uid = 0;
112 do {
113 uid = uid * 10 + *str++ - '0';
114 } while (isdigit(*str));
115 }
116
117 pid_t pid = Prune::pid_all;
118 if (*str == '/') {
119 ++str;
120 if (isdigit(*str)) {
121 pid = 0;
122 do {
123 pid = pid * 10 + *str++ - '0';
124 } while (isdigit(*str));
125 }
126 }
127
128 if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {
129 return 1;
130 }
131
132 if (*str && !isspace(*str)) {
133 return 1;
134 }
135
136 // insert sequentially into list
137 PruneCollection::iterator it = list->begin();
138 while (it != list->end()) {
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700139 Prune &p = *it;
140 int m = uid - p.mUid;
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800141 if (m == 0) {
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700142 if (p.mPid == p.pid_all) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800143 break;
144 }
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700145 if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800146 it = list->erase(it);
147 continue;
148 }
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700149 m = pid - p.mPid;
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800150 }
Mark Salyzyn22e287d2014-03-21 13:12:16 -0700151 if (m <= 0) {
152 if (m < 0) {
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700153 list->insert(it, Prune(uid,pid));
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800154 }
155 break;
156 }
157 ++it;
158 }
159 if (it == list->end()) {
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700160 list->push_back(Prune(uid,pid));
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800161 }
162 if (!*str) {
163 break;
164 }
165 }
166
167 return 0;
168}
169
170void PruneList::format(char **strp) {
171 if (*strp) {
172 free(*strp);
173 *strp = NULL;
174 }
175
176 static const char nice_format[] = " %s";
177 const char *fmt = nice_format + 1;
178
179 android::String8 string;
180
181 if (mWorstUidEnabled) {
182 string.setTo("~!");
183 fmt = nice_format;
184 }
185
186 PruneCollection::iterator it;
187
188 for (it = mNice.begin(); it != mNice.end(); ++it) {
189 char *a = NULL;
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700190 (*it).format(&a);
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800191
192 string.appendFormat(fmt, a);
193 fmt = nice_format;
194
195 free(a);
196 }
197
198 static const char naughty_format[] = " ~%s";
199 fmt = naughty_format + (*fmt != ' ');
200 for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
201 char *a = NULL;
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700202 (*it).format(&a);
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800203
204 string.appendFormat(fmt, a);
205 fmt = naughty_format;
206
207 free(a);
208 }
209
210 *strp = strdup(string.string());
211}
212
213// ToDo: Lists are in sorted order, Prune->cmp() returns + or -
214// If there is scaling issues, resort to a better algorithm than linear
215// based on these assumptions.
216
217bool PruneList::naughty(LogBufferElement *element) {
218 PruneCollection::iterator it;
219 for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700220 if (!(*it).cmp(element)) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800221 return true;
222 }
223 }
224 return false;
225}
226
227bool PruneList::nice(LogBufferElement *element) {
228 PruneCollection::iterator it;
229 for (it = mNice.begin(); it != mNice.end(); ++it) {
Mark Salyzyne0ed16c2015-08-19 13:31:31 -0700230 if (!(*it).cmp(element)) {
Mark Salyzyndfa7a072014-02-11 12:29:31 -0800231 return true;
232 }
233 }
234 return false;
235}