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
BlockedPath()17 BlockedPath::BlockedPath()
18 :
19 fPath(NULL),
20 fLength(0),
21 fCapacity(0)
22 {
23 }
24
25
~BlockedPath()26 BlockedPath::~BlockedPath()
27 {
28 free(fPath);
29 }
30
31
32 bool
SetTo(const char * path)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
Append(const char * component)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
_Resize(size_t length,bool keepData)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
PathBlocklist()115 PathBlocklist::PathBlocklist()
116 {
117 }
118
119
~PathBlocklist()120 PathBlocklist::~PathBlocklist()
121 {
122 MakeEmpty();
123 }
124
125
126 bool
Add(const char * path)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
Remove(const char * path)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
Contains(const char * path) const156 PathBlocklist::Contains(const char* path) const
157 {
158 return _FindPath(path) != NULL;
159 }
160
161
162 void
MakeEmpty()163 PathBlocklist::MakeEmpty()
164 {
165 while (BlockedPath* blockedPath = fPaths.RemoveHead())
166 delete blockedPath;
167 }
168
169
170 BlockedPath*
_FindPath(const char * path) const171 PathBlocklist::_FindPath(const char* path) const
172 {
173 for (PathList::ConstIterator it = fPaths.GetIterator(); it.HasNext();) {
174 BlockedPath* blockedPath = it.Next();
175 if (*blockedPath == path)
176 return blockedPath;
177 }
178
179 return NULL;
180 }
181