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