vfs: check userland buffers before reading them.
[haiku.git] / src / kits / package / PackageRoster.cpp
blobf5c8a42d80c662f105d29734533a0f36f1e22a6e
1 /*
2 * Copyright 2011-2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Oliver Tappe <zooey@hirschkaefer.de>
7 */
10 #include <package/PackageRoster.h>
12 #include <errno.h>
13 #include <sys/stat.h>
15 #include <Directory.h>
16 #include <Entry.h>
17 #include <Messenger.h>
18 #include <Path.h>
19 #include <String.h>
20 #include <StringList.h>
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>
29 #include <package/hpkg/PackageReader.h>
32 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU)
33 # include <package/DaemonClient.h>
34 # include <RegistrarDefs.h>
35 # include <RosterPrivate.h>
36 #endif
39 namespace BPackageKit {
42 using namespace BHPKG;
45 BPackageRoster::BPackageRoster()
50 BPackageRoster::~BPackageRoster()
55 status_t
56 BPackageRoster::GetCommonRepositoryConfigPath(BPath* path, bool create) const
58 return _GetRepositoryPath(path, create, B_SYSTEM_SETTINGS_DIRECTORY);
62 status_t
63 BPackageRoster::GetUserRepositoryConfigPath(BPath* path, bool create) const
65 return _GetRepositoryPath(path, create, B_USER_SETTINGS_DIRECTORY);
69 status_t
70 BPackageRoster::GetCommonRepositoryCachePath(BPath* path, bool create) const
72 return _GetRepositoryPath(path, create, B_SYSTEM_CACHE_DIRECTORY);
76 status_t
77 BPackageRoster::GetUserRepositoryCachePath(BPath* path, bool create) const
79 return _GetRepositoryPath(path, create, B_USER_CACHE_DIRECTORY);
83 status_t
84 BPackageRoster::VisitCommonRepositoryConfigs(BRepositoryConfigVisitor& visitor)
86 BPath commonRepositoryConfigPath;
87 status_t result
88 = GetCommonRepositoryConfigPath(&commonRepositoryConfigPath);
89 if (result != B_OK)
90 return result;
92 return _VisitRepositoryConfigs(commonRepositoryConfigPath, visitor);
96 status_t
97 BPackageRoster::VisitUserRepositoryConfigs(BRepositoryConfigVisitor& visitor)
99 BPath userRepositoryConfigPath;
100 status_t result = GetUserRepositoryConfigPath(&userRepositoryConfigPath);
101 if (result != B_OK)
102 return result;
104 return _VisitRepositoryConfigs(userRepositoryConfigPath, visitor);
108 status_t
109 BPackageRoster::GetRepositoryNames(BStringList& names)
111 struct RepositoryNameCollector : public BRepositoryConfigVisitor {
112 RepositoryNameCollector(BStringList& _names)
113 : names(_names)
116 status_t operator()(const BEntry& entry)
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;
127 names.Add(name);
128 return B_OK;
130 BStringList& names;
132 RepositoryNameCollector repositoryNameCollector(names);
133 status_t result = VisitUserRepositoryConfigs(repositoryNameCollector);
134 if (result != B_OK)
135 return result;
137 return VisitCommonRepositoryConfigs(repositoryNameCollector);
141 status_t
142 BPackageRoster::GetRepositoryCache(const BString& name,
143 BRepositoryCache* repositoryCache)
145 if (repositoryCache == NULL)
146 return B_BAD_VALUE;
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());
155 BEntry repoCacheEntry(path.Path());
156 if (repoCacheEntry.Exists())
157 return repositoryCache->SetTo(repoCacheEntry);
159 if ((result = GetCommonRepositoryCachePath(&path, true)) != B_OK)
160 return result;
161 path.Append(name.String());
163 repoCacheEntry.SetTo(path.Path());
164 return repositoryCache->SetTo(repoCacheEntry);
168 status_t
169 BPackageRoster::GetRepositoryConfig(const BString& name,
170 BRepositoryConfig* repositoryConfig)
172 if (repositoryConfig == NULL)
173 return B_BAD_VALUE;
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());
182 BEntry repoConfigEntry(path.Path());
183 if (repoConfigEntry.Exists())
184 return repositoryConfig->SetTo(repoConfigEntry);
186 if ((result = GetCommonRepositoryConfigPath(&path, true)) != B_OK)
187 return result;
188 path.Append(name.String());
190 repoConfigEntry.SetTo(path.Path());
191 return repositoryConfig->SetTo(repoConfigEntry);
195 status_t
196 BPackageRoster::GetInstallationLocationInfo(
197 BPackageInstallationLocation location, BInstallationLocationInfo& _info)
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
210 status_t
211 BPackageRoster::GetActivePackages(BPackageInstallationLocation location,
212 BPackageInfoSet& packageInfos)
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;
222 packageInfos = info.LatestActivePackageInfos();
223 return B_OK;
224 #else
225 return B_NOT_SUPPORTED;
226 #endif
230 status_t
231 BPackageRoster::StartWatching(const BMessenger& target, uint32 eventMask)
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;
244 // send it
245 BMessage reply;
246 error = BRoster::Private().SendTo(&request, &reply, false);
247 if (error != B_OK)
248 return error;
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;
258 return B_OK;
259 #else
260 return B_NOT_SUPPORTED;
261 #endif
265 status_t
266 BPackageRoster::StopWatching(const BMessenger& target)
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;
277 // send it
278 BMessage reply;
279 error = BRoster::Private().SendTo(&request, &reply, false);
280 if (error != B_OK)
281 return error;
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;
291 return B_OK;
292 #else
293 return B_NOT_SUPPORTED;
294 #endif
298 status_t
299 BPackageRoster::_GetRepositoryPath(BPath* path, bool create,
300 directory_which whichDir) const
302 if (path == NULL)
303 return B_BAD_VALUE;
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;
311 if (create) {
312 BEntry entry(path->Path(), true);
313 if (!entry.Exists()) {
314 if (mkdir(path->Path(), 0755) != 0)
315 return errno;
319 return B_OK;
323 status_t
324 BPackageRoster::_VisitRepositoryConfigs(const BPath& path,
325 BRepositoryConfigVisitor& visitor)
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;
334 BEntry entry;
335 while (directory.GetNextEntry(&entry, true) == B_OK) {
336 if ((result = visitor(entry)) != B_OK)
337 return result;
340 return B_OK;
344 } // namespace BPackageKit