packagefs: Initial support for booting into old states
If an old state is specified via mount parameters we load the packages as specified in its activated-packages file. The interface for the package daemon, the package daemon itself, and the package kit are still to be adjusted, so ATM some PM components might be a bit confused when an old state was booted.
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
PackagesDirectory::PackagesDirectory()
|
PackagesDirectory::PackagesDirectory()
|
||||||
:
|
:
|
||||||
|
fStateName(),
|
||||||
fPath(NULL),
|
fPath(NULL),
|
||||||
fDirFD(-1),
|
fDirFD(-1),
|
||||||
fNodeRef(),
|
fNodeRef(),
|
||||||
@@ -34,7 +35,20 @@ PackagesDirectory::~PackagesDirectory()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t PackagesDirectory::Init(const char* path, dev_t mountPointDeviceID,
|
/*static*/ bool
|
||||||
|
PackagesDirectory::IsNewer(const PackagesDirectory* a,
|
||||||
|
const PackagesDirectory* b)
|
||||||
|
{
|
||||||
|
if (b->fStateName.IsEmpty())
|
||||||
|
return false;
|
||||||
|
if (a->fStateName.IsEmpty())
|
||||||
|
return true;
|
||||||
|
return strcmp(a->fStateName, b->fStateName) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackagesDirectory::Init(const char* path, dev_t mountPointDeviceID,
|
||||||
ino_t mountPointNodeID, struct stat& _st)
|
ino_t mountPointNodeID, struct stat& _st)
|
||||||
{
|
{
|
||||||
// Open the directory. We want the path be interpreted depending on from
|
// Open the directory. We want the path be interpreted depending on from
|
||||||
@@ -56,14 +70,41 @@ status_t PackagesDirectory::Init(const char* path, dev_t mountPointDeviceID,
|
|||||||
"packages", &vnode);
|
"packages", &vnode);
|
||||||
}
|
}
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
ERROR("Failed to open package domain \"%s\"\n", strerror(error));
|
ERROR("Failed to open packages directory \"%s\"\n", strerror(error));
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return _Init(vnode, _st);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackagesDirectory::InitOldState(dev_t adminDirDeviceID, ino_t adminDirNodeID,
|
||||||
|
const char* stateName)
|
||||||
|
{
|
||||||
|
if (!fStateName.SetTo(stateName))
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
struct vnode* vnode;
|
||||||
|
status_t error = vfs_entry_ref_to_vnode(adminDirDeviceID, adminDirNodeID,
|
||||||
|
stateName, &vnode);
|
||||||
|
if (error != B_OK) {
|
||||||
|
ERROR("Failed to open old state directory \"%s\"\n", strerror(error));
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
return _Init(vnode, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackagesDirectory::_Init(struct vnode* vnode, struct stat& _st)
|
||||||
|
{
|
||||||
fDirFD = vfs_open_vnode(vnode, O_RDONLY, true);
|
fDirFD = vfs_open_vnode(vnode, O_RDONLY, true);
|
||||||
|
|
||||||
if (fDirFD < 0) {
|
if (fDirFD < 0) {
|
||||||
ERROR("Failed to open package domain \"%s\"\n", strerror(fDirFD));
|
ERROR("Failed to open packages directory \"%s\"\n", strerror(fDirFD));
|
||||||
vfs_put_vnode(vnode);
|
vfs_put_vnode(vnode);
|
||||||
RETURN_ERROR(fDirFD);
|
RETURN_ERROR(fDirFD);
|
||||||
}
|
}
|
||||||
@@ -83,8 +124,8 @@ status_t PackagesDirectory::Init(const char* path, dev_t mountPointDeviceID,
|
|||||||
RETURN_ERROR(normalizedPath.InitCheck());
|
RETURN_ERROR(normalizedPath.InitCheck());
|
||||||
|
|
||||||
char* normalizedPathBuffer = normalizedPath.LockBuffer();
|
char* normalizedPathBuffer = normalizedPath.LockBuffer();
|
||||||
error = vfs_entry_ref_to_path(fNodeRef.device, fNodeRef.node, NULL, true,
|
status_t error = vfs_entry_ref_to_path(fNodeRef.device, fNodeRef.node, NULL,
|
||||||
normalizedPathBuffer, normalizedPath.BufferSize());
|
true, normalizedPathBuffer, normalizedPath.BufferSize());
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
|||||||
@@ -9,15 +9,22 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
|
#include <util/DoublyLinkedList.h>
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
#include "NodeRef.h"
|
#include "NodeRef.h"
|
||||||
|
#include "String.h"
|
||||||
|
|
||||||
|
|
||||||
class PackagesDirectory : public BReferenceable {
|
class PackagesDirectory : public BReferenceable,
|
||||||
|
public DoublyLinkedListLinkImpl<PackagesDirectory> {
|
||||||
public:
|
public:
|
||||||
PackagesDirectory();
|
PackagesDirectory();
|
||||||
~PackagesDirectory();
|
~PackagesDirectory();
|
||||||
|
|
||||||
|
const String& StateName() const
|
||||||
|
{ return fStateName; }
|
||||||
|
// empty for the latest state
|
||||||
const char* Path() const
|
const char* Path() const
|
||||||
{ return fPath; }
|
{ return fPath; }
|
||||||
int DirectoryFD() const
|
int DirectoryFD() const
|
||||||
@@ -31,12 +38,57 @@ public:
|
|||||||
|
|
||||||
status_t Init(const char* path, dev_t mountPointDeviceID,
|
status_t Init(const char* path, dev_t mountPointDeviceID,
|
||||||
ino_t mountPointNodeID, struct stat& _st);
|
ino_t mountPointNodeID, struct stat& _st);
|
||||||
|
status_t InitOldState(dev_t adminDirDeviceID,
|
||||||
|
ino_t adminDirNodeID,
|
||||||
|
const char* stateName);
|
||||||
|
|
||||||
|
static bool IsNewer(const PackagesDirectory* a,
|
||||||
|
const PackagesDirectory* b);
|
||||||
|
|
||||||
|
PackagesDirectory*& HashTableNext()
|
||||||
|
{ return fHashNext; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t _Init(struct vnode* vnode, struct stat& _st);
|
||||||
|
|
||||||
|
private:
|
||||||
|
String fStateName;
|
||||||
char* fPath;
|
char* fPath;
|
||||||
int fDirFD;
|
int fDirFD;
|
||||||
node_ref fNodeRef;
|
node_ref fNodeRef;
|
||||||
|
PackagesDirectory* fHashNext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PackagesDirectoryHashDefinition {
|
||||||
|
typedef const node_ref& KeyType;
|
||||||
|
typedef PackagesDirectory ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const node_ref& key) const
|
||||||
|
{
|
||||||
|
return (size_t)key.device ^ (size_t)key.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(const PackagesDirectory* value) const
|
||||||
|
{
|
||||||
|
return HashKey(value->NodeRef());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(const node_ref& key, const PackagesDirectory* value) const
|
||||||
|
{
|
||||||
|
return key == value->NodeRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
PackagesDirectory*& GetLink(PackagesDirectory* value) const
|
||||||
|
{
|
||||||
|
return value->HashTableNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef BOpenHashTable<PackagesDirectoryHashDefinition>
|
||||||
|
PackagesDirectoryHashTable;
|
||||||
|
typedef DoublyLinkedList<PackagesDirectory> PackagesDirectoryList;
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGES_DIRECTORY_H
|
#endif // PACKAGES_DIRECTORY_H
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
#include "PackageFSRoot.h"
|
#include "PackageFSRoot.h"
|
||||||
#include "PackageLinkDirectory.h"
|
#include "PackageLinkDirectory.h"
|
||||||
#include "PackageLinksDirectory.h"
|
#include "PackageLinksDirectory.h"
|
||||||
#include "PackagesDirectory.h"
|
|
||||||
#include "Resolvable.h"
|
#include "Resolvable.h"
|
||||||
#include "SizeIndex.h"
|
#include "SizeIndex.h"
|
||||||
#include "UnpackingLeafNode.h"
|
#include "UnpackingLeafNode.h"
|
||||||
@@ -62,6 +61,10 @@ const size_t kMaxActivationRequestSize = 10 * 1024 * 1024;
|
|||||||
// sanity limit for activation file size
|
// sanity limit for activation file size
|
||||||
const size_t kMaxActivationFileSize = 10 * 1024 * 1024;
|
const size_t kMaxActivationFileSize = 10 * 1024 * 1024;
|
||||||
|
|
||||||
|
static const char* const kAdministrativeDirectoryName
|
||||||
|
= PACKAGES_DIRECTORY_ADMIN_DIRECTORY;
|
||||||
|
static const char* const kActivationFileName
|
||||||
|
= PACKAGES_DIRECTORY_ACTIVATION_FILE;
|
||||||
static const char* const kActivationFilePath
|
static const char* const kActivationFilePath
|
||||||
= PACKAGES_DIRECTORY_ADMIN_DIRECTORY "/"
|
= PACKAGES_DIRECTORY_ADMIN_DIRECTORY "/"
|
||||||
PACKAGES_DIRECTORY_ACTIVATION_FILE;
|
PACKAGES_DIRECTORY_ACTIVATION_FILE;
|
||||||
@@ -165,6 +168,8 @@ Volume::Volume(fs_volume* fsVolume)
|
|||||||
fRootDirectory(NULL),
|
fRootDirectory(NULL),
|
||||||
fPackageFSRoot(NULL),
|
fPackageFSRoot(NULL),
|
||||||
fPackagesDirectory(NULL),
|
fPackagesDirectory(NULL),
|
||||||
|
fPackagesDirectories(),
|
||||||
|
fPackagesDirectoriesByNodeRef(),
|
||||||
fPackageSettings(),
|
fPackageSettings(),
|
||||||
fNextNodeID(kRootDirectoryID + 1)
|
fNextNodeID(kRootDirectoryID + 1)
|
||||||
{
|
{
|
||||||
@@ -213,8 +218,8 @@ Volume::~Volume()
|
|||||||
if (fRootDirectory != NULL)
|
if (fRootDirectory != NULL)
|
||||||
fRootDirectory->ReleaseReference();
|
fRootDirectory->ReleaseReference();
|
||||||
|
|
||||||
if (fPackagesDirectory != NULL)
|
while (PackagesDirectory* directory = fPackagesDirectories.RemoveHead())
|
||||||
fPackagesDirectory->ReleaseReference();
|
directory->ReleaseReference();
|
||||||
|
|
||||||
rw_lock_destroy(&fLock);
|
rw_lock_destroy(&fLock);
|
||||||
}
|
}
|
||||||
@@ -224,7 +229,11 @@ status_t
|
|||||||
Volume::Mount(const char* parameterString)
|
Volume::Mount(const char* parameterString)
|
||||||
{
|
{
|
||||||
// init the hash tables
|
// init the hash tables
|
||||||
status_t error = fNodes.Init();
|
status_t error = fPackagesDirectoriesByNodeRef.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
error = fNodes.Init();
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
@@ -305,6 +314,7 @@ Volume::Mount(const char* parameterString)
|
|||||||
const char* volumeName = NULL;
|
const char* volumeName = NULL;
|
||||||
const char* mountType = NULL;
|
const char* mountType = NULL;
|
||||||
const char* shineThrough = NULL;
|
const char* shineThrough = NULL;
|
||||||
|
const char* packagesState = NULL;
|
||||||
|
|
||||||
void* parameterHandle = parse_driver_settings_string(parameterString);
|
void* parameterHandle = parse_driver_settings_string(parameterString);
|
||||||
if (parameterHandle != NULL) {
|
if (parameterHandle != NULL) {
|
||||||
@@ -315,6 +325,8 @@ Volume::Mount(const char* parameterString)
|
|||||||
mountType = get_driver_parameter(parameterHandle, "type", 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);
|
||||||
|
packagesState = get_driver_parameter(parameterHandle, "state", NULL,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjectDeleter<void, status_t> parameterHandleDeleter(parameterHandle,
|
CObjectDeleter<void, status_t> parameterHandleDeleter(parameterHandle,
|
||||||
@@ -348,6 +360,8 @@ Volume::Mount(const char* parameterString)
|
|||||||
fPackagesDirectory = new(std::nothrow) PackagesDirectory;
|
fPackagesDirectory = new(std::nothrow) PackagesDirectory;
|
||||||
if (fPackagesDirectory == NULL)
|
if (fPackagesDirectory == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
fPackagesDirectories.Add(fPackagesDirectory);
|
||||||
|
fPackagesDirectoriesByNodeRef.Insert(fPackagesDirectory);
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
error = fPackagesDirectory->Init(packages, fMountPoint.deviceID,
|
error = fPackagesDirectory->Init(packages, fMountPoint.deviceID,
|
||||||
@@ -355,6 +369,13 @@ Volume::Mount(const char* parameterString)
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// If a packages state has been specified, load the needed states.
|
||||||
|
if (packagesState != NULL) {
|
||||||
|
error = _LoadOldPackagesStates(packagesState);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
// If no volume name is given, infer it from the mount type.
|
// If no volume name is given, infer it from the mount type.
|
||||||
if (volumeName == NULL) {
|
if (volumeName == NULL) {
|
||||||
switch (fMountType) {
|
switch (fMountType) {
|
||||||
@@ -620,14 +641,89 @@ Volume::PackageLinkNodeChanged(Node* node, uint32 statFields,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Volume::_LoadOldPackagesStates(const char* packagesState)
|
||||||
|
{
|
||||||
|
// open and stat the admininistrative dir
|
||||||
|
int fd = openat(fPackagesDirectory->DirectoryFD(),
|
||||||
|
kAdministrativeDirectoryName, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
ERROR("Failed to open administrative directory: %s\n", strerror(errno));
|
||||||
|
RETURN_ERROR(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat adminDirStat;
|
||||||
|
if (fstat(fd, &adminDirStat) < 0) {
|
||||||
|
ERROR("Failed to fstat() administrative directory: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
RETURN_ERROR(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate through the "administrative" dir
|
||||||
|
DIR* dir = fdopendir(fd);
|
||||||
|
if (dir == NULL) {
|
||||||
|
ERROR("Failed to open administrative directory: %s\n", strerror(errno));
|
||||||
|
RETURN_ERROR(errno);
|
||||||
|
}
|
||||||
|
CObjectDeleter<DIR, int> dirCloser(dir, closedir);
|
||||||
|
|
||||||
|
while (dirent* entry = readdir(dir)) {
|
||||||
|
if (strncmp(entry->d_name, "state_", 6) != 0
|
||||||
|
|| strcmp(entry->d_name, packagesState) < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackagesDirectory* packagesDirectory
|
||||||
|
= new(std::nothrow) PackagesDirectory;
|
||||||
|
status_t error = packagesDirectory->InitOldState(adminDirStat.st_dev,
|
||||||
|
adminDirStat.st_ino, entry->d_name);
|
||||||
|
if (error != B_OK) {
|
||||||
|
delete packagesDirectory;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fPackagesDirectories.Add(packagesDirectory);
|
||||||
|
fPackagesDirectoriesByNodeRef.Insert(packagesDirectory);
|
||||||
|
|
||||||
|
INFORM("added old packages dir state \"%s\"\n",
|
||||||
|
packagesDirectory->StateName().Data());
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort the packages directories by state age
|
||||||
|
fPackagesDirectories.Sort(&PackagesDirectory::IsNewer);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Volume::_AddInitialPackages()
|
Volume::_AddInitialPackages()
|
||||||
{
|
{
|
||||||
dprintf("packagefs: Adding packages from \"%s\"\n",
|
PackagesDirectory* packagesDirectory = fPackagesDirectories.Last();
|
||||||
fPackagesDirectory->Path());
|
INFORM("Adding packages from \"%s\"\n", packagesDirectory->Path());
|
||||||
|
|
||||||
|
// try reading the activation file of the oldest state
|
||||||
|
status_t error = _AddInitialPackagesFromActivationFile(packagesDirectory);
|
||||||
|
if (error != B_OK && packagesDirectory != fPackagesDirectory) {
|
||||||
|
WARN("Loading packages from old state \"%s\" failed. Loading packages "
|
||||||
|
"from latest state.\n", packagesDirectory->StateName().Data());
|
||||||
|
|
||||||
|
// remove all packages already added
|
||||||
|
{
|
||||||
|
VolumeWriteLocker systemVolumeLocker(_SystemVolumeIfNotSelf());
|
||||||
|
VolumeWriteLocker volumeLocker(this);
|
||||||
|
_RemoveAllPackages();
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the old states
|
||||||
|
while (fPackagesDirectories.Last() != fPackagesDirectory)
|
||||||
|
fPackagesDirectories.RemoveTail()->ReleaseReference();
|
||||||
|
|
||||||
|
// try reading the activation file of the latest state
|
||||||
|
packagesDirectory = fPackagesDirectory;
|
||||||
|
error = _AddInitialPackagesFromActivationFile(packagesDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
// try reading the activation file
|
|
||||||
status_t error = _AddInitialPackagesFromActivationFile();
|
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
INFORM("Loading packages from activation file failed. Loading all "
|
INFORM("Loading packages from activation file failed. Loading all "
|
||||||
"packages in packages directory.\n");
|
"packages in packages directory.\n");
|
||||||
@@ -666,11 +762,14 @@ Volume::_AddInitialPackages()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Volume::_AddInitialPackagesFromActivationFile()
|
Volume::_AddInitialPackagesFromActivationFile(
|
||||||
|
PackagesDirectory* packagesDirectory)
|
||||||
{
|
{
|
||||||
// try reading the activation file
|
// try reading the activation file
|
||||||
int fd = openat(fPackagesDirectory->DirectoryFD(),
|
int fd = openat(packagesDirectory->DirectoryFD(),
|
||||||
kActivationFilePath, O_RDONLY);
|
packagesDirectory == fPackagesDirectory
|
||||||
|
? kActivationFilePath : kActivationFileName,
|
||||||
|
O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
INFORM("Failed to open packages activation file: %s\n",
|
INFORM("Failed to open packages activation file: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
@@ -730,7 +829,8 @@ Volume::_AddInitialPackagesFromActivationFile()
|
|||||||
RETURN_ERROR(B_BAD_DATA);
|
RETURN_ERROR(B_BAD_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t error = _LoadAndAddInitialPackage(packageName);
|
status_t error = _LoadAndAddInitialPackage(packagesDirectory,
|
||||||
|
packageName);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
@@ -771,7 +871,7 @@ Volume::_AddInitialPackagesFromDirectory()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_LoadAndAddInitialPackage(entry->d_name);
|
_LoadAndAddInitialPackage(fPackagesDirectory, entry->d_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -779,10 +879,11 @@ Volume::_AddInitialPackagesFromDirectory()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Volume::_LoadAndAddInitialPackage(const char* name)
|
Volume::_LoadAndAddInitialPackage(PackagesDirectory* packagesDirectory,
|
||||||
|
const char* name)
|
||||||
{
|
{
|
||||||
Package* package;
|
Package* package;
|
||||||
status_t error = _LoadPackage(name, package);
|
status_t error = _LoadPackage(packagesDirectory, name, package);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
ERROR("Failed to load package \"%s\": %s\n", name, strerror(error));
|
ERROR("Failed to load package \"%s\": %s\n", name, strerror(error));
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
@@ -1309,17 +1410,28 @@ Volume::_RemoveNodeAndVNode(Node* node)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Volume::_LoadPackage(const char* name, Package*& _package)
|
Volume::_LoadPackage(PackagesDirectory* packagesDirectory, const char* name,
|
||||||
|
Package*& _package)
|
||||||
{
|
{
|
||||||
// check whether the entry is a file
|
// Find the package -- check the specified packages directory and iterate
|
||||||
|
// toward the newer states.
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (fstatat(fPackagesDirectory->DirectoryFD(), name, &st, 0) < 0
|
for (;;) {
|
||||||
|| !S_ISREG(st.st_mode)) {
|
if (packagesDirectory == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
if (fstatat(packagesDirectory->DirectoryFD(), name, &st, 0) == 0) {
|
||||||
|
// check whether the entry is a file
|
||||||
|
if (!S_ISREG(st.st_mode))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
packagesDirectory = fPackagesDirectories.GetPrevious(packagesDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a package
|
// create a package
|
||||||
Package* package = new(std::nothrow) Package(this, fPackagesDirectory,
|
Package* package = new(std::nothrow) Package(this, packagesDirectory,
|
||||||
st.st_dev, st.st_ino);
|
st.st_dev, st.st_ino);
|
||||||
if (package == NULL)
|
if (package == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
@@ -1417,7 +1529,7 @@ INFORM("Volume::_ChangeActivation(): %" B_PRId32 " new packages, %" B_PRId32 " o
|
|||||||
}
|
}
|
||||||
|
|
||||||
Package* package;
|
Package* package;
|
||||||
status_t error = _LoadPackage(item->name, package);
|
status_t error = _LoadPackage(fPackagesDirectory, item->name, package);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
ERROR("Volume::_ChangeActivation(): failed to load package "
|
ERROR("Volume::_ChangeActivation(): failed to load package "
|
||||||
"\"%s\"\n", item->name);
|
"\"%s\"\n", item->name);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "NodeListener.h"
|
#include "NodeListener.h"
|
||||||
#include "Package.h"
|
#include "Package.h"
|
||||||
#include "PackageLinksListener.h"
|
#include "PackageLinksListener.h"
|
||||||
|
#include "PackagesDirectory.h"
|
||||||
#include "PackageSettings.h"
|
#include "PackageSettings.h"
|
||||||
#include "Query.h"
|
#include "Query.h"
|
||||||
|
|
||||||
@@ -109,10 +110,16 @@ private:
|
|||||||
struct ActivationChangeRequest;
|
struct ActivationChangeRequest;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
status_t _LoadOldPackagesStates(
|
||||||
|
const char* packagesState);
|
||||||
|
|
||||||
status_t _AddInitialPackages();
|
status_t _AddInitialPackages();
|
||||||
status_t _AddInitialPackagesFromActivationFile();
|
status_t _AddInitialPackagesFromActivationFile(
|
||||||
|
PackagesDirectory* packagesDirectory);
|
||||||
status_t _AddInitialPackagesFromDirectory();
|
status_t _AddInitialPackagesFromDirectory();
|
||||||
status_t _LoadAndAddInitialPackage(const char* name);
|
status_t _LoadAndAddInitialPackage(
|
||||||
|
PackagesDirectory* packagesDirectory,
|
||||||
|
const char* name);
|
||||||
|
|
||||||
inline void _AddPackage(Package* package);
|
inline void _AddPackage(Package* package);
|
||||||
inline void _RemovePackage(Package* package);
|
inline void _RemovePackage(Package* package);
|
||||||
@@ -145,8 +152,9 @@ private:
|
|||||||
void _RemoveNodeAndVNode(Node* node);
|
void _RemoveNodeAndVNode(Node* node);
|
||||||
// caller must hold a reference
|
// caller must hold a reference
|
||||||
|
|
||||||
status_t _LoadPackage(const char* name,
|
status_t _LoadPackage(
|
||||||
Package*& _package);
|
PackagesDirectory* packagesDirectory,
|
||||||
|
const char* name, Package*& _package);
|
||||||
|
|
||||||
status_t _ChangeActivation(
|
status_t _ChangeActivation(
|
||||||
ActivationChangeRequest& request);
|
ActivationChangeRequest& request);
|
||||||
@@ -178,6 +186,8 @@ private:
|
|||||||
::PackageFSRoot* fPackageFSRoot;
|
::PackageFSRoot* fPackageFSRoot;
|
||||||
::MountType fMountType;
|
::MountType fMountType;
|
||||||
PackagesDirectory* fPackagesDirectory;
|
PackagesDirectory* fPackagesDirectory;
|
||||||
|
PackagesDirectoryList fPackagesDirectories;
|
||||||
|
PackagesDirectoryHashTable fPackagesDirectoriesByNodeRef;
|
||||||
PackageSettings fPackageSettings;
|
PackageSettings fPackageSettings;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user