root/src/add-ons/kernel/file_systems/packagefs/nodes/Directory.cpp
/*
 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */


#include "Directory.h"

#include "DebugSupport.h"
#include "UnpackingAttributeCookie.h"
#include "UnpackingAttributeDirectoryCookie.h"
#include "Utils.h"


Directory::Directory(ino_t id)
        :
        Node(id)
{
        rw_lock_init(&fLock, "packagefs directory");
}


Directory::~Directory()
{
        Node* child = fChildTable.Clear(true);
        while (child != NULL) {
                Node* next = child->NameHashTableNext();
                child->_SetParent(NULL);
                child->ReleaseReference();
                child = next;
        }

        rw_lock_destroy(&fLock);
}


status_t
Directory::Init(const String& name)
{
        status_t error = Node::Init(name);
        if (error != B_OK)
                return error;

        return fChildTable.Init();
}


mode_t
Directory::Mode() const
{
        return S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
}


off_t
Directory::FileSize() const
{
        return 0;
}


status_t
Directory::Read(off_t offset, void* buffer, size_t* bufferSize)
{
        return B_IS_A_DIRECTORY;
}


status_t
Directory::Read(io_request* request)
{
        return B_IS_A_DIRECTORY;
}


status_t
Directory::ReadSymlink(void* buffer, size_t* bufferSize)
{
        return B_IS_A_DIRECTORY;
}


void
Directory::AddChild(Node* node)
{
        ASSERT_WRITE_LOCKED_RW_LOCK(&fLock);
        ASSERT(node->fParent == NULL);

        fChildTable.Insert(node);
        fChildList.Add(node);
        node->_SetParent(this);
        node->AcquireReference();
}


void
Directory::RemoveChild(Node* node)
{
        ASSERT_WRITE_LOCKED_RW_LOCK(&fLock);
        ASSERT(node->fParent == this);

        Node* nextNode = fChildList.GetNext(node);

        fChildTable.Remove(node);
        fChildList.Remove(node);
        node->_SetParent(NULL);
        node->ReleaseReference();

        // adjust directory iterators pointing to the removed child
        for (DirectoryIteratorList::Iterator it = fIterators.GetIterator();
                        DirectoryIterator* iterator = it.Next();) {
                if (iterator->node == node)
                        iterator->node = nextNode;
        }
}


Node*
Directory::FindChild(const StringKey& name)
{
        return fChildTable.Lookup(name);
}


void
Directory::AddDirectoryIterator(DirectoryIterator* iterator)
{
        ASSERT_WRITE_LOCKED_RW_LOCK(&fLock);
        fIterators.Add(iterator);
}


void
Directory::RemoveDirectoryIterator(DirectoryIterator* iterator)
{
        ASSERT_WRITE_LOCKED_RW_LOCK(&fLock);
        fIterators.Remove(iterator);
}