* Implemented intermediate base class PackageLeafNode for PackageFile and

PackageSymlink with a "fat" interface.
* Replaced File and Symlink by fat class LeafNode.
* Added Package* object management to Directory and LeafNode.
* Implemented packagefs_read_symlink(), so symlinks work now.
* Added some missing locking the kernel interface.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34096 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-11-17 16:10:21 +00:00
parent 9d6405b724
commit 694cb0b270
22 changed files with 336 additions and 168 deletions
@@ -7,14 +7,12 @@
#include "Directory.h" #include "Directory.h"
#include "DebugSupport.h" #include "DebugSupport.h"
#include "PackageDirectory.h"
Directory::Directory(ino_t id) Directory::Directory(ino_t id)
: :
Node(id) Node(id)
{ {
fMode = S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
} }
@@ -40,13 +38,43 @@ Directory::Init(Directory* parent, const char* name)
} }
mode_t
Directory::Mode() const
{
if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
return packageDirectory->Mode();
return S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
}
uid_t
Directory::UserID() const
{
if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
return packageDirectory->UserID();
return 0;
}
gid_t
Directory::GroupID() const
{
if (PackageDirectory* packageDirectory = fPackageDirectories.Head())
return packageDirectory->GroupID();
return 0;
}
status_t status_t
Directory::AddPackageNode(PackageNode* packageNode) Directory::AddPackageNode(PackageNode* packageNode)
{ {
if (!S_ISDIR(packageNode->Mode())) if (!S_ISDIR(packageNode->Mode()))
return B_BAD_VALUE; return B_BAD_VALUE;
// TODO:... PackageDirectory* packageDirectory
= dynamic_cast<PackageDirectory*>(packageNode);
fPackageDirectories.Add(packageDirectory);
return B_OK; return B_OK;
} }
@@ -7,6 +7,7 @@
#include "Node.h" #include "Node.h"
#include "PackageDirectory.h"
@@ -30,6 +31,10 @@ public:
virtual status_t Init(Directory* parent, const char* name); virtual status_t Init(Directory* parent, const char* name);
virtual mode_t Mode() const;
virtual uid_t UserID() const;
virtual gid_t GroupID() const;
virtual status_t AddPackageNode(PackageNode* packageNode); virtual status_t AddPackageNode(PackageNode* packageNode);
void AddChild(Node* node); void AddChild(Node* node);
@@ -47,6 +52,7 @@ public:
private: private:
NodeNameHashTable fChildTable; NodeNameHashTable fChildTable;
NodeList fChildList; NodeList fChildList;
PackageDirectoryList fPackageDirectories;
DirectoryIteratorList fIterators; DirectoryIteratorList fIterators;
}; };
@@ -1,41 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "File.h"
#include "PackageFile.h"
File::File(ino_t id)
:
Node(id)
{
fMode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
}
File::~File()
{
}
status_t
File::Init(Directory* parent, const char* name)
{
return Node::Init(parent, name);
}
status_t
File::AddPackageNode(PackageNode* packageNode)
{
if (!S_ISREG(packageNode->Mode()))
return B_BAD_VALUE;
// TODO:...
return B_OK;
}
@@ -1,23 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef FILE_H
#define FILE_H
#include "Node.h"
class File : public Node {
public:
File(ino_t id);
virtual ~File();
virtual status_t Init(Directory* parent, const char* name);
virtual status_t AddPackageNode(PackageNode* packageNode);
};
#endif // FILE_H
@@ -12,16 +12,16 @@ DEFINES += B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT ;
HAIKU_PACKAGE_FS_SOURCES = HAIKU_PACKAGE_FS_SOURCES =
DebugSupport.cpp DebugSupport.cpp
Directory.cpp Directory.cpp
File.cpp
kernel_interface.cpp kernel_interface.cpp
LeafNode.cpp
Node.cpp Node.cpp
Package.cpp Package.cpp
PackageDirectory.cpp PackageDirectory.cpp
PackageDomain.cpp PackageDomain.cpp
PackageFile.cpp PackageFile.cpp
PackageLeafNode.cpp
PackageNode.cpp PackageNode.cpp
PackageSymlink.cpp PackageSymlink.cpp
Symlink.cpp
Volume.cpp Volume.cpp
; ;
@@ -0,0 +1,74 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "LeafNode.h"
LeafNode::LeafNode(ino_t id)
:
Node(id)
{
}
LeafNode::~LeafNode()
{
}
status_t
LeafNode::Init(Directory* parent, const char* name)
{
return Node::Init(parent, name);
}
mode_t
LeafNode::Mode() const
{
if (PackageLeafNode* packageNode = fPackageNodes.Head())
return packageNode->Mode();
return S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
}
uid_t
LeafNode::UserID() const
{
if (PackageLeafNode* packageNode = fPackageNodes.Head())
return packageNode->UserID();
return 0;
}
gid_t
LeafNode::GroupID() const
{
if (PackageLeafNode* packageNode = fPackageNodes.Head())
return packageNode->GroupID();
return 0;
}
status_t
LeafNode::AddPackageNode(PackageNode* packageNode)
{
if (S_ISDIR(packageNode->Mode()))
return B_BAD_VALUE;
fPackageNodes.Add(dynamic_cast<PackageLeafNode*>(packageNode));
return B_OK;
}
const char*
LeafNode::SymlinkPath() const
{
if (PackageLeafNode* packageNode = fPackageNodes.Head())
return packageNode->SymlinkPath();
return NULL;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef LEAF_NODE_H
#define LEAF_NODE_H
#include "Node.h"
#include "PackageLeafNode.h"
class LeafNode : public Node {
public:
LeafNode(ino_t id);
virtual ~LeafNode();
virtual status_t Init(Directory* parent, const char* name);
virtual mode_t Mode() const;
virtual uid_t UserID() const;
virtual gid_t GroupID() const;
virtual status_t AddPackageNode(PackageNode* packageNode);
const char* SymlinkPath() const;
private:
PackageLeafNodeList fPackageNodes;
};
#endif // LEAF_NODE_H
@@ -40,12 +40,12 @@ public:
Node*& IDHashTableNext() Node*& IDHashTableNext()
{ return fIDHashTableNext; } { return fIDHashTableNext; }
mode_t Mode() const { return fMode; }
uid_t UserID() const { return fUserID; }
gid_t GroupID() const { return fGroupID; }
virtual status_t Init(Directory* parent, const char* name); virtual status_t Init(Directory* parent, const char* name);
virtual mode_t Mode() const = 0;
virtual uid_t UserID() const = 0;
virtual gid_t GroupID() const = 0;
virtual status_t AddPackageNode(PackageNode* packageNode) = 0; virtual status_t AddPackageNode(PackageNode* packageNode) = 0;
protected: protected:
@@ -7,7 +7,9 @@
#include "PackageDirectory.h" #include "PackageDirectory.h"
PackageDirectory::PackageDirectory() PackageDirectory::PackageDirectory(mode_t mode)
:
PackageNode(mode)
{ {
} }
@@ -6,12 +6,15 @@
#define PACKAGE_DIRECTORY_H #define PACKAGE_DIRECTORY_H
#include <util/DoublyLinkedList.h>
#include "PackageNode.h" #include "PackageNode.h"
class PackageDirectory : public PackageNode { class PackageDirectory : public PackageNode,
public DoublyLinkedListLinkImpl<PackageDirectory> {
public: public:
PackageDirectory(); PackageDirectory(mode_t mode);
virtual ~PackageDirectory(); virtual ~PackageDirectory();
void AddChild(PackageNode* node); void AddChild(PackageNode* node);
@@ -42,4 +45,7 @@ PackageDirectory::NextChild(PackageNode* node) const
} }
typedef DoublyLinkedList<PackageDirectory> PackageDirectoryList;
#endif // PACKAGE_DIRECTORY_H #endif // PACKAGE_DIRECTORY_H
@@ -7,7 +7,10 @@
#include "PackageFile.h" #include "PackageFile.h"
PackageFile::PackageFile() PackageFile::PackageFile(mode_t mode, const PackageData& data)
:
PackageLeafNode(mode),
fData(data)
{ {
} }
@@ -6,13 +6,19 @@
#define PACKAGE_FILE_H #define PACKAGE_FILE_H
#include "PackageNode.h" #include "PackageData.h"
#include "PackageLeafNode.h"
class PackageFile : public PackageNode { class PackageFile : public PackageLeafNode {
public: public:
PackageFile(); PackageFile(mode_t mode,
const PackageData& data);
virtual ~PackageFile(); virtual ~PackageFile();
private:
PackageData fData;
}; };
@@ -0,0 +1,26 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "PackageLeafNode.h"
PackageLeafNode::PackageLeafNode(mode_t mode)
:
PackageNode(mode)
{
}
PackageLeafNode::~PackageLeafNode()
{
}
const char*
PackageLeafNode::SymlinkPath() const
{
return NULL;
}
@@ -0,0 +1,32 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_LEAF_NODE_H
#define PACKAGE_LEAF_NODE_H
#include "PackageNode.h"
class PackageData;
class PackageLeafNode : public PackageNode {
public:
PackageLeafNode(mode_t mode);
virtual ~PackageLeafNode();
virtual const char* SymlinkPath() const;
public:
SinglyLinkedListLink<PackageLeafNode> fListLink;
};
typedef SinglyLinkedList<PackageLeafNode,
SinglyLinkedListMemberGetLink<PackageLeafNode,
&PackageLeafNode::fListLink> > PackageLeafNodeList;
#endif // PACKAGE_LEAF_NODE_H
@@ -12,10 +12,13 @@
#include "DebugSupport.h" #include "DebugSupport.h"
PackageNode::PackageNode() PackageNode::PackageNode(mode_t mode)
: :
fParent(NULL), fParent(NULL),
fName(NULL) fName(NULL),
fMode(mode),
fUserID(0),
fGroupID(0)
{ {
} }
@@ -16,7 +16,7 @@ class PackageDirectory;
class PackageNode : public SinglyLinkedListLinkImpl<PackageNode> { class PackageNode : public SinglyLinkedListLinkImpl<PackageNode> {
public: public:
PackageNode(); PackageNode(mode_t mode);
virtual ~PackageNode(); virtual ~PackageNode();
PackageDirectory* Parent() const { return fParent; } PackageDirectory* Parent() const { return fParent; }
@@ -25,13 +25,20 @@ public:
virtual status_t Init(PackageDirectory* parent, virtual status_t Init(PackageDirectory* parent,
const char* name); const char* name);
void SetMode(mode_t mode) { fMode = mode; }
mode_t Mode() const { return fMode; } mode_t Mode() const { return fMode; }
private: uid_t UserID() const { return fUserID; }
void SetUserID(uid_t id) { fUserID = id; }
gid_t GroupID() const { return fGroupID; }
void SetGroupID(gid_t id) { fGroupID = id; }
protected:
PackageDirectory* fParent; PackageDirectory* fParent;
char* fName; char* fName;
mode_t fMode; mode_t fMode;
uid_t fUserID;
gid_t fGroupID;
}; };
@@ -6,12 +6,37 @@
#include "PackageSymlink.h" #include "PackageSymlink.h"
#include <stdlib.h>
#include <string.h>
PackageSymlink::PackageSymlink()
PackageSymlink::PackageSymlink(mode_t mode)
:
PackageLeafNode(mode),
fSymlinkPath(NULL)
{ {
} }
PackageSymlink::~PackageSymlink() PackageSymlink::~PackageSymlink()
{ {
free(fSymlinkPath);
}
status_t
PackageSymlink::SetSymlinkPath(const char* path)
{
if (path == NULL)
return B_OK;
fSymlinkPath = strdup(path);
return fSymlinkPath != NULL ? B_OK : B_NO_MEMORY;
}
const char*
PackageSymlink::SymlinkPath() const
{
return fSymlinkPath;
} }
@@ -6,13 +6,20 @@
#define PACKAGE_SYMLINK_H #define PACKAGE_SYMLINK_H
#include "PackageNode.h" #include "PackageLeafNode.h"
class PackageSymlink : public PackageNode { class PackageSymlink : public PackageLeafNode {
public: public:
PackageSymlink(); PackageSymlink(mode_t mode);
virtual ~PackageSymlink(); virtual ~PackageSymlink();
status_t SetSymlinkPath(const char* path);
virtual const char* SymlinkPath() const;
private:
char* fSymlinkPath;
}; };
@@ -1,41 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "Symlink.h"
#include "PackageSymlink.h"
Symlink::Symlink(ino_t id)
:
Node(id)
{
fMode = S_IFLNK | S_IRUSR | S_IRGRP | S_IROTH;
}
Symlink::~Symlink()
{
}
status_t
Symlink::Init(Directory* parent, const char* name)
{
return Node::Init(parent, name);
}
status_t
Symlink::AddPackageNode(PackageNode* packageNode)
{
if (!S_ISLNK(packageNode->Mode()))
return B_BAD_VALUE;
// TODO:...
return B_OK;
}
@@ -1,23 +0,0 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef SYMLINK_H
#define SYMLINK_H
#include "Node.h"
class Symlink : public Node {
public:
Symlink(ino_t id);
virtual ~Symlink();
virtual status_t Init(Directory* parent, const char* name);
virtual status_t AddPackageNode(PackageNode* packageNode);
};
#endif // SYMLINK_H
@@ -25,12 +25,11 @@
#include "DebugSupport.h" #include "DebugSupport.h"
#include "Directory.h" #include "Directory.h"
#include "File.h" #include "LeafNode.h"
#include "kernel_interface.h" #include "kernel_interface.h"
#include "PackageDirectory.h" #include "PackageDirectory.h"
#include "PackageFile.h" #include "PackageFile.h"
#include "PackageSymlink.h" #include "PackageSymlink.h"
#include "Symlink.h"
// node ID of the root directory // node ID of the root directory
@@ -133,14 +132,30 @@ struct Volume::PackageLoaderContentHandler : PackageContentHandler {
RETURN_ERROR(B_BAD_DATA); RETURN_ERROR(B_BAD_DATA);
} }
status_t error;
// create the package node // create the package node
PackageNode* node; PackageNode* node;
if (S_ISREG(entry->Mode())) { if (S_ISREG(entry->Mode())) {
node = new(std::nothrow) PackageFile; // file
node = new(std::nothrow) PackageFile(entry->Mode(), entry->Data());
} else if (S_ISLNK(entry->Mode())) { } else if (S_ISLNK(entry->Mode())) {
node = new(std::nothrow) PackageSymlink; // symlink
PackageSymlink* symlink = new(std::nothrow) PackageSymlink(
entry->Mode());
if (symlink == NULL)
RETURN_ERROR(B_NO_MEMORY);
error = symlink->SetSymlinkPath(entry->SymlinkPath());
if (error != B_OK) {
delete symlink;
return error;
}
node = symlink;
} else if (S_ISDIR(entry->Mode())) { } else if (S_ISDIR(entry->Mode())) {
node = new(std::nothrow) PackageDirectory; // directory
node = new(std::nothrow) PackageDirectory(entry->Mode());
} else } else
RETURN_ERROR(B_BAD_DATA); RETURN_ERROR(B_BAD_DATA);
@@ -148,12 +163,10 @@ struct Volume::PackageLoaderContentHandler : PackageContentHandler {
RETURN_ERROR(B_NO_MEMORY); RETURN_ERROR(B_NO_MEMORY);
ObjectDeleter<PackageNode> nodeDeleter(node); ObjectDeleter<PackageNode> nodeDeleter(node);
status_t error = node->Init(parentDir, entry->Name()); error = node->Init(parentDir, entry->Name());
if (error != B_OK) if (error != B_OK)
RETURN_ERROR(error); RETURN_ERROR(error);
node->SetMode(entry->Mode());
// add it to the parent directory // add it to the parent directory
if (parentDir != NULL) if (parentDir != NULL)
parentDir->AddChild(node); parentDir->AddChild(node);
@@ -579,10 +592,8 @@ Volume::_CreateNode(mode_t mode, Directory* parent, const char* name,
Node*& _node) Node*& _node)
{ {
Node* node; Node* node;
if (S_ISREG(mode)) if (S_ISREG(mode) || S_ISLNK(mode))
node = new(std::nothrow) File(fNextNodeID++); node = new(std::nothrow) LeafNode(fNextNodeID++);
else if (S_ISLNK(mode))
node = new(std::nothrow) Symlink(fNextNodeID++);
else if (S_ISDIR(mode)) else if (S_ISDIR(mode))
node = new(std::nothrow) Directory(fNextNodeID++); node = new(std::nothrow) Directory(fNextNodeID++);
else else
@@ -8,6 +8,7 @@
#include <dirent.h> #include <dirent.h>
#include <algorithm>
#include <new> #include <new>
#include <fs_info.h> #include <fs_info.h>
@@ -18,6 +19,7 @@
#include "DebugSupport.h" #include "DebugSupport.h"
#include "Directory.h" #include "Directory.h"
#include "LeafNode.h"
#include "Volume.h" #include "Volume.h"
@@ -200,9 +202,30 @@ packagefs_put_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter)
static status_t static status_t
packagefs_read_symlink(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer, packagefs_read_symlink(fs_volume* fsVolume, fs_vnode* fsNode, char* buffer,
size_t* bufferSize) size_t* _bufferSize)
{ {
return B_UNSUPPORTED; Volume* volume = (Volume*)fsVolume->private_volume;
Node* node = (Node*)fsNode->private_node;
FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
TOUCH(volume);
NodeReadLocker nodeLocker(node);
if (!S_ISLNK(node->Mode()))
return B_BAD_VALUE;
const char* linkPath = dynamic_cast<LeafNode*>(node)->SymlinkPath();
if (linkPath == NULL) {
*_bufferSize = 0;
return B_OK;
}
size_t toCopy = std::min(strlen(linkPath), *_bufferSize);
memcpy(buffer, linkPath, toCopy);
*_bufferSize = toCopy;
return B_OK;
} }
@@ -211,7 +234,6 @@ packagefs_access(fs_volume* fsVolume, fs_vnode* fsNode, int mode)
{ {
Volume* volume = (Volume*)fsVolume->private_volume; Volume* volume = (Volume*)fsVolume->private_volume;
Node* node = (Node*)fsNode->private_node; Node* node = (Node*)fsNode->private_node;
TOUCH(volume);
FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
TOUCH(volume); TOUCH(volume);
@@ -220,6 +242,8 @@ packagefs_access(fs_volume* fsVolume, fs_vnode* fsNode, int mode)
if (mode & W_OK) if (mode & W_OK)
return B_READ_ONLY_DEVICE; return B_READ_ONLY_DEVICE;
NodeReadLocker nodeLocker(node);
// get node permissions // get node permissions
int userPermissions = (node->Mode() & S_IRWXU) >> 6; int userPermissions = (node->Mode() & S_IRWXU) >> 6;
int groupPermissions = (node->Mode() & S_IRWXG) >> 3; int groupPermissions = (node->Mode() & S_IRWXG) >> 3;
@@ -259,6 +283,8 @@ packagefs_read_stat(fs_volume* fsVolume, fs_vnode* fsNode, struct stat* st)
FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID()); FUNCTION("volume: %p, node: %p (%lld)\n", volume, node, node->ID());
TOUCH(volume); TOUCH(volume);
NodeReadLocker nodeLocker(node);
// TODO: Fill in correctly! // TODO: Fill in correctly!
st->st_mode = node->Mode(); st->st_mode = node->Mode();
st->st_nlink = 1; st->st_nlink = 1;
@@ -418,6 +444,7 @@ packagefs_open_dir(fs_volume* fsVolume, fs_vnode* fsNode, void** _cookie)
Directory* dir = dynamic_cast<Directory*>(node); Directory* dir = dynamic_cast<Directory*>(node);
// create a cookie // create a cookie
NodeWriteLocker dirLocker(dir);
DirectoryCookie* cookie = new(std::nothrow) DirectoryCookie(dir); DirectoryCookie* cookie = new(std::nothrow) DirectoryCookie(dir);
if (cookie == NULL) if (cookie == NULL)
RETURN_ERROR(B_NO_MEMORY); RETURN_ERROR(B_NO_MEMORY);