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 } 166 167 BString message(messageTemplate); 168 message.ReplaceAll("%path1%", fPath1) 169 .ReplaceAll("%path2%", fPath2) 170 .ReplaceAll("%error%", strerror(fSystemError)) 171 .ReplaceAll("%exitCode%", BString() << fExitCode); 172 return message; 173 } 174 175 176 status_t 177 BTransactionIssue::AddToMessage(BMessage& message) const 178 { 179 status_t error; 180 if ((error = message.AddInt32("type", (int32)fType)) != B_OK 181 || (error = message.AddString("package", fPackageName)) != B_OK 182 || (error = message.AddString("path1", fPath1)) != B_OK 183 || (error = message.AddString("path2", fPath2)) != B_OK 184 || (error = message.AddInt32("system error", (int32)fSystemError)) 185 != B_OK 186 || (error = message.AddInt32("exit code", (int32)fExitCode)) != B_OK) { 187 return error; 188 } 189 190 return B_OK; 191 } 192 193 194 status_t 195 BTransactionIssue::ExtractFromMessage(const BMessage& message) 196 { 197 status_t error; 198 int32 type; 199 int32 systemError; 200 int32 exitCode; 201 if ((error = message.FindInt32("type", &type)) != B_OK 202 || (error = message.FindString("package", &fPackageName)) != B_OK 203 || (error = message.FindString("path1", &fPath1)) != B_OK 204 || (error = message.FindString("path2", &fPath2)) != B_OK 205 || (error = message.FindInt32("system error", &systemError)) != B_OK 206 || (error = message.FindInt32("exit code", &exitCode)) != B_OK) { 207 return error; 208 } 209 210 fType = (BType)type; 211 fSystemError = (status_t)systemError; 212 fExitCode = (int)exitCode; 213 214 return B_OK; 215 } 216 217 218 BTransactionIssue& 219 BTransactionIssue::operator=(const BTransactionIssue& other) 220 { 221 fType = other.fType; 222 fPackageName = other.fPackageName; 223 fPath1 = other.fPath1; 224 fPath2 = other.fPath2; 225 fSystemError = other.fSystemError; 226 fExitCode = other.fExitCode; 227 228 return *this; 229 } 230 231 232 // #pragma mark - BCommitTransactionResult 233 234 235 BCommitTransactionResult::BCommitTransactionResult() 236 : 237 fError(B_TRANSACTION_INTERNAL_ERROR), 238 fSystemError(B_ERROR), 239 fErrorPackage(), 240 fPath1(), 241 fPath2(), 242 fString1(), 243 fString2(), 244 fOldStateDirectory(), 245 fIssues(10, true) 246 { 247 } 248 249 250 BCommitTransactionResult::BCommitTransactionResult(BTransactionError error) 251 : 252 fError(error), 253 fSystemError(B_ERROR), 254 fErrorPackage(), 255 fPath1(), 256 fPath2(), 257 fString1(), 258 fString2(), 259 fOldStateDirectory(), 260 fIssues(10, true) 261 { 262 } 263 264 265 BCommitTransactionResult::BCommitTransactionResult( 266 const BCommitTransactionResult& other) 267 : 268 fError(B_TRANSACTION_INTERNAL_ERROR), 269 fSystemError(B_ERROR), 270 fErrorPackage(), 271 fPath1(), 272 fPath2(), 273 fString1(), 274 fString2(), 275 fOldStateDirectory(), 276 fIssues(10, true) 277 { 278 *this = other; 279 } 280 281 282 BCommitTransactionResult::~BCommitTransactionResult() 283 { 284 } 285 286 287 void 288 BCommitTransactionResult::Unset() 289 { 290 fError = B_TRANSACTION_INTERNAL_ERROR; 291 fSystemError = B_ERROR; 292 fErrorPackage.Truncate(0); 293 fPath1.Truncate(0); 294 fPath2.Truncate(0); 295 fString1.Truncate(0); 296 fString2.Truncate(0); 297 fOldStateDirectory.Truncate(0); 298 fIssues.MakeEmpty(); 299 } 300 301 302 int32 303 BCommitTransactionResult::CountIssues() const 304 { 305 return fIssues.CountItems(); 306 } 307 308 309 const BTransactionIssue* 310 BCommitTransactionResult::IssueAt(int32 index) const 311 { 312 if (index < 0 || index >= CountIssues()) 313 return NULL; 314 return fIssues.ItemAt(index); 315 } 316 317 318 bool 319 BCommitTransactionResult::AddIssue(const BTransactionIssue& issue) 320 { 321 BTransactionIssue* newIssue = new(std::nothrow) BTransactionIssue(issue); 322 if (newIssue == NULL || !fIssues.AddItem(newIssue)) { 323 delete newIssue; 324 return false; 325 } 326 return true; 327 } 328 329 330 BTransactionError 331 BCommitTransactionResult::Error() const 332 { 333 return fError > 0 ? (BTransactionError)fError : B_TRANSACTION_OK; 334 } 335 336 337 void 338 BCommitTransactionResult::SetError(BTransactionError error) 339 { 340 fError = error; 341 } 342 343 344 status_t 345 BCommitTransactionResult::SystemError() const 346 { 347 return fSystemError; 348 } 349 350 351 void 352 BCommitTransactionResult::SetSystemError(status_t error) 353 { 354 fSystemError = error; 355 } 356 357 358 const BString& 359 BCommitTransactionResult::ErrorPackage() const 360 { 361 return fErrorPackage; 362 } 363 364 365 void 366 BCommitTransactionResult::SetErrorPackage(const BString& packageName) 367 { 368 fErrorPackage = packageName; 369 } 370 371 372 BString 373 BCommitTransactionResult::FullErrorMessage() const 374 { 375 if (fError == 0) 376 return "no error"; 377 378 const char* messageTemplate = ""; 379 switch ((BTransactionError)fError) { 380 case B_TRANSACTION_OK: 381 messageTemplate = "Everything went fine."; 382 break; 383 case B_TRANSACTION_NO_MEMORY: 384 messageTemplate = "Out of memory."; 385 break; 386 case B_TRANSACTION_INTERNAL_ERROR: 387 messageTemplate = "An internal error occurred. Specifics can be" 388 " found in the syslog."; 389 break; 390 case B_TRANSACTION_INSTALLATION_LOCATION_BUSY: 391 messageTemplate = "Another package operation is already in" 392 " progress."; 393 break; 394 case B_TRANSACTION_CHANGE_COUNT_MISMATCH: 395 messageTemplate = "The transaction is out of date."; 396 break; 397 case B_TRANSACTION_BAD_REQUEST: 398 messageTemplate = "The requested transaction is invalid."; 399 break; 400 case B_TRANSACTION_NO_SUCH_PACKAGE: 401 messageTemplate = "No such package \"%package%\"."; 402 break; 403 case B_TRANSACTION_PACKAGE_ALREADY_EXISTS: 404 messageTemplate = "The to be activated package \"%package%\" does" 405 " already exist."; 406 break; 407 case B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH: 408 if (fPath1.IsEmpty()) { 409 if (fErrorPackage.IsEmpty()) { 410 messageTemplate = "A file path could not be determined:" 411 "%error%"; 412 } else { 413 messageTemplate = "While processing package \"%package%\"" 414 " a file path could not be determined: %error%"; 415 } 416 } else { 417 if (fErrorPackage.IsEmpty()) { 418 messageTemplate = "The file path for \"%path1%\" could not" 419 " be determined: %error%"; 420 } else { 421 messageTemplate = "While processing package \"%package%\"" 422 " the file path for \"%path1%\" could not be" 423 " determined: %error%"; 424 } 425 } 426 break; 427 case B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY: 428 messageTemplate = "Failed to open directory \"%path1%\": %error%"; 429 break; 430 case B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY: 431 messageTemplate = "Failed to create directory \"%path1%\": %error%"; 432 break; 433 case B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY: 434 messageTemplate = "Failed to remove directory \"%path1%\": %error%"; 435 break; 436 case B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY: 437 messageTemplate = "Failed to move directory \"%path1%\" to" 438 " \"%path2%\": %error%"; 439 break; 440 case B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE: 441 messageTemplate = "Failed to write new package activation file" 442 " \"%path1%\": %error%"; 443 break; 444 case B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE: 445 messageTemplate = "Failed to read package file \"%path1%\":" 446 " %error%"; 447 break; 448 case B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE: 449 messageTemplate = "Failed to extract \"%path1%\" from package" 450 " \"%package%\": %error%"; 451 break; 452 case B_TRANSACTION_FAILED_TO_OPEN_FILE: 453 messageTemplate = "Failed to open file \"%path1%\": %error%"; 454 break; 455 case B_TRANSACTION_FAILED_TO_MOVE_FILE: 456 messageTemplate = "Failed to move file \"%path1%\" to \"%path2%\":" 457 " %error%"; 458 break; 459 case B_TRANSACTION_FAILED_TO_COPY_FILE: 460 messageTemplate = "Failed to copy file \"%path1%\" to \"%path2%\":" 461 " %error%"; 462 break; 463 case B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE: 464 messageTemplate = "Failed to write attribute \"%string1%\" of file" 465 " \"%path1%\": %error%"; 466 break; 467 case B_TRANSACTION_FAILED_TO_ACCESS_ENTRY: 468 messageTemplate = "Failed to access entry \"%path1%\": %error%"; 469 break; 470 case B_TRANSACTION_FAILED_TO_ADD_GROUP: 471 messageTemplate = "Failed to add user group \"%string1%\" required" 472 " by package \"%package%\"."; 473 break; 474 case B_TRANSACTION_FAILED_TO_ADD_USER: 475 messageTemplate = "Failed to add user \"%string1%\" required" 476 " by package \"%package%\"."; 477 break; 478 case B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP: 479 messageTemplate = "Failed to add user \"%string1%\" to group" 480 " \"%string2%\" as required by package \"%package%\"."; 481 break; 482 case B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION: 483 messageTemplate = "Failed to change the package activation in" 484 " packagefs: %error%"; 485 break; 486 } 487 488 BString message(messageTemplate); 489 message.ReplaceAll("%package%", fErrorPackage) 490 .ReplaceAll("%path1%", fPath1) 491 .ReplaceAll("%path2%", fPath2) 492 .ReplaceAll("%string1%", fString1) 493 .ReplaceAll("%string2%", fString2) 494 .ReplaceAll("%error%", strerror(fSystemError)); 495 return message; 496 } 497 498 499 const BString& 500 BCommitTransactionResult::Path1() const 501 { 502 return fPath1; 503 } 504 505 506 void 507 BCommitTransactionResult::SetPath1(const BString& path) 508 { 509 fPath1 = path; 510 } 511 512 513 const BString& 514 BCommitTransactionResult::Path2() const 515 { 516 return fPath2; 517 } 518 519 520 void 521 BCommitTransactionResult::SetPath2(const BString& path) 522 { 523 fPath2 = path; 524 } 525 526 527 const BString& 528 BCommitTransactionResult::String1() const 529 { 530 return fString1; 531 } 532 533 534 void 535 BCommitTransactionResult::SetString1(const BString& string) 536 { 537 fString1 = string; 538 } 539 540 541 const BString& 542 BCommitTransactionResult::String2() const 543 { 544 return fString2; 545 } 546 547 548 void 549 BCommitTransactionResult::SetString2(const BString& string) 550 { 551 fString2 = string; 552 } 553 554 555 const BString& 556 BCommitTransactionResult::OldStateDirectory() const 557 { 558 return fOldStateDirectory; 559 } 560 561 562 void 563 BCommitTransactionResult::SetOldStateDirectory(const BString& directory) 564 { 565 fOldStateDirectory = directory; 566 } 567 568 569 status_t 570 BCommitTransactionResult::AddToMessage(BMessage& message) const 571 { 572 status_t error; 573 if ((error = message.AddInt32("error", (int32)fError)) != B_OK 574 || (error = message.AddInt32("system error", (int32)fSystemError)) 575 != B_OK 576 || (error = message.AddString("error package", fErrorPackage)) != B_OK 577 || (error = message.AddString("path1", fPath1)) != B_OK 578 || (error = message.AddString("path2", fPath2)) != B_OK 579 || (error = message.AddString("string1", fString1)) != B_OK 580 || (error = message.AddString("string2", fString2)) != B_OK 581 || (error = message.AddString("old state", fOldStateDirectory)) 582 != B_OK) { 583 return error; 584 } 585 586 int32 count = fIssues.CountItems(); 587 for (int32 i = 0; i < count; i++) { 588 const BTransactionIssue* issue = fIssues.ItemAt(i); 589 BMessage issueMessage; 590 if ((error = issue->AddToMessage(issueMessage)) != B_OK 591 || (error = message.AddMessage("issues", &issueMessage)) != B_OK) { 592 return error; 593 } 594 } 595 596 return B_OK; 597 } 598 599 600 status_t 601 BCommitTransactionResult::ExtractFromMessage(const BMessage& message) 602 { 603 Unset(); 604 605 int32 resultError; 606 int32 systemError; 607 status_t error; 608 if ((error = message.FindInt32("error", &resultError)) != B_OK 609 || (error = message.FindInt32("system error", &systemError)) != B_OK 610 || (error = message.FindString("error package", &fErrorPackage)) != B_OK 611 || (error = message.FindString("path1", &fPath1)) != B_OK 612 || (error = message.FindString("path2", &fPath2)) != B_OK 613 || (error = message.FindString("string1", &fString1)) != B_OK 614 || (error = message.FindString("string2", &fString2)) != B_OK 615 || (error = message.FindString("old state", &fOldStateDirectory)) 616 != B_OK) { 617 return error; 618 } 619 620 fError = (BTransactionError)resultError; 621 fSystemError = (status_t)systemError; 622 623 BMessage issueMessage; 624 for (int32 i = 0; message.FindMessage("issues", i, &issueMessage) == B_OK; 625 i++) { 626 BTransactionIssue issue; 627 error = issue.ExtractFromMessage(issueMessage); 628 if (error != B_OK) 629 return error; 630 631 if (!AddIssue(issue)) 632 return B_NO_MEMORY; 633 } 634 635 return B_OK; 636 } 637 638 639 BCommitTransactionResult& 640 BCommitTransactionResult::operator=(const BCommitTransactionResult& other) 641 { 642 Unset(); 643 644 fError = other.fError; 645 fSystemError = other.fSystemError; 646 fErrorPackage = other.fErrorPackage; 647 fPath1 = other.fPath1; 648 fPath2 = other.fPath2; 649 fString1 = other.fString1; 650 fString2 = other.fString2; 651 fOldStateDirectory = other.fOldStateDirectory; 652 653 for (int32 i = 0; const BTransactionIssue* issue = other.fIssues.ItemAt(i); 654 i++) { 655 AddIssue(*issue); 656 } 657 658 return *this; 659 } 660 661 662 } // namespace BPackageKit 663