xref: /haiku/src/system/kernel/fs/KPath.cpp (revision 9708b080608f70250ed72121927004a42f549c4a)
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>
1842e3c6f9SAugustin Cavalier #include <slab/Slab.h>
1923a60f42SAxel Dörfler 
200d4c16e0SAxel Dörfler 
210d4c16e0SAxel Dörfler // debugging
220d4c16e0SAxel Dörfler #define TRACE(x) ;
230d4c16e0SAxel Dörfler //#define TRACE(x) dprintf x
240d4c16e0SAxel Dörfler 
250d4c16e0SAxel Dörfler 
2642e3c6f9SAugustin Cavalier #ifdef _KERNEL_MODE
2742e3c6f9SAugustin Cavalier extern object_cache* sPathNameCache;
2842e3c6f9SAugustin Cavalier #endif
2942e3c6f9SAugustin Cavalier 
3042e3c6f9SAugustin Cavalier 
KPath(size_t bufferSize)310d4c16e0SAxel Dörfler KPath::KPath(size_t bufferSize)
320d4c16e0SAxel Dörfler 	:
330d4c16e0SAxel Dörfler 	fBuffer(NULL),
342d690920SAxel Dörfler 	fBufferSize(0),
352d690920SAxel Dörfler 	fPathLength(0),
36e9843da3SAxel Dörfler 	fLocked(false),
37e9843da3SAxel Dörfler 	fLazy(false),
38e9843da3SAxel Dörfler 	fFailed(false),
39e9843da3SAxel Dörfler 	fIsNull(false)
402d690920SAxel Dörfler {
41e9843da3SAxel Dörfler 	SetTo(NULL, DEFAULT, bufferSize);
422d690920SAxel Dörfler }
432d690920SAxel Dörfler 
440d4c16e0SAxel Dörfler 
KPath(const char * path,int32 flags,size_t bufferSize)45eac83fb3SAxel Dörfler KPath::KPath(const char* path, int32 flags, size_t bufferSize)
460d4c16e0SAxel Dörfler 	:
470d4c16e0SAxel Dörfler 	fBuffer(NULL),
482d690920SAxel Dörfler 	fBufferSize(0),
492d690920SAxel Dörfler 	fPathLength(0),
50e9843da3SAxel Dörfler 	fLocked(false),
51e9843da3SAxel Dörfler 	fLazy(false),
52e9843da3SAxel Dörfler 	fFailed(false),
53e9843da3SAxel Dörfler 	fIsNull(false)
542d690920SAxel Dörfler {
55eac83fb3SAxel Dörfler 	SetTo(path, flags, bufferSize);
562d690920SAxel Dörfler }
572d690920SAxel Dörfler 
580d4c16e0SAxel Dörfler 
KPath(const KPath & other)592d690920SAxel Dörfler KPath::KPath(const KPath& other)
600d4c16e0SAxel Dörfler 	:
610d4c16e0SAxel Dörfler 	fBuffer(NULL),
622d690920SAxel Dörfler 	fBufferSize(0),
632d690920SAxel Dörfler 	fPathLength(0),
64e9843da3SAxel Dörfler 	fLocked(false),
65e9843da3SAxel Dörfler 	fLazy(false),
66e9843da3SAxel Dörfler 	fFailed(false),
67e9843da3SAxel Dörfler 	fIsNull(false)
682d690920SAxel Dörfler {
692d690920SAxel Dörfler 	*this = other;
702d690920SAxel Dörfler }
712d690920SAxel Dörfler 
720d4c16e0SAxel Dörfler 
~KPath()732d690920SAxel Dörfler KPath::~KPath()
742d690920SAxel Dörfler {
7542e3c6f9SAugustin Cavalier 	_FreeBuffer();
762d690920SAxel Dörfler }
772d690920SAxel Dörfler 
780d4c16e0SAxel Dörfler 
792d690920SAxel Dörfler status_t
SetTo(const char * path,int32 flags,size_t bufferSize)80eac83fb3SAxel Dörfler KPath::SetTo(const char* path, int32 flags, size_t bufferSize)
812d690920SAxel Dörfler {
820d4c16e0SAxel Dörfler 	if (bufferSize == 0)
83*9708b080SAugustin Cavalier 		bufferSize = B_PATH_NAME_LENGTH;
840d4c16e0SAxel Dörfler 
852d690920SAxel Dörfler 	// free the previous buffer, if the buffer size differs
863582d4feSAxel Dörfler 	if (fBuffer != NULL && fBufferSize != bufferSize) {
8742e3c6f9SAugustin Cavalier 		_FreeBuffer();
882d690920SAxel Dörfler 		fBufferSize = 0;
892d690920SAxel Dörfler 	}
90e9843da3SAxel Dörfler 
912d690920SAxel Dörfler 	fPathLength = 0;
922d690920SAxel Dörfler 	fLocked = false;
932d690920SAxel Dörfler 	fBufferSize = bufferSize;
94e9843da3SAxel Dörfler 	fLazy = (flags & LAZY_ALLOC) != 0;
95e9843da3SAxel Dörfler 	fIsNull = path == NULL;
96e9843da3SAxel Dörfler 
97e9843da3SAxel Dörfler 	if (path != NULL || !fLazy) {
98e9843da3SAxel Dörfler 		status_t status = _AllocateBuffer();
99e9843da3SAxel Dörfler 		if (status != B_OK)
100e9843da3SAxel Dörfler 			return status;
101e9843da3SAxel Dörfler 	}
1023582d4feSAxel Dörfler 
103eac83fb3SAxel Dörfler 	return SetPath(path, flags);
1042d690920SAxel Dörfler }
1052d690920SAxel Dörfler 
1060d4c16e0SAxel Dörfler 
10756bbbbc9SAxel Dörfler void
Adopt(KPath & other)10856bbbbc9SAxel Dörfler KPath::Adopt(KPath& other)
10956bbbbc9SAxel Dörfler {
11042e3c6f9SAugustin Cavalier 	_FreeBuffer();
11156bbbbc9SAxel Dörfler 
11256bbbbc9SAxel Dörfler 	fBuffer = other.fBuffer;
11356bbbbc9SAxel Dörfler 	fBufferSize = other.fBufferSize;
114f94671c3SAxel Dörfler 	fPathLength = other.fPathLength;
115e9843da3SAxel Dörfler 	fLazy = other.fLazy;
116e9843da3SAxel Dörfler 	fFailed = other.fFailed;
117e9843da3SAxel Dörfler 	fIsNull = other.fIsNull;
11856bbbbc9SAxel Dörfler 
11956bbbbc9SAxel Dörfler 	other.fBuffer = NULL;
120e9843da3SAxel Dörfler 	if (!other.fLazy)
1214be51875SAxel Dörfler 		other.fBufferSize = 0;
1224be51875SAxel Dörfler 	other.fPathLength = 0;
123e9843da3SAxel Dörfler 	other.fFailed = false;
124e9843da3SAxel Dörfler 	other.fIsNull = other.fLazy;
12556bbbbc9SAxel Dörfler }
12656bbbbc9SAxel Dörfler 
12756bbbbc9SAxel Dörfler 
1282d690920SAxel Dörfler status_t
InitCheck() const1292d690920SAxel Dörfler KPath::InitCheck() const
1302d690920SAxel Dörfler {
131655aae6aSAxel Dörfler 	if (fBuffer != NULL || (fLazy && !fFailed && fBufferSize != 0))
132e9843da3SAxel Dörfler 		return B_OK;
133e9843da3SAxel Dörfler 
134e9843da3SAxel Dörfler 	return fFailed ? B_NO_MEMORY : B_NO_INIT;
1352d690920SAxel Dörfler }
1362d690920SAxel Dörfler 
1370d4c16e0SAxel Dörfler 
138e9843da3SAxel Dörfler /*!	\brief Sets the buffer to \a path.
139e9843da3SAxel Dörfler 
140e9843da3SAxel Dörfler 	\param flags Understands the following two options:
141e9843da3SAxel Dörfler 		- \c NORMALIZE
142e9843da3SAxel Dörfler 		- \c TRAVERSE_LEAF_LINK
143e9843da3SAxel Dörfler */
1442d690920SAxel Dörfler status_t
SetPath(const char * path,int32 flags)145eac83fb3SAxel Dörfler KPath::SetPath(const char* path, int32 flags)
1462d690920SAxel Dörfler {
147e9843da3SAxel Dörfler 	if (path == NULL && fLazy && fBuffer == NULL) {
148e9843da3SAxel Dörfler 		fIsNull = true;
149e9843da3SAxel Dörfler 		return B_OK;
150e9843da3SAxel Dörfler 	}
151e9843da3SAxel Dörfler 
152e9843da3SAxel Dörfler 	if (fBuffer == NULL) {
153e9843da3SAxel Dörfler 		if (fLazy) {
154e9843da3SAxel Dörfler 			status_t status = _AllocateBuffer();
155e9843da3SAxel Dörfler 			if (status != B_OK)
156e9843da3SAxel Dörfler 				return B_NO_MEMORY;
157e9843da3SAxel Dörfler 		} else
1582d690920SAxel Dörfler 			return B_NO_INIT;
159e9843da3SAxel Dörfler 	}
160e9843da3SAxel Dörfler 
161e9843da3SAxel Dörfler 	fIsNull = false;
1620d4c16e0SAxel Dörfler 
1639abf4591Sczeidler 	if (path != NULL) {
164eac83fb3SAxel Dörfler 		if ((flags & NORMALIZE) != 0) {
1652d690920SAxel Dörfler 			// normalize path
166e9843da3SAxel Dörfler 			status_t status = _Normalize(path,
167e9843da3SAxel Dörfler 				(flags & TRAVERSE_LEAF_LINK) != 0);
168e9843da3SAxel Dörfler 			if (status != B_OK)
169e9843da3SAxel Dörfler 				return status;
1702d690920SAxel Dörfler 		} else {
1712d690920SAxel Dörfler 			// don't normalize path
1720d4c16e0SAxel Dörfler 			size_t length = strlen(path);
1730d4c16e0SAxel Dörfler 			if (length >= fBufferSize)
1742d690920SAxel Dörfler 				return B_BUFFER_OVERFLOW;
1750d4c16e0SAxel Dörfler 
1760d4c16e0SAxel Dörfler 			memcpy(fBuffer, path, length + 1);
1770d4c16e0SAxel Dörfler 			fPathLength = length;
1782d690920SAxel Dörfler 			_ChopTrailingSlashes();
1792d690920SAxel Dörfler 		}
1802d690920SAxel Dörfler 	} else {
1812d690920SAxel Dörfler 		fBuffer[0] = '\0';
1822d690920SAxel Dörfler 		fPathLength = 0;
183e9843da3SAxel Dörfler 		if (fLazy)
184e9843da3SAxel Dörfler 			fIsNull = true;
1852d690920SAxel Dörfler 	}
1862d690920SAxel Dörfler 	return B_OK;
1872d690920SAxel Dörfler }
1882d690920SAxel Dörfler 
1890d4c16e0SAxel Dörfler 
1902d690920SAxel Dörfler const char*
Path() const1912d690920SAxel Dörfler KPath::Path() const
1922d690920SAxel Dörfler {
193e9843da3SAxel Dörfler 	return fIsNull ? NULL : fBuffer;
1942d690920SAxel Dörfler }
1952d690920SAxel Dörfler 
1962d690920SAxel Dörfler 
197e9843da3SAxel Dörfler /*!	\brief Locks the buffer for external changes.
198e9843da3SAxel Dörfler 
199e9843da3SAxel Dörfler 	\param force In lazy mode, this will allocate a buffer when set.
200e9843da3SAxel Dörfler 		Otherwise, \c NULL will be returned if set to NULL.
201e9843da3SAxel Dörfler */
2022d690920SAxel Dörfler char*
LockBuffer(bool force)203e9843da3SAxel Dörfler KPath::LockBuffer(bool force)
2042d690920SAxel Dörfler {
205e9843da3SAxel Dörfler 	if (fBuffer == NULL && fLazy) {
206e9843da3SAxel Dörfler 		if (fIsNull && !force)
207e9843da3SAxel Dörfler 			return NULL;
208e9843da3SAxel Dörfler 
209e9843da3SAxel Dörfler 		_AllocateBuffer();
210e9843da3SAxel Dörfler 	}
211e9843da3SAxel Dörfler 
2129abf4591Sczeidler 	if (fBuffer == NULL || fLocked)
2132d690920SAxel Dörfler 		return NULL;
2140d4c16e0SAxel Dörfler 
2152d690920SAxel Dörfler 	fLocked = true;
216e9843da3SAxel Dörfler 	fIsNull = false;
217e9843da3SAxel Dörfler 
2182d690920SAxel Dörfler 	return fBuffer;
2192d690920SAxel Dörfler }
2202d690920SAxel Dörfler 
2210d4c16e0SAxel Dörfler 
2222d690920SAxel Dörfler void
UnlockBuffer()2232d690920SAxel Dörfler KPath::UnlockBuffer()
2242d690920SAxel Dörfler {
2252d690920SAxel Dörfler 	if (!fLocked) {
22642e3c6f9SAugustin Cavalier #ifdef _KERNEL_MODE
22742e3c6f9SAugustin Cavalier 		panic("KPath::UnlockBuffer(): Buffer not locked!");
22842e3c6f9SAugustin Cavalier #endif
2292d690920SAxel Dörfler 		return;
2302d690920SAxel Dörfler 	}
231e9843da3SAxel Dörfler 
2322d690920SAxel Dörfler 	fLocked = false;
233e9843da3SAxel Dörfler 
234e9843da3SAxel Dörfler 	if (fBuffer == NULL)
235e9843da3SAxel Dörfler 		return;
236e9843da3SAxel Dörfler 
2372d690920SAxel Dörfler 	fPathLength = strnlen(fBuffer, fBufferSize);
2382d690920SAxel Dörfler 	if (fPathLength == fBufferSize) {
2390d4c16e0SAxel Dörfler 		TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n"));
2402d690920SAxel Dörfler 		fPathLength--;
2412d690920SAxel Dörfler 		fBuffer[fPathLength] = '\0';
2422d690920SAxel Dörfler 	}
2432d690920SAxel Dörfler 	_ChopTrailingSlashes();
2442d690920SAxel Dörfler }
2452d690920SAxel Dörfler 
2460d4c16e0SAxel Dörfler 
247e8d3eff9SIngo Weinhold char*
DetachBuffer()248e8d3eff9SIngo Weinhold KPath::DetachBuffer()
249e8d3eff9SIngo Weinhold {
250e8d3eff9SIngo Weinhold 	char* buffer = fBuffer;
251e8d3eff9SIngo Weinhold 
252*9708b080SAugustin Cavalier #ifdef _KERNEL_MODE
253*9708b080SAugustin Cavalier 	if (fBufferSize == B_PATH_NAME_LENGTH) {
25442e3c6f9SAugustin Cavalier 		buffer = (char*)malloc(fBufferSize);
25542e3c6f9SAugustin Cavalier 		memcpy(buffer, fBuffer, fBufferSize);
25642e3c6f9SAugustin Cavalier 		_FreeBuffer();
25742e3c6f9SAugustin Cavalier 	}
258*9708b080SAugustin Cavalier #endif
25942e3c6f9SAugustin Cavalier 
260e8d3eff9SIngo Weinhold 	if (fBuffer != NULL) {
261e8d3eff9SIngo Weinhold 		fBuffer = NULL;
262e8d3eff9SIngo Weinhold 		fPathLength = 0;
263e8d3eff9SIngo Weinhold 		fLocked = false;
264e8d3eff9SIngo Weinhold 	}
265e8d3eff9SIngo Weinhold 
266e8d3eff9SIngo Weinhold 	return buffer;
267e8d3eff9SIngo Weinhold }
268e8d3eff9SIngo Weinhold 
269e8d3eff9SIngo Weinhold 
2702d690920SAxel Dörfler const char*
Leaf() const2712d690920SAxel Dörfler KPath::Leaf() const
2722d690920SAxel Dörfler {
2733582d4feSAxel Dörfler 	if (fBuffer == NULL)
2742d690920SAxel Dörfler 		return NULL;
2750d4c16e0SAxel Dörfler 
2762d690920SAxel Dörfler 	for (int32 i = fPathLength - 1; i >= 0; i--) {
2772d690920SAxel Dörfler 		if (fBuffer[i] == '/')
2782d690920SAxel Dörfler 			return fBuffer + i + 1;
2792d690920SAxel Dörfler 	}
280e1b4aed0SAxel Dörfler 
2812d690920SAxel Dörfler 	return fBuffer;
2822d690920SAxel Dörfler }
2832d690920SAxel Dörfler 
2840d4c16e0SAxel Dörfler 
2852d690920SAxel Dörfler status_t
ReplaceLeaf(const char * newLeaf)2862d690920SAxel Dörfler KPath::ReplaceLeaf(const char* newLeaf)
2872d690920SAxel Dörfler {
2882d690920SAxel Dörfler 	const char* leaf = Leaf();
2893582d4feSAxel Dörfler 	if (leaf == NULL)
2902d690920SAxel Dörfler 		return B_NO_INIT;
2910d4c16e0SAxel Dörfler 
2922d690920SAxel Dörfler 	int32 leafIndex = leaf - fBuffer;
2932d690920SAxel Dörfler 	// chop off the current leaf (don't replace "/", though)
2942d690920SAxel Dörfler 	if (leafIndex != 0 || fBuffer[leafIndex - 1]) {
2952d690920SAxel Dörfler 		fBuffer[leafIndex] = '\0';
2962d690920SAxel Dörfler 		fPathLength = leafIndex;
2972d690920SAxel Dörfler 		_ChopTrailingSlashes();
2982d690920SAxel Dörfler 	}
2990d4c16e0SAxel Dörfler 
3002d690920SAxel Dörfler 	// if a leaf was given, append it
3013582d4feSAxel Dörfler 	if (newLeaf != NULL)
3022d690920SAxel Dörfler 		return Append(newLeaf);
3032d690920SAxel Dörfler 	return B_OK;
3042d690920SAxel Dörfler }
3052d690920SAxel Dörfler 
3060d4c16e0SAxel Dörfler 
3073532662eSIngo Weinhold bool
RemoveLeaf()3083532662eSIngo Weinhold KPath::RemoveLeaf()
3093532662eSIngo Weinhold {
3103532662eSIngo Weinhold 	// get the leaf -- bail out, if not initialized or only the "/" is left
3113532662eSIngo Weinhold 	const char* leaf = Leaf();
312e1b4aed0SAxel Dörfler 	if (leaf == NULL || leaf == fBuffer || leaf[0] == '\0')
3133532662eSIngo Weinhold 		return false;
3143532662eSIngo Weinhold 
3153532662eSIngo Weinhold 	// chop off the leaf
3163532662eSIngo Weinhold 	int32 leafIndex = leaf - fBuffer;
3173532662eSIngo Weinhold 	fBuffer[leafIndex] = '\0';
3183532662eSIngo Weinhold 	fPathLength = leafIndex;
3193532662eSIngo Weinhold 	_ChopTrailingSlashes();
3203532662eSIngo Weinhold 
3213532662eSIngo Weinhold 	return true;
3223532662eSIngo Weinhold }
3233532662eSIngo Weinhold 
3243532662eSIngo Weinhold 
3252d690920SAxel Dörfler status_t
Append(const char * component,bool isComponent)3262d690920SAxel Dörfler KPath::Append(const char* component, bool isComponent)
3272d690920SAxel Dörfler {
3282d690920SAxel Dörfler 	// check initialization and parameter
3299abf4591Sczeidler 	if (fBuffer == NULL)
3302d690920SAxel Dörfler 		return B_NO_INIT;
3319abf4591Sczeidler 	if (component == NULL)
3322d690920SAxel Dörfler 		return B_BAD_VALUE;
3332d690920SAxel Dörfler 	if (fPathLength == 0)
3342d690920SAxel Dörfler 		return SetPath(component);
3350d4c16e0SAxel Dörfler 
3362d690920SAxel Dörfler 	// get component length
3370d4c16e0SAxel Dörfler 	size_t componentLength = strlen(component);
3380d4c16e0SAxel Dörfler 	if (componentLength < 1)
3392d690920SAxel Dörfler 		return B_OK;
3400d4c16e0SAxel Dörfler 
3412d690920SAxel Dörfler 	// if our current path is empty, we just copy the supplied one
3422d690920SAxel Dörfler 	// compute the result path len
3432d690920SAxel Dörfler 	bool insertSlash = isComponent && fBuffer[fPathLength - 1] != '/'
3442d690920SAxel Dörfler 		&& component[0] != '/';
345ea26d9f0SStephan Aßmus 	size_t resultPathLength = fPathLength + componentLength
346ea26d9f0SStephan Aßmus 		+ (insertSlash ? 1 : 0);
3470d4c16e0SAxel Dörfler 	if (resultPathLength >= fBufferSize)
3482d690920SAxel Dörfler 		return B_BUFFER_OVERFLOW;
3490d4c16e0SAxel Dörfler 
3502d690920SAxel Dörfler 	// compose the result path
3512d690920SAxel Dörfler 	if (insertSlash)
3522d690920SAxel Dörfler 		fBuffer[fPathLength++] = '/';
3530d4c16e0SAxel Dörfler 	memcpy(fBuffer + fPathLength, component, componentLength + 1);
3540d4c16e0SAxel Dörfler 	fPathLength = resultPathLength;
3552d690920SAxel Dörfler 	return B_OK;
3562d690920SAxel Dörfler }
3572d690920SAxel Dörfler 
3580d4c16e0SAxel Dörfler 
359e8d3eff9SIngo Weinhold status_t
Normalize(bool traverseLeafLink)360e8d3eff9SIngo Weinhold KPath::Normalize(bool traverseLeafLink)
361e8d3eff9SIngo Weinhold {
362e8d3eff9SIngo Weinhold 	if (fBuffer == NULL)
363e8d3eff9SIngo Weinhold 		return B_NO_INIT;
364e8d3eff9SIngo Weinhold 	if (fPathLength == 0)
365e8d3eff9SIngo Weinhold 		return B_BAD_VALUE;
366e8d3eff9SIngo Weinhold 
367e9843da3SAxel Dörfler 	return _Normalize(fBuffer, traverseLeafLink);
368e8d3eff9SIngo Weinhold }
369e8d3eff9SIngo Weinhold 
370e8d3eff9SIngo Weinhold 
3712d690920SAxel Dörfler KPath&
operator =(const KPath & other)3722d690920SAxel Dörfler KPath::operator=(const KPath& other)
3732d690920SAxel Dörfler {
374a07f133eSAugustin Cavalier 	if (other.fBuffer == fBuffer)
375a07f133eSAugustin Cavalier 		return *this;
376a07f133eSAugustin Cavalier 
377e9843da3SAxel Dörfler 	SetTo(other.fBuffer, fLazy ? KPath::LAZY_ALLOC : KPath::DEFAULT,
378e9843da3SAxel Dörfler 		other.fBufferSize);
3792d690920SAxel Dörfler 	return *this;
3802d690920SAxel Dörfler }
3812d690920SAxel Dörfler 
3820d4c16e0SAxel Dörfler 
3832d690920SAxel Dörfler KPath&
operator =(const char * path)3842d690920SAxel Dörfler KPath::operator=(const char* path)
3852d690920SAxel Dörfler {
386e1b4aed0SAxel Dörfler 	SetPath(path);
3872d690920SAxel Dörfler 	return *this;
3882d690920SAxel Dörfler }
3892d690920SAxel Dörfler 
3900d4c16e0SAxel Dörfler 
3912d690920SAxel Dörfler bool
operator ==(const KPath & other) const3922d690920SAxel Dörfler KPath::operator==(const KPath& other) const
3932d690920SAxel Dörfler {
394e1b4aed0SAxel Dörfler 	if (fBuffer == NULL)
3950d4c16e0SAxel Dörfler 		return !other.fBuffer;
3960d4c16e0SAxel Dörfler 
397e9843da3SAxel Dörfler 	return other.fBuffer != NULL
3982d690920SAxel Dörfler 		&& fPathLength == other.fPathLength
3993582d4feSAxel Dörfler 		&& strcmp(fBuffer, other.fBuffer) == 0;
4002d690920SAxel Dörfler }
4012d690920SAxel Dörfler 
4020d4c16e0SAxel Dörfler 
4032d690920SAxel Dörfler bool
operator ==(const char * path) const4042d690920SAxel Dörfler KPath::operator==(const char* path) const
4052d690920SAxel Dörfler {
406e1b4aed0SAxel Dörfler 	if (fBuffer == NULL)
407e9843da3SAxel Dörfler 		return path == NULL;
4080d4c16e0SAxel Dörfler 
409e9843da3SAxel Dörfler 	return path != NULL && strcmp(fBuffer, path) == 0;
4102d690920SAxel Dörfler }
4112d690920SAxel Dörfler 
4120d4c16e0SAxel Dörfler 
4132d690920SAxel Dörfler bool
operator !=(const KPath & other) const4142d690920SAxel Dörfler KPath::operator!=(const KPath& other) const
4152d690920SAxel Dörfler {
4162d690920SAxel Dörfler 	return !(*this == other);
4172d690920SAxel Dörfler }
4182d690920SAxel Dörfler 
4190d4c16e0SAxel Dörfler 
4202d690920SAxel Dörfler bool
operator !=(const char * path) const4212d690920SAxel Dörfler KPath::operator!=(const char* path) const
4222d690920SAxel Dörfler {
4232d690920SAxel Dörfler 	return !(*this == path);
4242d690920SAxel Dörfler }
4252d690920SAxel Dörfler 
4260d4c16e0SAxel Dörfler 
427e9843da3SAxel Dörfler status_t
_AllocateBuffer()428e9843da3SAxel Dörfler KPath::_AllocateBuffer()
429e9843da3SAxel Dörfler {
43042e3c6f9SAugustin Cavalier 	if (fBuffer == NULL && fBufferSize != 0) {
43142e3c6f9SAugustin Cavalier #ifdef _KERNEL_MODE
432*9708b080SAugustin Cavalier 		if (fBufferSize == B_PATH_NAME_LENGTH)
43342e3c6f9SAugustin Cavalier 			fBuffer = (char*)object_cache_alloc(sPathNameCache, 0);
43442e3c6f9SAugustin Cavalier 		else
43542e3c6f9SAugustin Cavalier #endif
436e9843da3SAxel Dörfler 			fBuffer = (char*)malloc(fBufferSize);
43742e3c6f9SAugustin Cavalier 	}
438e9843da3SAxel Dörfler 	if (fBuffer == NULL) {
439e9843da3SAxel Dörfler 		fFailed = true;
440e9843da3SAxel Dörfler 		return B_NO_MEMORY;
441e9843da3SAxel Dörfler 	}
442e9843da3SAxel Dörfler 
44390bf90faSwaddlesplash 	memset(fBuffer, 0, fBufferSize);
444e9843da3SAxel Dörfler 	fFailed = false;
445e9843da3SAxel Dörfler 	return B_OK;
446e9843da3SAxel Dörfler }
447e9843da3SAxel Dörfler 
448e9843da3SAxel Dörfler 
44942e3c6f9SAugustin Cavalier void
_FreeBuffer()45042e3c6f9SAugustin Cavalier KPath::_FreeBuffer()
45142e3c6f9SAugustin Cavalier {
45242e3c6f9SAugustin Cavalier #ifdef _KERNEL_MODE
453*9708b080SAugustin Cavalier 	if (fBufferSize == B_PATH_NAME_LENGTH)
45442e3c6f9SAugustin Cavalier 		object_cache_free(sPathNameCache, fBuffer, 0);
45542e3c6f9SAugustin Cavalier 	else
45642e3c6f9SAugustin Cavalier #endif
45742e3c6f9SAugustin Cavalier 		free(fBuffer);
45842e3c6f9SAugustin Cavalier 	fBuffer = NULL;
45942e3c6f9SAugustin Cavalier }
46042e3c6f9SAugustin Cavalier 
46142e3c6f9SAugustin Cavalier 
462e9843da3SAxel Dörfler status_t
_Normalize(const char * path,bool traverseLeafLink)463e9843da3SAxel Dörfler KPath::_Normalize(const char* path, bool traverseLeafLink)
464e9843da3SAxel Dörfler {
465e9843da3SAxel Dörfler 	status_t error = vfs_normalize_path(path, fBuffer, fBufferSize,
466e9843da3SAxel Dörfler 		traverseLeafLink,
467e9843da3SAxel Dörfler 		team_get_kernel_team_id() == team_get_current_team_id());
468e9843da3SAxel Dörfler 	if (error != B_OK) {
469e9843da3SAxel Dörfler 		// vfs_normalize_path() might have screwed up the previous
470e9843da3SAxel Dörfler 		// path -- unset it completely to avoid weird problems.
471e9843da3SAxel Dörfler 		fBuffer[0] = '\0';
472e9843da3SAxel Dörfler 		fPathLength = 0;
473e9843da3SAxel Dörfler 		return error;
474e9843da3SAxel Dörfler 	}
475e9843da3SAxel Dörfler 
476e9843da3SAxel Dörfler 	fPathLength = strlen(fBuffer);
477e9843da3SAxel Dörfler 	return B_OK;
478e9843da3SAxel Dörfler }
479e9843da3SAxel Dörfler 
480e9843da3SAxel Dörfler 
4812d690920SAxel Dörfler void
_ChopTrailingSlashes()4822d690920SAxel Dörfler KPath::_ChopTrailingSlashes()
4832d690920SAxel Dörfler {
4843582d4feSAxel Dörfler 	if (fBuffer != NULL) {
4852d690920SAxel Dörfler 		while (fPathLength > 1 && fBuffer[fPathLength - 1] == '/')
4862d690920SAxel Dörfler 			fBuffer[--fPathLength] = '\0';
4872d690920SAxel Dörfler 	}
4882d690920SAxel Dörfler }
4892d690920SAxel Dörfler 
490