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:
parent
166412ff77
commit
4caf282707
@ -46,6 +46,7 @@
|
||||
#include "SizeIndex.h"
|
||||
#include "UnpackingLeafNode.h"
|
||||
#include "UnpackingDirectory.h"
|
||||
#include "Utils.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
|
||||
|
||||
|
||||
@ -656,6 +678,11 @@ Volume::Mount(const char* parameterString)
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
// create shine-through directories
|
||||
error = _CreateShineThroughDirectories(shineThrough);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
// create default package domain
|
||||
error = _AddInitialPackageDomain(packages);
|
||||
if (error != B_OK)
|
||||
@ -667,11 +694,6 @@ Volume::Mount(const char* parameterString)
|
||||
if (fPackageLoader < 0)
|
||||
RETURN_ERROR(fPackageLoader);
|
||||
|
||||
// establish shine-through directories
|
||||
error = _CreateShineThroughDirectories(shineThrough);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
// publish the root node
|
||||
fRootDirectory->AcquireReference();
|
||||
error = PublishVNode(fRootDirectory);
|
||||
@ -680,6 +702,11 @@ Volume::Mount(const char* parameterString)
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
// bind and publish the shine-through directories
|
||||
error = _PublishShineThroughDirectories();
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
// run the package loader
|
||||
resume_thread(fPackageLoader);
|
||||
|
||||
@ -1083,6 +1110,7 @@ Volume::_AddPackageContentRootNode(Package* package,
|
||||
do {
|
||||
Node* node;
|
||||
status_t error = _AddPackageNode(directory, packageNode, notify, node);
|
||||
// returns B_OK with a NULL node, when skipping the node
|
||||
if (error != B_OK) {
|
||||
// unlock all directories
|
||||
while (directory != NULL) {
|
||||
@ -1096,14 +1124,16 @@ Volume::_AddPackageContentRootNode(Package* package,
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
// recursive into directory
|
||||
if (PackageDirectory* packageDirectory
|
||||
= dynamic_cast<PackageDirectory*>(packageNode)) {
|
||||
if (packageDirectory->FirstChild() != NULL) {
|
||||
directory = dynamic_cast<Directory*>(node);
|
||||
packageNode = packageDirectory->FirstChild();
|
||||
directory->WriteLock();
|
||||
continue;
|
||||
// recursive into directory, unless we're supposed to skip the node
|
||||
if (node != NULL) {
|
||||
if (PackageDirectory* packageDirectory
|
||||
= dynamic_cast<PackageDirectory*>(packageNode)) {
|
||||
if (packageDirectory->FirstChild() != NULL) {
|
||||
directory = dynamic_cast<Directory*>(node);
|
||||
packageNode = packageDirectory->FirstChild();
|
||||
directory->WriteLock();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1196,8 +1226,11 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode,
|
||||
|
||||
if (node != NULL) {
|
||||
unpackingNode = dynamic_cast<UnpackingNode*>(node);
|
||||
if (unpackingNode == NULL)
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
if (unpackingNode == NULL) {
|
||||
_node = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
oldPackageNode = unpackingNode->GetPackageNode();
|
||||
} else {
|
||||
status_t error = _CreateUnpackingNode(packageNode->Mode(), directory,
|
||||
packageNode->Name(), unpackingNode);
|
||||
@ -1205,7 +1238,6 @@ Volume::_AddPackageNode(Directory* directory, PackageNode* packageNode,
|
||||
RETURN_ERROR(error);
|
||||
|
||||
node = unpackingNode->GetNode();
|
||||
oldPackageNode = unpackingNode->GetPackageNode();
|
||||
newNode = true;
|
||||
}
|
||||
|
||||
@ -1356,7 +1388,7 @@ Volume::_CreateUnpackingNode(mode_t mode, Directory* parent, const char* name,
|
||||
|
||||
fNodes.Insert(node);
|
||||
nodeReference.Detach();
|
||||
// we keep the initial node reference for this table
|
||||
// we keep the initial node reference for the table
|
||||
|
||||
_node = unpackingNode;
|
||||
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
|
||||
Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
||||
{
|
||||
@ -1582,9 +1639,38 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
||||
if (directories == NULL)
|
||||
return B_OK;
|
||||
|
||||
// iterate through the directory list, create the directories, and bind them
|
||||
// to the mount point subdirectories
|
||||
// iterate through the directory list and create the 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
|
||||
struct vnode* vnode;
|
||||
status_t error = vfs_entry_ref_to_vnode(fMountPoint.deviceID,
|
||||
@ -1592,6 +1678,7 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
||||
if (error != B_OK) {
|
||||
dprintf("packagefs: Failed to get shine-through directory \"%s\": "
|
||||
"%s\n", directoryName, strerror(error));
|
||||
_RemoveNode(directory);
|
||||
continue;
|
||||
}
|
||||
CObjectDeleter<struct vnode> vnodePutter(vnode, &vfs_put_vnode);
|
||||
@ -1602,35 +1689,29 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting)
|
||||
if (error != B_OK) {
|
||||
dprintf("packagefs: Failed to stat shine-through directory \"%s\": "
|
||||
"%s\n", directoryName, strerror(error));
|
||||
_RemoveNode(directory);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
dprintf("packagefs: Shine-through entry \"%s\" is not a "
|
||||
"directory\n", directoryName);
|
||||
_RemoveNode(directory);
|
||||
continue;
|
||||
}
|
||||
|
||||
// create the directory
|
||||
UnpackingNode* 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);
|
||||
// publish the vnode, so the VFS will find it without asking us
|
||||
error = PublishVNode(directory);
|
||||
if (error != B_OK) {
|
||||
_RemoveNode(directoryNode);
|
||||
_RemoveNode(directory);
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
// bind the directory
|
||||
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
|
||||
// vfs_bind_mount_directory() got one
|
||||
|
||||
|
@ -111,6 +111,7 @@ private:
|
||||
struct PackageLoaderErrorOutput;
|
||||
struct PackageLoaderContentHandler;
|
||||
struct DomainDirectoryListener;
|
||||
struct ShineThroughDirectory;
|
||||
|
||||
friend struct AddPackageDomainJob;
|
||||
friend struct DomainDirectoryEventJob;
|
||||
@ -175,8 +176,11 @@ private:
|
||||
const char* name, bool notify);
|
||||
|
||||
status_t _InitMountType(const char* mountType);
|
||||
status_t _CreateShineThroughDirectory(Directory* parent,
|
||||
const char* name, Directory*& _directory);
|
||||
status_t _CreateShineThroughDirectories(
|
||||
const char* shineThroughSetting);
|
||||
status_t _PublishShineThroughDirectories();
|
||||
|
||||
status_t _AddPackageLinksDirectory();
|
||||
void _RemovePackageLinksDirectory();
|
||||
|
Loading…
Reference in New Issue
Block a user