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