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