#include "NodeHandle.h"
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fs_attr.h>
#include "Compatibility.h"
#include "Directory.h"
#include "FDManager.h"
#include "Path.h"
NodeHandle::NodeHandle()
: BReferenceable(),
Lockable(),
fCookie(-1),
fNodeRef()
{
}
NodeHandle::~NodeHandle()
{
}
status_t
NodeHandle::GetStat(struct stat* st)
{
int fd = GetFD();
if (fd < 0)
return B_ENTRY_NOT_FOUND;
if (fstat(fd, st) < 0)
return errno;
return B_OK;
}
void
NodeHandle::SetCookie(int32 cookie)
{
fCookie = cookie;
}
int32
NodeHandle::GetCookie() const
{
return fCookie;
}
const NodeRef&
NodeHandle::GetNodeRef() const
{
return fNodeRef;
}
int
NodeHandle::GetFD() const
{
return -1;
}
FileHandle::FileHandle()
: fFD(-1)
{
}
FileHandle::~FileHandle()
{
Close();
}
status_t
FileHandle::Open(Node* node, int openMode)
{
if (!node)
return B_BAD_VALUE;
openMode &= O_RWMASK | O_TRUNC | O_APPEND;
Path path;
status_t error = node->GetPath(&path);
if (error != B_OK)
return error;
error = FDManager::Open(path.GetPath(), openMode | O_NOTRAVERSE, 0, fFD);
if (error != B_OK)
return error;
fNodeRef = node->GetNodeRef();
return B_OK;
}
status_t
FileHandle::Close()
{
if (fFD < 0)
return B_BAD_VALUE;
status_t error = B_OK;
if (close(fFD) < 0)
error = errno;
fFD = -1;
return error;
}
status_t
FileHandle::Read(off_t pos, void* buffer, size_t size, size_t* _bytesRead)
{
if (fFD < 0)
return B_BAD_VALUE;
ssize_t bytesRead = read_pos(fFD, pos, buffer, size);
if (bytesRead < 0)
return errno;
*_bytesRead = bytesRead;
return B_OK;
}
status_t
FileHandle::Write(off_t pos, const void* buffer, size_t size,
size_t* _bytesWritten)
{
if (fFD < 0)
return B_BAD_VALUE;
ssize_t bytesWritten = write_pos(fFD, pos, buffer, size);
if (bytesWritten < 0)
return errno;
*_bytesWritten = bytesWritten;
return B_OK;
}
status_t
FileHandle::ReadAttr(const char* name, uint32 type, off_t pos, void* buffer,
size_t size, size_t* _bytesRead)
{
if (fFD < 0)
return B_BAD_VALUE;
ssize_t bytesRead = fs_read_attr(fFD, name, type, pos, buffer, size);
if (bytesRead < 0)
return errno;
*_bytesRead = bytesRead;
return B_OK;
}
status_t
FileHandle::WriteAttr(const char* name, uint32 type, off_t pos,
const void* buffer, size_t size, size_t* _bytesWritten)
{
if (fFD < 0)
return B_BAD_VALUE;
ssize_t bytesWritten = fs_write_attr(fFD, name, type, pos, buffer, size);
if (bytesWritten < 0)
return errno;
*_bytesWritten = bytesWritten;
return B_OK;
}
status_t
FileHandle::RemoveAttr(const char* name)
{
if (fFD < 0)
return B_BAD_VALUE;
return (fs_remove_attr(fFD, name) == 0 ? B_OK : errno);
}
status_t
FileHandle::StatAttr(const char* name, attr_info* info)
{
if (fFD < 0)
return B_BAD_VALUE;
return (fs_stat_attr(fFD, name, info) == 0 ? B_OK : errno);
}
int
FileHandle::GetFD() const
{
return fFD;
}
DirIterator::DirIterator()
: fDirectory(NULL)
{
}
DirIterator::~DirIterator()
{
if (fDirectory)
fDirectory->RemoveDirIterator(this);
}
bool
DirIterator::IsValid() const
{
return fDirectory;
}
AttrDirIterator::AttrDirIterator()
: NodeHandle(),
fDir(NULL)
{
}
AttrDirIterator::~AttrDirIterator()
{
Close();
}
status_t
AttrDirIterator::Open(Node* node)
{
if (!node)
return B_BAD_VALUE;
Path path;
status_t error = node->GetPath(&path);
if (error != B_OK)
return error;
error = FDManager::OpenAttrDir(path.GetPath(), fDir);
if (error != B_OK)
return errno;
fNodeRef = node->GetNodeRef();
return B_OK;
}
status_t
AttrDirIterator::Close()
{
if (!fDir)
return B_BAD_VALUE;
status_t error = B_OK;
if (fs_close_attr_dir(fDir) < 0)
error = errno;
fDir = NULL;
return error;
}
status_t
AttrDirIterator::ReadDir(dirent* _entry, int32 bufferSize,
int32 count, int32* countRead, bool* done)
{
if (!fDir)
return B_ENTRY_NOT_FOUND;
*countRead = 0;
*done = false;
if (count == 0)
return B_OK;
if (struct dirent* entry = fs_read_attr_dir(fDir)) {
size_t entryLen = entry->d_name + strlen(entry->d_name) + 1
- (char*)entry;
memcpy(_entry, entry, entryLen);
*countRead = 1;
} else {
*countRead = 0;
*done = true;
}
return B_OK;
}
status_t
AttrDirIterator::RewindDir()
{
if (!fDir)
return B_ENTRY_NOT_FOUND;
fs_rewind_attr_dir(fDir);
return B_OK;
}
int
AttrDirIterator::GetFD() const
{
return dirfd(fDir);
}
QueryListener::QueryListener()
{
}
QueryListener::~QueryListener()
{
}
QueryHandle::QueryHandle(port_id remotePort, int32 remoteToken)
: NodeHandle(),
fRemotePort(remotePort),
fRemoteToken(remoteToken),
fQueries(),
fCurrentQuery(NULL),
fListener(NULL),
fClosed(false)
{
}
QueryHandle::~QueryHandle()
{
Close();
}
void
QueryHandle::SetQueryListener(QueryListener* listener)
{
fListener = listener;
}
QueryListener*
QueryHandle::GetQueryListener() const
{
return fListener;
}
void
QueryHandle::AddQuery(Query* query)
{
if (query) {
fQueries.Insert(query);
if (!fCurrentQuery)
fCurrentQuery = query;
}
}
void
QueryHandle::RemoveQuery(Query* query)
{
if (query) {
if (query == fCurrentQuery)
fCurrentQuery = fQueries.GetNext(query);
fQueries.Remove(query);
}
}
port_id
QueryHandle::GetRemotePort() const
{
return fRemotePort;
}
int32
QueryHandle::GetRemoteToken() const
{
return fRemoteToken;
}
status_t
QueryHandle::Close()
{
if (fClosed)
return B_OK;
fCurrentQuery = NULL;
for (DoublyLinkedList<Query>::Iterator it = fQueries.GetIterator();
it.HasNext();) {
Query* query = it.Next();
it.Remove();
delete query;
}
fClosed = true;
if (fListener)
fListener->QueryHandleClosed(this);
return B_OK;
}
status_t
QueryHandle::ReadDir(dirent* entry, int32 count, int32* countRead)
{
if (count == 0) {
*countRead = 0;
return B_OK;
}
while (fCurrentQuery) {
int32 readEntries = fCurrentQuery->GetNextDirents(entry,
offsetof(struct dirent, d_name) + B_FILE_NAME_LENGTH, 1);
if (readEntries < 0)
return readEntries;
if (readEntries > 0) {
*countRead = 1;
return B_OK;
}
fCurrentQuery = fQueries.GetNext(fCurrentQuery);
}
*countRead = 0;
return B_OK;
}