packagefs: Move Volume::PackagesDirectory to top level

Also make it a BReferenceable and fix Volume::fPackagesDirectory leak.
This commit is contained in:
Ingo Weinhold
2014-04-18 23:31:38 +02:00
parent 586f1aeea2
commit aeb6fc9eca
5 changed files with 141 additions and 114 deletions
@@ -51,6 +51,7 @@ HAIKU_PACKAGE_FS_SOURCES =
PackageLinkSymlink.cpp
PackageNode.cpp
PackageNodeAttribute.cpp
PackagesDirectory.cpp
PackageSettings.cpp
PackageSymlink.cpp
Resolvable.cpp
@@ -0,0 +1,94 @@
/*
* 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()
:
fPath(NULL),
fDirFD(-1)
{
}
PackagesDirectory::~PackagesDirectory()
{
if (fDirFD >= 0)
close(fDirFD);
free(fPath);
}
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 package domain \"%s\"\n", strerror(error));
RETURN_ERROR(error);
}
fDirFD = vfs_open_vnode(vnode, O_RDONLY, true);
if (fDirFD < 0) {
ERROR("Failed to open package domain \"%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);
fDeviceID = st.st_dev;
fNodeID = st.st_ino;
// get a normalized path
KPath normalizedPath;
if (normalizedPath.InitCheck() != B_OK)
RETURN_ERROR(normalizedPath.InitCheck());
char* normalizedPathBuffer = normalizedPath.LockBuffer();
error = vfs_entry_ref_to_path(fDeviceID, fNodeID, 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;
}
@@ -0,0 +1,39 @@
/*
* Copyright 2009-2014, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGES_DIRECTORY_H
#define PACKAGES_DIRECTORY_H
#include <sys/stat.h>
#include <Referenceable.h>
class PackagesDirectory : public BReferenceable {
public:
PackagesDirectory();
~PackagesDirectory();
const char* Path() const
{ return fPath; }
int DirectoryFD() const
{ return fDirFD; }
dev_t DeviceID() const
{ return fDeviceID; }
ino_t NodeID() const
{ return fNodeID; }
status_t Init(const char* path, dev_t mountPointDeviceID,
ino_t mountPointNodeID, struct stat& _st);
private:
char* fPath;
int fDirFD;
dev_t fDeviceID;
ino_t fNodeID;
};
#endif // PACKAGES_DIRECTORY_H
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2013, Ingo Weinhold, [email protected].
* Copyright 2009-2014, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -24,8 +24,6 @@
#include <AutoDeleter.h>
#include <PackagesDirectoryDefs.h>
#include <fs/KPath.h>
#include <team.h>
#include <vfs.h>
#include "AttributeIndex.h"
@@ -37,6 +35,7 @@
#include "PackageFSRoot.h"
#include "PackageLinkDirectory.h"
#include "PackageLinksDirectory.h"
#include "PackagesDirectory.h"
#include "Resolvable.h"
#include "SizeIndex.h"
#include "UnpackingLeafNode.h"
@@ -71,115 +70,6 @@ static const char* const kActivationFilePath
// #pragma mark - ShineThroughDirectory
struct Volume::PackagesDirectory {
PackagesDirectory()
:
fPath(NULL),
fDirFD(-1)
{
}
~PackagesDirectory()
{
if (fDirFD >= 0)
close(fDirFD);
free(fPath);
}
const char* Path() const
{
return fPath;
}
int DirectoryFD() const
{
return fDirFD;
}
dev_t DeviceID() const
{
return fDeviceID;
}
ino_t NodeID() const
{
return fNodeID;
}
status_t 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 package domain \"%s\"\n", strerror(error));
RETURN_ERROR(error);
}
fDirFD = vfs_open_vnode(vnode, O_RDONLY, true);
if (fDirFD < 0) {
ERROR("Failed to open package domain \"%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);
fDeviceID = st.st_dev;
fNodeID = st.st_ino;
// get a normalized path
KPath normalizedPath;
if (normalizedPath.InitCheck() != B_OK)
RETURN_ERROR(normalizedPath.InitCheck());
char* normalizedPathBuffer = normalizedPath.LockBuffer();
error = vfs_entry_ref_to_path(fDeviceID, fNodeID, 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;
}
private:
char* fPath;
int fDirFD;
dev_t fDeviceID;
ino_t fNodeID;
};
// #pragma mark - ShineThroughDirectory
struct Volume::ShineThroughDirectory : public Directory {
ShineThroughDirectory(ino_t id)
:
@@ -323,6 +213,9 @@ Volume::~Volume()
if (fRootDirectory != NULL)
fRootDirectory->ReleaseReference();
if (fPackagesDirectory != NULL)
fPackagesDirectory->ReleaseReference();
rw_lock_destroy(&fLock);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2009-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VOLUME_H
@@ -27,6 +27,7 @@
class Directory;
class PackageFSRoot;
class PackagesDirectory;
class UnpackingNode;
typedef IndexHashTable::Iterator IndexDirIterator;
@@ -106,7 +107,6 @@ private:
const OldNodeAttributes& oldAttributes);
private:
struct PackagesDirectory;
struct ShineThroughDirectory;
struct ActivationChangeRequest;