From 59e76dbe414f32cc65320b605442f97eb60296c0 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 26 Jun 2011 04:42:37 +0200 Subject: [PATCH] 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. --- .../packagefs/AutoPackageAttributes.cpp | 146 ++++++++++++++++++ .../packagefs/AutoPackageAttributes.h | 38 +++++ .../kernel/file_systems/packagefs/Jamfile | 1 + .../packagefs/UnpackingAttributeCookie.cpp | 8 +- .../UnpackingAttributeDirectoryCookie.cpp | 21 ++- .../UnpackingAttributeDirectoryCookie.h | 2 + 6 files changed, 210 insertions(+), 6 deletions(-) create mode 100644 src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.cpp create mode 100644 src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.h diff --git a/src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.cpp b/src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.cpp new file mode 100644 index 0000000000..fac17f9c25 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.cpp @@ -0,0 +1,146 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "AutoPackageAttributes.h" + +#include +#include + +#include + +#include + +#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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.h b/src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.h new file mode 100644 index 0000000000..cbb4d05818 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/AutoPackageAttributes.h @@ -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 + + +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 diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index fb5a9ff0a0..9dade89c75 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -9,6 +9,7 @@ UsePrivateHeaders shared ; HAIKU_PACKAGE_FS_SOURCES = AttributeCookie.cpp AttributeDirectoryCookie.cpp + AutoPackageAttributes.cpp BlockBufferCacheKernel.cpp DebugSupport.cpp Dependency.cpp diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp index 632038d887..8804dcbd93 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeCookie.cpp @@ -15,6 +15,7 @@ #include +#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) diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.cpp b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.cpp index 05f9b528f8..ab2d3db30f 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.cpp @@ -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; } diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.h b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.h index a0ce184c90..e8ff28651e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.h +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingAttributeDirectoryCookie.h @@ -7,6 +7,7 @@ #include "AttributeDirectoryCookie.h" +#include "AutoPackageAttributes.h" struct dirent; @@ -32,6 +33,7 @@ public: private: PackageNode* fPackageNode; PackageNodeAttribute* fAttribute; + uint32 fState; };