* Extract the attributes from the package files and attach them as
PackageNodeAttribute to the PackageNodes. * Implemented the attribute FS interface hooks. * Made Package and PackageNode BReferenceable. * Fixed the reference management for Node. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34119 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
1892e95632
commit
46776004f7
@ -111,6 +111,13 @@ Directory::AddPackageNode(PackageNode* packageNode)
|
||||
}
|
||||
|
||||
|
||||
PackageNode*
|
||||
Directory::GetPackageNode()
|
||||
{
|
||||
return fPackageDirectories.Head();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Directory::Read(off_t offset, void* buffer, size_t* bufferSize)
|
||||
{
|
||||
@ -123,6 +130,7 @@ Directory::AddChild(Node* node)
|
||||
{
|
||||
fChildTable.Insert(node);
|
||||
fChildList.Add(node);
|
||||
node->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
@ -133,6 +141,7 @@ Directory::RemoveChild(Node* node)
|
||||
|
||||
fChildTable.Remove(node);
|
||||
fChildList.Remove(node);
|
||||
node->ReleaseReference();
|
||||
|
||||
// adjust directory iterators pointing to the removed child
|
||||
for (DirectoryIteratorList::Iterator it = fIterators.GetIterator();
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
|
||||
virtual status_t AddPackageNode(PackageNode* packageNode);
|
||||
|
||||
virtual PackageNode* GetPackageNode();
|
||||
|
||||
virtual status_t Read(off_t offset, void* buffer,
|
||||
size_t* bufferSize);
|
||||
|
||||
|
@ -23,6 +23,7 @@ HAIKU_PACKAGE_FS_SOURCES =
|
||||
PackageFile.cpp
|
||||
PackageLeafNode.cpp
|
||||
PackageNode.cpp
|
||||
PackageNodeAttribute.cpp
|
||||
PackageSymlink.cpp
|
||||
Volume.cpp
|
||||
;
|
||||
|
@ -102,6 +102,13 @@ LeafNode::AddPackageNode(PackageNode* packageNode)
|
||||
}
|
||||
|
||||
|
||||
PackageNode*
|
||||
LeafNode::GetPackageNode()
|
||||
{
|
||||
return fPackageNodes.Head();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
LeafNode::Read(off_t offset, void* buffer, size_t* bufferSize)
|
||||
{
|
||||
|
@ -28,6 +28,8 @@ public:
|
||||
|
||||
virtual status_t AddPackageNode(PackageNode* packageNode);
|
||||
|
||||
virtual PackageNode* GetPackageNode();
|
||||
|
||||
virtual status_t Read(off_t offset, void* buffer,
|
||||
size_t* bufferSize);
|
||||
|
||||
|
@ -53,6 +53,8 @@ public:
|
||||
|
||||
virtual status_t AddPackageNode(PackageNode* packageNode) = 0;
|
||||
|
||||
virtual PackageNode* GetPackageNode() = 0;
|
||||
|
||||
virtual status_t Read(off_t offset, void* buffer,
|
||||
size_t* bufferSize) = 0;
|
||||
|
||||
|
@ -34,7 +34,7 @@ Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
|
||||
Package::~Package()
|
||||
{
|
||||
while (PackageNode* node = fNodes.RemoveHead())
|
||||
delete node;
|
||||
node->ReleaseReference();
|
||||
|
||||
free(fName);
|
||||
|
||||
@ -57,6 +57,7 @@ void
|
||||
Package::AddNode(PackageNode* node)
|
||||
{
|
||||
fNodes.Add(node);
|
||||
node->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
#define PACKAGE_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include <util/khash.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
@ -17,7 +19,7 @@
|
||||
class PackageDomain;
|
||||
|
||||
|
||||
class Package {
|
||||
class Package : public BReferenceable {
|
||||
public:
|
||||
Package(PackageDomain* domain, dev_t deviceID,
|
||||
ino_t nodeID);
|
||||
|
@ -17,7 +17,7 @@ PackageDirectory::PackageDirectory(Package* package, mode_t mode)
|
||||
PackageDirectory::~PackageDirectory()
|
||||
{
|
||||
while (PackageNode* child = fChildren.RemoveHead())
|
||||
delete child;
|
||||
child->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,7 @@ void
|
||||
PackageDirectory::AddChild(PackageNode* node)
|
||||
{
|
||||
fChildren.Add(node);
|
||||
node->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
@ -32,4 +33,5 @@ void
|
||||
PackageDirectory::RemoveChild(PackageNode* node)
|
||||
{
|
||||
fChildren.Remove(node);
|
||||
node->ReleaseReference();
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ PackageDomain::~PackageDomain()
|
||||
Package* package = fPackages.Clear(true);
|
||||
while (package != NULL) {
|
||||
Package* next = package->HashTableNext();
|
||||
delete package;
|
||||
package->ReleaseReference();
|
||||
package = next;
|
||||
}
|
||||
|
||||
@ -70,6 +70,7 @@ void
|
||||
PackageDomain::AddPackage(Package* package)
|
||||
{
|
||||
fPackages.Insert(package);
|
||||
package->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
@ -77,4 +78,5 @@ void
|
||||
PackageDomain::RemovePackage(Package* package)
|
||||
{
|
||||
fPackages.Remove(package);
|
||||
package->ReleaseReference();
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ PackageNode::PackageNode(Package* package, mode_t mode)
|
||||
|
||||
PackageNode::~PackageNode()
|
||||
{
|
||||
while (PackageNodeAttribute* attribute = fAttributes.RemoveHead())
|
||||
delete attribute;
|
||||
|
||||
free(fName);
|
||||
}
|
||||
|
||||
@ -60,3 +63,30 @@ PackageNode::FileSize() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PackageNode::AddAttribute(PackageNodeAttribute* attribute)
|
||||
{
|
||||
fAttributes.Add(attribute);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PackageNode::RemoveAttribute(PackageNodeAttribute* attribute)
|
||||
{
|
||||
fAttributes.Remove(attribute);
|
||||
}
|
||||
|
||||
|
||||
PackageNodeAttribute*
|
||||
PackageNode::FindAttribute(const char* name) const
|
||||
{
|
||||
for (PackageNodeAttributeList::ConstIterator it = fAttributes.GetIterator();
|
||||
PackageNodeAttribute* attribute = it.Next();) {
|
||||
if (strcmp(attribute->Name(), name) == 0)
|
||||
return attribute;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -8,22 +8,26 @@
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include <util/SinglyLinkedList.h>
|
||||
|
||||
#include "PackageNodeAttribute.h"
|
||||
|
||||
|
||||
class Package;
|
||||
class PackageDirectory;
|
||||
|
||||
|
||||
class PackageNode : public SinglyLinkedListLinkImpl<PackageNode> {
|
||||
class PackageNode : public BReferenceable,
|
||||
public SinglyLinkedListLinkImpl<PackageNode> {
|
||||
public:
|
||||
PackageNode(Package* package, mode_t mode);
|
||||
virtual ~PackageNode();
|
||||
|
||||
PackageDirectory* Parent() const { return fParent; }
|
||||
const char* Name() const { return fName; }
|
||||
Package* GetPackage() const { return fPackage; }
|
||||
PackageDirectory* Parent() const { return fParent; }
|
||||
const char* Name() const { return fName; }
|
||||
|
||||
virtual status_t Init(PackageDirectory* parent,
|
||||
const char* name);
|
||||
@ -46,6 +50,15 @@ public:
|
||||
|
||||
virtual off_t FileSize() const;
|
||||
|
||||
void AddAttribute(PackageNodeAttribute* attribute);
|
||||
void RemoveAttribute(
|
||||
PackageNodeAttribute* attribute);
|
||||
|
||||
const PackageNodeAttributeList& Attributes() const
|
||||
{ return fAttributes; }
|
||||
|
||||
PackageNodeAttribute* FindAttribute(const char* name) const;
|
||||
|
||||
protected:
|
||||
Package* fPackage;
|
||||
PackageDirectory* fParent;
|
||||
@ -54,6 +67,7 @@ protected:
|
||||
uid_t fUserID;
|
||||
gid_t fGroupID;
|
||||
timespec fModifiedTime;
|
||||
PackageNodeAttributeList fAttributes;
|
||||
};
|
||||
|
||||
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "PackageNodeAttribute.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
PackageNodeAttribute::PackageNodeAttribute(PackageNode* parent, uint32 type,
|
||||
const PackageData& data)
|
||||
:
|
||||
fData(data),
|
||||
fParent(parent),
|
||||
fName(NULL),
|
||||
fType(type)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PackageNodeAttribute::~PackageNodeAttribute()
|
||||
{
|
||||
free(fName);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PackageNodeAttribute::Init(const char* name)
|
||||
{
|
||||
fName = strdup(name);
|
||||
return fName != NULL ? B_OK : B_NO_MEMORY;
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PACKAGE_NODE_ATTRIBUTE_H
|
||||
#define PACKAGE_NODE_ATTRIBUTE_H
|
||||
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include "PackageData.h"
|
||||
|
||||
|
||||
class PackageNode;
|
||||
|
||||
|
||||
class PackageNodeAttribute
|
||||
: public DoublyLinkedListLinkImpl<PackageNodeAttribute> {
|
||||
public:
|
||||
PackageNodeAttribute(PackageNode* parent,
|
||||
uint32 type, const PackageData& data);
|
||||
~PackageNodeAttribute();
|
||||
|
||||
PackageNode* Parent() const { return fParent; }
|
||||
const char* Name() const { return fName; }
|
||||
uint32 Type() const { return fType; }
|
||||
const PackageData& Data() const { return fData; }
|
||||
|
||||
status_t Init(const char* name);
|
||||
|
||||
|
||||
protected:
|
||||
PackageData fData;
|
||||
PackageNode* fParent;
|
||||
char* fName;
|
||||
uint32 fType;
|
||||
};
|
||||
|
||||
|
||||
typedef DoublyLinkedList<PackageNodeAttribute> PackageNodeAttributeList;
|
||||
|
||||
|
||||
#endif // PACKAGE_NODE_ATTRIBUTE_H
|
@ -21,6 +21,7 @@
|
||||
#include "ErrorOutput.h"
|
||||
#include "FDCloser.h"
|
||||
#include "PackageEntry.h"
|
||||
#include "PackageEntryAttribute.h"
|
||||
#include "PackageReader.h"
|
||||
|
||||
#include "DebugSupport.h"
|
||||
@ -164,7 +165,7 @@ struct Volume::PackageLoaderContentHandler : PackageContentHandler {
|
||||
|
||||
if (node == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
ObjectDeleter<PackageNode> nodeDeleter(node);
|
||||
BReference<PackageNode> nodeReference(node, true);
|
||||
|
||||
error = node->Init(parentDir, entry->Name());
|
||||
if (error != B_OK)
|
||||
@ -178,7 +179,6 @@ struct Volume::PackageLoaderContentHandler : PackageContentHandler {
|
||||
else
|
||||
fPackage->AddNode(node);
|
||||
|
||||
nodeDeleter.Detach();
|
||||
entry->SetUserToken(node);
|
||||
|
||||
return B_OK;
|
||||
@ -187,7 +187,24 @@ struct Volume::PackageLoaderContentHandler : PackageContentHandler {
|
||||
virtual status_t HandleEntryAttribute(PackageEntry* entry,
|
||||
PackageEntryAttribute* attribute)
|
||||
{
|
||||
// TODO:...
|
||||
if (fErrorOccurred)
|
||||
return B_OK;
|
||||
|
||||
PackageNode* node = (PackageNode*)entry->UserToken();
|
||||
|
||||
PackageNodeAttribute* nodeAttribute = new(std::nothrow)
|
||||
PackageNodeAttribute(node, attribute->Type(), attribute->Data());
|
||||
if (nodeAttribute == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY)
|
||||
|
||||
status_t error = nodeAttribute->Init(attribute->Name());
|
||||
if (error != B_OK) {
|
||||
delete nodeAttribute;
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
node->AddAttribute(nodeAttribute);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -231,6 +248,14 @@ Volume::~Volume()
|
||||
while (PackageDomain* packageDomain = fPackageDomains.RemoveHead())
|
||||
delete packageDomain;
|
||||
|
||||
// remove all nodes from the ID hash table
|
||||
Node* node = fNodes.Clear(true);
|
||||
while (node != NULL) {
|
||||
Node* next = node->IDHashTableNext();
|
||||
node->ReleaseReference();
|
||||
node = next;
|
||||
}
|
||||
|
||||
if (fRootDirectory != NULL)
|
||||
fRootDirectory->ReleaseReference();
|
||||
|
||||
@ -444,7 +469,7 @@ Volume::_AddPackageDomain(PackageDomain* domain)
|
||||
st.st_ino);
|
||||
if (package == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
ObjectDeleter<Package> packageDeleter(package);
|
||||
BReference<Package> packageReference(package, true);
|
||||
|
||||
status_t error = package->Init(entry->d_name);
|
||||
if (error != B_OK)
|
||||
@ -454,7 +479,7 @@ Volume::_AddPackageDomain(PackageDomain* domain)
|
||||
if (error != B_OK)
|
||||
continue;
|
||||
|
||||
domain->AddPackage(packageDeleter.Detach());
|
||||
domain->AddPackage(package);
|
||||
}
|
||||
|
||||
// add the packages to the node tree
|
||||
@ -602,7 +627,7 @@ Volume::_CreateNode(mode_t mode, Directory* parent, const char* name,
|
||||
|
||||
if (node == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
ObjectDeleter<Node> nodeDeleter(node);
|
||||
BReference<Node> nodeReference(node, true);
|
||||
|
||||
status_t error = node->Init(parent, name);
|
||||
if (error != B_OK)
|
||||
@ -611,8 +636,9 @@ Volume::_CreateNode(mode_t mode, Directory* parent, const char* name,
|
||||
parent->AddChild(node);
|
||||
|
||||
fNodes.Insert(node);
|
||||
nodeReference.Detach();
|
||||
// we keep the initial node reference for this table
|
||||
|
||||
_node = nodeDeleter.Detach();
|
||||
_node = node;
|
||||
return B_OK;
|
||||
}
|
||||
|
@ -523,6 +523,10 @@ packagefs_open_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
|
||||
|
||||
Directory* dir = dynamic_cast<Directory*>(node);
|
||||
|
||||
status_t error = check_access(dir, R_OK);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create a cookie
|
||||
NodeWriteLocker dirLocker(dir);
|
||||
DirectoryCookie* cookie = new(std::nothrow) DirectoryCookie(dir);
|
||||
@ -644,6 +648,361 @@ 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)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
|
||||
|
||||
status_t error = check_access(node, R_OK);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create a cookie
|
||||
NodeReadLocker nodeLocker(node);
|
||||
AttributeDirectoryCookie* cookie
|
||||
= new(std::nothrow) AttributeDirectoryCookie(node);
|
||||
if (cookie == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
*_cookie = cookie;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_close_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_free_attr_dir_cookie(fs_volume* fsVolume, fs_vnode* fsNode,
|
||||
void* _cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
AttributeDirectoryCookie* cookie = (AttributeDirectoryCookie*)_cookie;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
|
||||
node->ID(), cookie);
|
||||
TOUCH(volume);
|
||||
TOUCH(node);
|
||||
|
||||
delete cookie;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_read_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
|
||||
struct dirent* buffer, size_t bufferSize, uint32* _count)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
AttributeDirectoryCookie* cookie = (AttributeDirectoryCookie*)_cookie;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
|
||||
node->ID(), 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;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
AttributeDirectoryCookie* cookie = (AttributeDirectoryCookie*)_cookie;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
|
||||
node->ID(), cookie);
|
||||
TOUCH(volume);
|
||||
TOUCH(node);
|
||||
|
||||
cookie->Rewind();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Attribute Operations
|
||||
|
||||
|
||||
struct AttributeCookie {
|
||||
PackageNode* packageNode;
|
||||
Package* package;
|
||||
PackageNodeAttribute* attribute;
|
||||
int openMode;
|
||||
|
||||
AttributeCookie(PackageNode* packageNode, PackageNodeAttribute* attribute,
|
||||
int openMode)
|
||||
:
|
||||
packageNode(packageNode),
|
||||
package(packageNode->GetPackage()),
|
||||
attribute(attribute),
|
||||
openMode(openMode)
|
||||
{
|
||||
packageNode->AcquireReference();
|
||||
package->AcquireReference();
|
||||
}
|
||||
|
||||
~AttributeCookie()
|
||||
{
|
||||
packageNode->ReleaseReference();
|
||||
package->ReleaseReference();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
|
||||
int openMode, void** _cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld), name: \"%s\", openMode %#x\n",
|
||||
volume, node, node->ID(), name, openMode);
|
||||
TOUCH(volume);
|
||||
|
||||
NodeReadLocker nodeLocker(node);
|
||||
|
||||
// check the open mode and permissions
|
||||
if ((openMode & O_RWMASK) != O_RDONLY)
|
||||
return B_NOT_ALLOWED;
|
||||
|
||||
status_t error = check_access(node, R_OK);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// get the package node and the respectively named attribute
|
||||
PackageNode* packageNode = node->GetPackageNode();
|
||||
PackageNodeAttribute* attribute = packageNode != NULL
|
||||
? packageNode->FindAttribute(name) : NULL;
|
||||
if (attribute == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
// allocate the cookie
|
||||
AttributeCookie* cookie = new(std::nothrow) AttributeCookie(packageNode,
|
||||
attribute, openMode);
|
||||
if (cookie == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
*_cookie = cookie;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_close_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_free_attr_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
|
||||
node->ID(), cookie);
|
||||
TOUCH(volume);
|
||||
TOUCH(node);
|
||||
|
||||
delete cookie;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
read_package_data(const PackageData& data, DataReader* dataReader, off_t offset,
|
||||
void* buffer, size_t* bufferSize)
|
||||
{
|
||||
// create a PackageDataReader
|
||||
PackageDataReader* reader;
|
||||
status_t error = GlobalFactory::Default()->CreatePackageDataReader(
|
||||
dataReader, data, reader);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
ObjectDeleter<PackageDataReader> readerDeleter(reader);
|
||||
|
||||
// check the offset
|
||||
if (offset < 0 || (uint64)offset > data.UncompressedSize())
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// clamp the size
|
||||
size_t toRead = std::min((uint64)*bufferSize,
|
||||
data.UncompressedSize() - offset);
|
||||
|
||||
// read
|
||||
if (toRead > 0) {
|
||||
status_t error = reader->ReadData(offset, buffer, toRead);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
*bufferSize = toRead;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
|
||||
off_t offset, void* buffer, size_t* bufferSize)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
|
||||
node->ID(), cookie);
|
||||
TOUCH(volume);
|
||||
TOUCH(node);
|
||||
|
||||
const PackageData& data = cookie->attribute->Data();
|
||||
if (data.IsEncodedInline()) {
|
||||
// inline data
|
||||
BufferDataReader dataReader(data.InlineData(), data.CompressedSize());
|
||||
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
||||
}
|
||||
|
||||
// data not inline -- open the package
|
||||
int fd = cookie->package->Open();
|
||||
if (fd < 0)
|
||||
RETURN_ERROR(fd);
|
||||
PackageCloser packageCloser(cookie->package);
|
||||
|
||||
FDDataReader dataReader(fd);
|
||||
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
packagefs_read_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode,
|
||||
void* _cookie, struct stat* st)
|
||||
{
|
||||
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||
Node* node = (Node*)fsNode->private_node;
|
||||
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||
|
||||
FUNCTION("volume: %p, node: %p (%lld), cookie: %p\n", volume, node,
|
||||
node->ID(), cookie);
|
||||
TOUCH(volume);
|
||||
TOUCH(node);
|
||||
|
||||
st->st_size = cookie->attribute->Data().UncompressedSize();
|
||||
st->st_type = cookie->attribute->Type();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Module Interface
|
||||
|
||||
|
||||
@ -717,13 +1076,13 @@ fs_volume_ops gPackageFSVolumeOps = {
|
||||
|
||||
|
||||
fs_vnode_ops gPackageFSVnodeOps = {
|
||||
/* vnode operations */
|
||||
// vnode operations
|
||||
&packagefs_lookup,
|
||||
NULL, // get_vnode_name,
|
||||
&packagefs_put_vnode,
|
||||
&packagefs_put_vnode, // remove_vnode -- same as put_vnode
|
||||
|
||||
/* VM file access */
|
||||
// VM file access
|
||||
NULL, // can_page,
|
||||
NULL, // read_pages,
|
||||
NULL, // write_pages,
|
||||
@ -750,7 +1109,7 @@ fs_vnode_ops gPackageFSVnodeOps = {
|
||||
&packagefs_read_stat,
|
||||
NULL, // write_stat,
|
||||
|
||||
/* file operations */
|
||||
// file operations
|
||||
NULL, // create,
|
||||
&packagefs_open,
|
||||
&packagefs_close,
|
||||
@ -758,17 +1117,35 @@ fs_vnode_ops gPackageFSVnodeOps = {
|
||||
&packagefs_read,
|
||||
NULL, // write,
|
||||
|
||||
/* directory operations */
|
||||
// directory operations
|
||||
NULL, // create_dir,
|
||||
NULL, // remove_dir,
|
||||
&packagefs_open_dir,
|
||||
&packagefs_close_dir,
|
||||
&packagefs_free_dir_cookie,
|
||||
&packagefs_read_dir,
|
||||
&packagefs_rewind_dir
|
||||
&packagefs_rewind_dir,
|
||||
|
||||
// attribute directory operations
|
||||
&packagefs_open_attr_dir,
|
||||
&packagefs_close_attr_dir,
|
||||
&packagefs_free_attr_dir_cookie,
|
||||
&packagefs_read_attr_dir,
|
||||
&packagefs_rewind_attr_dir,
|
||||
|
||||
// attribute operations
|
||||
NULL, // create_attr,
|
||||
&packagefs_open_attr,
|
||||
&packagefs_close_attr,
|
||||
&packagefs_free_attr_cookie,
|
||||
&packagefs_read_attr,
|
||||
NULL, // write_attr,
|
||||
|
||||
&packagefs_read_attr_stat,
|
||||
NULL, // write_attr_stat,
|
||||
NULL, // rename_attr,
|
||||
NULL // remove_attr,
|
||||
|
||||
// TODO: attribute directory operations
|
||||
// TODO: attribute operations
|
||||
// TODO: FS layer operations
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user