diff --git a/headers/os/storage/Path.h b/headers/os/storage/Path.h index e3ba9f1e87..0e27303b0f 100644 --- a/headers/os/storage/Path.h +++ b/headers/os/storage/Path.h @@ -1,103 +1,79 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the OpenBeOS license. -//--------------------------------------------------------------------- -/*! - \file Path.h - BPath interface declaration. -*/ - +/* + * Copyright 2002-2009, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ #ifndef _PATH_H #define _PATH_H -#include -#include -#include /* for convenience, as in R5 */ -#ifdef USE_OPENBEOS_NAMESPACE -namespace OpenBeOS { -#endif +#include +#include +#include + // Forward declarations class BDirectory; class BEntry; struct entry_ref; -/*! - \class BPath - \brief An absolute pathname wrapper class - - Provides a convenient means of managing pathnames. - \author Ingo Weinhold - \author Tyler Dauwalder - - \version 0.0.0 -*/ class BPath : public BFlattenable { public: + BPath(); + BPath(const BPath& path); + BPath(const entry_ref* ref); + BPath(const BEntry* entry); + BPath(const char* dir, const char* leaf = NULL, + bool normalize = false); + BPath(const BDirectory* dir, const char* leaf, + bool normalize = false); - BPath(); - BPath(const BPath &path); - BPath(const entry_ref *ref); - BPath(const BEntry *entry); - BPath(const char *dir, const char *leaf = NULL, bool normalize = false); - BPath(const BDirectory *dir, const char *leaf, bool normalize = false); - - virtual ~BPath(); + virtual ~BPath(); - status_t InitCheck() const; + status_t InitCheck() const; + + status_t SetTo(const entry_ref* ref); + status_t SetTo(const BEntry* entry); + status_t SetTo(const char* path, const char* leaf = NULL, + bool normalize = false); + status_t SetTo(const BDirectory* dir, const char* path, + bool normalize = false); + void Unset(); + + status_t Append(const char* path, bool normalize = false); + + const char* Path() const; + const char* Leaf() const; + status_t GetParent(BPath* path) const; + + bool operator==(const BPath& item) const; + bool operator==(const char* path) const; + bool operator!=(const BPath& item) const; + bool operator!=(const char* path) const; + BPath& operator=(const BPath& item); + BPath& operator=(const char* path); - status_t SetTo(const entry_ref *ref); - status_t SetTo(const BEntry *entry); - status_t SetTo(const char *path, const char *leaf = NULL, - bool normalize = false); - status_t SetTo(const BDirectory *dir, const char *path, - bool normalize = false); - void Unset(); - - status_t Append(const char *path, bool normalize = false); - - const char *Path() const; - const char *Leaf() const; - status_t GetParent(BPath *path) const; - - bool operator==(const BPath &item) const; - bool operator==(const char *path) const; - bool operator!=(const BPath &item) const; - bool operator!=(const char *path) const; - BPath& operator=(const BPath &item); - BPath& operator=(const char *path); - // BFlattenable protocol - virtual bool IsFixedSize() const; - virtual type_code TypeCode() const; - virtual ssize_t FlattenedSize() const; - virtual status_t Flatten(void *buffer, ssize_t size) const; - virtual bool AllowsTypeCode(type_code code) const; - virtual status_t Unflatten(type_code c, const void *buf, ssize_t size); + virtual bool IsFixedSize() const; + virtual type_code TypeCode() const; + virtual ssize_t FlattenedSize() const; + virtual status_t Flatten(void* buffer, ssize_t size) const; + virtual bool AllowsTypeCode(type_code code) const; + virtual status_t Unflatten(type_code code, const void* buffer, + ssize_t size); private: - virtual void _WarPath1(); - virtual void _WarPath2(); - virtual void _WarPath3(); + virtual void _WarPath1(); + virtual void _WarPath2(); + virtual void _WarPath3(); - uint32 _warData[4]; + status_t _SetPath(const char* path); + static bool _MustNormalize(const char* path, status_t* _error); - char *fName; - status_t fCStatus; + uint32 _reserved[4]; - class EBadInput { }; - - status_t set_path(const char *path); - - static bool MustNormalize(const char *path); + char* fName; + status_t fCStatus; }; -#ifdef USE_OPENBEOS_NAMESPACE -}; // namespace OpenBeOS -#endif - #endif // _PATH_H - - diff --git a/src/kits/storage/Path.cpp b/src/kits/storage/Path.cpp index 74a207021f..7ba3171ab8 100644 --- a/src/kits/storage/Path.cpp +++ b/src/kits/storage/Path.cpp @@ -1,15 +1,21 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the OpenBeOS license. -//--------------------------------------------------------------------- +/* + * Copyright 2002-2009, Haiku Inc. + * Distributed under the terms of the MIT License. + * + * Authors: + * Tyler Dauwalder + * Ingo Weinhold, bonefish@users.sf.net + */ + /*! \file Path.cpp BPath implementation. */ +#include + #include -#include #include #include #include @@ -21,66 +27,74 @@ using namespace std; -#ifdef USE_OPENBEOS_NAMESPACE -using namespace OpenBeOS; -#endif -//! Creates an uninitialized BPath object. +//! Creates an uninitialized BPath object. BPath::BPath() - : fName(NULL), - fCStatus(B_NO_INIT) + : + fName(NULL), + fCStatus(B_NO_INIT) { } - -//! Creates a copy of the given BPath object. -/*! \param path the object to be copied + + +/*! Creates a copy of the given BPath object. + \param path the object to be copied */ -BPath::BPath(const BPath &path) - : fName(NULL), - fCStatus(B_NO_INIT) +BPath::BPath(const BPath& path) + : + fName(NULL), + fCStatus(B_NO_INIT) { *this = path; } + /*! \brief Creates a BPath object and initializes it to the filesystem entry specified by the given entry_ref struct. \param ref the entry_ref */ -BPath::BPath(const entry_ref *ref) - : fName(NULL), - fCStatus(B_NO_INIT) +BPath::BPath(const entry_ref* ref) + : + fName(NULL), + fCStatus(B_NO_INIT) { SetTo(ref); } -/*! Creates a BPath object and initializes it to the filesystem entry + +/*! \brief Creates a BPath object and initializes it to the filesystem entry specified by the given BEntry object. \param entry the BEntry object */ -BPath::BPath(const BEntry *entry) - : fName(NULL), - fCStatus(B_NO_INIT) +BPath::BPath(const BEntry* entry) + : + fName(NULL), + fCStatus(B_NO_INIT) { SetTo(entry); } + /*! \brief Creates a BPath object and initializes it to the specified path or path and filename combination. + \param dir The base component of the pathname. May be absolute or relative. If relative, it is reckoned off the current working directory. \param leaf The (optional) leaf component of the pathname. Must be relative. The value of leaf is concatenated to the end of \a dir (a "/" will be added as a separator, if necessary). \param normalize boolean flag used to force normalization; normalization - may occur even if false (see \ref MustNormalize). + may occur even if false (see \ref _MustNormalize). */ -BPath::BPath(const char *dir, const char *leaf, bool normalize) - : fName(NULL), - fCStatus(B_NO_INIT) +BPath::BPath(const char* dir, const char* leaf, bool normalize) + : + fName(NULL), + fCStatus(B_NO_INIT) { SetTo(dir, leaf, normalize); } - + + /*! \brief Creates a BPath object and initializes it to the specified directory and filename combination. \param dir Refers to the directory that provides the base component of the @@ -89,23 +103,26 @@ BPath::BPath(const char *dir, const char *leaf, bool normalize) relative. The value of leaf is concatenated to the end of \a dir (a "/" will be added as a separator, if necessary). \param normalize boolean flag used to force normalization; normalization - may occur even if false (see \ref MustNormalize). + may occur even if false (see \ref _MustNormalize). */ -BPath::BPath(const BDirectory *dir, const char *leaf, bool normalize) - : fName(NULL), - fCStatus(B_NO_INIT) +BPath::BPath(const BDirectory* dir, const char* leaf, bool normalize) + : + fName(NULL), + fCStatus(B_NO_INIT) { SetTo(dir, leaf, normalize); } + //! Destroys the BPath object and frees any of its associated resources. BPath::~BPath() { Unset(); } -//! Returns the status of the most recent construction or SetTo() call. -/*! \return \c B_OK, if the BPath object is properly initialized, an error + +/*! \brief Returns the status of the most recent construction or SetTo() call. + \return \c B_OK, if the BPath object is properly initialized, an error code otherwise. */ status_t @@ -114,6 +131,7 @@ BPath::InitCheck() const return fCStatus; } + /*! \brief Reinitializes the object to the filesystem entry specified by the given entry_ref struct. \param ref the entry_ref @@ -124,21 +142,24 @@ BPath::InitCheck() const - other error codes. */ status_t -BPath::SetTo(const entry_ref *ref) +BPath::SetTo(const entry_ref* ref) { Unset(); if (!ref) - return (fCStatus = B_BAD_VALUE); + return fCStatus = B_BAD_VALUE; char path[B_PATH_NAME_LENGTH]; - status_t error = _kern_entry_ref_to_path(ref->device, ref->directory, + fCStatus = _kern_entry_ref_to_path(ref->device, ref->directory, ref->name, path, sizeof(path)); - if (error != B_OK) - return (fCStatus = error); - fCStatus = set_path(path); // the path is already normalized + if (fCStatus != B_OK) + return fCStatus; + + fCStatus = _SetPath(path); + // the path is already normalized return fCStatus; } + /*! \brief Reinitializes the object to the specified filesystem entry. \param entry the BEntry \return @@ -148,25 +169,27 @@ BPath::SetTo(const entry_ref *ref) - other error codes. */ status_t -BPath::SetTo(const BEntry *entry) +BPath::SetTo(const BEntry* entry) { Unset(); - status_t error = (entry ? B_OK : B_BAD_VALUE); + if (entry == NULL) + return B_BAD_VALUE; + entry_ref ref; - if (error == B_OK) - error = entry->GetRef(&ref); - if (error == B_OK) - error = SetTo(&ref); - fCStatus = error; - return error; + fCStatus = entry->GetRef(&ref); + if (fCStatus == B_OK) + fCStatus = SetTo(&ref); + + return fCStatus; } - + + /*! \brief Reinitializes the object to the specified path or path and file name combination. \param path the path name \param leaf the leaf name (may be \c NULL) \param normalize boolean flag used to force normalization; normalization - may occur even if false (see \ref MustNormalize). + may occur even if false (see \ref _MustNormalize). \return - \c B_OK: The initialization was successful. - \c B_BAD_VALUE: \c NULL \a path or absolute \a leaf. @@ -175,7 +198,7 @@ BPath::SetTo(const BEntry *entry) \note \code path.SetTo(path.Path(), "new leaf") \endcode is safe. */ status_t -BPath::SetTo(const char *path, const char *leaf, bool normalize) +BPath::SetTo(const char* path, const char* leaf, bool normalize) { status_t error = (path ? B_OK : B_BAD_VALUE); if (error == B_OK && leaf && BPrivate::Storage::is_absolute_path(leaf)) @@ -207,13 +230,9 @@ BPath::SetTo(const char *path, const char *leaf, bool normalize) } } // check, if necessary to normalize - if (error == B_OK && !normalize) { - try { - normalize = normalize || MustNormalize(newPath); - } catch (BPath::EBadInput) { - error = B_BAD_VALUE; - } - } + if (error == B_OK && !normalize) + normalize = normalize || _MustNormalize(newPath, &error); + // normalize the path, if necessary, otherwise just set it if (error == B_OK) { if (normalize) { @@ -223,7 +242,7 @@ BPath::SetTo(const char *path, const char *leaf, bool normalize) if (error == B_OK) return SetTo(&entry); } else - error = set_path(newPath); + error = _SetPath(newPath); } } // cleanup, if something went wrong @@ -232,14 +251,15 @@ BPath::SetTo(const char *path, const char *leaf, bool normalize) fCStatus = error; return error; } - + + /*! \brief Reinitializes the object to the specified directory and relative path combination. \param dir Refers to the directory that provides the base component of the pathname. \param path the relative path name (may be \c NULL) \param normalize boolean flag used to force normalization; normalization - may occur even if false (see \ref MustNormalize). + may occur even if false (see \ref _MustNormalize). \return - \c B_OK: The initialization was successful. - \c B_BAD_VALUE: \c NULL \a dir or absolute \a path. @@ -247,7 +267,7 @@ BPath::SetTo(const char *path, const char *leaf, bool normalize) - other error codes. */ status_t -BPath::SetTo(const BDirectory *dir, const char *path, bool normalize) +BPath::SetTo(const BDirectory* dir, const char* path, bool normalize) { status_t error = (dir && dir->InitCheck() == B_OK ? B_OK : B_BAD_VALUE); // get the path of the BDirectory @@ -265,23 +285,25 @@ BPath::SetTo(const BDirectory *dir, const char *path, bool normalize) fCStatus = error; return error; } - + + /*! \brief Returns the object to an uninitialized state. The object frees any resources it allocated and marks itself as uninitialized. */ void BPath::Unset() { - set_path(NULL); + _SetPath(NULL); fCStatus = B_NO_INIT; } - + + /*! \brief Appends the given (relative) path to the end of the current path. This call fails if the path is absolute or the object to which you're appending is uninitialized. \param path relative pathname to append to current path (may be \c NULL). \param normalize boolean flag used to force normalization; normalization - may occur even if false (see \ref MustNormalize). + may occur even if false (see \ref _MustNormalize). \return - \c B_OK: The initialization was successful. - \c B_BAD_VALUE: The object is not properly initialized. @@ -289,7 +311,7 @@ BPath::Unset() - other error codes. */ status_t -BPath::Append(const char *path, bool normalize) +BPath::Append(const char* path, bool normalize) { status_t error = (InitCheck() == B_OK ? B_OK : B_BAD_VALUE); if (error == B_OK) @@ -299,41 +321,45 @@ BPath::Append(const char *path, bool normalize) fCStatus = error; return error; } - -//! Returns the object's complete path name. -/*! \return + + +/*! \brief Returns the object's complete path name. + \return - the object's path name, or - \c NULL, if it is not properly initialized. */ -const char * +const char* BPath::Path() const { return fName; } - -//! Returns the leaf portion of the object's path name. -/*! The leaf portion is defined as the string after the last \c '/'. For + + +/*! \brief Returns the leaf portion of the object's path name. + The leaf portion is defined as the string after the last \c '/'. For the root path (\c "/") it is the empty string (\c ""). \return - the leaf portion of the object's path name, or - \c NULL, if it is not properly initialized. */ -const char * +const char* BPath::Leaf() const { - const char *result = NULL; - if (InitCheck() == B_OK) { - result = fName + strlen(fName); - // There should be no need for the second condition, since we deal - // with absolute paths only and those contain at least one '/'. - // However, it doesn't harm. - while (*result != '/' && result > fName) - result--; - result++; - } + if (InitCheck() != B_OK) + return NULL; + + const char* result = fName + strlen(fName); + // There should be no need for the second condition, since we deal + // with absolute paths only and those contain at least one '/'. + // However, it doesn't harm. + while (*result != '/' && result > fName) + result--; + result++; + return result; } + /*! \brief Calls the argument's SetTo() method with the name of the object's parent directory. No normalization is done. @@ -346,96 +372,107 @@ BPath::Leaf() const - other error code returned by SetTo(). */ status_t -BPath::GetParent(BPath *path) const +BPath::GetParent(BPath* path) const { - status_t error = (path ? B_OK : B_BAD_VALUE); - if (error == B_OK) - error = InitCheck(); - if (error == B_OK) { - int32 len = strlen(fName); - if (len == 1) // handle "/" - error = B_ENTRY_NOT_FOUND; - else { - char parentPath[B_PATH_NAME_LENGTH]; - len--; - while (fName[len] != '/' && len > 0) - len--; - if (len == 0) // parent dir is "/" - len++; - memcpy(parentPath, fName, len); - parentPath[len] = 0; - error = path->SetTo(parentPath); - } + if (path == NULL) + return B_BAD_VALUE; + + status_t error = InitCheck(); + if (error != B_OK) + return error; + + int32 length = strlen(fName); + if (length == 1) { + // handle "/" (path is supposed to be absolute) + return B_ENTRY_NOT_FOUND; } - return error; + + char parentPath[B_PATH_NAME_LENGTH]; + length--; + while (fName[length] != '/' && length > 0) + length--; + if (length == 0) { + // parent dir is "/" + length++; + } + memcpy(parentPath, fName, length); + parentPath[length] = '\0'; + + return path->SetTo(parentPath); } - -//! Performs a simple (string-wise) comparison of paths. -/*! No normalization takes place! Uninitialized BPath objects are considered + + +/*! \brief Performs a simple (string-wise) comparison of paths. + No normalization takes place! Uninitialized BPath objects are considered to be equal. \param item the BPath object to be compared with \return \c true, if the path names are equal, \c false otherwise. */ bool -BPath::operator==(const BPath &item) const +BPath::operator==(const BPath& item) const { - return (*this == item.Path()); + return *this == item.Path(); } -//! Performs a simple (string-wise) comparison of paths. -/*! No normalization takes place! + +/*! \brief Performs a simple (string-wise) comparison of paths. + No normalization takes place! \param path the path name to be compared with \return \c true, if the path names are equal, \c false otherwise. */ bool -BPath::operator==(const char *path) const +BPath::operator==(const char* path) const { - return ((InitCheck() != B_OK && path == NULL) - || (fName != NULL && path != NULL && strcmp(fName, path) == 0)); + return (InitCheck() != B_OK && path == NULL) + || (fName != NULL && path != NULL && strcmp(fName, path) == 0); } -//! Performs a simple (string-wise) comparison of paths. -/*! No normalization takes place! Uninitialized BPath objects are considered + +/*! \brief Performs a simple (string-wise) comparison of paths. + No normalization takes place! Uninitialized BPath objects are considered to be equal. \param item the BPath object to be compared with \return \c true, if the path names are not equal, \c false otherwise. */ bool -BPath::operator!=(const BPath &item) const +BPath::operator!=(const BPath& item) const { return !(*this == item); } -//! Performs a simple (string-wise) comparison of paths. -/*! No normalization takes place! + +/*! \brief Performs a simple (string-wise) comparison of paths. + No normalization takes place! \param path the path name to be compared with \return \c true, if the path names are not equal, \c false otherwise. */ bool -BPath::operator!=(const char *path) const +BPath::operator!=(const char* path) const { return !(*this == path); } - -//! Initializes the object to be a copy of the argument. -/*! \param item the BPath object to be copied + + +/*! \brief Initializes the object to be a copy of the argument. + \param item the BPath object to be copied \return \c *this */ BPath& -BPath::operator=(const BPath &item) +BPath::operator=(const BPath& item) { if (this != &item) *this = item.Path(); return *this; } -//! Initializes the object to be a copy of the argument. -/*! Has the same effect as \code SetTo(path) \endcode. + +/*! \brief Initializes the object to be a copy of the argument. + Has the same effect as \code SetTo(path) \endcode. \param path the path name to be assigned to this object \return \c *this */ BPath& -BPath::operator=(const char *path) +BPath::operator=(const char* path) { if (path == NULL) Unset(); @@ -445,7 +482,8 @@ BPath::operator=(const char *path) } -// BFlattenable functionality +// #pragma mark - BFlattenable functionality + // that's the layout of a flattened entry_ref struct flattened_entry_ref { @@ -459,8 +497,8 @@ static const size_t flattened_entry_ref_size = sizeof(dev_t) + sizeof(ino_t); -//! Returns \c false. -/*! Implements BFlattenable. +/*! \brief Returns \c false. + Implements BFlattenable. \return \c false */ bool @@ -468,9 +506,10 @@ BPath::IsFixedSize() const { return false; } - -//! Returns \c B_REF_TYPE. -/*! Implements BFlattenable. + + +/*! \brief Returns \c B_REF_TYPE. + Implements BFlattenable. \return \c B_REF_TYPE */ type_code @@ -478,7 +517,8 @@ BPath::TypeCode() const { return B_REF_TYPE; } - + + /*! \brief Returns the size of the flattened entry_ref structure that represents the pathname. Implements BFlattenable. @@ -497,7 +537,8 @@ BPath::FlattenedSize() const } return size; } - + + /*! \brief Converts the object's pathname to an entry_ref and writes it into buffer. Implements BFlattenable. @@ -510,43 +551,52 @@ BPath::FlattenedSize() const \todo Reimplement for performance reasons: Don't call FlattenedSize(). */ status_t -BPath::Flatten(void *buffer, ssize_t size) const +BPath::Flatten(void* buffer, ssize_t size) const { - status_t error = (buffer ? B_OK : B_BAD_VALUE); - if (error == B_OK) { - ssize_t flattenedSize = FlattenedSize(); - if (flattenedSize < 0) - error = flattenedSize; - if (error == B_OK && size < flattenedSize) - error = B_BAD_VALUE; - if (error == B_OK) { - // convert the path to an entry_ref - BEntry entry; - entry_ref ref; - if (InitCheck() == B_OK && entry.SetTo(Path()) == B_OK) - entry.GetRef(&ref); - // store the entry_ref in the buffer - flattened_entry_ref &fref = *(flattened_entry_ref*)buffer; - fref.device = ref.device; - fref.directory = ref.directory; - if (ref.name) - strcpy(fref.name, ref.name); - } - } - return error; + if (buffer == NULL) + return B_BAD_VALUE; + + ssize_t flattenedSize = FlattenedSize(); + if (flattenedSize < 0) + return flattenedSize; + if (size < flattenedSize) + return B_BAD_VALUE; + status_t status = InitCheck(); + if (status != B_OK) + return status; + + // convert the path to an entry_ref + BEntry entry; + entry_ref ref; + status = entry.SetTo(Path()); + if (status == B_OK) + status = entry.GetRef(&ref); + if (status != B_OK) + return status; + + // store the entry_ref in the buffer + flattened_entry_ref& fref = *(flattened_entry_ref*)buffer; + fref.device = ref.device; + fref.directory = ref.directory; + if (ref.name) + strcpy(fref.name, ref.name); + + return B_OK; } - -//! Returns \c true if code is \c B_REF_TYPE, and false otherwise. -/*! Implements BFlattenable. + + +/*! \brief Returns \c true if code is \c B_REF_TYPE, and false otherwise. + Implements BFlattenable. \param code the type code in question \return \c true if code is \c B_REF_TYPE, and false otherwise. */ bool BPath::AllowsTypeCode(type_code code) const { - return (code == B_REF_TYPE); + return code == B_REF_TYPE; } - + + /*! \brief Initializes the BPath with the flattened entry_ref data that's found in the supplied buffer. The type code must be \c B_REF_TYPE. @@ -561,12 +611,12 @@ BPath::AllowsTypeCode(type_code code) const - other error codes. */ status_t -BPath::Unflatten(type_code code, const void *buf, ssize_t size) +BPath::Unflatten(type_code code, const void* buffer, ssize_t size) { Unset(); status_t error = B_OK; // check params - if (!(code == B_REF_TYPE && buf + if (!(code == B_REF_TYPE && buffer != NULL && size >= (ssize_t)flattened_entry_ref_size)) { error = B_BAD_VALUE; } @@ -575,7 +625,8 @@ BPath::Unflatten(type_code code, const void *buf, ssize_t size) // already Unset(); } else { // reconstruct the entry_ref from the buffer - const flattened_entry_ref &fref = *(const flattened_entry_ref*)buf; + const flattened_entry_ref& fref + = *(const flattened_entry_ref*)buffer; BString name(fref.name, size - flattened_entry_ref_size); entry_ref ref(fref.device, fref.directory, name.String()); error = SetTo(&ref); @@ -586,10 +637,12 @@ BPath::Unflatten(type_code code, const void *buf, ssize_t size) return error; } + void BPath::_WarPath1() {} void BPath::_WarPath2() {} void BPath::_WarPath3() {} + /*! \brief Sets the supplied path. The path is copied. If \c NULL, the object's path is set to NULL as well. The object's old path is deleted. @@ -599,10 +652,10 @@ void BPath::_WarPath3() {} - \c B_NO_MEMORY: Insufficient memory. */ status_t -BPath::set_path(const char *path) +BPath::_SetPath(const char* path) { status_t error = B_OK; - const char *oldPath = fName; + const char* oldPath = fName; // set the new path if (path) { fName = new(nothrow) char[strlen(path) + 1]; @@ -612,37 +665,39 @@ BPath::set_path(const char *path) error = B_NO_MEMORY; } else fName = NULL; + // delete the old one delete[] oldPath; return error; } - /*! \brief Checks a path to see if normalization is required. The following items require normalization: - - Relative pathnames (after concatenation; e.g. "boot/ltj") + - Relative pathnames (after concatenation; e.g. "boot/ltj") - The presence of "." or ".." ("/boot/ltj/../ltj/./gwar") - Redundant slashes ("/boot//ltj") - A trailing slash ("/boot/ltj/") - + + \param _error A pointer to an error variable that will be set if the input + is not a valid path. \return - \c true: \a path requires normalization - \c false: \a path does not require normalization - - \exception BPath::EBadInput : \a path is \c NULL or an empty string. - - */ +*/ bool -BPath::MustNormalize(const char *path) +BPath::_MustNormalize(const char* path, status_t* _error) { // Check for useless input - if (path == NULL || path[0] == 0) - throw BPath::EBadInput(); - - int len = strlen(path); - + if (path == NULL || path[0] == 0) { + if (_error != NULL) + *_error = B_BAD_VALUE; + return false; + } + + int len = strlen(path); + /* Look for anything in the string that forces us to normalize: + No leading / + any occurence of /./ or /../ or //, or a trailing /. or /.. @@ -661,54 +716,52 @@ BPath::MustNormalize(const char *path) OneDot, TwoDots } state = NoMatch; - + for (int i = 0; path[i] != 0; i++) { switch (state) { case NoMatch: if (path[i] == '/') state = InitialSlash; break; - + case InitialSlash: if (path[i] == '/') return true; // "*//*" - else if (path[i] == '.') + + if (path[i] == '.') state = OneDot; else state = NoMatch; break; - + case OneDot: if (path[i] == '/') return true; // "*/./*" - else if (path[i] == '.') + + if (path[i] == '.') state = TwoDots; else state = NoMatch; break; - + case TwoDots: if (path[i] == '/') return true; // "*/../*" - else - state = NoMatch; - break; + + state = NoMatch; + break; } } + // If we hit the end of the string while in either // of these two states, there was a trailing /. or /.. if (state == OneDot || state == TwoDots) return true; - else - return false; + + return false; } - } -/*! \class BPath::EBadInput - \brief Internal exception class thrown by BPath::MustNormalize() when given - invalid input. -*/ /*! \var char *BPath::fName @@ -719,6 +772,3 @@ BPath::MustNormalize(const char *path) \var status_t BPath::fCStatus \brief The object's initialization status. */ - - -