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