diff --git a/src/add-ons/kernel/file_systems/packagefs/Directory.cpp b/src/add-ons/kernel/file_systems/packagefs/Directory.cpp index 0dbb8feaa7..7759ae709e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Directory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Directory.cpp @@ -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(); diff --git a/src/add-ons/kernel/file_systems/packagefs/Directory.h b/src/add-ons/kernel/file_systems/packagefs/Directory.h index a48059f8ac..9f5e0bf8d8 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Directory.h +++ b/src/add-ons/kernel/file_systems/packagefs/Directory.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 6809f94040..67364d59be 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -23,6 +23,7 @@ HAIKU_PACKAGE_FS_SOURCES = PackageFile.cpp PackageLeafNode.cpp PackageNode.cpp + PackageNodeAttribute.cpp PackageSymlink.cpp Volume.cpp ; diff --git a/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp b/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp index e25fa003b0..06c3eba92f 100644 --- a/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/LeafNode.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) { diff --git a/src/add-ons/kernel/file_systems/packagefs/LeafNode.h b/src/add-ons/kernel/file_systems/packagefs/LeafNode.h index 1384d73405..1a8fad642c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/LeafNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/LeafNode.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/packagefs/Node.h b/src/add-ons/kernel/file_systems/packagefs/Node.h index 37541eb7af..673eea7705 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Node.h +++ b/src/add-ons/kernel/file_systems/packagefs/Node.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/packagefs/Package.cpp b/src/add-ons/kernel/file_systems/packagefs/Package.cpp index 0546566b1c..e0123a6926 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Package.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Package.cpp @@ -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(); } diff --git a/src/add-ons/kernel/file_systems/packagefs/Package.h b/src/add-ons/kernel/file_systems/packagefs/Package.h index b026cedac2..17f76633ec 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Package.h +++ b/src/add-ons/kernel/file_systems/packagefs/Package.h @@ -6,6 +6,8 @@ #define PACKAGE_H +#include + #include #include @@ -17,7 +19,7 @@ class PackageDomain; -class Package { +class Package : public BReferenceable { public: Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID); diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp index 62e4fb864f..e24542c6f3 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageDirectory.cpp @@ -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(); } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageDomain.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageDomain.cpp index 8fbd52e223..f2627490f5 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageDomain.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageDomain.cpp @@ -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(); } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp index 2283c34ead..7291a0f381 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNode.cpp @@ -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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNode.h b/src/add-ons/kernel/file_systems/packagefs/PackageNode.h index b68d0f5f16..1b215ec363 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNode.h @@ -8,22 +8,26 @@ #include -#include +#include #include +#include "PackageNodeAttribute.h" + class Package; class PackageDirectory; -class PackageNode : public SinglyLinkedListLinkImpl { +class PackageNode : public BReferenceable, + public SinglyLinkedListLinkImpl { 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; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.cpp new file mode 100644 index 0000000000..0e361bf347 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "PackageNodeAttribute.h" + +#include +#include + + +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; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.h b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.h new file mode 100644 index 0000000000..a395e7fbc1 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/PackageNodeAttribute.h @@ -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 + +#include "PackageData.h" + + +class PackageNode; + + +class PackageNodeAttribute + : public DoublyLinkedListLinkImpl { +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 PackageNodeAttributeList; + + +#endif // PACKAGE_NODE_ATTRIBUTE_H diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index ca374eaa8d..950332a65a 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -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 nodeDeleter(node); + BReference 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 packageDeleter(package); + BReference 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 nodeDeleter(node); + BReference 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; } diff --git a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp index b8a53b1b00..30369620ad 100644 --- a/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/kernel_interface.cpp @@ -523,6 +523,10 @@ packagefs_open_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie) Directory* dir = dynamic_cast(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 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 };