LogWhiteBlackList.cpp revision 4141cb2391cfd7211ffff7e53841c6c52869d525
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 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() 50 : mWorstUidEnabled(false) { 51 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 = 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 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} 240