added 4 changesets to branch 'refs/remotes/HaikuPM-github/package-management' old head: bbb2dc237a6a82b22dc0a93542078e39b2046d17 new head: e6216e372af01cc90339fe7afb70c113c99974bd overview: https://github.com/haiku/HaikuPM/compare/bbb2dc2...e6216e3 ---------------------------------------------------------------------------- 8a4ebe2: Make BPackageInfo archivable b2d96da: BPackageInfoSet::Iterator: Fix NULL pointer dereference Since the BPackageInfoSet's map is created lazily, it can be NULL when an Iterator is constructed. d7d9497: Add BInstallationLocationInfo e6216e3: Implement getting a BInstallationLocationInfo * Rename PackageDaemonDefs.h to DaemonDefs.h. * Replace the MESSAGE_GET_PACKAGES by the new B_MESSAGE_GET_INSTALLATION_LOCATION_INFO, which not only returns the packages, but also other information about the installation location. * daemon: Volume: Implement a change count which is bumped whenever packages are activated/deactivated/added/removed. Cache the reply for a location info request, using the change count to check whether it is still up-to-date. * Add private BDaemonClient for communication with the daemon. * BRoster: - Add GetInstallationLocationInfo() using BDaemonClient. - Reimplement GetActivePackages(), using GetInstallationLocationInfo(). [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 20 files changed, 1055 insertions(+), 146 deletions(-) .../build/os/package/InstallationLocationInfo.h | 1 + headers/os/package/InstallationLocationInfo.h | 59 +++ headers/os/package/PackageInfo.h | 55 ++- headers/os/package/PackageInfoSet.h | 3 +- headers/os/package/PackageRoster.h | 4 + headers/private/package/DaemonClient.h | 49 ++ headers/private/package/DaemonDefs.h | 46 ++ headers/private/package/PackageDaemonDefs.h | 37 -- src/build/libpackage/Jamfile | 1 + src/kits/package/DaemonClient.cpp | 137 ++++++ src/kits/package/InstallationLocationInfo.cpp | 131 +++++ src/kits/package/Jamfile | 2 + src/kits/package/PackageInfo.cpp | 487 ++++++++++++++++++- src/kits/package/PackageInfoSet.cpp | 10 +- src/kits/package/PackageRoster.cpp | 79 +-- src/servers/package/PackageDaemon.cpp | 8 +- src/servers/package/Root.cpp | 18 +- src/servers/package/Root.h | 9 +- src/servers/package/Volume.cpp | 58 ++- src/servers/package/Volume.h | 7 +- ############################################################################ Commit: 8a4ebe2c469333d0cabc9a9a6d353d4b42f61d6c Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sun Apr 14 12:09:11 2013 UTC Make BPackageInfo archivable ---------------------------------------------------------------------------- diff --git a/headers/os/package/PackageInfo.h b/headers/os/package/PackageInfo.h index 4d9e3f5..1a34a38 100644 --- a/headers/os/package/PackageInfo.h +++ b/headers/os/package/PackageInfo.h @@ -6,6 +6,7 @@ #define _PACKAGE__PACKAGE_INFO_H_ +#include <Archivable.h> #include <ObjectList.h> #include <String.h> #include <StringList.h> @@ -31,7 +32,7 @@ namespace BPackageKit { * these elements have been parsed from a ".PackageInfo" file. * Alternatively, they can be read from an existing package file. */ -class BPackageInfo { +class BPackageInfo : public BArchivable { public: struct ParseErrorListener { virtual ~ParseErrorListener(); @@ -40,7 +41,9 @@ public: public: BPackageInfo(); - ~BPackageInfo(); + BPackageInfo(BMessage* archive, + status_t* _error = NULL); + virtual ~BPackageInfo(); status_t ReadFromConfigFile( const BEntry& packageInfoEntry, @@ -137,6 +140,10 @@ public: void Clear(); + virtual status_t Archive(BMessage* archive, + bool deep = true) const; + static BArchivable* Instantiate(BMessage* archive); + status_t GetConfigString(BString& _string) const; BString ToString() const; @@ -157,6 +164,36 @@ private: class Parser; friend class Parser; struct StringBuilder; + struct FieldName; + + typedef BObjectList<BPackageResolvable> ResolvableList; + typedef BObjectList<BPackageResolvableExpression> + ResolvableExpressionList; + +private: + static status_t _AddVersion(BMessage* archive, + const char* field, + const BPackageVersion& version); + static status_t _AddStringList(BMessage* archive, + const char* field, const BStringList& list); + static status_t _AddResolvables(BMessage* archive, + const char* field, + const ResolvableList& resolvables); + static status_t _AddResolvableExpressions(BMessage* archive, + const char* field, + const ResolvableExpressionList& + expressions); + static status_t _ExtractVersion(BMessage* archive, + const char* field, int32 index, + BPackageVersion& _version); + static status_t _ExtractStringList(BMessage* archive, + const char* field, BStringList& _list); + static status_t _ExtractResolvables(BMessage* archive, + const char* field, + ResolvableList& _resolvables); + static status_t _ExtractResolvableExpressions(BMessage* archive, + const char* field, + ResolvableExpressionList& _expressions); private: BString fName; @@ -167,7 +204,7 @@ private: uint32 fFlags; - BPackageArchitecture fArchitecture; + BPackageArchitecture fArchitecture; BPackageVersion fVersion; @@ -176,14 +213,12 @@ private: BStringList fURLList; BStringList fSourceURLList; - BObjectList<BPackageResolvable> fProvidesList; - - BObjectList<BPackageResolvableExpression> fRequiresList; - BObjectList<BPackageResolvableExpression> fSupplementsList; - - BObjectList<BPackageResolvableExpression> fConflictsList; + ResolvableList fProvidesList; - BObjectList<BPackageResolvableExpression> fFreshensList; + ResolvableExpressionList fRequiresList; + ResolvableExpressionList fSupplementsList; + ResolvableExpressionList fConflictsList; + ResolvableExpressionList fFreshensList; BStringList fReplacesList; diff --git a/src/kits/package/PackageInfo.cpp b/src/kits/package/PackageInfo.cpp index 4a1ae56..6ff7cf9 100644 --- a/src/kits/package/PackageInfo.cpp +++ b/src/kits/package/PackageInfo.cpp @@ -1098,12 +1098,58 @@ private: }; -// #pragma mark - BPackageInfo +// #pragma mark - FieldName + + +struct BPackageInfo::FieldName { + FieldName(const char* prefix, const char* suffix) + { + size_t prefixLength = strlen(prefix); + size_t suffixLength = strlen(suffix); + if (prefixLength + suffixLength >= sizeof(fFieldName)) { + fFieldName[0] = '\0'; + return; + } + + memcpy(fFieldName, prefix, prefixLength); + memcpy(fFieldName + prefixLength, suffix, suffixLength); + fFieldName[prefixLength + suffixLength] = '\0'; + } + + bool ReplaceSuffix(size_t prefixLength, const char* suffix) + { + size_t suffixLength = strlen(suffix); + if (prefixLength + suffixLength >= sizeof(fFieldName)) { + fFieldName[0] = '\0'; + return false; + } + + memcpy(fFieldName + prefixLength, suffix, suffixLength); + fFieldName[prefixLength + suffixLength] = '\0'; + return true; + } + bool IsValid() const + { + return fFieldName[0] != '\0'; + } + + operator const char*() + { + return fFieldName; + } + +private: + char fFieldName[64]; +}; + + +// #pragma mark - BPackageInfo BPackageInfo::BPackageInfo() : + BArchivable(), fFlags(0), fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT), fCopyrightList(5), @@ -1120,6 +1166,65 @@ BPackageInfo::BPackageInfo() } +BPackageInfo::BPackageInfo(BMessage* archive, status_t* _error) + : + BArchivable(archive), + fFlags(0), + fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT), + fCopyrightList(5), + fLicenseList(5), + fURLList(5), + fSourceURLList(5), + fProvidesList(20, true), + fRequiresList(20, true), + fSupplementsList(20, true), + fConflictsList(5, true), + fFreshensList(5, true), + fReplacesList(5) +{ + status_t error; + int32 architecture; + if ((error = archive->FindString("name", &fName)) == B_OK + && (error = archive->FindString("summary", &fSummary)) == B_OK + && (error = archive->FindString("description", &fDescription)) == B_OK + && (error = archive->FindString("vendor", &fVendor)) == B_OK + && (error = archive->FindString("packager", &fPackager)) == B_OK + && (error = archive->FindUInt32("flags", &fFlags)) == B_OK + && (error = archive->FindInt32("architecture", &architecture)) == B_OK + && (error = _ExtractVersion(archive, "version", 0, fVersion)) == B_OK + && (error = _ExtractStringList(archive, "copyrights", fCopyrightList)) + == B_OK + && (error = _ExtractStringList(archive, "licenses", fLicenseList)) + == B_OK + && (error = _ExtractStringList(archive, "urls", fURLList)) == B_OK + && (error = _ExtractStringList(archive, "source-urls", fSourceURLList)) + == B_OK + && (error = _ExtractResolvables(archive, "provides", fProvidesList)) + == B_OK + && (error = _ExtractResolvableExpressions(archive, "requires", + fRequiresList)) == B_OK + && (error = _ExtractResolvableExpressions(archive, "supplements", + fSupplementsList)) == B_OK + && (error = _ExtractResolvableExpressions(archive, "conflicts", + fConflictsList)) == B_OK + && (error = _ExtractResolvableExpressions(archive, "freshens", + fFreshensList)) == B_OK + && (error = _ExtractStringList(archive, "replaces", fReplacesList)) + == B_OK + && (error = archive->FindString("checksum", &fChecksum)) == B_OK + && (error = archive->FindString("install-path", &fInstallPath)) == B_OK) { + if (architecture >= 0 + || architecture <= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { + fArchitecture = (BPackageArchitecture)architecture; + } else + error = B_BAD_DATA; + } + + if (_error != NULL) + *_error = error; +} + + BPackageInfo::~BPackageInfo() { } @@ -1625,6 +1730,55 @@ BPackageInfo::Clear() status_t +BPackageInfo::Archive(BMessage* archive, bool deep) const +{ + status_t error = BArchivable::Archive(archive, deep); + if (error != B_OK) + return error; + + if ((error = archive->AddString("name", fName)) != B_OK + || (error = archive->AddString("summary", fSummary)) != B_OK + || (error = archive->AddString("description", fDescription)) != B_OK + || (error = archive->AddString("vendor", fVendor)) != B_OK + || (error = archive->AddString("packager", fPackager)) != B_OK + || (error = archive->AddUInt32("flags", fFlags)) != B_OK + || (error = archive->AddInt32("architecture", fArchitecture)) != B_OK + || (error = _AddVersion(archive, "version", fVersion)) != B_OK + || (error = _AddStringList(archive, "copyrights", fCopyrightList)) + != B_OK + || (error = _AddStringList(archive, "licenses", fLicenseList)) != B_OK + || (error = _AddStringList(archive, "urls", fURLList)) != B_OK + || (error = _AddStringList(archive, "source-urls", fSourceURLList)) + != B_OK + || (error = _AddResolvables(archive, "provides", fProvidesList)) != B_OK + || (error = _AddResolvableExpressions(archive, "requires", + fRequiresList)) != B_OK + || (error = _AddResolvableExpressions(archive, "supplements", + fSupplementsList)) != B_OK + || (error = _AddResolvableExpressions(archive, "conflicts", + fConflictsList)) != B_OK + || (error = _AddResolvableExpressions(archive, "freshens", + fFreshensList)) != B_OK + || (error = _AddStringList(archive, "replaces", fReplacesList)) != B_OK + || (error = archive->AddString("checksum", fChecksum)) != B_OK + || (error = archive->AddString("install-path", fInstallPath)) != B_OK) { + return error; + } + + return B_OK; +} + + +/*static*/ BArchivable* +BPackageInfo::Instantiate(BMessage* archive) +{ + if (validate_instantiation(archive, "BPackageInfo")) + return new(std::nothrow) BPackageInfo(archive); + return NULL; +} + + +status_t BPackageInfo::GetConfigString(BString& _string) const { return StringBuilder() @@ -1683,4 +1837,335 @@ BPackageInfo::ParseVersionString(const BString& string, bool releaseIsOptional, } +/*static*/ status_t +BPackageInfo::_AddVersion(BMessage* archive, const char* field, + const BPackageVersion& version) +{ + // Storing BPackageVersion::ToString() would be nice, but the corresponding + // constructor only works for valid versions and we might want to store + // invalid versions as well. + + // major + size_t fieldLength = strlen(field); + FieldName fieldName(field, ":major"); + if (!fieldName.IsValid()) + return B_BAD_VALUE; + + status_t error = archive->AddString(fieldName, version.Major()); + if (error != B_OK) + return error; + + // minor + if (!fieldName.ReplaceSuffix(fieldLength, ":minor")) + return B_BAD_VALUE; + + error = archive->AddString(fieldName, version.Minor()); + if (error != B_OK) + return error; + + // micro + if (!fieldName.ReplaceSuffix(fieldLength, ":micro")) + return B_BAD_VALUE; + + error = archive->AddString(fieldName, version.Micro()); + if (error != B_OK) + return error; + + // pre-release + if (!fieldName.ReplaceSuffix(fieldLength, ":pre")) + return B_BAD_VALUE; + + error = archive->AddString(fieldName, version.PreRelease()); + if (error != B_OK) + return error; + + // revision + if (!fieldName.ReplaceSuffix(fieldLength, ":revision")) + return B_BAD_VALUE; + + return archive->AddUInt8(fieldName, version.Release()); +} + + +/*static*/ status_t +BPackageInfo::_AddStringList(BMessage* archive, const char* field, + const BStringList& list) +{ + int32 count = list.CountStrings(); + for (int32 i = 0; i < count; i++) { + status_t error = archive->AddString(field, list.StringAt(i)); + if (error != B_OK) + return error; + } + + return B_OK; +} + + +/*static*/ status_t +BPackageInfo::_AddResolvables(BMessage* archive, const char* field, + const ResolvableList& resolvables) +{ + // construct the field names we need + FieldName nameField(field, ":name"); + FieldName typeField(field, ":type"); + FieldName versionField(field, ":version"); + FieldName compatibleVersionField(field, ":compat"); + + if (!nameField.IsValid() || !typeField.IsValid() || !versionField.IsValid() + || !compatibleVersionField.IsValid()) { + return B_BAD_VALUE; + } + + // add fields + int32 count = resolvables.CountItems(); + for (int32 i = 0; i < count; i++) { + const BPackageResolvable* resolvable = resolvables.ItemAt(i); + status_t error; + if ((error = archive->AddString(nameField, resolvable->Name())) != B_OK + || (error = archive->AddInt32(typeField, resolvable->Type())) + != B_OK + || (error = _AddVersion(archive, versionField, + resolvable->Version())) != B_OK + || (error = _AddVersion(archive, compatibleVersionField, + resolvable->CompatibleVersion())) != B_OK) { + return error; + } + } + + return B_OK; +} + + +/*static*/ status_t +BPackageInfo::_AddResolvableExpressions(BMessage* archive, const char* field, + const ResolvableExpressionList& expressions) +{ + // construct the field names we need + FieldName nameField(field, ":name"); + FieldName operatorField(field, ":operator"); + FieldName versionField(field, ":version"); + + if (!nameField.IsValid() || !operatorField.IsValid() + || !versionField.IsValid()) { + return B_BAD_VALUE; + } + + // add fields + int32 count = expressions.CountItems(); + for (int32 i = 0; i < count; i++) { + const BPackageResolvableExpression* expression = expressions.ItemAt(i); + status_t error; + if ((error = archive->AddString(nameField, expression->Name())) != B_OK + || (error = archive->AddInt32(operatorField, + expression->Operator())) != B_OK + || (error = _AddVersion(archive, versionField, + expression->Version())) != B_OK) { + return error; + } + } + + return B_OK; +} + + +/*static*/ status_t +BPackageInfo::_ExtractVersion(BMessage* archive, const char* field, int32 index, + BPackageVersion& _version) +{ + // major + size_t fieldLength = strlen(field); + FieldName fieldName(field, ":major"); + if (!fieldName.IsValid()) + return B_BAD_VALUE; + + BString major; + status_t error = archive->FindString(fieldName, index, &major); + if (error != B_OK) + return error; + + // minor + if (!fieldName.ReplaceSuffix(fieldLength, ":minor")) + return B_BAD_VALUE; + + BString minor; + error = archive->FindString(fieldName, index, &minor); + if (error != B_OK) + return error; + + // micro + if (!fieldName.ReplaceSuffix(fieldLength, ":micro")) + return B_BAD_VALUE; + + BString micro; + error = archive->FindString(fieldName, index, µ); + if (error != B_OK) + return error; + + // pre-release + if (!fieldName.ReplaceSuffix(fieldLength, ":pre")) + return B_BAD_VALUE; + + BString preRelease; + error = archive->FindString(fieldName, index, &preRelease); + if (error != B_OK) + return error; + + // revision + if (!fieldName.ReplaceSuffix(fieldLength, ":revision")) + return B_BAD_VALUE; + + uint8 revision; + error = archive->FindUInt8(fieldName, index, &revision); + if (error != B_OK) + return error; + + _version.SetTo(major, minor, micro, preRelease, revision); + return B_OK; +} + + +/*static*/ status_t +BPackageInfo::_ExtractStringList(BMessage* archive, const char* field, + BStringList& _list) +{ + // get the number of items + type_code type; + int32 count; + if (archive->GetInfo(field, &type, &count)) { + // the field is missing + return B_OK; + } + if (type != B_STRING_TYPE) + return B_BAD_DATA; + + for (int32 i = 0; i < count; i++) { + BString string; + status_t error = archive->FindString(field, i, &string); + if (error != B_OK) + return error; + if (!_list.Add(string)) + return B_NO_MEMORY; + } + + return B_OK; +} + + +/*static*/ status_t +BPackageInfo::_ExtractResolvables(BMessage* archive, const char* field, + ResolvableList& _resolvables) +{ + // construct the field names we need + FieldName nameField(field, ":name"); + FieldName typeField(field, ":type"); + FieldName versionField(field, ":version"); + FieldName compatibleVersionField(field, ":compat"); + + if (!nameField.IsValid() || !typeField.IsValid() || !versionField.IsValid() + || !compatibleVersionField.IsValid()) { + return B_BAD_VALUE; + } + + // get the number of items + type_code type; + int32 count; + if (archive->GetInfo(nameField, &type, &count)) { + // the field is missing + return B_OK; + } + + // extract fields + for (int32 i = 0; i < count; i++) { + BString name; + status_t error = archive->FindString(nameField, i, &name); + if (error != B_OK) + return error; + + int32 type; + error = archive->FindInt32(typeField, i, &type); + if (error != B_OK) + return error; + if (type < 0 || type > B_PACKAGE_RESOLVABLE_TYPE_ENUM_COUNT) + return B_BAD_DATA; + + BPackageVersion version; + error = _ExtractVersion(archive, versionField, i, version); + if (error != B_OK) + return error; + + BPackageVersion compatibleVersion; + error = _ExtractVersion(archive, compatibleVersionField, i, + compatibleVersion); + if (error != B_OK) + return error; + + BPackageResolvable* resolvable = new(std::nothrow) BPackageResolvable( + name, (BPackageResolvableType)type, version, compatibleVersion); + if (resolvable == NULL || !_resolvables.AddItem(resolvable)) { + delete resolvable; + return B_NO_MEMORY; + } + } + + return B_OK; +} + + +/*static*/ status_t +BPackageInfo::_ExtractResolvableExpressions(BMessage* archive, + const char* field, ResolvableExpressionList& _expressions) +{ + // construct the field names we need + FieldName nameField(field, ":name"); + FieldName operatorField(field, ":operator"); + FieldName versionField(field, ":version"); + + if (!nameField.IsValid() || !operatorField.IsValid() + || !versionField.IsValid()) { + return B_BAD_VALUE; + } + + // get the number of items + type_code type; + int32 count; + if (archive->GetInfo(nameField, &type, &count)) { + // the field is missing + return B_OK; + } + + // extract fields + for (int32 i = 0; i < count; i++) { + BString name; + status_t error = archive->FindString(nameField, i, &name); + if (error != B_OK) + return error; + + int32 operatorType; + error = archive->FindInt32(operatorField, i, &operatorType); + if (error != B_OK) + return error; + if (operatorType < 0 + | operatorType > B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { + return B_BAD_DATA; + } + + BPackageVersion version; + error = _ExtractVersion(archive, versionField, i, version); + if (error != B_OK) + return error; + + BPackageResolvableExpression* expression + = new(std::nothrow) BPackageResolvableExpression(name, + (BPackageResolvableOperator)operatorType, version); + if (expression == NULL || !_expressions.AddItem(expression)) { + delete expression; + return B_NO_MEMORY; + } + } + + return B_OK; +} + + } // namespace BPackageKit ############################################################################ Commit: b2d96da589896ed9ebb2524f873e9fc0baa650ec Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sun Apr 14 14:47:01 2013 UTC BPackageInfoSet::Iterator: Fix NULL pointer dereference Since the BPackageInfoSet's map is created lazily, it can be NULL when an Iterator is constructed. ---------------------------------------------------------------------------- diff --git a/headers/os/package/PackageInfoSet.h b/headers/os/package/PackageInfoSet.h index 35fbbdc..4a11f55 100644 --- a/headers/os/package/PackageInfoSet.h +++ b/headers/os/package/PackageInfoSet.h @@ -49,8 +49,7 @@ private: class BPackageInfoSet::Iterator { public: - Iterator(); - Iterator(const PackageMap* map); + Iterator(const PackageMap* map = NULL); bool HasNext() const; const BPackageInfo* Next(); diff --git a/src/kits/package/PackageInfoSet.cpp b/src/kits/package/PackageInfoSet.cpp index 997e1dc..f279e67 100644 --- a/src/kits/package/PackageInfoSet.cpp +++ b/src/kits/package/PackageInfoSet.cpp @@ -173,18 +173,10 @@ private: // #pragma mark - Iterator -BPackageInfoSet::Iterator::Iterator() - : - fMap(NULL), - fNextInfo(NULL) -{ -} - - BPackageInfoSet::Iterator::Iterator(const PackageMap* map) : fMap(map), - fNextInfo(map->GetIterator().Next()) + fNextInfo(map != NULL ? map->GetIterator().Next() : NULL) { } ############################################################################ Commit: d7d9497e31047e9cf1c486865d6cbb7df3441487 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sun Apr 14 14:50:30 2013 UTC Add BInstallationLocationInfo ---------------------------------------------------------------------------- diff --git a/headers/build/os/package/InstallationLocationInfo.h b/headers/build/os/package/InstallationLocationInfo.h new file mode 100644 index 0000000..d9e9759 --- /dev/null +++ b/headers/build/os/package/InstallationLocationInfo.h @@ -0,0 +1 @@ +#include <../os/package/InstallationLocationInfo.h> diff --git a/headers/os/package/InstallationLocationInfo.h b/headers/os/package/InstallationLocationInfo.h new file mode 100644 index 0000000..3bdec66 --- /dev/null +++ b/headers/os/package/InstallationLocationInfo.h @@ -0,0 +1,59 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _PACKAGE__INSTALLATION_LOCATION_INFO_H_ +#define _PACKAGE__INSTALLATION_LOCATION_INFO_H_ + + +#include <Node.h> + +#include <package/PackageDefs.h> +#include <package/PackageInfoSet.h> + + +namespace BPackageKit { + + +class BInstallationLocationInfo { +public: + BInstallationLocationInfo(); + ~BInstallationLocationInfo(); + + void Unset(); + + BPackageInstallationLocation Location() const; + void SetLocation( + BPackageInstallationLocation location); + + const node_ref& BaseDirectoryRef() const; + status_t SetBaseDirectoryRef(const node_ref& ref); + + const node_ref& PackagesDirectoryRef() const; + status_t SetPackagesDirectoryRef(const node_ref& ref); + + const BPackageInfoSet& ActivePackageInfos() const; + void SetActivePackageInfos( + const BPackageInfoSet& infos); + + const BPackageInfoSet& InactivePackageInfos() const; + void SetInactivePackageInfos( + const BPackageInfoSet& infos); + + int64 ChangeCount() const; + void SetChangeCount(int64 changeCount); + +private: + BPackageInstallationLocation fLocation; + node_ref fBaseDirectoryRef; + node_ref fPackageDirectoryRef; + BPackageInfoSet fActivePackageInfos; + BPackageInfoSet fInactivePackageInfos; + int64 fChangeCount; +}; + + +} // namespace BPackageKit + + +#endif // _PACKAGE__INSTALLATION_LOCATION_INFO_H_ diff --git a/src/build/libpackage/Jamfile b/src/build/libpackage/Jamfile index 58ce24b..65a24be 100644 --- a/src/build/libpackage/Jamfile +++ b/src/build/libpackage/Jamfile @@ -74,6 +74,7 @@ BuildPlatformSharedLibrary libpackage_build.so Context.cpp DropRepositoryRequest.cpp FetchFileJob.cpp + InstallationLocationInfo.cpp Job.cpp JobQueue.cpp PackageInfo.cpp diff --git a/src/kits/package/InstallationLocationInfo.cpp b/src/kits/package/InstallationLocationInfo.cpp new file mode 100644 index 0000000..6d67d07 --- /dev/null +++ b/src/kits/package/InstallationLocationInfo.cpp @@ -0,0 +1,131 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ + + +#include <package/InstallationLocationInfo.h> + + +namespace BPackageKit { + + +BInstallationLocationInfo::BInstallationLocationInfo() + : + fLocation(B_PACKAGE_INSTALLATION_LOCATION_ENUM_COUNT), + fBaseDirectoryRef(), + fPackageDirectoryRef(), + fActivePackageInfos(), + fInactivePackageInfos(), + fChangeCount(0) +{ +} + + +BInstallationLocationInfo::~BInstallationLocationInfo() +{ +} + + +void +BInstallationLocationInfo::Unset() +{ + fLocation = B_PACKAGE_INSTALLATION_LOCATION_ENUM_COUNT; + fBaseDirectoryRef = node_ref(); + fPackageDirectoryRef = node_ref(); + fActivePackageInfos.MakeEmpty(); + fInactivePackageInfos.MakeEmpty(); + fChangeCount = 0; +} + + +BPackageInstallationLocation +BInstallationLocationInfo::Location() const +{ + return fLocation; +} + + +void +BInstallationLocationInfo::SetLocation(BPackageInstallationLocation location) +{ + fLocation = location; +} + + +const node_ref& +BInstallationLocationInfo::BaseDirectoryRef() const +{ + return fBaseDirectoryRef; +} + + +status_t +BInstallationLocationInfo::SetBaseDirectoryRef(const node_ref& ref) +{ + fBaseDirectoryRef = ref; + return fBaseDirectoryRef == ref ? B_OK : B_NO_MEMORY; +} + + +const node_ref& +BInstallationLocationInfo::PackagesDirectoryRef() const +{ + return fPackageDirectoryRef; +} + + +status_t +BInstallationLocationInfo::SetPackagesDirectoryRef(const node_ref& ref) +{ + fPackageDirectoryRef = ref; + return fPackageDirectoryRef == ref ? B_OK : B_NO_MEMORY; +} + + +const BPackageInfoSet& +BInstallationLocationInfo::ActivePackageInfos() const +{ + return fActivePackageInfos; +} + + +void +BInstallationLocationInfo::SetActivePackageInfos(const BPackageInfoSet& infos) +{ + fActivePackageInfos = infos; +} + + +const BPackageInfoSet& +BInstallationLocationInfo::InactivePackageInfos() const +{ + return fInactivePackageInfos; +} + + +void +BInstallationLocationInfo::SetInactivePackageInfos(const BPackageInfoSet& infos) +{ + fInactivePackageInfos = infos; +} + + +int64 +BInstallationLocationInfo::ChangeCount() const +{ + return fChangeCount; +} + + +void +BInstallationLocationInfo::SetChangeCount(int64 changeCount) +{ + fChangeCount = changeCount; +} + + +} // namespace BPackageKit diff --git a/src/kits/package/Jamfile b/src/kits/package/Jamfile index 338acee..a3c9bed 100644 --- a/src/kits/package/Jamfile +++ b/src/kits/package/Jamfile @@ -53,6 +53,7 @@ SharedLibrary libpackage.so Context.cpp DropRepositoryRequest.cpp FetchFileJob.cpp + InstallationLocationInfo.cpp Job.cpp JobQueue.cpp PackageInfo.cpp ############################################################################ Commit: e6216e372af01cc90339fe7afb70c113c99974bd Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Sun Apr 14 15:04:33 2013 UTC Implement getting a BInstallationLocationInfo * Rename PackageDaemonDefs.h to DaemonDefs.h. * Replace the MESSAGE_GET_PACKAGES by the new B_MESSAGE_GET_INSTALLATION_LOCATION_INFO, which not only returns the packages, but also other information about the installation location. * daemon: Volume: Implement a change count which is bumped whenever packages are activated/deactivated/added/removed. Cache the reply for a location info request, using the change count to check whether it is still up-to-date. * Add private BDaemonClient for communication with the daemon. * BRoster: - Add GetInstallationLocationInfo() using BDaemonClient. - Reimplement GetActivePackages(), using GetInstallationLocationInfo(). ---------------------------------------------------------------------------- diff --git a/headers/os/package/PackageRoster.h b/headers/os/package/PackageRoster.h index d407da7..15487c2 100644 --- a/headers/os/package/PackageRoster.h +++ b/headers/os/package/PackageRoster.h @@ -28,6 +28,7 @@ struct BRepositoryConfigVisitor { }; +class BInstallationLocationInfo; class BPackageInfoSet; class BRepositoryCache; class BRepositoryConfig; @@ -60,6 +61,9 @@ public: status_t GetRepositoryConfig(const BString& name, BRepositoryConfig* repositoryConfig); + status_t GetInstallationLocationInfo( + BPackageInstallationLocation location, + BInstallationLocationInfo& _info); status_t GetActivePackages( BPackageInstallationLocation location, BPackageInfoSet& packageInfos); diff --git a/headers/private/package/DaemonClient.h b/headers/private/package/DaemonClient.h new file mode 100644 index 0000000..e16b3e3 --- /dev/null +++ b/headers/private/package/DaemonClient.h @@ -0,0 +1,49 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ +#ifndef _PACKAGE__PRIVATE__DAEMON_CLIENT_H_ +#define _PACKAGE__PRIVATE__DAEMON_CLIENT_H_ + + +#include <Messenger.h> +#include <package/PackageDefs.h> + + +namespace BPackageKit { + + +class BInstallationLocationInfo; +class BPackageInfoSet; + + +namespace BPrivate { + + +class BDaemonClient { +public: + BDaemonClient(); + ~BDaemonClient(); + + status_t GetInstallationLocationInfo( + BPackageInstallationLocation location, + BInstallationLocationInfo& _info); + +private: + status_t _InitMessenger(); + status_t _ExtractPackageInfoSet(const BMessage& message, + const char* field, BPackageInfoSet& _infos); + +private: + BMessenger fDaemonMessenger; +}; + + +} // namespace BPrivate +} // namespace BPackageKit + + +#endif // _PACKAGE__PRIVATE__DAEMON_CLIENT_H_ diff --git a/headers/private/package/DaemonDefs.h b/headers/private/package/DaemonDefs.h new file mode 100644 index 0000000..3bde3b7 --- /dev/null +++ b/headers/private/package/DaemonDefs.h @@ -0,0 +1,46 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ +#ifndef _PACKAGE__PRIVATE__DAEMON_DEFS_H_ +#define _PACKAGE__PRIVATE__DAEMON_DEFS_H_ + + +namespace BPackageKit { +namespace BPrivate { + + +#define B_PACKAGE_DAEMON_APP_SIGNATURE "application/x-vnd.haiku-package_daemon" + + +enum BDaemonError { + B_DAEMON_OK +}; + + +// message codes for requests to and replies from the daemon +enum { + B_MESSAGE_GET_INSTALLATION_LOCATION_INFO = 'PKLI', + // "location": int32 + // the respective installation location constant + B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY = 'PKLR', + // "base directory device": int32 + // "base directory node": int64 + // "packages directory device": int32 + // "packages directory node": int64 + // "change count": int64 + // "active packages": message[] + // archived BPackageInfos of the active packages + // "inactive packages": message[] + // archived BPackageInfos of the inactive packages +}; + + +#endif // _PACKAGE__PRIVATE__DAEMON_DEFS_H_ + + +} // namespace BPrivate +} // namespace BPackageKit diff --git a/headers/private/package/PackageDaemonDefs.h b/headers/private/package/PackageDaemonDefs.h deleted file mode 100644 index ccb74b7..0000000 --- a/headers/private/package/PackageDaemonDefs.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2013, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Ingo Weinhold <ingo_weinhold@xxxxxx> - */ -#ifndef _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_ -#define _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_ - - -namespace BPackageKit { -namespace BPrivate { - - -#define PACKAGE_DAEMON_APP_SIGNATURE "application/x-vnd.haiku-package_daemon" - - -// message codes for requests to and replies from the daemon -enum { - MESSAGE_GET_PACKAGES = 'PKGG', - // "location": int32 - // the respective installation location constant - MESSAGE_GET_PACKAGES_REPLY = 'PKGR' - // "active packages": string[] - // file names of the active packages (no path) - // "inactive packages": string[] - // file names of the inactive packages (no path) - -}; - - -#endif // _PACKAGE__PRIVATE__PACKAGE_DAEMON_DEFS_H_ - - -} // namespace BPrivate -} // namespace BPackageKit diff --git a/src/kits/package/DaemonClient.cpp b/src/kits/package/DaemonClient.cpp new file mode 100644 index 0000000..10d35c0 --- /dev/null +++ b/src/kits/package/DaemonClient.cpp @@ -0,0 +1,137 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ + + +#include <package/DaemonClient.h> + +#include <package/InstallationLocationInfo.h> +#include <package/PackageInfo.h> + +#include <package/DaemonDefs.h> + + +namespace BPackageKit { +namespace BPrivate { + + +BDaemonClient::BDaemonClient() + : + fDaemonMessenger() +{ +} + + +BDaemonClient::~BDaemonClient() +{ +} + + +status_t +BDaemonClient::GetInstallationLocationInfo( + BPackageInstallationLocation location, BInstallationLocationInfo& _info) +{ + status_t error = _InitMessenger(); + if (error != B_OK) + return error; + + // send the request + BMessage request(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO); + error = request.AddInt32("location", location); + if (error != B_OK) + return error; + + BMessage reply; + fDaemonMessenger.SendMessage(&request, &reply); + if (reply.what != B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY) + return B_ERROR; + + // extract the location info + int32 baseDirectoryDevice; + int64 baseDirectoryNode; + int32 packagesDirectoryDevice; + int64 packagesDirectoryNode; + int64 changeCount; + BPackageInfoSet activePackages; + BPackageInfoSet inactivePackages; + if ((error = reply.FindInt32("base directory device", &baseDirectoryDevice)) + != B_OK + || (error = reply.FindInt64("base directory node", &baseDirectoryNode)) + != B_OK + || (error = reply.FindInt32("packages directory device", + &packagesDirectoryDevice)) != B_OK + || (error = reply.FindInt64("packages directory node", + &packagesDirectoryNode)) != B_OK + || (error = _ExtractPackageInfoSet(reply, "active packages", + activePackages)) != B_OK + || (error = _ExtractPackageInfoSet(reply, "inactive packages", + inactivePackages)) != B_OK + || (error = reply.FindInt64("change count", &changeCount)) != B_OK) { + return error; + } + + _info.Unset(); + _info.SetLocation(location); + _info.SetBaseDirectoryRef(node_ref(baseDirectoryDevice, baseDirectoryNode)); + _info.SetPackagesDirectoryRef( + node_ref(packagesDirectoryDevice, packagesDirectoryNode)); + _info.SetActivePackageInfos(activePackages); + _info.SetInactivePackageInfos(inactivePackages); + _info.SetChangeCount(changeCount); + + return B_OK; +} + + +status_t +BDaemonClient::_InitMessenger() +{ + if (fDaemonMessenger.IsValid()) + return B_OK; + + // get the package daemon's address + status_t error; + fDaemonMessenger = BMessenger(B_PACKAGE_DAEMON_APP_SIGNATURE, -1, &error); + return error; +} + + +status_t +BDaemonClient::_ExtractPackageInfoSet(const BMessage& message, + const char* field, BPackageInfoSet& _infos) +{ + // get the number of items + type_code type; + int32 count; + if (message.GetInfo(field, &type, &count)) { + // the field is missing + return B_OK; + } + if (type != B_MESSAGE_TYPE) + return B_BAD_DATA; + + for (int32 i = 0; i < count; i++) { + BMessage archive; + status_t error = message.FindMessage(field, i, &archive); + if (error != B_OK) + return error; + + BPackageInfo info(&archive, &error); + if (error != B_OK) + return error; + + error = _infos.AddInfo(info); + if (error != B_OK) + return error; + } + + return B_OK; +} + + +} // namespace BPrivate +} // namespace BPackageKit diff --git a/src/kits/package/Jamfile b/src/kits/package/Jamfile index a3c9bed..8ebcc9c 100644 --- a/src/kits/package/Jamfile +++ b/src/kits/package/Jamfile @@ -51,6 +51,7 @@ SharedLibrary libpackage.so BlockBufferCacheNoLock.cpp ChecksumAccessors.cpp Context.cpp + DaemonClient.cpp DropRepositoryRequest.cpp FetchFileJob.cpp InstallationLocationInfo.cpp diff --git a/src/kits/package/PackageRoster.cpp b/src/kits/package/PackageRoster.cpp index 62b4bb9..9e5a3a3 100644 --- a/src/kits/package/PackageRoster.cpp +++ b/src/kits/package/PackageRoster.cpp @@ -19,6 +19,7 @@ #include <String.h> #include <StringList.h> +#include <package/InstallationLocationInfo.h> #include <package/PackageInfo.h> #include <package/PackageInfoContentHandler.h> #include <package/PackageInfoSet.h> @@ -28,7 +29,7 @@ #include <package/hpkg/PackageReader.h> #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) -# include <package/PackageDaemonDefs.h> +# include <package/DaemonClient.h> #endif @@ -189,73 +190,33 @@ BPackageRoster::GetRepositoryConfig(const BString& name, status_t -BPackageRoster::GetActivePackages(BPackageInstallationLocation location, - BPackageInfoSet& packageInfos) +BPackageRoster::GetInstallationLocationInfo( + BPackageInstallationLocation location, BInstallationLocationInfo& _info) { // This method makes sense only on an installed Haiku, but not for the build // tools. #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) - // check the given location - directory_which packagesDirectory; - switch (location) { - case B_PACKAGE_INSTALLATION_LOCATION_SYSTEM: - packagesDirectory = B_SYSTEM_PACKAGES_DIRECTORY; - break; - case B_PACKAGE_INSTALLATION_LOCATION_COMMON: - packagesDirectory = B_COMMON_PACKAGES_DIRECTORY; - break; - case B_PACKAGE_INSTALLATION_LOCATION_HOME: - packagesDirectory = B_USER_PACKAGES_DIRECTORY; - break; - default: - return B_BAD_VALUE; - } - - // get the package daemon's address - status_t error; - BMessenger messenger(PACKAGE_DAEMON_APP_SIGNATURE, -1, &error); - if (error != B_OK) - return error; - - // request a list of packages - BMessage request(BPackageKit::BPrivate::MESSAGE_GET_PACKAGES); - error = request.AddInt32("location", location); - if (error != B_OK) - return error; + return BPackageKit::BPrivate::BDaemonClient().GetInstallationLocationInfo( + location, _info); +#else + return B_NOT_SUPPORTED; +#endif +} - BMessage reply; - messenger.SendMessage(&request, &reply); - if (reply.what != BPackageKit::BPrivate::MESSAGE_GET_PACKAGES_REPLY) - return B_ERROR; - // find and open the packages directory - BPath packagesDirPath; - error = find_directory(packagesDirectory, &packagesDirPath); +status_t +BPackageRoster::GetActivePackages(BPackageInstallationLocation location, + BPackageInfoSet& packageInfos) +{ +// This method makes sense only on an installed Haiku, but not for the build +// tools. +#if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) + BInstallationLocationInfo info; + status_t error = GetInstallationLocationInfo(location, info); if (error != B_OK) return error; - // iterate through the packages - const char* packageFileName; - for (int32 i = 0; - reply.FindString("active packages", i, &packageFileName) == B_OK; i++) { - // get the full package file path - BPath packagePath; - error = packagePath.SetTo(packagesDirPath.Path(), packageFileName); - if (error != B_OK) - continue; - - // read the package info from the file - BPackageInfo info; - error = info.ReadFromPackageFile(packagePath.Path()); - if (error != B_OK || info.InitCheck() != B_OK) - continue; - - // add the info - error = packageInfos.AddInfo(info); - if (error != B_OK) - return error; - } - + packageInfos = info.ActivePackageInfos(); return B_OK; #else return B_NOT_SUPPORTED; diff --git a/src/servers/package/PackageDaemon.cpp b/src/servers/package/PackageDaemon.cpp index e5ebee0..58d76c0 100644 --- a/src/servers/package/PackageDaemon.cpp +++ b/src/servers/package/PackageDaemon.cpp @@ -16,7 +16,7 @@ #include <NodeMonitor.h> #include <AutoDeleter.h> -#include <package/PackageDaemonDefs.h> +#include <package/DaemonDefs.h> #include "DebugSupport.h" #include "Root.h" @@ -28,7 +28,7 @@ using namespace BPackageKit::BPrivate; PackageDaemon::PackageDaemon(status_t* _error) : - BServer(PACKAGE_DAEMON_APP_SIGNATURE, false, _error), + BServer(B_PACKAGE_DAEMON_APP_SIGNATURE, false, _error), fSystemRoot(NULL), fRoots(10, true), fVolumeWatcher() @@ -85,12 +85,12 @@ PackageDaemon::MessageReceived(BMessage* message) break; } - case MESSAGE_GET_PACKAGES: + case B_MESSAGE_GET_INSTALLATION_LOCATION_INFO: { if (fSystemRoot == NULL) break; - fSystemRoot->HandleGetPackagesRequest(DetachCurrentMessage()); + fSystemRoot->HandleGetLocationInfoRequest(DetachCurrentMessage()); break; } diff --git a/src/servers/package/Root.cpp b/src/servers/package/Root.cpp index b2d63b4..fd0c456 100644 --- a/src/servers/package/Root.cpp +++ b/src/servers/package/Root.cpp @@ -42,11 +42,11 @@ private: }; -// #pragma mark - VolumeJob +// #pragma mark - HandleGetLocationInfoRequestJob -struct Root::HandleGetPackagesJob : public Job { - HandleGetPackagesJob(Root* root, BMessage* message) +struct Root::HandleGetLocationInfoRequestJob : public Job { + HandleGetLocationInfoRequestJob(Root* root, BMessage* message) : fRoot(root), fMessage(message) @@ -55,7 +55,7 @@ struct Root::HandleGetPackagesJob : public Job { virtual void Do() { - fRoot->_HandleGetPackagesRequest(fMessage.Get()); + fRoot->_HandleGetLocationInfoRequest(fMessage.Get()); } private: @@ -209,10 +209,10 @@ Root::FindVolume(dev_t deviceID) const void -Root::HandleGetPackagesRequest(BMessage* message) +Root::HandleGetLocationInfoRequest(BMessage* message) { - HandleGetPackagesJob* job - = new(std::nothrow) HandleGetPackagesJob(this, message); + HandleGetLocationInfoRequestJob* job + = new(std::nothrow) HandleGetLocationInfoRequestJob(this, message); if (job == NULL) { delete message; return; @@ -314,7 +314,7 @@ Root::_ProcessNodeMonitorEvents(Volume* volume) void -Root::_HandleGetPackagesRequest(BMessage* message) +Root::_HandleGetLocationInfoRequest(BMessage* message) { int32 location; if (message->FindInt32("location", &location) != B_OK @@ -341,7 +341,7 @@ Root::_HandleGetPackagesRequest(BMessage* message) } if (volume != NULL) - volume->HandleGetPackagesRequest(message); + volume->HandleGetLocationInfoRequest(message); } diff --git a/src/servers/package/Root.h b/src/servers/package/Root.h index ad84421..62aba1b 100644 --- a/src/servers/package/Root.h +++ b/src/servers/package/Root.h @@ -41,7 +41,7 @@ public: Volume* FindVolume(dev_t deviceID) const; - void HandleGetPackagesRequest(BMessage* message); + void HandleGetLocationInfoRequest(BMessage* message); private: // Volume::Listener @@ -52,9 +52,9 @@ protected: private: struct VolumeJob; - struct HandleGetPackagesJob; + struct HandleGetLocationInfoRequestJob; - friend struct HandleGetPackagesJob; + friend struct HandleGetLocationInfoRequestJob; private: Volume** _GetVolume(PackageFSMountType mountType); @@ -63,7 +63,8 @@ private: void _InitPackages(Volume* volume); void _DeleteVolume(Volume* volume); void _ProcessNodeMonitorEvents(Volume* volume); - void _HandleGetPackagesRequest(BMessage* message); + void _HandleGetLocationInfoRequest( + BMessage* message); status_t _QueueJob(Job* job); diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp index abc5732..401d760 100644 --- a/src/servers/package/Volume.cpp +++ b/src/servers/package/Volume.cpp @@ -30,7 +30,7 @@ #include <AutoDeleter.h> #include <AutoLocker.h> -#include <package/PackageDaemonDefs.h> +#include <package/DaemonDefs.h> #include <package/PackagesDirectoryDefs.h> #include "DebugSupport.h" @@ -104,7 +104,9 @@ Volume::Volume(BLooper* looper) fPendingNodeMonitorEventsLock("pending node monitor events"), fPendingNodeMonitorEvents(), fPackagesToBeActivated(), - fPackagesToBeDeactivated() + fPackagesToBeDeactivated(), + fChangeCount(0), + fLocationInfoReply(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY) { looper->AddHandler(this); } @@ -335,20 +337,49 @@ INFORM("Volume::InitialVerify(%p, %p)\n", nextVolume, nextNextVolume); void -Volume::HandleGetPackagesRequest(BMessage* message) +Volume::HandleGetLocationInfoRequest(BMessage* message) { - BMessage reply(MESSAGE_GET_PACKAGES_REPLY); + // If the cached reply message is up-to-date, just send it. + int64 changeCount; + if (fLocationInfoReply.FindInt64("change count", &changeCount) == B_OK + && changeCount == fChangeCount) { + message->SendReply(&fLocationInfoReply, (BHandler*)NULL, + kCommunicationTimeout); + return; + } + + // rebuild the reply message + fLocationInfoReply.MakeEmpty(); + + if (fLocationInfoReply.AddInt32("base directory device", + fRootDirectoryRef.device) != B_OK + || fLocationInfoReply.AddInt64("base directory node", + fRootDirectoryRef.node) != B_OK + || fLocationInfoReply.AddInt32("packages directory device", + fPackagesDirectoryRef.device) != B_OK + || fLocationInfoReply.AddInt64("packages directory node", + fPackagesDirectoryRef.node) != B_OK) { + return; + } for (PackageFileNameHashTable::Iterator it = fPackagesByFileName.GetIterator(); it.HasNext();) { Package* package = it.Next(); const char* fieldName = package->IsActive() ? "active packages" : "inactive packages"; - if (reply.AddString(fieldName, package->FileName()) != B_OK) + BMessage packageArchive; + if (package->Info().Archive(&packageArchive) != B_OK + || fLocationInfoReply.AddMessage(fieldName, &packageArchive) + != B_OK) { return; + } } - message->SendReply(&reply, (BHandler*)NULL, kCommunicationTimeout); + if (fLocationInfoReply.AddInt64("change count", fChangeCount) != B_OK) + return; + + message->SendReply(&fLocationInfoReply, (BHandler*)NULL, + kCommunicationTimeout); } @@ -514,6 +545,7 @@ fPackagesToBeActivated.size(), fPackagesToBeDeactivated.size()); for (PackageSet::iterator it = fPackagesToBeActivated.begin(); it != fPackagesToBeActivated.end(); ++it) { (*it)->SetActive(true); + fChangeCount++; } for (PackageSet::iterator it = fPackagesToBeDeactivated.begin(); @@ -671,8 +703,7 @@ INFORM("Volume::_PackagesEntryCreated(\"%s\")\n", name); return; } - fPackagesByFileName.Insert(package); - fPackagesByNodeRef.Insert(package); + _AddPackage(package); packageDeleter.Detach(); try { @@ -732,10 +763,18 @@ Volume::_FillInActivationChangeItem(PackageFSActivationChangeItem* item, void +Volume::_AddPackage(Package* package) +{ + fPackagesByFileName.Insert(package); + fPackagesByNodeRef.Insert(package); +} + +void Volume::_RemovePackage(Package* package) { fPackagesByFileName.Remove(package); fPackagesByNodeRef.Remove(package); + fChangeCount++; } @@ -762,8 +801,7 @@ Volume::_ReadPackagesDirectory() status_t error = package->Init(entry); if (error == B_OK) { - fPackagesByFileName.Insert(package); - fPackagesByNodeRef.Insert(package); + _AddPackage(package); packageDeleter.Detach(); } } diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h index 404f6c4..8e65ff3 100644 --- a/src/servers/package/Volume.h +++ b/src/servers/package/Volume.h @@ -13,6 +13,7 @@ #include <Handler.h> #include <Locker.h> +#include <Message.h> #include <String.h> #include <package/packagefs.h> @@ -48,7 +49,7 @@ public: bool activeOnly); void InitialVerify(Volume* nextVolume, Volume* nextNextVolume); - void HandleGetPackagesRequest(BMessage* message); + void HandleGetLocationInfoRequest(BMessage* message); void Unmounted(); @@ -105,6 +106,8 @@ private: PackageFSActivationChangeItem* item, PackageFSActivationChangeType type, Package* package, char*& nameBuffer); + + void _AddPackage(Package* package); void _RemovePackage(Package* package); status_t _ReadPackagesDirectory(); @@ -133,6 +136,8 @@ private: NodeMonitorEventList fPendingNodeMonitorEvents; PackageSet fPackagesToBeActivated; PackageSet fPackagesToBeDeactivated; + int64 fChangeCount; + BMessage fLocationInfoReply; };