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