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-11-25 06:17:55 +01:00
parent 4ac4d15c3a
commit 5167a80703
11 changed files with 229 additions and 99 deletions
@@ -0,0 +1,12 @@
/*
* Copyright 2011, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "AttributeDirectoryCookie.h"
AttributeDirectoryCookie::~AttributeDirectoryCookie()
{
}
@@ -0,0 +1,26 @@
/*
* Copyright 2011, Ingo Weinhold, [email protected].
* 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
@@ -8,6 +8,7 @@
#include "DebugSupport.h" #include "DebugSupport.h"
#include "UnpackingAttributeCookie.h" #include "UnpackingAttributeCookie.h"
#include "UnpackingAttributeDirectoryCookie.h"
#include "Utils.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 status_t
Directory::OpenAttribute(const char* name, int openMode, Directory::OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie) AttributeCookie*& _cookie)
@@ -51,6 +51,8 @@ public:
virtual status_t ReadSymlink(void* buffer, virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize); size_t* bufferSize);
virtual status_t OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie);
virtual status_t OpenAttribute(const char* name, int openMode, virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie); AttributeCookie*& _cookie);
@@ -8,6 +8,7 @@ UsePrivateHeaders shared ;
HAIKU_PACKAGE_FS_SOURCES = HAIKU_PACKAGE_FS_SOURCES =
AttributeCookie.cpp AttributeCookie.cpp
AttributeDirectoryCookie.cpp
BlockBufferCacheKernel.cpp BlockBufferCacheKernel.cpp
DebugSupport.cpp DebugSupport.cpp
Dependency.cpp Dependency.cpp
@@ -28,6 +29,7 @@ HAIKU_PACKAGE_FS_SOURCES =
PackageSymlink.cpp PackageSymlink.cpp
Resolvable.cpp Resolvable.cpp
UnpackingAttributeCookie.cpp UnpackingAttributeCookie.cpp
UnpackingAttributeDirectoryCookie.cpp
Version.cpp Version.cpp
Volume.cpp Volume.cpp
; ;
@@ -11,6 +11,7 @@
#include <algorithm> #include <algorithm>
#include "UnpackingAttributeCookie.h" #include "UnpackingAttributeCookie.h"
#include "UnpackingAttributeDirectoryCookie.h"
#include "Utils.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 status_t
LeafNode::OpenAttribute(const char* name, int openMode, LeafNode::OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie) AttributeCookie*& _cookie)
@@ -38,6 +38,8 @@ public:
virtual status_t ReadSymlink(void* buffer, virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize); size_t* bufferSize);
virtual status_t OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie);
virtual status_t OpenAttribute(const char* name, int openMode, virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie); AttributeCookie*& _cookie);
@@ -18,6 +18,7 @@
class AttributeCookie; class AttributeCookie;
class AttributeDirectoryCookie;
class Directory; class Directory;
class PackageNode; class PackageNode;
@@ -64,6 +65,8 @@ public:
virtual status_t ReadSymlink(void* buffer, virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize) = 0; size_t* bufferSize) = 0;
virtual status_t OpenAttributeDirectory(
AttributeDirectoryCookie*& _cookie) = 0;
virtual status_t OpenAttribute(const char* name, int openMode, virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie) = 0; AttributeCookie*& _cookie) = 0;
@@ -0,0 +1,116 @@
/*
* Copyright 2011, Ingo Weinhold, [email protected].
* 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;
}
@@ -0,0 +1,39 @@
/*
* Copyright 2011, Ingo Weinhold, [email protected].
* 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
@@ -18,6 +18,7 @@
#include <AutoDeleter.h> #include <AutoDeleter.h>
#include "AttributeCookie.h" #include "AttributeCookie.h"
#include "AttributeDirectoryCookie.h"
#include "DebugSupport.h" #include "DebugSupport.h"
#include "Directory.h" #include "Directory.h"
#include "GlobalFactory.h" #include "GlobalFactory.h"
@@ -663,50 +664,6 @@ packagefs_rewind_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
// #pragma mark - Attribute Directories // #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 status_t
packagefs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie) 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 // create a cookie
NodeReadLocker nodeLocker(node); NodeReadLocker nodeLocker(node);
AttributeDirectoryCookie* cookie AttributeDirectoryCookie* cookie;
= new(std::nothrow) AttributeDirectoryCookie(node); error = node->OpenAttributeDirectory(cookie);
if (cookie == NULL) if (error != B_OK)
RETURN_ERROR(B_NO_MEMORY); RETURN_ERROR(error);
*_cookie = cookie; *_cookie = cookie;
return B_OK; return B_OK;
@@ -735,7 +692,8 @@ packagefs_open_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
status_t status_t
packagefs_close_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie) 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(volume);
TOUCH(node); TOUCH(node);
uint32 maxCount = *_count; return cookie->Read(volume->ID(), node->ID(), buffer, bufferSize, _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;
} }
@@ -833,9 +745,7 @@ packagefs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
TOUCH(volume); TOUCH(volume);
TOUCH(node); TOUCH(node);
cookie->Rewind(); return cookie->Rewind();
return B_OK;
} }