1 /* 2 * Copyright 2011, 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 #endif 35 36 37 namespace BPackageKit { 38 39 40 using namespace BHPKG; 41 42 43 BPackageRoster::BPackageRoster() 44 { 45 } 46 47 48 BPackageRoster::~BPackageRoster() 49 { 50 } 51 52 53 status_t 54 BPackageRoster::GetCommonRepositoryConfigPath(BPath* path, bool create) const 55 { 56 return _GetRepositoryPath(path, create, B_COMMON_SETTINGS_DIRECTORY); 57 } 58 59 60 status_t 61 BPackageRoster::GetUserRepositoryConfigPath(BPath* path, bool create) const 62 { 63 return _GetRepositoryPath(path, create, B_USER_SETTINGS_DIRECTORY); 64 } 65 66 67 status_t 68 BPackageRoster::GetCommonRepositoryCachePath(BPath* path, bool create) const 69 { 70 return _GetRepositoryPath(path, create, B_COMMON_CACHE_DIRECTORY); 71 } 72 73 74 status_t 75 BPackageRoster::GetUserRepositoryCachePath(BPath* path, bool create) const 76 { 77 return _GetRepositoryPath(path, create, B_USER_CACHE_DIRECTORY); 78 } 79 80 81 status_t 82 BPackageRoster::VisitCommonRepositoryConfigs(BRepositoryConfigVisitor& visitor) 83 { 84 BPath commonRepositoryConfigPath; 85 status_t result 86 = GetCommonRepositoryConfigPath(&commonRepositoryConfigPath); 87 if (result != B_OK) 88 return result; 89 90 return _VisitRepositoryConfigs(commonRepositoryConfigPath, visitor); 91 } 92 93 94 status_t 95 BPackageRoster::VisitUserRepositoryConfigs(BRepositoryConfigVisitor& visitor) 96 { 97 BPath userRepositoryConfigPath; 98 status_t result = GetUserRepositoryConfigPath(&userRepositoryConfigPath); 99 if (result != B_OK) 100 return result; 101 102 return _VisitRepositoryConfigs(userRepositoryConfigPath, visitor); 103 } 104 105 106 status_t 107 BPackageRoster::GetRepositoryNames(BStringList& names) 108 { 109 struct RepositoryNameCollector : public BRepositoryConfigVisitor { 110 RepositoryNameCollector(BStringList& _names) 111 : names(_names) 112 { 113 } 114 status_t operator()(const BEntry& entry) 115 { 116 char name[B_FILE_NAME_LENGTH]; 117 status_t result = entry.GetName(name); 118 if (result != B_OK) 119 return result; 120 int32 count = names.CountStrings(); 121 for (int i = 0; i < count; ++i) { 122 if (names.StringAt(i).Compare(name) == 0) 123 return B_OK; 124 } 125 names.Add(name); 126 return B_OK; 127 } 128 BStringList& names; 129 }; 130 RepositoryNameCollector repositoryNameCollector(names); 131 status_t result = VisitUserRepositoryConfigs(repositoryNameCollector); 132 if (result != B_OK) 133 return result; 134 135 return VisitCommonRepositoryConfigs(repositoryNameCollector); 136 } 137 138 139 status_t 140 BPackageRoster::GetRepositoryCache(const BString& name, 141 BRepositoryCache* repositoryCache) 142 { 143 if (repositoryCache == NULL) 144 return B_BAD_VALUE; 145 146 // user path has higher precedence than common path 147 BPath path; 148 status_t result = GetUserRepositoryCachePath(&path); 149 if (result != B_OK) 150 return result; 151 path.Append(name.String()); 152 153 BEntry repoCacheEntry(path.Path()); 154 if (repoCacheEntry.Exists()) 155 return repositoryCache->SetTo(repoCacheEntry); 156 157 if ((result = GetCommonRepositoryCachePath(&path, true)) != B_OK) 158 return result; 159 path.Append(name.String()); 160 161 repoCacheEntry.SetTo(path.Path()); 162 return repositoryCache->SetTo(repoCacheEntry); 163 } 164 165 166 status_t 167 BPackageRoster::GetRepositoryConfig(const BString& name, 168 BRepositoryConfig* repositoryConfig) 169 { 170 if (repositoryConfig == NULL) 171 return B_BAD_VALUE; 172 173 // user path has higher precedence than common path 174 BPath path; 175 status_t result = GetUserRepositoryConfigPath(&path); 176 if (result != B_OK) 177 return result; 178 path.Append(name.String()); 179 180 BEntry repoConfigEntry(path.Path()); 181 if (repoConfigEntry.Exists()) 182 return repositoryConfig->SetTo(repoConfigEntry); 183 184 if ((result = GetCommonRepositoryConfigPath(&path, true)) != B_OK) 185 return result; 186 path.Append(name.String()); 187 188 repoConfigEntry.SetTo(path.Path()); 189 return repositoryConfig->SetTo(repoConfigEntry); 190 } 191 192 193 status_t 194 BPackageRoster::GetInstallationLocationInfo( 195 BPackageInstallationLocation location, BInstallationLocationInfo& _info) 196 { 197 // This method makes sense only on an installed Haiku, but not for the build 198 // tools. 199 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) 200 return BPackageKit::BPrivate::BDaemonClient().GetInstallationLocationInfo( 201 location, _info); 202 #else 203 return B_NOT_SUPPORTED; 204 #endif 205 } 206 207 208 status_t 209 BPackageRoster::GetActivePackages(BPackageInstallationLocation location, 210 BPackageInfoSet& packageInfos) 211 { 212 // This method makes sense only on an installed Haiku, but not for the build 213 // tools. 214 #if defined(__HAIKU__) && !defined(HAIKU_HOST_PLATFORM_HAIKU) 215 BInstallationLocationInfo info; 216 status_t error = GetInstallationLocationInfo(location, info); 217 if (error != B_OK) 218 return error; 219 220 packageInfos = info.ActivePackageInfos(); 221 return B_OK; 222 #else 223 return B_NOT_SUPPORTED; 224 #endif 225 } 226 227 228 status_t 229 BPackageRoster::_GetRepositoryPath(BPath* path, bool create, 230 directory_which whichDir) const 231 { 232 if (path == NULL) 233 return B_BAD_VALUE; 234 235 status_t result = find_directory(whichDir, path); 236 if (result != B_OK) 237 return result; 238 if ((result = path->Append("package-repositories")) != B_OK) 239 return result; 240 241 if (create) { 242 BEntry entry(path->Path(), true); 243 if (!entry.Exists()) { 244 if (mkdir(path->Path(), 0755) != 0) 245 return errno; 246 } 247 } 248 249 return B_OK; 250 } 251 252 253 status_t 254 BPackageRoster::_VisitRepositoryConfigs(const BPath& path, 255 BRepositoryConfigVisitor& visitor) 256 { 257 BDirectory directory(path.Path()); 258 status_t result = directory.InitCheck(); 259 if (result == B_ENTRY_NOT_FOUND) 260 return B_OK; 261 if (result != B_OK) 262 return result; 263 264 BEntry entry; 265 while (directory.GetNextEntry(&entry, true) == B_OK) { 266 if ((result = visitor(entry)) != B_OK) 267 return result; 268 } 269 270 return B_OK; 271 } 272 273 274 } // namespace BPackageKit 275