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