* Flatten() would create an invalid entry ref if the path did not exist, or the

path was not yet initialized. It will now fail instead.
* Got rid of EBadInput - _MustNormalize() can now return an error code instead.
* Style cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30787 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2009-05-18 09:09:23 +00:00
parent 2ae482f582
commit 49fb9a2eab
2 changed files with 306 additions and 280 deletions

View File

@ -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 <Flattenable.h>
#include <StorageDefs.h>
#include <Message.h> /* for convenience, as in R5 */
#ifdef USE_OPENBEOS_NAMESPACE
namespace OpenBeOS {
#endif
#include <Flattenable.h>
#include <Message.h>
#include <StorageDefs.h>
// 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 <a href='mailto:bonefish@users.sf.net'>Ingo Weinhold</a>
\author <a href="mailto:tylerdauwalder@users.sf.net">Tyler Dauwalder</a>
\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

View File

@ -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 <Path.h>
#include <new>
#include <Path.h>
#include <Directory.h>
#include <Entry.h>
#include <StorageDefs.h>
@ -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.
*/