xref: /haiku/src/kits/package/PackageInfo.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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 {
91 	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 
105 	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 
118 	bool IsValid() const
119 	{
120 		return fFieldName[0] != '\0';
121 	}
122 
123 	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 {
137 	PackageFileLocation(const char* path)
138 		:
139 		fPath(path),
140 		fFD(-1)
141 	{
142 	}
143 
144 	PackageFileLocation(int fd)
145 		:
146 		fPath(NULL),
147 		fFD(fd)
148 	{
149 	}
150 
151 	const char* Path() const
152 	{
153 		return fPath;
154 	}
155 
156 	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 
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 
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 
272 BPackageInfo::~BPackageInfo()
273 {
274 }
275 
276 
277 status_t
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
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
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
331 BPackageInfo::ReadFromPackageFile(const char* path)
332 {
333 	return _ReadFromPackageFile(PackageFileLocation(path));
334 }
335 
336 
337 status_t
338 BPackageInfo::ReadFromPackageFile(int fd)
339 {
340 	return _ReadFromPackageFile(PackageFileLocation(fd));
341 }
342 
343 
344 status_t
345 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&
405 BPackageInfo::Name() const
406 {
407 	return fName;
408 }
409 
410 
411 const BString&
412 BPackageInfo::Summary() const
413 {
414 	return fSummary;
415 }
416 
417 
418 const BString&
419 BPackageInfo::Description() const
420 {
421 	return fDescription;
422 }
423 
424 
425 const BString&
426 BPackageInfo::Vendor() const
427 {
428 	return fVendor;
429 }
430 
431 
432 const BString&
433 BPackageInfo::Packager() const
434 {
435 	return fPackager;
436 }
437 
438 
439 const BString&
440 BPackageInfo::BasePackage() const
441 {
442 	return fBasePackage;
443 }
444 
445 
446 const BString&
447 BPackageInfo::Checksum() const
448 {
449 	return fChecksum;
450 }
451 
452 
453 const BString&
454 BPackageInfo::InstallPath() const
455 {
456 	return fInstallPath;
457 }
458 
459 
460 BString
461 BPackageInfo::FileName() const
462 {
463 	return fFileName.IsEmpty() ? CanonicalFileName() : fFileName;
464 }
465 
466 
467 uint32
468 BPackageInfo::Flags() const
469 {
470 	return fFlags;
471 }
472 
473 
474 BPackageArchitecture
475 BPackageInfo::Architecture() const
476 {
477 	return fArchitecture;
478 }
479 
480 
481 const char*
482 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&
493 BPackageInfo::Version() const
494 {
495 	return fVersion;
496 }
497 
498 
499 const BStringList&
500 BPackageInfo::CopyrightList() const
501 {
502 	return fCopyrightList;
503 }
504 
505 
506 const BStringList&
507 BPackageInfo::LicenseList() const
508 {
509 	return fLicenseList;
510 }
511 
512 
513 const BStringList&
514 BPackageInfo::URLList() const
515 {
516 	return fURLList;
517 }
518 
519 
520 const BStringList&
521 BPackageInfo::SourceURLList() const
522 {
523 	return fSourceURLList;
524 }
525 
526 
527 const BObjectList<BGlobalWritableFileInfo>&
528 BPackageInfo::GlobalWritableFileInfos() const
529 {
530 	return fGlobalWritableFileInfos;
531 }
532 
533 
534 const BObjectList<BUserSettingsFileInfo>&
535 BPackageInfo::UserSettingsFileInfos() const
536 {
537 	return fUserSettingsFileInfos;
538 }
539 
540 
541 const BObjectList<BUser>&
542 BPackageInfo::Users() const
543 {
544 	return fUsers;
545 }
546 
547 
548 const BStringList&
549 BPackageInfo::Groups() const
550 {
551 	return fGroups;
552 }
553 
554 
555 const BStringList&
556 BPackageInfo::PostInstallScripts() const
557 {
558 	return fPostInstallScripts;
559 }
560 
561 
562 const BStringList&
563 BPackageInfo::PreUninstallScripts() const
564 {
565 	return fPreUninstallScripts;
566 }
567 
568 
569 const BObjectList<BPackageResolvable>&
570 BPackageInfo::ProvidesList() const
571 {
572 	return fProvidesList;
573 }
574 
575 
576 const BObjectList<BPackageResolvableExpression>&
577 BPackageInfo::RequiresList() const
578 {
579 	return fRequiresList;
580 }
581 
582 
583 const BObjectList<BPackageResolvableExpression>&
584 BPackageInfo::SupplementsList() const
585 {
586 	return fSupplementsList;
587 }
588 
589 
590 const BObjectList<BPackageResolvableExpression>&
591 BPackageInfo::ConflictsList() const
592 {
593 	return fConflictsList;
594 }
595 
596 
597 const BObjectList<BPackageResolvableExpression>&
598 BPackageInfo::FreshensList() const
599 {
600 	return fFreshensList;
601 }
602 
603 
604 const BStringList&
605 BPackageInfo::ReplacesList() const
606 {
607 	return fReplacesList;
608 }
609 
610 
611 BString
612 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
623 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
644 BPackageInfo::SetName(const BString& name)
645 {
646 	fName = name;
647 	fName.ToLower();
648 }
649 
650 
651 void
652 BPackageInfo::SetSummary(const BString& summary)
653 {
654 	fSummary = summary;
655 }
656 
657 
658 void
659 BPackageInfo::SetDescription(const BString& description)
660 {
661 	fDescription = description;
662 }
663 
664 
665 void
666 BPackageInfo::SetVendor(const BString& vendor)
667 {
668 	fVendor = vendor;
669 }
670 
671 
672 void
673 BPackageInfo::SetPackager(const BString& packager)
674 {
675 	fPackager = packager;
676 }
677 
678 
679 void
680 BPackageInfo::SetBasePackage(const BString& basePackage)
681 {
682 	fBasePackage = basePackage;
683 }
684 
685 
686 void
687 BPackageInfo::SetChecksum(const BString& checksum)
688 {
689 	fChecksum = checksum;
690 }
691 
692 
693 void
694 BPackageInfo::SetInstallPath(const BString& installPath)
695 {
696 	fInstallPath = installPath;
697 }
698 
699 
700 void
701 BPackageInfo::SetFileName(const BString& fileName)
702 {
703 	fFileName = fileName;
704 }
705 
706 
707 void
708 BPackageInfo::SetVersion(const BPackageVersion& version)
709 {
710 	fVersion = version;
711 }
712 
713 
714 void
715 BPackageInfo::SetFlags(uint32 flags)
716 {
717 	fFlags = flags;
718 }
719 
720 
721 void
722 BPackageInfo::SetArchitecture(BPackageArchitecture architecture)
723 {
724 	fArchitecture = architecture;
725 }
726 
727 
728 void
729 BPackageInfo::ClearCopyrightList()
730 {
731 	fCopyrightList.MakeEmpty();
732 }
733 
734 
735 status_t
736 BPackageInfo::AddCopyright(const BString& copyright)
737 {
738 	return fCopyrightList.Add(copyright) ? B_OK : B_ERROR;
739 }
740 
741 
742 void
743 BPackageInfo::ClearLicenseList()
744 {
745 	fLicenseList.MakeEmpty();
746 }
747 
748 
749 status_t
750 BPackageInfo::AddLicense(const BString& license)
751 {
752 	return fLicenseList.Add(license) ? B_OK : B_ERROR;
753 }
754 
755 
756 void
757 BPackageInfo::ClearURLList()
758 {
759 	fURLList.MakeEmpty();
760 }
761 
762 
763 status_t
764 BPackageInfo::AddURL(const BString& url)
765 {
766 	return fURLList.Add(url) ? B_OK : B_NO_MEMORY;
767 }
768 
769 
770 void
771 BPackageInfo::ClearSourceURLList()
772 {
773 	fSourceURLList.MakeEmpty();
774 }
775 
776 
777 status_t
778 BPackageInfo::AddSourceURL(const BString& url)
779 {
780 	return fSourceURLList.Add(url) ? B_OK : B_NO_MEMORY;
781 }
782 
783 
784 void
785 BPackageInfo::ClearGlobalWritableFileInfos()
786 {
787 	fGlobalWritableFileInfos.MakeEmpty();
788 }
789 
790 
791 status_t
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
806 BPackageInfo::ClearUserSettingsFileInfos()
807 {
808 	fUserSettingsFileInfos.MakeEmpty();
809 }
810 
811 
812 status_t
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
827 BPackageInfo::ClearUsers()
828 {
829 	fUsers.MakeEmpty();
830 }
831 
832 
833 status_t
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
847 BPackageInfo::ClearGroups()
848 {
849 	fGroups.MakeEmpty();
850 }
851 
852 
853 status_t
854 BPackageInfo::AddGroup(const BString& group)
855 {
856 	return fGroups.Add(group) ? B_OK : B_NO_MEMORY;
857 }
858 
859 
860 void
861 BPackageInfo::ClearPostInstallScripts()
862 {
863 	fPostInstallScripts.MakeEmpty();
864 }
865 
866 
867 void
868 BPackageInfo::ClearPreUninstallScripts()
869 {
870 	fPreUninstallScripts.MakeEmpty();
871 }
872 
873 
874 status_t
875 BPackageInfo::AddPostInstallScript(const BString& path)
876 {
877 	return fPostInstallScripts.Add(path) ? B_OK : B_NO_MEMORY;
878 }
879 
880 
881 status_t
882 BPackageInfo::AddPreUninstallScript(const BString& path)
883 {
884 	return fPreUninstallScripts.Add(path) ? B_OK : B_NO_MEMORY;
885 }
886 
887 
888 void
889 BPackageInfo::ClearProvidesList()
890 {
891 	fProvidesList.MakeEmpty();
892 }
893 
894 
895 status_t
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
908 BPackageInfo::ClearRequiresList()
909 {
910 	fRequiresList.MakeEmpty();
911 }
912 
913 
914 status_t
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
927 BPackageInfo::ClearSupplementsList()
928 {
929 	fSupplementsList.MakeEmpty();
930 }
931 
932 
933 status_t
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
946 BPackageInfo::ClearConflictsList()
947 {
948 	fConflictsList.MakeEmpty();
949 }
950 
951 
952 status_t
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
965 BPackageInfo::ClearFreshensList()
966 {
967 	fFreshensList.MakeEmpty();
968 }
969 
970 
971 status_t
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
984 BPackageInfo::ClearReplacesList()
985 {
986 	fReplacesList.MakeEmpty();
987 }
988 
989 
990 status_t
991 BPackageInfo::AddReplaces(const BString& replaces)
992 {
993 	return fReplacesList.Add(BString(replaces).ToLower()) ? B_OK : B_ERROR;
994 }
995 
996 
997 void
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
1032 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*
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
1093 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
1129 BPackageInfo::ToString() const
1130 {
1131 	BString string;
1132 	GetConfigString(string);
1133 	return string;
1134 }
1135 
1136 
1137 /*static*/ status_t
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
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
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
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
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
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
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
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
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
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
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
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, &micro);
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
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
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
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
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
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
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