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