mirror of
https://review.haiku-os.org/haiku
synced 2025-02-10 15:49:27 +01:00
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1131 a95241bf-73f2-0310-859d-f6bbb57e9c96
331 lines
7.8 KiB
C++
331 lines
7.8 KiB
C++
//----------------------------------------------------------------------
|
|
// This software is part of the OpenBeOS distribution and is covered
|
|
// by the OpenBeOS license.
|
|
//---------------------------------------------------------------------
|
|
/*!
|
|
\file SymLink.cpp
|
|
BSymLink implementation.
|
|
*/
|
|
|
|
#include <new>
|
|
|
|
#include <SymLink.h>
|
|
#include <Directory.h>
|
|
#include <Entry.h>
|
|
#include <Entry.h>
|
|
#include <Path.h>
|
|
#include "kernel_interface.h"
|
|
#include "storage_support.h"
|
|
|
|
#ifdef USE_OPENBEOS_NAMESPACE
|
|
namespace OpenBeOS {
|
|
#endif
|
|
|
|
// constructor
|
|
//! Creates an uninitialized BSymLink object.
|
|
BSymLink::BSymLink()
|
|
: BNode()
|
|
// WORKAROUND
|
|
, fSecretEntry(new(nothrow) BEntry)
|
|
{
|
|
}
|
|
|
|
// copy constructor
|
|
//! Creates a copy of the supplied BSymLink.
|
|
/*! \param link the BSymLink object to be copied
|
|
*/
|
|
BSymLink::BSymLink(const BSymLink &link)
|
|
: BNode()
|
|
// WORKAROUND
|
|
, fSecretEntry(new(nothrow) BEntry)
|
|
{
|
|
*this = link;
|
|
}
|
|
|
|
// constructor
|
|
/*! \brief Creates a BSymLink and initializes it to the symbolic link referred
|
|
to by the supplied entry_ref.
|
|
\param ref the entry_ref referring to the symbolic link
|
|
*/
|
|
BSymLink::BSymLink(const entry_ref *ref)
|
|
: BNode()
|
|
// WORKAROUND
|
|
, fSecretEntry(new(nothrow) BEntry)
|
|
{
|
|
SetTo(ref);
|
|
}
|
|
|
|
// constructor
|
|
/*! \brief Creates a BSymLink and initializes it to the symbolic link referred
|
|
to by the supplied BEntry.
|
|
\param entry the BEntry referring to the symbolic link
|
|
*/
|
|
BSymLink::BSymLink(const BEntry *entry)
|
|
: BNode()
|
|
// WORKAROUND
|
|
, fSecretEntry(new(nothrow) BEntry)
|
|
{
|
|
SetTo(entry);
|
|
}
|
|
|
|
// constructor
|
|
/*! \brief Creates a BSymLink and initializes it to the symbolic link referred
|
|
to by the supplied path name.
|
|
\param path the symbolic link's path name
|
|
*/
|
|
BSymLink::BSymLink(const char *path)
|
|
: BNode()
|
|
// WORKAROUND
|
|
, fSecretEntry(new(nothrow) BEntry)
|
|
{
|
|
SetTo(path);
|
|
}
|
|
|
|
// constructor
|
|
/*! \brief Creates a BSymLink and initializes it to the symbolic link referred
|
|
to by the supplied path name relative to the specified BDirectory.
|
|
\param dir the BDirectory, relative to which the symbolic link's path name
|
|
is given
|
|
\param path the symbolic link's path name relative to \a dir
|
|
*/
|
|
BSymLink::BSymLink(const BDirectory *dir, const char *path)
|
|
: BNode()
|
|
// WORKAROUND
|
|
, fSecretEntry(new(nothrow) BEntry)
|
|
{
|
|
SetTo(dir, path);
|
|
}
|
|
|
|
// destructor
|
|
//! Frees all allocated resources.
|
|
/*! If the BSymLink is properly initialized, the symbolic link's file
|
|
descriptor is closed.
|
|
*/
|
|
BSymLink::~BSymLink()
|
|
{
|
|
// WORKAROUND
|
|
delete fSecretEntry;
|
|
}
|
|
|
|
// WORKAROUND
|
|
status_t
|
|
BSymLink::SetTo(const entry_ref *ref)
|
|
{
|
|
status_t error = BNode::SetTo(ref);
|
|
if (fSecretEntry) {
|
|
fSecretEntry->Unset();
|
|
if (error == B_OK)
|
|
fSecretEntry->SetTo(ref);
|
|
} else
|
|
error = B_NO_MEMORY;
|
|
return error;
|
|
}
|
|
|
|
// WORKAROUND
|
|
status_t
|
|
BSymLink::SetTo(const BEntry *entry)
|
|
{
|
|
status_t error = BNode::SetTo(entry);
|
|
if (fSecretEntry) {
|
|
fSecretEntry->Unset();
|
|
if (error == B_OK)
|
|
*fSecretEntry = *entry;
|
|
} else
|
|
error = B_NO_MEMORY;
|
|
return error;
|
|
}
|
|
|
|
// WORKAROUND
|
|
status_t
|
|
BSymLink::SetTo(const char *path)
|
|
{
|
|
status_t error = BNode::SetTo(path);
|
|
if (fSecretEntry) {
|
|
fSecretEntry->Unset();
|
|
if (error == B_OK)
|
|
fSecretEntry->SetTo(path);
|
|
} else
|
|
error = B_NO_MEMORY;
|
|
return error;
|
|
}
|
|
|
|
// WORKAROUND
|
|
status_t
|
|
BSymLink::SetTo(const BDirectory *dir, const char *path)
|
|
{
|
|
status_t error = BNode::SetTo(dir, path);
|
|
if (fSecretEntry) {
|
|
fSecretEntry->Unset();
|
|
if (error == B_OK)
|
|
fSecretEntry->SetTo(dir, path);
|
|
} else
|
|
error = B_NO_MEMORY;
|
|
return error;
|
|
}
|
|
|
|
// WORKAROUND
|
|
void
|
|
BSymLink::Unset()
|
|
{
|
|
BNode::Unset();
|
|
if (fSecretEntry)
|
|
fSecretEntry->Unset();
|
|
}
|
|
|
|
|
|
// ReadLink
|
|
//! Reads the contents of the symbolic link into a buffer.
|
|
/*! \param buf the buffer
|
|
\param size the size of the buffer
|
|
\return
|
|
- the number of bytes written into the buffer
|
|
- \c B_BAD_VALUE: \c NULL \a buf or the object doesn't refer to a symbolic
|
|
link.
|
|
- \c B_FILE_ERROR: The object is not initialized.
|
|
- some other error code
|
|
*/
|
|
ssize_t
|
|
BSymLink::ReadLink(char *buf, size_t size)
|
|
{
|
|
/*
|
|
status_t error = (buf ? B_OK : B_BAD_VALUE);
|
|
if (error == B_OK && InitCheck() != B_OK)
|
|
error = B_FILE_ERROR;
|
|
if (error == B_OK)
|
|
error = BPrivate::Storage::read_link(get_fd(), buf, size);
|
|
return error;
|
|
*/
|
|
// WORKAROUND
|
|
status_t error = (buf ? B_OK : B_BAD_VALUE);
|
|
if (error == B_OK && (InitCheck() != B_OK
|
|
|| !fSecretEntry
|
|
|| fSecretEntry->InitCheck() != B_OK)) {
|
|
error = B_FILE_ERROR;
|
|
}
|
|
entry_ref ref;
|
|
if (error == B_OK)
|
|
error = fSecretEntry->GetRef(&ref);
|
|
char path[B_PATH_NAME_LENGTH];
|
|
if (error == B_OK)
|
|
error = BPrivate::Storage::entry_ref_to_path(&ref, path, sizeof(path));
|
|
if (error == B_OK)
|
|
error = BPrivate::Storage::read_link(path, buf, size);
|
|
return error;
|
|
}
|
|
|
|
// MakeLinkedPath
|
|
/*! \brief Combines a directory path and the contents of this symbolic link to
|
|
an absolute path.
|
|
\param dirPath the path name of the directory
|
|
\param path the BPath object to be set to the resulting path name
|
|
\return
|
|
- \c the length of the resulting path name,
|
|
- \c B_BAD_VALUE: \c NULL \a dirPath or \a path or the object doesn't
|
|
refer to a symbolic link.
|
|
- \c B_FILE_ERROR: The object is not initialized.
|
|
- \c B_NAME_TOO_LONG: The resulting path name is too long.
|
|
- some other error code
|
|
*/
|
|
ssize_t
|
|
BSymLink::MakeLinkedPath(const char *dirPath, BPath *path)
|
|
{
|
|
// R5 seems to convert the dirPath to a BDirectory, which causes links to
|
|
// be resolved, i.e. a "/tmp" dirPath expands to "/boot/var/tmp".
|
|
// That does also mean, that the dirPath must exists!
|
|
ssize_t result = (dirPath && path ? B_OK : B_BAD_VALUE);
|
|
if (result == B_OK) {
|
|
BDirectory dir(dirPath);
|
|
result = dir.InitCheck();
|
|
if (result == B_OK)
|
|
result = MakeLinkedPath(&dir, path);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// MakeLinkedPath
|
|
/*! \brief Combines a directory path and the contents of this symbolic link to
|
|
an absolute path.
|
|
\param dir the BDirectory referring to the directory
|
|
\param path the BPath object to be set to the resulting path name
|
|
\return
|
|
- \c the length of the resulting path name,
|
|
- \c B_BAD_VALUE: \c NULL \a dir or \a path or the object doesn't
|
|
refer to a symbolic link.
|
|
- \c B_FILE_ERROR: The object is not initialized.
|
|
- \c B_NAME_TOO_LONG: The resulting path name is too long.
|
|
- some other error code
|
|
*/
|
|
ssize_t
|
|
BSymLink::MakeLinkedPath(const BDirectory *dir, BPath *path)
|
|
{
|
|
ssize_t result = (dir && path ? 0 : B_BAD_VALUE);
|
|
char contents[B_PATH_NAME_LENGTH];
|
|
if (result == 0)
|
|
result = ReadLink(contents, sizeof(contents));
|
|
if (result >= 0) {
|
|
if (BPrivate::Storage::is_absolute_path(contents))
|
|
result = path->SetTo(contents);
|
|
else
|
|
result = path->SetTo(dir, contents);
|
|
if (result == B_OK)
|
|
result = strlen(path->Path());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// IsAbsolute
|
|
//! Returns whether this BSymLink refers to an absolute link.
|
|
/*! /return
|
|
- \c true, if the object is properly initialized and the symbolic link it
|
|
refers to is an absolute link,
|
|
- \c false, otherwise.
|
|
*/
|
|
bool
|
|
BSymLink::IsAbsolute()
|
|
{
|
|
char contents[B_PATH_NAME_LENGTH];
|
|
bool result = (ReadLink(contents, sizeof(contents)) >= 0);
|
|
if (result)
|
|
result = BPrivate::Storage::is_absolute_path(contents);
|
|
return result;
|
|
}
|
|
|
|
// WORKAROUND
|
|
BSymLink &
|
|
BSymLink::operator=(const BSymLink &link)
|
|
{
|
|
if (&link != this) { // no need to assign us to ourselves
|
|
Unset();
|
|
static_cast<BNode&>(*this) = link;
|
|
if (fSecretEntry && link.fSecretEntry)
|
|
*fSecretEntry = *link.fSecretEntry;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
|
|
void BSymLink::_ReservedSymLink1() {}
|
|
void BSymLink::_ReservedSymLink2() {}
|
|
void BSymLink::_ReservedSymLink3() {}
|
|
void BSymLink::_ReservedSymLink4() {}
|
|
void BSymLink::_ReservedSymLink5() {}
|
|
void BSymLink::_ReservedSymLink6() {}
|
|
|
|
//! Returns the BSymLink's file descriptor.
|
|
/*! To be used instead of accessing the BNode's private \c fFd member directly.
|
|
\return the file descriptor, or -1, if not properly initialized.
|
|
*/
|
|
BPrivate::Storage::FileDescriptor
|
|
BSymLink::get_fd() const
|
|
{
|
|
return fFd;
|
|
}
|
|
|
|
|
|
#ifdef USE_OPENBEOS_NAMESPACE
|
|
}; // namespace OpenBeOS
|
|
#endif
|
|
|
|
|
|
|