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::ParseResolvableExpressionString(const BString& string, 1161 BPackageResolvableExpression& _expression, ParseErrorListener* listener) 1162 { 1163 return Parser(listener).ParseResolvableExpression(string, _expression); 1164 } 1165 1166 1167 status_t 1168 BPackageInfo::_ReadFromPackageFile(const PackageFileLocation& fileLocation) 1169 { 1170 BHPKG::BNoErrorOutput errorOutput; 1171 1172 // try current package file format version 1173 { 1174 BHPKG::BPackageReader packageReader(&errorOutput); 1175 status_t error = fileLocation.Path() != NULL 1176 ? packageReader.Init(fileLocation.Path()) 1177 : packageReader.Init(fileLocation.FD(), false); 1178 if (error == B_OK) { 1179 BPackageInfoContentHandler handler(*this); 1180 return packageReader.ParseContent(&handler); 1181 } 1182 1183 if (error != B_MISMATCHED_VALUES) 1184 return error; 1185 } 1186 1187 // try package file format version 1 1188 BHPKG::V1::BPackageReader packageReader(&errorOutput); 1189 status_t error = fileLocation.Path() != NULL 1190 ? packageReader.Init(fileLocation.Path()) 1191 : packageReader.Init(fileLocation.FD(), false); 1192 if (error != B_OK) 1193 return error; 1194 1195 BHPKG::V1::BPackageInfoContentHandler handler(*this); 1196 return packageReader.ParseContent(&handler); 1197 } 1198 1199 1200 /*static*/ status_t 1201 BPackageInfo::_AddVersion(BMessage* archive, const char* field, 1202 const BPackageVersion& version) 1203 { 1204 // Storing BPackageVersion::ToString() would be nice, but the corresponding 1205 // constructor only works for valid versions and we might want to store 1206 // invalid versions as well. 1207 1208 // major 1209 size_t fieldLength = strlen(field); 1210 FieldName fieldName(field, ":major"); 1211 if (!fieldName.IsValid()) 1212 return B_BAD_VALUE; 1213 1214 status_t error = archive->AddString(fieldName, version.Major()); 1215 if (error != B_OK) 1216 return error; 1217 1218 // minor 1219 if (!fieldName.ReplaceSuffix(fieldLength, ":minor")) 1220 return B_BAD_VALUE; 1221 1222 error = archive->AddString(fieldName, version.Minor()); 1223 if (error != B_OK) 1224 return error; 1225 1226 // micro 1227 if (!fieldName.ReplaceSuffix(fieldLength, ":micro")) 1228 return B_BAD_VALUE; 1229 1230 error = archive->AddString(fieldName, version.Micro()); 1231 if (error != B_OK) 1232 return error; 1233 1234 // pre-release 1235 if (!fieldName.ReplaceSuffix(fieldLength, ":pre")) 1236 return B_BAD_VALUE; 1237 1238 error = archive->AddString(fieldName, version.PreRelease()); 1239 if (error != B_OK) 1240 return error; 1241 1242 // revision 1243 if (!fieldName.ReplaceSuffix(fieldLength, ":revision")) 1244 return B_BAD_VALUE; 1245 1246 return archive->AddUInt32(fieldName, version.Revision()); 1247 } 1248 1249 1250 /*static*/ status_t 1251 BPackageInfo::_AddResolvables(BMessage* archive, const char* field, 1252 const ResolvableList& resolvables) 1253 { 1254 // construct the field names we need 1255 FieldName nameField(field, ":name"); 1256 FieldName typeField(field, ":type"); 1257 FieldName versionField(field, ":version"); 1258 FieldName compatibleVersionField(field, ":compat"); 1259 1260 if (!nameField.IsValid() || !typeField.IsValid() || !versionField.IsValid() 1261 || !compatibleVersionField.IsValid()) { 1262 return B_BAD_VALUE; 1263 } 1264 1265 // add fields 1266 int32 count = resolvables.CountItems(); 1267 for (int32 i = 0; i < count; i++) { 1268 const BPackageResolvable* resolvable = resolvables.ItemAt(i); 1269 status_t error; 1270 if ((error = archive->AddString(nameField, resolvable->Name())) != B_OK 1271 || (error = _AddVersion(archive, versionField, 1272 resolvable->Version())) != B_OK 1273 || (error = _AddVersion(archive, compatibleVersionField, 1274 resolvable->CompatibleVersion())) != B_OK) { 1275 return error; 1276 } 1277 } 1278 1279 return B_OK; 1280 } 1281 1282 1283 /*static*/ status_t 1284 BPackageInfo::_AddResolvableExpressions(BMessage* archive, const char* field, 1285 const ResolvableExpressionList& expressions) 1286 { 1287 // construct the field names we need 1288 FieldName nameField(field, ":name"); 1289 FieldName operatorField(field, ":operator"); 1290 FieldName versionField(field, ":version"); 1291 1292 if (!nameField.IsValid() || !operatorField.IsValid() 1293 || !versionField.IsValid()) { 1294 return B_BAD_VALUE; 1295 } 1296 1297 // add fields 1298 int32 count = expressions.CountItems(); 1299 for (int32 i = 0; i < count; i++) { 1300 const BPackageResolvableExpression* expression = expressions.ItemAt(i); 1301 status_t error; 1302 if ((error = archive->AddString(nameField, expression->Name())) != B_OK 1303 || (error = archive->AddInt32(operatorField, 1304 expression->Operator())) != B_OK 1305 || (error = _AddVersion(archive, versionField, 1306 expression->Version())) != B_OK) { 1307 return error; 1308 } 1309 } 1310 1311 return B_OK; 1312 } 1313 1314 1315 /*static*/ status_t 1316 BPackageInfo::_AddGlobalWritableFileInfos(BMessage* archive, const char* field, 1317 const GlobalWritableFileInfoList& infos) 1318 { 1319 // construct the field names we need 1320 FieldName pathField(field, ":path"); 1321 FieldName updateTypeField(field, ":updateType"); 1322 FieldName isDirectoryField(field, ":isDirectory"); 1323 1324 if (!pathField.IsValid() || !updateTypeField.IsValid() 1325 || !isDirectoryField.IsValid()) { 1326 return B_BAD_VALUE; 1327 } 1328 1329 // add fields 1330 int32 count = infos.CountItems(); 1331 for (int32 i = 0; i < count; i++) { 1332 const BGlobalWritableFileInfo* info = infos.ItemAt(i); 1333 status_t error; 1334 if ((error = archive->AddString(pathField, info->Path())) != B_OK 1335 || (error = archive->AddInt32(updateTypeField, info->UpdateType())) 1336 != B_OK 1337 || (error = archive->AddBool(isDirectoryField, 1338 info->IsDirectory())) != B_OK) { 1339 return error; 1340 } 1341 } 1342 1343 return B_OK; 1344 } 1345 1346 1347 /*static*/ status_t 1348 BPackageInfo::_AddUserSettingsFileInfos(BMessage* archive, const char* field, 1349 const UserSettingsFileInfoList& infos) 1350 { 1351 // construct the field names we need 1352 FieldName pathField(field, ":path"); 1353 FieldName templatePathField(field, ":templatePath"); 1354 FieldName isDirectoryField(field, ":isDirectory"); 1355 1356 if (!pathField.IsValid() || !templatePathField.IsValid() 1357 || !isDirectoryField.IsValid()) { 1358 return B_BAD_VALUE; 1359 } 1360 1361 // add fields 1362 int32 count = infos.CountItems(); 1363 for (int32 i = 0; i < count; i++) { 1364 const BUserSettingsFileInfo* info = infos.ItemAt(i); 1365 status_t error; 1366 if ((error = archive->AddString(pathField, info->Path())) != B_OK 1367 || (error = archive->AddString(templatePathField, 1368 info->TemplatePath())) != B_OK 1369 || (error = archive->AddBool(isDirectoryField, 1370 info->IsDirectory())) != B_OK) { 1371 return error; 1372 } 1373 } 1374 1375 return B_OK; 1376 } 1377 1378 1379 /*static*/ status_t 1380 BPackageInfo::_AddUsers(BMessage* archive, const char* field, 1381 const UserList& users) 1382 { 1383 // construct the field names we need 1384 FieldName nameField(field, ":name"); 1385 FieldName realNameField(field, ":realName"); 1386 FieldName homeField(field, ":home"); 1387 FieldName shellField(field, ":shell"); 1388 FieldName groupsField(field, ":groups"); 1389 1390 if (!nameField.IsValid() || !realNameField.IsValid() || !homeField.IsValid() 1391 || !shellField.IsValid() || !groupsField.IsValid()) 1392 return B_BAD_VALUE; 1393 1394 // add fields 1395 int32 count = users.CountItems(); 1396 for (int32 i = 0; i < count; i++) { 1397 const BUser* user = users.ItemAt(i); 1398 BString groups = user->Groups().Join(" "); 1399 if (groups.IsEmpty() && !user->Groups().IsEmpty()) 1400 return B_NO_MEMORY; 1401 1402 status_t error; 1403 if ((error = archive->AddString(nameField, user->Name())) != B_OK 1404 || (error = archive->AddString(realNameField, user->RealName())) 1405 != B_OK 1406 || (error = archive->AddString(homeField, user->Home())) != B_OK 1407 || (error = archive->AddString(shellField, user->Shell())) != B_OK 1408 || (error = archive->AddString(groupsField, groups)) != B_OK) { 1409 return error; 1410 } 1411 } 1412 1413 return B_OK; 1414 } 1415 1416 1417 /*static*/ status_t 1418 BPackageInfo::_ExtractVersion(BMessage* archive, const char* field, int32 index, 1419 BPackageVersion& _version) 1420 { 1421 // major 1422 size_t fieldLength = strlen(field); 1423 FieldName fieldName(field, ":major"); 1424 if (!fieldName.IsValid()) 1425 return B_BAD_VALUE; 1426 1427 BString major; 1428 status_t error = archive->FindString(fieldName, index, &major); 1429 if (error != B_OK) 1430 return error; 1431 1432 // minor 1433 if (!fieldName.ReplaceSuffix(fieldLength, ":minor")) 1434 return B_BAD_VALUE; 1435 1436 BString minor; 1437 error = archive->FindString(fieldName, index, &minor); 1438 if (error != B_OK) 1439 return error; 1440 1441 // micro 1442 if (!fieldName.ReplaceSuffix(fieldLength, ":micro")) 1443 return B_BAD_VALUE; 1444 1445 BString micro; 1446 error = archive->FindString(fieldName, index, µ); 1447 if (error != B_OK) 1448 return error; 1449 1450 // pre-release 1451 if (!fieldName.ReplaceSuffix(fieldLength, ":pre")) 1452 return B_BAD_VALUE; 1453 1454 BString preRelease; 1455 error = archive->FindString(fieldName, index, &preRelease); 1456 if (error != B_OK) 1457 return error; 1458 1459 // revision 1460 if (!fieldName.ReplaceSuffix(fieldLength, ":revision")) 1461 return B_BAD_VALUE; 1462 1463 uint32 revision; 1464 error = archive->FindUInt32(fieldName, index, &revision); 1465 if (error != B_OK) 1466 return error; 1467 1468 _version.SetTo(major, minor, micro, preRelease, revision); 1469 return B_OK; 1470 } 1471 1472 1473 /*static*/ status_t 1474 BPackageInfo::_ExtractStringList(BMessage* archive, const char* field, 1475 BStringList& _list) 1476 { 1477 status_t error = archive->FindStrings(field, &_list); 1478 return error == B_NAME_NOT_FOUND ? B_OK : error; 1479 // If the field doesn't exist, that's OK. 1480 } 1481 1482 1483 /*static*/ status_t 1484 BPackageInfo::_ExtractResolvables(BMessage* archive, const char* field, 1485 ResolvableList& _resolvables) 1486 { 1487 // construct the field names we need 1488 FieldName nameField(field, ":name"); 1489 FieldName typeField(field, ":type"); 1490 FieldName versionField(field, ":version"); 1491 FieldName compatibleVersionField(field, ":compat"); 1492 1493 if (!nameField.IsValid() || !typeField.IsValid() || !versionField.IsValid() 1494 || !compatibleVersionField.IsValid()) { 1495 return B_BAD_VALUE; 1496 } 1497 1498 // get the number of items 1499 type_code type; 1500 int32 count; 1501 if (archive->GetInfo(nameField, &type, &count) != B_OK) { 1502 // the field is missing 1503 return B_OK; 1504 } 1505 1506 // extract fields 1507 for (int32 i = 0; i < count; i++) { 1508 BString name; 1509 status_t error = archive->FindString(nameField, i, &name); 1510 if (error != B_OK) 1511 return error; 1512 1513 BPackageVersion version; 1514 error = _ExtractVersion(archive, versionField, i, version); 1515 if (error != B_OK) 1516 return error; 1517 1518 BPackageVersion compatibleVersion; 1519 error = _ExtractVersion(archive, compatibleVersionField, i, 1520 compatibleVersion); 1521 if (error != B_OK) 1522 return error; 1523 1524 BPackageResolvable* resolvable = new(std::nothrow) BPackageResolvable( 1525 name, version, compatibleVersion); 1526 if (resolvable == NULL || !_resolvables.AddItem(resolvable)) { 1527 delete resolvable; 1528 return B_NO_MEMORY; 1529 } 1530 } 1531 1532 return B_OK; 1533 } 1534 1535 1536 /*static*/ status_t 1537 BPackageInfo::_ExtractResolvableExpressions(BMessage* archive, 1538 const char* field, ResolvableExpressionList& _expressions) 1539 { 1540 // construct the field names we need 1541 FieldName nameField(field, ":name"); 1542 FieldName operatorField(field, ":operator"); 1543 FieldName versionField(field, ":version"); 1544 1545 if (!nameField.IsValid() || !operatorField.IsValid() 1546 || !versionField.IsValid()) { 1547 return B_BAD_VALUE; 1548 } 1549 1550 // get the number of items 1551 type_code type; 1552 int32 count; 1553 if (archive->GetInfo(nameField, &type, &count) != B_OK) { 1554 // the field is missing 1555 return B_OK; 1556 } 1557 1558 // extract fields 1559 for (int32 i = 0; i < count; i++) { 1560 BString name; 1561 status_t error = archive->FindString(nameField, i, &name); 1562 if (error != B_OK) 1563 return error; 1564 1565 int32 operatorType; 1566 error = archive->FindInt32(operatorField, i, &operatorType); 1567 if (error != B_OK) 1568 return error; 1569 if (operatorType < 0 1570 || operatorType > B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { 1571 return B_BAD_DATA; 1572 } 1573 1574 BPackageVersion version; 1575 error = _ExtractVersion(archive, versionField, i, version); 1576 if (error != B_OK) 1577 return error; 1578 1579 BPackageResolvableExpression* expression 1580 = new(std::nothrow) BPackageResolvableExpression(name, 1581 (BPackageResolvableOperator)operatorType, version); 1582 if (expression == NULL || !_expressions.AddItem(expression)) { 1583 delete expression; 1584 return B_NO_MEMORY; 1585 } 1586 } 1587 1588 return B_OK; 1589 } 1590 1591 1592 /*static*/ status_t 1593 BPackageInfo::_ExtractGlobalWritableFileInfos(BMessage* archive, 1594 const char* field, GlobalWritableFileInfoList& _infos) 1595 { 1596 // construct the field names we need 1597 FieldName pathField(field, ":path"); 1598 FieldName updateTypeField(field, ":updateType"); 1599 FieldName isDirectoryField(field, ":isDirectory"); 1600 1601 if (!pathField.IsValid() || !updateTypeField.IsValid() 1602 || !isDirectoryField.IsValid()) { 1603 return B_BAD_VALUE; 1604 } 1605 1606 // get the number of items 1607 type_code type; 1608 int32 count; 1609 if (archive->GetInfo(pathField, &type, &count) != B_OK) { 1610 // the field is missing 1611 return B_OK; 1612 } 1613 1614 // extract fields 1615 for (int32 i = 0; i < count; i++) { 1616 BString path; 1617 status_t error = archive->FindString(pathField, i, &path); 1618 if (error != B_OK) 1619 return error; 1620 1621 int32 updateType; 1622 error = archive->FindInt32(updateTypeField, i, &updateType); 1623 if (error != B_OK) 1624 return error; 1625 if (updateType < 0 1626 || updateType > B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT) { 1627 return B_BAD_DATA; 1628 } 1629 1630 bool isDirectory; 1631 error = archive->FindBool(isDirectoryField, i, &isDirectory); 1632 if (error != B_OK) 1633 return error; 1634 1635 BGlobalWritableFileInfo* info 1636 = new(std::nothrow) BGlobalWritableFileInfo(path, 1637 (BWritableFileUpdateType)updateType, isDirectory); 1638 if (info == NULL || !_infos.AddItem(info)) { 1639 delete info; 1640 return B_NO_MEMORY; 1641 } 1642 } 1643 1644 return B_OK; 1645 } 1646 1647 1648 /*static*/ status_t 1649 BPackageInfo::_ExtractUserSettingsFileInfos(BMessage* archive, 1650 const char* field, UserSettingsFileInfoList& _infos) 1651 { 1652 // construct the field names we need 1653 FieldName pathField(field, ":path"); 1654 FieldName templatePathField(field, ":templatePath"); 1655 FieldName isDirectoryField(field, ":isDirectory"); 1656 1657 if (!pathField.IsValid() || !templatePathField.IsValid() 1658 || !isDirectoryField.IsValid()) { 1659 return B_BAD_VALUE; 1660 } 1661 1662 // get the number of items 1663 type_code type; 1664 int32 count; 1665 if (archive->GetInfo(pathField, &type, &count) != B_OK) { 1666 // the field is missing 1667 return B_OK; 1668 } 1669 1670 // extract fields 1671 for (int32 i = 0; i < count; i++) { 1672 BString path; 1673 status_t error = archive->FindString(pathField, i, &path); 1674 if (error != B_OK) 1675 return error; 1676 1677 BString templatePath; 1678 error = archive->FindString(templatePathField, i, &templatePath); 1679 if (error != B_OK) 1680 return error; 1681 1682 bool isDirectory; 1683 error = archive->FindBool(isDirectoryField, i, &isDirectory); 1684 if (error != B_OK) 1685 return error; 1686 1687 BUserSettingsFileInfo* info = isDirectory 1688 ? new(std::nothrow) BUserSettingsFileInfo(path, true) 1689 : new(std::nothrow) BUserSettingsFileInfo(path, templatePath); 1690 if (info == NULL || !_infos.AddItem(info)) { 1691 delete info; 1692 return B_NO_MEMORY; 1693 } 1694 } 1695 1696 return B_OK; 1697 } 1698 1699 1700 /*static*/ status_t 1701 BPackageInfo::_ExtractUsers(BMessage* archive, const char* field, 1702 UserList& _users) 1703 { 1704 // construct the field names we need 1705 FieldName nameField(field, ":name"); 1706 FieldName realNameField(field, ":realName"); 1707 FieldName homeField(field, ":home"); 1708 FieldName shellField(field, ":shell"); 1709 FieldName groupsField(field, ":groups"); 1710 1711 if (!nameField.IsValid() || !realNameField.IsValid() || !homeField.IsValid() 1712 || !shellField.IsValid() || !groupsField.IsValid()) 1713 return B_BAD_VALUE; 1714 1715 // get the number of items 1716 type_code type; 1717 int32 count; 1718 if (archive->GetInfo(nameField, &type, &count) != B_OK) { 1719 // the field is missing 1720 return B_OK; 1721 } 1722 1723 // extract fields 1724 for (int32 i = 0; i < count; i++) { 1725 BString name; 1726 status_t error = archive->FindString(nameField, i, &name); 1727 if (error != B_OK) 1728 return error; 1729 1730 BString realName; 1731 error = archive->FindString(realNameField, i, &realName); 1732 if (error != B_OK) 1733 return error; 1734 1735 BString home; 1736 error = archive->FindString(homeField, i, &home); 1737 if (error != B_OK) 1738 return error; 1739 1740 BString shell; 1741 error = archive->FindString(shellField, i, &shell); 1742 if (error != B_OK) 1743 return error; 1744 1745 BString groupsString; 1746 error = archive->FindString(groupsField, i, &groupsString); 1747 if (error != B_OK) 1748 return error; 1749 1750 BStringList groups; 1751 if (!groupsString.IsEmpty() && !groupsString.Split(" ", false, groups)) 1752 return B_NO_MEMORY; 1753 1754 BUser* user = new(std::nothrow) BUser(name, realName, home, shell, 1755 groups); 1756 if (user == NULL || !_users.AddItem(user)) { 1757 delete user; 1758 return B_NO_MEMORY; 1759 } 1760 } 1761 1762 return B_OK; 1763 } 1764 1765 1766 } // namespace BPackageKit 1767