diff --git a/src/add-ons/kernel/file_systems/packagefs/Jamfile b/src/add-ons/kernel/file_systems/packagefs/Jamfile index 2c28c97616..757707b913 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Jamfile +++ b/src/add-ons/kernel/file_systems/packagefs/Jamfile @@ -23,6 +23,7 @@ HAIKU_PACKAGE_FS_SOURCES = PackageFile.cpp PackageFSRoot.cpp PackageLeafNode.cpp + PackageLinksDirectory.cpp PackageNode.cpp PackageNodeAttribute.cpp PackageSymlink.cpp diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp index e91adafa05..923c23df4c 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.cpp @@ -11,6 +11,10 @@ #include #include "DebugSupport.h" +#include "PackageLinksDirectory.h" + + +static const char* const kPackageLinksDirectoryName = "package-links"; mutex PackageFSRoot::sRootListLock = MUTEX_INITIALIZER("packagefs root list"); @@ -21,7 +25,8 @@ PackageFSRoot::PackageFSRoot(dev_t deviceID, ino_t nodeID) : fDeviceID(deviceID), fNodeID(nodeID), - fSystemVolume(NULL) + fSystemVolume(NULL), + fPackageLinksDirectory(NULL) { rw_lock_init(&fLock, "packagefs root"); } @@ -53,6 +58,15 @@ PackageFSRoot::Init() if (error != B_OK) RETURN_ERROR(error); + // create package links directory + fPackageLinksDirectory = new(std::nothrow) PackageLinksDirectory; + if (fPackageLinksDirectory == NULL) + return B_NO_MEMORY; + + error = fPackageLinksDirectory->Init(NULL, kPackageLinksDirectoryName); + if (error != B_OK) + RETURN_ERROR(error); + return B_OK; } diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.h b/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.h index 9f08229971..bca3f11b61 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageFSRoot.h @@ -17,6 +17,9 @@ #include "Volume.h" +class PackageLinksDirectory; + + class PackageFSRoot : private BReferenceable, public DoublyLinkedListLinkImpl { public: @@ -45,6 +48,8 @@ public: bool IsCustom() const { return fDeviceID < 0; } Volume* SystemVolume() const; + PackageLinksDirectory* GetPackageLinksDirectory() const + { return fPackageLinksDirectory; } private: typedef DoublyLinkedList RootList; @@ -69,6 +74,7 @@ private: VolumeList fVolumes; Volume* fSystemVolume; PackageFamilyHashTable fPackageFamilies; + PackageLinksDirectory* fPackageLinksDirectory; }; diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp new file mode 100644 index 0000000000..29a544068f --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + + +#include "PackageLinksDirectory.h" + +#include "AttributeDirectoryCookie.h" + + +namespace { + +class EmptyAttributeDirectoryCookie : public AttributeDirectoryCookie { +public: + virtual status_t Close() + { + return B_OK; + } + + virtual status_t Read(dev_t volumeID, ino_t nodeID, struct dirent* buffer, + size_t bufferSize, uint32* _count) + { + *_count = 0; + return B_OK; + } + + virtual status_t Rewind() + { + return B_OK; + } +}; + + +} // unnamed namespace + + +PackageLinksDirectory::PackageLinksDirectory() + : + Directory(0) + // the ID needs to be assigned later, when added to a volume +{ + bigtime_t timeMicros = real_time_clock_usecs(); + + fModifiedTime.tv_sec = timeMicros / 1000000; + fModifiedTime.tv_nsec = (timeMicros % 1000000) * 1000; +} + + +PackageLinksDirectory::~PackageLinksDirectory() +{ +} + + +status_t +PackageLinksDirectory::Init(Directory* parent, const char* name) +{ + return Directory::Init(parent, name); +} + + +mode_t +PackageLinksDirectory::Mode() const +{ + return S_IFDIR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; +} + + +uid_t +PackageLinksDirectory::UserID() const +{ + return 0; +} + + +gid_t +PackageLinksDirectory::GroupID() const +{ + return 0; +} + + +timespec +PackageLinksDirectory::ModifiedTime() const +{ + return fModifiedTime; +} + + +off_t +PackageLinksDirectory::FileSize() const +{ + return 0; +} + + +status_t +PackageLinksDirectory::OpenAttributeDirectory( + AttributeDirectoryCookie*& _cookie) +{ + AttributeDirectoryCookie* cookie + = new(std::nothrow) EmptyAttributeDirectoryCookie; + if (cookie == NULL) + return B_NO_MEMORY; + + _cookie = cookie; + return B_OK; +} + + +status_t +PackageLinksDirectory::OpenAttribute(const char* name, int openMode, + AttributeCookie*& _cookie) +{ + return B_ENTRY_NOT_FOUND; +} diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.h new file mode 100644 index 0000000000..44b583efbc --- /dev/null +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinksDirectory.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef PACKAGE_LINKS_DIRECTORY_H +#define PACKAGE_LINKS_DIRECTORY_H + + +#include "Directory.h" + + +class PackageLinksDirectory : public Directory { +public: + PackageLinksDirectory(); + virtual ~PackageLinksDirectory(); + + virtual status_t Init(Directory* parent, const char* name); + + virtual mode_t Mode() const; + virtual uid_t UserID() const; + virtual gid_t GroupID() const; + virtual timespec ModifiedTime() const; + virtual off_t FileSize() const; + + virtual status_t OpenAttributeDirectory( + AttributeDirectoryCookie*& _cookie); + virtual status_t OpenAttribute(const char* name, int openMode, + AttributeCookie*& _cookie); + +private: + timespec fModifiedTime; +}; + + +#endif // PACKAGE_LINKS_DIRECTORY_H diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp index 4672543f97..6d14b6f330 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.cpp @@ -35,6 +35,7 @@ #include "PackageDirectory.h" #include "PackageFile.h" #include "PackageFSRoot.h" +#include "PackageLinksDirectory.h" #include "PackageSymlink.h" #include "Resolvable.h" #include "UnpackingLeafNode.h" @@ -447,8 +448,12 @@ Volume::~Volume() node = next; } - if (fPackageFSRoot != NULL) + if (fPackageFSRoot != NULL) { + if (this == fPackageFSRoot->SystemVolume()) + _RemovePackageLinksDirectory(); + fPackageFSRoot->UnregisterVolume(this); + } if (fRootDirectory != NULL) fRootDirectory->ReleaseReference(); @@ -1375,6 +1380,37 @@ Volume::_CreateShineThroughDirectories(const char* shineThroughSetting) status_t Volume::_AddPackageLinksDirectory() { -// TODO:... + // called when mounting, so we don't need to lock the volume + + PackageLinksDirectory* packageLinksDirectory + = fPackageFSRoot->GetPackageLinksDirectory(); + + NodeWriteLocker rootDirectoryWriteLocker(fRootDirectory); + NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory); + + packageLinksDirectory->SetID(fNextNodeID++); + packageLinksDirectory->SetParent(fRootDirectory); + + fRootDirectory->AddChild(packageLinksDirectory); + fNodes.Insert(packageLinksDirectory); + packageLinksDirectory->AcquireReference(); + return B_OK; } + + +void +Volume::_RemovePackageLinksDirectory() +{ + PackageLinksDirectory* packageLinksDirectory + = fPackageFSRoot->GetPackageLinksDirectory(); + + VolumeWriteLocker volumeLocker(this); + NodeWriteLocker rootDirectoryWriteLocker(fRootDirectory); + NodeWriteLocker packageLinksDirectoryWriteLocker(packageLinksDirectory); + + if (packageLinksDirectory->Parent() == fRootDirectory) { + _RemoveNode(packageLinksDirectory); + packageLinksDirectory->SetParent(NULL); + } +} diff --git a/src/add-ons/kernel/file_systems/packagefs/Volume.h b/src/add-ons/kernel/file_systems/packagefs/Volume.h index e7e5a3a867..7dc209f4af 100644 --- a/src/add-ons/kernel/file_systems/packagefs/Volume.h +++ b/src/add-ons/kernel/file_systems/packagefs/Volume.h @@ -144,7 +144,10 @@ private: status_t _InitMountType(const char* mountType); status_t _CreateShineThroughDirectories( const char* shineThroughSetting); + status_t _AddPackageLinksDirectory(); + void _RemovePackageLinksDirectory(); + private: mutable rw_lock fLock; fs_volume* fFSVolume;