xref: /haiku/src/system/kernel/fs/KPath.cpp (revision a07f133e5b6be3881ce0beacc3333629b0d9dbd8)
10d4c16e0SAxel Dörfler /*
2e8d3eff9SIngo Weinhold  * Copyright 2004-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3e1b4aed0SAxel Dörfler  * Copyright 2008-2017, Axel Dörfler, axeld@pinc-software.de.
40d4c16e0SAxel Dörfler  * Distributed under the terms of the MIT License.
50d4c16e0SAxel Dörfler  */
62d690920SAxel Dörfler 
73582d4feSAxel Dörfler 
83582d4feSAxel Dörfler /*! A simple class wrapping a path. Has a fixed-sized buffer. */
93582d4feSAxel Dörfler 
102d690920SAxel Dörfler 
1123a60f42SAxel Dörfler #include <fs/KPath.h>
122d690920SAxel Dörfler 
130d4c16e0SAxel Dörfler #include <stdlib.h>
140d4c16e0SAxel Dörfler #include <string.h>
152d690920SAxel Dörfler 
1623a60f42SAxel Dörfler #include <team.h>
1723a60f42SAxel Dörfler #include <vfs.h>
1823a60f42SAxel Dörfler 
190d4c16e0SAxel Dörfler 
200d4c16e0SAxel Dörfler // debugging
210d4c16e0SAxel Dörfler #define TRACE(x) ;
220d4c16e0SAxel Dörfler //#define TRACE(x) dprintf x
230d4c16e0SAxel Dörfler 
240d4c16e0SAxel Dörfler 
250d4c16e0SAxel Dörfler KPath::KPath(size_t bufferSize)
260d4c16e0SAxel Dörfler 	:
270d4c16e0SAxel Dörfler 	fBuffer(NULL),
282d690920SAxel Dörfler 	fBufferSize(0),
292d690920SAxel Dörfler 	fPathLength(0),
30e9843da3SAxel Dörfler 	fLocked(false),
31e9843da3SAxel Dörfler 	fLazy(false),
32e9843da3SAxel Dörfler 	fFailed(false),
33e9843da3SAxel Dörfler 	fIsNull(false)
342d690920SAxel Dörfler {
35e9843da3SAxel Dörfler 	SetTo(NULL, DEFAULT, bufferSize);
362d690920SAxel Dörfler }
372d690920SAxel Dörfler 
380d4c16e0SAxel Dörfler 
39eac83fb3SAxel Dörfler KPath::KPath(const char* path, int32 flags, size_t bufferSize)
400d4c16e0SAxel Dörfler 	:
410d4c16e0SAxel Dörfler 	fBuffer(NULL),
422d690920SAxel Dörfler 	fBufferSize(0),
432d690920SAxel Dörfler 	fPathLength(0),
44e9843da3SAxel Dörfler 	fLocked(false),
45e9843da3SAxel Dörfler 	fLazy(false),
46e9843da3SAxel Dörfler 	fFailed(false),
47e9843da3SAxel Dörfler 	fIsNull(false)
482d690920SAxel Dörfler {
49eac83fb3SAxel Dörfler 	SetTo(path, flags, bufferSize);
502d690920SAxel Dörfler }
512d690920SAxel Dörfler 
520d4c16e0SAxel Dörfler 
532d690920SAxel Dörfler KPath::KPath(const KPath& other)
540d4c16e0SAxel Dörfler 	:
550d4c16e0SAxel Dörfler 	fBuffer(NULL),
562d690920SAxel Dörfler 	fBufferSize(0),
572d690920SAxel Dörfler 	fPathLength(0),
58e9843da3SAxel Dörfler 	fLocked(false),
59e9843da3SAxel Dörfler 	fLazy(false),
60e9843da3SAxel Dörfler 	fFailed(false),
61e9843da3SAxel Dörfler 	fIsNull(false)
622d690920SAxel Dörfler {
632d690920SAxel Dörfler 	*this = other;
642d690920SAxel Dörfler }
652d690920SAxel Dörfler 
660d4c16e0SAxel Dörfler 
672d690920SAxel Dörfler KPath::~KPath()
682d690920SAxel Dörfler {
692d690920SAxel Dörfler 	free(fBuffer);
702d690920SAxel Dörfler }
712d690920SAxel Dörfler 
720d4c16e0SAxel Dörfler 
732d690920SAxel Dörfler status_t
74eac83fb3SAxel Dörfler KPath::SetTo(const char* path, int32 flags, size_t bufferSize)
752d690920SAxel Dörfler {
760d4c16e0SAxel Dörfler 	if (bufferSize == 0)
772d690920SAxel Dörfler 		bufferSize = B_PATH_NAME_LENGTH;
780d4c16e0SAxel Dörfler 
792d690920SAxel Dörfler 	// free the previous buffer, if the buffer size differs
803582d4feSAxel Dörfler 	if (fBuffer != NULL && fBufferSize != bufferSize) {
812d690920SAxel Dörfler 		free(fBuffer);
822d690920SAxel Dörfler 		fBuffer = NULL;
832d690920SAxel Dörfler 		fBufferSize = 0;
842d690920SAxel Dörfler 	}
85e9843da3SAxel Dörfler 
862d690920SAxel Dörfler 	fPathLength = 0;
872d690920SAxel Dörfler 	fLocked = false;
882d690920SAxel Dörfler 	fBufferSize = bufferSize;
89e9843da3SAxel Dörfler 	fLazy = (flags & LAZY_ALLOC) != 0;
90e9843da3SAxel Dörfler 	fIsNull = path == NULL;
91e9843da3SAxel Dörfler 
92e9843da3SAxel Dörfler 	if (path != NULL || !fLazy) {
93e9843da3SAxel Dörfler 		status_t status = _AllocateBuffer();
94e9843da3SAxel Dörfler 		if (status != B_OK)
95e9843da3SAxel Dörfler 			return status;
96e9843da3SAxel Dörfler 	}
973582d4feSAxel Dörfler 
98eac83fb3SAxel Dörfler 	return SetPath(path, flags);
992d690920SAxel Dörfler }
1002d690920SAxel Dörfler 
1010d4c16e0SAxel Dörfler 
10256bbbbc9SAxel Dörfler void
10356bbbbc9SAxel Dörfler KPath::Adopt(KPath& other)
10456bbbbc9SAxel Dörfler {
10556bbbbc9SAxel Dörfler 	free(fBuffer);
10656bbbbc9SAxel Dörfler 
10756bbbbc9SAxel Dörfler 	fBuffer = other.fBuffer;
10856bbbbc9SAxel Dörfler 	fBufferSize = other.fBufferSize;
109f94671c3SAxel Dörfler 	fPathLength = other.fPathLength;
110e9843da3SAxel Dörfler 	fLazy = other.fLazy;
111e9843da3SAxel Dörfler 	fFailed = other.fFailed;
112e9843da3SAxel Dörfler 	fIsNull = other.fIsNull;
11356bbbbc9SAxel Dörfler 
11456bbbbc9SAxel Dörfler 	other.fBuffer = NULL;
115e9843da3SAxel Dörfler 	if (!other.fLazy)
1164be51875SAxel Dörfler 		other.fBufferSize = 0;
1174be51875SAxel Dörfler 	other.fPathLength = 0;
118e9843da3SAxel Dörfler 	other.fFailed = false;
119e9843da3SAxel Dörfler 	other.fIsNull = other.fLazy;
12056bbbbc9SAxel Dörfler }
12156bbbbc9SAxel Dörfler 
12256bbbbc9SAxel Dörfler 
1232d690920SAxel Dörfler status_t
1242d690920SAxel Dörfler KPath::InitCheck() const
1252d690920SAxel Dörfler {
126655aae6aSAxel Dörfler 	if (fBuffer != NULL || (fLazy && !fFailed && fBufferSize != 0))
127e9843da3SAxel Dörfler 		return B_OK;
128e9843da3SAxel Dörfler 
129e9843da3SAxel Dörfler 	return fFailed ? B_NO_MEMORY : B_NO_INIT;
1302d690920SAxel Dörfler }
1312d690920SAxel Dörfler 
1320d4c16e0SAxel Dörfler 
133e9843da3SAxel Dörfler /*!	\brief Sets the buffer to \a path.
134e9843da3SAxel Dörfler 
135e9843da3SAxel Dörfler 	\param flags Understands the following two options:
136e9843da3SAxel Dörfler 		- \c NORMALIZE
137e9843da3SAxel Dörfler 		- \c TRAVERSE_LEAF_LINK
138e9843da3SAxel Dörfler */
1392d690920SAxel Dörfler status_t
140eac83fb3SAxel Dörfler KPath::SetPath(const char* path, int32 flags)
1412d690920SAxel Dörfler {
142e9843da3SAxel Dörfler 	if (path == NULL && fLazy && fBuffer == NULL) {
143e9843da3SAxel Dörfler 		fIsNull = true;
144e9843da3SAxel Dörfler 		return B_OK;
145e9843da3SAxel Dörfler 	}
146e9843da3SAxel Dörfler 
147e9843da3SAxel Dörfler 	if (fBuffer == NULL) {
148e9843da3SAxel Dörfler 		if (fLazy) {
149e9843da3SAxel Dörfler 			status_t status = _AllocateBuffer();
150e9843da3SAxel Dörfler 			if (status != B_OK)
151e9843da3SAxel Dörfler 				return B_NO_MEMORY;
152e9843da3SAxel Dörfler 		} else
1532d690920SAxel Dörfler 			return B_NO_INIT;
154e9843da3SAxel Dörfler 	}
155e9843da3SAxel Dörfler 
156e9843da3SAxel Dörfler 	fIsNull = false;
1570d4c16e0SAxel Dörfler 
1589abf4591Sczeidler 	if (path != NULL) {
159eac83fb3SAxel Dörfler 		if ((flags & NORMALIZE) != 0) {
1602d690920SAxel Dörfler 			// normalize path
161e9843da3SAxel Dörfler 			status_t status = _Normalize(path,
162e9843da3SAxel Dörfler 				(flags & TRAVERSE_LEAF_LINK) != 0);
163e9843da3SAxel Dörfler 			if (status != B_OK)
164e9843da3SAxel Dörfler 				return status;
1652d690920SAxel Dörfler 		} else {
1662d690920SAxel Dörfler 			// don't normalize path
1670d4c16e0SAxel Dörfler 			size_t length = strlen(path);
1680d4c16e0SAxel Dörfler 			if (length >= fBufferSize)
1692d690920SAxel Dörfler 				return B_BUFFER_OVERFLOW;
1700d4c16e0SAxel Dörfler 
1710d4c16e0SAxel Dörfler 			memcpy(fBuffer, path, length + 1);
1720d4c16e0SAxel Dörfler 			fPathLength = length;
1732d690920SAxel Dörfler 			_ChopTrailingSlashes();
1742d690920SAxel Dörfler 		}
1752d690920SAxel Dörfler 	} else {
1762d690920SAxel Dörfler 		fBuffer[0] = '\0';
1772d690920SAxel Dörfler 		fPathLength = 0;
178e9843da3SAxel Dörfler 		if (fLazy)
179e9843da3SAxel Dörfler 			fIsNull = true;
1802d690920SAxel Dörfler 	}
1812d690920SAxel Dörfler 	return B_OK;
1822d690920SAxel Dörfler }
1832d690920SAxel Dörfler 
1840d4c16e0SAxel Dörfler 
1852d690920SAxel Dörfler const char*
1862d690920SAxel Dörfler KPath::Path() const
1872d690920SAxel Dörfler {
188e9843da3SAxel Dörfler 	return fIsNull ? NULL : fBuffer;
1892d690920SAxel Dörfler }
1902d690920SAxel Dörfler 
1912d690920SAxel Dörfler 
192e9843da3SAxel Dörfler /*!	\brief Locks the buffer for external changes.
193e9843da3SAxel Dörfler 
194e9843da3SAxel Dörfler 	\param force In lazy mode, this will allocate a buffer when set.
195e9843da3SAxel Dörfler 		Otherwise, \c NULL will be returned if set to NULL.
196e9843da3SAxel Dörfler */
1972d690920SAxel Dörfler char*
198e9843da3SAxel Dörfler KPath::LockBuffer(bool force)
1992d690920SAxel Dörfler {
200e9843da3SAxel Dörfler 	if (fBuffer == NULL && fLazy) {
201e9843da3SAxel Dörfler 		if (fIsNull && !force)
202e9843da3SAxel Dörfler 			return NULL;
203e9843da3SAxel Dörfler 
204e9843da3SAxel Dörfler 		_AllocateBuffer();
205e9843da3SAxel Dörfler 	}
206e9843da3SAxel Dörfler 
2079abf4591Sczeidler 	if (fBuffer == NULL || fLocked)
2082d690920SAxel Dörfler 		return NULL;
2090d4c16e0SAxel Dörfler 
2102d690920SAxel Dörfler 	fLocked = true;
211e9843da3SAxel Dörfler 	fIsNull = false;
212e9843da3SAxel Dörfler 
2132d690920SAxel Dörfler 	return fBuffer;
2142d690920SAxel Dörfler }
2152d690920SAxel Dörfler 
2160d4c16e0SAxel Dörfler 
2172d690920SAxel Dörfler void
2182d690920SAxel Dörfler KPath::UnlockBuffer()
2192d690920SAxel Dörfler {
2202d690920SAxel Dörfler 	if (!fLocked) {
2210d4c16e0SAxel Dörfler 		TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n"));
2222d690920SAxel Dörfler 		return;
2232d690920SAxel Dörfler 	}
224e9843da3SAxel Dörfler 
2252d690920SAxel Dörfler 	fLocked = false;
226e9843da3SAxel Dörfler 
227e9843da3SAxel Dörfler 	if (fBuffer == NULL)
228e9843da3SAxel Dörfler 		return;
229e9843da3SAxel Dörfler 
2302d690920SAxel Dörfler 	fPathLength = strnlen(fBuffer, fBufferSize);
2312d690920SAxel Dörfler 	if (fPathLength == fBufferSize) {
2320d4c16e0SAxel Dörfler 		TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n"));
2332d690920SAxel Dörfler 		fPathLength--;
2342d690920SAxel Dörfler 		fBuffer[fPathLength] = '\0';
2352d690920SAxel Dörfler 	}
2362d690920SAxel Dörfler 	_ChopTrailingSlashes();
2372d690920SAxel Dörfler }
2382d690920SAxel Dörfler 
2390d4c16e0SAxel Dörfler 
240e8d3eff9SIngo Weinhold char*
241e8d3eff9SIngo Weinhold KPath::DetachBuffer()
242e8d3eff9SIngo Weinhold {
243e8d3eff9SIngo Weinhold 	char* buffer = fBuffer;
244e8d3eff9SIngo Weinhold 
245e8d3eff9SIngo Weinhold 	if (fBuffer != NULL) {
246e8d3eff9SIngo Weinhold 		fBuffer = NULL;
247e8d3eff9SIngo Weinhold 		fPathLength = 0;
248e8d3eff9SIngo Weinhold 		fLocked = false;
249e8d3eff9SIngo Weinhold 	}
250e8d3eff9SIngo Weinhold 
251e8d3eff9SIngo Weinhold 	return buffer;
252e8d3eff9SIngo Weinhold }
253e8d3eff9SIngo Weinhold 
254e8d3eff9SIngo Weinhold 
2552d690920SAxel Dörfler const char*
2562d690920SAxel Dörfler KPath::Leaf() const
2572d690920SAxel Dörfler {
2583582d4feSAxel Dörfler 	if (fBuffer == NULL)
2592d690920SAxel Dörfler 		return NULL;
2600d4c16e0SAxel Dörfler 
2612d690920SAxel Dörfler 	for (int32 i = fPathLength - 1; i >= 0; i--) {
2622d690920SAxel Dörfler 		if (fBuffer[i] == '/')
2632d690920SAxel Dörfler 			return fBuffer + i + 1;
2642d690920SAxel Dörfler 	}
265e1b4aed0SAxel Dörfler 
2662d690920SAxel Dörfler 	return fBuffer;
2672d690920SAxel Dörfler }
2682d690920SAxel Dörfler 
2690d4c16e0SAxel Dörfler 
2702d690920SAxel Dörfler status_t
2712d690920SAxel Dörfler KPath::ReplaceLeaf(const char* newLeaf)
2722d690920SAxel Dörfler {
2732d690920SAxel Dörfler 	const char* leaf = Leaf();
2743582d4feSAxel Dörfler 	if (leaf == NULL)
2752d690920SAxel Dörfler 		return B_NO_INIT;
2760d4c16e0SAxel Dörfler 
2772d690920SAxel Dörfler 	int32 leafIndex = leaf - fBuffer;
2782d690920SAxel Dörfler 	// chop off the current leaf (don't replace "/", though)
2792d690920SAxel Dörfler 	if (leafIndex != 0 || fBuffer[leafIndex - 1]) {
2802d690920SAxel Dörfler 		fBuffer[leafIndex] = '\0';
2812d690920SAxel Dörfler 		fPathLength = leafIndex;
2822d690920SAxel Dörfler 		_ChopTrailingSlashes();
2832d690920SAxel Dörfler 	}
2840d4c16e0SAxel Dörfler 
2852d690920SAxel Dörfler 	// if a leaf was given, append it
2863582d4feSAxel Dörfler 	if (newLeaf != NULL)
2872d690920SAxel Dörfler 		return Append(newLeaf);
2882d690920SAxel Dörfler 	return B_OK;
2892d690920SAxel Dörfler }
2902d690920SAxel Dörfler 
2910d4c16e0SAxel Dörfler 
2923532662eSIngo Weinhold bool
2933532662eSIngo Weinhold KPath::RemoveLeaf()
2943532662eSIngo Weinhold {
2953532662eSIngo Weinhold 	// get the leaf -- bail out, if not initialized or only the "/" is left
2963532662eSIngo Weinhold 	const char* leaf = Leaf();
297e1b4aed0SAxel Dörfler 	if (leaf == NULL || leaf == fBuffer || leaf[0] == '\0')
2983532662eSIngo Weinhold 		return false;
2993532662eSIngo Weinhold 
3003532662eSIngo Weinhold 	// chop off the leaf
3013532662eSIngo Weinhold 	int32 leafIndex = leaf - fBuffer;
3023532662eSIngo Weinhold 	fBuffer[leafIndex] = '\0';
3033532662eSIngo Weinhold 	fPathLength = leafIndex;
3043532662eSIngo Weinhold 	_ChopTrailingSlashes();
3053532662eSIngo Weinhold 
3063532662eSIngo Weinhold 	return true;
3073532662eSIngo Weinhold }
3083532662eSIngo Weinhold 
3093532662eSIngo Weinhold 
3102d690920SAxel Dörfler status_t
3112d690920SAxel Dörfler KPath::Append(const char* component, bool isComponent)
3122d690920SAxel Dörfler {
3132d690920SAxel Dörfler 	// check initialization and parameter
3149abf4591Sczeidler 	if (fBuffer == NULL)
3152d690920SAxel Dörfler 		return B_NO_INIT;
3169abf4591Sczeidler 	if (component == NULL)
3172d690920SAxel Dörfler 		return B_BAD_VALUE;
3182d690920SAxel Dörfler 	if (fPathLength == 0)
3192d690920SAxel Dörfler 		return SetPath(component);
3200d4c16e0SAxel Dörfler 
3212d690920SAxel Dörfler 	// get component length
3220d4c16e0SAxel Dörfler 	size_t componentLength = strlen(component);
3230d4c16e0SAxel Dörfler 	if (componentLength < 1)
3242d690920SAxel Dörfler 		return B_OK;
3250d4c16e0SAxel Dörfler 
3262d690920SAxel Dörfler 	// if our current path is empty, we just copy the supplied one
3272d690920SAxel Dörfler 	// compute the result path len
3282d690920SAxel Dörfler 	bool insertSlash = isComponent && fBuffer[fPathLength - 1] != '/'
3292d690920SAxel Dörfler 		&& component[0] != '/';
330ea26d9f0SStephan Aßmus 	size_t resultPathLength = fPathLength + componentLength
331ea26d9f0SStephan Aßmus 		+ (insertSlash ? 1 : 0);
3320d4c16e0SAxel Dörfler 	if (resultPathLength >= fBufferSize)
3332d690920SAxel Dörfler 		return B_BUFFER_OVERFLOW;
3340d4c16e0SAxel Dörfler 
3352d690920SAxel Dörfler 	// compose the result path
3362d690920SAxel Dörfler 	if (insertSlash)
3372d690920SAxel Dörfler 		fBuffer[fPathLength++] = '/';
3380d4c16e0SAxel Dörfler 	memcpy(fBuffer + fPathLength, component, componentLength + 1);
3390d4c16e0SAxel Dörfler 	fPathLength = resultPathLength;
3402d690920SAxel Dörfler 	return B_OK;
3412d690920SAxel Dörfler }
3422d690920SAxel Dörfler 
3430d4c16e0SAxel Dörfler 
344e8d3eff9SIngo Weinhold status_t
345e8d3eff9SIngo Weinhold KPath::Normalize(bool traverseLeafLink)
346e8d3eff9SIngo Weinhold {
347e8d3eff9SIngo Weinhold 	if (fBuffer == NULL)
348e8d3eff9SIngo Weinhold 		return B_NO_INIT;
349e8d3eff9SIngo Weinhold 	if (fPathLength == 0)
350e8d3eff9SIngo Weinhold 		return B_BAD_VALUE;
351e8d3eff9SIngo Weinhold 
352e9843da3SAxel Dörfler 	return _Normalize(fBuffer, traverseLeafLink);
353e8d3eff9SIngo Weinhold }
354e8d3eff9SIngo Weinhold 
355e8d3eff9SIngo Weinhold 
3562d690920SAxel Dörfler KPath&
3572d690920SAxel Dörfler KPath::operator=(const KPath& other)
3582d690920SAxel Dörfler {
359*a07f133eSAugustin Cavalier 	if (other.fBuffer == fBuffer)
360*a07f133eSAugustin Cavalier 		return *this;
361*a07f133eSAugustin Cavalier 
362e9843da3SAxel Dörfler 	SetTo(other.fBuffer, fLazy ? KPath::LAZY_ALLOC : KPath::DEFAULT,
363e9843da3SAxel Dörfler 		other.fBufferSize);
3642d690920SAxel Dörfler 	return *this;
3652d690920SAxel Dörfler }
3662d690920SAxel Dörfler 
3670d4c16e0SAxel Dörfler 
3682d690920SAxel Dörfler KPath&
3692d690920SAxel Dörfler KPath::operator=(const char* path)
3702d690920SAxel Dörfler {
371e1b4aed0SAxel Dörfler 	SetPath(path);
3722d690920SAxel Dörfler 	return *this;
3732d690920SAxel Dörfler }
3742d690920SAxel Dörfler 
3750d4c16e0SAxel Dörfler 
3762d690920SAxel Dörfler bool
3772d690920SAxel Dörfler KPath::operator==(const KPath& other) const
3782d690920SAxel Dörfler {
379e1b4aed0SAxel Dörfler 	if (fBuffer == NULL)
3800d4c16e0SAxel Dörfler 		return !other.fBuffer;
3810d4c16e0SAxel Dörfler 
382e9843da3SAxel Dörfler 	return other.fBuffer != NULL
3832d690920SAxel Dörfler 		&& fPathLength == other.fPathLength
3843582d4feSAxel Dörfler 		&& strcmp(fBuffer, other.fBuffer) == 0;
3852d690920SAxel Dörfler }
3862d690920SAxel Dörfler 
3870d4c16e0SAxel Dörfler 
3882d690920SAxel Dörfler bool
3892d690920SAxel Dörfler KPath::operator==(const char* path) const
3902d690920SAxel Dörfler {
391e1b4aed0SAxel Dörfler 	if (fBuffer == NULL)
392e9843da3SAxel Dörfler 		return path == NULL;
3930d4c16e0SAxel Dörfler 
394e9843da3SAxel Dörfler 	return path != NULL && strcmp(fBuffer, path) == 0;
3952d690920SAxel Dörfler }
3962d690920SAxel Dörfler 
3970d4c16e0SAxel Dörfler 
3982d690920SAxel Dörfler bool
3992d690920SAxel Dörfler KPath::operator!=(const KPath& other) const
4002d690920SAxel Dörfler {
4012d690920SAxel Dörfler 	return !(*this == other);
4022d690920SAxel Dörfler }
4032d690920SAxel Dörfler 
4040d4c16e0SAxel Dörfler 
4052d690920SAxel Dörfler bool
4062d690920SAxel Dörfler KPath::operator!=(const char* path) const
4072d690920SAxel Dörfler {
4082d690920SAxel Dörfler 	return !(*this == path);
4092d690920SAxel Dörfler }
4102d690920SAxel Dörfler 
4110d4c16e0SAxel Dörfler 
412e9843da3SAxel Dörfler status_t
413e9843da3SAxel Dörfler KPath::_AllocateBuffer()
414e9843da3SAxel Dörfler {
415e9843da3SAxel Dörfler 	if (fBuffer == NULL && fBufferSize != 0)
416e9843da3SAxel Dörfler 		fBuffer = (char*)malloc(fBufferSize);
417e9843da3SAxel Dörfler 	if (fBuffer == NULL) {
418e9843da3SAxel Dörfler 		fFailed = true;
419e9843da3SAxel Dörfler 		return B_NO_MEMORY;
420e9843da3SAxel Dörfler 	}
421e9843da3SAxel Dörfler 
422e9843da3SAxel Dörfler 	fBuffer[0] = '\0';
423e9843da3SAxel Dörfler 	fFailed = false;
424e9843da3SAxel Dörfler 	return B_OK;
425e9843da3SAxel Dörfler }
426e9843da3SAxel Dörfler 
427e9843da3SAxel Dörfler 
428e9843da3SAxel Dörfler status_t
429e9843da3SAxel Dörfler KPath::_Normalize(const char* path, bool traverseLeafLink)
430e9843da3SAxel Dörfler {
431e9843da3SAxel Dörfler 	status_t error = vfs_normalize_path(path, fBuffer, fBufferSize,
432e9843da3SAxel Dörfler 		traverseLeafLink,
433e9843da3SAxel Dörfler 		team_get_kernel_team_id() == team_get_current_team_id());
434e9843da3SAxel Dörfler 	if (error != B_OK) {
435e9843da3SAxel Dörfler 		// vfs_normalize_path() might have screwed up the previous
436e9843da3SAxel Dörfler 		// path -- unset it completely to avoid weird problems.
437e9843da3SAxel Dörfler 		fBuffer[0] = '\0';
438e9843da3SAxel Dörfler 		fPathLength = 0;
439e9843da3SAxel Dörfler 		return error;
440e9843da3SAxel Dörfler 	}
441e9843da3SAxel Dörfler 
442e9843da3SAxel Dörfler 	fPathLength = strlen(fBuffer);
443e9843da3SAxel Dörfler 	return B_OK;
444e9843da3SAxel Dörfler }
445e9843da3SAxel Dörfler 
446e9843da3SAxel Dörfler 
4472d690920SAxel Dörfler void
4482d690920SAxel Dörfler KPath::_ChopTrailingSlashes()
4492d690920SAxel Dörfler {
4503582d4feSAxel Dörfler 	if (fBuffer != NULL) {
4512d690920SAxel Dörfler 		while (fPathLength > 1 && fBuffer[fPathLength - 1] == '/')
4522d690920SAxel Dörfler 			fBuffer[--fPathLength] = '\0';
4532d690920SAxel Dörfler 	}
4542d690920SAxel Dörfler }
4552d690920SAxel Dörfler 
456