2 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
3 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
8 #include <package/PackageInfo.h>
19 #include <package/hpkg/NoErrorOutput.h>
20 #include <package/hpkg/PackageReader.h>
21 #include <package/hpkg/v1/PackageInfoContentHandler.h>
22 #include <package/hpkg/v1/PackageReader.h>
23 #include <package/PackageInfoContentHandler.h>
25 #include "PackageInfoParser.h"
26 #include "PackageInfoStringBuilder.h"
29 namespace BPackageKit
{
32 const char* const BPackageInfo::kElementNames
[B_PACKAGE_INFO_ENUM_COUNT
] = {
51 "checksum", // not being parsed, computed externally
52 NULL
, // install-path -- not settable via .PackageInfo
54 "global-writable-files",
55 "user-settings-files",
58 "post-install-scripts"
63 BPackageInfo::kArchitectureNames
[B_PACKAGE_ARCHITECTURE_ENUM_COUNT
] = {
75 const char* const BPackageInfo::kWritableFileUpdateTypes
[
76 B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT
] = {
83 // #pragma mark - FieldName
86 struct BPackageInfo::FieldName
{
87 FieldName(const char* prefix
, const char* suffix
)
89 size_t prefixLength
= strlen(prefix
);
90 size_t suffixLength
= strlen(suffix
);
91 if (prefixLength
+ suffixLength
>= sizeof(fFieldName
)) {
96 memcpy(fFieldName
, prefix
, prefixLength
);
97 memcpy(fFieldName
+ prefixLength
, suffix
, suffixLength
);
98 fFieldName
[prefixLength
+ suffixLength
] = '\0';
101 bool ReplaceSuffix(size_t prefixLength
, const char* suffix
)
103 size_t suffixLength
= strlen(suffix
);
104 if (prefixLength
+ suffixLength
>= sizeof(fFieldName
)) {
105 fFieldName
[0] = '\0';
109 memcpy(fFieldName
+ prefixLength
, suffix
, suffixLength
);
110 fFieldName
[prefixLength
+ suffixLength
] = '\0';
116 return fFieldName
[0] != '\0';
119 operator const char*()
129 // #pragma mark - PackageFileLocation
132 struct BPackageInfo::PackageFileLocation
{
133 PackageFileLocation(const char* path
)
140 PackageFileLocation(int fd
)
147 const char* Path() const
163 // #pragma mark - BPackageInfo
166 BPackageInfo::BPackageInfo()
170 fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT
),
175 fGlobalWritableFileInfos(4, true),
176 fUserSettingsFileInfos(4, true),
179 fPostInstallScripts(4),
180 fProvidesList(20, true),
181 fRequiresList(20, true),
182 fSupplementsList(20, true),
183 fConflictsList(4, true),
184 fFreshensList(4, true),
190 BPackageInfo::BPackageInfo(BMessage
* archive
, status_t
* _error
)
192 BArchivable(archive
),
194 fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT
),
199 fGlobalWritableFileInfos(4, true),
200 fUserSettingsFileInfos(4, true),
203 fPostInstallScripts(4),
204 fProvidesList(20, true),
205 fRequiresList(20, true),
206 fSupplementsList(20, true),
207 fConflictsList(4, true),
208 fFreshensList(4, true),
213 if ((error
= archive
->FindString("name", &fName
)) == B_OK
214 && (error
= archive
->FindString("summary", &fSummary
)) == B_OK
215 && (error
= archive
->FindString("description", &fDescription
)) == B_OK
216 && (error
= archive
->FindString("vendor", &fVendor
)) == B_OK
217 && (error
= archive
->FindString("packager", &fPackager
)) == B_OK
218 && (error
= archive
->FindString("basePackage", &fBasePackage
)) == B_OK
219 && (error
= archive
->FindUInt32("flags", &fFlags
)) == B_OK
220 && (error
= archive
->FindInt32("architecture", &architecture
)) == B_OK
221 && (error
= _ExtractVersion(archive
, "version", 0, fVersion
)) == B_OK
222 && (error
= _ExtractStringList(archive
, "copyrights", fCopyrightList
))
224 && (error
= _ExtractStringList(archive
, "licenses", fLicenseList
))
226 && (error
= _ExtractStringList(archive
, "urls", fURLList
)) == B_OK
227 && (error
= _ExtractStringList(archive
, "source-urls", fSourceURLList
))
229 && (error
= _ExtractGlobalWritableFileInfos(archive
,
230 "global-writable-files", fGlobalWritableFileInfos
)) == B_OK
231 && (error
= _ExtractUserSettingsFileInfos(archive
, "user-settings-files",
232 fUserSettingsFileInfos
)) == B_OK
233 && (error
= _ExtractUsers(archive
, "users", fUsers
)) == B_OK
234 && (error
= _ExtractStringList(archive
, "groups", fGroups
)) == B_OK
235 && (error
= _ExtractStringList(archive
, "post-install-scripts",
236 fPostInstallScripts
)) == B_OK
237 && (error
= _ExtractResolvables(archive
, "provides", fProvidesList
))
239 && (error
= _ExtractResolvableExpressions(archive
, "requires",
240 fRequiresList
)) == B_OK
241 && (error
= _ExtractResolvableExpressions(archive
, "supplements",
242 fSupplementsList
)) == B_OK
243 && (error
= _ExtractResolvableExpressions(archive
, "conflicts",
244 fConflictsList
)) == B_OK
245 && (error
= _ExtractResolvableExpressions(archive
, "freshens",
246 fFreshensList
)) == B_OK
247 && (error
= _ExtractStringList(archive
, "replaces", fReplacesList
))
249 && (error
= archive
->FindString("checksum", &fChecksum
)) == B_OK
250 && (error
= archive
->FindString("install-path", &fInstallPath
)) == B_OK
251 && (error
= archive
->FindString("file-name", &fFileName
)) == B_OK
) {
252 if (architecture
>= 0
253 && architecture
<= B_PACKAGE_ARCHITECTURE_ENUM_COUNT
) {
254 fArchitecture
= (BPackageArchitecture
)architecture
;
264 BPackageInfo::~BPackageInfo()
270 BPackageInfo::ReadFromConfigFile(const BEntry
& packageInfoEntry
,
271 ParseErrorListener
* listener
)
273 status_t result
= packageInfoEntry
.InitCheck();
277 BFile
file(&packageInfoEntry
, B_READ_ONLY
);
278 if ((result
= file
.InitCheck()) != B_OK
)
281 return ReadFromConfigFile(file
, listener
);
286 BPackageInfo::ReadFromConfigFile(BFile
& packageInfoFile
,
287 ParseErrorListener
* listener
)
290 status_t result
= packageInfoFile
.GetSize(&size
);
294 BString packageInfoString
;
295 char* buffer
= packageInfoString
.LockBuffer(size
);
299 if ((result
= packageInfoFile
.Read(buffer
, size
)) < size
) {
300 packageInfoString
.UnlockBuffer(0);
301 return result
>= 0 ? B_IO_ERROR
: result
;
305 packageInfoString
.UnlockBuffer(size
);
307 return ReadFromConfigString(packageInfoString
, listener
);
312 BPackageInfo::ReadFromConfigString(const BString
& packageInfoString
,
313 ParseErrorListener
* listener
)
317 Parser
parser(listener
);
318 return parser
.Parse(packageInfoString
, this);
323 BPackageInfo::ReadFromPackageFile(const char* path
)
325 return _ReadFromPackageFile(PackageFileLocation(path
));
330 BPackageInfo::ReadFromPackageFile(int fd
)
332 return _ReadFromPackageFile(PackageFileLocation(fd
));
337 BPackageInfo::InitCheck() const
339 if (fName
.Length() == 0 || fSummary
.Length() == 0
340 || fDescription
.Length() == 0 || fVendor
.Length() == 0
341 || fPackager
.Length() == 0
342 || fArchitecture
== B_PACKAGE_ARCHITECTURE_ENUM_COUNT
343 || fVersion
.InitCheck() != B_OK
344 || fCopyrightList
.IsEmpty() || fLicenseList
.IsEmpty()
345 || fProvidesList
.IsEmpty())
348 // check global writable files
349 int32 globalWritableFileCount
= fGlobalWritableFileInfos
.CountItems();
350 for (int32 i
= 0; i
< globalWritableFileCount
; i
++) {
351 const BGlobalWritableFileInfo
* info
352 = fGlobalWritableFileInfos
.ItemAt(i
);
353 status_t error
= info
->InitCheck();
358 // check user settings files
359 int32 userSettingsFileCount
= fUserSettingsFileInfos
.CountItems();
360 for (int32 i
= 0; i
< userSettingsFileCount
; i
++) {
361 const BUserSettingsFileInfo
* info
= fUserSettingsFileInfos
.ItemAt(i
);
362 status_t error
= info
->InitCheck();
368 int32 userCount
= fUsers
.CountItems();
369 for (int32 i
= 0; i
< userCount
; i
++) {
370 const BUser
* user
= fUsers
.ItemAt(i
);
371 status_t error
= user
->InitCheck();
375 // make sure the user's groups are specified as groups
376 const BStringList
& userGroups
= user
->Groups();
377 int32 groupCount
= userGroups
.CountStrings();
378 for (int32 k
= 0; k
< groupCount
; k
++) {
379 const BString
& group
= userGroups
.StringAt(k
);
380 if (!fGroups
.HasString(group
))
386 int32 groupCount
= fGroups
.CountStrings();
387 for (int32 i
= 0; i
< groupCount
; i
++) {
388 if (!BUser::IsValidUserName(fGroups
.StringAt(i
)))
397 BPackageInfo::Name() const
404 BPackageInfo::Summary() const
411 BPackageInfo::Description() const
418 BPackageInfo::Vendor() const
425 BPackageInfo::Packager() const
432 BPackageInfo::BasePackage() const
439 BPackageInfo::Checksum() const
446 BPackageInfo::InstallPath() const
453 BPackageInfo::FileName() const
455 return fFileName
.IsEmpty() ? CanonicalFileName() : fFileName
;
460 BPackageInfo::Flags() const
467 BPackageInfo::Architecture() const
469 return fArchitecture
;
474 BPackageInfo::ArchitectureName() const
476 if ((int)fArchitecture
< 0
477 || fArchitecture
>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT
) {
480 return kArchitectureNames
[fArchitecture
];
484 const BPackageVersion
&
485 BPackageInfo::Version() const
492 BPackageInfo::CopyrightList() const
494 return fCopyrightList
;
499 BPackageInfo::LicenseList() const
506 BPackageInfo::URLList() const
513 BPackageInfo::SourceURLList() const
515 return fSourceURLList
;
519 const BObjectList
<BGlobalWritableFileInfo
>&
520 BPackageInfo::GlobalWritableFileInfos() const
522 return fGlobalWritableFileInfos
;
526 const BObjectList
<BUserSettingsFileInfo
>&
527 BPackageInfo::UserSettingsFileInfos() const
529 return fUserSettingsFileInfos
;
533 const BObjectList
<BUser
>&
534 BPackageInfo::Users() const
541 BPackageInfo::Groups() const
548 BPackageInfo::PostInstallScripts() const
550 return fPostInstallScripts
;
554 const BObjectList
<BPackageResolvable
>&
555 BPackageInfo::ProvidesList() const
557 return fProvidesList
;
561 const BObjectList
<BPackageResolvableExpression
>&
562 BPackageInfo::RequiresList() const
564 return fRequiresList
;
568 const BObjectList
<BPackageResolvableExpression
>&
569 BPackageInfo::SupplementsList() const
571 return fSupplementsList
;
575 const BObjectList
<BPackageResolvableExpression
>&
576 BPackageInfo::ConflictsList() const
578 return fConflictsList
;
582 const BObjectList
<BPackageResolvableExpression
>&
583 BPackageInfo::FreshensList() const
585 return fFreshensList
;
590 BPackageInfo::ReplacesList() const
592 return fReplacesList
;
597 BPackageInfo::CanonicalFileName() const
599 if (InitCheck() != B_OK
)
602 return BString().SetToFormat("%s-%s-%s.hpkg", fName
.String(),
603 fVersion
.ToString().String(), kArchitectureNames
[fArchitecture
]);
608 BPackageInfo::Matches(const BPackageResolvableExpression
& expression
) const
610 // check for an explicit match on the package
611 if (expression
.Name().StartsWith("pkg:")) {
612 return fName
== expression
.Name().String() + 4
613 && expression
.Matches(fVersion
, fVersion
);
616 // search for a matching provides
617 int32 count
= fProvidesList
.CountItems();
618 for (int32 i
= 0; i
< count
; i
++) {
619 const BPackageResolvable
* provides
= fProvidesList
.ItemAt(i
);
620 if (expression
.Matches(*provides
))
629 BPackageInfo::SetName(const BString
& name
)
637 BPackageInfo::SetSummary(const BString
& summary
)
644 BPackageInfo::SetDescription(const BString
& description
)
646 fDescription
= description
;
651 BPackageInfo::SetVendor(const BString
& vendor
)
658 BPackageInfo::SetPackager(const BString
& packager
)
660 fPackager
= packager
;
665 BPackageInfo::SetBasePackage(const BString
& basePackage
)
667 fBasePackage
= basePackage
;
672 BPackageInfo::SetChecksum(const BString
& checksum
)
674 fChecksum
= checksum
;
679 BPackageInfo::SetInstallPath(const BString
& installPath
)
681 fInstallPath
= installPath
;
686 BPackageInfo::SetFileName(const BString
& fileName
)
688 fFileName
= fileName
;
693 BPackageInfo::SetVersion(const BPackageVersion
& version
)
700 BPackageInfo::SetFlags(uint32 flags
)
707 BPackageInfo::SetArchitecture(BPackageArchitecture architecture
)
709 fArchitecture
= architecture
;
714 BPackageInfo::ClearCopyrightList()
716 fCopyrightList
.MakeEmpty();
721 BPackageInfo::AddCopyright(const BString
& copyright
)
723 return fCopyrightList
.Add(copyright
) ? B_OK
: B_ERROR
;
728 BPackageInfo::ClearLicenseList()
730 fLicenseList
.MakeEmpty();
735 BPackageInfo::AddLicense(const BString
& license
)
737 return fLicenseList
.Add(license
) ? B_OK
: B_ERROR
;
742 BPackageInfo::ClearURLList()
744 fURLList
.MakeEmpty();
749 BPackageInfo::AddURL(const BString
& url
)
751 return fURLList
.Add(url
) ? B_OK
: B_NO_MEMORY
;
756 BPackageInfo::ClearSourceURLList()
758 fSourceURLList
.MakeEmpty();
763 BPackageInfo::AddSourceURL(const BString
& url
)
765 return fSourceURLList
.Add(url
) ? B_OK
: B_NO_MEMORY
;
770 BPackageInfo::ClearGlobalWritableFileInfos()
772 fGlobalWritableFileInfos
.MakeEmpty();
777 BPackageInfo::AddGlobalWritableFileInfo(const BGlobalWritableFileInfo
& info
)
779 BGlobalWritableFileInfo
* newInfo
780 = new (std::nothrow
) BGlobalWritableFileInfo(info
);
781 if (newInfo
== NULL
|| !fGlobalWritableFileInfos
.AddItem(newInfo
)) {
791 BPackageInfo::ClearUserSettingsFileInfos()
793 fUserSettingsFileInfos
.MakeEmpty();
798 BPackageInfo::AddUserSettingsFileInfo(const BUserSettingsFileInfo
& info
)
800 BUserSettingsFileInfo
* newInfo
801 = new (std::nothrow
) BUserSettingsFileInfo(info
);
802 if (newInfo
== NULL
|| !fUserSettingsFileInfos
.AddItem(newInfo
)) {
812 BPackageInfo::ClearUsers()
819 BPackageInfo::AddUser(const BUser
& user
)
821 BUser
* newUser
= new (std::nothrow
) BUser(user
);
822 if (newUser
== NULL
|| !fUsers
.AddItem(newUser
)) {
832 BPackageInfo::ClearGroups()
839 BPackageInfo::AddGroup(const BString
& group
)
841 return fGroups
.Add(group
) ? B_OK
: B_NO_MEMORY
;
846 BPackageInfo::ClearPostInstallScripts()
848 fPostInstallScripts
.MakeEmpty();
853 BPackageInfo::AddPostInstallScript(const BString
& path
)
855 return fPostInstallScripts
.Add(path
) ? B_OK
: B_NO_MEMORY
;
860 BPackageInfo::ClearProvidesList()
862 fProvidesList
.MakeEmpty();
867 BPackageInfo::AddProvides(const BPackageResolvable
& provides
)
869 BPackageResolvable
* newProvides
870 = new (std::nothrow
) BPackageResolvable(provides
);
871 if (newProvides
== NULL
)
874 return fProvidesList
.AddItem(newProvides
) ? B_OK
: B_ERROR
;
879 BPackageInfo::ClearRequiresList()
881 fRequiresList
.MakeEmpty();
886 BPackageInfo::AddRequires(const BPackageResolvableExpression
& requires
)
888 BPackageResolvableExpression
* newRequires
889 = new (std::nothrow
) BPackageResolvableExpression(requires
);
890 if (newRequires
== NULL
)
893 return fRequiresList
.AddItem(newRequires
) ? B_OK
: B_ERROR
;
898 BPackageInfo::ClearSupplementsList()
900 fSupplementsList
.MakeEmpty();
905 BPackageInfo::AddSupplements(const BPackageResolvableExpression
& supplements
)
907 BPackageResolvableExpression
* newSupplements
908 = new (std::nothrow
) BPackageResolvableExpression(supplements
);
909 if (newSupplements
== NULL
)
912 return fSupplementsList
.AddItem(newSupplements
) ? B_OK
: B_ERROR
;
917 BPackageInfo::ClearConflictsList()
919 fConflictsList
.MakeEmpty();
924 BPackageInfo::AddConflicts(const BPackageResolvableExpression
& conflicts
)
926 BPackageResolvableExpression
* newConflicts
927 = new (std::nothrow
) BPackageResolvableExpression(conflicts
);
928 if (newConflicts
== NULL
)
931 return fConflictsList
.AddItem(newConflicts
) ? B_OK
: B_ERROR
;
936 BPackageInfo::ClearFreshensList()
938 fFreshensList
.MakeEmpty();
943 BPackageInfo::AddFreshens(const BPackageResolvableExpression
& freshens
)
945 BPackageResolvableExpression
* newFreshens
946 = new (std::nothrow
) BPackageResolvableExpression(freshens
);
947 if (newFreshens
== NULL
)
950 return fFreshensList
.AddItem(newFreshens
) ? B_OK
: B_ERROR
;
955 BPackageInfo::ClearReplacesList()
957 fReplacesList
.MakeEmpty();
962 BPackageInfo::AddReplaces(const BString
& replaces
)
964 return fReplacesList
.Add(BString(replaces
).ToLower()) ? B_OK
: B_ERROR
;
969 BPackageInfo::Clear()
972 fSummary
.Truncate(0);
973 fDescription
.Truncate(0);
975 fPackager
.Truncate(0);
976 fBasePackage
.Truncate(0);
977 fChecksum
.Truncate(0);
978 fInstallPath
.Truncate(0);
979 fFileName
.Truncate(0);
981 fArchitecture
= B_PACKAGE_ARCHITECTURE_ENUM_COUNT
;
983 fCopyrightList
.MakeEmpty();
984 fLicenseList
.MakeEmpty();
985 fURLList
.MakeEmpty();
986 fSourceURLList
.MakeEmpty();
987 fGlobalWritableFileInfos
.MakeEmpty();
988 fUserSettingsFileInfos
.MakeEmpty();
991 fPostInstallScripts
.MakeEmpty();
992 fRequiresList
.MakeEmpty();
993 fProvidesList
.MakeEmpty();
994 fSupplementsList
.MakeEmpty();
995 fConflictsList
.MakeEmpty();
996 fFreshensList
.MakeEmpty();
997 fReplacesList
.MakeEmpty();
1002 BPackageInfo::Archive(BMessage
* archive
, bool deep
) const
1004 status_t error
= BArchivable::Archive(archive
, deep
);
1008 if ((error
= archive
->AddString("name", fName
)) != B_OK
1009 || (error
= archive
->AddString("summary", fSummary
)) != B_OK
1010 || (error
= archive
->AddString("description", fDescription
)) != B_OK
1011 || (error
= archive
->AddString("vendor", fVendor
)) != B_OK
1012 || (error
= archive
->AddString("packager", fPackager
)) != B_OK
1013 || (error
= archive
->AddString("basePackage", fBasePackage
)) != B_OK
1014 || (error
= archive
->AddUInt32("flags", fFlags
)) != B_OK
1015 || (error
= archive
->AddInt32("architecture", fArchitecture
)) != B_OK
1016 || (error
= _AddVersion(archive
, "version", fVersion
)) != B_OK
1017 || (error
= archive
->AddStrings("copyrights", fCopyrightList
))
1019 || (error
= archive
->AddStrings("licenses", fLicenseList
)) != B_OK
1020 || (error
= archive
->AddStrings("urls", fURLList
)) != B_OK
1021 || (error
= archive
->AddStrings("source-urls", fSourceURLList
))
1023 || (error
= _AddGlobalWritableFileInfos(archive
,
1024 "global-writable-files", fGlobalWritableFileInfos
)) != B_OK
1025 || (error
= _AddUserSettingsFileInfos(archive
,
1026 "user-settings-files", fUserSettingsFileInfos
)) != B_OK
1027 || (error
= _AddUsers(archive
, "users", fUsers
)) != B_OK
1028 || (error
= archive
->AddStrings("groups", fGroups
)) != B_OK
1029 || (error
= archive
->AddStrings("post-install-scripts",
1030 fPostInstallScripts
)) != B_OK
1031 || (error
= _AddResolvables(archive
, "provides", fProvidesList
)) != B_OK
1032 || (error
= _AddResolvableExpressions(archive
, "requires",
1033 fRequiresList
)) != B_OK
1034 || (error
= _AddResolvableExpressions(archive
, "supplements",
1035 fSupplementsList
)) != B_OK
1036 || (error
= _AddResolvableExpressions(archive
, "conflicts",
1037 fConflictsList
)) != B_OK
1038 || (error
= _AddResolvableExpressions(archive
, "freshens",
1039 fFreshensList
)) != B_OK
1040 || (error
= archive
->AddStrings("replaces", fReplacesList
)) != B_OK
1041 || (error
= archive
->AddString("checksum", fChecksum
)) != B_OK
1042 || (error
= archive
->AddString("install-path", fInstallPath
)) != B_OK
1043 || (error
= archive
->AddString("file-name", fFileName
)) != B_OK
) {
1051 /*static*/ BArchivable
*
1052 BPackageInfo::Instantiate(BMessage
* archive
)
1054 if (validate_instantiation(archive
, "BPackageInfo"))
1055 return new(std::nothrow
) BPackageInfo(archive
);
1061 BPackageInfo::GetConfigString(BString
& _string
) const
1063 return StringBuilder()
1064 .Write("name", fName
)
1065 .Write("version", fVersion
)
1066 .Write("summary", fSummary
)
1067 .Write("description", fDescription
)
1068 .Write("vendor", fVendor
)
1069 .Write("packager", fPackager
)
1070 .Write("architecture", kArchitectureNames
[fArchitecture
])
1071 .Write("copyrights", fCopyrightList
)
1072 .Write("licenses", fLicenseList
)
1073 .Write("urls", fURLList
)
1074 .Write("source-urls", fSourceURLList
)
1075 .Write("global-writable-files", fGlobalWritableFileInfos
)
1076 .Write("user-settings-files", fUserSettingsFileInfos
)
1077 .Write("users", fUsers
)
1078 .Write("groups", fGroups
)
1079 .Write("post-install-scripts", fPostInstallScripts
)
1080 .Write("provides", fProvidesList
)
1081 .BeginRequires(fBasePackage
)
1082 .Write("requires", fRequiresList
)
1084 .Write("supplements", fSupplementsList
)
1085 .Write("conflicts", fConflictsList
)
1086 .Write("freshens", fFreshensList
)
1087 .Write("replaces", fReplacesList
)
1088 .WriteFlags("flags", fFlags
)
1089 .Write("checksum", fChecksum
)
1090 .GetString(_string
);
1091 // Note: fInstallPath and fFileName can not be specified via .PackageInfo.
1096 BPackageInfo::ToString() const
1099 GetConfigString(string
);
1105 BPackageInfo::GetArchitectureByName(const BString
& name
,
1106 BPackageArchitecture
& _architecture
)
1108 for (int i
= 0; i
< B_PACKAGE_ARCHITECTURE_ENUM_COUNT
; ++i
) {
1109 if (name
.ICompare(kArchitectureNames
[i
]) == 0) {
1110 _architecture
= (BPackageArchitecture
)i
;
1114 return B_NAME_NOT_FOUND
;
1119 BPackageInfo::ParseVersionString(const BString
& string
, bool revisionIsOptional
,
1120 BPackageVersion
& _version
, ParseErrorListener
* listener
)
1122 return Parser(listener
).ParseVersion(string
, revisionIsOptional
, _version
);
1127 BPackageInfo::ParseResolvableExpressionString(const BString
& string
,
1128 BPackageResolvableExpression
& _expression
, ParseErrorListener
* listener
)
1130 return Parser(listener
).ParseResolvableExpression(string
, _expression
);
1135 BPackageInfo::_ReadFromPackageFile(const PackageFileLocation
& fileLocation
)
1137 BHPKG::BNoErrorOutput errorOutput
;
1139 // try current package file format version
1141 BHPKG::BPackageReader
packageReader(&errorOutput
);
1142 status_t error
= fileLocation
.Path() != NULL
1143 ? packageReader
.Init(fileLocation
.Path())
1144 : packageReader
.Init(fileLocation
.FD(), false);
1145 if (error
== B_OK
) {
1146 BPackageInfoContentHandler
handler(*this);
1147 return packageReader
.ParseContent(&handler
);
1150 if (error
!= B_MISMATCHED_VALUES
)
1154 // try package file format version 1
1155 BHPKG::V1::BPackageReader
packageReader(&errorOutput
);
1156 status_t error
= fileLocation
.Path() != NULL
1157 ? packageReader
.Init(fileLocation
.Path())
1158 : packageReader
.Init(fileLocation
.FD(), false);
1162 BHPKG::V1::BPackageInfoContentHandler
handler(*this);
1163 return packageReader
.ParseContent(&handler
);
1168 BPackageInfo::_AddVersion(BMessage
* archive
, const char* field
,
1169 const BPackageVersion
& version
)
1171 // Storing BPackageVersion::ToString() would be nice, but the corresponding
1172 // constructor only works for valid versions and we might want to store
1173 // invalid versions as well.
1176 size_t fieldLength
= strlen(field
);
1177 FieldName
fieldName(field
, ":major");
1178 if (!fieldName
.IsValid())
1181 status_t error
= archive
->AddString(fieldName
, version
.Major());
1186 if (!fieldName
.ReplaceSuffix(fieldLength
, ":minor"))
1189 error
= archive
->AddString(fieldName
, version
.Minor());
1194 if (!fieldName
.ReplaceSuffix(fieldLength
, ":micro"))
1197 error
= archive
->AddString(fieldName
, version
.Micro());
1202 if (!fieldName
.ReplaceSuffix(fieldLength
, ":pre"))
1205 error
= archive
->AddString(fieldName
, version
.PreRelease());
1210 if (!fieldName
.ReplaceSuffix(fieldLength
, ":revision"))
1213 return archive
->AddUInt32(fieldName
, version
.Revision());
1218 BPackageInfo::_AddResolvables(BMessage
* archive
, const char* field
,
1219 const ResolvableList
& resolvables
)
1221 // construct the field names we need
1222 FieldName
nameField(field
, ":name");
1223 FieldName
typeField(field
, ":type");
1224 FieldName
versionField(field
, ":version");
1225 FieldName
compatibleVersionField(field
, ":compat");
1227 if (!nameField
.IsValid() || !typeField
.IsValid() || !versionField
.IsValid()
1228 || !compatibleVersionField
.IsValid()) {
1233 int32 count
= resolvables
.CountItems();
1234 for (int32 i
= 0; i
< count
; i
++) {
1235 const BPackageResolvable
* resolvable
= resolvables
.ItemAt(i
);
1237 if ((error
= archive
->AddString(nameField
, resolvable
->Name())) != B_OK
1238 || (error
= _AddVersion(archive
, versionField
,
1239 resolvable
->Version())) != B_OK
1240 || (error
= _AddVersion(archive
, compatibleVersionField
,
1241 resolvable
->CompatibleVersion())) != B_OK
) {
1251 BPackageInfo::_AddResolvableExpressions(BMessage
* archive
, const char* field
,
1252 const ResolvableExpressionList
& expressions
)
1254 // construct the field names we need
1255 FieldName
nameField(field
, ":name");
1256 FieldName
operatorField(field
, ":operator");
1257 FieldName
versionField(field
, ":version");
1259 if (!nameField
.IsValid() || !operatorField
.IsValid()
1260 || !versionField
.IsValid()) {
1265 int32 count
= expressions
.CountItems();
1266 for (int32 i
= 0; i
< count
; i
++) {
1267 const BPackageResolvableExpression
* expression
= expressions
.ItemAt(i
);
1269 if ((error
= archive
->AddString(nameField
, expression
->Name())) != B_OK
1270 || (error
= archive
->AddInt32(operatorField
,
1271 expression
->Operator())) != B_OK
1272 || (error
= _AddVersion(archive
, versionField
,
1273 expression
->Version())) != B_OK
) {
1283 BPackageInfo::_AddGlobalWritableFileInfos(BMessage
* archive
, const char* field
,
1284 const GlobalWritableFileInfoList
& infos
)
1286 // construct the field names we need
1287 FieldName
pathField(field
, ":path");
1288 FieldName
updateTypeField(field
, ":updateType");
1289 FieldName
isDirectoryField(field
, ":isDirectory");
1291 if (!pathField
.IsValid() || !updateTypeField
.IsValid()
1292 || !isDirectoryField
.IsValid()) {
1297 int32 count
= infos
.CountItems();
1298 for (int32 i
= 0; i
< count
; i
++) {
1299 const BGlobalWritableFileInfo
* info
= infos
.ItemAt(i
);
1301 if ((error
= archive
->AddString(pathField
, info
->Path())) != B_OK
1302 || (error
= archive
->AddInt32(updateTypeField
, info
->UpdateType()))
1304 || (error
= archive
->AddBool(isDirectoryField
,
1305 info
->IsDirectory())) != B_OK
) {
1315 BPackageInfo::_AddUserSettingsFileInfos(BMessage
* archive
, const char* field
,
1316 const UserSettingsFileInfoList
& infos
)
1318 // construct the field names we need
1319 FieldName
pathField(field
, ":path");
1320 FieldName
templatePathField(field
, ":templatePath");
1321 FieldName
isDirectoryField(field
, ":isDirectory");
1323 if (!pathField
.IsValid() || !templatePathField
.IsValid()
1324 || !isDirectoryField
.IsValid()) {
1329 int32 count
= infos
.CountItems();
1330 for (int32 i
= 0; i
< count
; i
++) {
1331 const BUserSettingsFileInfo
* info
= infos
.ItemAt(i
);
1333 if ((error
= archive
->AddString(pathField
, info
->Path())) != B_OK
1334 || (error
= archive
->AddString(templatePathField
,
1335 info
->TemplatePath())) != B_OK
1336 || (error
= archive
->AddBool(isDirectoryField
,
1337 info
->IsDirectory())) != B_OK
) {
1347 BPackageInfo::_AddUsers(BMessage
* archive
, const char* field
,
1348 const UserList
& users
)
1350 // construct the field names we need
1351 FieldName
nameField(field
, ":name");
1352 FieldName
realNameField(field
, ":realName");
1353 FieldName
homeField(field
, ":home");
1354 FieldName
shellField(field
, ":shell");
1355 FieldName
groupsField(field
, ":groups");
1357 if (!nameField
.IsValid() || !realNameField
.IsValid() || !homeField
.IsValid()
1358 || !shellField
.IsValid() || !groupsField
.IsValid())
1362 int32 count
= users
.CountItems();
1363 for (int32 i
= 0; i
< count
; i
++) {
1364 const BUser
* user
= users
.ItemAt(i
);
1365 BString groups
= user
->Groups().Join(" ");
1366 if (groups
.IsEmpty() && !user
->Groups().IsEmpty())
1370 if ((error
= archive
->AddString(nameField
, user
->Name())) != B_OK
1371 || (error
= archive
->AddString(realNameField
, user
->RealName()))
1373 || (error
= archive
->AddString(homeField
, user
->Home())) != B_OK
1374 || (error
= archive
->AddString(shellField
, user
->Shell())) != B_OK
1375 || (error
= archive
->AddString(groupsField
, groups
)) != B_OK
) {
1385 BPackageInfo::_ExtractVersion(BMessage
* archive
, const char* field
, int32 index
,
1386 BPackageVersion
& _version
)
1389 size_t fieldLength
= strlen(field
);
1390 FieldName
fieldName(field
, ":major");
1391 if (!fieldName
.IsValid())
1395 status_t error
= archive
->FindString(fieldName
, index
, &major
);
1400 if (!fieldName
.ReplaceSuffix(fieldLength
, ":minor"))
1404 error
= archive
->FindString(fieldName
, index
, &minor
);
1409 if (!fieldName
.ReplaceSuffix(fieldLength
, ":micro"))
1413 error
= archive
->FindString(fieldName
, index
, µ
);
1418 if (!fieldName
.ReplaceSuffix(fieldLength
, ":pre"))
1422 error
= archive
->FindString(fieldName
, index
, &preRelease
);
1427 if (!fieldName
.ReplaceSuffix(fieldLength
, ":revision"))
1431 error
= archive
->FindUInt32(fieldName
, index
, &revision
);
1435 _version
.SetTo(major
, minor
, micro
, preRelease
, revision
);
1441 BPackageInfo::_ExtractStringList(BMessage
* archive
, const char* field
,
1444 status_t error
= archive
->FindStrings(field
, &_list
);
1445 return error
== B_NAME_NOT_FOUND
? B_OK
: error
;
1446 // If the field doesn't exist, that's OK.
1451 BPackageInfo::_ExtractResolvables(BMessage
* archive
, const char* field
,
1452 ResolvableList
& _resolvables
)
1454 // construct the field names we need
1455 FieldName
nameField(field
, ":name");
1456 FieldName
typeField(field
, ":type");
1457 FieldName
versionField(field
, ":version");
1458 FieldName
compatibleVersionField(field
, ":compat");
1460 if (!nameField
.IsValid() || !typeField
.IsValid() || !versionField
.IsValid()
1461 || !compatibleVersionField
.IsValid()) {
1465 // get the number of items
1468 if (archive
->GetInfo(nameField
, &type
, &count
) != B_OK
) {
1469 // the field is missing
1474 for (int32 i
= 0; i
< count
; i
++) {
1476 status_t error
= archive
->FindString(nameField
, i
, &name
);
1480 BPackageVersion version
;
1481 error
= _ExtractVersion(archive
, versionField
, i
, version
);
1485 BPackageVersion compatibleVersion
;
1486 error
= _ExtractVersion(archive
, compatibleVersionField
, i
,
1491 BPackageResolvable
* resolvable
= new(std::nothrow
) BPackageResolvable(
1492 name
, version
, compatibleVersion
);
1493 if (resolvable
== NULL
|| !_resolvables
.AddItem(resolvable
)) {
1504 BPackageInfo::_ExtractResolvableExpressions(BMessage
* archive
,
1505 const char* field
, ResolvableExpressionList
& _expressions
)
1507 // construct the field names we need
1508 FieldName
nameField(field
, ":name");
1509 FieldName
operatorField(field
, ":operator");
1510 FieldName
versionField(field
, ":version");
1512 if (!nameField
.IsValid() || !operatorField
.IsValid()
1513 || !versionField
.IsValid()) {
1517 // get the number of items
1520 if (archive
->GetInfo(nameField
, &type
, &count
) != B_OK
) {
1521 // the field is missing
1526 for (int32 i
= 0; i
< count
; i
++) {
1528 status_t error
= archive
->FindString(nameField
, i
, &name
);
1533 error
= archive
->FindInt32(operatorField
, i
, &operatorType
);
1536 if (operatorType
< 0
1537 || operatorType
> B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT
) {
1541 BPackageVersion version
;
1542 error
= _ExtractVersion(archive
, versionField
, i
, version
);
1546 BPackageResolvableExpression
* expression
1547 = new(std::nothrow
) BPackageResolvableExpression(name
,
1548 (BPackageResolvableOperator
)operatorType
, version
);
1549 if (expression
== NULL
|| !_expressions
.AddItem(expression
)) {
1560 BPackageInfo::_ExtractGlobalWritableFileInfos(BMessage
* archive
,
1561 const char* field
, GlobalWritableFileInfoList
& _infos
)
1563 // construct the field names we need
1564 FieldName
pathField(field
, ":path");
1565 FieldName
updateTypeField(field
, ":updateType");
1566 FieldName
isDirectoryField(field
, ":isDirectory");
1568 if (!pathField
.IsValid() || !updateTypeField
.IsValid()
1569 || !isDirectoryField
.IsValid()) {
1573 // get the number of items
1576 if (archive
->GetInfo(pathField
, &type
, &count
) != B_OK
) {
1577 // the field is missing
1582 for (int32 i
= 0; i
< count
; i
++) {
1584 status_t error
= archive
->FindString(pathField
, i
, &path
);
1589 error
= archive
->FindInt32(updateTypeField
, i
, &updateType
);
1593 || updateType
> B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT
) {
1598 error
= archive
->FindBool(isDirectoryField
, i
, &isDirectory
);
1602 BGlobalWritableFileInfo
* info
1603 = new(std::nothrow
) BGlobalWritableFileInfo(path
,
1604 (BWritableFileUpdateType
)updateType
, isDirectory
);
1605 if (info
== NULL
|| !_infos
.AddItem(info
)) {
1616 BPackageInfo::_ExtractUserSettingsFileInfos(BMessage
* archive
,
1617 const char* field
, UserSettingsFileInfoList
& _infos
)
1619 // construct the field names we need
1620 FieldName
pathField(field
, ":path");
1621 FieldName
templatePathField(field
, ":templatePath");
1622 FieldName
isDirectoryField(field
, ":isDirectory");
1624 if (!pathField
.IsValid() || !templatePathField
.IsValid()
1625 || !isDirectoryField
.IsValid()) {
1629 // get the number of items
1632 if (archive
->GetInfo(pathField
, &type
, &count
) != B_OK
) {
1633 // the field is missing
1638 for (int32 i
= 0; i
< count
; i
++) {
1640 status_t error
= archive
->FindString(pathField
, i
, &path
);
1644 BString templatePath
;
1645 error
= archive
->FindString(templatePathField
, i
, &templatePath
);
1650 error
= archive
->FindBool(isDirectoryField
, i
, &isDirectory
);
1654 BUserSettingsFileInfo
* info
= isDirectory
1655 ? new(std::nothrow
) BUserSettingsFileInfo(path
, true)
1656 : new(std::nothrow
) BUserSettingsFileInfo(path
, templatePath
);
1657 if (info
== NULL
|| !_infos
.AddItem(info
)) {
1668 BPackageInfo::_ExtractUsers(BMessage
* archive
, const char* field
,
1671 // construct the field names we need
1672 FieldName
nameField(field
, ":name");
1673 FieldName
realNameField(field
, ":realName");
1674 FieldName
homeField(field
, ":home");
1675 FieldName
shellField(field
, ":shell");
1676 FieldName
groupsField(field
, ":groups");
1678 if (!nameField
.IsValid() || !realNameField
.IsValid() || !homeField
.IsValid()
1679 || !shellField
.IsValid() || !groupsField
.IsValid())
1682 // get the number of items
1685 if (archive
->GetInfo(nameField
, &type
, &count
) != B_OK
) {
1686 // the field is missing
1691 for (int32 i
= 0; i
< count
; i
++) {
1693 status_t error
= archive
->FindString(nameField
, i
, &name
);
1698 error
= archive
->FindString(realNameField
, i
, &realName
);
1703 error
= archive
->FindString(homeField
, i
, &home
);
1708 error
= archive
->FindString(shellField
, i
, &shell
);
1712 BString groupsString
;
1713 error
= archive
->FindString(groupsField
, i
, &groupsString
);
1718 if (!groupsString
.IsEmpty() && !groupsString
.Split(" ", false, groups
))
1721 BUser
* user
= new(std::nothrow
) BUser(name
, realName
, home
, shell
,
1723 if (user
== NULL
|| !_users
.AddItem(user
)) {
1733 } // namespace BPackageKit