Attribute dir access kernel interface abstraction

* Introduce interface AttributeDirectoryCookie and currently only
  implementation UnpackingAttributeDirectoryCookie. This is an interface
  for reading/rewinding an attribute directory.
* Add abstract virtual Node::OpenAttributeDirectory() method that
  returns an AttributeDirectoryCookie and implement it for derived
  classes.
* In the kernel interface attribute directory hooks use
  AttributeDirectoryCookie now.
This commit is contained in:
Ingo Weinhold 2011-06-23 22:01:59 +02:00
parent 3ad1037bcc
commit e807d80833
11 changed files with 229 additions and 99 deletions

View File

@ -0,0 +1,12 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "AttributeDirectoryCookie.h"
AttributeDirectoryCookie::~AttributeDirectoryCookie()
{
}

View File

@ -0,0 +1,26 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ATTRIBUTE_DIRECTORY_COOKIE_H
#define ATTRIBUTE_DIRECTORY_COOKIE_H
#include <dirent.h>
#include <SupportDefs.h>
class AttributeDirectoryCookie {
public:
virtual ~AttributeDirectoryCookie();
virtual status_t Close() = 0;
virtual status_t Read(dev_t volumeID, ino_t nodeID,
struct dirent* buffer, size_t bufferSize,
uint32* _count) = 0;
virtual status_t Rewind() = 0;
};
#endif // ATTRIBUTE_DIRECTORY_COOKIE_H

View File

@ -8,6 +8,7 @@
#include "DebugSupport.h"
#include "UnpackingAttributeCookie.h"
#include "UnpackingAttributeDirectoryCookie.h"
#include "Utils.h"
@ -172,6 +173,14 @@ Directory::ReadSymlink(void* buffer, size_t* bufferSize)
}
status_t
Directory::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
{
return UnpackingAttributeDirectoryCookie::Open(fPackageDirectories.Head(),
_cookie);
}
status_t
Directory::OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie)

View File

@ -51,6 +51,8 @@ public:
virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize);
virtual status_t OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie);
virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie);

View File

@ -8,6 +8,7 @@ UsePrivateHeaders shared ;
HAIKU_PACKAGE_FS_SOURCES =
AttributeCookie.cpp
AttributeDirectoryCookie.cpp
BlockBufferCacheKernel.cpp
DebugSupport.cpp
Dependency.cpp
@ -28,6 +29,7 @@ HAIKU_PACKAGE_FS_SOURCES =
PackageSymlink.cpp
Resolvable.cpp
UnpackingAttributeCookie.cpp
UnpackingAttributeDirectoryCookie.cpp
Version.cpp
Volume.cpp
;

View File

@ -11,6 +11,7 @@
#include <algorithm>
#include "UnpackingAttributeCookie.h"
#include "UnpackingAttributeDirectoryCookie.h"
#include "Utils.h"
@ -194,6 +195,14 @@ LeafNode::ReadSymlink(void* buffer, size_t* bufferSize)
}
status_t
LeafNode::OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie)
{
return UnpackingAttributeDirectoryCookie::Open(fPackageNodes.Head(),
_cookie);
}
status_t
LeafNode::OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie)

View File

@ -38,6 +38,8 @@ public:
virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize);
virtual status_t OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie);
virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie);

View File

@ -18,6 +18,7 @@
class AttributeCookie;
class AttributeDirectoryCookie;
class Directory;
class PackageNode;
@ -64,6 +65,8 @@ public:
virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize) = 0;
virtual status_t OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie) = 0;
virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie) = 0;

View File

