xref: /haiku/src/system/boot/loader/PathBlocklist.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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::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