1 /* 2 * Copyright 2013-2014, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold <ingo_weinhold@gmx.de> 7 */ 8 9 10 #include <package/CommitTransactionResult.h> 11 12 #include <Message.h> 13 14 //#include <package/DaemonDefs.h> 15 16 17 namespace BPackageKit { 18 19 20 // #pragma mark - BTransactionIssue 21 22 23 BTransactionIssue::BTransactionIssue() 24 : 25 fType(B_WRITABLE_FILE_TYPE_MISMATCH), 26 fPackageName(), 27 fPath1(), 28 fPath2(), 29 fSystemError(B_OK), 30 fExitCode(0) 31 { 32 } 33 34 35 BTransactionIssue::BTransactionIssue(BType type, const BString& packageName, 36 const BString& path1, const BString& path2, status_t systemError, 37 int exitCode) 38 : 39 fType(type), 40 fPackageName(packageName), 41 fPath1(path1), 42 fPath2(path2), 43 fSystemError(systemError), 44 fExitCode(exitCode) 45 { 46 } 47 48 49 BTransactionIssue::BTransactionIssue(const BTransactionIssue& other) 50 { 51 *this = other; 52 } 53 54 55 BTransactionIssue::~BTransactionIssue() 56 { 57 } 58 59 60 BTransactionIssue::BType 61 BTransactionIssue::Type() const 62 { 63 return fType; 64 } 65 66 67 const BString& 68 BTransactionIssue::PackageName() const 69 { 70 return fPackageName; 71 } 72 73 74 const BString& 75 BTransactionIssue::Path1() const 76 { 77 return fPath1; 78 } 79 80 81 const BString& 82 BTransactionIssue::Path2() const 83 { 84 return fPath2; 85 } 86 87 88 status_t 89 BTransactionIssue::SystemError() const 90 { 91 return fSystemError; 92 } 93 94 95 int 96 BTransactionIssue::ExitCode() const 97 { 98 return fExitCode; 99 } 100 101 102 BString 103 BTransactionIssue::ToString() const 104 { 105 const char* messageTemplate = ""; 106 switch (fType) { 107 case B_WRITABLE_FILE_TYPE_MISMATCH: 108 messageTemplate = "\"%path1%\" cannot be updated automatically," 109 " since its type doesn't match the type of \"%path2%\" which it" 110 " is supposed to be updated with." 111 " Please perform the update manually if needed."; 112 break; 113 case B_WRITABLE_FILE_NO_PACKAGE_ATTRIBUTE: 114 messageTemplate = "\"%path1%\" cannot be updated automatically," 115 " since it doesn't have a SYS:PACKAGE attribute." 116 " Please perform the update manually if needed."; 117 break; 118 case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_MISSING: 119 messageTemplate = "\"%path1%\" cannot be updated automatically," 120 " since \"%path2%\" which we need to compare it with is" 121 " missing." 122 " Please perform the update manually if needed."; 123 break; 124 case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_TYPE_MISMATCH: 125 messageTemplate = "\"%path1%\" cannot be updated automatically," 126 " since its type doesn't match the type of \"%path2%\" which we" 127 " need to compare it with." 128 " Please perform the update manually if needed."; 129 break; 130 case B_WRITABLE_FILE_COMPARISON_FAILED: 131 messageTemplate = "\"%path1%\" cannot be updated automatically," 132 " since the comparison with \"%path2%\" failed: %error%." 133 " Please perform the update manually if needed."; 134 break; 135 case B_WRITABLE_FILE_NOT_EQUAL: // !keep old 136 messageTemplate = "\"%path1%\" cannot be updated automatically," 137 " since it was changed manually from previous version" 138 " \"%path2%\"." 139 " Please perform the update manually if needed."; 140 break; 141 case B_WRITABLE_SYMLINK_COMPARISON_FAILED: // !keep old 142 messageTemplate = "Symbolic link \"%path1%\" cannot be updated" 143 " automatically, since the comparison with \"%path2%\" failed:" 144 " %error%." 145 " Please perform the update manually if needed."; 146 break; 147 case B_WRITABLE_SYMLINK_NOT_EQUAL: // !keep old 148 messageTemplate = "Symbolic link \"%path1%\" cannot be updated" 149 " automatically, since it was changed manually from previous" 150 " version \"%path2%\"." 151 " Please perform the update manually if needed."; 152 break; 153 case B_POST_INSTALL_SCRIPT_NOT_FOUND: 154 messageTemplate = "Failed to find post-installation script " 155 " \"%path1%\": %error%."; 156 break; 157 case B_STARTING_POST_INSTALL_SCRIPT_FAILED: 158 messageTemplate = "Failed to run post-installation script " 159 " \"%path1%\": %error%."; 160 break; 161 case B_POST_INSTALL_SCRIPT_FAILED: 162 messageTemplate = "The post-installation script " 163 " \"%path1%\" failed with exit code %exitCode%."; 164 break; 165 case B_PRE_UNINSTALL_SCRIPT_NOT_FOUND: 166 messageTemplate = "Failed to find pre-uninstall script " 167 " \"%path1%\": %error%."; 168 break; 169 case B_STARTING_PRE_UNINSTALL_SCRIPT_FAILED: 170 messageTemplate = "Failed to run pre-uninstall script " 171 " \"%path1%\": %error%."; 172 break; 173 case B_PRE_UNINSTALL_SCRIPT_FAILED: 174 messageTemplate = "The pre-uninstall script " 175 " \"%path1%\" failed with exit code %exitCode%."; 176 break; 177 } 178 179 BString message(messageTemplate); 180 message.ReplaceAll("%path1%", fPath1) 181 .ReplaceAll("%path2%", fPath2) 182 .ReplaceAll("%error%", strerror(fSystemError)) 183 .ReplaceAll("%exitCode%", BString() << fExitCode); 184 return message; 185 } 186 187 188 status_t 189 BTransactionIssue::AddToMessage(BMessage& message) const 190 { 191 status_t error; 192 if ((error = message.AddInt32("type", (int32)fType)) != B_OK 193 || (error = message.AddString("package", fPackageName)) != B_OK 194 || (error = message.AddString("path1", fPath1)) != B_OK 195 || (error = message.AddString("path2", fPath2)) != B_OK 196 || (error = message.AddInt32("system error", (int32)fSystemError)) 197 != B_OK 198 || (error = message.AddInt32("exit code", (int32)fExitCode)) != B_OK) { 199 return error; 200 } 201 202 return B_OK; 203 } 204 205 206 status_t 207 BTransactionIssue::ExtractFromMessage(const BMessage& message) 208 { 209 status_t error; 210 int32 type; 211 int32 systemError; 212 int32 exitCode; 213 if ((error = message.FindInt32("type", &type)) != B_OK 214 || (error = message.FindString("package", &fPackageName)) != B_OK 215 || (error = message.FindString("path1", &fPath1)) != B_OK 216 || (error = message.FindString("path2", &fPath2)) != B_OK 217 || (error = message.FindInt32("system error", &systemError)) != B_OK 218 || (error = message.FindInt32("exit code", &exitCode)) != B_OK) { 219 return error; 220 } 221 222 fType = (BType)type; 223 fSystemError = (status_t)systemError; 224 fExitCode = (int)exitCode; 225 226 return B_OK; 227 } 228 229 230 BTransactionIssue& 231 BTransactionIssue::operator=(const BTransactionIssue& other) 232 { 233 fType = other.fType; 234 fPackageName = other.fPackageName; 235 fPath1 = other.fPath1; 236 fPath2 = other.fPath2; 237 fSystemError = other.fSystemError; 238 fExitCode = other.fExitCode; 239 240 return *this; 241 } 242 243 244 // #pragma mark - BCommitTransactionResult 245 246 247 BCommitTransactionResult::BCommitTransactionResult() 248 : 249 fError(B_TRANSACTION_INTERNAL_ERROR), 250 fSystemError(B_ERROR), 251 fErrorPackage(), 252 fPath1(), 253 fPath2(), 254 fString1(), 255 fString2(), 256 fOldStateDirectory(), 257 fIssues(10, true) 258 { 259 } 260 261 262 BCommitTransactionResult::BCommitTransactionResult(BTransactionError error) 263 : 264 fError(error), 265 fSystemError(B_ERROR), 266 fErrorPackage(), 267 fPath1(), 268 fPath2(), 269 fString1(), 270 fString2(), 271 fOldStateDirectory(), 272 fIssues(10, true) 273 { 274 } 275 276 277 BCommitTransactionResult::BCommitTransactionResult( 278 const BCommitTransactionResult& other) 279 : 280 fError(B_TRANSACTION_INTERNAL_ERROR), 281 fSystemError(B_ERROR), 282 fErrorPackage(), 283 fPath1(), 284 fPath2(), 285 fString1(), 286 fString2(), 287 fOldStateDirectory(), 288 fIssues(10, true) 289 { 290 *this = other; 291 } 292 293 294 BCommitTransactionResult::~BCommitTransactionResult() 295 { 296 } 297 298 299 void 300 BCommitTransactionResult::Unset() 301 { 302 fError = B_TRANSACTION_INTERNAL_ERROR; 303 fSystemError = B_ERROR; 304 fErrorPackage.Truncate(0); 305 fPath1.Truncate(0); 306 fPath2.Truncate(0); 307 fString1.Truncate(0); 308 fString2.Truncate(0); 309 fOldStateDirectory.Truncate(0); 310 fIssues.MakeEmpty(); 311 } 312 313 314 int32 315 BCommitTransactionResult::CountIssues() const 316 { 317 return fIssues.CountItems(); 318 } 319 320 321 const BTransactionIssue* 322 BCommitTransactionResult::IssueAt(int32 index) const 323 { 324 if (index < 0 || index >= CountIssues()) 325 return NULL; 326 return fIssues.ItemAt(index); 327 } 328 329 330 bool 331 BCommitTransactionResult::AddIssue(const BTransactionIssue& issue) 332 { 333 BTransactionIssue* newIssue = new(std::nothrow) BTransactionIssue(issue); 334 if (newIssue == NULL || !fIssues.AddItem(newIssue)) { 335 delete newIssue; 336 return false; 337 } 338 return true; 339 } 340 341 342 BTransactionError 343 BCommitTransactionResult::Error() const 344 { 345 return fError > 0 ? (BTransactionError)fError : B_TRANSACTION_OK; 346 } 347 348 349 void 350 BCommitTransactionResult::SetError(BTransactionError error) 351 { 352 fError = error; 353 } 354 355 356 status_t 357 BCommitTransactionResult::SystemError() const 358 { 359 return fSystemError; 360 } 361 362 363 void 364 BCommitTransactionResult::SetSystemError(status_t error) 365 { 366 fSystemError = error; 367 } 368 369 370 const BString& 371 BCommitTransactionResult::ErrorPackage() const 372 { 373 return fErrorPackage; 374 } 375 376 377 void 378 BCommitTransactionResult::SetErrorPackage(const BString& packageName) 379 { 380 fErrorPackage = packageName; 381 } 382 383 384 BString 385 BCommitTransactionResult::FullErrorMessage() const 386 { 387 if (fError == 0) 388 return "no error"; 389 390 const char* messageTemplate = ""; 391 switch ((BTransactionError)fError) { 392 case B_TRANSACTION_OK: 393 messageTemplate = "Everything went fine."; 394 break; 395 case B_TRANSACTION_NO_MEMORY: 396 messageTemplate = "Out of memory."; 397 break; 398 case B_TRANSACTION_INTERNAL_ERROR: 399 messageTemplate = "An internal error occurred. Specifics can be" 400 " found in the syslog."; 401 break; 402 case B_TRANSACTION_INSTALLATION_LOCATION_BUSY: 403 messageTemplate = "Another package operation is already in" 404 " progress."; 405 break; 406 case B_TRANSACTION_CHANGE_COUNT_MISMATCH: 407 messageTemplate = "The transaction is out of date."; 408 break; 409 case B_TRANSACTION_BAD_REQUEST: 410 messageTemplate = "The requested transaction is invalid."; 411 break; 412 case B_TRANSACTION_NO_SUCH_PACKAGE: 413 messageTemplate = "No such package \"%package%\"."; 414 break; 415 case B_TRANSACTION_PACKAGE_ALREADY_EXISTS: 416 messageTemplate = "The to be activated package \"%package%\" does" 417 " already exist."; 418 break; 419 case B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH: 420 if (fPath1.IsEmpty()) { 421 if (fErrorPackage.IsEmpty()) { 422 messageTemplate = "A file path could not be determined:" 423 "%error%"; 424 } else { 425 messageTemplate = "While processing package \"%package%\"" 426 " a file path could not be determined: %error%"; 427 } 428 } else { 429 if (fErrorPackage.IsEmpty()) { 430 messageTemplate = "The file path for \"%path1%\" could not" 431 " be determined: %error%"; 432 } else { 433 messageTemplate = "While processing package \"%package%\"" 434 " the file path for \"%path1%\" could not be" 435 " determined: %error%"; 436 } 437 } 438 break; 439 case B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY: 440 messageTemplate = "Failed to open directory \"%path1%\": %error%"; 441 break; 442 case B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY: 443 messageTemplate = "Failed to create directory \"%path1%\": %error%"; 444 break; 445 case B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY: 446 messageTemplate = "Failed to remove directory \"%path1%\": %error%"; 447 break; 448 case B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY: 449 messageTemplate = "Failed to move directory \"%path1%\" to" 450 " \"%path2%\": %error%"; 451 break; 452 case B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE: 453 messageTemplate = "Failed to write new package activation file" 454 " \"%path1%\": %error%"; 455 break; 456 case B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE: 457 messageTemplate = "Failed to read package file \"%path1%\":" 458 " %error%"; 459 break; 460 case B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE: 461 messageTemplate = "Failed to extract \"%path1%\" from package" 462 " \"%package%\": %error%"; 463 break; 464 case B_TRANSACTION_FAILED_TO_OPEN_FILE: 465 messageTemplate = "Failed to open file \"%path1%\": %error%"; 466 break; 467 case B_TRANSACTION_FAILED_TO_MOVE_FILE: 468 messageTemplate = "Failed to move file \"%path1%\" to \"%path2%\":" 469 " %error%"; 470 break; 471 case B_TRANSACTION_FAILED_TO_COPY_FILE: 472 messageTemplate = "Failed to copy file \"%path1%\" to \"%path2%\":" 473 " %error%"; 474 break; 475 case B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE: 476 messageTemplate = "Failed to write attribute \"%string1%\" of file" 477 " \"%path1%\": %error%"; 478 break; 479 case B_TRANSACTION_FAILED_TO_ACCESS_ENTRY: 480 messageTemplate = "Failed to access entry \"%path1%\": %error%"; 481 break; 482 case B_TRANSACTION_FAILED_TO_ADD_GROUP: 483 messageTemplate = "Failed to add user group \"%string1%\" required" 484 " by package \"%package%\"."; 485 break; 486 case B_TRANSACTION_FAILED_TO_ADD_USER: 487 messageTemplate = "Failed to add user \"%string1%\" required" 488 " by package \"%package%\"."; 489 break; 490 case B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP: 491 messageTemplate = "Failed to add user \"%string1%\" to group" 492 " \"%string2%\" as required by package \"%package%\"."; 493 break; 494 case B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION: 495 messageTemplate = "Failed to change the package activation in" 496 " packagefs: %error%"; 497 break; 498 } 499 500 BString message(messageTemplate); 501 message.ReplaceAll("%package%", fErrorPackage) 502 .ReplaceAll("%path1%", fPath1) 503 .ReplaceAll("%path2%", fPath2) 504 .ReplaceAll("%string1%", fString1) 505 .ReplaceAll("%string2%", fString2) 506 .ReplaceAll("%error%", strerror(fSystemError)); 507 return message; 508 } 509 510 511 const BString& 512 BCommitTransactionResult::Path1() const 513 { 514 return fPath1; 515 } 516 517 518 void 519 BCommitTransactionResult::SetPath1(const BString& path) 520 { 521 fPath1 = path; 522 } 523 524 525 const BString& 526 BCommitTransactionResult::Path2() const 527 { 528 return fPath2; 529 } 530 531 532 void 533 BCommitTransactionResult::SetPath2(const BString& path) 534 { 535 fPath2 = path; 536 } 537 538 539 const BString& 540 BCommitTransactionResult::String1() const 541 { 542 return fString1; 543 } 544 545 546 void 547 BCommitTransactionResult::SetString1(const BString& string) 548 { 549 fString1 = string; 550 } 551 552 553 const BString& 554 BCommitTransactionResult::String2() const 555 { 556 return fString2; 557 } 558 559 560 void 561 BCommitTransactionResult::SetString2(const BString& string) 562 { 563 fString2 = string; 564 } 565 566 567 const BString& 568 BCommitTransactionResult::OldStateDirectory() const 569 { 570 return fOldStateDirectory; 571 } 572 573 574 void 575 BCommitTransactionResult::SetOldStateDirectory(const BString& directory) 576 { 577 fOldStateDirectory = directory; 578 } 579 580 581 status_t 582 BCommitTransactionResult::AddToMessage(BMessage& message) const 583 { 584 status_t error; 585 if ((error = message.AddInt32("error", (int32)fError)) != B_OK 586 || (error = message.AddInt32("system error", (int32)fSystemError)) 587 != B_OK 588 || (error = message.AddString("error package", fErrorPackage)) != B_OK 589 || (error = message.AddString("path1", fPath1)) != B_OK 590 || (error = message.AddString("path2", fPath2)) != B_OK 591 || (error = message.AddString("string1", fString1)) != B_OK 592 || (error = message.AddString("string2", fString2)) != B_OK 593 || (error = message.AddString("old state", fOldStateDirectory)) 594 != B_OK) { 595 return error; 596 } 597 598 int32 count = fIssues.CountItems(); 599 for (int32 i = 0; i < count; i++) { 600 const BTransactionIssue* issue = fIssues.ItemAt(i); 601 BMessage issueMessage; 602 if ((error = issue->AddToMessage(issueMessage)) != B_OK 603 || (error = message.AddMessage("issues", &issueMessage)) != B_OK) { 604 return error; 605 } 606 } 607 608 return B_OK; 609 } 610 611 612 status_t 613 BCommitTransactionResult::ExtractFromMessage(const BMessage& message) 614 { 615 Unset(); 616 617 int32 resultError; 618 int32 systemError; 619 status_t error; 620 if ((error = message.FindInt32("error", &resultError)) != B_OK 621 || (error = message.FindInt32("system error", &systemError)) != B_OK 622 || (error = message.FindString("error package", &fErrorPackage)) != B_OK 623 || (error = message.FindString("path1", &fPath1)) != B_OK 624 || (error = message.FindString("path2", &fPath2)) != B_OK 625 || (error = message.FindString("string1", &fString1)) != B_OK 626 || (error = message.FindString("string2", &fString2)) != B_OK 627 || (error = message.FindString("old state", &fOldStateDirectory)) 628 != B_OK) { 629 return error; 630 } 631 632 fError = (BTransactionError)resultError; 633 fSystemError = (status_t)systemError; 634 635 BMessage issueMessage; 636 for (int32 i = 0; message.FindMessage("issues", i, &issueMessage) == B_OK; 637 i++) { 638 BTransactionIssue issue; 639 error = issue.ExtractFromMessage(issueMessage); 640 if (error != B_OK) 641 return error; 642 643 if (!AddIssue(issue)) 644 return B_NO_MEMORY; 645 } 646 647 return B_OK; 648 } 649 650 651 BCommitTransactionResult& 652 BCommitTransactionResult::operator=(const BCommitTransactionResult& other) 653 { 654 Unset(); 655 656 fError = other.fError; 657 fSystemError = other.fSystemError; 658 fErrorPackage = other.fErrorPackage; 659 fPath1 = other.fPath1; 660 fPath2 = other.fPath2; 661 fString1 = other.fString1; 662 fString2 = other.fString2; 663 fOldStateDirectory = other.fOldStateDirectory; 664 665 for (int32 i = 0; const BTransactionIssue* issue = other.fIssues.ItemAt(i); 666 i++) { 667 AddIssue(*issue); 668 } 669 670 return *this; 671 } 672 673 674 } // namespace BPackageKit 675