xref: /haiku/src/tests/add-ons/kernel/kernelland_emu/KPath.cpp (revision 66c7a2ac9c1fcccc1455d2bc0a617bc44c631bfa)
1*66c7a2acSAugustin Cavalier /*
2*66c7a2acSAugustin Cavalier  * Copyright 2004-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3*66c7a2acSAugustin Cavalier  * Copyright 2008-2017, Axel Dörfler, axeld@pinc-software.de.
4*66c7a2acSAugustin Cavalier  * Distributed under the terms of the MIT License.
5*66c7a2acSAugustin Cavalier  */
6*66c7a2acSAugustin Cavalier 
7*66c7a2acSAugustin Cavalier 
8*66c7a2acSAugustin Cavalier /*! A simple class wrapping a path. Has a fixed-sized buffer. */
9*66c7a2acSAugustin Cavalier 
10*66c7a2acSAugustin Cavalier 
11*66c7a2acSAugustin Cavalier #include <fs/KPath.h>
12*66c7a2acSAugustin Cavalier #include <Path.h>
13*66c7a2acSAugustin Cavalier 
14*66c7a2acSAugustin Cavalier #include <stdlib.h>
15*66c7a2acSAugustin Cavalier #include <string.h>
16*66c7a2acSAugustin Cavalier 
17*66c7a2acSAugustin Cavalier #include <team.h>
18*66c7a2acSAugustin Cavalier 
19*66c7a2acSAugustin Cavalier 
20*66c7a2acSAugustin Cavalier // debugging
21*66c7a2acSAugustin Cavalier #define TRACE(x) ;
22*66c7a2acSAugustin Cavalier //#define TRACE(x) dprintf x
23*66c7a2acSAugustin Cavalier 
24*66c7a2acSAugustin Cavalier 
KPath(size_t bufferSize)25*66c7a2acSAugustin Cavalier KPath::KPath(size_t bufferSize)
26*66c7a2acSAugustin Cavalier 	:
27*66c7a2acSAugustin Cavalier 	fBuffer(NULL),
28*66c7a2acSAugustin Cavalier 	fBufferSize(0),
29*66c7a2acSAugustin Cavalier 	fPathLength(0),
30*66c7a2acSAugustin Cavalier 	fLocked(false),
31*66c7a2acSAugustin Cavalier 	fLazy(false),
32*66c7a2acSAugustin Cavalier 	fFailed(false),
33*66c7a2acSAugustin Cavalier 	fIsNull(false)
34*66c7a2acSAugustin Cavalier {
35*66c7a2acSAugustin Cavalier 	SetTo(NULL, DEFAULT, bufferSize);
36*66c7a2acSAugustin Cavalier }
37*66c7a2acSAugustin Cavalier 
38*66c7a2acSAugustin Cavalier 
KPath(const char * path,int32 flags,size_t bufferSize)39*66c7a2acSAugustin Cavalier KPath::KPath(const char* path, int32 flags, size_t bufferSize)
40*66c7a2acSAugustin Cavalier 	:
41*66c7a2acSAugustin Cavalier 	fBuffer(NULL),
42*66c7a2acSAugustin Cavalier 	fBufferSize(0),
43*66c7a2acSAugustin Cavalier 	fPathLength(0),
44*66c7a2acSAugustin Cavalier 	fLocked(false),
45*66c7a2acSAugustin Cavalier 	fLazy(false),
46*66c7a2acSAugustin Cavalier 	fFailed(false),
47*66c7a2acSAugustin Cavalier 	fIsNull(false)
48*66c7a2acSAugustin Cavalier {
49*66c7a2acSAugustin Cavalier 	SetTo(path, flags, bufferSize);
50*66c7a2acSAugustin Cavalier }
51*66c7a2acSAugustin Cavalier 
52*66c7a2acSAugustin Cavalier 
KPath(const KPath & other)53*66c7a2acSAugustin Cavalier KPath::KPath(const KPath& other)
54*66c7a2acSAugustin Cavalier 	:
55*66c7a2acSAugustin Cavalier 	fBuffer(NULL),
56*66c7a2acSAugustin Cavalier 	fBufferSize(0),
57*66c7a2acSAugustin Cavalier 	fPathLength(0),
58*66c7a2acSAugustin Cavalier 	fLocked(false),
59*66c7a2acSAugustin Cavalier 	fLazy(false),
60*66c7a2acSAugustin Cavalier 	fFailed(false),
61*66c7a2acSAugustin Cavalier 	fIsNull(false)
62*66c7a2acSAugustin Cavalier {
63*66c7a2acSAugustin Cavalier 	*this = other;
64*66c7a2acSAugustin Cavalier }
65*66c7a2acSAugustin Cavalier 
66*66c7a2acSAugustin Cavalier 
~KPath()67*66c7a2acSAugustin Cavalier KPath::~KPath()
68*66c7a2acSAugustin Cavalier {
69*66c7a2acSAugustin Cavalier 	free(fBuffer);
70*66c7a2acSAugustin Cavalier }
71*66c7a2acSAugustin Cavalier 
72*66c7a2acSAugustin Cavalier 
73*66c7a2acSAugustin Cavalier status_t
SetTo(const char * path,int32 flags,size_t bufferSize)74*66c7a2acSAugustin Cavalier KPath::SetTo(const char* path, int32 flags, size_t bufferSize)
75*66c7a2acSAugustin Cavalier {
76*66c7a2acSAugustin Cavalier 	if (bufferSize == 0)
77*66c7a2acSAugustin Cavalier 		bufferSize = B_PATH_NAME_LENGTH;
78*66c7a2acSAugustin Cavalier 
79*66c7a2acSAugustin Cavalier 	// free the previous buffer, if the buffer size differs
80*66c7a2acSAugustin Cavalier 	if (fBuffer != NULL && fBufferSize != bufferSize) {
81*66c7a2acSAugustin Cavalier 		free(fBuffer);
82*66c7a2acSAugustin Cavalier 		fBuffer = NULL;
83*66c7a2acSAugustin Cavalier 		fBufferSize = 0;
84*66c7a2acSAugustin Cavalier 	}
85*66c7a2acSAugustin Cavalier 
86*66c7a2acSAugustin Cavalier 	fPathLength = 0;
87*66c7a2acSAugustin Cavalier 	fLocked = false;
88*66c7a2acSAugustin Cavalier 	fBufferSize = bufferSize;
89*66c7a2acSAugustin Cavalier 	fLazy = (flags & LAZY_ALLOC) != 0;
90*66c7a2acSAugustin Cavalier 	fIsNull = path == NULL;
91*66c7a2acSAugustin Cavalier 
92*66c7a2acSAugustin Cavalier 	if (path != NULL || !fLazy) {
93*66c7a2acSAugustin Cavalier 		status_t status = _AllocateBuffer();
94*66c7a2acSAugustin Cavalier 		if (status != B_OK)
95*66c7a2acSAugustin Cavalier 			return status;
96*66c7a2acSAugustin Cavalier 	}
97*66c7a2acSAugustin Cavalier 
98*66c7a2acSAugustin Cavalier 	return SetPath(path, flags);
99*66c7a2acSAugustin Cavalier }
100*66c7a2acSAugustin Cavalier 
101*66c7a2acSAugustin Cavalier 
102*66c7a2acSAugustin Cavalier void
Adopt(KPath & other)103*66c7a2acSAugustin Cavalier KPath::Adopt(KPath& other)
104*66c7a2acSAugustin Cavalier {
105*66c7a2acSAugustin Cavalier 	free(fBuffer);
106*66c7a2acSAugustin Cavalier 
107*66c7a2acSAugustin Cavalier 	fBuffer = other.fBuffer;
108*66c7a2acSAugustin Cavalier 	fBufferSize = other.fBufferSize;
109*66c7a2acSAugustin Cavalier 	fPathLength = other.fPathLength;
110*66c7a2acSAugustin Cavalier 	fLazy = other.fLazy;
111*66c7a2acSAugustin Cavalier 	fFailed = other.fFailed;
112*66c7a2acSAugustin Cavalier 	fIsNull = other.fIsNull;
113*66c7a2acSAugustin Cavalier 
114*66c7a2acSAugustin Cavalier 	other.fBuffer = NULL;
115*66c7a2acSAugustin Cavalier 	if (!other.fLazy)
116*66c7a2acSAugustin Cavalier 		other.fBufferSize = 0;
117*66c7a2acSAugustin Cavalier 	other.fPathLength = 0;
118*66c7a2acSAugustin Cavalier 	other.fFailed = false;
119*66c7a2acSAugustin Cavalier 	other.fIsNull = other.fLazy;
120*66c7a2acSAugustin Cavalier }
121*66c7a2acSAugustin Cavalier 
122*66c7a2acSAugustin Cavalier 
123*66c7a2acSAugustin Cavalier status_t
InitCheck() const124*66c7a2acSAugustin Cavalier KPath::InitCheck() const
125*66c7a2acSAugustin Cavalier {
126*66c7a2acSAugustin Cavalier 	if (fBuffer != NULL || (fLazy && !fFailed && fBufferSize != 0))
127*66c7a2acSAugustin Cavalier 		return B_OK;
128*66c7a2acSAugustin Cavalier 
129*66c7a2acSAugustin Cavalier 	return fFailed ? B_NO_MEMORY : B_NO_INIT;
130*66c7a2acSAugustin Cavalier }
131*66c7a2acSAugustin Cavalier 
132*66c7a2acSAugustin Cavalier 
133*66c7a2acSAugustin Cavalier /*!	\brief Sets the buffer to \a path.
134*66c7a2acSAugustin Cavalier 
135*66c7a2acSAugustin Cavalier 	\param flags Understands the following two options:
136*66c7a2acSAugustin Cavalier 		- \c NORMALIZE
137*66c7a2acSAugustin Cavalier 		- \c TRAVERSE_LEAF_LINK
138*66c7a2acSAugustin Cavalier */
139*66c7a2acSAugustin Cavalier status_t
SetPath(const char * path,int32 flags)140*66c7a2acSAugustin Cavalier KPath::SetPath(const char* path, int32 flags)
141*66c7a2acSAugustin Cavalier {
142*66c7a2acSAugustin Cavalier 	if (path == NULL && fLazy && fBuffer == NULL) {
143*66c7a2acSAugustin Cavalier 		fIsNull = true;
144*66c7a2acSAugustin Cavalier 		return B_OK;
145*66c7a2acSAugustin Cavalier 	}
146*66c7a2acSAugustin Cavalier 
147*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL) {
148*66c7a2acSAugustin Cavalier 		if (fLazy) {
149*66c7a2acSAugustin Cavalier 			status_t status = _AllocateBuffer();
150*66c7a2acSAugustin Cavalier 			if (status != B_OK)
151*66c7a2acSAugustin Cavalier 				return B_NO_MEMORY;
152*66c7a2acSAugustin Cavalier 		} else
153*66c7a2acSAugustin Cavalier 			return B_NO_INIT;
154*66c7a2acSAugustin Cavalier 	}
155*66c7a2acSAugustin Cavalier 
156*66c7a2acSAugustin Cavalier 	fIsNull = false;
157*66c7a2acSAugustin Cavalier 
158*66c7a2acSAugustin Cavalier 	if (path != NULL) {
159*66c7a2acSAugustin Cavalier 		if ((flags & NORMALIZE) != 0) {
160*66c7a2acSAugustin Cavalier 			// normalize path
161*66c7a2acSAugustin Cavalier 			status_t status = _Normalize(path,
162*66c7a2acSAugustin Cavalier 				(flags & TRAVERSE_LEAF_LINK) != 0);
163*66c7a2acSAugustin Cavalier 			if (status != B_OK)
164*66c7a2acSAugustin Cavalier 				return status;
165*66c7a2acSAugustin Cavalier 		} else {
166*66c7a2acSAugustin Cavalier 			// don't normalize path
167*66c7a2acSAugustin Cavalier 			size_t length = strlen(path);
168*66c7a2acSAugustin Cavalier 			if (length >= fBufferSize)
169*66c7a2acSAugustin Cavalier 				return B_BUFFER_OVERFLOW;
170*66c7a2acSAugustin Cavalier 
171*66c7a2acSAugustin Cavalier 			memcpy(fBuffer, path, length + 1);
172*66c7a2acSAugustin Cavalier 			fPathLength = length;
173*66c7a2acSAugustin Cavalier 			_ChopTrailingSlashes();
174*66c7a2acSAugustin Cavalier 		}
175*66c7a2acSAugustin Cavalier 	} else {
176*66c7a2acSAugustin Cavalier 		fBuffer[0] = '\0';
177*66c7a2acSAugustin Cavalier 		fPathLength = 0;
178*66c7a2acSAugustin Cavalier 		if (fLazy)
179*66c7a2acSAugustin Cavalier 			fIsNull = true;
180*66c7a2acSAugustin Cavalier 	}
181*66c7a2acSAugustin Cavalier 	return B_OK;
182*66c7a2acSAugustin Cavalier }
183*66c7a2acSAugustin Cavalier 
184*66c7a2acSAugustin Cavalier 
185*66c7a2acSAugustin Cavalier const char*
Path() const186*66c7a2acSAugustin Cavalier KPath::Path() const
187*66c7a2acSAugustin Cavalier {
188*66c7a2acSAugustin Cavalier 	return fIsNull ? NULL : fBuffer;
189*66c7a2acSAugustin Cavalier }
190*66c7a2acSAugustin Cavalier 
191*66c7a2acSAugustin Cavalier 
192*66c7a2acSAugustin Cavalier /*!	\brief Locks the buffer for external changes.
193*66c7a2acSAugustin Cavalier 
194*66c7a2acSAugustin Cavalier 	\param force In lazy mode, this will allocate a buffer when set.
195*66c7a2acSAugustin Cavalier 		Otherwise, \c NULL will be returned if set to NULL.
196*66c7a2acSAugustin Cavalier */
197*66c7a2acSAugustin Cavalier char*
LockBuffer(bool force)198*66c7a2acSAugustin Cavalier KPath::LockBuffer(bool force)
199*66c7a2acSAugustin Cavalier {
200*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL && fLazy) {
201*66c7a2acSAugustin Cavalier 		if (fIsNull && !force)
202*66c7a2acSAugustin Cavalier 			return NULL;
203*66c7a2acSAugustin Cavalier 
204*66c7a2acSAugustin Cavalier 		_AllocateBuffer();
205*66c7a2acSAugustin Cavalier 	}
206*66c7a2acSAugustin Cavalier 
207*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL || fLocked)
208*66c7a2acSAugustin Cavalier 		return NULL;
209*66c7a2acSAugustin Cavalier 
210*66c7a2acSAugustin Cavalier 	fLocked = true;
211*66c7a2acSAugustin Cavalier 	fIsNull = false;
212*66c7a2acSAugustin Cavalier 
213*66c7a2acSAugustin Cavalier 	return fBuffer;
214*66c7a2acSAugustin Cavalier }
215*66c7a2acSAugustin Cavalier 
216*66c7a2acSAugustin Cavalier 
217*66c7a2acSAugustin Cavalier void
UnlockBuffer()218*66c7a2acSAugustin Cavalier KPath::UnlockBuffer()
219*66c7a2acSAugustin Cavalier {
220*66c7a2acSAugustin Cavalier 	if (!fLocked) {
221*66c7a2acSAugustin Cavalier 		TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n"));
222*66c7a2acSAugustin Cavalier 		return;
223*66c7a2acSAugustin Cavalier 	}
224*66c7a2acSAugustin Cavalier 
225*66c7a2acSAugustin Cavalier 	fLocked = false;
226*66c7a2acSAugustin Cavalier 
227*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL)
228*66c7a2acSAugustin Cavalier 		return;
229*66c7a2acSAugustin Cavalier 
230*66c7a2acSAugustin Cavalier 	fPathLength = strnlen(fBuffer, fBufferSize);
231*66c7a2acSAugustin Cavalier 	if (fPathLength == fBufferSize) {
232*66c7a2acSAugustin Cavalier 		TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n"));
233*66c7a2acSAugustin Cavalier 		fPathLength--;
234*66c7a2acSAugustin Cavalier 		fBuffer[fPathLength] = '\0';
235*66c7a2acSAugustin Cavalier 	}
236*66c7a2acSAugustin Cavalier 	_ChopTrailingSlashes();
237*66c7a2acSAugustin Cavalier }
238*66c7a2acSAugustin Cavalier 
239*66c7a2acSAugustin Cavalier 
240*66c7a2acSAugustin Cavalier char*
DetachBuffer()241*66c7a2acSAugustin Cavalier KPath::DetachBuffer()
242*66c7a2acSAugustin Cavalier {
243*66c7a2acSAugustin Cavalier 	char* buffer = fBuffer;
244*66c7a2acSAugustin Cavalier 
245*66c7a2acSAugustin Cavalier 	if (fBuffer != NULL) {
246*66c7a2acSAugustin Cavalier 		fBuffer = NULL;
247*66c7a2acSAugustin Cavalier 		fPathLength = 0;
248*66c7a2acSAugustin Cavalier 		fLocked = false;
249*66c7a2acSAugustin Cavalier 	}
250*66c7a2acSAugustin Cavalier 
251*66c7a2acSAugustin Cavalier 	return buffer;
252*66c7a2acSAugustin Cavalier }
253*66c7a2acSAugustin Cavalier 
254*66c7a2acSAugustin Cavalier 
255*66c7a2acSAugustin Cavalier const char*
Leaf() const256*66c7a2acSAugustin Cavalier KPath::Leaf() const
257*66c7a2acSAugustin Cavalier {
258*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL)
259*66c7a2acSAugustin Cavalier 		return NULL;
260*66c7a2acSAugustin Cavalier 
261*66c7a2acSAugustin Cavalier 	for (int32 i = fPathLength - 1; i >= 0; i--) {
262*66c7a2acSAugustin Cavalier 		if (fBuffer[i] == '/')
263*66c7a2acSAugustin Cavalier 			return fBuffer + i + 1;
264*66c7a2acSAugustin Cavalier 	}
265*66c7a2acSAugustin Cavalier 
266*66c7a2acSAugustin Cavalier 	return fBuffer;
267*66c7a2acSAugustin Cavalier }
268*66c7a2acSAugustin Cavalier 
269*66c7a2acSAugustin Cavalier 
270*66c7a2acSAugustin Cavalier status_t
ReplaceLeaf(const char * newLeaf)271*66c7a2acSAugustin Cavalier KPath::ReplaceLeaf(const char* newLeaf)
272*66c7a2acSAugustin Cavalier {
273*66c7a2acSAugustin Cavalier 	const char* leaf = Leaf();
274*66c7a2acSAugustin Cavalier 	if (leaf == NULL)
275*66c7a2acSAugustin Cavalier 		return B_NO_INIT;
276*66c7a2acSAugustin Cavalier 
277*66c7a2acSAugustin Cavalier 	int32 leafIndex = leaf - fBuffer;
278*66c7a2acSAugustin Cavalier 	// chop off the current leaf (don't replace "/", though)
279*66c7a2acSAugustin Cavalier 	if (leafIndex != 0 || fBuffer[leafIndex - 1]) {
280*66c7a2acSAugustin Cavalier 		fBuffer[leafIndex] = '\0';
281*66c7a2acSAugustin Cavalier 		fPathLength = leafIndex;
282*66c7a2acSAugustin Cavalier 		_ChopTrailingSlashes();
283*66c7a2acSAugustin Cavalier 	}
284*66c7a2acSAugustin Cavalier 
285*66c7a2acSAugustin Cavalier 	// if a leaf was given, append it
286*66c7a2acSAugustin Cavalier 	if (newLeaf != NULL)
287*66c7a2acSAugustin Cavalier 		return Append(newLeaf);
288*66c7a2acSAugustin Cavalier 	return B_OK;
289*66c7a2acSAugustin Cavalier }
290*66c7a2acSAugustin Cavalier 
291*66c7a2acSAugustin Cavalier 
292*66c7a2acSAugustin Cavalier bool
RemoveLeaf()293*66c7a2acSAugustin Cavalier KPath::RemoveLeaf()
294*66c7a2acSAugustin Cavalier {
295*66c7a2acSAugustin Cavalier 	// get the leaf -- bail out, if not initialized or only the "/" is left
296*66c7a2acSAugustin Cavalier 	const char* leaf = Leaf();
297*66c7a2acSAugustin Cavalier 	if (leaf == NULL || leaf == fBuffer || leaf[0] == '\0')
298*66c7a2acSAugustin Cavalier 		return false;
299*66c7a2acSAugustin Cavalier 
300*66c7a2acSAugustin Cavalier 	// chop off the leaf
301*66c7a2acSAugustin Cavalier 	int32 leafIndex = leaf - fBuffer;
302*66c7a2acSAugustin Cavalier 	fBuffer[leafIndex] = '\0';
303*66c7a2acSAugustin Cavalier 	fPathLength = leafIndex;
304*66c7a2acSAugustin Cavalier 	_ChopTrailingSlashes();
305*66c7a2acSAugustin Cavalier 
306*66c7a2acSAugustin Cavalier 	return true;
307*66c7a2acSAugustin Cavalier }
308*66c7a2acSAugustin Cavalier 
309*66c7a2acSAugustin Cavalier 
310*66c7a2acSAugustin Cavalier status_t
Append(const char * component,bool isComponent)311*66c7a2acSAugustin Cavalier KPath::Append(const char* component, bool isComponent)
312*66c7a2acSAugustin Cavalier {
313*66c7a2acSAugustin Cavalier 	// check initialization and parameter
314*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL)
315*66c7a2acSAugustin Cavalier 		return B_NO_INIT;
316*66c7a2acSAugustin Cavalier 	if (component == NULL)
317*66c7a2acSAugustin Cavalier 		return B_BAD_VALUE;
318*66c7a2acSAugustin Cavalier 	if (fPathLength == 0)
319*66c7a2acSAugustin Cavalier 		return SetPath(component);
320*66c7a2acSAugustin Cavalier 
321*66c7a2acSAugustin Cavalier 	// get component length
322*66c7a2acSAugustin Cavalier 	size_t componentLength = strlen(component);
323*66c7a2acSAugustin Cavalier 	if (componentLength < 1)
324*66c7a2acSAugustin Cavalier 		return B_OK;
325*66c7a2acSAugustin Cavalier 
326*66c7a2acSAugustin Cavalier 	// if our current path is empty, we just copy the supplied one
327*66c7a2acSAugustin Cavalier 	// compute the result path len
328*66c7a2acSAugustin Cavalier 	bool insertSlash = isComponent && fBuffer[fPathLength - 1] != '/'
329*66c7a2acSAugustin Cavalier 		&& component[0] != '/';
330*66c7a2acSAugustin Cavalier 	size_t resultPathLength = fPathLength + componentLength
331*66c7a2acSAugustin Cavalier 		+ (insertSlash ? 1 : 0);
332*66c7a2acSAugustin Cavalier 	if (resultPathLength >= fBufferSize)
333*66c7a2acSAugustin Cavalier 		return B_BUFFER_OVERFLOW;
334*66c7a2acSAugustin Cavalier 
335*66c7a2acSAugustin Cavalier 	// compose the result path
336*66c7a2acSAugustin Cavalier 	if (insertSlash)
337*66c7a2acSAugustin Cavalier 		fBuffer[fPathLength++] = '/';
338*66c7a2acSAugustin Cavalier 	memcpy(fBuffer + fPathLength, component, componentLength + 1);
339*66c7a2acSAugustin Cavalier 	fPathLength = resultPathLength;
340*66c7a2acSAugustin Cavalier 	return B_OK;
341*66c7a2acSAugustin Cavalier }
342*66c7a2acSAugustin Cavalier 
343*66c7a2acSAugustin Cavalier 
344*66c7a2acSAugustin Cavalier status_t
Normalize(bool traverseLeafLink)345*66c7a2acSAugustin Cavalier KPath::Normalize(bool traverseLeafLink)
346*66c7a2acSAugustin Cavalier {
347*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL)
348*66c7a2acSAugustin Cavalier 		return B_NO_INIT;
349*66c7a2acSAugustin Cavalier 	if (fPathLength == 0)
350*66c7a2acSAugustin Cavalier 		return B_BAD_VALUE;
351*66c7a2acSAugustin Cavalier 
352*66c7a2acSAugustin Cavalier 	return _Normalize(fBuffer, traverseLeafLink);
353*66c7a2acSAugustin Cavalier }
354*66c7a2acSAugustin Cavalier 
355*66c7a2acSAugustin Cavalier 
356*66c7a2acSAugustin Cavalier KPath&
operator =(const KPath & other)357*66c7a2acSAugustin Cavalier KPath::operator=(const KPath& other)
358*66c7a2acSAugustin Cavalier {
359*66c7a2acSAugustin Cavalier 	SetTo(other.fBuffer, fLazy ? KPath::LAZY_ALLOC : KPath::DEFAULT,
360*66c7a2acSAugustin Cavalier 		other.fBufferSize);
361*66c7a2acSAugustin Cavalier 	return *this;
362*66c7a2acSAugustin Cavalier }
363*66c7a2acSAugustin Cavalier 
364*66c7a2acSAugustin Cavalier 
365*66c7a2acSAugustin Cavalier KPath&
operator =(const char * path)366*66c7a2acSAugustin Cavalier KPath::operator=(const char* path)
367*66c7a2acSAugustin Cavalier {
368*66c7a2acSAugustin Cavalier 	SetPath(path);
369*66c7a2acSAugustin Cavalier 	return *this;
370*66c7a2acSAugustin Cavalier }
371*66c7a2acSAugustin Cavalier 
372*66c7a2acSAugustin Cavalier 
373*66c7a2acSAugustin Cavalier bool
operator ==(const KPath & other) const374*66c7a2acSAugustin Cavalier KPath::operator==(const KPath& other) const
375*66c7a2acSAugustin Cavalier {
376*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL)
377*66c7a2acSAugustin Cavalier 		return !other.fBuffer;
378*66c7a2acSAugustin Cavalier 
379*66c7a2acSAugustin Cavalier 	return other.fBuffer != NULL
380*66c7a2acSAugustin Cavalier 		&& fPathLength == other.fPathLength
381*66c7a2acSAugustin Cavalier 		&& strcmp(fBuffer, other.fBuffer) == 0;
382*66c7a2acSAugustin Cavalier }
383*66c7a2acSAugustin Cavalier 
384*66c7a2acSAugustin Cavalier 
385*66c7a2acSAugustin Cavalier bool
operator ==(const char * path) const386*66c7a2acSAugustin Cavalier KPath::operator==(const char* path) const
387*66c7a2acSAugustin Cavalier {
388*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL)
389*66c7a2acSAugustin Cavalier 		return path == NULL;
390*66c7a2acSAugustin Cavalier 
391*66c7a2acSAugustin Cavalier 	return path != NULL && strcmp(fBuffer, path) == 0;
392*66c7a2acSAugustin Cavalier }
393*66c7a2acSAugustin Cavalier 
394*66c7a2acSAugustin Cavalier 
395*66c7a2acSAugustin Cavalier bool
operator !=(const KPath & other) const396*66c7a2acSAugustin Cavalier KPath::operator!=(const KPath& other) const
397*66c7a2acSAugustin Cavalier {
398*66c7a2acSAugustin Cavalier 	return !(*this == other);
399*66c7a2acSAugustin Cavalier }
400*66c7a2acSAugustin Cavalier 
401*66c7a2acSAugustin Cavalier 
402*66c7a2acSAugustin Cavalier bool
operator !=(const char * path) const403*66c7a2acSAugustin Cavalier KPath::operator!=(const char* path) const
404*66c7a2acSAugustin Cavalier {
405*66c7a2acSAugustin Cavalier 	return !(*this == path);
406*66c7a2acSAugustin Cavalier }
407*66c7a2acSAugustin Cavalier 
408*66c7a2acSAugustin Cavalier 
409*66c7a2acSAugustin Cavalier status_t
_AllocateBuffer()410*66c7a2acSAugustin Cavalier KPath::_AllocateBuffer()
411*66c7a2acSAugustin Cavalier {
412*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL && fBufferSize != 0)
413*66c7a2acSAugustin Cavalier 		fBuffer = (char*)malloc(fBufferSize);
414*66c7a2acSAugustin Cavalier 	if (fBuffer == NULL) {
415*66c7a2acSAugustin Cavalier 		fFailed = true;
416*66c7a2acSAugustin Cavalier 		return B_NO_MEMORY;
417*66c7a2acSAugustin Cavalier 	}
418*66c7a2acSAugustin Cavalier 
419*66c7a2acSAugustin Cavalier 	fBuffer[0] = '\0';
420*66c7a2acSAugustin Cavalier 	fFailed = false;
421*66c7a2acSAugustin Cavalier 	return B_OK;
422*66c7a2acSAugustin Cavalier }
423*66c7a2acSAugustin Cavalier 
424*66c7a2acSAugustin Cavalier 
425*66c7a2acSAugustin Cavalier status_t
_Normalize(const char * path,bool traverseLeafLink)426*66c7a2acSAugustin Cavalier KPath::_Normalize(const char* path, bool traverseLeafLink)
427*66c7a2acSAugustin Cavalier {
428*66c7a2acSAugustin Cavalier 	BPath normalizedPath;
429*66c7a2acSAugustin Cavalier 	status_t error = normalizedPath.SetTo(path, NULL, true);
430*66c7a2acSAugustin Cavalier 	if (error != B_OK) {
431*66c7a2acSAugustin Cavalier 		fBuffer[0] = '\0';
432*66c7a2acSAugustin Cavalier 		fPathLength = 0;
433*66c7a2acSAugustin Cavalier 		return error;
434*66c7a2acSAugustin Cavalier 	}
435*66c7a2acSAugustin Cavalier 
436*66c7a2acSAugustin Cavalier 	strlcpy(fBuffer, normalizedPath.Path(), fBufferSize);
437*66c7a2acSAugustin Cavalier 	fPathLength = strlen(fBuffer);
438*66c7a2acSAugustin Cavalier 	return B_OK;
439*66c7a2acSAugustin Cavalier }
440*66c7a2acSAugustin Cavalier 
441*66c7a2acSAugustin Cavalier 
442*66c7a2acSAugustin Cavalier void
_ChopTrailingSlashes()443*66c7a2acSAugustin Cavalier KPath::_ChopTrailingSlashes()
444*66c7a2acSAugustin Cavalier {
445*66c7a2acSAugustin Cavalier 	if (fBuffer != NULL) {
446*66c7a2acSAugustin Cavalier 		while (fPathLength > 1 && fBuffer[fPathLength - 1] == '/')
447*66c7a2acSAugustin Cavalier 			fBuffer[--fPathLength] = '\0';
448*66c7a2acSAugustin Cavalier 	}
449*66c7a2acSAugustin Cavalier }
450*66c7a2acSAugustin Cavalier 
451