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:
Ingo Weinhold
2011-07-17 16:55:19 +02:00
parent f361dbbe99
commit 6c9fa46136
2 changed files with 117 additions and 32 deletions
@@ -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();