2 * Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Ingo Weinhold <ingo_weinhold@gmx.de>
10 #include <package/DaemonClient.h>
14 #include <Directory.h>
16 #include <package/CommitTransactionResult.h>
17 #include <package/InstallationLocationInfo.h>
18 #include <package/PackageInfo.h>
20 #include <package/ActivationTransaction.h>
21 #include <package/PackagesDirectoryDefs.h>
24 namespace BPackageKit
{
28 BDaemonClient::BDaemonClient()
35 BDaemonClient::~BDaemonClient()
41 BDaemonClient::GetInstallationLocationInfo(
42 BPackageInstallationLocation location
, BInstallationLocationInfo
& _info
)
44 status_t error
= _InitMessenger();
48 BMessage
request(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO
);
49 error
= request
.AddInt32("location", location
);
53 // Get our filesystem root node. If we are in a chroot this is not the same
54 // as the package_daemon root node, so we must provide it.
56 if (stat("/boot", &st
) == 0)
58 error
= request
.AddInt32("volume", st
.st_dev
);
61 error
= request
.AddInt64("root", st
.st_ino
);
68 fDaemonMessenger
.SendMessage(&request
, &reply
);
69 if (reply
.what
!= B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY
)
72 // extract the location info
73 int32 baseDirectoryDevice
;
74 int64 baseDirectoryNode
;
75 int32 packagesDirectoryDevice
;
76 int64 packagesDirectoryNode
;
78 BPackageInfoSet latestActivePackages
;
79 BPackageInfoSet latestInactivePackages
;
80 if ((error
= reply
.FindInt32("base directory device", &baseDirectoryDevice
))
82 || (error
= reply
.FindInt64("base directory node", &baseDirectoryNode
))
84 || (error
= reply
.FindInt32("packages directory device",
85 &packagesDirectoryDevice
)) != B_OK
86 || (error
= reply
.FindInt64("packages directory node",
87 &packagesDirectoryNode
)) != B_OK
88 || (error
= _ExtractPackageInfoSet(reply
, "latest active packages",
89 latestActivePackages
)) != B_OK
90 || (error
= _ExtractPackageInfoSet(reply
, "latest inactive packages",
91 latestInactivePackages
)) != B_OK
92 || (error
= reply
.FindInt64("change count", &changeCount
)) != B_OK
) {
96 BPackageInfoSet currentlyActivePackages
;
97 error
= _ExtractPackageInfoSet(reply
, "currently active packages",
98 currentlyActivePackages
);
99 if (error
!= B_OK
&& error
!= B_NAME_NOT_FOUND
)
102 BString oldStateName
;
103 error
= reply
.FindString("old state", &oldStateName
);
104 if (error
!= B_OK
&& error
!= B_NAME_NOT_FOUND
)
108 _info
.SetLocation(location
);
109 _info
.SetBaseDirectoryRef(node_ref(baseDirectoryDevice
, baseDirectoryNode
));
110 _info
.SetPackagesDirectoryRef(
111 node_ref(packagesDirectoryDevice
, packagesDirectoryNode
));
112 _info
.SetLatestActivePackageInfos(latestActivePackages
);
113 _info
.SetLatestInactivePackageInfos(latestInactivePackages
);
114 _info
.SetCurrentlyActivePackageInfos(currentlyActivePackages
);
115 _info
.SetOldStateName(oldStateName
);
116 _info
.SetChangeCount(changeCount
);
123 BDaemonClient::CommitTransaction(const BActivationTransaction
& transaction
,
124 BCommitTransactionResult
& _result
)
126 if (transaction
.InitCheck() != B_OK
)
129 status_t error
= _InitMessenger();
134 BMessage
request(B_MESSAGE_COMMIT_TRANSACTION
);
135 error
= transaction
.Archive(&request
);
140 fDaemonMessenger
.SendMessage(&request
, &reply
);
141 if (reply
.what
!= B_MESSAGE_COMMIT_TRANSACTION_REPLY
)
144 // extract the result
145 return _result
.ExtractFromMessage(reply
);
150 BDaemonClient::CreateTransaction(BPackageInstallationLocation location
,
151 BActivationTransaction
& _transaction
, BDirectory
& _transactionDirectory
)
153 // get an info for the location
154 BInstallationLocationInfo info
;
155 status_t error
= GetInstallationLocationInfo(location
, info
);
159 // open admin directory
161 entryRef
.device
= info
.PackagesDirectoryRef().device
;
162 entryRef
.directory
= info
.PackagesDirectoryRef().node
;
163 error
= entryRef
.set_name(PACKAGES_DIRECTORY_ADMIN_DIRECTORY
);
167 BDirectory adminDirectory
;
168 error
= adminDirectory
.SetTo(&entryRef
);
172 // create a transaction directory
174 BString directoryName
;
175 for (;; uniqueId
++) {
176 directoryName
.SetToFormat("transaction-%d", uniqueId
);
177 if (directoryName
.IsEmpty())
180 error
= adminDirectory
.CreateDirectory(directoryName
,
181 &_transactionDirectory
);
184 if (error
!= B_FILE_EXISTS
)
188 // init the transaction
189 error
= _transaction
.SetTo(location
, info
.ChangeCount(), directoryName
);
192 _transactionDirectory
.GetEntry(&entry
);
193 _transactionDirectory
.Unset();
194 if (entry
.InitCheck() == B_OK
)
204 BDaemonClient::_InitMessenger()
206 if (fDaemonMessenger
.IsValid())
209 // get the package daemon's address
211 fDaemonMessenger
= BMessenger(B_PACKAGE_DAEMON_APP_SIGNATURE
, -1, &error
);
217 BDaemonClient::_ExtractPackageInfoSet(const BMessage
& message
,
218 const char* field
, BPackageInfoSet
& _infos
)
220 // get the number of items
223 if (message
.GetInfo(field
, &type
, &count
) != B_OK
) {
224 // the field is missing
227 if (type
!= B_MESSAGE_TYPE
)
230 for (int32 i
= 0; i
< count
; i
++) {
232 status_t error
= message
.FindMessage(field
, i
, &archive
);
236 BPackageInfo
info(&archive
, &error
);
240 error
= _infos
.AddInfo(info
);
249 } // namespace BPrivate
250 } // namespace BPackageKit