From 66c7a2ac9c1fcccc1455d2bc0a617bc44c631bfa Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 16 Oct 2018 18:50:00 -0400 Subject: [PATCH] KPath: Add to kernelland_emu. This replaces the one in the "playground." It's identical to the current kernel implementation, except with the few VFS functions replaced with Storage Kit calls. Userland packagefs will need this. --- .../add-ons/kernel/kernelland_emu/Jamfile | 1 + .../add-ons/kernel/kernelland_emu/KPath.cpp | 450 ++++++++++++++++++ .../kernel/device_manager/playground/Jamfile | 1 - .../device_manager/playground/KPath.cpp | 330 ------------- 4 files changed, 451 insertions(+), 331 deletions(-) create mode 100644 src/tests/add-ons/kernel/kernelland_emu/KPath.cpp delete mode 100644 src/tests/system/kernel/device_manager/playground/KPath.cpp diff --git a/src/tests/add-ons/kernel/kernelland_emu/Jamfile b/src/tests/add-ons/kernel/kernelland_emu/Jamfile index 8175bd0550..2e02f88bf1 100644 --- a/src/tests/add-ons/kernel/kernelland_emu/Jamfile +++ b/src/tests/add-ons/kernel/kernelland_emu/Jamfile @@ -7,6 +7,7 @@ SharedLibrary libkernelland_emu.so : condition_variable.cpp debug.cpp device_manager.cpp + KPath.cpp lock.cpp low_resource_manager.cpp misc.cpp diff --git a/src/tests/add-ons/kernel/kernelland_emu/KPath.cpp b/src/tests/add-ons/kernel/kernelland_emu/KPath.cpp new file mode 100644 index 0000000000..ee3f9e0776 --- /dev/null +++ b/src/tests/add-ons/kernel/kernelland_emu/KPath.cpp @@ -0,0 +1,450 @@ +/* + * Copyright 2004-2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2008-2017, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +/*! A simple class wrapping a path. Has a fixed-sized buffer. */ + + +#include +#include + +#include +#include + +#include + + +// debugging +#define TRACE(x) ; +//#define TRACE(x) dprintf x + + +KPath::KPath(size_t bufferSize) + : + fBuffer(NULL), + fBufferSize(0), + fPathLength(0), + fLocked(false), + fLazy(false), + fFailed(false), + fIsNull(false) +{ + SetTo(NULL, DEFAULT, bufferSize); +} + + +KPath::KPath(const char* path, int32 flags, size_t bufferSize) + : + fBuffer(NULL), + fBufferSize(0), + fPathLength(0), + fLocked(false), + fLazy(false), + fFailed(false), + fIsNull(false) +{ + SetTo(path, flags, bufferSize); +} + + +KPath::KPath(const KPath& other) + : + fBuffer(NULL), + fBufferSize(0), + fPathLength(0), + fLocked(false), + fLazy(false), + fFailed(false), + fIsNull(false) +{ + *this = other; +} + + +KPath::~KPath() +{ + free(fBuffer); +} + + +status_t +KPath::SetTo(const char* path, int32 flags, size_t bufferSize) +{ + if (bufferSize == 0) + bufferSize = B_PATH_NAME_LENGTH; + + // free the previous buffer, if the buffer size differs + if (fBuffer != NULL && fBufferSize != bufferSize) { + free(fBuffer); + fBuffer = NULL; + fBufferSize = 0; + } + + fPathLength = 0; + fLocked = false; + fBufferSize = bufferSize; + fLazy = (flags & LAZY_ALLOC) != 0; + fIsNull = path == NULL; + + if (path != NULL || !fLazy) { + status_t status = _AllocateBuffer(); + if (status != B_OK) + return status; + } + + return SetPath(path, flags); +} + + +void +KPath::Adopt(KPath& other) +{ + free(fBuffer); + + fBuffer = other.fBuffer; + fBufferSize = other.fBufferSize; + fPathLength = other.fPathLength; + fLazy = other.fLazy; + fFailed = other.fFailed; + fIsNull = other.fIsNull; + + other.fBuffer = NULL; + if (!other.fLazy) + other.fBufferSize = 0; + other.fPathLength = 0; + other.fFailed = false; + other.fIsNull = other.fLazy; +} + + +status_t +KPath::InitCheck() const +{ + if (fBuffer != NULL || (fLazy && !fFailed && fBufferSize != 0)) + return B_OK; + + return fFailed ? B_NO_MEMORY : B_NO_INIT; +} + + +/*! \brief Sets the buffer to \a path. + + \param flags Understands the following two options: + - \c NORMALIZE + - \c TRAVERSE_LEAF_LINK +*/ +status_t +KPath::SetPath(const char* path, int32 flags) +{ + if (path == NULL && fLazy && fBuffer == NULL) { + fIsNull = true; + return B_OK; + } + + if (fBuffer == NULL) { + if (fLazy) { + status_t status = _AllocateBuffer(); + if (status != B_OK) + return B_NO_MEMORY; + } else + return B_NO_INIT; + } + + fIsNull = false; + + if (path != NULL) { + if ((flags & NORMALIZE) != 0) { + // normalize path + status_t status = _Normalize(path, + (flags & TRAVERSE_LEAF_LINK) != 0); + if (status != B_OK) + return status; + } else { + // don't normalize path + size_t length = strlen(path); + if (length >= fBufferSize) + return B_BUFFER_OVERFLOW; + + memcpy(fBuffer, path, length + 1); + fPathLength = length; + _ChopTrailingSlashes(); + } + } else { + fBuffer[0] = '\0'; + fPathLength = 0; + if (fLazy) + fIsNull = true; + } + return B_OK; +} + + +const char* +KPath::Path() const +{ + return fIsNull ? NULL : fBuffer; +} + + +/*! \brief Locks the buffer for external changes. + + \param force In lazy mode, this will allocate a buffer when set. + Otherwise, \c NULL will be returned if set to NULL. +*/ +char* +KPath::LockBuffer(bool force) +{ + if (fBuffer == NULL && fLazy) { + if (fIsNull && !force) + return NULL; + + _AllocateBuffer(); + } + + if (fBuffer == NULL || fLocked) + return NULL; + + fLocked = true; + fIsNull = false; + + return fBuffer; +} + + +void +KPath::UnlockBuffer() +{ + if (!fLocked) { + TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n")); + return; + } + + fLocked = false; + + if (fBuffer == NULL) + return; + + fPathLength = strnlen(fBuffer, fBufferSize); + if (fPathLength == fBufferSize) { + TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n")); + fPathLength--; + fBuffer[fPathLength] = '\0'; + } + _ChopTrailingSlashes(); +} + + +char* +KPath::DetachBuffer() +{ + char* buffer = fBuffer; + + if (fBuffer != NULL) { + fBuffer = NULL; + fPathLength = 0; + fLocked = false; + } + + return buffer; +} + + +const char* +KPath::Leaf() const +{ + if (fBuffer == NULL) + return NULL; + + for (int32 i = fPathLength - 1; i >= 0; i--) { + if (fBuffer[i] == '/') + return fBuffer + i + 1; + } + + return fBuffer; +} + + +status_t +KPath::ReplaceLeaf(const char* newLeaf) +{ + const char* leaf = Leaf(); + if (leaf == NULL) + return B_NO_INIT; + + int32 leafIndex = leaf - fBuffer; + // chop off the current leaf (don't replace "/", though) + if (leafIndex != 0 || fBuffer[leafIndex - 1]) { + fBuffer[leafIndex] = '\0'; + fPathLength = leafIndex; + _ChopTrailingSlashes(); + } + + // if a leaf was given, append it + if (newLeaf != NULL) + return Append(newLeaf); + return B_OK; +} + + +bool +KPath::RemoveLeaf() +{ + // get the leaf -- bail out, if not initialized or only the "/" is left + const char* leaf = Leaf(); + if (leaf == NULL || leaf == fBuffer || leaf[0] == '\0') + return false; + + // chop off the leaf + int32 leafIndex = leaf - fBuffer; + fBuffer[leafIndex] = '\0'; + fPathLength = leafIndex; + _ChopTrailingSlashes(); + + return true; +} + + +status_t +KPath::Append(const char* component, bool isComponent) +{ + // check initialization and parameter + if (fBuffer == NULL) + return B_NO_INIT; + if (component == NULL) + return B_BAD_VALUE; + if (fPathLength == 0) + return SetPath(component); + + // get component length + size_t componentLength = strlen(component); + if (componentLength < 1) + return B_OK; + + // if our current path is empty, we just copy the supplied one + // compute the result path len + bool insertSlash = isComponent && fBuffer[fPathLength - 1] != '/' + && component[0] != '/'; + size_t resultPathLength = fPathLength + componentLength + + (insertSlash ? 1 : 0); + if (resultPathLength >= fBufferSize) + return B_BUFFER_OVERFLOW; + + // compose the result path + if (insertSlash) + fBuffer[fPathLength++] = '/'; + memcpy(fBuffer + fPathLength, component, componentLength + 1); + fPathLength = resultPathLength; + return B_OK; +} + + +status_t +KPath::Normalize(bool traverseLeafLink) +{ + if (fBuffer == NULL) + return B_NO_INIT; + if (fPathLength == 0) + return B_BAD_VALUE; + + return _Normalize(fBuffer, traverseLeafLink); +} + + +KPath& +KPath::operator=(const KPath& other) +{ + SetTo(other.fBuffer, fLazy ? KPath::LAZY_ALLOC : KPath::DEFAULT, + other.fBufferSize); + return *this; +} + + +KPath& +KPath::operator=(const char* path) +{ + SetPath(path); + return *this; +} + + +bool +KPath::operator==(const KPath& other) const +{ + if (fBuffer == NULL) + return !other.fBuffer; + + return other.fBuffer != NULL + && fPathLength == other.fPathLength + && strcmp(fBuffer, other.fBuffer) == 0; +} + + +bool +KPath::operator==(const char* path) const +{ + if (fBuffer == NULL) + return path == NULL; + + return path != NULL && strcmp(fBuffer, path) == 0; +} + + +bool +KPath::operator!=(const KPath& other) const +{ + return !(*this == other); +} + + +bool +KPath::operator!=(const char* path) const +{ + return !(*this == path); +} + + +status_t +KPath::_AllocateBuffer() +{ + if (fBuffer == NULL && fBufferSize != 0) + fBuffer = (char*)malloc(fBufferSize); + if (fBuffer == NULL) { + fFailed = true; + return B_NO_MEMORY; + } + + fBuffer[0] = '\0'; + fFailed = false; + return B_OK; +} + + +status_t +KPath::_Normalize(const char* path, bool traverseLeafLink) +{ + BPath normalizedPath; + status_t error = normalizedPath.SetTo(path, NULL, true); + if (error != B_OK) { + fBuffer[0] = '\0'; + fPathLength = 0; + return error; + } + + strlcpy(fBuffer, normalizedPath.Path(), fBufferSize); + fPathLength = strlen(fBuffer); + return B_OK; +} + + +void +KPath::_ChopTrailingSlashes() +{ + if (fBuffer != NULL) { + while (fPathLength > 1 && fBuffer[fPathLength - 1] == '/') + fBuffer[--fPathLength] = '\0'; + } +} + diff --git a/src/tests/system/kernel/device_manager/playground/Jamfile b/src/tests/system/kernel/device_manager/playground/Jamfile index 6cf8ea6991..2d94d7a7dd 100644 --- a/src/tests/system/kernel/device_manager/playground/Jamfile +++ b/src/tests/system/kernel/device_manager/playground/Jamfile @@ -7,7 +7,6 @@ UsePrivateHeaders shared ; SimpleTest device_manager : device_manager.cpp - KPath.cpp bus.cpp driver.cpp diff --git a/src/tests/system/kernel/device_manager/playground/KPath.cpp b/src/tests/system/kernel/device_manager/playground/KPath.cpp deleted file mode 100644 index bf24b30671..0000000000 --- a/src/tests/system/kernel/device_manager/playground/KPath.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright 2004-2006, Ingo Weinhold, bonefish@users.sf.net. - * Distributed under the terms of the MIT License. - */ - -/** A simple class wrapping a path. Has a fixed-sized buffer. */ - -#include - -#include -#include - -#include - - -// debugging -#define TRACE(x) ; -//#define TRACE(x) dprintf x - - -KPath::KPath(size_t bufferSize) - : - fBuffer(NULL), - fBufferSize(0), - fPathLength(0), - fLocked(false) -{ - SetTo(NULL, false, bufferSize); -} - - -KPath::KPath(const char* path, bool normalize, size_t bufferSize) - : - fBuffer(NULL), - fBufferSize(0), - fPathLength(0), - fLocked(false) -{ - SetTo(path, normalize, bufferSize); -} - - -KPath::KPath(const KPath& other) - : - fBuffer(NULL), - fBufferSize(0), - fPathLength(0), - fLocked(false) -{ - *this = other; -} - - -KPath::~KPath() -{ - free(fBuffer); -} - - -status_t -KPath::SetTo(const char* path, bool normalize, size_t bufferSize) -{ - if (bufferSize == 0) - bufferSize = B_PATH_NAME_LENGTH; - - // free the previous buffer, if the buffer size differs - if (fBuffer && fBufferSize != bufferSize) { - free(fBuffer); - fBuffer = NULL; - fBufferSize = 0; - } - fPathLength = 0; - fLocked = false; - - // allocate buffer - if (!fBuffer) - fBuffer = (char*)malloc(bufferSize); - if (!fBuffer) - return B_NO_MEMORY; - if (fBuffer) { - fBufferSize = bufferSize; - fBuffer[0] = '\0'; - } - return SetPath(path, normalize); -} - - -void -KPath::Adopt(KPath& other) -{ - free(fBuffer); - - fBuffer = other.fBuffer; - fBufferSize = other.fBufferSize; - - other.fBuffer = NULL; -} - - -status_t -KPath::InitCheck() const -{ - return fBuffer ? B_OK : B_NO_MEMORY; -} - - -status_t -KPath::SetPath(const char *path, bool normalize) -{ - if (!fBuffer) - return B_NO_INIT; - - if (path) { - if (normalize) { - // normalize path - BPath normalizedPath; - status_t error = normalizedPath.SetTo(path, NULL, true); - if (error != B_OK) { - SetPath(NULL); - return error; - } - - strlcpy(fBuffer, normalizedPath.Path(), fBufferSize); - fPathLength = strlen(fBuffer); - } else { - // don't normalize path - size_t length = strlen(path); - if (length >= fBufferSize) - return B_BUFFER_OVERFLOW; - - memcpy(fBuffer, path, length + 1); - fPathLength = length; - _ChopTrailingSlashes(); - } - } else { - fBuffer[0] = '\0'; - fPathLength = 0; - } - return B_OK; -} - - -const char* -KPath::Path() const -{ - return fBuffer; -} - - -char * -KPath::LockBuffer() -{ - if (!fBuffer || fLocked) - return NULL; - - fLocked = true; - return fBuffer; -} - - -void -KPath::UnlockBuffer() -{ - if (!fLocked) { - TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n")); - return; - } - fLocked = false; - fPathLength = strnlen(fBuffer, fBufferSize); - if (fPathLength == fBufferSize) { - TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n")); - fPathLength--; - fBuffer[fPathLength] = '\0'; - } - _ChopTrailingSlashes(); -} - - -const char * -KPath::Leaf() const -{ - if (!fBuffer) - return NULL; - - // only "/" has trailing slashes -- then we have to return the complete - // buffer, as we have to do in case there are no slashes at all - if (fPathLength != 1 || fBuffer[0] != '/') { - for (int32 i = fPathLength - 1; i >= 0; i--) { - if (fBuffer[i] == '/') - return fBuffer + i + 1; - } - } - return fBuffer; -} - - -status_t -KPath::ReplaceLeaf(const char *newLeaf) -{ - const char *leaf = Leaf(); - if (!leaf) - return B_NO_INIT; - - int32 leafIndex = leaf - fBuffer; - // chop off the current leaf (don't replace "/", though) - if (leafIndex != 0 || fBuffer[leafIndex - 1]) { - fBuffer[leafIndex] = '\0'; - fPathLength = leafIndex; - _ChopTrailingSlashes(); - } - - // if a leaf was given, append it - if (newLeaf) - return Append(newLeaf); - return B_OK; -} - - -bool -KPath::RemoveLeaf() -{ - // get the leaf -- bail out, if not initialized or only the "/" is left - const char *leaf = Leaf(); - if (!leaf || leaf == fBuffer) - return false; - - // chop off the leaf - int32 leafIndex = leaf - fBuffer; - fBuffer[leafIndex] = '\0'; - fPathLength = leafIndex; - _ChopTrailingSlashes(); - - return true; -} - - -status_t -KPath::Append(const char *component, bool isComponent) -{ - // check initialization and parameter - if (!fBuffer) - return B_NO_INIT; - if (!component) - return B_BAD_VALUE; - if (fPathLength == 0) - return SetPath(component); - - // get component length - size_t componentLength = strlen(component); - if (componentLength < 1) - return B_OK; - - // if our current path is empty, we just copy the supplied one - // compute the result path len - bool insertSlash = isComponent && fBuffer[fPathLength - 1] != '/' - && component[0] != '/'; - size_t resultPathLength = fPathLength + componentLength + (insertSlash ? 1 : 0); - if (resultPathLength >= fBufferSize) - return B_BUFFER_OVERFLOW; - - // compose the result path - if (insertSlash) - fBuffer[fPathLength++] = '/'; - memcpy(fBuffer + fPathLength, component, componentLength + 1); - fPathLength = resultPathLength; - return B_OK; -} - - -KPath& -KPath::operator=(const KPath& other) -{ - SetTo(other.fBuffer, other.fBufferSize); - return *this; -} - - -KPath& -KPath::operator=(const char* path) -{ - SetTo(path); - return *this; -} - - -bool -KPath::operator==(const KPath& other) const -{ - if (!fBuffer) - return !other.fBuffer; - - return (other.fBuffer - && fPathLength == other.fPathLength - && strcmp(fBuffer, other.fBuffer) == 0); -} - - -bool -KPath::operator==(const char* path) const -{ - if (!fBuffer) - return (!path); - - return path && !strcmp(fBuffer, path); -} - - -bool -KPath::operator!=(const KPath& other) const -{ - return !(*this == other); -} - - -bool -KPath::operator!=(const char* path) const -{ - return !(*this == path); -} - - -void -KPath::_ChopTrailingSlashes() -{ - if (fBuffer) { - while (fPathLength > 1 && fBuffer[fPathLength - 1] == '/') - fBuffer[--fPathLength] = '\0'; - } -} -