1 /*
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.
5 */
6
7
8 #include <package/PackageInfo.h>
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include <new>
15
16 #include <File.h>
17 #include <Entry.h>
18 #include <Message.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>
24
25 #include "PackageInfoParser.h"
26 #include "PackageInfoStringBuilder.h"
27
28
29 namespace BPackageKit {
30
31
32 const char* const BPackageInfo::kElementNames[B_PACKAGE_INFO_ENUM_COUNT] = {
33 "name",
34 "summary",
35 "description",
36 "vendor",
37 "packager",
38 "architecture",
39 "version",
40 "copyrights",
41 "licenses",
42 "provides",
43 "requires",
44 "supplements",
45 "conflicts",
46 "freshens",
47 "replaces",
48 "flags",
49 "urls",
50 "source-urls",
51 "checksum", // not being parsed, computed externally
52 NULL, // install-path -- not settable via .PackageInfo
53 "base-package",
54 "global-writable-files",
55 "user-settings-files",
56 "users",
57 "groups",
58 "post-install-scripts",
59 "pre-uninstall-scripts"
60 };
61
62
63 const char* const
64 BPackageInfo::kArchitectureNames[B_PACKAGE_ARCHITECTURE_ENUM_COUNT] = {
65 "any",
66 "x86",
67 "x86_gcc2",
68 "source",
69 "x86_64",
70 "ppc",
71 "arm",
72 "m68k",
73 "sparc",
74 "arm64",
75 "riscv64"
76 };
77
78
79 const char* const BPackageInfo::kWritableFileUpdateTypes[
80 B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT] = {
81 "keep-old",
82 "manual",
83 "auto-merge",
84 };
85
86
87 // #pragma mark - FieldName
88
89
90 struct BPackageInfo::FieldName {
FieldNameBPackageKit::BPackageInfo::FieldName91 FieldName(const char* prefix, const char* suffix)
92 {
93 size_t prefixLength = strlen(prefix);
94 size_t suffixLength = strlen(suffix);
95 if (prefixLength + suffixLength >= sizeof(fFieldName)) {
96 fFieldName[0] = '\0';
97 return;
98 }
99
100 memcpy(fFieldName, prefix, prefixLength);
101 memcpy(fFieldName + prefixLength, suffix, suffixLength);
102 fFieldName[prefixLength + suffixLength] = '\0';
103 }
104
ReplaceSuffixBPackageKit::BPackageInfo::FieldName105 bool ReplaceSuffix(size_t prefixLength, const char* suffix)
106 {
107 size_t suffixLength = strlen(suffix);
108 if (prefixLength + suffixLength >= sizeof(fFieldName)) {
109 fFieldName[0] = '\0';
110 return false;
111 }
112
113 memcpy(fFieldName + prefixLength, suffix, suffixLength);
114 fFieldName[prefixLength + suffixLength] = '\0';
115 return true;
116 }
117
IsValidBPackageKit::BPackageInfo::FieldName118 bool IsValid() const
119 {
120 return fFieldName[0] != '\0';
121 }
122
operator const char*BPackageKit::BPackageInfo::FieldName123 operator const char*()
124 {
125 return fFieldName;
126 }
127
128 private:
129 char fFieldName[64];
130 };
131
132
133 // #pragma mark - PackageFileLocation
134
135
136 struct BPackageInfo::PackageFileLocation {
PackageFileLocationBPackageKit::BPackageInfo::PackageFileLocation137 PackageFileLocation(const char* path)
138 :
139 fPath(path),
140 fFD(-1)
141 {
142 }
143
PackageFileLocationBPackageKit::BPackageInfo::PackageFileLocation144 PackageFileLocation(int fd)
145 :
146 fPath(NULL),
147 fFD(fd)
148 {
149 }
150
PathBPackageKit::BPackageInfo::PackageFileLocation151 const char* Path() const
152 {
153 return fPath;
154 }
155
FDBPackageKit::BPackageInfo::PackageFileLocation156 int FD() const
157 {
158 return fFD;
159 }
160
161 private:
162 const char* fPath;
163 int fFD;
164 };
165
166
167 // #pragma mark - BPackageInfo
168
169
BPackageInfo()170 BPackageInfo::BPackageInfo()
171 :
172 BArchivable(),
173 fFlags(0),
174 fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT),
175 fCopyrightList(4),
176 fLicenseList(4),
177 fURLList(4),
178 fSourceURLList(4),
179 fGlobalWritableFileInfos(4, true),
180 fUserSettingsFileInfos(4, true),
181 fUsers(4, true),
182 fGroups(4),
183 fPostInstallScripts(4),
184 fPreUninstallScripts(4),
185 fProvidesList(20, true),
186 fRequiresList(20, true),
187 fSupplementsList(20, true),
188 fConflictsList(4, true),
189 fFreshensList(4, true),
190 fReplacesList(4)
191 {
192 }
193
194
BPackageInfo(BMessage * archive,status_t * _error)195 BPackageInfo::BPackageInfo(BMessage* archive, status_t* _error)
196 :
197 BArchivable(archive),
198 fFlags(0),
199 fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT),
200 fCopyrightList(4),
201 fLicenseList(4),
202 fURLList(4),
203 fSourceURLList(4),
204 fGlobalWritableFileInfos(4, true),
205 fUserSettingsFileInfos(4, true),
206 fUsers(4, true),
207 fGroups(4),
208 fPostInstallScripts(4),
209 fPreUninstallScripts(4),
210 fProvidesList(20, true),
211 fRequiresList(20, true),
212 fSupplementsList(20, true),
213 fConflictsList(4, true),
214 fFreshensList(4, true),
215 fReplacesList(4)
216 {
217 status_t error;
218 int32 architecture;
219 if ((error = archive->FindString("name", &fName)) == B_OK
220 && (error = archive->FindString("summary", &fSummary)) == B_OK
221 && (error = archive->FindString("description", &fDescription)) == B_OK
222 && (error = archive->FindString("vendor", &fVendor)) == B_OK
223 && (error = archive->FindString("packager", &fPackager)) == B_OK
224 && (error = archive->FindString("basePackage", &fBasePackage)) == B_OK
225 && (error = archive->FindUInt32("flags", &fFlags)) == B_OK
226 && (error = archive->FindInt32("architecture", &architecture)) == B_OK
227 && (error = _ExtractVersion(archive, "version", 0, fVersion)) == B_OK
228 && (error = _ExtractStringList(archive, "copyrights", fCopyrightList))
229 == B_OK
230 && (error = _ExtractStringList(archive, "licenses", fLicenseList))
231 == B_OK
232 && (error = _ExtractStringList(archive, "urls", fURLList)) == B_OK
233 && (error = _ExtractStringList(archive, "source-urls", fSourceURLList))
234 == B_OK
235 && (error = _ExtractGlobalWritableFileInfos(archive,
236 "global-writable-files", fGlobalWritableFileInfos)) == B_OK
237 && (error = _ExtractUserSettingsFileInfos(archive, "user-settings-files",
238 fUserSettingsFileInfos)) == B_OK
239 && (error = _ExtractUsers(archive, "users", fUsers)) == B_OK
240 && (error = _ExtractStringList(archive, "groups", fGroups)) == B_OK
241 && (error = _ExtractStringList(archive, "post-install-scripts",
242 fPostInstallScripts)) == B_OK
243 && (error = _ExtractStringList(archive, "pre-uninstall-scripts",
244 fPreUninstallScripts)) == B_OK
245 && (error = _ExtractResolvables(archive, "provides", fProvidesList))
246 == B_OK
247 && (error = _ExtractResolvableExpressions(archive, "requires",
248 fRequiresList)) == B_OK
249 && (error = _ExtractResolvableExpressions(archive, "supplements",
250 fSupplementsList)) == B_OK
251 && (error = _ExtractResolvableExpressions(archive, "conflicts",
252 fConflictsList)) == B_OK
253 && (error = _ExtractResolvableExpressions(archive, "freshens",
254 fFreshensList)) == B_OK
255 && (error = _ExtractStringList(archive, "replaces", fReplacesList))
256 == B_OK
257 && (error = archive->FindString("checksum", &fChecksum)) == B_OK
258 && (error = archive->FindString("install-path", &fInstallPath)) == B_OK
259 && (error = archive->FindString("file-name", &fFileName)) == B_OK) {
260 if (architecture >= 0
261 && architecture <= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
262 fArchitecture = (BPackageArchitecture)architecture;
263 } else
264 error = B_BAD_DATA;
265 }
266
267 if (_error != NULL)
268 *_error = error;
269 }
270
271
~BPackageInfo()272 BPackageInfo::~BPackageInfo()
273 {
274 }
275
276
277 status_t
ReadFromConfigFile(const BEntry & packageInfoEntry,ParseErrorListener * listener)278 BPackageInfo::ReadFromConfigFile(const BEntry& packageInfoEntry,
279 ParseErrorListener* listener)
280 {
281 status_t result = packageInfoEntry.InitCheck();
282 if (result != B_OK)
283 return result;
284
285 BFile file(&packageInfoEntry, B_READ_ONLY);
286 if ((result = file.InitCheck()) != B_OK)
287 return result;
288
289 return ReadFromConfigFile(file, listener);
290 }
291
292
293 status_t
ReadFromConfigFile(BFile & packageInfoFile,ParseErrorListener * listener)294 BPackageInfo::ReadFromConfigFile(BFile& packageInfoFile,
295 ParseErrorListener* listener)
296 {
297 off_t size;
298 status_t result = packageInfoFile.GetSize(&size);
299 if (result != B_OK)
300 return result;
301
302 BString packageInfoString;
303 char* buffer = packageInfoString.LockBuffer(size);
304 if (buffer == NULL)
305 return B_NO_MEMORY;
306
307 if ((result = packageInfoFile.Read(buffer, size)) < size) {
308 packageInfoString.UnlockBuffer(0);
309 return result >= 0 ? B_IO_ERROR : result;
310 }
311
312 buffer[size] = '\0';
313 packageInfoString.UnlockBuffer(size);
314
315 return ReadFromConfigString(packageInfoString, listener);
316 }
317
318
319 status_t
ReadFromConfigString(const BString & packageInfoString,ParseErrorListener * listener)320 BPackageInfo::ReadFromConfigString(const BString& packageInfoString,
321 ParseErrorListener* listener)
322 {
323 Clear();
324
325 Parser parser(listener);
326 return parser.Parse(packageInfoString, this);
327 }
328
329
330 status_t
ReadFromPackageFile(const char * path)331 BPackageInfo::ReadFromPackageFile(const char* path)
332 {
333 return _ReadFromPackageFile(PackageFileLocation(path));
334 }
335
336
337 status_t
ReadFromPackageFile(int fd)338 BPackageInfo::ReadFromPackageFile(int fd)
339 {
340 return _ReadFromPackageFile(PackageFileLocation(fd));
341 }
342
343
344 status_t
InitCheck() const345 BPackageInfo::InitCheck() const
346 {
347 if (fName.Length() == 0 || fSummary.Length() == 0
348 || fDescription.Length() == 0 || fVendor.Length() == 0
349 || fPackager.Length() == 0
350 || fArchitecture == B_PACKAGE_ARCHITECTURE_ENUM_COUNT
351 || fVersion.InitCheck() != B_OK
352 || fCopyrightList.IsEmpty() || fLicenseList.IsEmpty()
353 || fProvidesList.IsEmpty())
354 return B_NO_INIT;
355
356 // check global writable files
357 int32 globalWritableFileCount = fGlobalWritableFileInfos.CountItems();
358 for (int32 i = 0; i < globalWritableFileCount; i++) {
359 const BGlobalWritableFileInfo* info
360 = fGlobalWritableFileInfos.ItemAt(i);
361 status_t error = info->InitCheck();
362 if (error != B_OK)
363 return error;
364 }
365
366 // check user settings files
367 int32 userSettingsFileCount = fUserSettingsFileInfos.CountItems();
368 for (int32 i = 0; i < userSettingsFileCount; i++) {
369 const BUserSettingsFileInfo* info = fUserSettingsFileInfos.ItemAt(i);
370 status_t error = info->InitCheck();
371 if (error != B_OK)
372 return error;
373 }
374
375 // check users
376 int32 userCount = fUsers.CountItems();
377 for (int32 i = 0; i < userCount; i++) {
378 const BUser* user = fUsers.ItemAt(i);
379 status_t error = user->InitCheck();
380 if (error != B_OK)
381 return B_NO_INIT;
382
383 // make sure the user's groups are specified as groups
384 const BStringList& userGroups = user->Groups();
385 int32 groupCount = userGroups.CountStrings();
386 for (int32 k = 0; k < groupCount; k++) {
387 const BString& group = userGroups.StringAt(k);
388 if (!fGroups.HasString(group))
389 return B_BAD_VALUE;
390 }
391 }
392
393 // check groups
394 int32 groupCount = fGroups.CountStrings();
395 for (int32 i = 0; i< groupCount; i++) {
396 if (!BUser::IsValidUserName(fGroups.StringAt(i)))
397 return B_BAD_VALUE;
398 }
399
400 return B_OK;
401 }
402
403
404 const BString&
Name() const405 BPackageInfo::Name() const
406 {
407 return fName;
408 }
409
410
411 const BString&
Summary() const412 BPackageInfo::Summary() const
413 {
414 return fSummary;
415 }
416
417
418 const BString&
Description() const419 BPackageInfo::Description() const
420 {
421 return fDescription;
422 }
423
424
425 const BString&
Vendor() const426 BPackageInfo::Vendor() const
427 {
428 return fVendor;
429 }
430
431
432 const BString&
Packager() const433 BPackageInfo::Packager() const
434 {
435 return fPackager;
436 }
437
438
439 const BString&
BasePackage() const440 BPackageInfo::BasePackage() const
441 {
442 return fBasePackage;
443 }
444
445
446 const BString&
Checksum() const447 BPackageInfo::Checksum() const
448 {
449 return fChecksum;
450 }
451
452
453 const BString&
InstallPath() const454 BPackageInfo::InstallPath() const
455 {
456 return fInstallPath;
457 }
458
459
460 BString
FileName() const461 BPackageInfo::FileName() const
462 {
463 return fFileName.IsEmpty() ? CanonicalFileName() : fFileName;
464 }
465
466
467 uint32
Flags() const468 BPackageInfo::Flags() const
469 {
470 return fFlags;
471 }
472
473
474 BPackageArchitecture
Architecture() const475 BPackageInfo::Architecture() const
476 {
477 return fArchitecture;
478 }
479
480
481 const char*
ArchitectureName() const482 BPackageInfo::ArchitectureName() const
483 {
484 if ((int)fArchitecture < 0
485 || fArchitecture >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
486 return NULL;
487 }
488 return kArchitectureNames[fArchitecture];
489 }
490
491
492 const BPackageVersion&
Version() const493 BPackageInfo::Version() const
494 {
495 return fVersion;
496 }
497
498
499 const BStringList&
CopyrightList() const500 BPackageInfo::CopyrightList() const
501 {
502 return fCopyrightList;
503 }
504
505
506 const BStringList&
LicenseList() const507 BPackageInfo::LicenseList() const
508 {
509 return fLicenseList;
510 }
511
512
513 const BStringList&
URLList() const514 BPackageInfo::URLList() const
515 {
516 return fURLList;
517 }
518
519
520 const BStringList&
SourceURLList() const521 BPackageInfo::SourceURLList() const
522 {
523 return fSourceURLList;
524 }
525
526
527 const BObjectList<BGlobalWritableFileInfo>&
GlobalWritableFileInfos() const528 BPackageInfo::GlobalWritableFileInfos() const
529 {
530 return fGlobalWritableFileInfos;
531 }
532
533
534 const BObjectList<BUserSettingsFileInfo>&
UserSettingsFileInfos() const535 BPackageInfo::UserSettingsFileInfos() const
536 {
537 return fUserSettingsFileInfos;
538 }
539
540
541 const BObjectList<BUser>&
Users() const542 BPackageInfo::Users() const
543 {
544 return fUsers;
545 }
546
547
548 const BStringList&
Groups() const549 BPackageInfo::Groups() const
550 {
551 return fGroups;
552 }
553
554
555 const BStringList&
PostInstallScripts() const556 BPackageInfo::PostInstallScripts() const
557 {
558 return fPostInstallScripts;
559 }
560
561
562 const BStringList&
PreUninstallScripts() const563 BPackageInfo::PreUninstallScripts() const
564 {
565 return fPreUninstallScripts;
566 }
567
568
569 const BObjectList<BPackageResolvable>&
ProvidesList() const570 BPackageInfo::ProvidesList() const
571 {
572 return fProvidesList;
573 }
574
575
576 const BObjectList<BPackageResolvableExpression>&
RequiresList() const577 BPackageInfo::RequiresList() const
578 {
579 return fRequiresList;
580 }
581
582
583 const BObjectList<BPackageResolvableExpression>&
SupplementsList() const584 BPackageInfo::SupplementsList() const
585 {
586 return fSupplementsList;
587 }
588
589
590 const BObjectList<BPackageResolvableExpression>&
ConflictsList() const591 BPackageInfo::ConflictsList() const
592 {
593 return fConflictsList;
594 }
595
596
597 const BObjectList<BPackageResolvableExpression>&
FreshensList() const598 BPackageInfo::FreshensList() const
599 {
600 return fFreshensList;
601 }
602
603
604 const BStringList&
ReplacesList() const605 BPackageInfo::ReplacesList() const
606 {
607 return fReplacesList;
608 }
609
610
611 BString
CanonicalFileName() const612 BPackageInfo::CanonicalFileName() const
613 {
614 if (InitCheck() != B_OK)
615 return BString();
616
617 return BString().SetToFormat("%s-%s-%s.hpkg", fName.String(),
618 fVersion.ToString().String(), kArchitectureNames[fArchitecture]);
619 }
620
621
622 bool
Matches(const BPackageResolvableExpression & expression) const623 BPackageInfo::Matches(const BPackageResolvableExpression& expression) const
624 {
625 // check for an explicit match on the package
626 if (expression.Name().StartsWith("pkg:")) {
627 return fName == expression.Name().String() + 4
628 && expression.Matches(fVersion, fVersion);
629 }
630
631 // search for a matching provides
632 int32 count = fProvidesList.CountItems();
633 for (int32 i = 0; i < count; i++) {
634 const BPackageResolvable* provides = fProvidesList.ItemAt(i);
635 if (expression.Matches(*provides))
636 return true;
637 }
638
639 return false;
640 }
641
642
643 void
SetName(const BString & name)644 BPackageInfo::SetName(const BString& name)
645 {
646 fName = name;
647 fName.ToLower();
648 }
649
650
651 void
SetSummary(const BString & summary)652 BPackageInfo::SetSummary(const BString& summary)
653 {
654 fSummary = summary;
655 }
656
657
658 void
SetDescription(const BString & description)659 BPackageInfo::SetDescription(const BString& description)
660 {
661 fDescription = description;
662 }
663
664
665 void
SetVendor(const BString & vendor)666 BPackageInfo::SetVendor(const BString& vendor)
667 {
668 fVendor = vendor;
669 }
670
671
672 void
SetPackager(const BString & packager)673 BPackageInfo::SetPackager(const BString& packager)
674 {
675 fPackager = packager;
676 }
677
678
679 void
SetBasePackage(const BString & basePackage)680 BPackageInfo::SetBasePackage(const BString& basePackage)
681 {
682 fBasePackage = basePackage;
683 }
684
685
686 void
SetChecksum(const BString & checksum)687 BPackageInfo::SetChecksum(const BString& checksum)
688 {
689 fChecksum = checksum;
690 }
691
692
693 void
SetInstallPath(const BString & installPath)694 BPackageInfo::SetInstallPath(const BString& installPath)
695 {
696 fInstallPath = installPath;
697 }
698
699
700 void
SetFileName(const BString & fileName)701 BPackageInfo::SetFileName(const BString& fileName)
702 {
703 fFileName = fileName;
704 }
705
706
707 void
SetVersion(const BPackageVersion & version)708 BPackageInfo::SetVersion(const BPackageVersion& version)
709 {
710 fVersion = version;
711 }
712
713
714 void
SetFlags(uint32 flags)715 BPackageInfo::SetFlags(uint32 flags)
716 {
717 fFlags = flags;
718 }
719
720
721 void
SetArchitecture(BPackageArchitecture architecture)722 BPackageInfo::SetArchitecture(BPackageArchitecture architecture)
723 {
724 fArchitecture = architecture;
725 }
726
727
728 void
ClearCopyrightList()729 BPackageInfo::ClearCopyrightList()
730 {
731 fCopyrightList.MakeEmpty();
732 }
733
734
735 status_t
AddCopyright(const BString & copyright)736 BPackageInfo::AddCopyright(const BString& copyright)
737 {
738 return fCopyrightList.Add(copyright) ? B_OK : B_ERROR;
739 }
740
741
742 void
ClearLicenseList()743 BPackageInfo::ClearLicenseList()
744 {
745 fLicenseList.MakeEmpty();
746 }
747
748
749 status_t
AddLicense(const BString & license)750 BPackageInfo::AddLicense(const BString& license)
751 {
752 return fLicenseList.Add(license) ? B_OK : B_ERROR;
753 }
754
755
756 void
ClearURLList()757 BPackageInfo::ClearURLList()
758 {
759 fURLList.MakeEmpty();
760 }
761
762
763 status_t
AddURL(const BString & url)764 BPackageInfo::AddURL(const BString& url)
765 {
766 return fURLList.Add(url) ? B_OK : B_NO_MEMORY;
767 }
768
769
770 void
ClearSourceURLList()771 BPackageInfo::ClearSourceURLList()
772 {
773 fSourceURLList.MakeEmpty();
774 }
775
776
777 status_t
AddSourceURL(const BString & url)778 BPackageInfo::AddSourceURL(const BString& url)
779 {
780 return fSourceURLList.Add(url) ? B_OK : B_NO_MEMORY;
781 }
782
783
784 void
ClearGlobalWritableFileInfos()785 BPackageInfo::ClearGlobalWritableFileInfos()
786 {
787 fGlobalWritableFileInfos.MakeEmpty();
788 }
789
790
791 status_t
AddGlobalWritableFileInfo(const BGlobalWritableFileInfo & info)792 BPackageInfo::AddGlobalWritableFileInfo(const BGlobalWritableFileInfo& info)
793 {
794 BGlobalWritableFileInfo* newInfo
795 = new (std::nothrow) BGlobalWritableFileInfo(info);
796 if (newInfo == NULL || !fGlobalWritableFileInfos.AddItem(newInfo)) {
797 delete newInfo;
798 return B_NO_MEMORY;
799 }
800
801 return B_OK;
802 }
803
804
805 void
ClearUserSettingsFileInfos()806 BPackageInfo::ClearUserSettingsFileInfos()
807 {
808 fUserSettingsFileInfos.MakeEmpty();
809 }
810
811
812 status_t
AddUserSettingsFileInfo(const BUserSettingsFileInfo & info)813 BPackageInfo::AddUserSettingsFileInfo(const BUserSettingsFileInfo& info)
814 {
815 BUserSettingsFileInfo* newInfo
816 = new (std::nothrow) BUserSettingsFileInfo(info);
817 if (newInfo == NULL || !fUserSettingsFileInfos.AddItem(newInfo)) {
818 delete newInfo;
819 return B_NO_MEMORY;
820 }
821
822 return B_OK;
823 }
824
825
826 void
ClearUsers()827 BPackageInfo::ClearUsers()
828 {
829 fUsers.MakeEmpty();
830 }
831
832
833 status_t
AddUser(const BUser & user)834 BPackageInfo::AddUser(const BUser& user)
835 {
836 BUser* newUser = new (std::nothrow) BUser(user);
837 if (newUser == NULL || !fUsers.AddItem(newUser)) {
838 delete newUser;
839 return B_NO_MEMORY;
840 }
841
842 return B_OK;
843 }
844
845
846 void
ClearGroups()847 BPackageInfo::ClearGroups()
848 {
849 fGroups.MakeEmpty();
850 }
851
852
853 status_t
AddGroup(const BString & group)854 BPackageInfo::AddGroup(const BString& group)
855 {
856 return fGroups.Add(group) ? B_OK : B_NO_MEMORY;
857 }
858
859
860 void
ClearPostInstallScripts()861 BPackageInfo::ClearPostInstallScripts()
862 {
863 fPostInstallScripts.MakeEmpty();
864 }
865
866
867 void
ClearPreUninstallScripts()868 BPackageInfo::ClearPreUninstallScripts()
869 {
870 fPreUninstallScripts.MakeEmpty();
871 }
872
873
874 status_t
AddPostInstallScript(const BString & path)875 BPackageInfo::AddPostInstallScript(const BString& path)
876 {
877 return fPostInstallScripts.Add(path) ? B_OK : B_NO_MEMORY;
878 }
879
880
881 status_t
AddPreUninstallScript(const BString & path)882 BPackageInfo::AddPreUninstallScript(const BString& path)
883 {
884 return fPreUninstallScripts.Add(path) ? B_OK : B_NO_MEMORY;
885 }
886
887
888 void
ClearProvidesList()889 BPackageInfo::ClearProvidesList()
890 {
891 fProvidesList.MakeEmpty();
892 }
893
894
895 status_t
AddProvides(const BPackageResolvable & provides)896 BPackageInfo::AddProvides(const BPackageResolvable& provides)
897 {
898 BPackageResolvable* newProvides
899 = new (std::nothrow) BPackageResolvable(provides);
900 if (newProvides == NULL)
901 return B_NO_MEMORY;
902
903 return fProvidesList.AddItem(newProvides) ? B_OK : B_ERROR;
904 }
905
906
907 void
ClearRequiresList()908 BPackageInfo::ClearRequiresList()
909 {
910 fRequiresList.MakeEmpty();
911 }
912
913
914 status_t
AddRequires(const BPackageResolvableExpression & packageRequires)915 BPackageInfo::AddRequires(const BPackageResolvableExpression& packageRequires)
916 {
917 BPackageResolvableExpression* newRequires
918 = new (std::nothrow) BPackageResolvableExpression(packageRequires);
919 if (newRequires == NULL)
920 return B_NO_MEMORY;
921
922 return fRequiresList.AddItem(newRequires) ? B_OK : B_ERROR;
923 }
924
925
926 void
ClearSupplementsList()927 BPackageInfo::ClearSupplementsList()
928 {
929 fSupplementsList.MakeEmpty();
930 }
931
932
933 status_t
AddSupplements(const BPackageResolvableExpression & supplements)934 BPackageInfo::AddSupplements(const BPackageResolvableExpression& supplements)
935 {
936 BPackageResolvableExpression* newSupplements
937 = new (std::nothrow) BPackageResolvableExpression(supplements);
938 if (newSupplements == NULL)
939 return B_NO_MEMORY;
940
941 return fSupplementsList.AddItem(newSupplements) ? B_OK : B_ERROR;
942 }
943
944
945 void
ClearConflictsList()946 BPackageInfo::ClearConflictsList()
947 {
948 fConflictsList.MakeEmpty();
949 }
950
951
952 status_t
AddConflicts(const BPackageResolvableExpression & conflicts)953 BPackageInfo::AddConflicts(const BPackageResolvableExpression& conflicts)
954 {
955 BPackageResolvableExpression* newConflicts
956 = new (std::nothrow) BPackageResolvableExpression(conflicts);
957 if (newConflicts == NULL)
958 return B_NO_MEMORY;
959
960 return fConflictsList.AddItem(newConflicts) ? B_OK : B_ERROR;
961 }
962
963
964 void
ClearFreshensList()965 BPackageInfo::ClearFreshensList()
966 {
967 fFreshensList.MakeEmpty();
968 }
969
970
971 status_t
AddFreshens(const BPackageResolvableExpression & freshens)972 BPackageInfo::AddFreshens(const BPackageResolvableExpression& freshens)
973 {
974 BPackageResolvableExpression* newFreshens
975 = new (std::nothrow) BPackageResolvableExpression(freshens);
976 if (newFreshens == NULL)
977 return B_NO_MEMORY;
978
979 return fFreshensList.AddItem(newFreshens) ? B_OK : B_ERROR;
980 }
981
982
983 void
ClearReplacesList()984 BPackageInfo::ClearReplacesList()
985 {
986 fReplacesList.MakeEmpty();
987 }
988
989
990 status_t
AddReplaces(const BString & replaces)991 BPackageInfo::AddReplaces(const BString& replaces)
992 {
993 return fReplacesList.Add(BString(replaces).ToLower()) ? B_OK : B_ERROR;
994 }
995
996
997 void
Clear()998 BPackageInfo::Clear()
999 {
1000 fName.Truncate(0);
1001 fSummary.Truncate(0);
1002 fDescription.Truncate(0);
1003 fVendor.Truncate(0);
1004 fPackager.Truncate(0);
1005 fBasePackage.Truncate(0);
1006 fChecksum.Truncate(0);
1007 fInstallPath.Truncate(0);
1008 fFileName.Truncate(0);
1009 fFlags = 0;
1010 fArchitecture = B_PACKAGE_ARCHITECTURE_ENUM_COUNT;
1011 fVersion.Clear();
1012 fCopyrightList.MakeEmpty();
1013 fLicenseList.MakeEmpty();
1014 fURLList.MakeEmpty();
1015 fSourceURLList.MakeEmpty();
1016 fGlobalWritableFileInfos.MakeEmpty();
1017 fUserSettingsFileInfos.MakeEmpty();
1018 fUsers.MakeEmpty();
1019 fGroups.MakeEmpty();
1020 fPostInstallScripts.MakeEmpty();
1021 fPreUninstallScripts.MakeEmpty();
1022 fRequiresList.MakeEmpty();
1023 fProvidesList.MakeEmpty();
1024 fSupplementsList.MakeEmpty();
1025 fConflictsList.MakeEmpty();
1026 fFreshensList.MakeEmpty();
1027 fReplacesList.MakeEmpty();
1028 }
1029
1030
1031 status_t
Archive(BMessage * archive,bool deep) const1032 BPackageInfo::Archive(BMessage* archive, bool deep) const
1033 {
1034 status_t error = BArchivable::Archive(archive, deep);
1035 if (error != B_OK)
1036 return error;
1037
1038 if ((error = archive->AddString("name", fName)) != B_OK
1039 || (error = archive->AddString("summary", fSummary)) != B_OK
1040 || (error = archive->AddString("description", fDescription)) != B_OK
1041 || (error = archive->AddString("vendor", fVendor)) != B_OK
1042 || (error = archive->AddString("packager", fPackager)) != B_OK
1043 || (error = archive->AddString("basePackage", fBasePackage)) != B_OK
1044 || (error = archive->AddUInt32("flags", fFlags)) != B_OK
1045 || (error = archive->AddInt32("architecture", fArchitecture)) != B_OK
1046 || (error = _AddVersion(archive, "version", fVersion)) != B_OK
1047 || (error = archive->AddStrings("copyrights", fCopyrightList))
1048 != B_OK
1049 || (error = archive->AddStrings("licenses", fLicenseList)) != B_OK
1050 || (error = archive->AddStrings("urls", fURLList)) != B_OK
1051 || (error = archive->AddStrings("source-urls", fSourceURLList))
1052 != B_OK
1053 || (error = _AddGlobalWritableFileInfos(archive,
1054 "global-writable-files", fGlobalWritableFileInfos)) != B_OK
1055 || (error = _AddUserSettingsFileInfos(archive,
1056 "user-settings-files", fUserSettingsFileInfos)) != B_OK
1057 || (error = _AddUsers(archive, "users", fUsers)) != B_OK
1058 || (error = archive->AddStrings("groups", fGroups)) != B_OK
1059 || (error = archive->AddStrings("post-install-scripts",
1060 fPostInstallScripts)) != B_OK
1061 || (error = archive->AddStrings("pre-uninstall-scripts",
1062 fPreUninstallScripts)) != B_OK
1063 || (error = _AddResolvables(archive, "provides", fProvidesList)) != B_OK
1064 || (error = _AddResolvableExpressions(archive, "requires",
1065 fRequiresList)) != B_OK
1066 || (error = _AddResolvableExpressions(archive, "supplements",
1067 fSupplementsList)) != B_OK
1068 || (error = _AddResolvableExpressions(archive, "conflicts",
1069 fConflictsList)) != B_OK
1070 || (error = _AddResolvableExpressions(archive, "freshens",
1071 fFreshensList)) != B_OK
1072 || (error = archive->AddStrings("replaces", fReplacesList)) != B_OK
1073 || (error = archive->AddString("checksum", fChecksum)) != B_OK
1074 || (error = archive->AddString("install-path", fInstallPath)) != B_OK
1075 || (error = archive->AddString("file-name", fFileName)) != B_OK) {
1076 return error;
1077 }
1078
1079 return B_OK;
1080 }
1081
1082
1083 /*static*/ BArchivable*
Instantiate(BMessage * archive)1084 BPackageInfo::Instantiate(BMessage* archive)
1085 {
1086 if (validate_instantiation(archive, "BPackageInfo"))
1087 return new(std::nothrow) BPackageInfo(archive);
1088 return NULL;
1089 }
1090
1091
1092 status_t
GetConfigString(BString & _string) const1093 BPackageInfo::GetConfigString(BString& _string) const
1094 {
1095 return StringBuilder()
1096 .Write("name", fName)
1097 .Write("version", fVersion)
1098 .Write("summary", fSummary)
1099 .Write("description", fDescription)
1100 .Write("vendor", fVendor)
1101 .Write("packager", fPackager)
1102 .Write("architecture", kArchitectureNames[fArchitecture])
1103 .Write("copyrights", fCopyrightList)
1104 .Write("licenses", fLicenseList)
1105 .Write("urls", fURLList)
1106 .Write("source-urls", fSourceURLList)
1107 .Write("global-writable-files", fGlobalWritableFileInfos)
1108 .Write("user-settings-files", fUserSettingsFileInfos)
1109 .Write("users", fUsers)
1110 .Write("groups", fGroups)
1111 .Write("post-install-scripts", fPostInstallScripts)
1112 .Write("pre-uninstall-scripts", fPreUninstallScripts)
1113 .Write("provides", fProvidesList)
1114 .BeginRequires(fBasePackage)
1115 .Write("requires", fRequiresList)
1116 .EndRequires()
1117 .Write("supplements", fSupplementsList)
1118 .Write("conflicts", fConflictsList)
1119 .Write("freshens", fFreshensList)
1120 .Write("replaces", fReplacesList)
1121 .WriteFlags("flags", fFlags)
1122 .Write("checksum", fChecksum)
1123 .GetString(_string);
1124 // Note: fInstallPath and fFileName can not be specified via .PackageInfo.
1125 }
1126
1127
1128 BString
ToString() const1129 BPackageInfo::ToString() const
1130 {
1131 BString string;
1132 GetConfigString(string);
1133 return string;
1134 }
1135
1136
1137 /*static*/ status_t
GetArchitectureByName(const BString & name,BPackageArchitecture & _architecture)1138 BPackageInfo::GetArchitectureByName(const BString& name,
1139 BPackageArchitecture& _architecture)
1140 {
1141 for (int i = 0; i < B_PACKAGE_ARCHITECTURE_ENUM_COUNT; ++i) {
1142 if (name.ICompare(kArchitectureNames[i]) == 0) {
1143 _architecture = (BPackageArchitecture)i;
1144 return B_OK;
1145 }
1146 }
1147 return B_NAME_NOT_FOUND;
1148 }
1149
1150
1151 /*static*/ status_t
ParseVersionString(const BString & string,bool revisionIsOptional,BPackageVersion & _version,ParseErrorListener * listener)1152 BPackageInfo::ParseVersionString(const BString& string, bool revisionIsOptional,
1153 BPackageVersion& _version, ParseErrorListener* listener)
1154 {
1155 return Parser(listener).ParseVersion(string, revisionIsOptional, _version);
1156 }
1157
1158
1159 /*static*/ status_t
ParseResolvableString(const BString & string,BPackageResolvable & _expression,ParseErrorListener * listener)1160 BPackageInfo::ParseResolvableString(const BString& string,
1161 BPackageResolvable& _expression, ParseErrorListener* listener)
1162 {
1163 return Parser(listener).ParseResolvable(string, _expression);
1164 }
1165
1166
1167 /*static*/ status_t
ParseResolvableExpressionString(const BString & string,BPackageResolvableExpression & _expression,ParseErrorListener * listener)1168 BPackageInfo::ParseResolvableExpressionString(const BString& string,
1169 BPackageResolvableExpression& _expression, ParseErrorListener* listener)
1170 {
1171 return Parser(listener).ParseResolvableExpression(string, _expression);
1172 }
1173
1174
1175 status_t
_ReadFromPackageFile(const PackageFileLocation & fileLocation)1176 BPackageInfo::_ReadFromPackageFile(const PackageFileLocation& fileLocation)
1177 {
1178 BHPKG::BNoErrorOutput errorOutput;
1179
1180 // try current package file format version
1181 {
1182 BHPKG::BPackageReader packageReader(&errorOutput);
1183 status_t error = fileLocation.Path() != NULL
1184 ? packageReader.Init(fileLocation.Path())
1185 : packageReader.Init(fileLocation.FD(), false);
1186 if (error == B_OK) {
1187 BPackageInfoContentHandler handler(*this);
1188 return packageReader.ParseContent(&handler);
1189 }
1190
1191 if (error != B_MISMATCHED_VALUES)
1192 return error;
1193 }
1194
1195 // try package file format version 1
1196 BHPKG::V1::BPackageReader packageReader(&errorOutput);
1197 status_t error = fileLocation.Path() != NULL
1198 ? packageReader.Init(fileLocation.Path())
1199 : packageReader.Init(fileLocation.FD(), false);
1200 if (error != B_OK)
1201 return error;
1202
1203 BHPKG::V1::BPackageInfoContentHandler handler(*this);
1204 return packageReader.ParseContent(&handler);
1205 }
1206
1207
1208 /*static*/ status_t
_AddVersion(BMessage * archive,const char * field,const BPackageVersion & version)1209 BPackageInfo::_AddVersion(BMessage* archive, const char* field,
1210 const BPackageVersion& version)
1211 {
1212 // Storing BPackageVersion::ToString() would be nice, but the corresponding
1213 // constructor only works for valid versions and we might want to store
1214 // invalid versions as well.
1215
1216 // major
1217 size_t fieldLength = strlen(field);
1218 FieldName fieldName(field, ":major");
1219 if (!fieldName.IsValid())
1220 return B_BAD_VALUE;
1221
1222 status_t error = archive->AddString(fieldName, version.Major());
1223 if (error != B_OK)
1224 return error;
1225
1226 // minor
1227 if (!fieldName.ReplaceSuffix(fieldLength, ":minor"))
1228 return B_BAD_VALUE;
1229
1230 error = archive->AddString(fieldName, version.Minor());
1231 if (error != B_OK)
1232 return error;
1233
1234 // micro
1235 if (!fieldName.ReplaceSuffix(fieldLength, ":micro"))
1236 return B_BAD_VALUE;
1237
1238 error = archive->AddString(fieldName, version.Micro());
1239 if (error != B_OK)
1240 return error;
1241
1242 // pre-release
1243 if (!fieldName.ReplaceSuffix(fieldLength, ":pre"))
1244 return B_BAD_VALUE;
1245
1246 error = archive->AddString(fieldName, version.PreRelease());
1247 if (error != B_OK)
1248 return error;
1249
1250 // revision
1251 if (!fieldName.ReplaceSuffix(fieldLength, ":revision"))
1252 return B_BAD_VALUE;
1253
1254 return archive->AddUInt32(fieldName, version.Revision());
1255 }
1256
1257
1258 /*static*/ status_t
_AddResolvables(BMessage * archive,const char * field,const ResolvableList & resolvables)1259 BPackageInfo::_AddResolvables(BMessage* archive, const char* field,
1260 const ResolvableList& resolvables)
1261 {
1262 // construct the field names we need
1263 FieldName nameField(field, ":name");
1264 FieldName typeField(field, ":type");
1265 FieldName versionField(field, ":version");
1266 FieldName compatibleVersionField(field, ":compat");
1267
1268 if (!nameField.IsValid() || !typeField.IsValid() || !versionField.IsValid()
1269 || !compatibleVersionField.IsValid()) {
1270 return B_BAD_VALUE;
1271 }
1272
1273 // add fields
1274 int32 count = resolvables.CountItems();
1275 for (int32 i = 0; i < count; i++) {
1276 const BPackageResolvable* resolvable = resolvables.ItemAt(i);
1277 status_t error;
1278 if ((error = archive->AddString(nameField, resolvable->Name())) != B_OK
1279 || (error = _AddVersion(archive, versionField,
1280 resolvable->Version())) != B_OK
1281 || (error = _AddVersion(archive, compatibleVersionField,
1282 resolvable->CompatibleVersion())) != B_OK) {
1283 return error;
1284 }
1285 }
1286
1287 return B_OK;
1288 }
1289
1290
1291 /*static*/ status_t
_AddResolvableExpressions(BMessage * archive,const char * field,const ResolvableExpressionList & expressions)1292 BPackageInfo::_AddResolvableExpressions(BMessage* archive, const char* field,
1293 const ResolvableExpressionList& expressions)
1294 {
1295 // construct the field names we need
1296 FieldName nameField(field, ":name");
1297 FieldName operatorField(field, ":operator");
1298 FieldName versionField(field, ":version");
1299
1300 if (!nameField.IsValid() || !operatorField.IsValid()
1301 || !versionField.IsValid()) {
1302 return B_BAD_VALUE;
1303 }
1304
1305 // add fields
1306 int32 count = expressions.CountItems();
1307 for (int32 i = 0; i < count; i++) {
1308 const BPackageResolvableExpression* expression = expressions.ItemAt(i);
1309 status_t error;
1310 if ((error = archive->AddString(nameField, expression->Name())) != B_OK
1311 || (error = archive->AddInt32(operatorField,
1312 expression->Operator())) != B_OK
1313 || (error = _AddVersion(archive, versionField,
1314 expression->Version())) != B_OK) {
1315 return error;
1316 }
1317 }
1318
1319 return B_OK;
1320 }
1321
1322
1323 /*static*/ status_t
_AddGlobalWritableFileInfos(BMessage * archive,const char * field,const GlobalWritableFileInfoList & infos)1324 BPackageInfo::_AddGlobalWritableFileInfos(BMessage* archive, const char* field,
1325 const GlobalWritableFileInfoList& infos)
1326 {
1327 // construct the field names we need
1328 FieldName pathField(field, ":path");
1329 FieldName updateTypeField(field, ":updateType");
1330 FieldName isDirectoryField(field, ":isDirectory");
1331
1332 if (!pathField.IsValid() || !updateTypeField.IsValid()
1333 || !isDirectoryField.IsValid()) {
1334 return B_BAD_VALUE;
1335 }
1336
1337 // add fields
1338 int32 count = infos.CountItems();
1339 for (int32 i = 0; i < count; i++) {
1340 const BGlobalWritableFileInfo* info = infos.ItemAt(i);
1341 status_t error;
1342 if ((error = archive->AddString(pathField, info->Path())) != B_OK
1343 || (error = archive->AddInt32(updateTypeField, info->UpdateType()))
1344 != B_OK
1345 || (error = archive->AddBool(isDirectoryField,
1346 info->IsDirectory())) != B_OK) {
1347 return error;
1348 }
1349 }
1350
1351 return B_OK;
1352 }
1353
1354
1355 /*static*/ status_t
_AddUserSettingsFileInfos(BMessage * archive,const char * field,const UserSettingsFileInfoList & infos)1356 BPackageInfo::_AddUserSettingsFileInfos(BMessage* archive, const char* field,
1357 const UserSettingsFileInfoList& infos)
1358 {
1359 // construct the field names we need
1360 FieldName pathField(field, ":path");
1361 FieldName templatePathField(field, ":templatePath");
1362 FieldName isDirectoryField(field, ":isDirectory");
1363
1364 if (!pathField.IsValid() || !templatePathField.IsValid()
1365 || !isDirectoryField.IsValid()) {
1366 return B_BAD_VALUE;
1367 }
1368
1369 // add fields
1370 int32 count = infos.CountItems();
1371 for (int32 i = 0; i < count; i++) {
1372 const BUserSettingsFileInfo* info = infos.ItemAt(i);
1373 status_t error;
1374 if ((error = archive->AddString(pathField, info->Path())) != B_OK
1375 || (error = archive->AddString(templatePathField,
1376 info->TemplatePath())) != B_OK
1377 || (error = archive->AddBool(isDirectoryField,
1378 info->IsDirectory())) != B_OK) {
1379 return error;
1380 }
1381 }
1382
1383 return B_OK;
1384 }
1385
1386
1387 /*static*/ status_t
_AddUsers(BMessage * archive,const char * field,const UserList & users)1388 BPackageInfo::_AddUsers(BMessage* archive, const char* field,
1389 const UserList& users)
1390 {
1391 // construct the field names we need
1392 FieldName nameField(field, ":name");
1393 FieldName realNameField(field, ":realName");
1394 FieldName homeField(field, ":home");
1395 FieldName shellField(field, ":shell");
1396 FieldName groupsField(field, ":groups");
1397
1398 if (!nameField.IsValid() || !realNameField.IsValid() || !homeField.IsValid()
1399 || !shellField.IsValid() || !groupsField.IsValid())
1400 return B_BAD_VALUE;
1401
1402 // add fields
1403 int32 count = users.CountItems();
1404 for (int32 i = 0; i < count; i++) {
1405 const BUser* user = users.ItemAt(i);
1406 BString groups = user->Groups().Join(" ");
1407 if (groups.IsEmpty() && !user->Groups().IsEmpty())
1408 return B_NO_MEMORY;
1409
1410 status_t error;
1411 if ((error = archive->AddString(nameField, user->Name())) != B_OK
1412 || (error = archive->AddString(realNameField, user->RealName()))
1413 != B_OK
1414 || (error = archive->AddString(homeField, user->Home())) != B_OK
1415 || (error = archive->AddString(shellField, user->Shell())) != B_OK
1416 || (error = archive->AddString(groupsField, groups)) != B_OK) {
1417 return error;
1418 }
1419 }
1420
1421 return B_OK;
1422 }
1423
1424
1425 /*static*/ status_t
_ExtractVersion(BMessage * archive,const char * field,int32 index,BPackageVersion & _version)1426 BPackageInfo::_ExtractVersion(BMessage* archive, const char* field, int32 index,
1427 BPackageVersion& _version)
1428 {
1429 // major
1430 size_t fieldLength = strlen(field);
1431 FieldName fieldName(field, ":major");
1432 if (!fieldName.IsValid())
1433 return B_BAD_VALUE;
1434
1435 BString major;
1436 status_t error = archive->FindString(fieldName, index, &major);
1437 if (error != B_OK)
1438 return error;
1439
1440 // minor
1441 if (!fieldName.ReplaceSuffix(fieldLength, ":minor"))
1442 return B_BAD_VALUE;
1443
1444 BString minor;
1445 error = archive->FindString(fieldName, index, &minor);
1446 if (error != B_OK)
1447 return error;
1448
1449 // micro
1450 if (!fieldName.ReplaceSuffix(fieldLength, ":micro"))
1451 return B_BAD_VALUE;
1452
1453 BString micro;
1454 error = archive->FindString(fieldName, index, µ);
1455 if (error != B_OK)
1456 return error;
1457
1458 // pre-release
1459 if (!fieldName.ReplaceSuffix(fieldLength, ":pre"))
1460 return B_BAD_VALUE;
1461
1462 BString preRelease;
1463 error = archive->FindString(fieldName, index, &preRelease);
1464 if (error != B_OK)
1465 return error;
1466
1467 // revision
1468 if (!fieldName.ReplaceSuffix(fieldLength, ":revision"))
1469 return B_BAD_VALUE;
1470
1471 uint32 revision;
1472 error = archive->FindUInt32(fieldName, index, &revision);
1473 if (error != B_OK)
1474 return error;
1475
1476 _version.SetTo(major, minor, micro, preRelease, revision);
1477 return B_OK;
1478 }
1479
1480
1481 /*static*/ status_t
_ExtractStringList(BMessage * archive,const char * field,BStringList & _list)1482 BPackageInfo::_ExtractStringList(BMessage* archive, const char* field,
1483 BStringList& _list)
1484 {
1485 status_t error = archive->FindStrings(field, &_list);
1486 return error == B_NAME_NOT_FOUND ? B_OK : error;
1487 // If the field doesn't exist, that's OK.
1488 }
1489
1490
1491 /*static*/ status_t
_ExtractResolvables(BMessage * archive,const char * field,ResolvableList & _resolvables)1492 BPackageInfo::_ExtractResolvables(BMessage* archive, const char* field,
1493 ResolvableList& _resolvables)
1494 {
1495 // construct the field names we need
1496 FieldName nameField(field, ":name");
1497 FieldName typeField(field, ":type");
1498 FieldName versionField(field, ":version");
1499 FieldName compatibleVersionField(field, ":compat");
1500
1501 if (!nameField.IsValid() || !typeField.IsValid() || !versionField.IsValid()
1502 || !compatibleVersionField.IsValid()) {
1503 return B_BAD_VALUE;
1504 }
1505
1506 // get the number of items
1507 type_code type;
1508 int32 count;
1509 if (archive->GetInfo(nameField, &type, &count) != B_OK) {
1510 // the field is missing
1511 return B_OK;
1512 }
1513
1514 // extract fields
1515 for (int32 i = 0; i < count; i++) {
1516 BString name;
1517 status_t error = archive->FindString(nameField, i, &name);
1518 if (error != B_OK)
1519 return error;
1520
1521 BPackageVersion version;
1522 error = _ExtractVersion(archive, versionField, i, version);
1523 if (error != B_OK)
1524 return error;
1525
1526 BPackageVersion compatibleVersion;
1527 error = _ExtractVersion(archive, compatibleVersionField, i,
1528 compatibleVersion);
1529 if (error != B_OK)
1530 return error;
1531
1532 BPackageResolvable* resolvable = new(std::nothrow) BPackageResolvable(
1533 name, version, compatibleVersion);
1534 if (resolvable == NULL || !_resolvables.AddItem(resolvable)) {
1535 delete resolvable;
1536 return B_NO_MEMORY;
1537 }
1538 }
1539
1540 return B_OK;
1541 }
1542
1543
1544 /*static*/ status_t
_ExtractResolvableExpressions(BMessage * archive,const char * field,ResolvableExpressionList & _expressions)1545 BPackageInfo::_ExtractResolvableExpressions(BMessage* archive,
1546 const char* field, ResolvableExpressionList& _expressions)
1547 {
1548 // construct the field names we need
1549 FieldName nameField(field, ":name");
1550 FieldName operatorField(field, ":operator");
1551 FieldName versionField(field, ":version");
1552
1553 if (!nameField.IsValid() || !operatorField.IsValid()
1554 || !versionField.IsValid()) {
1555 return B_BAD_VALUE;
1556 }
1557
1558 // get the number of items
1559 type_code type;
1560 int32 count;
1561 if (archive->GetInfo(nameField, &type, &count) != B_OK) {
1562 // the field is missing
1563 return B_OK;
1564 }
1565
1566 // extract fields
1567 for (int32 i = 0; i < count; i++) {
1568 BString name;
1569 status_t error = archive->FindString(nameField, i, &name);
1570 if (error != B_OK)
1571 return error;
1572
1573 int32 operatorType;
1574 error = archive->FindInt32(operatorField, i, &operatorType);
1575 if (error != B_OK)
1576 return error;
1577 if (operatorType < 0
1578 || operatorType > B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
1579 return B_BAD_DATA;
1580 }
1581
1582 BPackageVersion version;
1583 error = _ExtractVersion(archive, versionField, i, version);
1584 if (error != B_OK)
1585 return error;
1586
1587 BPackageResolvableExpression* expression
1588 = new(std::nothrow) BPackageResolvableExpression(name,
1589 (BPackageResolvableOperator)operatorType, version);
1590 if (expression == NULL || !_expressions.AddItem(expression)) {
1591 delete expression;
1592 return B_NO_MEMORY;
1593 }
1594 }
1595
1596 return B_OK;
1597 }
1598
1599
1600 /*static*/ status_t
_ExtractGlobalWritableFileInfos(BMessage * archive,const char * field,GlobalWritableFileInfoList & _infos)1601 BPackageInfo::_ExtractGlobalWritableFileInfos(BMessage* archive,
1602 const char* field, GlobalWritableFileInfoList& _infos)
1603 {
1604 // construct the field names we need
1605 FieldName pathField(field, ":path");
1606 FieldName updateTypeField(field, ":updateType");
1607 FieldName isDirectoryField(field, ":isDirectory");
1608
1609 if (!pathField.IsValid() || !updateTypeField.IsValid()
1610 || !isDirectoryField.IsValid()) {
1611 return B_BAD_VALUE;
1612 }
1613
1614 // get the number of items
1615 type_code type;
1616 int32 count;
1617 if (archive->GetInfo(pathField, &type, &count) != B_OK) {
1618 // the field is missing
1619 return B_OK;
1620 }
1621
1622 // extract fields
1623 for (int32 i = 0; i < count; i++) {
1624 BString path;
1625 status_t error = archive->FindString(pathField, i, &path);
1626 if (error != B_OK)
1627 return error;
1628
1629 int32 updateType;
1630 error = archive->FindInt32(updateTypeField, i, &updateType);
1631 if (error != B_OK)
1632 return error;
1633 if (updateType < 0
1634 || updateType > B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT) {
1635 return B_BAD_DATA;
1636 }
1637
1638 bool isDirectory;
1639 error = archive->FindBool(isDirectoryField, i, &isDirectory);
1640 if (error != B_OK)
1641 return error;
1642
1643 BGlobalWritableFileInfo* info
1644 = new(std::nothrow) BGlobalWritableFileInfo(path,
1645 (BWritableFileUpdateType)updateType, isDirectory);
1646 if (info == NULL || !_infos.AddItem(info)) {
1647 delete info;
1648 return B_NO_MEMORY;
1649 }
1650 }
1651
1652 return B_OK;
1653 }
1654
1655
1656 /*static*/ status_t
_ExtractUserSettingsFileInfos(BMessage * archive,const char * field,UserSettingsFileInfoList & _infos)1657 BPackageInfo::_ExtractUserSettingsFileInfos(BMessage* archive,
1658 const char* field, UserSettingsFileInfoList& _infos)
1659 {
1660 // construct the field names we need
1661 FieldName pathField(field, ":path");
1662 FieldName templatePathField(field, ":templatePath");
1663 FieldName isDirectoryField(field, ":isDirectory");
1664
1665 if (!pathField.IsValid() || !templatePathField.IsValid()
1666 || !isDirectoryField.IsValid()) {
1667 return B_BAD_VALUE;
1668 }
1669
1670 // get the number of items
1671 type_code type;
1672 int32 count;
1673 if (archive->GetInfo(pathField, &type, &count) != B_OK) {
1674 // the field is missing
1675 return B_OK;
1676 }
1677
1678 // extract fields
1679 for (int32 i = 0; i < count; i++) {
1680 BString path;
1681 status_t error = archive->FindString(pathField, i, &path);
1682 if (error != B_OK)
1683 return error;
1684
1685 BString templatePath;
1686 error = archive->FindString(templatePathField, i, &templatePath);
1687 if (error != B_OK)
1688 return error;
1689
1690 bool isDirectory;
1691 error = archive->FindBool(isDirectoryField, i, &isDirectory);
1692 if (error != B_OK)
1693 return error;
1694
1695 BUserSettingsFileInfo* info = isDirectory
1696 ? new(std::nothrow) BUserSettingsFileInfo(path, true)
1697 : new(std::nothrow) BUserSettingsFileInfo(path, templatePath);
1698 if (info == NULL || !_infos.AddItem(info)) {
1699 delete info;
1700 return B_NO_MEMORY;
1701 }
1702 }
1703
1704 return B_OK;
1705 }
1706
1707
1708 /*static*/ status_t
_ExtractUsers(BMessage * archive,const char * field,UserList & _users)1709 BPackageInfo::_ExtractUsers(BMessage* archive, const char* field,
1710 UserList& _users)
1711 {
1712 // construct the field names we need
1713 FieldName nameField(field, ":name");
1714 FieldName realNameField(field, ":realName");
1715 FieldName homeField(field, ":home");
1716 FieldName shellField(field, ":shell");
1717 FieldName groupsField(field, ":groups");
1718
1719 if (!nameField.IsValid() || !realNameField.IsValid() || !homeField.IsValid()
1720 || !shellField.IsValid() || !groupsField.IsValid())
1721 return B_BAD_VALUE;
1722
1723 // get the number of items
1724 type_code type;
1725 int32 count;
1726 if (archive->GetInfo(nameField, &type, &count) != B_OK) {
1727 // the field is missing
1728 return B_OK;
1729 }
1730
1731 // extract fields
1732 for (int32 i = 0; i < count; i++) {
1733 BString name;
1734 status_t error = archive->FindString(nameField, i, &name);
1735 if (error != B_OK)
1736 return error;
1737
1738 BString realName;
1739 error = archive->FindString(realNameField, i, &realName);
1740 if (error != B_OK)
1741 return error;
1742
1743 BString home;
1744 error = archive->FindString(homeField, i, &home);
1745 if (error != B_OK)
1746 return error;
1747
1748 BString shell;
1749 error = archive->FindString(shellField, i, &shell);
1750 if (error != B_OK)
1751 return error;
1752
1753 BString groupsString;
1754 error = archive->FindString(groupsField, i, &groupsString);
1755 if (error != B_OK)
1756 return error;
1757
1758 BStringList groups;
1759 if (!groupsString.IsEmpty() && !groupsString.Split(" ", false, groups))
1760 return B_NO_MEMORY;
1761
1762 BUser* user = new(std::nothrow) BUser(name, realName, home, shell,
1763 groups);
1764 if (user == NULL || !_users.AddItem(user)) {
1765 delete user;
1766 return B_NO_MEMORY;
1767 }
1768 }
1769
1770 return B_OK;
1771 }
1772
1773
1774 } // namespace BPackageKit
1775