Fix handling of shine-through directories
* Add a new class ShineThroughDirectory for shine-through directories instead of using UnpackingDirectory. * Split up setting up the shine-through directories in two steps. First the directories are only created. That happens before adding the initial package domains. After publishing the root node we bind the shine-through directories to the underlying directories. * This makes adding a package directory with the same name as a shine-through directory fail in _AddPackageNode() as originally intended. Since we no longer want it to fail -- the package daemon will copy the files in the respective directories as part of the activation process -- we simply skip the directory now. Adjust _AddPackageNode() and _AddPackageContentRootNode() accordingly.
This commit is contained in:
@@ -46,6 +46,7 @@
|
|||||||
#include "SizeIndex.h"
|
#include "SizeIndex.h"
|
||||||
#include "UnpackingLeafNode.h"
|
#include "UnpackingLeafNode.h"
|
||||||
#include "UnpackingDirectory.h"
|
#include "UnpackingDirectory.h"
|
||||||
|
#include "Utils.h"
|
||||||
#include "Version.h"
|
#include "Version.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -443,6 +444,27 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - ShineThroughDirectory
|
||||||
|
|
||||||
|
|
||||||
|
struct Volume::ShineThroughDirectory : public Directory {
|
||||||
|
ShineThroughDirectory(ino_t id)
|
||||||
|
:
|
||||||
|
Directory(id)
|
||||||
|
{
|
||||||
|
get_real_time(fModifiedTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual timespec ModifiedTime() const
|
||||||
|
{
|
||||||
|
return fModifiedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
timespec fModifiedTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Volume
|
// #pragma mark - Volume
|
||||||
|
|
||||||
|
|
||||||
@@ -656,6 +678,11 @@ Volume::Mount(const char* parameterString)
|
|||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create shine-through directories
|
||||||
|
error = _CreateShineThroughDirectories(shineThrough);
|
||||||
|
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)
|
||||||
@@ -667,11 +694,6 @@ 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);
|
||||||
@@ -680,6 +702,11 @@ Volume::Mount(const char* parameterString)
|
|||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bind and publish the shine-through directories
|
||||||
|
error = _PublishShineThroughDirectories();
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
// run the package loader
|
// run the package loader
|
||||||
resume_thread(fPackageLoader);
|
resume_thread(fPackageLoader);
|
||||||
|
|
||||||
@@ -1083,6 +1110,7 @@ Volume::_AddPackageContentRootNode(Package* package,
|
|||||||
do {
|
do {
|
||||||
Node* node;
|
Node* node;
|
||||||
status_t error = _AddPackageNode(directory, packageNode, notify, node);
|
status_t error = _AddPackageNode(directory, packageNode, notify, node);
|
||||||
|
// returns B_OK with a NULL node, when skipping the node
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
// unlock all directories
|
// unlock all directories
|
||||||
while (directory != NULL) {
|
while (directory != NULL) {
|
||||||
@@ -1096,14 +1124,16 @@ Volume::_AddPackageContentRootNode(Package* package,
|
|||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursive into directory
|
// recursive into directory, unless we're supposed to skip the node
|
||||||
if (PackageDirectory* packageDirectory
|
if (node != NULL) {
|
||||||
= dynamic_cast<PackageDirectory*>(packageNode)) {
|
if (PackageDirectory* packageDirectory
|
||||||
if (packageDirectory->FirstChild() != NULL) {
|
= dynamic_cast<PackageDirectory*>(packageNode)) {
|
||||||
directory = dynamic_cast<Directory*>(node);
|
if (packageDirectory->FirstChild() != NULL) {
|
||||||
packageNode = packageDirectory->FirstChild();
|
directory = dynamic_cast<Directory*>(node);
|
||||||
directory->WriteLock();
|
packageNode = packageDirectory->FirstChild();
|
||||||
continue;
|
directory->WriteLock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1196,8 +1226,11 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode,
|
|||||||
|
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
unpackingNode = dynamic_cast<UnpackingNode*>(node);
|
unpackingNode = dynamic_cast<UnpackingNode*>(node);
|
||||||
if (unpackingNode == NULL)
|
if (unpackingNode == NULL) {
|
||||||
RETURN_ERROR(B_BAD_VALUE);
|
_node = NULL;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
oldPackageNode = unpackingNode->GetPackageNode();
|
||||||
} else {
|
} else {
|
||||||
status_t error = _CreateUnpackingNode(packageNode->Mode(), directory,
|
status_t error = _CreateUnpackingNode(packageNode->Mode(), directory,
|
||||||
packageNode->Name(), unpackingNode);
|
packageNode->Name(), unpackingNode);
|
||||||
@@ -1205,7 +1238,6 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode,
|
|||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
node = unpackingNode->GetNode();
|
node = unpackingNode->GetNode();
|
||||||
oldPackageNode = unpackingNode->GetPackageNode();
|
|
||||||
newNode = true;
|
newNode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1356,7 +1388,7 @@ Volume::_CreateUnpackingNode(mode_t mode, Directory* parent, const char* name,
|
|||||||
|
|
||||||
fNodes.Insert(node);
|
fNodes.Insert(node);
|
||||||
nodeReference.Detach();
|
nodeReference.Detach();
|
||||||
// we keep the initial node reference for this table
|
// we keep the initial node reference for the table
|
||||||
|
|
||||||
_node = unpackingNode;
|
_node = unpackingNode;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -1547,6 +1579,31 @@ Volume::_InitMountType(const char* mountType)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Volume::_CreateShineThroughDirectory(Directory* parent, const char* name,
|
||||||
|
Directory*& _directory)
|
||||||
|
{
|
||||||
|
ShineThroughDirectory* directory = new(std::nothrow) ShineThroughDirectory(
|
||||||
|
fNextNodeID++);
|
||||||
|
if (directory == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
BReference<ShineThroughDirectory> directoryReference(directory, true);
|
||||||
|
|
||||||
|
status_t error = directory->Init(parent, name, 0);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
parent->AddChild(directory);
|
||||||
|
|
||||||
|
fNodes.Insert(directory);
|
||||||
|
directoryReference.Detach();
|
||||||
|
// we keep the initial node reference for the table
|
||||||
|
|
||||||
|
_directory = directory;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
||||||
{
|
{
|
||||||
@@ -1582,9 +1639,38 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
|||||||
if (directories == NULL)
|
if (directories == NULL)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
// iterate through the directory list, create the directories, and bind them
|
// iterate through the directory list and create the directories
|
||||||
// to the mount point subdirectories
|
|
||||||
while (const char* directoryName = *(directories++)) {
|
while (const char* directoryName = *(directories++)) {
|
||||||
|
// create the directory
|
||||||
|
Directory* directory;
|
||||||
|
status_t error = _CreateShineThroughDirectory(fRootDirectory,
|
||||||
|
directoryName, directory);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Volume::_PublishShineThroughDirectories()
|
||||||
|
{
|
||||||
|
// Iterate through the root directory children and bind the shine-through
|
||||||
|
// directories to the respective mount point subdirectories.
|
||||||
|
Node* nextNode;
|
||||||
|
for (Node* node = fRootDirectory->FirstChild(); node != NULL;
|
||||||
|
node = nextNode) {
|
||||||
|
nextNode = fRootDirectory->NextChild(node);
|
||||||
|
|
||||||
|
// skip anything but shine-through directories
|
||||||
|
ShineThroughDirectory* directory
|
||||||
|
= dynamic_cast<ShineThroughDirectory*>(node);
|
||||||
|
if (directory == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char* directoryName = directory->Name();
|
||||||
|
|
||||||
// look up the mount point subdirectory
|
// look up the mount point subdirectory
|
||||||
struct vnode* vnode;
|
struct vnode* vnode;
|
||||||
status_t error = vfs_entry_ref_to_vnode(fMountPoint.deviceID,
|
status_t error = vfs_entry_ref_to_vnode(fMountPoint.deviceID,
|
||||||
@@ -1592,6 +1678,7 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
|||||||
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));
|
||||||
|
_RemoveNode(directory);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CObjectDeleter<struct vnode> vnodePutter(vnode, &vfs_put_vnode);
|
CObjectDeleter<struct vnode> vnodePutter(vnode, &vfs_put_vnode);
|
||||||
@@ -1602,35 +1689,29 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
|||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
dprintf("packagefs: Failed to stat shine-through directory \"%s\": "
|
dprintf("packagefs: Failed to stat shine-through directory \"%s\": "
|
||||||
"%s\n", directoryName, strerror(error));
|
"%s\n", directoryName, strerror(error));
|
||||||
|
_RemoveNode(directory);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!S_ISDIR(st.st_mode)) {
|
if (!S_ISDIR(st.st_mode)) {
|
||||||
dprintf("packagefs: Shine-through entry \"%s\" is not a "
|
dprintf("packagefs: Shine-through entry \"%s\" is not a "
|
||||||
"directory\n", directoryName);
|
"directory\n", directoryName);
|
||||||
|
_RemoveNode(directory);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the directory
|
// publish the vnode, so the VFS will find it without asking us
|
||||||
UnpackingNode* directory;
|
error = PublishVNode(directory);
|
||||||
error = _CreateUnpackingNode(S_IFDIR, fRootDirectory, directoryName,
|
|
||||||
directory);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
|
|
||||||
// publish its vnode, so the VFS will find it without asking us
|
|
||||||
Node* directoryNode = directory->GetNode();
|
|
||||||
error = PublishVNode(directoryNode);
|
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
_RemoveNode(directoryNode);
|
_RemoveNode(directory);
|
||||||
RETURN_ERROR(error);
|
RETURN_ERROR(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind the directory
|
// bind the directory
|
||||||
error = vfs_bind_mount_directory(st.st_dev, st.st_ino, fFSVolume->id,
|
error = vfs_bind_mount_directory(st.st_dev, st.st_ino, fFSVolume->id,
|
||||||
directoryNode->ID());
|
directory->ID());
|
||||||
|
|
||||||
PutVNode(directoryNode->ID());
|
PutVNode(directory->ID());
|
||||||
// release our reference again -- on success
|
// release our reference again -- on success
|
||||||
// vfs_bind_mount_directory() got one
|
// vfs_bind_mount_directory() got one
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ private:
|
|||||||
struct PackageLoaderErrorOutput;
|
struct PackageLoaderErrorOutput;
|
||||||
struct PackageLoaderContentHandler;
|
struct PackageLoaderContentHandler;
|
||||||
struct DomainDirectoryListener;
|
struct DomainDirectoryListener;
|
||||||
|
struct ShineThroughDirectory;
|
||||||
|
|
||||||
friend struct AddPackageDomainJob;
|
friend struct AddPackageDomainJob;
|
||||||
friend struct DomainDirectoryEventJob;
|
friend struct DomainDirectoryEventJob;
|
||||||
@@ -175,8 +176,11 @@ private:
|
|||||||
const char* name, bool notify);
|
const char* name, bool notify);
|
||||||
|
|
||||||
status_t _InitMountType(const char* mountType);
|
status_t _InitMountType(const char* mountType);
|
||||||
|
status_t _CreateShineThroughDirectory(Directory* parent,
|
||||||
|
const char* name, Directory*& _directory);
|
||||||
status_t _CreateShineThroughDirectories(
|
status_t _CreateShineThroughDirectories(
|
||||||
const char* shineThroughSetting);
|
const char* shineThroughSetting);
|
||||||
|
status_t _PublishShineThroughDirectories();
|
||||||
|
|
||||||
status_t _AddPackageLinksDirectory();
|
status_t _AddPackageLinksDirectory();
|
||||||
void _RemovePackageLinksDirectory();
|
void _RemovePackageLinksDirectory();
|
||||||
|
|||||||
Reference in New Issue
Block a user