• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #include <ctype.h>
18 
19 #include <utils/String8.h>
20 
21 #include "LogWhiteBlackList.h"
22 
23 // White and Black list
24 
Prune(uid_t uid,pid_t pid)25 Prune::Prune(uid_t uid, pid_t pid)
26         : mUid(uid)
27         , mPid(pid)
28 { }
29 
cmp(uid_t uid,pid_t pid) const30 int 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 
format(char ** strp)40 void 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 
PruneList()49 PruneList::PruneList()
50         : mWorstUidEnabled(false) {
51     mNaughty.clear();
52     mNice.clear();
53 }
54 
~PruneList()55 PruneList::~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 
init(char * str)67 int PruneList::init(char *str) {
68     mWorstUidEnabled = false;
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             }
155             if (m <= 0) {
156                 if (m < 0) {
157                     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 
format(char ** strp)174 void 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 
naughty(LogBufferElement * element)221 bool 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 
nice(LogBufferElement * element)231 bool 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 }
240