1 /* 2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <boot/PathBlocklist.h> 8 9 #include <stdlib.h> 10 11 #include <algorithm> 12 13 14 // #pragma mark - BlockedPath 15 16 17 BlockedPath::BlockedPath() 18 : 19 fPath(NULL), 20 fLength(0), 21 fCapacity(0) 22 { 23 } 24 25 26 BlockedPath::~BlockedPath() 27 { 28 free(fPath); 29 } 30 31 32 bool 33 BlockedPath::SetTo(const char* path) 34 { 35 size_t length = strlen(path); 36 if (length > 0 && path[length - 1] == '/') 37 length--; 38 39 if (!_Resize(length, false)) 40 return false; 41 42 if (length > 0) { 43 memcpy(fPath, path, length); 44 fPath[length] = '\0'; 45 } 46 47 return true; 48 } 49 50 51 bool 52 BlockedPath::Append(const char* component) 53 { 54 size_t componentLength = strlen(component); 55 if (componentLength > 0 && component[componentLength - 1] == '/') 56 componentLength--; 57 if (componentLength == 0) 58 return true; 59 60 size_t oldLength = fLength; 61 size_t length = (fLength > 0 ? fLength + 1 : 0) + componentLength; 62 if (!_Resize(length, true)) 63 return false; 64 65 if (oldLength > 0) 66 fPath[oldLength++] = '/'; 67 memcpy(fPath + oldLength, component, componentLength); 68 return true; 69 } 70 71 72 bool 73 BlockedPath::_Resize(size_t length, bool keepData) 74 { 75 if (length == 0) { 76 free(fPath); 77 fPath = NULL; 78 fLength = 0; 79 fCapacity = 0; 80 return true; 81 } 82 83 if (length < fCapacity) { 84 fPath[length] = '\0'; 85 fLength = length; 86 return true; 87 } 88 89 size_t capacity = std::max(length + 1, 2 * fCapacity); 90 capacity = std::max(capacity, size_t(32)); 91 92 char* path; 93 if (fLength > 0 && keepData) { 94 path = (char*)realloc(fPath, capacity); 95 if (path == NULL) 96 return false; 97 } else { 98 path = (char*)malloc(capacity); 99 if (path == NULL) 100 return false; 101 free(fPath); 102 } 103 104 fPath = path; 105 fPath[length] = '\0'; 106 fLength = length; 107 fCapacity = capacity; 108 return true; 109 } 110 111 112 // #pragma mark - PathBlocklist 113 114 115 PathBlocklist::PathBlocklist() 116 { 117 } 118 119 120 PathBlocklist::~PathBlocklist() 121 { 122 MakeEmpty(); 123 } 124 125 126 bool 127 PathBlocklist::Add(const char* path) 128 { 129 BlockedPath* blockedPath = _FindPath(path); 130 if (blockedPath != NULL) 131 return true; 132 133 blockedPath = new(std::nothrow) BlockedPath; 134 if (blockedPath == NULL || !blockedPath->SetTo(path)) { 135 delete blockedPath; 136 return false; 137 } 138 139 fPaths.Add(blockedPath); 140 return true; 141 } 142 143 144 void 145 PathBlocklist::Remove(const char* path) 146 { 147 BlockedPath* blockedPath = _FindPath(path); 148 if (blockedPath != NULL) { 149 fPaths.Remove(blockedPath); 150 delete blockedPath; 151 } 152 } 153 154 155 bool 156 PathBlocklist::Contains(const char* path) const 157 { 158 return _FindPath(path) != NULL; 159 } 160 161 162 void 163 PathBlocklist::MakeEmpty() 164 { 165 while (BlockedPath* blockedPath = fPaths.RemoveHead()) 166 delete blockedPath; 167 } 168 169 170 BlockedPath* 171 PathBlocklist::_FindPath(const char* path) const 172 { 173 for (PathList::Iterator it = fPaths.GetIterator(); it.HasNext();) { 174 BlockedPath* blockedPath = it.Next(); 175 if (*blockedPath == path) 176 return blockedPath; 177 } 178 179 return NULL; 180 } 181