xref: /haiku/src/kits/package/PackageRoster.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2011-2014, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Oliver Tappe <zooey@hirschkaefer.de>
7  */
8 
9 
10 #include <package/PackageRoster.h>
11 
12 #include <errno.h>
13 #include <sys/stat.h>
14 
15 #include <Directory.h>
16 #include <Entry.h>
17 #include <Messenger.h>
18 #include <Path.h>
19 #include <String.h>
20 #include <StringList.h>
21 
22 #include <package/InstallationLocationInfo.h>
23 #include <package/PackageInfo.h>
24 #include <package/PackageInfoContentHandler.h>
25 #include <package/PackageInfoSet.h>
26 #include <package/RepositoryCache.h>
27 #include <package/RepositoryConfig.h>
28 
29 #include <package/hpkg/PackageReader.h>
30 
31 
32 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
33 #	include <package/DaemonClient.h>
34 #	include <RegistrarDefs.h>
35 #	include <RosterPrivate.h>
36 #endif
37 
38 
39 namespace BPackageKit {
40 
41 
42 using namespace BHPKG;
43 
44 
45 BPackageRoster::BPackageRoster()
46 {
47 }
48 
49 
50 BPackageRoster::~BPackageRoster()
51 {
52 }
53 
54 
55 status_t
56 BPackageRoster::GetCommonRepositoryConfigPath(BPath* path, bool create) const
57 {
58 	return _GetRepositoryPath(path, create, B_SYSTEM_SETTINGS_DIRECTORY);
59 }
60 
61 
62 status_t
63 BPackageRoster::GetUserRepositoryConfigPath(BPath* path, bool create) const
64 {
65 	return _GetRepositoryPath(path, create, B_USER_SETTINGS_DIRECTORY);
66 }
67 
68 
69 status_t
70 BPackageRoster::GetCommonRepositoryCachePath(BPath* path, bool create) const
71 {
72 	return _GetRepositoryPath(path, create, B_SYSTEM_CACHE_DIRECTORY);
73 }
74 
75 
76 status_t
77 BPackageRoster::GetUserRepositoryCachePath(BPath* path, bool create) const
78 {
79 	return _GetRepositoryPath(path, create, B_USER_CACHE_DIRECTORY);
80 }
81 
82 
83 status_t
84 BPackageRoster::VisitCommonRepositoryConfigs(BRepositoryConfigVisitor& visitor)
85 {
86 	BPath commonRepositoryConfigPath;
87 	status_t result
88 		= GetCommonRepositoryConfigPath(&commonRepositoryConfigPath);
89 	if (result != B_OK)
90 		return result;
91 
92 	return _VisitRepositoryConfigs(commonRepositoryConfigPath, visitor);
93 }
94 
95 
96 status_t
97 BPackageRoster::VisitUserRepositoryConfigs(BRepositoryConfigVisitor& visitor)
98 {
99 	BPath userRepositoryConfigPath;
100 	status_t result = GetUserRepositoryConfigPath(&userRepositoryConfigPath);
101 	if (result != B_OK)
102 		return result;
103 
104 	return _VisitRepositoryConfigs(userRepositoryConfigPath, visitor);
105 }
106 
107 
108 status_t
109 BPackageRoster::GetRepositoryNames(BStringList& names)
110 {
111 	struct RepositoryNameCollector : public BRepositoryConfigVisitor {
112 		RepositoryNameCollector(BStringList& _names)
113 			: names(_names)
114 		{
115 		}
116 		status_t operator()(const BEntry& entry)
117 		{
118 			char name[B_FILE_NAME_LENGTH];
119 			status_t result = entry.GetName(name);
120 			if (result != B_OK)
121 				return result;
122 			int32 count = names.CountStrings();
123 			for (int i = 0; i < count; ++i) {
124 				if (names.StringAt(i).Compare(name) == 0)
125 					return B_OK;
126 			}
127 			names.Add(name);
128 			return B_OK;
129 		}
130 		BStringList& names;
131 	};
132 	RepositoryNameCollector repositoryNameCollector(names);
133 	status_t result = VisitUserRepositoryConfigs(repositoryNameCollector);
134 	if (result != B_OK)
135 		return result;
136 
137 	return VisitCommonRepositoryConfigs(repositoryNameCollector);
138 }
139 
140 
141 status_t
142 BPackageRoster::GetRepositoryCache(const BString& name,
143 	BRepositoryCache* repositoryCache)
144 {
145 	if (repositoryCache == NULL)
146 		return B_BAD_VALUE;
147 
148 	// user path has higher precedence than common path
149 	BPath path;
150 	status_t result = GetUserRepositoryCachePath(&path);
151 	if (result != B_OK)
152 		return result;
153 	path.Append(name.String());
154 
155 	BEntry repoCacheEntry(path.Path());
156 	if (repoCacheEntry.Exists())
157 		return repositoryCache->SetTo(repoCacheEntry);
158 
159 	if ((result = GetCommonRepositoryCachePath(&path, true)) != B_OK)
160 		return result;
161 	path.Append(name.String());
162 
163 	repoCacheEntry.SetTo(path.Path());
164 	return repositoryCache->SetTo(repoCacheEntry);
165 }
166 
167 
168 status_t
169 BPackageRoster::GetRepositoryConfig(const BString& name,
170 	BRepositoryConfig* repositoryConfig)
171 {
172 	if (repositoryConfig == NULL)
173 		return B_BAD_VALUE;
174 
175 	// user path has higher precedence than common path
176 	BPath path;
177 	status_t result = GetUserRepositoryConfigPath(&path);
178 	if (result != B_OK)
179 		return result;
180 	path.Append(name.String());
181 
182 	BEntry repoConfigEntry(path.Path());
183 	if (repoConfigEntry.Exists())
184 		return repositoryConfig->SetTo(repoConfigEntry);
185 
186 	if ((result = GetCommonRepositoryConfigPath(&path, true)) != B_OK)
187 		return result;
188 	path.Append(name.String());
189 
190 	repoConfigEntry.SetTo(path.Path());
191 	return repositoryConfig->SetTo(repoConfigEntry);
192 }
193 
194 
195 status_t
196 BPackageRoster::GetInstallationLocationInfo(
197 	BPackageInstallationLocation location, BInstallationLocationInfo& _info)
198 {
199 // This method makes sense only on an installed Haiku, but not for the build
200 // tools.
201 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
202 	return BPackageKit::BPrivate::BDaemonClient().GetInstallationLocationInfo(
203 		location, _info);
204 #else
205 	return B_NOT_SUPPORTED;
206 #endif
207 }
208 
209 
210 status_t
211 BPackageRoster::GetActivePackages(BPackageInstallationLocation location,
212 	BPackageInfoSet& packageInfos)
213 {
214 // This method makes sense only on an installed Haiku, but not for the build
215 // tools.
216 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
217 	BInstallationLocationInfo info;
218 	status_t error = GetInstallationLocationInfo(location, info);
219 	if (error != B_OK)
220 		return error;
221 
222 	packageInfos = info.LatestActivePackageInfos();
223 	return B_OK;
224 #else
225 	return B_NOT_SUPPORTED;
226 #endif
227 }
228 
229 
230 status_t
231 BPackageRoster::StartWatching(const BMessenger& target, uint32 eventMask)
232 {
233 // This method makes sense only on an installed Haiku, but not for the build
234 // tools.
235 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
236 	// compose the registrar request
237 	BMessage request(::BPrivate::B_REG_PACKAGE_START_WATCHING);
238 	status_t error;
239 	if ((error = request.AddMessenger("target", target)) != B_OK
240 		|| (error = request.AddUInt32("events", eventMask)) != B_OK) {
241 		return error;
242 	}
243 
244 	// send it
245 	BMessage reply;
246 	error = BRoster::Private().SendTo(&request, &reply, false);
247 	if (error != B_OK)
248 		return error;
249 
250 	// get result
251 	if (reply.what != ::BPrivate::B_REG_SUCCESS) {
252 		int32 result;
253 		if (reply.FindInt32("error", &result) != B_OK)
254 			result = B_ERROR;
255 		return (status_t)error;
256 	}
257 
258 	return B_OK;
259 #else
260 	return B_NOT_SUPPORTED;
261 #endif
262 }
263 
264 
265 status_t
266 BPackageRoster::StopWatching(const BMessenger& target)
267 {
268 // This method makes sense only on an installed Haiku, but not for the build
269 // tools.
270 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
271 	// compose the registrar request
272 	BMessage request(::BPrivate::B_REG_PACKAGE_STOP_WATCHING);
273 	status_t error = request.AddMessenger("target", target);
274 	if (error  != B_OK)
275 		return error;
276 
277 	// send it
278 	BMessage reply;
279 	error = BRoster::Private().SendTo(&request, &reply, false);
280 	if (error != B_OK)
281 		return error;
282 
283 	// get result
284 	if (reply.what != ::BPrivate::B_REG_SUCCESS) {
285 		int32 result;
286 		if (reply.FindInt32("error", &result) != B_OK)
287 			result = B_ERROR;
288 		return (status_t)error;
289 	}
290 
291 	return B_OK;
292 #else
293 	return B_NOT_SUPPORTED;
294 #endif
295 }
296 
297 
298 status_t
299 BPackageRoster::_GetRepositoryPath(BPath* path, bool create,
300 	directory_which whichDir) const
301 {
302 	if (path == NULL)
303 		return B_BAD_VALUE;
304 
305 	status_t result = find_directory(whichDir, path);
306 	if (result != B_OK)
307 		return result;
308 	if ((result = path->Append("package-repositories")) != B_OK)
309 		return result;
310 
311 	if (create) {
312 		BEntry entry(path->Path(), true);
313 		if (!entry.Exists()) {
314 			if (mkdir(path->Path(), 0755) != 0)
315 				return errno;
316 		}
317 	}
318 
319 	return B_OK;
320 }
321 
322 
323 status_t
324 BPackageRoster::_VisitRepositoryConfigs(const BPath& path,
325 	BRepositoryConfigVisitor& visitor)
326 {
327 	BDirectory directory(path.Path());
328 	status_t result = directory.InitCheck();
329 	if (result == B_ENTRY_NOT_FOUND)
330 		return B_OK;
331 	if (result != B_OK)
332 		return result;
333 
334 	BEntry entry;
335 	while (directory.GetNextEntry(&entry, true) == B_OK) {
336 		if ((result = visitor(entry)) != B_OK)
337 			return result;
338 	}
339 
340 	return B_OK;
341 }
342 
343 
344 }	// namespace BPackageKit
345