• 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) : mUid(uid), mPid(pid) {
26 }
27 
cmp(uid_t uid,pid_t pid) const28 int 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 
format(char ** strp)38 void Prune::format(char **strp) {
39     if (mUid != uid_all) {
40         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, "/");
49     }
50 }
51 
PruneList()52 PruneList::PruneList() : mWorstUidEnabled(true) {
53 }
54 
~PruneList()55 PruneList::~PruneList() {
56     PruneCollection::iterator it;
57     for (it = mNice.begin(); it != mNice.end();) {
58         it = mNice.erase(it);
59     }
60     for (it = mNaughty.begin(); it != mNaughty.end();) {
61         it = mNaughty.erase(it);
62     }
63 }
64 
init(char * str)65 int PruneList::init(char *str) {
66     mWorstUidEnabled = true;
67     PruneCollection::iterator it;
68     for (it = mNice.begin(); it != mNice.end();) {
69         it = mNice.erase(it);
70     }
71     for (it = mNaughty.begin(); it != mNaughty.end();) {
72         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()) {
139             Prune &p = *it;
140             int m = uid - p.mUid;
141             if (m == 0) {
142                 if (p.mPid == p.pid_all) {
143                     break;
144                 }
145                 if ((pid == p.pid_all) && (p.mPid != p.pid_all)) {
146                     it = list->erase(it);
147                     continue;
148                 }
149                 m = pid - p.mPid;
150             }
151             if (m <= 0) {
152                 if (m < 0) {
153                     list->insert(it, Prune(uid,pid));
154                 }
155                 break;
156             }
157             ++it;
158         }
159         if (it == list->end()) {
160             list->push_back(Prune(uid,pid));
161         }
162         if (!*str) {
163             break;
164         }
165     }
166 
167     return 0;
168 }
169 
format(char ** strp)170 void 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;
190         (*it).format(&a);
191 
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;
202         (*it).format(&a);
203 
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 
naughty(LogBufferElement * element)217 bool PruneList::naughty(LogBufferElement *element) {
218     PruneCollection::iterator it;
219     for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
220         if (!(*it).cmp(element)) {
221             return true;
222         }
223     }
224     return false;
225 }
226 
nice(LogBufferElement * element)227 bool PruneList::nice(LogBufferElement *element) {
228     PruneCollection::iterator it;
229     for (it = mNice.begin(); it != mNice.end(); ++it) {
230         if (!(*it).cmp(element)) {
231             return true;
232         }
233     }
234     return false;
235 }
236