WIP towards packagefs package links support
* Introduce Version class representing a version. * Introduce Dependency and Resolvable class and add lists of either to Package. * Parse package attributes and add dependencies and resolvables to Package. * Add a mount type to Volume and add a respective mount parameter "mount-type" (values "system", "common", "home", "custom"). Also implies the shine-through type, if that's not given. * Introduce class PackageFamily which groups equally named and versioned packages. * Add class PackageFSRoot. Each instance represents a possible file system root (separate roots for different chroot environments). Tracks Volumes belonging to the same root and their packages.
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Dependency.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
|
||||||
|
Dependency::Dependency(Package* package)
|
||||||
|
:
|
||||||
|
fPackage(package),
|
||||||
|
fResolvable(NULL),
|
||||||
|
fName(NULL),
|
||||||
|
fVersion(NULL),
|
||||||
|
fVersionOperator(B_PACKAGE_RESOLVABLE_OP_EQUAL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Dependency::~Dependency()
|
||||||
|
{
|
||||||
|
free(fName);
|
||||||
|
delete fVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Dependency::Init(const char* name)
|
||||||
|
{
|
||||||
|
fName = strdup(name);
|
||||||
|
if (fName == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Dependency::SetVersionRequirement(BPackageResolvableOperator op,
|
||||||
|
Version* version)
|
||||||
|
{
|
||||||
|
fVersionOperator = op;
|
||||||
|
fVersion = version;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DEPENDENCY_H
|
||||||
|
#define DEPENDENCY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/PackageResolvableOperator.h>
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Package;
|
||||||
|
class Resolvable;
|
||||||
|
class Version;
|
||||||
|
|
||||||
|
|
||||||
|
using BPackageKit::BPackageResolvableOperator;
|
||||||
|
|
||||||
|
|
||||||
|
class Dependency : public BReferenceable,
|
||||||
|
public DoublyLinkedListLinkImpl<Dependency> {
|
||||||
|
public:
|
||||||
|
Dependency(Package* package);
|
||||||
|
virtual ~Dependency();
|
||||||
|
|
||||||
|
status_t Init(const char* name);
|
||||||
|
void SetVersionRequirement(
|
||||||
|
BPackageResolvableOperator op,
|
||||||
|
Version* version);
|
||||||
|
// version is optional; object takes over
|
||||||
|
// ownership
|
||||||
|
|
||||||
|
void SetResolvable(::Resolvable* resolvable)
|
||||||
|
{ fResolvable = resolvable; }
|
||||||
|
::Resolvable* Resolvable() const
|
||||||
|
{ return fResolvable; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Package* fPackage;
|
||||||
|
::Resolvable* fResolvable;
|
||||||
|
char* fName;
|
||||||
|
Version* fVersion;
|
||||||
|
BPackageResolvableOperator fVersionOperator;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<Dependency> DependencyList;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DEPENDENCY_H
|
||||||
@@ -5,13 +5,11 @@ UseLibraryHeaders zlib ;
|
|||||||
UsePrivateKernelHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
DEFINES += B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT ;
|
|
||||||
# TODO: Remove when it is complete!
|
|
||||||
|
|
||||||
|
|
||||||
HAIKU_PACKAGE_FS_SOURCES =
|
HAIKU_PACKAGE_FS_SOURCES =
|
||||||
BlockBufferCacheKernel.cpp
|
BlockBufferCacheKernel.cpp
|
||||||
DebugSupport.cpp
|
DebugSupport.cpp
|
||||||
|
Dependency.cpp
|
||||||
Directory.cpp
|
Directory.cpp
|
||||||
GlobalFactory.cpp
|
GlobalFactory.cpp
|
||||||
kernel_interface.cpp
|
kernel_interface.cpp
|
||||||
@@ -20,11 +18,15 @@ HAIKU_PACKAGE_FS_SOURCES =
|
|||||||
Package.cpp
|
Package.cpp
|
||||||
PackageDirectory.cpp
|
PackageDirectory.cpp
|
||||||
PackageDomain.cpp
|
PackageDomain.cpp
|
||||||
|
PackageFamily.cpp
|
||||||
PackageFile.cpp
|
PackageFile.cpp
|
||||||
|
PackageFSRoot.cpp
|
||||||
PackageLeafNode.cpp
|
PackageLeafNode.cpp
|
||||||
PackageNode.cpp
|
PackageNode.cpp
|
||||||
PackageNodeAttribute.cpp
|
PackageNodeAttribute.cpp
|
||||||
PackageSymlink.cpp
|
PackageSymlink.cpp
|
||||||
|
Resolvable.cpp
|
||||||
|
Version.cpp
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -50,6 +52,11 @@ HAIKU_PACKAGE_FS_PACKAGE_READER_SOURCES =
|
|||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
local libSharedSources =
|
||||||
|
NaturalCompare.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ;
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src kits package hpkg ] ;
|
||||||
|
|
||||||
|
|
||||||
@@ -57,9 +64,14 @@ KernelAddon packagefs
|
|||||||
:
|
:
|
||||||
$(HAIKU_PACKAGE_FS_SOURCES)
|
$(HAIKU_PACKAGE_FS_SOURCES)
|
||||||
$(HAIKU_PACKAGE_FS_PACKAGE_READER_SOURCES)
|
$(HAIKU_PACKAGE_FS_PACKAGE_READER_SOURCES)
|
||||||
|
$(libSharedSources)
|
||||||
|
|
||||||
: $(HAIKU_STATIC_LIBSUPC++) libz.a
|
: $(HAIKU_STATIC_LIBSUPC++) libz.a
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
SEARCH on [ FGristFiles $(libSharedSources) ]
|
||||||
|
+= [ FDirName $(HAIKU_TOP) src kits shared ] ;
|
||||||
|
|
||||||
|
|
||||||
HaikuSubInclude userland ;
|
HaikuSubInclude userland ;
|
||||||
|
|||||||
@@ -16,12 +16,16 @@
|
|||||||
|
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
#include "PackageDomain.h"
|
#include "PackageDomain.h"
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
|
||||||
Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
|
Package::Package(PackageDomain* domain, dev_t deviceID, ino_t nodeID)
|
||||||
:
|
:
|
||||||
fDomain(domain),
|
fDomain(domain),
|
||||||
fFileName(NULL),
|
fFileName(NULL),
|
||||||
|
fName(NULL),
|
||||||
|
fVersion(NULL),
|
||||||
|
fFamily(NULL),
|
||||||
fFD(-1),
|
fFD(-1),
|
||||||
fOpenCount(0),
|
fOpenCount(0),
|
||||||
fNodeID(nodeID),
|
fNodeID(nodeID),
|
||||||
@@ -36,7 +40,15 @@ Package::~Package()
|
|||||||
while (PackageNode* node = fNodes.RemoveHead())
|
while (PackageNode* node = fNodes.RemoveHead())
|
||||||
node->ReleaseReference();
|
node->ReleaseReference();
|
||||||
|
|
||||||
|
while (Resolvable* resolvable = fResolvables.RemoveHead())
|
||||||
|
delete resolvable;
|
||||||
|
|
||||||
|
while (Dependency* dependency = fDependencies.RemoveHead())
|
||||||
|
delete dependency;
|
||||||
|
|
||||||
free(fFileName);
|
free(fFileName);
|
||||||
|
free(fName);
|
||||||
|
delete fVersion;
|
||||||
|
|
||||||
mutex_destroy(&fLock);
|
mutex_destroy(&fLock);
|
||||||
}
|
}
|
||||||
@@ -53,6 +65,30 @@ Package::Init(const char* fileName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Package::SetName(const char* name)
|
||||||
|
{
|
||||||
|
if (fName != NULL)
|
||||||
|
free(fName);
|
||||||
|
|
||||||
|
fName = strdup(name);
|
||||||
|
if (fName == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Package::SetVersion(::Version* version)
|
||||||
|
{
|
||||||
|
if (fVersion != NULL)
|
||||||
|
delete fVersion;
|
||||||
|
|
||||||
|
fVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Package::AddNode(PackageNode* node)
|
Package::AddNode(PackageNode* node)
|
||||||
{
|
{
|
||||||
@@ -61,6 +97,20 @@ Package::AddNode(PackageNode* node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Package::AddResolvable(Resolvable* resolvable)
|
||||||
|
{
|
||||||
|
fResolvables.Add(resolvable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Package::AddDependency(Dependency* dependency)
|
||||||
|
{
|
||||||
|
fDependencies.Add(dependency);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
Package::Open()
|
Package::Open()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,18 +8,24 @@
|
|||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/khash.h>
|
#include <util/khash.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
|
||||||
|
#include "Dependency.h"
|
||||||
#include "PackageNode.h"
|
#include "PackageNode.h"
|
||||||
|
#include "Resolvable.h"
|
||||||
|
|
||||||
|
|
||||||
class PackageDomain;
|
class PackageDomain;
|
||||||
|
class PackageFamily;
|
||||||
|
class Version;
|
||||||
|
|
||||||
|
|
||||||
class Package : public BReferenceable {
|
class Package : public BReferenceable,
|
||||||
|
public DoublyLinkedListLinkImpl<Package> {
|
||||||
public:
|
public:
|
||||||
Package(PackageDomain* domain, dev_t deviceID,
|
Package(PackageDomain* domain, dev_t deviceID,
|
||||||
ino_t nodeID);
|
ino_t nodeID);
|
||||||
@@ -30,10 +36,25 @@ public:
|
|||||||
PackageDomain* Domain() const { return fDomain; }
|
PackageDomain* Domain() const { return fDomain; }
|
||||||
const char* FileName() const { return fFileName; }
|
const char* FileName() const { return fFileName; }
|
||||||
|
|
||||||
|
status_t SetName(const char* name);
|
||||||
|
const char* Name() const { return fName; }
|
||||||
|
|
||||||
|
void SetVersion(::Version* version);
|
||||||
|
// takes over object ownership
|
||||||
|
::Version* Version() const
|
||||||
|
{ return fVersion; }
|
||||||
|
|
||||||
|
void SetFamily(PackageFamily* family)
|
||||||
|
{ fFamily = family; }
|
||||||
|
PackageFamily* Family() const
|
||||||
|
{ return fFamily; }
|
||||||
|
|
||||||
Package*& FileNameHashTableNext()
|
Package*& FileNameHashTableNext()
|
||||||
{ return fFileNameHashTableNext; }
|
{ return fFileNameHashTableNext; }
|
||||||
|
|
||||||
void AddNode(PackageNode* node);
|
void AddNode(PackageNode* node);
|
||||||
|
void AddResolvable(Resolvable* resolvable);
|
||||||
|
void AddDependency(Dependency* dependency);
|
||||||
|
|
||||||
int Open();
|
int Open();
|
||||||
void Close();
|
void Close();
|
||||||
@@ -44,12 +65,17 @@ private:
|
|||||||
mutex fLock;
|
mutex fLock;
|
||||||
PackageDomain* fDomain;
|
PackageDomain* fDomain;
|
||||||
char* fFileName;
|
char* fFileName;
|
||||||
|
char* fName;
|
||||||
|
::Version* fVersion;
|
||||||
|
PackageFamily* fFamily;
|
||||||
int fFD;
|
int fFD;
|
||||||
uint32 fOpenCount;
|
uint32 fOpenCount;
|
||||||
Package* fFileNameHashTableNext;
|
Package* fFileNameHashTableNext;
|
||||||
ino_t fNodeID;
|
ino_t fNodeID;
|
||||||
dev_t fDeviceID;
|
dev_t fDeviceID;
|
||||||
PackageNodeList fNodes;
|
PackageNodeList fNodes;
|
||||||
|
ResolvableList fResolvables;
|
||||||
|
DependencyList fDependencies;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -103,6 +129,7 @@ struct PackageFileNameHashDefinition {
|
|||||||
|
|
||||||
|
|
||||||
typedef BOpenHashTable<PackageFileNameHashDefinition> PackageFileNameHashTable;
|
typedef BOpenHashTable<PackageFileNameHashDefinition> PackageFileNameHashTable;
|
||||||
|
typedef DoublyLinkedList<Package> PackageList;
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_H
|
#endif // PACKAGE_H
|
||||||
|
|||||||
@@ -21,8 +21,9 @@
|
|||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
|
|
||||||
|
|
||||||
PackageDomain::PackageDomain()
|
PackageDomain::PackageDomain(::Volume* volume)
|
||||||
:
|
:
|
||||||
|
fVolume(volume),
|
||||||
fPath(NULL),
|
fPath(NULL),
|
||||||
fDirFD(-1),
|
fDirFD(-1),
|
||||||
fListener(NULL)
|
fListener(NULL)
|
||||||
|
|||||||
@@ -14,14 +14,16 @@
|
|||||||
|
|
||||||
|
|
||||||
class NotificationListener;
|
class NotificationListener;
|
||||||
|
class Volume;
|
||||||
|
|
||||||
|
|
||||||
class PackageDomain : public BReferenceable,
|
class PackageDomain : public BReferenceable,
|
||||||
public DoublyLinkedListLinkImpl<PackageDomain> {
|
public DoublyLinkedListLinkImpl<PackageDomain> {
|
||||||
public:
|
public:
|
||||||
PackageDomain();
|
PackageDomain(::Volume* volume);
|
||||||
~PackageDomain();
|
~PackageDomain();
|
||||||
|
|
||||||
|
::Volume* Volume() const { return fVolume; }
|
||||||
const char* Path() const { return fPath; }
|
const char* Path() const { return fPath; }
|
||||||
int DirectoryFD() { return fDirFD; }
|
int DirectoryFD() { return fDirFD; }
|
||||||
dev_t DeviceID() { return fDeviceID; }
|
dev_t DeviceID() { return fDeviceID; }
|
||||||
@@ -40,6 +42,7 @@ public:
|
|||||||
{ return fPackages; }
|
{ return fPackages; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
::Volume* fVolume;
|
||||||
char* fPath;
|
char* fPath;
|
||||||
int fDirFD;
|
int fDirFD;
|
||||||
dev_t fDeviceID;
|
dev_t fDeviceID;
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "PackageFSRoot.h"
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include <vfs.h>
|
||||||
|
|
||||||
|
#include "DebugSupport.h"
|
||||||
|
|
||||||
|
|
||||||
|
mutex PackageFSRoot::sRootListLock = MUTEX_INITIALIZER("packagefs root list");
|
||||||
|
PackageFSRoot::RootList PackageFSRoot::sRootList;
|
||||||
|
|
||||||
|
|
||||||
|
PackageFSRoot::PackageFSRoot(dev_t deviceID, ino_t nodeID)
|
||||||
|
:
|
||||||
|
fDeviceID(deviceID),
|
||||||
|
fNodeID(nodeID),
|
||||||
|
fSystemVolume(NULL)
|
||||||
|
{
|
||||||
|
rw_lock_init(&fLock, "packagefs root");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFSRoot::~PackageFSRoot()
|
||||||
|
{
|
||||||
|
rw_lock_destroy(&fLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
PackageFSRoot::GlobalInit()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
PackageFSRoot::GlobalUninit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageFSRoot::Init()
|
||||||
|
{
|
||||||
|
status_t error = fPackageFamilies.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
PackageFSRoot::RegisterVolume(Volume* volume)
|
||||||
|
{
|
||||||
|
// Unless the volume is custom mounted, we stat the supposed root directory.
|
||||||
|
// Get the volume mount point relative path to the root directory depending
|
||||||
|
// on the mount type.
|
||||||
|
const char* relativeRootPath = NULL;
|
||||||
|
|
||||||
|
switch (volume->MountType()) {
|
||||||
|
case MOUNT_TYPE_SYSTEM:
|
||||||
|
case MOUNT_TYPE_COMMON:
|
||||||
|
relativeRootPath = "..";
|
||||||
|
break;
|
||||||
|
case MOUNT_TYPE_HOME:
|
||||||
|
relativeRootPath = "../..";
|
||||||
|
break;
|
||||||
|
case MOUNT_TYPE_CUSTOM:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relativeRootPath != NULL) {
|
||||||
|
struct vnode* vnode;
|
||||||
|
status_t error = vfs_entry_ref_to_vnode(volume->MountPointDeviceID(),
|
||||||
|
volume->MountPointNodeID(), relativeRootPath, &vnode);
|
||||||
|
if (error != B_OK) {
|
||||||
|
dprintf("packagefs: Failed to get root directory \"%s\": %s\n",
|
||||||
|
relativeRootPath, strerror(error));
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
CObjectDeleter<struct vnode> vnodePutter(vnode, &vfs_put_vnode);
|
||||||
|
|
||||||
|
// stat it
|
||||||
|
struct stat st;
|
||||||
|
error = vfs_stat_vnode(vnode, &st);
|
||||||
|
if (error != B_OK) {
|
||||||
|
dprintf("packagefs: Failed to stat root directory \"%s\": %s\n",
|
||||||
|
relativeRootPath, strerror(error));
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get/create the root
|
||||||
|
PackageFSRoot* root;
|
||||||
|
error = PackageFSRoot::_GetOrCreateRoot(st.st_dev, st.st_ino, root);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// add the volume
|
||||||
|
error = root->_AddVolume(volume);
|
||||||
|
if (error != B_OK) {
|
||||||
|
_PutRoot(root);
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom mount -- always create a new root
|
||||||
|
PackageFSRoot* root = new(std::nothrow) PackageFSRoot(-1, 0);
|
||||||
|
if (root == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<PackageFSRoot> rootDeleter(root);
|
||||||
|
|
||||||
|
status_t error = root->Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// add the volume
|
||||||
|
error = root->_AddVolume(volume);
|
||||||
|
if (error != B_OK) {
|
||||||
|
_PutRoot(root);
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't add the root to the list.
|
||||||
|
rootDeleter.Detach();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFSRoot::UnregisterVolume(Volume* volume)
|
||||||
|
{
|
||||||
|
_RemoveVolume(volume);
|
||||||
|
_PutRoot(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageFSRoot::AddPackage(Package* package)
|
||||||
|
{
|
||||||
|
// Create a package family -- there might already be one, but since that's
|
||||||
|
// unlikely, we don't bother to check and recheck later.
|
||||||
|
PackageFamily* packageFamily = new(std::nothrow) PackageFamily;
|
||||||
|
if (packageFamily == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<PackageFamily> packageFamilyDeleter(packageFamily);
|
||||||
|
|
||||||
|
status_t error = packageFamily->Init(package);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// add the family
|
||||||
|
PackageFSRootWriteLocker writeLocker(this);
|
||||||
|
if (PackageFamily* otherPackageFamily
|
||||||
|
= fPackageFamilies.Lookup(packageFamily->Name())) {
|
||||||
|
packageFamily->RemovePackage(package);
|
||||||
|
packageFamily = otherPackageFamily;
|
||||||
|
packageFamily->AddPackage(package);
|
||||||
|
} else
|
||||||
|
fPackageFamilies.Insert(packageFamilyDeleter.Detach());
|
||||||
|
|
||||||
|
// TODO:...
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFSRoot::RemovePackage(Package* package)
|
||||||
|
{
|
||||||
|
PackageFSRootWriteLocker writeLocker(this);
|
||||||
|
|
||||||
|
PackageFamily* packageFamily = package->Family();
|
||||||
|
if (packageFamily == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
packageFamily->RemovePackage(package);
|
||||||
|
|
||||||
|
if (packageFamily->IsEmpty()) {
|
||||||
|
fPackageFamilies.Remove(packageFamily);
|
||||||
|
delete packageFamily;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:...
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Volume*
|
||||||
|
PackageFSRoot::SystemVolume() const
|
||||||
|
{
|
||||||
|
PackageFSRootReadLocker readLocker(this);
|
||||||
|
return fSystemVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageFSRoot::_AddVolume(Volume* volume)
|
||||||
|
{
|
||||||
|
PackageFSRootWriteLocker writeLocker(this);
|
||||||
|
|
||||||
|
volume->SetPackageFSRoot(this);
|
||||||
|
|
||||||
|
fVolumes.Add(volume);
|
||||||
|
// TODO: Correct order?
|
||||||
|
|
||||||
|
if (fSystemVolume == NULL && volume->MountType() == MOUNT_TYPE_SYSTEM)
|
||||||
|
fSystemVolume = volume;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFSRoot::_RemoveVolume(Volume* volume)
|
||||||
|
{
|
||||||
|
PackageFSRootWriteLocker writeLocker(this);
|
||||||
|
|
||||||
|
if (volume == fSystemVolume)
|
||||||
|
fSystemVolume = NULL;
|
||||||
|
|
||||||
|
fVolumes.Remove(volume);
|
||||||
|
|
||||||
|
volume->SetPackageFSRoot(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
PackageFSRoot::_GetOrCreateRoot(dev_t deviceID, ino_t nodeID,
|
||||||
|
PackageFSRoot*& _root)
|
||||||
|
{
|
||||||
|
// first check the list, if the root already exists
|
||||||
|
MutexLocker rootListLocker(sRootListLock);
|
||||||
|
|
||||||
|
if (PackageFSRoot* root = _FindRootLocked(deviceID, nodeID)) {
|
||||||
|
root->AcquireReference();
|
||||||
|
_root = root;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
rootListLocker.Unlock();
|
||||||
|
|
||||||
|
// create a new root
|
||||||
|
PackageFSRoot* root = new(std::nothrow) PackageFSRoot(deviceID, nodeID);
|
||||||
|
if (root == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<PackageFSRoot> rootDeleter(root);
|
||||||
|
|
||||||
|
status_t error = root->Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// add the root -- first recheck whether someone else added the root in the
|
||||||
|
// meantime
|
||||||
|
rootListLocker.Lock();
|
||||||
|
|
||||||
|
if (PackageFSRoot* otherRoot = _FindRootLocked(deviceID, nodeID)) {
|
||||||
|
// indeed, someone was faster
|
||||||
|
otherRoot->AcquireReference();
|
||||||
|
_root = otherRoot;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
sRootList.Add(root);
|
||||||
|
|
||||||
|
_root = rootDeleter.Detach();
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ PackageFSRoot*
|
||||||
|
PackageFSRoot::_FindRootLocked(dev_t deviceID, ino_t nodeID)
|
||||||
|
{
|
||||||
|
for (RootList::Iterator it = sRootList.GetIterator();
|
||||||
|
PackageFSRoot* root = it.Next();) {
|
||||||
|
if (root->DeviceID() == deviceID && root->NodeID() == nodeID)
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ void
|
||||||
|
PackageFSRoot::_PutRoot(PackageFSRoot* root)
|
||||||
|
{
|
||||||
|
// Only non-custom roots are in the global list.
|
||||||
|
if (!root->IsCustom()) {
|
||||||
|
MutexLocker rootListLocker(sRootListLock);
|
||||||
|
|
||||||
|
// When releasing the last reference, remove the root from the list.
|
||||||
|
if (root->CountReferences() == 1)
|
||||||
|
sRootList.Remove(root);
|
||||||
|
|
||||||
|
rootListLocker.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
root->ReleaseReference();
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef PACKAGE_FS_ROOT_H
|
||||||
|
#define PACKAGE_FS_ROOT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include <util/AutoLock.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
|
#include "PackageFamily.h"
|
||||||
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PackageFSRoot : private BReferenceable,
|
||||||
|
public DoublyLinkedListLinkImpl<PackageFSRoot> {
|
||||||
|
public:
|
||||||
|
// constructor and destructor are conceptually private
|
||||||
|
PackageFSRoot(dev_t deviceID, ino_t nodeID);
|
||||||
|
virtual ~PackageFSRoot();
|
||||||
|
|
||||||
|
static status_t GlobalInit();
|
||||||
|
static void GlobalUninit();
|
||||||
|
|
||||||
|
inline bool ReadLock() const;
|
||||||
|
inline void ReadUnlock() const;
|
||||||
|
inline bool WriteLock();
|
||||||
|
inline void WriteUnlock();
|
||||||
|
|
||||||
|
status_t Init();
|
||||||
|
|
||||||
|
static status_t RegisterVolume(Volume* volume);
|
||||||
|
void UnregisterVolume(Volume* volume);
|
||||||
|
|
||||||
|
status_t AddPackage(Package* package);
|
||||||
|
void RemovePackage(Package* package);
|
||||||
|
|
||||||
|
dev_t DeviceID() const { return fDeviceID; }
|
||||||
|
ino_t NodeID() const { return fNodeID; }
|
||||||
|
bool IsCustom() const { return fDeviceID < 0; }
|
||||||
|
|
||||||
|
Volume* SystemVolume() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef DoublyLinkedList<PackageFSRoot> RootList;
|
||||||
|
typedef DoublyLinkedList<Volume> VolumeList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _AddVolume(Volume* volume);
|
||||||
|
void _RemoveVolume(Volume* volume);
|
||||||
|
|
||||||
|
static status_t _GetOrCreateRoot(dev_t deviceID, ino_t nodeID,
|
||||||
|
PackageFSRoot*& _root);
|
||||||
|
static PackageFSRoot* _FindRootLocked(dev_t deviceID, ino_t nodeID);
|
||||||
|
static void _PutRoot(PackageFSRoot* root);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static mutex sRootListLock;
|
||||||
|
static RootList sRootList;
|
||||||
|
|
||||||
|
mutable rw_lock fLock;
|
||||||
|
dev_t fDeviceID;
|
||||||
|
ino_t fNodeID;
|
||||||
|
VolumeList fVolumes;
|
||||||
|
Volume* fSystemVolume;
|
||||||
|
PackageFamilyHashTable fPackageFamilies;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFSRoot::ReadLock() const
|
||||||
|
{
|
||||||
|
return rw_lock_read_lock(&fLock) == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFSRoot::ReadUnlock() const
|
||||||
|
{
|
||||||
|
rw_lock_read_unlock(&fLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PackageFSRoot::WriteLock()
|
||||||
|
{
|
||||||
|
return rw_lock_write_lock(&fLock) == B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFSRoot::WriteUnlock()
|
||||||
|
{
|
||||||
|
rw_lock_write_unlock(&fLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef AutoLocker<const PackageFSRoot,
|
||||||
|
AutoLockerReadLocking<const PackageFSRoot> > PackageFSRootReadLocker;
|
||||||
|
typedef AutoLocker<PackageFSRoot, AutoLockerWriteLocking<PackageFSRoot> >
|
||||||
|
PackageFSRootWriteLocker;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PACKAGE_FS_ROOT_H
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "PackageFamily.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "DebugSupport.h"
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
|
||||||
|
PackageFamily::PackageFamily()
|
||||||
|
:
|
||||||
|
fName(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PackageFamily::~PackageFamily()
|
||||||
|
{
|
||||||
|
while (Package* package = fPackages.RemoveHead())
|
||||||
|
package->SetFamily(NULL);
|
||||||
|
|
||||||
|
free(fName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageFamily::Init(Package* package)
|
||||||
|
{
|
||||||
|
// compute the allocation size needed for the versioned name
|
||||||
|
size_t nameLength = strlen(package->Name());
|
||||||
|
size_t size = nameLength + 1;
|
||||||
|
|
||||||
|
Version* version = package->Version();
|
||||||
|
if (version != NULL) {
|
||||||
|
size += 1 + version->ToString(NULL, 0);
|
||||||
|
// + 1 for the '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate the name and compose it
|
||||||
|
fName = (char*)malloc(size);
|
||||||
|
if (fName == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
memcpy(fName, package->Name(), nameLength + 1);
|
||||||
|
if (version != NULL) {
|
||||||
|
fName[nameLength] = '-';
|
||||||
|
version->ToString(fName + nameLength + 1, size - nameLength - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the package
|
||||||
|
AddPackage(package);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFamily::AddPackage(Package* package)
|
||||||
|
{
|
||||||
|
fPackages.Add(package);
|
||||||
|
package->SetFamily(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageFamily::RemovePackage(Package* package)
|
||||||
|
{
|
||||||
|
ASSERT(package->Family() == this);
|
||||||
|
|
||||||
|
package->SetFamily(NULL);
|
||||||
|
fPackages.Remove(package);
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef PACKAGE_FAMILY_H
|
||||||
|
#define PACKAGE_FAMILY_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include "Package.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*! A set of equally named and versioned packages.
|
||||||
|
This should only happen when the same package is installed in multiple
|
||||||
|
domains (e.g. common and home).
|
||||||
|
*/
|
||||||
|
class PackageFamily {
|
||||||
|
public:
|
||||||
|
PackageFamily();
|
||||||
|
~PackageFamily();
|
||||||
|
|
||||||
|
status_t Init(Package* package);
|
||||||
|
|
||||||
|
const char* Name() const { return fName; }
|
||||||
|
|
||||||
|
void AddPackage(Package* package);
|
||||||
|
void RemovePackage(Package* package);
|
||||||
|
|
||||||
|
bool IsEmpty() const
|
||||||
|
{ return fPackages.IsEmpty(); }
|
||||||
|
|
||||||
|
PackageFamily*& HashNext() { return fHashNext; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageFamily* fHashNext;
|
||||||
|
char* fName;
|
||||||
|
PackageList fPackages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PackageFamilyHashDefinition {
|
||||||
|
typedef const char* KeyType;
|
||||||
|
typedef PackageFamily ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const char* key) const
|
||||||
|
{
|
||||||
|
return hash_hash_string(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(const PackageFamily* value) const
|
||||||
|
{
|
||||||
|
return HashKey(value->Name());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(const char* key, const PackageFamily* value) const
|
||||||
|
{
|
||||||
|
return strcmp(value->Name(), key) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageFamily*& GetLink(PackageFamily* value) const
|
||||||
|
{
|
||||||
|
return value->HashNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BOpenHashTable<PackageFamilyHashDefinition> PackageFamilyHashTable;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PACKAGE_FAMILY_H
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Resolvable.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
|
||||||
|
Resolvable::Resolvable(Package* package)
|
||||||
|
:
|
||||||
|
fPackage(package),
|
||||||
|
fName(NULL),
|
||||||
|
fVersion(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Resolvable::~Resolvable()
|
||||||
|
{
|
||||||
|
free(fName);
|
||||||
|
delete fVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Resolvable::Init(const char* name, Version* version)
|
||||||
|
{
|
||||||
|
fVersion = version;
|
||||||
|
|
||||||
|
fName = strdup(name);
|
||||||
|
if (fName == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef RESOLVABLE_H
|
||||||
|
#define RESOLVABLE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Package;
|
||||||
|
class Version;
|
||||||
|
|
||||||
|
|
||||||
|
class Resolvable : public BReferenceable,
|
||||||
|
public DoublyLinkedListLinkImpl<Resolvable> {
|
||||||
|
public:
|
||||||
|
Resolvable(Package* package);
|
||||||
|
virtual ~Resolvable();
|
||||||
|
|
||||||
|
status_t Init(const char* name, Version* version);
|
||||||
|
// version is optional; object takes over
|
||||||
|
// ownership (even in case of error)
|
||||||
|
|
||||||
|
private:
|
||||||
|
Package* fPackage;
|
||||||
|
char* fName;
|
||||||
|
Version* fVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<Resolvable> ResolvableList;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // RESOLVABLE_H
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <NaturalCompare.h>
|
||||||
|
|
||||||
|
#include "DebugSupport.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char* const kVersionPartPlaceholder = "_";
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_version_part(const char* a, const char* b)
|
||||||
|
{
|
||||||
|
if (a == NULL)
|
||||||
|
return b != NULL ? -1 : 0;
|
||||||
|
if (b == NULL)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return BPrivate::NaturalCompare(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Version::Version()
|
||||||
|
:
|
||||||
|
fMajor(NULL),
|
||||||
|
fMinor(NULL),
|
||||||
|
fMicro(NULL),
|
||||||
|
fRelease(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Version::~Version()
|
||||||
|
{
|
||||||
|
free(fMajor);
|
||||||
|
free(fMinor);
|
||||||
|
free(fMicro);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Version::Init(const char* major, const char* minor, const char* micro,
|
||||||
|
uint8 release)
|
||||||
|
{
|
||||||
|
if (major != NULL) {
|
||||||
|
fMajor = strdup(major);
|
||||||
|
if (fMajor == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minor != NULL) {
|
||||||
|
fMinor = strdup(major);
|
||||||
|
if (fMinor == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (micro != NULL) {
|
||||||
|
fMicro = strdup(micro);
|
||||||
|
if (fMicro == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
fRelease = release;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
Version::Create(const char* major, const char* minor, const char* micro,
|
||||||
|
uint8 release, Version*& _version)
|
||||||
|
{
|
||||||
|
Version* version = new(std::nothrow) Version;
|
||||||
|
if (version == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
status_t error = version->Init(major, minor, micro, release);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete version;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
_version = version;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
Version::Compare(const Version& other) const
|
||||||
|
{
|
||||||
|
int cmp = compare_version_part(fMajor, other.fMajor);
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
cmp = compare_version_part(fMinor, other.fMinor);
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
cmp = compare_version_part(fMicro, other.fMicro);
|
||||||
|
if (cmp != 0)
|
||||||
|
return cmp;
|
||||||
|
|
||||||
|
return (int)fRelease - other.fRelease;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Version::Compare(BPackageResolvableOperator op,
|
||||||
|
const Version& other) const
|
||||||
|
{
|
||||||
|
int cmp = Compare(other);
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case B_PACKAGE_RESOLVABLE_OP_LESS:
|
||||||
|
return cmp < 0;
|
||||||
|
case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL:
|
||||||
|
return cmp <= 0;
|
||||||
|
case B_PACKAGE_RESOLVABLE_OP_EQUAL:
|
||||||
|
return cmp == 0;
|
||||||
|
case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL:
|
||||||
|
return cmp != 0;
|
||||||
|
case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL:
|
||||||
|
return cmp >= 0;
|
||||||
|
case B_PACKAGE_RESOLVABLE_OP_GREATER:
|
||||||
|
return cmp > 0;
|
||||||
|
default:
|
||||||
|
ERROR("packagefs: Version::Compare(): Invalid operator %d\n", op);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t
|
||||||
|
Version::ToString(char* buffer, size_t bufferSize) const
|
||||||
|
{
|
||||||
|
// We need to normalize the version string somewhat. If a subpart is given,
|
||||||
|
// make sure that also the superparts are defined, using a placeholder. This
|
||||||
|
// avoids clashes, e.g. if one version defines only major and one only
|
||||||
|
// micro.
|
||||||
|
const char* major = fMajor;
|
||||||
|
const char* minor = fMinor;
|
||||||
|
const char* micro = fMicro;
|
||||||
|
|
||||||
|
if (micro != NULL && minor == NULL)
|
||||||
|
minor = kVersionPartPlaceholder;
|
||||||
|
if (minor != NULL && major == NULL)
|
||||||
|
major = kVersionPartPlaceholder;
|
||||||
|
|
||||||
|
if (micro != NULL) {
|
||||||
|
return snprintf(buffer, bufferSize, "%s.%s.%s-%u", major, minor, micro,
|
||||||
|
fRelease);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minor != NULL)
|
||||||
|
return snprintf(buffer, bufferSize, "%s.%s-%u", major, minor, fRelease);
|
||||||
|
|
||||||
|
if (major != NULL)
|
||||||
|
return snprintf(buffer, bufferSize, "%s-%u", major, fRelease);
|
||||||
|
|
||||||
|
return snprintf(buffer, bufferSize, "%u", fRelease);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef VERSION_H
|
||||||
|
#define VERSION_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <package/PackageResolvableOperator.h>
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPackageKit;
|
||||||
|
|
||||||
|
|
||||||
|
class Version {
|
||||||
|
public:
|
||||||
|
Version();
|
||||||
|
~Version();
|
||||||
|
|
||||||
|
status_t Init(const char* major, const char* minor,
|
||||||
|
const char* micro, uint8 release);
|
||||||
|
|
||||||
|
static status_t Create(const char* major, const char* minor,
|
||||||
|
const char* micro, uint8 release,
|
||||||
|
Version*& _version);
|
||||||
|
|
||||||
|
int Compare(const Version& other) const;
|
||||||
|
bool Compare(BPackageResolvableOperator op,
|
||||||
|
const Version& other) const;
|
||||||
|
|
||||||
|
size_t ToString(char* buffer, size_t bufferSize) const;
|
||||||
|
// returns how big the buffer should have
|
||||||
|
// been (excluding the terminating null)
|
||||||
|
|
||||||
|
private:
|
||||||
|
char* fMajor;
|
||||||
|
char* fMinor;
|
||||||
|
char* fMicro;
|
||||||
|
uint8 fRelease;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // VERSION_H
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
* Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <driver_settings.h>
|
#include <driver_settings.h>
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
|
#include <package/PackageInfoAttributes.h>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
@@ -35,9 +36,13 @@
|
|||||||
#include "kernel_interface.h"
|
#include "kernel_interface.h"
|
||||||
#include "PackageDirectory.h"
|
#include "PackageDirectory.h"
|
||||||
#include "PackageFile.h"
|
#include "PackageFile.h"
|
||||||
|
#include "PackageFSRoot.h"
|
||||||
#include "PackageSymlink.h"
|
#include "PackageSymlink.h"
|
||||||
|
#include "Resolvable.h"
|
||||||
|
#include "Version.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace BPackageKit;
|
||||||
using namespace BPackageKit::BHPKG;
|
using namespace BPackageKit::BHPKG;
|
||||||
using BPackageKit::BHPKG::BPrivate::PackageReaderImpl;
|
using BPackageKit::BHPKG::BPrivate::PackageReaderImpl;
|
||||||
|
|
||||||
@@ -271,6 +276,99 @@ struct Volume::PackageLoaderContentHandler : BPackageContentHandler {
|
|||||||
virtual status_t HandlePackageAttribute(
|
virtual status_t HandlePackageAttribute(
|
||||||
const BPackageInfoAttributeValue& value)
|
const BPackageInfoAttributeValue& value)
|
||||||
{
|
{
|
||||||
|
switch (value.attributeID) {
|
||||||
|
// union {
|
||||||
|
// uint64 unsignedInt;
|
||||||
|
// const char* string;
|
||||||
|
// BPackageVersionData version;
|
||||||
|
// BPackageResolvableData resolvable;
|
||||||
|
// BPackageResolvableExpressionData resolvableExpression;
|
||||||
|
// };
|
||||||
|
case B_PACKAGE_INFO_NAME:
|
||||||
|
return fPackage->SetName(value.string);
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_VERSION:
|
||||||
|
{
|
||||||
|
Version* version;
|
||||||
|
status_t error = Version::Create(value.version.major,
|
||||||
|
value.version.minor, value.version.micro,
|
||||||
|
value.version.release, version);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
fPackage->SetVersion(version);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_PROVIDES:
|
||||||
|
{
|
||||||
|
// create a version object, if a version is specified
|
||||||
|
Version* version = NULL;
|
||||||
|
if (value.resolvable.haveVersion) {
|
||||||
|
const BPackageVersionData& versionInfo
|
||||||
|
= value.resolvable.version;
|
||||||
|
status_t error = Version::Create(versionInfo.major,
|
||||||
|
versionInfo.minor, versionInfo.micro,
|
||||||
|
versionInfo.release, version);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
ObjectDeleter<Version> versionDeleter(version);
|
||||||
|
|
||||||
|
// create the resolvable
|
||||||
|
Resolvable* resolvable = new(std::nothrow) Resolvable(fPackage);
|
||||||
|
if (resolvable == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
ObjectDeleter<Resolvable> resolvableDeleter(resolvable);
|
||||||
|
|
||||||
|
status_t error = resolvable->Init(value.resolvable.name,
|
||||||
|
versionDeleter.Detach());
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
fPackage->AddResolvable(resolvableDeleter.Detach());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_PACKAGE_INFO_REQUIRES:
|
||||||
|
{
|
||||||
|
// create the dependency
|
||||||
|
Dependency* dependency = new(std::nothrow) Dependency(fPackage);
|
||||||
|
if (dependency == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
ObjectDeleter<Dependency> dependencyDeleter(dependency);
|
||||||
|
|
||||||
|
status_t error = dependency->Init(
|
||||||
|
value.resolvableExpression.name);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// create a version object, if a version is specified
|
||||||
|
Version* version = NULL;
|
||||||
|
if (value.resolvableExpression.haveOpAndVersion) {
|
||||||
|
const BPackageVersionData& versionInfo
|
||||||
|
= value.resolvableExpression.version;
|
||||||
|
status_t error = Version::Create(versionInfo.major,
|
||||||
|
versionInfo.minor, versionInfo.micro,
|
||||||
|
versionInfo.release, version);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
dependency->SetVersionRequirement(
|
||||||
|
value.resolvableExpression.op, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
fPackage->AddDependency(dependencyDeleter.Detach());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO!
|
// TODO!
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -323,6 +421,7 @@ Volume::Volume(fs_volume* fsVolume)
|
|||||||
:
|
:
|
||||||
fFSVolume(fsVolume),
|
fFSVolume(fsVolume),
|
||||||
fRootDirectory(NULL),
|
fRootDirectory(NULL),
|
||||||
|
fPackageFSRoot(NULL),
|
||||||
fPackageLoader(-1),
|
fPackageLoader(-1),
|
||||||
fNextNodeID(kRootDirectoryID + 1),
|
fNextNodeID(kRootDirectoryID + 1),
|
||||||
fTerminating(false)
|
fTerminating(false)
|
||||||
@@ -348,6 +447,9 @@ Volume::~Volume()
|
|||||||
node = next;
|
node = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fPackageFSRoot != NULL)
|
||||||
|
fPackageFSRoot->UnregisterVolume(this);
|
||||||
|
|
||||||
if (fRootDirectory != NULL)
|
if (fRootDirectory != NULL)
|
||||||
fRootDirectory->ReleaseReference();
|
fRootDirectory->ReleaseReference();
|
||||||
|
|
||||||
@@ -366,6 +468,7 @@ Volume::Mount(const char* parameterString)
|
|||||||
|
|
||||||
const char* packages = NULL;
|
const char* packages = NULL;
|
||||||
const char* volumeName = NULL;
|
const char* volumeName = NULL;
|
||||||
|
const char* mountType = NULL;
|
||||||
const char* shineThrough = NULL;
|
const char* shineThrough = NULL;
|
||||||
|
|
||||||
void* parameterHandle = parse_driver_settings_string(parameterString);
|
void* parameterHandle = parse_driver_settings_string(parameterString);
|
||||||
@@ -374,6 +477,7 @@ Volume::Mount(const char* parameterString)
|
|||||||
NULL);
|
NULL);
|
||||||
volumeName = get_driver_parameter(parameterHandle, "volume-name", NULL,
|
volumeName = get_driver_parameter(parameterHandle, "volume-name", NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
mountType = get_driver_parameter(parameterHandle, "type", NULL, NULL);
|
||||||
shineThrough = get_driver_parameter(parameterHandle, "shine-through",
|
shineThrough = get_driver_parameter(parameterHandle, "shine-through",
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
}
|
}
|
||||||
@@ -386,6 +490,12 @@ Volume::Mount(const char* parameterString)
|
|||||||
RETURN_ERROR(B_BAD_VALUE);
|
RETURN_ERROR(B_BAD_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = _InitMountType(mountType);
|
||||||
|
if (error != B_OK) {
|
||||||
|
ERROR("invalid mount type: \"%s\"\n", mountType);
|
||||||
|
RETURN_ERROR(B_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(packages, &st) < 0)
|
if (stat(packages, &st) < 0)
|
||||||
RETURN_ERROR(B_ERROR);
|
RETURN_ERROR(B_ERROR);
|
||||||
@@ -398,6 +508,23 @@ Volume::Mount(const char* parameterString)
|
|||||||
fRootDirectory->Init(NULL, volumeName != NULL ? volumeName : "Package FS");
|
fRootDirectory->Init(NULL, volumeName != NULL ? volumeName : "Package FS");
|
||||||
fNodes.Insert(fRootDirectory);
|
fNodes.Insert(fRootDirectory);
|
||||||
|
|
||||||
|
// get our mount point
|
||||||
|
error = vfs_get_mount_point(fFSVolume->id, &fMountPoint.deviceID,
|
||||||
|
&fMountPoint.nodeID);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// register with packagefs root
|
||||||
|
error = ::PackageFSRoot::RegisterVolume(this);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
if (this == fPackageFSRoot->SystemVolume()) {
|
||||||
|
error = _AddPackageLinksDirectory();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
// create default package domain
|
// create default package domain
|
||||||
error = _AddInitialPackageDomain(packages);
|
error = _AddInitialPackageDomain(packages);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
@@ -409,6 +536,11 @@ Volume::Mount(const char* parameterString)
|
|||||||
if (fPackageLoader < 0)
|
if (fPackageLoader < 0)
|
||||||
RETURN_ERROR(fPackageLoader);
|
RETURN_ERROR(fPackageLoader);
|
||||||
|
|
||||||
|
// establish shine-through directories
|
||||||
|
error = _CreateShineThroughDirectories(shineThrough);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
// publish the root node
|
// publish the root node
|
||||||
fRootDirectory->AcquireReference();
|
fRootDirectory->AcquireReference();
|
||||||
error = PublishVNode(fRootDirectory);
|
error = PublishVNode(fRootDirectory);
|
||||||
@@ -417,11 +549,6 @@ Volume::Mount(const char* parameterString)
|
|||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// establish shine-through directories
|
|
||||||
error = _CreateShineThroughDirectories(shineThrough);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
|
|
||||||
// run the package loader
|
// run the package loader
|
||||||
resume_thread(fPackageLoader);
|
resume_thread(fPackageLoader);
|
||||||
|
|
||||||
@@ -468,7 +595,7 @@ Volume::PublishVNode(Node* node)
|
|||||||
status_t
|
status_t
|
||||||
Volume::AddPackageDomain(const char* path)
|
Volume::AddPackageDomain(const char* path)
|
||||||
{
|
{
|
||||||
PackageDomain* packageDomain = new(std::nothrow) PackageDomain;
|
PackageDomain* packageDomain = new(std::nothrow) PackageDomain(this);
|
||||||
if (packageDomain == NULL)
|
if (packageDomain == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
BReference<PackageDomain> packageDomainReference(packageDomain, true);
|
BReference<PackageDomain> packageDomainReference(packageDomain, true);
|
||||||
@@ -552,7 +679,7 @@ Volume::_PushJob(Job* job)
|
|||||||
status_t
|
status_t
|
||||||
Volume::_AddInitialPackageDomain(const char* path)
|
Volume::_AddInitialPackageDomain(const char* path)
|
||||||
{
|
{
|
||||||
PackageDomain* domain = new(std::nothrow) PackageDomain;
|
PackageDomain* domain = new(std::nothrow) PackageDomain(this);
|
||||||
if (domain == NULL)
|
if (domain == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
BReference<PackageDomain> domainReference(domain, true);
|
BReference<PackageDomain> domainReference(domain, true);
|
||||||
@@ -656,12 +783,16 @@ Volume::_LoadPackage(Package* package)
|
|||||||
status_t
|
status_t
|
||||||
Volume::_AddPackageContent(Package* package, bool notify)
|
Volume::_AddPackageContent(Package* package, bool notify)
|
||||||
{
|
{
|
||||||
|
status_t error = fPackageFSRoot->AddPackage(package);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
for (PackageNodeList::Iterator it = package->Nodes().GetIterator();
|
for (PackageNodeList::Iterator it = package->Nodes().GetIterator();
|
||||||
PackageNode* node = it.Next();) {
|
PackageNode* node = it.Next();) {
|
||||||
// skip over ".PackageInfo" file, it isn't part of the package content
|
// skip over ".PackageInfo" file, it isn't part of the package content
|
||||||
if (strcmp(node->Name(), B_HPKG_PACKAGE_INFO_FILE_NAME) == 0)
|
if (strcmp(node->Name(), B_HPKG_PACKAGE_INFO_FILE_NAME) == 0)
|
||||||
continue;
|
continue;
|
||||||
status_t error = _AddPackageContentRootNode(package, node, notify);
|
error = _AddPackageContentRootNode(package, node, notify);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
_RemovePackageContent(package, node, notify);
|
_RemovePackageContent(package, node, notify);
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
@@ -689,6 +820,8 @@ Volume::_RemovePackageContent(Package* package, PackageNode* endNode,
|
|||||||
|
|
||||||
node = nextNode;
|
node = nextNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fPackageFSRoot->RemovePackage(package);;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1109,16 +1242,48 @@ Volume::_DomainEntryMoved(PackageDomain* domain, dev_t deviceID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Volume::_InitMountType(const char* mountType)
|
||||||
|
{
|
||||||
|
if (mountType == NULL)
|
||||||
|
fMountType = MOUNT_TYPE_CUSTOM;
|
||||||
|
else if (strcmp(mountType, "system") == 0)
|
||||||
|
fMountType = MOUNT_TYPE_SYSTEM;
|
||||||
|
else if (strcmp(mountType, "common") == 0)
|
||||||
|
fMountType = MOUNT_TYPE_COMMON;
|
||||||
|
else if (strcmp(mountType, "home") == 0)
|
||||||
|
fMountType = MOUNT_TYPE_HOME;
|
||||||
|
else if (strcmp(mountType, "custom") == 0)
|
||||||
|
fMountType = MOUNT_TYPE_CUSTOM;
|
||||||
|
else
|
||||||
|
RETURN_ERROR(B_BAD_VALUE);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
||||||
{
|
{
|
||||||
if (shineThroughSetting == NULL)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
// get the directories to map
|
// get the directories to map
|
||||||
const char* const* directories = NULL;
|
const char* const* directories = NULL;
|
||||||
|
|
||||||
if (strcmp(shineThroughSetting, "system") == 0)
|
if (shineThroughSetting == NULL) {
|
||||||
|
// nothing specified -- derive from mount type
|
||||||
|
switch (fMountType) {
|
||||||
|
case MOUNT_TYPE_SYSTEM:
|
||||||
|
directories = kSystemShineThroughDirectories;
|
||||||
|
break;
|
||||||
|
case MOUNT_TYPE_COMMON:
|
||||||
|
directories = kCommonShineThroughDirectories;
|
||||||
|
break;
|
||||||
|
case MOUNT_TYPE_HOME:
|
||||||
|
directories = kHomeShineThroughDirectories;
|
||||||
|
break;
|
||||||
|
case MOUNT_TYPE_CUSTOM:
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
} else if (strcmp(shineThroughSetting, "system") == 0)
|
||||||
directories = kSystemShineThroughDirectories;
|
directories = kSystemShineThroughDirectories;
|
||||||
else if (strcmp(shineThroughSetting, "common") == 0)
|
else if (strcmp(shineThroughSetting, "common") == 0)
|
||||||
directories = kCommonShineThroughDirectories;
|
directories = kCommonShineThroughDirectories;
|
||||||
@@ -1132,21 +1297,13 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
|||||||
if (directories == NULL)
|
if (directories == NULL)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
// get our mount point
|
|
||||||
dev_t mountPointDevice;
|
|
||||||
ino_t mountPointNode;
|
|
||||||
status_t error = vfs_get_mount_point(fFSVolume->id, &mountPointDevice,
|
|
||||||
&mountPointNode);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
|
|
||||||
// iterate through the directory list, create the directories, and bind them
|
// iterate through the directory list, create the directories, and bind them
|
||||||
// to the mount point subdirectories
|
// to the mount point subdirectories
|
||||||
while (const char* directoryName = *(directories++)) {
|
while (const char* directoryName = *(directories++)) {
|
||||||
// look up the mount point subdirectory
|
// look up the mount point subdirectory
|
||||||
struct vnode* vnode;
|
struct vnode* vnode;
|
||||||
error = vfs_entry_ref_to_vnode(mountPointDevice, mountPointNode,
|
status_t error = vfs_entry_ref_to_vnode(fMountPoint.deviceID,
|
||||||
directoryName, &vnode);
|
fMountPoint.nodeID, directoryName, &vnode);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
dprintf("packagefs: Failed to get shine-through directory \"%s\": "
|
dprintf("packagefs: Failed to get shine-through directory \"%s\": "
|
||||||
"%s\n", directoryName, strerror(error));
|
"%s\n", directoryName, strerror(error));
|
||||||
@@ -1196,3 +1353,11 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
|||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Volume::_AddPackageLinksDirectory()
|
||||||
|
{
|
||||||
|
// TODO:...
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,9 +20,18 @@
|
|||||||
|
|
||||||
class Directory;
|
class Directory;
|
||||||
class Node;
|
class Node;
|
||||||
|
class PackageFSRoot;
|
||||||
|
|
||||||
|
|
||||||
class Volume {
|
enum MountType {
|
||||||
|
MOUNT_TYPE_SYSTEM,
|
||||||
|
MOUNT_TYPE_COMMON,
|
||||||
|
MOUNT_TYPE_HOME,
|
||||||
|
MOUNT_TYPE_CUSTOM
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Volume : public DoublyLinkedListLinkImpl<Volume> {
|
||||||
public:
|
public:
|
||||||
Volume(fs_volume* fsVolume);
|
Volume(fs_volume* fsVolume);
|
||||||
~Volume();
|
~Volume();
|
||||||
@@ -36,6 +45,18 @@ public:
|
|||||||
dev_t ID() const { return fFSVolume->id; }
|
dev_t ID() const { return fFSVolume->id; }
|
||||||
Directory* RootDirectory() const { return fRootDirectory; }
|
Directory* RootDirectory() const { return fRootDirectory; }
|
||||||
|
|
||||||
|
::MountType MountType() const { return fMountType; }
|
||||||
|
|
||||||
|
void SetPackageFSRoot(::PackageFSRoot* root)
|
||||||
|
{ fPackageFSRoot = root; }
|
||||||
|
::PackageFSRoot* PackageFSRoot() const
|
||||||
|
{ return fPackageFSRoot; }
|
||||||
|
|
||||||
|
dev_t MountPointDeviceID() const
|
||||||
|
{ return fMountPoint.deviceID; }
|
||||||
|
ino_t MountPointNodeID() const
|
||||||
|
{ return fMountPoint.nodeID; }
|
||||||
|
|
||||||
status_t Mount(const char* parameterString);
|
status_t Mount(const char* parameterString);
|
||||||
void Unmount();
|
void Unmount();
|
||||||
|
|
||||||
@@ -118,15 +139,24 @@ private:
|
|||||||
ino_t nodeID, const char* fromName,
|
ino_t nodeID, const char* fromName,
|
||||||
const char* name, bool notify);
|
const char* name, bool notify);
|
||||||
|
|
||||||
|
status_t _InitMountType(const char* mountType);
|
||||||
status_t _CreateShineThroughDirectories(
|
status_t _CreateShineThroughDirectories(
|
||||||
const char* shineThroughSetting);
|
const char* shineThroughSetting);
|
||||||
|
status_t _AddPackageLinksDirectory();
|
||||||
private:
|
private:
|
||||||
rw_lock fLock;
|
rw_lock fLock;
|
||||||
fs_volume* fFSVolume;
|
fs_volume* fFSVolume;
|
||||||
Directory* fRootDirectory;
|
Directory* fRootDirectory;
|
||||||
|
::PackageFSRoot* fPackageFSRoot;
|
||||||
|
::MountType fMountType;
|
||||||
thread_id fPackageLoader;
|
thread_id fPackageLoader;
|
||||||
PackageDomainList fPackageDomains;
|
PackageDomainList fPackageDomains;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
dev_t deviceID;
|
||||||
|
ino_t nodeID;
|
||||||
|
} fMountPoint;
|
||||||
|
|
||||||
NodeIDHashTable fNodes;
|
NodeIDHashTable fNodes;
|
||||||
|
|
||||||
JobList fJobQueue;
|
JobList fJobQueue;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
#include "GlobalFactory.h"
|
#include "GlobalFactory.h"
|
||||||
#include "LeafNode.h"
|
#include "LeafNode.h"
|
||||||
|
#include "PackageFSRoot.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -1063,12 +1064,21 @@ packagefs_std_ops(int32 op, ...)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = PackageFSRoot::GlobalInit();
|
||||||
|
if (error != B_OK) {
|
||||||
|
ERROR("Failed to init PackageFSRoot\n");
|
||||||
|
GlobalFactory::DeleteDefault();
|
||||||
|
exit_debugging();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_MODULE_UNINIT:
|
case B_MODULE_UNINIT:
|
||||||
{
|
{
|
||||||
PRINT("package_std_ops(): B_MODULE_UNINIT\n");
|
PRINT("package_std_ops(): B_MODULE_UNINIT\n");
|
||||||
|
PackageFSRoot::GlobalUninit();
|
||||||
GlobalFactory::DeleteDefault();
|
GlobalFactory::DeleteDefault();
|
||||||
exit_debugging();
|
exit_debugging();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user