@ -0,0 +1,116 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "UnpackingAttributeDirectoryCookie.h"
#include "DebugSupport.h"
#include "PackageNode.h"
#include "Utils.h"
UnpackingAttributeDirectoryCookie::UnpackingAttributeDirectoryCookie(
PackageNode* packageNode)
:
fPackageNode(packageNode),
fAttribute(NULL)
{
if (fPackageNode != NULL) {
fPackageNode->AcquireReference();
fAttribute = fPackageNode->Attributes().Head();
}
}
UnpackingAttributeDirectoryCookie::~UnpackingAttributeDirectoryCookie()
{
if (fPackageNode != NULL)
fPackageNode->ReleaseReference();
}
/*static*/ status_t
UnpackingAttributeDirectoryCookie::Open(PackageNode* packageNode,
AttributeDirectoryCookie*& _cookie)
{
UnpackingAttributeDirectoryCookie* cookie = new(std::nothrow)
UnpackingAttributeDirectoryCookie(packageNode);
if (cookie == NULL)
return B_NO_MEMORY;
_cookie = cookie;
return B_OK;
}
status_t
UnpackingAttributeDirectoryCookie::Close()
{
return B_OK;
}
status_t
UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
struct dirent* buffer, size_t bufferSize, uint32* _count)
{
uint32 maxCount = *_count;
uint32 count = 0;
dirent* previousEntry = NULL;
while (fAttribute != NULL) {
// don't read more entries than requested
if (count >= maxCount)
break;
// align the buffer for subsequent entries
if (count > 0) {
addr_t offset = (addr_t)buffer % 8;
if (offset > 0) {
offset = 8 - offset;
if (bufferSize <= offset)
break;
previousEntry->d_reclen += offset;
buffer = (dirent*)((addr_t)buffer + offset);
bufferSize -= offset;
}
}
// fill in the entry name -- checks whether the entry fits into the
// buffer
const char* name = fAttribute->Name();
if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) {
if (count == 0)
RETURN_ERROR(B_BUFFER_OVERFLOW);
break;
}
// fill in the other data
buffer->d_dev = volumeID;
buffer->d_ino = nodeID;
count++;
previousEntry = buffer;
bufferSize -= buffer->d_reclen;
buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
}
*_count = count;
return B_OK;
}
status_t
UnpackingAttributeDirectoryCookie::Rewind()
{
if (fPackageNode != NULL)
fAttribute = fPackageNode->Attributes().Head();
return B_OK;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef UNPACKING_ATTRIBUTE_DIRECTORY_COOKIE_H
#define UNPACKING_ATTRIBUTE_DIRECTORY_COOKIE_H
#include "AttributeDirectoryCookie.h"
struct dirent;
class PackageNode;
class PackageNodeAttribute;
class UnpackingAttributeDirectoryCookie : public AttributeDirectoryCookie {
public:
UnpackingAttributeDirectoryCookie(
PackageNode* packageNode);
virtual ~UnpackingAttributeDirectoryCookie();
static status_t Open(PackageNode* packageNode,
AttributeDirectoryCookie*& _cookie);
virtual status_t Close();
virtual status_t Read(dev_t volumeID, ino_t nodeID,
struct dirent* buffer, size_t bufferSize,
uint32* _count);
virtual status_t Rewind();
private:
PackageNode* fPackageNode;
PackageNodeAttribute* fAttribute;
};
#endif // UNPACKING_ATTRIBUTE_DIRECTORY_COOKIE_H

View File

@ -18,6 +18,7 @@
#include <AutoDeleter.h>
#include "AttributeCookie.h"
#include "AttributeDirectoryCookie.h"
#include "DebugSupport.h"
#include "Directory.h"
#include "GlobalFactory.h"
@ -663,50 +664,6 @@ packagefs_rewind_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
// #pragma mark - Attribute Directories
struct AttributeDirectoryCookie {
Node* node;
PackageNode* packageNode;
PackageNodeAttribute* attribute;
AttributeDirectoryCookie(Node* node)
:
node(node),
packageNode(node->GetPackageNode()),
attribute(NULL)
{
if (packageNode != NULL) {
packageNode->AcquireReference();
attribute = packageNode->Attributes().Head();
}
}
~AttributeDirectoryCookie()
{
if (packageNode != NULL)
packageNode->ReleaseReference();
}
PackageNodeAttribute* Current() const
{
return attribute;
}
void Next()
{
if (attribute == NULL)
return;
attribute = packageNode->Attributes().GetNext(attribute);
}
void Rewind()
{
if (packageNode != NULL)
attribute = packageNode->Attributes().Head();
}
};
status_t
packagefs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
{
@ -722,10 +679,10 @@ packagefs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
// create a cookie
NodeReadLocker nodeLocker(node);
AttributeDirectoryCookie* cookie
= new(std::nothrow) AttributeDirectoryCookie(node);
if (cookie == NULL)
RETURN_ERROR(B_NO_MEMORY);
AttributeDirectoryCookie* cookie;
error = node->OpenAttributeDirectory(cookie);
if (error != B_OK)
RETURN_ERROR(error);
*_cookie = cookie;
return B_OK;
@ -735,7 +692,8 @@ packagefs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
status_t
packagefs_close_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
{
return B_OK;
AttributeDirectoryCookie* cookie = (AttributeDirectoryCookie*)_cookie;
return cookie->Close();
}
@ -771,53 +729,7 @@ packagefs_read_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
TOUCH(volume);
TOUCH(node);
uint32 maxCount = *_count;
uint32 count = 0;
dirent* previousEntry = NULL;
while (PackageNodeAttribute* attribute = cookie->Current()) {
// don't read more entries than requested
if (count >= maxCount)
break;
// align the buffer for subsequent entries
if (count > 0) {
addr_t offset = (addr_t)buffer % 8;
if (offset > 0) {
offset = 8 - offset;
if (bufferSize <= offset)
break;
previousEntry->d_reclen += offset;
buffer = (dirent*)((addr_t)buffer + offset);
bufferSize -= offset;
}
}
// fill in the entry name -- checks whether the entry fits into the
// buffer
const char* name = attribute->Name();
if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) {
if (count == 0)
RETURN_ERROR(B_BUFFER_OVERFLOW);
break;
}
// fill in the other data
buffer->d_dev = volume->ID();
buffer->d_ino = node->ID();
count++;
previousEntry = buffer;
bufferSize -= buffer->d_reclen;
buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
cookie->Next();
}
*_count = count;
return B_OK;
return cookie->Read(volume->ID(), node->ID(), buffer, bufferSize, _count);
}
@ -833,9 +745,7 @@ packagefs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
TOUCH(volume);
TOUCH(node);
cookie->Rewind();
return B_OK;
return cookie->Rewind();
}