diff --git a/src/add-ons/kernel/file_systems/packagefs/Directory.cpp b/src/add-ons/kernel/file_systems/packagefs/Directory.cpp index 0962974498..141c6ce85e 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Directory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Directory.cpp @@ -99,6 +99,13 @@ Directory::FileSize() const } +Node* +Directory::GetNode() +{ + return this; +} + + status_t Directory::AddPackageNode(PackageNode* packageNode) { diff --git a/src/add-ons/kernel/file_systems/packagefs/Directory.h b/src/add-ons/kernel/file_systems/packagefs/Directory.h index 6a73d24fef..f9c9ac173f 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Directory.h +++ b/src/add-ons/kernel/file_systems/packagefs/Directory.h @@ -8,6 +8,7 @@ #include "Node.h" #include "PackageDirectory.h" +#include "UnpackingNode.h" struct DirectoryIterator : DoublyLinkedListLinkImpl { @@ -23,7 +24,7 @@ struct DirectoryIterator : DoublyLinkedListLinkImpl { typedef DoublyLinkedList DirectoryIteratorList; -class Directory : public Node { +class Directory : public Node, public UnpackingNode { public: Directory(ino_t id); virtual ~Directory(); @@ -39,6 +40,8 @@ public: virtual timespec ModifiedTime() const; virtual off_t FileSize() const; + virtual Node* GetNode(); + virtual status_t AddPackageNode(PackageNode* packageNode); virtual void RemovePackageNode(PackageNode* packageNode); diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 12d9dae345..043f157e09 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -30,6 +30,7 @@ HAIKU_PACKAGE_FS_SOURCES = Resolvable.cpp UnpackingAttributeCookie.cpp UnpackingAttributeDirectoryCookie.cpp + UnpackingNode.cpp Version.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 b02a48b930..874dbc264c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/LeafNode.cpp @@ -98,6 +98,13 @@ LeafNode::FileSize() const } +Node* +LeafNode::GetNode() +{ + return this; +} + + status_t LeafNode::AddPackageNode(PackageNode* packageNode) { diff --git a/src/add-ons/kernel/file_systems/packagefs/LeafNode.h b/src/add-ons/kernel/file_systems/packagefs/LeafNode.h index 877a9bd3be..2e427b3b75 100644 --- a/src/add-ons/kernel/file_systems/packagefs/LeafNode.h +++ b/src/add-ons/kernel/file_systems/packagefs/LeafNode.h @@ -8,9 +8,10 @@ #include "Node.h" #include "PackageLeafNode.h" +#include "UnpackingNode.h" -class LeafNode : public Node { +class LeafNode : public Node, public UnpackingNode { public: LeafNode(ino_t id); virtual ~LeafNode(); @@ -26,6 +27,8 @@ public: virtual timespec ModifiedTime() const; virtual off_t FileSize() const; + virtual Node* GetNode(); + virtual status_t AddPackageNode(PackageNode* packageNode); virtual void RemovePackageNode(PackageNode* packageNode); diff --git a/src/add-ons/kernel/file_systems/packagefs/Node.h b/src/add-ons/kernel/file_systems/packagefs/Node.h index 62b1695231..9b0dc31efe 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Node.h +++ b/src/add-ons/kernel/file_systems/packagefs/Node.h @@ -53,11 +53,6 @@ public: virtual timespec ModifiedTime() const = 0; virtual off_t FileSize() const = 0; - virtual status_t AddPackageNode(PackageNode* packageNode) = 0; - virtual void RemovePackageNode(PackageNode* packageNode) = 0; - - virtual PackageNode* GetPackageNode() = 0; - virtual status_t Read(off_t offset, void* buffer, size_t* bufferSize) = 0; virtual status_t Read(io_request* request) = 0; diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingNode.cpp b/src/add-ons/kernel/file_systems/packagefs/UnpackingNode.cpp new file mode 100644 index 0000000000..dd99ca9dd2 --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingNode.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "UnpackingNode.h" + + +UnpackingNode::~UnpackingNode() +{ +} diff --git a/src/add-ons/kernel/file_systems/packagefs/UnpackingNode.h b/src/add-ons/kernel/file_systems/packagefs/UnpackingNode.h new file mode 100644 index 0000000000..f1edd5fe3d --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/UnpackingNode.h @@ -0,0 +1,29 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef UNPACKING_NODE_H +#define UNPACKING_NODE_H + + +#include + + +class Node; +class PackageNode; + + +class UnpackingNode { +public: + virtual ~UnpackingNode(); + + virtual Node* GetNode() = 0; + + virtual status_t AddPackageNode(PackageNode* packageNode) = 0; + virtual void RemovePackageNode(PackageNode* packageNode) = 0; + + virtual PackageNode* GetPackageNode() = 0; +}; + + +#endif // UNPACKING_NODE_H diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 9f06212992..1ee70f9349 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -949,17 +949,26 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode, bool notify, Node*& _node) { bool newNode = false; + UnpackingNode* unpackingNode; Node* node = directory->FindChild(packageNode->Name()); - if (node == NULL) { - status_t error = _CreateNode(packageNode->Mode(), directory, - packageNode->Name(), node); + + if (node != NULL) { + unpackingNode = dynamic_cast(node); + if (unpackingNode == NULL) + RETURN_ERROR(B_BAD_VALUE); + } else { + status_t error = _CreateUnpackingNode(packageNode->Mode(), directory, + packageNode->Name(), unpackingNode); if (error != B_OK) RETURN_ERROR(error); + + node = unpackingNode->GetNode(); newNode = true; } + BReference nodeReference(node); - status_t error = node->AddPackageNode(packageNode); + status_t error = unpackingNode->AddPackageNode(packageNode); if (error != B_OK) { // remove the node, if created before if (newNode) @@ -971,7 +980,7 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode, if (newNode) { notify_entry_created(ID(), directory->ID(), node->Name(), node->ID()); - } else if (packageNode == node->GetPackageNode()) { + } else if (packageNode == unpackingNode->GetPackageNode()) { // The new package node has become the one representing the node. // Send stat changed notification for directories and entry // removed + created notifications for files and symlinks. @@ -999,15 +1008,19 @@ void Volume::_RemovePackageNode(Directory* directory, PackageNode* packageNode, Node* node, bool notify) { + UnpackingNode* unpackingNode = dynamic_cast(node); + if (unpackingNode == NULL) + return; + BReference nodeReference(node); - PackageNode* headPackageNode = node->GetPackageNode(); - node->RemovePackageNode(packageNode); + PackageNode* headPackageNode = unpackingNode->GetPackageNode(); + unpackingNode->RemovePackageNode(packageNode); // If the node doesn't have any more package nodes attached, remove it // completely. bool nodeRemoved = false; - if (node->GetPackageNode() == NULL) { + if (unpackingNode->GetPackageNode() == NULL) { // we get and put the vnode to notify the VFS // TODO: We should probably only do that, if the node is known to the // VFS in the first place. @@ -1050,19 +1063,21 @@ Volume::_RemovePackageNode(Directory* directory, PackageNode* packageNode, status_t -Volume::_CreateNode(mode_t mode, Directory* parent, const char* name, - Node*& _node) +Volume::_CreateUnpackingNode(mode_t mode, Directory* parent, const char* name, + UnpackingNode*& _node) { - Node* node; + UnpackingNode* unpackingNode; if (S_ISREG(mode) || S_ISLNK(mode)) - node = new(std::nothrow) LeafNode(fNextNodeID++); + unpackingNode = new(std::nothrow) LeafNode(fNextNodeID++); else if (S_ISDIR(mode)) - node = new(std::nothrow) Directory(fNextNodeID++); + unpackingNode = new(std::nothrow) Directory(fNextNodeID++); else RETURN_ERROR(B_UNSUPPORTED); - if (node == NULL) + if (unpackingNode == NULL) RETURN_ERROR(B_NO_MEMORY); + + Node* node = unpackingNode->GetNode(); BReference nodeReference(node, true); status_t error = node->Init(parent, name); @@ -1075,7 +1090,7 @@ Volume::_CreateNode(mode_t mode, Directory* parent, const char* name, nodeReference.Detach(); // we keep the initial node reference for this table - _node = node; + _node = unpackingNode; return B_OK; } @@ -1327,23 +1342,25 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting) } // create the directory - Node* directory; - error = _CreateNode(S_IFDIR, fRootDirectory, directoryName, directory); + UnpackingNode* directory; + error = _CreateUnpackingNode(S_IFDIR, fRootDirectory, directoryName, + directory); if (error != B_OK) RETURN_ERROR(error); // publish its vnode, so the VFS will find it without asking us - error = PublishVNode(directory); + Node* directoryNode = directory->GetNode(); + error = PublishVNode(directoryNode); if (error != B_OK) { - _RemoveNode(directory); + _RemoveNode(directoryNode); RETURN_ERROR(error); } // bind the directory error = vfs_bind_mount_directory(st.st_dev, st.st_ino, fFSVolume->id, - directory->ID()); + directoryNode->ID()); - PutVNode(directory->ID()); + PutVNode(directoryNode->ID()); // release our reference again -- on success // vfs_bind_mount_directory() got one diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h b/src/add-ons/kernel/file_systems/packagefs/Volume.h index 813b0f505c..e7e5a3a867 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h @@ -21,6 +21,7 @@ class Directory; class Node; class PackageFSRoot; +class UnpackingNode; enum MountType { @@ -117,8 +118,9 @@ private: PackageNode* packageNode, Node* node, bool notify); - status_t _CreateNode(mode_t mode, Directory* parent, - const char* name, Node*& _node); + status_t _CreateUnpackingNode(mode_t mode, + Directory* parent, const char* name, + UnpackingNode*& _node); // does *not* return a reference void _RemoveNode(Node* node);