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.
138 lines
3.1 KiB
C++
138 lines
3.1 KiB
C++
/*
|
|
* Copyright 2009-2014, Ingo Weinhold, [email protected].
|
|
* Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include "PackagesDirectory.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fs/KPath.h>
|
|
#include <team.h>
|
|
#include <vfs.h>
|
|
|
|
#include "DebugSupport.h"
|
|
|
|
|
|
PackagesDirectory::PackagesDirectory()
|
|
:
|
|
fStateName(),
|
|
fPath(NULL),
|
|
fDirFD(-1),
|
|
fNodeRef(),
|
|
fHashNext(NULL)
|
|
{
|
|
}
|
|
|
|
|
|
PackagesDirectory::~PackagesDirectory()
|
|
{
|
|
if (fDirFD >= 0)
|
|
close(fDirFD);
|
|
|
|
free(fPath);
|
|
}
|
|
|
|
|
|
/*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)
|
|
{
|
|
// Open the directory. We want the path be interpreted depending on from
|
|
// where it came (kernel or userland), but we always want a FD in the
|
|
// kernel I/O context. There's no VFS service method to do that for us,
|
|
// so we need to do that ourselves.
|
|
bool calledFromKernel
|
|
= team_get_current_team_id() == team_get_kernel_team_id();
|
|
// Not entirely correct, but good enough for now. The only
|
|
// alternative is to have that information passed in as well.
|
|
|
|
struct vnode* vnode;
|
|
status_t error;
|
|
if (path != NULL) {
|
|
error = vfs_get_vnode_from_path(path, calledFromKernel, &vnode);
|
|
} else {
|
|
// No path given -- use the "packages" directory at our mount point.
|
|
error = vfs_entry_ref_to_vnode(mountPointDeviceID, mountPointNodeID,
|
|
"packages", &vnode);
|
|
}
|
|
if (error != B_OK) {
|
|
ERROR("Failed to open packages directory \"%s\"\n", strerror(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);
|
|
|
|
if (fDirFD < 0) {
|
|
ERROR("Failed to open packages directory \"%s\"\n", strerror(fDirFD));
|
|
vfs_put_vnode(vnode);
|
|
RETURN_ERROR(fDirFD);
|
|
}
|
|
// Our vnode reference has been transferred to the FD.
|
|
|
|
// Is it a directory at all?
|
|
struct stat& st = _st;
|
|
if (fstat(fDirFD, &st) < 0)
|
|
RETURN_ERROR(errno);
|
|
|
|
fNodeRef.device = st.st_dev;
|
|
fNodeRef.node = st.st_ino;
|
|
|
|
// get a normalized path
|
|
KPath normalizedPath;
|
|
if (normalizedPath.InitCheck() != B_OK)
|
|
RETURN_ERROR(normalizedPath.InitCheck());
|
|
|
|
char* normalizedPathBuffer = normalizedPath.LockBuffer();
|
|
status_t error = vfs_entry_ref_to_path(fNodeRef.device, fNodeRef.node, NULL,
|
|
true, normalizedPathBuffer, normalizedPath.BufferSize());
|
|
if (error != B_OK)
|
|
RETURN_ERROR(error);
|
|
|
|
fPath = strdup(normalizedPathBuffer);
|
|
if (fPath == NULL)
|
|
RETURN_ERROR(B_NO_MEMORY);
|
|
|
|
return B_OK;
|
|
}
|