diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp index eb9879ee72..15701f0866 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.cpp @@ -6,6 +6,9 @@ #include "PackageLinkDirectory.h" +#include +#include + #include #include "EmptyAttributeDirectoryCookie.h" @@ -13,6 +16,126 @@ #include "PackageLinksListener.h" #include "Utils.h" #include "Version.h" +#include "Volume.h" + + +static const char* const kSelfLinkName = ".self"; +static const char* const kSystemLinkPath = "../.."; +static const char* const kCommonLinkPath = "../../../common"; +static const char* const kHomeLinkPath = "../../../home/config"; + + +static const char* +link_path_for_mount_type(MountType type) +{ + switch (type) { + case MOUNT_TYPE_SYSTEM: + return kSystemLinkPath; + case MOUNT_TYPE_COMMON: + return kCommonLinkPath; + case MOUNT_TYPE_HOME: + return kHomeLinkPath; + case MOUNT_TYPE_CUSTOM: + default: + return "?"; + } +} + + +// #pragma mark - SelfLink + + +class PackageLinkDirectory::SelfLink : public Node { +public: + SelfLink(Package* package) + : + Node(0), + fPackage(package), + fLinkPath(link_path_for_mount_type( + package->Domain()->Volume()->MountType())) + { + get_real_time(fModifiedTime); + } + + virtual ~SelfLink() + { + } + + virtual status_t Init(Directory* parent, const char* name) + { + return Node::Init(parent, name); + } + + virtual mode_t Mode() const + { + return S_IFLNK | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH + | S_IXOTH; + } + + virtual uid_t UserID() const + { + return 0; + } + + virtual gid_t GroupID() const + { + return 0; + } + + virtual timespec ModifiedTime() const + { + return fModifiedTime; + } + + virtual off_t FileSize() const + { + return strlen(fLinkPath); + } + + virtual status_t Read(off_t offset, void* buffer, size_t* bufferSize) + { + return B_BAD_VALUE; + } + + virtual status_t Read(io_request* request) + { + return B_BAD_VALUE; + } + + virtual status_t ReadSymlink(void* buffer, size_t* bufferSize) + { + size_t toCopy = std::min(strlen(fLinkPath), *bufferSize); + memcpy(buffer, fLinkPath, toCopy); + *bufferSize = toCopy; + + return B_OK; + } + + virtual status_t OpenAttributeDirectory(AttributeDirectoryCookie*& _cookie) + { + AttributeDirectoryCookie* cookie + = new(std::nothrow) EmptyAttributeDirectoryCookie; + if (cookie == NULL) + return B_NO_MEMORY; + + _cookie = cookie; + return B_OK; + } + + virtual status_t OpenAttribute(const char* name, int openMode, + AttributeCookie*& _cookie) + { + return B_ENTRY_NOT_FOUND; + } + +private: + Package* fPackage; + timespec fModifiedTime; + const char* fLinkPath; +}; + + +// #pragma mark - PackageLinkDirectory PackageLinkDirectory::PackageLinkDirectory() @@ -26,12 +149,25 @@ PackageLinkDirectory::PackageLinkDirectory() PackageLinkDirectory::~PackageLinkDirectory() { + if (fSelfLink != NULL) + fSelfLink->ReleaseReference(); } status_t PackageLinkDirectory::Init(Directory* parent, Package* package) { + // create the self link + fSelfLink = new(std::nothrow) SelfLink(package); + if (fSelfLink == NULL) + return B_NO_MEMORY; + + status_t error = fSelfLink->Init(this, kSelfLinkName); + if (error != B_OK) + RETURN_ERROR(error); + + AddChild(fSelfLink); + // compute the allocation size needed for the versioned name size_t nameLength = strlen(package->Name()); size_t size = nameLength + 1; @@ -55,7 +191,7 @@ PackageLinkDirectory::Init(Directory* parent, Package* package) } // init the directory/node - status_t error = Init(parent, name); + error = Init(parent, name); // TODO: This copies the name unnecessarily! if (error != B_OK) RETURN_ERROR(error); diff --git a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h index 8fbaf8fa4c..b5fa320038 100644 --- a/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h +++ b/src/add-ons/kernel/file_systems/packagefs/PackageLinkDirectory.h @@ -40,9 +40,13 @@ public: bool IsEmpty() const { return fPackages.IsEmpty(); } +private: + class SelfLink; + private: timespec fModifiedTime; PackageList fPackages; + SelfLink* fSelfLink; };