Ticket #3762: fixed_script.patch
File fixed_script.patch, 36.4 KB (added by , 14 years ago) |
---|
-
src/apps/packageinstaller/PackageStatus.cpp
92 92 93 93 94 94 PackageStatus::PackageStatus(const char *title, const char *label, 95 const char *trailing )95 const char *trailing, BHandler *parent) 96 96 : BWindow(BRect(200, 200, 550, 255), title, B_TITLED_WINDOW, 97 97 B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE, 0), 98 fIsStopped(false) 98 fIsStopped(false), 99 fParent(parent) 99 100 { 100 101 SetLayout(new BGroupLayout(B_VERTICAL)); 101 102 … … 129 130 switch (msg->what) { 130 131 case P_MSG_STOP: 131 132 fIsStopped = true; 133 if (fParent != NULL) { 134 // If we have a parent defined, forward this message 135 BLooper *loop = fParent->Looper(); 136 if (loop != NULL) { 137 loop->PostMessage(msg, fParent); 138 } 139 } 132 140 break; 133 141 default: 134 142 BWindow::MessageReceived(msg); -
src/apps/packageinstaller/PackageStatus.h
31 31 class PackageStatus : public BWindow { 32 32 public: 33 33 PackageStatus(const char *title, const char *label = NULL, 34 const char *trailing = NULL );34 const char *trailing = NULL, BHandler *parent = NULL); 35 35 ~PackageStatus(); 36 36 37 37 void MessageReceived(BMessage *msg); … … 46 46 BStatusBar *fStatus; 47 47 StopButton *fButton; 48 48 bool fIsStopped; 49 BHandler *fParent; 49 50 }; 50 51 51 52 -
src/apps/packageinstaller/PackageInfo.cpp
39 39 P_NONE = 0, 40 40 P_FILE, 41 41 P_DIRECTORY, 42 P_LINK 42 P_LINK, 43 P_SCRIPT 43 44 }; 44 45 45 46 … … 86 87 delete file; 87 88 } 88 89 90 while (true) { 91 file = static_cast<PackageScript *>(fScripts.RemoveItem((long int)0)); 92 if (file == NULL) 93 break; 94 95 delete file; 96 } 97 89 98 delete fPackageFile; 90 99 } 91 100 … … 624 633 RETURN_AND_SET_STATUS(B_ERROR); 625 634 } 626 635 627 // TODO: Here's the deal... there seems to be a strange ScrI tag that 628 // seems to mean script files (check this). It seems exaclty the same 629 // as a normal file (just as script files are normal files) so for 630 // now I'm treating those as files. Check if it's correct! 631 // No, it isn't and I will fix this soon. 632 if (!memcmp(buffer, "FilI", 5) || !memcmp(buffer, "ScrI", 5)) { 633 parser_debug("FilI\n"); 634 element = P_FILE; 636 #define INIT_VARS(tag, type) \ 637 parser_debug(tag "\n"); \ 638 element = type; \ 639 mimeString = ""; \ 640 nameString = ""; \ 641 linkString = ""; \ 642 signatureString = ""; \ 643 itemGroups = 0; \ 644 ctime = 0; \ 645 mtime = 0; \ 646 offset = 0; \ 647 cust = 0; \ 648 mode = 0; \ 649 platform = 0xffffffff; \ 650 size = 0; \ 651 originalSize = 0 635 652 636 mimeString = ""; 637 nameString = ""; 638 signatureString = ""; 639 640 itemGroups = 0; 641 ctime = 0; 642 mtime = 0; 643 offset = 0; 644 itemGroups = 0; 645 cust = 0; 646 mode = 0; 647 platform = 0xffffffff; 648 649 size = 0; 650 originalSize = 0; 653 if (!memcmp(buffer, "FilI", 5)) { 654 INIT_VARS("FilI", P_FILE); 651 655 } else if (!memcmp(buffer, "FldI", 5)) { 652 parser_debug("FldI\n"); 653 element = P_DIRECTORY; 654 655 nameString = ""; 656 657 itemGroups = 0; 658 ctime = 0; 659 mtime = 0; 660 offset = 0; 661 itemGroups = 0; 662 cust = 0; 663 platform = 0xffffffff; 664 665 size = 0; 666 originalSize = 0; 656 INIT_VARS("FldI", P_DIRECTORY); 667 657 } else if (!memcmp(buffer, "LnkI", 5)) { 668 parser_debug("LnkI\n"); 669 element = P_LINK; 670 671 nameString = ""; 672 linkString = ""; 673 674 itemGroups = 0; 675 ctime = 0; 676 mtime = 0; 677 offset = 0; 678 itemGroups = 0; 679 cust = 0; 680 platform = 0xffffffff; 681 682 size = 0; 683 originalSize = 0; 658 INIT_VARS("LnkI", P_LINK); 659 } else if (!memcmp(buffer, "ScrI", 5)) { 660 INIT_VARS("ScrI", P_SCRIPT); 684 661 } else if (!memcmp(buffer, "Name", 5)) { 685 662 if (element == P_NONE) { 686 663 RETURN_AND_SET_STATUS(B_ERROR); … … 795 772 swap_data(B_UINT64_TYPE, &size, sizeof(uint64), 796 773 B_SWAP_BENDIAN_TO_HOST); 797 774 } else if (!memcmp(buffer, "OrgS", 5)) { 798 if (element != P_FILE && element != P_LINK ) {775 if (element != P_FILE && element != P_LINK && element != P_SCRIPT) { 799 776 RETURN_AND_SET_STATUS(B_ERROR); 800 777 } 801 778 … … 1019 996 item = new PackageLink(fPackageFile, dest, linkString, 1020 997 localType, ctime, mtime, mode, offset, size); 1021 998 } 999 } else if (element == P_SCRIPT) { 1000 fScripts.AddItem(new PackageScript(fPackageFile, offset, size, 1001 originalSize)); 1022 1002 } else { 1023 1003 // If the directory tree count is equal to zero, this means all 1024 1004 // directory trees have been closed and a padding sequence means the -
src/apps/packageinstaller/PackageItem.cpp
16 16 #include <Directory.h> 17 17 #include <fs_info.h> 18 18 #include <NodeInfo.h> 19 #include <OS.h> 19 20 #include <SymLink.h> 20 21 #include <Volume.h> 21 22 … … 37 38 P_ATTRIBUTE 38 39 }; 39 40 41 extern const char **environ; 40 42 43 41 44 status_t 42 45 inflate_data(uint8 *in, uint32 inSize, uint8 *out, uint32 outSize) 43 46 { 47 parser_debug("inflate_data() called - input_size: %ld, output_size: %ld\n", 48 inSize, outSize); 44 49 z_stream stream; 45 50 stream.zalloc = Z_NULL; 46 51 stream.zfree = Z_NULL; … … 375 380 376 381 377 382 status_t 383 PackageItem::SkipAttribute(uint8 *buffer, bool *attrStarted, bool *done) 384 { 385 status_t ret = B_OK; 386 uint32 length; 387 388 if (!memcmp(buffer, "BeAI", 5)) { 389 parser_debug(" Attribute started.\n"); 390 *attrStarted = true; 391 } else if (!memcmp(buffer, "BeAN", 5)) { 392 if (!*attrStarted) { 393 ret = B_ERROR; 394 return ret; 395 } 396 397 parser_debug(" BeAN.\n"); 398 fPackage->Read(&length, 4); 399 swap_data(B_UINT32_TYPE, &length, sizeof(uint32), 400 B_SWAP_BENDIAN_TO_HOST); 401 402 fPackage->Seek(length, SEEK_CUR); 403 } else if (!memcmp(buffer, "BeAT", 5)) { 404 if (!*attrStarted) { 405 ret = B_ERROR; 406 return ret; 407 } 408 409 parser_debug(" BeAT.\n"); 410 fPackage->Seek(4, SEEK_CUR); 411 } else if (!memcmp(buffer, "BeAD", 5)) { 412 if (!*attrStarted) { 413 ret = B_ERROR; 414 return ret; 415 } 416 417 parser_debug(" BeAD.\n"); 418 uint64 length64; 419 fPackage->Read(&length64, 8); 420 swap_data(B_UINT64_TYPE, &length64, sizeof(length64), B_SWAP_BENDIAN_TO_HOST); 421 422 fPackage->Seek(12 + length64, SEEK_CUR); 423 424 parser_debug(" Data skipped successfuly.\n"); 425 } else if (!memcmp(buffer, padding, 7)) { 426 if (!*attrStarted) { 427 *done = true; 428 return ret; 429 } 430 431 parser_debug(" Padding.\n"); 432 *attrStarted = false; 433 parser_debug(" > Attribute skipped.\n"); 434 } else { 435 parser_debug(" Unknown attribute\n"); 436 ret = B_ERROR; 437 } 438 439 return ret; 440 } 441 442 443 status_t 378 444 PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize, 379 445 bool *done) 380 446 { … … 425 491 } 426 492 427 493 494 // #pragma mark - PackageScript 495 496 497 PackageScript::PackageScript(BFile *parent, uint64 offset, uint64 size, 498 uint64 originalSize) 499 : 500 PackageItem(parent, NULL, 0, 0, 0, offset, size), 501 fOriginalSize(originalSize), 502 fThreadId(-1) 503 { 504 } 505 506 507 status_t 508 PackageScript::DoInstall(const char *path, ItemState *state) 509 { 510 status_t ret = B_OK; 511 parser_debug("Script: DoInstall() called!\n"); 512 513 if (fOffset) { 514 parser_debug("We have an offset\n"); 515 if (!fPackage) 516 return B_ERROR; 517 518 ret = fPackage->InitCheck(); 519 if (ret != B_OK) 520 return ret; 521 522 // We need to parse the data section now 523 fPackage->Seek(fOffset, SEEK_SET); 524 uint8 buffer[7]; 525 bool attrStarted = false, done = false; 526 527 uint8 section = P_ATTRIBUTE; 528 529 while (fPackage->Read(buffer, 7) == 7) { 530 if (!memcmp(buffer, "FBeA", 5)) { 531 parser_debug("-> Attribute\n"); 532 section = P_ATTRIBUTE; 533 continue; 534 } else if (!memcmp(buffer, "FiDa", 5)) { 535 parser_debug("-> File data\n"); 536 section = P_DATA; 537 continue; 538 } 539 540 switch (section) { 541 case P_ATTRIBUTE: 542 ret = SkipAttribute(buffer, &attrStarted, &done); 543 break; 544 545 case P_DATA: 546 ret = _ParseScript(buffer, fOriginalSize, &done); 547 break; 548 549 default: 550 return B_ERROR; 551 } 552 553 if (ret != B_OK || done) 554 break; 555 } 556 } 557 558 parser_debug("Ret: %d %s\n", ret, strerror(ret)); 559 return ret; 560 } 561 562 563 const char* 564 PackageScript::ItemKind() 565 { 566 return "script"; 567 } 568 569 570 status_t 571 PackageScript::_ParseScript(uint8 *buffer, uint64 originalSize, bool *done) 572 { 573 status_t ret = B_OK; 574 575 if (!memcmp(buffer, "FiMF", 5)) { 576 parser_debug(" Found file (script) data.\n"); 577 uint64 compressed, original; 578 fPackage->Read(&compressed, 8); 579 swap_data(B_UINT64_TYPE, &compressed, sizeof(uint64), 580 B_SWAP_BENDIAN_TO_HOST); 581 582 fPackage->Read(&original, 8); 583 swap_data(B_UINT64_TYPE, &original, sizeof(uint64), 584 B_SWAP_BENDIAN_TO_HOST); 585 parser_debug(" Still good... (%llu : %llu)\n", original, 586 originalSize); 587 588 if (original != originalSize) { 589 parser_debug(" File size mismatch\n"); 590 return B_ERROR; // File size mismatch 591 } 592 parser_debug(" Still good...\n"); 593 594 if (fPackage->Read(buffer, 4) != 4) { 595 parser_debug(" Read(buffer, 4) failed\n"); 596 return B_ERROR; 597 } 598 parser_debug(" Still good...\n"); 599 600 uint8 *temp = new uint8[compressed]; 601 if (fPackage->Read(temp, compressed) != compressed) { 602 parser_debug(" Read(temp, compressed) failed\n"); 603 delete[] temp; 604 return B_ERROR; 605 } 606 607 uint8 *script = new uint8[original]; 608 ret = inflate_data(temp, compressed, script, original); 609 if (ret != B_OK) { 610 parser_debug(" inflate_data failed\n"); 611 delete[] temp; 612 delete[] script; 613 return ret; 614 } 615 616 ret = _RunScript(script, originalSize); 617 delete[] script; 618 delete[] temp; 619 parser_debug(" Script data inflation complete!\n"); 620 } else if (!memcmp(buffer, padding, 7)) { 621 *done = true; 622 return ret; 623 } else { 624 parser_debug("_ParseData unknown tag\n"); 625 ret = B_ERROR; 626 } 627 628 return ret; 629 } 630 631 632 status_t 633 PackageScript::_RunScript(uint8 *script, uint32 len) 634 { 635 // This function written by Peter Folk <pfolk@uni.uiuc.edu> 636 // and published in the BeDevTalk FAQ, modified for use in the 637 // PackageInstaller 638 // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209 639 640 // Save current FDs 641 int old_in = dup(0); 642 int old_out = dup(1); 643 int old_err = dup(2); 644 645 int filedes[2]; 646 647 /* Create new pipe FDs as stdin, stdout, stderr */ 648 pipe(filedes); dup2(filedes[0], 0); close(filedes[0]); 649 int in = filedes[1]; // Write to in, appears on cmd's stdin 650 pipe(filedes); dup2(filedes[1], 1); close(filedes[1]); 651 pipe(filedes); dup2(filedes[1], 2); close(filedes[1]); 652 653 const char **argv = new const char * [3]; 654 argv[0] = strdup("/bin/sh"); 655 argv[1] = strdup("-s"); 656 argv[2] = NULL; 657 658 // "load" command. 659 fThreadId = load_image(2, argv, environ); 660 661 int i; 662 for (i = 0; i < 2; i++) 663 delete argv[i]; 664 delete [] argv; 665 666 if (fThreadId < B_OK) 667 return fThreadId; 668 669 // thread id is now suspended. 670 setpgid(fThreadId, fThreadId); 671 672 // Restore old FDs 673 close(0); dup(old_in); close(old_in); 674 close(1); dup(old_out); close(old_out); 675 close(2); dup(old_err); close(old_err); 676 677 set_thread_priority(fThreadId, B_LOW_PRIORITY); 678 resume_thread(fThreadId); 679 680 // Write the script 681 if (write(in, script, len) != len || write(in, "\nexit\n", 6) != 6) { 682 parser_debug("Writing script failed\n"); 683 kill_thread(fThreadId); 684 return B_ERROR; 685 } 686 687 return B_OK; 688 } 689 690 428 691 // #pragma mark - PackageDirectory 429 692 430 693 … … 437 700 438 701 439 702 status_t 440 PackageDirectory:: WriteToPath(const char *path, ItemState *state)703 PackageDirectory::DoInstall(const char *path, ItemState *state) 441 704 { 442 705 BPath &destination = state->destination; 443 706 status_t ret; 444 parser_debug("Directory: %s WriteToPath() called!\n", fPath.String());707 parser_debug("Directory: %s DoInstall() called!\n", fPath.String()); 445 708 446 709 ret = InitPath(path, &destination); 447 710 parser_debug("Ret: %d %s\n", ret, strerror(ret)); … … 499 762 500 763 501 764 status_t 502 PackageFile:: WriteToPath(const char *path, ItemState *state)765 PackageFile::DoInstall(const char *path, ItemState *state) 503 766 { 504 767 if (state == NULL) 505 768 return B_ERROR; 506 769 507 770 BPath &destination = state->destination; 508 771 status_t ret = B_OK; 509 parser_debug("File: %s WriteToPath() called!\n", fPath.String());772 parser_debug("File: %s DoInstall() called!\n", fPath.String()); 510 773 511 774 BFile file; 512 775 if (state->status == B_NO_INIT || destination.InitCheck() != B_OK) { … … 661 924 662 925 663 926 status_t 664 PackageLink:: WriteToPath(const char *path, ItemState *state)927 PackageLink::DoInstall(const char *path, ItemState *state) 665 928 { 666 929 if (state == NULL) 667 930 return B_ERROR; 668 931 669 932 status_t ret = B_OK; 670 933 BSymLink symlink; 671 parser_debug("Symlink: %s WriteToPath() called!\n", fPath.String());934 parser_debug("Symlink: %s DoInstall() called!\n", fPath.String()); 672 935 673 936 BPath &destination = state->destination; 674 937 BDirectory *dir = &state->parent; -
src/apps/packageinstaller/PackageInfo.h
33 33 BMallocIO *GetSplashScreen() { return fHasImage ? &fImage : NULL; } 34 34 int32 GetProfileCount() { return fProfiles.CountItems(); } 35 35 pkg_profile *GetProfile(int32 num) { return static_cast<pkg_profile *>(fProfiles.ItemAt(num)); } 36 int32 GetScriptCount() { return fScripts.CountItems(); } 37 PackageScript *GetScript(int32 num) { return static_cast<PackageScript *>(fScripts.ItemAt(num)); } 36 38 37 39 status_t Parse(); 38 40 status_t InitCheck() { return fStatus; } … … 56 58 bool fHasImage; 57 59 58 60 BList fFiles; // Holds all files in the package 61 BList fScripts; 59 62 }; 60 63 61 64 -
src/apps/packageinstaller/PackageItem.h
72 72 uint64 offset = 0, uint64 size = 0); 73 73 virtual ~PackageItem(); 74 74 75 virtual status_t WriteToPath(const char* path = NULL,75 virtual status_t DoInstall(const char* path = NULL, 76 76 ItemState *state = NULL) = 0; 77 77 virtual void SetTo(BFile* parent, const BString& path, 78 78 uint8 type, uint32 ctime, uint32 mtime, 79 79 uint64 offset = 0, uint64 size = 0); 80 80 virtual const char* ItemKind() = 0; 81 81 82 protected:82 protected: 83 83 status_t InitPath(const char* path, BPath* destination); 84 84 status_t HandleAttributes(BPath* destination, BNode* node, 85 85 const char* header); … … 91 91 uint64* tempSize, uint64* attrCSize, 92 92 uint64* attrOSize, bool* attrStarted, 93 93 bool* done); 94 status_t SkipAttribute(uint8 *buffer, bool *attrStarted, 95 bool *done); 94 96 status_t ParseData(uint8* buffer, BFile* file, 95 97 uint64 originalSize, bool* done); 96 98 … … 111 113 uint8 type, uint32 ctime, uint32 mtime, 112 114 uint64 offset = 0, uint64 size = 0); 113 115 114 virtual status_t WriteToPath(const char* path = NULL,116 virtual status_t DoInstall(const char* path = NULL, 115 117 ItemState *state = NULL); 116 118 virtual const char* ItemKind(); 117 119 }; 118 120 119 121 122 class PackageScript : public PackageItem { 123 public: 124 PackageScript(BFile* parent, uint64 offset = 0, uint64 size = 0, 125 uint64 originalSize = 0); 126 127 virtual status_t DoInstall(const char* path = NULL, 128 ItemState *state = NULL); 129 virtual const char* ItemKind(); 130 131 thread_id GetThreadId() { return fThreadId; } 132 void SetThreadId(thread_id id) { fThreadId = id; } 133 134 private: 135 status_t _ParseScript(uint8 *buffer, uint64 originalSize, 136 bool *done); 137 status_t _RunScript(uint8 *script, uint32 len); 138 139 uint64 fOriginalSize; 140 thread_id fThreadId; 141 }; 142 143 120 144 class PackageFile : public PackageItem { 121 145 public: 122 146 PackageFile(BFile* parent, const BString& path, … … 125 149 uint32 platform, const BString& mime, 126 150 const BString& signature, uint32 mode); 127 151 128 virtual status_t WriteToPath(const char* path = NULL,152 virtual status_t DoInstall(const char* path = NULL, 129 153 ItemState *state = NULL); 130 154 virtual const char* ItemKind(); 131 155 … … 146 170 uint32 mtime, uint32 mode, uint64 offset = 0, 147 171 uint64 size = 0); 148 172 149 virtual status_t WriteToPath(const char* path = NULL,173 virtual status_t DoInstall(const char* path = NULL, 150 174 ItemState *state = NULL); 151 175 virtual const char* ItemKind(); 152 176 -
src/apps/packageinstaller/PackageInstall.cpp
1 /* 2 * Copyright (c) 2010, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Author: 6 * Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org> 7 */ 8 9 10 #include "PackageInstall.h" 11 12 #include "InstalledPackageInfo.h" 13 #include "PackageItem.h" 14 #include "PackageView.h" 15 16 #include <Alert.h> 17 #include <stdio.h> 18 19 20 // Macro reserved for later localization 21 #define T(x) x 22 23 static int32 install_function(void *data) 24 { 25 // TODO: Inform if already one thread is running 26 PackageInstall *install = static_cast<PackageInstall *>(data); 27 if (data == NULL) 28 return -1; 29 30 install->Install(); 31 return 0; 32 } 33 34 35 PackageInstall::PackageInstall(PackageView *parent) 36 : fParent(parent), 37 fThreadId(-1) 38 { 39 } 40 41 42 PackageInstall::~PackageInstall() 43 { 44 } 45 46 47 status_t 48 PackageInstall::Start() 49 { 50 status_t ret = B_OK; 51 52 fIdLocker.Lock(); 53 if (fThreadId > -1) { 54 ret = B_BUSY; 55 } else { 56 fThreadId = spawn_thread(install_function, "install_package", B_NORMAL_PRIORITY, 57 static_cast<void *>(this)); 58 resume_thread(fThreadId); 59 } 60 fIdLocker.Unlock(); 61 62 return ret; 63 } 64 65 66 void 67 PackageInstall::Stop() 68 { 69 fIdLocker.Lock(); 70 if (fThreadId > -1) { 71 kill_thread(fThreadId); 72 fThreadId = -1; 73 } 74 fIdLocker.Unlock(); 75 76 fCurrentScriptLocker.Lock(); 77 if (fCurrentScript != NULL) { 78 thread_id id = fCurrentScript->GetThreadId(); 79 if (id > -1) { 80 fCurrentScript->SetThreadId(-1); 81 kill_thread(id); 82 } 83 fCurrentScript = NULL; 84 } 85 fCurrentScriptLocker.Unlock(); 86 } 87 88 89 void 90 PackageInstall::Install() 91 { 92 // A message sending wrapper around _Install() 93 uint32 msg = _Install(); 94 if (fParent && fParent->Looper()) 95 fParent->Looper()->PostMessage(new BMessage(msg), fParent); 96 } 97 98 99 uint32 100 PackageInstall::_Install() 101 { 102 PackageInfo *info = fParent->GetPackageInfo(); 103 pkg_profile *type = static_cast<pkg_profile *>(info->GetProfile(fParent->GetCurrentType())); 104 uint32 n = type->items.CountItems(), m = info->GetScriptCount(); 105 106 PackageStatus *progress = fParent->GetStatusWindow(); 107 progress->Reset(n + m + 5); 108 109 progress->StageStep(1, T("Preparing package")); 110 111 InstalledPackageInfo packageInfo(info->GetName(), info->GetVersion()); 112 113 status_t err = packageInfo.InitCheck(); 114 if (err == B_OK) { 115 // The package is already installed, inform the user 116 BAlert *reinstall = new BAlert("reinstall", 117 T("The given package seems to be already installed on your system. " 118 "Would you like to uninstall the existing one and continue the " 119 "installation?"), T("Continue"), T("Abort")); 120 121 if (reinstall->Go() == 0) { 122 // Uninstall the package 123 err = packageInfo.Uninstall(); 124 if (err != B_OK) { 125 fprintf(stderr, "Error on uninstall\n"); 126 return P_MSG_I_ERROR; 127 } 128 129 err = packageInfo.SetTo(info->GetName(), info->GetVersion(), true); 130 if (err != B_OK) { 131 fprintf(stderr, "Error on SetTo\n"); 132 return P_MSG_I_ERROR; 133 } 134 } else { 135 // Abort the installation 136 return P_MSG_I_ABORT; 137 } 138 } else if (err == B_ENTRY_NOT_FOUND) { 139 err = packageInfo.SetTo(info->GetName(), info->GetVersion(), true); 140 if (err != B_OK) { 141 fprintf(stderr, "Error on SetTo\n"); 142 return P_MSG_I_ERROR; 143 } 144 } else if (progress->Stopped()) { 145 return P_MSG_I_ABORT; 146 } else { 147 fprintf(stderr, "returning on error\n"); 148 return P_MSG_I_ERROR; 149 } 150 151 progress->StageStep(1, T("Installing files and folders")); 152 153 // Install files and directories 154 PackageItem *iter; 155 ItemState state; 156 uint32 i; 157 int32 choice; 158 BString label; 159 160 packageInfo.SetName(info->GetName()); 161 // TODO: Here's a small problem, since right now it's not quite sure 162 // which description is really used as such. The one displayed on 163 // the installer is mostly package installation description, but 164 // most people use it for describing the application in more detail 165 // then in the short description. 166 // For now, we'll use the short description if possible. 167 BString description = info->GetShortDescription(); 168 if (description.Length() <= 0) 169 description = info->GetDescription(); 170 packageInfo.SetDescription(description.String()); 171 packageInfo.SetSpaceNeeded(type->space_needed); 172 173 fItemExistsPolicy = P_EXISTS_NONE; 174 175 const char *installPath = fParent->GetCurrentPath()->Path(); 176 for (i = 0; i < n; i++) { 177 state.Reset(fItemExistsPolicy); // Reset the current item state 178 iter = static_cast<PackageItem *>(type->items.ItemAt(i)); 179 180 err = iter->DoInstall(installPath, &state); 181 if (err == B_FILE_EXISTS) { 182 // Writing to path failed because path already exists - ask the user 183 // what to do and retry the writing process 184 choice = fParent->ItemExists(*iter, state.destination, fItemExistsPolicy); 185 if (choice != P_EXISTS_ABORT) { 186 state.policy = choice; 187 err = iter->DoInstall(installPath, &state); 188 } 189 } 190 191 if (err != B_OK) { 192 fprintf(stderr, "Error while writing path\n"); 193 return P_MSG_I_ERROR; 194 } 195 196 if (progress->Stopped()) 197 return P_MSG_I_ABORT; 198 label = ""; 199 label << (uint32)(i + 1) << " of " << (uint32)n; 200 progress->StageStep(1, NULL, label.String()); 201 202 packageInfo.AddItem(state.destination.Path()); 203 } 204 205 progress->StageStep(1, T("Running post-installation scripts"), ""); 206 207 PackageScript *scr; 208 status_t status; 209 // Run all scripts 210 for (i = 0; i < m; i++) { 211 scr = info->GetScript(i); 212 213 fCurrentScriptLocker.Lock(); 214 fCurrentScript = scr; 215 216 if (scr->DoInstall() != B_OK) { 217 fprintf(stderr, "Error while running script\n"); 218 return P_MSG_I_ERROR; 219 } 220 fCurrentScriptLocker.Unlock(); 221 222 wait_for_thread(scr->GetThreadId(), &status); 223 fCurrentScriptLocker.Lock(); 224 scr->SetThreadId(-1); 225 fCurrentScript = NULL; 226 fCurrentScriptLocker.Unlock(); 227 228 if (progress->Stopped()) 229 return P_MSG_I_ABORT; 230 label = ""; 231 label << (uint32)(i + 1) << " of " << (uint32)m; 232 progress->StageStep(1, NULL, label.String()); 233 } 234 235 progress->StageStep(1, T("Finishing installation"), ""); 236 237 err = packageInfo.Save(); 238 if (err != B_OK) 239 return P_MSG_I_ERROR; 240 241 progress->StageStep(1, T("Done")); 242 243 // Inform our parent that we finished 244 return P_MSG_I_FINISHED; 245 } 246 -
src/apps/packageinstaller/Jamfile
11 11 PackageView.cpp 12 12 PackageInfo.cpp 13 13 PackageItem.cpp 14 PackageInstall.cpp 14 15 PackageStatus.cpp 15 16 PackageTextViewer.cpp 16 17 PackageImageViewer.cpp -
src/apps/packageinstaller/PackageView.cpp
63 63 //BView("package_view", B_WILL_DRAW, new BGroupLayout(B_HORIZONTAL)), 64 64 fOpenPanel(new BFilePanel(B_OPEN_PANEL, NULL, NULL, 65 65 B_DIRECTORY_NODE, false)), 66 fInfo(ref) 66 fInfo(ref), 67 fInstallProcess(this) 67 68 { 68 69 _InitView(); 69 70 … … 121 122 // attaching the view to the window 122 123 _GroupChanged(0); 123 124 124 fStatusWindow = new PackageStatus(T("Installation progress")); 125 fStatusWindow = new PackageStatus(T("Installation progress"), NULL, NULL, 126 this); 125 127 126 128 // Show the splash screen, if present 127 129 BMallocIO *image = fInfo.GetSplashScreen(); … … 133 135 // Show the disclaimer/info text popup, if present 134 136 BString disclaimer = fInfo.GetDisclaimer(); 135 137 if (disclaimer.Length() != 0) { 136 138 PackageTextViewer *text = new PackageTextViewer(disclaimer.String()); 137 139 int32 selection = text->Go(); 138 140 // The user didn't accept our disclaimer, this means we cannot continue. 139 141 if (selection == 0) { 140 142 BWindow *parent = Window(); 141 143 if (parent && parent->Lock()) 142 144 parent->Quit(); … … 153 155 case P_MSG_INSTALL: 154 156 { 155 157 fInstall->SetEnabled(false); 158 fInstallTypes->SetEnabled(false); 159 fDestination->SetEnabled(false); 156 160 fStatusWindow->Show(); 157 BAlert *notify;158 status_t ret = Install();159 if (ret == B_OK) {160 notify = new BAlert("installation_success",161 T("The package you requested has been successfully installed "162 "on your system."), T("OK"));163 161 164 notify->Go(); 165 fStatusWindow->Hide(); 166 167 BWindow *parent = Window(); 168 if (parent && parent->Lock()) 169 parent->Quit(); 170 } 171 else if (ret == B_FILE_EXISTS) 172 notify = new BAlert("installation_aborted", 173 T("The installation of the package has been aborted."), T("OK")); 174 else { 175 notify = new BAlert("installation_failed", // TODO: Review this 176 T("The requested package failed to install on your system. This " 177 "might be a problem with the target package file. Please consult " 178 "this issue with the package distributor."), T("OK"), NULL, 179 NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 180 fprintf(stderr, "Error while installing the package : %s\n", strerror(ret)); 181 } 182 notify->Go(); 183 fStatusWindow->Hide(); 184 fInstall->SetEnabled(true); 185 162 fInstallProcess.Start(); 186 163 break; 187 164 } 188 165 case P_MSG_PATH_CHANGED: … … 204 181 } 205 182 break; 206 183 } 184 case P_MSG_I_FINISHED: 185 { 186 BAlert *notify = new BAlert("installation_success", 187 T("The package you requested has been successfully installed " 188 "on your system."), T("OK")); 189 190 notify->Go(); 191 fStatusWindow->Hide(); 192 fInstall->SetEnabled(true); 193 fInstallTypes->SetEnabled(true); 194 fDestination->SetEnabled(true); 195 fInstallProcess.Stop(); 196 197 BWindow *parent = Window(); 198 if (parent && parent->Lock()) 199 parent->Quit(); 200 break; 201 } 202 case P_MSG_I_ABORT: 203 { 204 BAlert *notify = new BAlert("installation_aborted", 205 T("The installation of the package has been aborted."), T("OK")); 206 notify->Go(); 207 fStatusWindow->Hide(); 208 fInstall->SetEnabled(true); 209 fInstallTypes->SetEnabled(true); 210 fDestination->SetEnabled(true); 211 fInstallProcess.Stop(); 212 break; 213 } 214 case P_MSG_I_ERROR: 215 { 216 BAlert *notify = new BAlert("installation_failed", // TODO: Review this 217 T("The requested package failed to install on your system. This " 218 "might be a problem with the target package file. Please consult " 219 "this issue with the package distributor."), T("OK"), NULL, 220 NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 221 fprintf(stderr, "Error while installing the package\n"); 222 notify->Go(); 223 fStatusWindow->Hide(); 224 fInstall->SetEnabled(true); 225 fInstallTypes->SetEnabled(true); 226 fDestination->SetEnabled(true); 227 fInstallProcess.Stop(); 228 break; 229 } 230 case P_MSG_STOP: 231 { 232 // This message is sent to us by the PackageStatus window, informing 233 // user interruptions. 234 // We actually use this message only when a post installation script 235 // is running and we want to kill it while it's still running 236 fStatusWindow->Hide(); 237 fInstall->SetEnabled(true); 238 fInstallTypes->SetEnabled(true); 239 fDestination->SetEnabled(true); 240 fInstallProcess.Stop(); 241 break; 242 } 207 243 case B_REFS_RECEIVED: 208 244 { 209 245 entry_ref ref; … … 247 283 } 248 284 249 285 250 status_t 251 PackageView::I nstall()286 int32 287 PackageView::ItemExists(PackageItem &item, BPath &path, int32 &policy) 252 288 { 253 pkg_profile *type = static_cast<pkg_profile *>(fInfo.GetProfile(fCurrentType)); 254 uint32 n = type->items.CountItems(); 289 int32 choice = P_EXISTS_NONE; 255 290 256 fStatusWindow->Reset(n + 4); 291 switch (policy) { 292 case P_EXISTS_OVERWRITE: 293 choice = P_EXISTS_OVERWRITE; 294 break; 257 295 258 fStatusWindow->StageStep(1, "Preparing package"); 296 case P_EXISTS_SKIP: 297 choice = P_EXISTS_SKIP; 298 break; 259 299 260 InstalledPackageInfo packageInfo(fInfo.GetName(), fInfo.GetVersion()); 300 case P_EXISTS_ASK: 301 case P_EXISTS_NONE: 302 { 303 BString alertString = T("The "); 261 304 262 status_t err = packageInfo.InitCheck(); 263 err = B_ENTRY_NOT_FOUND; 264 if (err == B_OK) { 265 // The package is already installed, inform the user 266 BAlert *reinstall = new BAlert("reinstall", 267 T("The given package seems to be already installed on your system. " 268 "Would you like to uninstall the existing one and continue the " 269 "installation?"), T("Continue"), T("Abort")); 305 alertString << item.ItemKind() << T(" named \'") << path.Leaf() << "\' "; 306 alertString << T("already exists in the given path.\nReplace the file with " 307 "the one from this package or skip it?"); 270 308 271 if (reinstall->Go() == 0) { 272 // Uninstall the package 273 err = packageInfo.Uninstall(); 274 if (err != B_OK) { 275 fprintf(stderr, "Error on uninstall\n"); 276 return err; 277 } 309 BAlert *alert = new BAlert(T("file_exists"), alertString.String(), 310 T("Replace"), T("Skip"), T("Abort")); 278 311 279 err = packageInfo.SetTo(fInfo.GetName(), fInfo.GetVersion(), true); 280 if (err != B_OK) { 281 fprintf(stderr, "Error on SetTo\n"); 282 return err; 312 choice = alert->Go(); 313 switch (choice) { 314 case 0: 315 choice = P_EXISTS_OVERWRITE; 316 break; 317 case 1: 318 choice = P_EXISTS_SKIP; 319 break; 320 default: 321 return P_EXISTS_ABORT; 283 322 } 284 }285 else {286 // Abort the installation287 return B_FILE_EXISTS;288 }289 }290 else if (err == B_ENTRY_NOT_FOUND) {291 err = packageInfo.SetTo(fInfo.GetName(), fInfo.GetVersion(), true);292 if (err != B_OK) {293 fprintf(stderr, "Error on SetTo\n");294 return err;295 }296 }297 else if (fStatusWindow->Stopped())298 return B_FILE_EXISTS;299 else {300 fprintf(stderr, "returning on error\n");301 return err;302 }303 323 304 fStatusWindow->StageStep(1, "Installing files and folders"); 324 if (policy == P_EXISTS_NONE) { 325 // TODO: Maybe add 'No, but ask again' type of choice as well? 326 alertString = T("Do you want to remember this decision for the rest of " 327 "this installation?\nAll existing files will be "); 328 alertString << ((choice == P_EXISTS_OVERWRITE) 329 ? T("replaced?") : T("skipped?")); 305 330 306 // Install files and directories 307 PackageItem *iter; 308 ItemState state; 309 uint32 i; 310 int32 choice; 311 BString label; 331 alert = new BAlert(T("policy_decision"), alertString.String(), 332 T("Yes"), T("No")); 312 333 313 packageInfo.SetName(fInfo.GetName()); 314 // TODO: Here's a small problem, since right now it's not quite sure 315 // which description is really used as such. The one displayed on 316 // the installer is mostly package installation description, but 317 // most people use it for describing the application in more detail 318 // then in the short description. 319 // For now, we'll use the short description if possible. 320 BString description = fInfo.GetShortDescription(); 321 if (description.Length() <= 0) 322 description = fInfo.GetDescription(); 323 packageInfo.SetDescription(description.String()); 324 packageInfo.SetSpaceNeeded(type->space_needed); 325 326 fItemExistsPolicy = P_EXISTS_NONE; 327 328 for (i = 0; i < n; i++) { 329 state.Reset(fItemExistsPolicy); // Reset the current item state 330 iter = static_cast<PackageItem *>(type->items.ItemAt(i)); 331 332 err = iter->WriteToPath(fCurrentPath.Path(), &state); 333 if (err == B_FILE_EXISTS) { 334 // Writing to path failed because path already exists - ask the user 335 // what to do and retry the writing process 336 choice = _ItemExists(*iter, state.destination); 337 if (choice != P_EXISTS_ABORT) { 338 state.policy = choice; 339 err = iter->WriteToPath(fCurrentPath.Path(), &state); 334 int32 decision = alert->Go(); 335 if (decision == 0) 336 policy = choice; 337 else 338 policy = P_EXISTS_ASK; 340 339 } 340 break; 341 341 } 342 343 if (err != B_OK) {344 fprintf(stderr, "Error while writing path %s\n", fCurrentPath.Path());345 return err;346 }347 348 if (fStatusWindow->Stopped())349 return B_FILE_EXISTS;350 label = "";351 label << (uint32)(i + 1) << " of " << (uint32)n;352 fStatusWindow->StageStep(1, NULL, label.String());353 354 packageInfo.AddItem(state.destination.Path());355 342 } 356 343 357 fStatusWindow->StageStep(1, "Finishing installation", ""); 358 359 err = packageInfo.Save(); 360 if (err != B_OK) 361 return err; 362 363 fStatusWindow->StageStep(1, "Done"); 364 365 return B_OK; 344 return choice; 366 345 } 367 346 368 347 … … 550 529 } 551 530 552 531 553 int32554 PackageView::_ItemExists(PackageItem &item, BPath &path)555 {556 int32 choice = P_EXISTS_NONE;557 558 switch (fItemExistsPolicy) {559 case P_EXISTS_OVERWRITE:560 choice = P_EXISTS_OVERWRITE;561 break;562 563 case P_EXISTS_SKIP:564 choice = P_EXISTS_SKIP;565 break;566 567 case P_EXISTS_ASK:568 case P_EXISTS_NONE:569 {570 BString alertString = T("The ");571 572 alertString << item.ItemKind() << T(" named \'") << path.Leaf() << "\' ";573 alertString << T("already exists in the given path.\nReplace the file with "574 "the one from this package or skip it?");575 576 BAlert *alert = new BAlert(T("file_exists"), alertString.String(),577 T("Replace"), T("Skip"), T("Abort"));578 579 choice = alert->Go();580 switch (choice) {581 case 0:582 choice = P_EXISTS_OVERWRITE;583 break;584 case 1:585 choice = P_EXISTS_SKIP;586 break;587 default:588 return P_EXISTS_ABORT;589 }590 591 if (fItemExistsPolicy == P_EXISTS_NONE) {592 // TODO: Maybe add 'No, but ask again' type of choice as well?593 alertString = T("Do you want to remember this decision for the rest of "594 "this installation?\nAll existing files will be ");595 alertString << ((choice == P_EXISTS_OVERWRITE)596 ? T("replaced?") : T("skipped?"));597 598 alert = new BAlert(T("policy_decision"), alertString.String(),599 T("Yes"), T("No"));600 601 int32 decision = alert->Go();602 if (decision == 0)603 fItemExistsPolicy = choice;604 else605 fItemExistsPolicy = P_EXISTS_ASK;606 }607 break;608 }609 }610 611 return choice;612 }613 614 615 532 status_t 616 533 PackageView::_GroupChanged(int32 index) 617 534 { -
src/apps/packageinstaller/PackageInstall.h
1 /* 2 * Copyright (c) 2010, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Author: 6 * Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org> 7 */ 8 #ifndef PACKAGE_INSTALL_H 9 #define PACKAGE_INSTALL_H 10 11 #include <Locker.h> 12 13 class PackageView; 14 class PackageScript; 15 16 enum { 17 P_MSG_I_FINISHED = 'pifi', 18 P_MSG_I_ABORT = 'piab', 19 P_MSG_I_ERROR = 'pier' 20 }; 21 22 class PackageInstall { 23 public: 24 PackageInstall(PackageView *parent); 25 ~PackageInstall(); 26 27 status_t Start(); 28 void Stop(); 29 void Install(); 30 31 private: 32 uint32 _Install(); 33 34 PackageView *fParent; 35 thread_id fThreadId; 36 BLocker fIdLocker; 37 38 PackageScript *fCurrentScript; 39 BLocker fCurrentScriptLocker; // XXX: will we need this? 40 int32 fItemExistsPolicy; 41 }; 42 43 #endif -
src/apps/packageinstaller/PackageView.h
10 10 11 11 12 12 #include "PackageInfo.h" 13 #include "PackageInstall.h" 13 14 #include "PackageStatus.h" 14 15 15 #include <View.h>16 16 #include <Box.h> 17 17 #include <Button.h> 18 #include <FilePanel.h> 18 19 #include <MenuField.h> 19 #include < FilePanel.h>20 #include <View.h> 20 21 21 22 class BPopUpMenu; 22 23 class BTextView; … … 37 38 void AttachedToWindow(); 38 39 void MessageReceived(BMessage *msg); 39 40 40 status_t Install();41 int32 ItemExists(PackageItem &item, BPath &path, int32 &policy); 41 42 43 BPath *GetCurrentPath() { return &fCurrentPath; } 44 PackageInfo *GetPackageInfo() { return &fInfo; } 45 uint32 GetCurrentType() { return fCurrentType; } 46 PackageStatus *GetStatusWindow() { return fStatusWindow; } 47 42 48 private: 43 49 void _InitView(); 44 50 void _InitProfiles(); 45 int32 _ItemExists(PackageItem &item, BPath &path);46 51 47 52 status_t _GroupChanged(int32 index); 48 53 … … 55 60 BFilePanel *fOpenPanel; 56 61 BPath fCurrentPath; 57 62 uint32 fCurrentType; 58 int32 fItemExistsPolicy;59 63 60 64 PackageInfo fInfo; 61 65 PackageStatus *fStatusWindow; 66 PackageInstall fInstallProcess; 62 67 }; 63 68 64 69 #endif // PACKAGE_VIEW_H