* Copyright 2003-2013, Axel DΓΆrfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#include "Directory.h"
#include "File.h"
#include "Link.h"
#include <StorageDefs.h>
#include <KernelExport.h>
#include <string.h>
#include <unistd.h>
extern Node *get_node_from(int fd);
using std::nothrow;
namespace BFS {
Directory::Directory(Volume &volume, block_run run)
:
fStream(volume, run),
fTree(&fStream)
{
}
Directory::Directory(Volume &volume, off_t id)
:
fStream(volume, id),
fTree(&fStream)
{
}
Directory::Directory(const Stream &stream)
:
fStream(stream),
fTree(&fStream)
{
}
Directory::~Directory()
{
}
status_t
Directory::InitCheck()
{
return fStream.InitCheck();
}
status_t
Directory::Open(void **_cookie, int mode)
{
_inherited::Open(_cookie, mode);
*_cookie = (void *)new(nothrow) TreeIterator(&fTree);
if (*_cookie == NULL)
return B_NO_MEMORY;
return B_OK;
}
status_t
Directory::Close(void *cookie)
{
_inherited::Close(cookie);
delete (TreeIterator *)cookie;
return B_OK;
}
Node*
Directory::LookupDontTraverse(const char* name)
{
off_t id;
if (fTree.Find((uint8 *)name, strlen(name), &id) < B_OK)
return NULL;
return Stream::NodeFactory(fStream.GetVolume(), id);
}
status_t
Directory::GetNextEntry(void *cookie, char *name, size_t size)
{
TreeIterator *iterator = (TreeIterator *)cookie;
uint16 length;
off_t id;
return iterator->GetNextEntry(name, &length, size, &id);
}
status_t
Directory::GetNextNode(void *cookie, Node **_node)
{
TreeIterator *iterator = (TreeIterator *)cookie;
char name[B_FILE_NAME_LENGTH];
uint16 length;
off_t id;
status_t status = iterator->GetNextEntry(name, &length, sizeof(name), &id);
if (status != B_OK)
return status;
*_node = Stream::NodeFactory(fStream.GetVolume(), id);
if (*_node == NULL)
return B_ERROR;
return B_OK;
}
status_t
Directory::Rewind(void *cookie)
{
TreeIterator *iterator = (TreeIterator *)cookie;
return iterator->Rewind();
}
bool
Directory::IsEmpty()
{
TreeIterator iterator(&fTree);
uint32 count = 0;
char name[BPLUSTREE_MAX_KEY_LENGTH];
uint16 length;
off_t id;
while (iterator.GetNextEntry(name, &length, B_FILE_NAME_LENGTH, &id)
== B_OK) {
if (fStream.Mode() & (S_ATTR_DIR | S_INDEX_DIR))
return false;
if (++count > 2 || (strcmp(".", name) && strcmp("..", name)))
return false;
}
return true;
}
status_t
Directory::GetName(char *name, size_t size) const
{
if (fStream.inode_num == fStream.GetVolume().Root()) {
strlcpy(name, fStream.GetVolume().SuperBlock().name, size);
return B_OK;
}
return fStream.GetName(name, size);
}
ino_t
Directory::Inode() const
{
return fStream.ID();
}
}