Support for auto-generated package node attributes

* Add utility class AutoPackageAttributes and AttributeCookie subclass
  AutoPackageAttributeCookie.
* UnpackingAttributeCookie::Open() does now try to create a
  AutoPackageAttributeCookie, when it doesn't find the attribute in the
  PackageNode.
* Adjust UnpackingAttributeDirectoryCookie to also list auto-generated
  attributes.

Currently the only supported attribute is "SYS:PACKAGE", which is the
file name of the package containing the node.
This commit is contained in:
Ingo Weinhold 2011-06-26 04:42:37 +02:00
parent a83fe53dce
commit 59e76dbe41
6 changed files with 210 additions and 6 deletions

View File

@ -0,0 +1,146 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "AutoPackageAttributes.h"
#include <algorithm>
#include <new>
#include <TypeConstants.h>
#include <AutoDeleter.h>
#include "AttributeCookie.h"
#include "DebugSupport.h"
#include "Package.h"
static const char* const kAttributeNames[AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT] = {
"SYS:PACKAGE"
};
class AutoPackageAttributeCookie : public AttributeCookie {
public:
AutoPackageAttributeCookie(Package* package, AutoPackageAttribute attribute)
:
fPackage(package),
fAttribute(attribute)
{
fPackage->AcquireReference();
}
virtual ~AutoPackageAttributeCookie()
{
fPackage->ReleaseReference();
}
virtual status_t ReadAttribute(off_t offset, void* buffer,
size_t* bufferSize)
{
// get the attribute
off_t size;
uint32 type;
const void* value = AutoPackageAttributes::GetAttributeValue(fPackage,
fAttribute, size, type);
if (value == NULL)
return B_BAD_VALUE;
// check and clamp offset and size
if (offset < 0 || offset > size)
return B_BAD_VALUE;
size_t toCopy = *bufferSize;
if (offset + toCopy > size)
toCopy = size - offset;
if (toCopy > 0)
memcpy(buffer, (const uint8*)value + offset, toCopy);
*bufferSize = toCopy;
return B_OK;
}
virtual status_t ReadAttributeStat(struct stat* st)
{
if (AutoPackageAttributes::GetAttributeValue(fPackage, fAttribute,
st->st_size, st->st_type) == NULL) {
return B_BAD_VALUE;
}
return B_OK;
}
private:
Package* fPackage;
AutoPackageAttribute fAttribute;
};
/*static*/ bool
AutoPackageAttributes::AttributeForName(const char* name,
AutoPackageAttribute& _attribute)
{
for (int i = 0; i < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT; i++) {
if (strcmp(name, kAttributeNames[i]) == 0) {
_attribute = (AutoPackageAttribute)i;
return true;
}
}
return false;
}
/*static*/ const char*
AutoPackageAttributes::NameForAttribute(AutoPackageAttribute attribute)
{
if (attribute >= 0 && attribute < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
return kAttributeNames[attribute];
return NULL;
}
/*static*/ const void*
AutoPackageAttributes::GetAttributeValue(const Package* package,
AutoPackageAttribute attribute, off_t& _size, uint32& _type)
{
switch (attribute) {
case AUTO_PACKAGE_ATTRIBUTE_PACKAGE:
{
const char* value = package->FileName();
_size = strlen(value) + 1;
_type = B_STRING_TYPE;
return value;
}
default:
return NULL;
}
}
/*static*/ status_t
AutoPackageAttributes::OpenCookie(Package* package, const char* name,
int openMode, AttributeCookie*& _cookie)
{
if (package == NULL)
return B_ENTRY_NOT_FOUND;
// get the attribute
AutoPackageAttribute attribute;
if (!AttributeForName(name, attribute))
return B_ENTRY_NOT_FOUND;
// allocate the cookie
AutoPackageAttributeCookie* cookie = new(std::nothrow)
AutoPackageAttributeCookie(package, attribute);
if (cookie == NULL)
RETURN_ERROR(B_NO_MEMORY);
_cookie = cookie;
return B_OK;
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef AUTO_PACKAGE_ATTRIBUTES_H
#define AUTO_PACKAGE_ATTRIBUTES_H
#include <SupportDefs.h>
class AttributeCookie;
class Package;
enum AutoPackageAttribute {
AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST,
AUTO_PACKAGE_ATTRIBUTE_PACKAGE = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST,
AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT
};
struct AutoPackageAttributes {
static bool AttributeForName(const char* name,
AutoPackageAttribute& _attribute);
static const char* NameForAttribute(
AutoPackageAttribute attribute);
static const void* GetAttributeValue(const Package* package,
AutoPackageAttribute attribute,
off_t& _size, uint32& _type);
static status_t OpenCookie(Package* package, const char* name,
int openMode, AttributeCookie*& _cookie);
};
#endif // AUTO_PACKAGE_ATTRIBUTES_H

View File

@ -9,6 +9,7 @@ UsePrivateHeaders shared ;
HAIKU_PACKAGE_FS_SOURCES =
AttributeCookie.cpp
AttributeDirectoryCookie.cpp
AutoPackageAttributes.cpp
BlockBufferCacheKernel.cpp
DebugSupport.cpp
Dependency.cpp

View File

@ -15,6 +15,7 @@
#include <AutoDeleter.h>
#include "AutoPackageAttributes.h"
#include "DebugSupport.h"
#include "GlobalFactory.h"
#include "Package.h"
@ -86,8 +87,11 @@ UnpackingAttributeCookie::Open(PackageNode* packageNode, const char* name,
// get the attribute
PackageNodeAttribute* attribute = packageNode->FindAttribute(name);
if (attribute == NULL)
return B_ENTRY_NOT_FOUND;
if (attribute == NULL) {
// We don't know the attribute -- maybe it's an auto-generated one.
return AutoPackageAttributes::OpenCookie(packageNode->GetPackage(),
name, openMode, _cookie);
}
// allocate the cookie
UnpackingAttributeCookie* cookie = new(std::nothrow)

View File

@ -15,7 +15,8 @@ UnpackingAttributeDirectoryCookie::UnpackingAttributeDirectoryCookie(
PackageNode* packageNode)
:
fPackageNode(packageNode),
fAttribute(NULL)
fAttribute(NULL),
fState(AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST)
{
if (fPackageNode != NULL) {
fPackageNode->AcquireReference();
@ -54,7 +55,7 @@ UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
dirent* previousEntry = NULL;
while (fAttribute != NULL) {
while (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT || fAttribute != NULL) {
// don't read more entries than requested
if (count >= maxCount)
break;
@ -73,9 +74,16 @@ UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
}
}
// get the attribute name
const char* name;
if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT) {
name = AutoPackageAttributes::NameForAttribute(
(AutoPackageAttribute)fState);
} else
name = fAttribute->Name();
// 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);
@ -91,7 +99,10 @@ UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
bufferSize -= buffer->d_reclen;
buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
fState++;
else
fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
}
*_count = count;
@ -105,5 +116,7 @@ UnpackingAttributeDirectoryCookie::Rewind()
if (fPackageNode != NULL)
fAttribute = fPackageNode->Attributes().Head();
fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST;
return B_OK;
}

View File

@ -7,6 +7,7 @@
#include "AttributeDirectoryCookie.h"
#include "AutoPackageAttributes.h"
struct dirent;
@ -32,6 +33,7 @@ public:
private:
PackageNode* fPackageNode;
PackageNodeAttribute* fAttribute;
uint32 fState;
};