[haiku-commits] BRANCH HaikuPM-github.package-management - src/kits/package headers/os/package src/servers/package headers/private/package

  • From: HaikuPM-github.package-management <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 14 Apr 2013 17:15:32 +0200 (CEST)

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, &micro);
+       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;
 };
 
 


Other related posts:

  • » [haiku-commits] BRANCH HaikuPM-github.package-management - src/kits/package headers/os/package src/servers/package headers/private/package - HaikuPM-github . package-management