[haiku-commits] r36020 - haiku/trunk/src/apps/packageinstaller

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 1 Apr 2010 21:02:24 +0200 (CEST)

Author: korli
Date: 2010-04-01 21:02:24 +0200 (Thu, 01 Apr 2010)
New Revision: 36020
Changeset: http://dev.haiku-os.org/changeset/36020/haiku
Ticket: http://dev.haiku-os.org/ticket/3762

Modified:
   haiku/trunk/src/apps/packageinstaller/Jamfile
   haiku/trunk/src/apps/packageinstaller/PackageInfo.cpp
   haiku/trunk/src/apps/packageinstaller/PackageInfo.h
   haiku/trunk/src/apps/packageinstaller/PackageItem.cpp
   haiku/trunk/src/apps/packageinstaller/PackageItem.h
   haiku/trunk/src/apps/packageinstaller/PackageStatus.cpp
   haiku/trunk/src/apps/packageinstaller/PackageStatus.h
   haiku/trunk/src/apps/packageinstaller/PackageView.cpp
   haiku/trunk/src/apps/packageinstaller/PackageView.h
Log:
Applied patch by sil2100 that enables handling of script files (bug #3762)


Modified: haiku/trunk/src/apps/packageinstaller/Jamfile
===================================================================
--- haiku/trunk/src/apps/packageinstaller/Jamfile       2010-04-01 18:35:48 UTC 
(rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/Jamfile       2010-04-01 19:02:24 UTC 
(rev 36020)
@@ -11,6 +11,7 @@
        PackageView.cpp
        PackageInfo.cpp
        PackageItem.cpp
+       PackageInstall.cpp
        PackageStatus.cpp
        PackageTextViewer.cpp
        PackageImageViewer.cpp

Modified: haiku/trunk/src/apps/packageinstaller/PackageInfo.cpp
===================================================================
--- haiku/trunk/src/apps/packageinstaller/PackageInfo.cpp       2010-04-01 
18:35:48 UTC (rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/PackageInfo.cpp       2010-04-01 
19:02:24 UTC (rev 36020)
@@ -39,7 +39,8 @@
        P_NONE = 0,
        P_FILE,
        P_DIRECTORY,
-       P_LINK
+       P_LINK,
+       P_SCRIPT
 };
 
 
@@ -86,6 +87,14 @@
                delete file;
        }
 
+       while (true) {
+               file = static_cast<PackageScript *>(fScripts.RemoveItem((long 
int)0));
+               if (file == NULL)
+                       break;
+
+               delete file;
+       }
+
        delete fPackageFile;
 }
 
@@ -624,63 +633,31 @@
                        RETURN_AND_SET_STATUS(B_ERROR);
                }
 
-               // TODO: Here's the deal... there seems to be a strange ScrI 
tag that
-               //      seems to mean script files (check this). It seems 
exaclty the same
-               //      as a normal file (just as script files are normal 
files) so for
-               //      now I'm treating those as files. Check if it's correct!
-               //      No, it isn't and I will fix this soon.
-               if (!memcmp(buffer, "FilI", 5) || !memcmp(buffer, "ScrI", 5)) {
-                       parser_debug("FilI\n");
-                       element = P_FILE;
+#define INIT_VARS(tag, type) \
+               parser_debug(tag "\n"); \
+               element = type; \
+               mimeString = ""; \
+               nameString = ""; \
+               linkString = ""; \
+               signatureString = ""; \
+               itemGroups = 0; \
+               ctime = 0; \
+               mtime = 0; \
+               offset = 0; \
+               cust = 0; \
+               mode = 0; \
+               platform = 0xffffffff; \
+               size = 0; \
+               originalSize = 0
 
-                       mimeString = "";
-                       nameString = "";
-                       signatureString = "";
-
-                       itemGroups = 0;
-                       ctime = 0;
-                       mtime = 0;
-                       offset = 0;
-                       itemGroups = 0;
-                       cust = 0;
-                       mode = 0;
-                       platform = 0xffffffff;
-
-                       size = 0;
-                       originalSize = 0;
+               if (!memcmp(buffer, "FilI", 5)) {
+                       INIT_VARS("FilI", P_FILE);
                } else if (!memcmp(buffer, "FldI", 5)) {
-                       parser_debug("FldI\n");
-                       element = P_DIRECTORY;
-
-                       nameString = "";
-
-                       itemGroups = 0;
-                       ctime = 0;
-                       mtime = 0;
-                       offset = 0;
-                       itemGroups = 0;
-                       cust = 0;
-                       platform = 0xffffffff;
-
-                       size = 0;
-                       originalSize = 0;
+                       INIT_VARS("FldI", P_DIRECTORY);
                } else if (!memcmp(buffer, "LnkI", 5)) {
-                       parser_debug("LnkI\n");
-                       element = P_LINK;
-
-                       nameString = "";
-                       linkString = "";
-
-                       itemGroups = 0;
-                       ctime = 0;
-                       mtime = 0;
-                       offset = 0;
-                       itemGroups = 0;
-                       cust = 0;
-                       platform = 0xffffffff;
-
-                       size = 0;
-                       originalSize = 0;
+                       INIT_VARS("LnkI", P_LINK);
+               } else if (!memcmp(buffer, "ScrI", 5)) {
+                       INIT_VARS("ScrI", P_SCRIPT);
                } else if (!memcmp(buffer, "Name", 5)) {
                        if (element == P_NONE) {
                                RETURN_AND_SET_STATUS(B_ERROR);
@@ -795,7 +772,7 @@
                        swap_data(B_UINT64_TYPE, &size, sizeof(uint64),
                                B_SWAP_BENDIAN_TO_HOST);
                } else if (!memcmp(buffer, "OrgS", 5)) {
-                       if (element != P_FILE && element != P_LINK) {
+                       if (element != P_FILE && element != P_LINK && element 
!= P_SCRIPT) {
                                RETURN_AND_SET_STATUS(B_ERROR);
                        }
 
@@ -1019,6 +996,9 @@
                                        item = new PackageLink(fPackageFile, 
dest, linkString,
                                                localType, ctime, mtime, mode, 
offset, size);
                                }
+                       } else if (element == P_SCRIPT) {
+                               fScripts.AddItem(new 
PackageScript(fPackageFile, offset, size, 
+                                       originalSize));
                        } else {
                                // If the directory tree count is equal to 
zero, this means all
                                // directory trees have been closed and a 
padding sequence means the

Modified: haiku/trunk/src/apps/packageinstaller/PackageInfo.h
===================================================================
--- haiku/trunk/src/apps/packageinstaller/PackageInfo.h 2010-04-01 18:35:48 UTC 
(rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/PackageInfo.h 2010-04-01 19:02:24 UTC 
(rev 36020)
@@ -32,7 +32,11 @@
                const char *GetDisclaimer() { return fDisclaimer.String(); }
                BMallocIO *GetSplashScreen() { return fHasImage ? &fImage : 
NULL; }
                int32 GetProfileCount() { return fProfiles.CountItems(); }
-               pkg_profile *GetProfile(int32 num) { return 
static_cast<pkg_profile *>(fProfiles.ItemAt(num)); }
+               pkg_profile *GetProfile(int32 num) {
+                       return static_cast<pkg_profile 
*>(fProfiles.ItemAt(num)); }
+               int32 GetScriptCount() { return fScripts.CountItems(); }
+               PackageScript *GetScript(int32 num) {
+                       return static_cast<PackageScript 
*>(fScripts.ItemAt(num)); }
                
                status_t Parse();
                status_t InitCheck() { return fStatus; }
@@ -56,6 +60,7 @@
                bool fHasImage;
 
                BList fFiles; // Holds all files in the package
+               BList fScripts;
 };
 
 

Modified: haiku/trunk/src/apps/packageinstaller/PackageItem.cpp
===================================================================
--- haiku/trunk/src/apps/packageinstaller/PackageItem.cpp       2010-04-01 
18:35:48 UTC (rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/PackageItem.cpp       2010-04-01 
19:02:24 UTC (rev 36020)
@@ -16,6 +16,7 @@
 #include <Directory.h>
 #include <fs_info.h>
 #include <NodeInfo.h>
+#include <OS.h>
 #include <SymLink.h>
 #include <Volume.h>
 
@@ -37,10 +38,14 @@
        P_ATTRIBUTE
 };
 
+extern const char **environ;
 
+
 status_t
 inflate_data(uint8 *in, uint32 inSize, uint8 *out, uint32 outSize)
 {
+       parser_debug("inflate_data() called - input_size: %ld, output_size: 
%ld\n",
+               inSize, outSize);
        z_stream stream;
        stream.zalloc = Z_NULL;
        stream.zfree = Z_NULL;
@@ -375,6 +380,68 @@
 
 
 status_t
+PackageItem::SkipAttribute(uint8 *buffer, bool *attrStarted, bool *done)
+{
+       status_t ret = B_OK;
+       uint32 length;
+
+       if (!memcmp(buffer, "BeAI", 5)) {
+               parser_debug(" Attribute started.\n");
+               *attrStarted = true;
+       } else if (!memcmp(buffer, "BeAN", 5)) {
+               if (!*attrStarted) {
+                       ret = B_ERROR;
+                       return ret;
+               }
+
+               parser_debug(" BeAN.\n");
+               fPackage->Read(&length, 4);
+               swap_data(B_UINT32_TYPE, &length, sizeof(uint32),
+                       B_SWAP_BENDIAN_TO_HOST);
+
+               fPackage->Seek(length, SEEK_CUR);
+       } else if (!memcmp(buffer, "BeAT", 5)) {
+               if (!*attrStarted) {
+                       ret = B_ERROR;
+                       return ret;
+               }
+
+               parser_debug(" BeAT.\n");
+               fPackage->Seek(4, SEEK_CUR);
+       } else if (!memcmp(buffer, "BeAD", 5)) {
+               if (!*attrStarted) {
+                       ret = B_ERROR;
+                       return ret;
+               }
+
+               parser_debug(" BeAD.\n");
+               uint64 length64;
+               fPackage->Read(&length64, 8);
+               swap_data(B_UINT64_TYPE, &length64, sizeof(length64),
+                       B_SWAP_BENDIAN_TO_HOST);
+
+               fPackage->Seek(12 + length64, SEEK_CUR);
+
+               parser_debug("  Data skipped successfuly.\n");
+       } else if (!memcmp(buffer, padding, 7)) {
+               if (!*attrStarted) {
+                       *done = true;
+                       return ret;
+               }
+
+               parser_debug(" Padding.\n");
+               *attrStarted = false;
+               parser_debug(" > Attribute skipped.\n");
+       } else {
+               parser_debug(" Unknown attribute\n");
+               ret = B_ERROR;
+       }
+
+       return ret;
+}
+
+
+status_t
 PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
        bool *done)
 {
@@ -425,6 +492,203 @@
 }
 
 
+// #pragma mark - PackageScript
+
+
+PackageScript::PackageScript(BFile *parent, uint64 offset, uint64 size, 
+               uint64 originalSize)
+       :
+       PackageItem(parent, NULL, 0, 0, 0, offset, size),
+       fOriginalSize(originalSize),
+       fThreadId(-1)
+{
+}
+
+
+status_t
+PackageScript::DoInstall(const char *path, ItemState *state)
+{
+       status_t ret = B_OK;
+       parser_debug("Script: DoInstall() called!\n");
+
+       if (fOffset) {
+               parser_debug("We have an offset\n");
+               if (!fPackage)
+                       return B_ERROR;
+
+               ret = fPackage->InitCheck();
+               if (ret != B_OK)
+                       return ret;
+
+               // We need to parse the data section now
+               fPackage->Seek(fOffset, SEEK_SET);
+               uint8 buffer[7];
+               bool attrStarted = false, done = false;
+
+               uint8 section = P_ATTRIBUTE;
+
+               while (fPackage->Read(buffer, 7) == 7) {
+                       if (!memcmp(buffer, "FBeA", 5)) {
+                               parser_debug("-> Attribute\n");
+                               section = P_ATTRIBUTE;
+                               continue;
+                       } else if (!memcmp(buffer, "FiDa", 5)) {
+                               parser_debug("-> File data\n");
+                               section = P_DATA;
+                               continue;
+                       }
+
+                       switch (section) {
+                               case P_ATTRIBUTE:
+                                       ret = SkipAttribute(buffer, 
&attrStarted, &done);
+                                       break;
+
+                               case P_DATA:
+                                       ret = _ParseScript(buffer, 
fOriginalSize, &done);
+                                       break;
+
+                               default:
+                                       return B_ERROR;
+                       }
+
+                       if (ret != B_OK || done)
+                               break;
+               }
+       }
+
+       parser_debug("Ret: %d %s\n", ret, strerror(ret));
+       return ret;
+}
+
+
+const char*
+PackageScript::ItemKind()
+{
+       return "script";
+}
+
+
+status_t
+PackageScript::_ParseScript(uint8 *buffer, uint64 originalSize, bool *done)
+{
+       status_t ret = B_OK;
+
+       if (!memcmp(buffer, "FiMF", 5)) {
+               parser_debug(" Found file (script) data.\n");
+               uint64 compressed, original;
+               fPackage->Read(&compressed, 8);
+               swap_data(B_UINT64_TYPE, &compressed, sizeof(uint64),
+                               B_SWAP_BENDIAN_TO_HOST);
+
+               fPackage->Read(&original, 8);
+               swap_data(B_UINT64_TYPE, &original, sizeof(uint64),
+                               B_SWAP_BENDIAN_TO_HOST);
+               parser_debug(" Still good... (%llu : %llu)\n", original,
+                               originalSize);
+
+               if (original != originalSize) {
+                       parser_debug(" File size mismatch\n");
+                       return B_ERROR; // File size mismatch
+               }
+               parser_debug(" Still good...\n");
+
+               if (fPackage->Read(buffer, 4) != 4) {
+                       parser_debug(" Read(buffer, 4) failed\n");
+                       return B_ERROR;
+               }
+               parser_debug(" Still good...\n");
+
+               uint8 *temp = new uint8[compressed];
+               if (fPackage->Read(temp, compressed) != (int64)compressed) {
+                       parser_debug(" Read(temp, compressed) failed\n");
+                       delete[] temp;
+                       return B_ERROR;
+               }
+
+               uint8 *script = new uint8[original];
+               ret = inflate_data(temp, compressed, script, original);
+               if (ret != B_OK) {
+                       parser_debug(" inflate_data failed\n");
+                       delete[] temp;
+                       delete[] script;
+                       return ret;
+               }
+
+               ret = _RunScript(script, originalSize);
+               delete[] script;
+               delete[] temp;
+               parser_debug(" Script data inflation complete!\n");
+       } else if (!memcmp(buffer, padding, 7)) {
+               *done = true;
+               return ret;
+       } else {
+               parser_debug("_ParseData unknown tag\n");
+               ret = B_ERROR;
+       }
+
+       return ret;
+}
+
+
+status_t
+PackageScript::_RunScript(uint8 *script, uint32 len)
+{
+       // This function written by Peter Folk <pfolk@xxxxxxxxxxxx>
+       // and published in the BeDevTalk FAQ, modified for use in the
+       // PackageInstaller
+       // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
+
+       // Save current FDs
+       int old_in  =  dup(0);
+       int old_out  =  dup(1);
+       int old_err  =  dup(2);
+
+       int filedes[2];
+
+       /* Create new pipe FDs as stdin, stdout, stderr */
+       pipe(filedes);  dup2(filedes[0], 0); close(filedes[0]);
+       int in = filedes[1];  // Write to in, appears on cmd's stdin
+       pipe(filedes);  dup2(filedes[1], 1); close(filedes[1]);
+       pipe(filedes);  dup2(filedes[1], 2); close(filedes[1]);
+
+       const char **argv = new const char * [3];
+       argv[0] = strdup("/bin/sh");
+       argv[1] = strdup("-s");
+       argv[2] = NULL;
+
+       // "load" command.
+       fThreadId = load_image(2, argv, environ);
+
+       int i;
+       for (i = 0; i < 2; i++)
+               delete argv[i];
+       delete [] argv;
+
+       if (fThreadId < B_OK)
+               return fThreadId;
+
+       // thread id is now suspended.
+       setpgid(fThreadId, fThreadId);
+
+       // Restore old FDs
+       close(0); dup(old_in); close(old_in);
+       close(1); dup(old_out); close(old_out);
+       close(2); dup(old_err); close(old_err);
+
+       set_thread_priority(fThreadId, B_LOW_PRIORITY);
+       resume_thread(fThreadId);
+
+       // Write the script
+       if (write(in, script, len) != (int32)len || write(in, "\nexit\n", 6) != 
6) {
+               parser_debug("Writing script failed\n");
+               kill_thread(fThreadId);
+               return B_ERROR;
+       }
+
+       return B_OK;
+}
+
+
 // #pragma mark - PackageDirectory
 
 
@@ -437,11 +701,11 @@
 
 
 status_t
-PackageDirectory::WriteToPath(const char *path, ItemState *state)
+PackageDirectory::DoInstall(const char *path, ItemState *state)
 {
        BPath &destination = state->destination;
        status_t ret;
-       parser_debug("Directory: %s WriteToPath() called!\n", fPath.String());
+       parser_debug("Directory: %s DoInstall() called!\n", fPath.String());
 
        ret = InitPath(path, &destination);
        parser_debug("Ret: %d %s\n", ret, strerror(ret));
@@ -499,14 +763,14 @@
 
 
 status_t
-PackageFile::WriteToPath(const char *path, ItemState *state)
+PackageFile::DoInstall(const char *path, ItemState *state)
 {
        if (state == NULL)
                return B_ERROR;
 
        BPath &destination = state->destination;
        status_t ret = B_OK;
-       parser_debug("File: %s WriteToPath() called!\n", fPath.String());
+       parser_debug("File: %s DoInstall() called!\n", fPath.String());
 
        BFile file;
        if (state->status == B_NO_INIT || destination.InitCheck() != B_OK) {
@@ -661,14 +925,14 @@
 
 
 status_t
-PackageLink::WriteToPath(const char *path, ItemState *state)
+PackageLink::DoInstall(const char *path, ItemState *state)
 {
        if (state == NULL)
                return B_ERROR;
 
        status_t ret = B_OK;
        BSymLink symlink;
-       parser_debug("Symlink: %s WriteToPath() called!\n", fPath.String());
+       parser_debug("Symlink: %s DoInstall() called!\n", fPath.String());
 
        BPath &destination = state->destination;
        BDirectory *dir = &state->parent;

Modified: haiku/trunk/src/apps/packageinstaller/PackageItem.h
===================================================================
--- haiku/trunk/src/apps/packageinstaller/PackageItem.h 2010-04-01 18:35:48 UTC 
(rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/PackageItem.h 2010-04-01 19:02:24 UTC 
(rev 36020)
@@ -72,14 +72,14 @@
                                                                uint64 offset = 
0, uint64 size = 0);
        virtual                                 ~PackageItem();
 
-       virtual status_t                WriteToPath(const char* path = NULL,
+       virtual status_t                DoInstall(const char* path = NULL,
                                                                ItemState 
*state = NULL) = 0;
        virtual void                    SetTo(BFile* parent, const BString& 
path,
                                                                uint8 type, 
uint32 ctime, uint32 mtime,
                                                                uint64 offset = 
0, uint64 size = 0);
        virtual const char*             ItemKind() = 0;
 
-protected:
+       protected:
                        status_t                InitPath(const char* path, 
BPath* destination);
                        status_t                HandleAttributes(BPath* 
destination, BNode* node,
                                                                const char* 
header);
@@ -91,6 +91,8 @@
                                                                uint64* 
tempSize, uint64* attrCSize,
                                                                uint64* 
attrOSize, bool* attrStarted,
                                                                bool* done);
+                       status_t                SkipAttribute(uint8 *buffer, 
bool *attrStarted, 
+                                                               bool *done);
                        status_t                ParseData(uint8* buffer, BFile* 
file,
                                                                uint64 
originalSize, bool* done);
 
@@ -111,12 +113,34 @@
                                                                uint8 type, 
uint32 ctime, uint32 mtime,
                                                                uint64 offset = 
0, uint64 size = 0);
 
-       virtual status_t                WriteToPath(const char* path = NULL,
+       virtual status_t                DoInstall(const char* path = NULL,
                                                                ItemState 
*state = NULL);
        virtual const char*             ItemKind();
 };
 
 
+class PackageScript : public PackageItem {
+public:
+                                                       PackageScript(BFile* 
parent, uint64 offset = 0, 
+                                                               uint64 size = 
0, uint64 originalSize = 0);
+
+       virtual status_t                DoInstall(const char* path = NULL,
+                                                               ItemState 
*state = NULL);
+       virtual const char*             ItemKind();
+
+                       thread_id               GetThreadId() { return 
fThreadId; }
+                       void                    SetThreadId(thread_id id) { 
fThreadId = id; }
+
+private:
+                       status_t                _ParseScript(uint8 *buffer, 
uint64 originalSize, 
+                                                               bool *done);
+                       status_t                _RunScript(uint8 *script, 
uint32 len);
+
+                       uint64                  fOriginalSize;
+                       thread_id               fThreadId;
+};
+
+
 class PackageFile : public PackageItem {
 public:
                                                        PackageFile(BFile* 
parent, const BString& path,
@@ -125,7 +149,7 @@
                                                                uint32 
platform, const BString& mime,
                                                                const BString& 
signature, uint32 mode);
 
-       virtual status_t                WriteToPath(const char* path = NULL,
+       virtual status_t                DoInstall(const char* path = NULL,
                                                                ItemState 
*state = NULL);
        virtual const char*             ItemKind();
 
@@ -146,7 +170,7 @@
                                                                uint32 mtime, 
uint32 mode, uint64 offset = 0,
                                                                uint64 size = 
0);
 
-       virtual status_t                WriteToPath(const char* path = NULL,
+       virtual status_t                DoInstall(const char* path = NULL,
                                                                ItemState 
*state = NULL);
        virtual const char*             ItemKind();
 

Modified: haiku/trunk/src/apps/packageinstaller/PackageStatus.cpp
===================================================================
--- haiku/trunk/src/apps/packageinstaller/PackageStatus.cpp     2010-04-01 
18:35:48 UTC (rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/PackageStatus.cpp     2010-04-01 
19:02:24 UTC (rev 36020)
@@ -92,10 +92,11 @@
 
 
 PackageStatus::PackageStatus(const char *title, const char *label, 
-               const char *trailing)
+               const char *trailing, BHandler *parent)
        :       BWindow(BRect(200, 200, 550, 255), title, B_TITLED_WINDOW,
                        B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_NOT_ZOOMABLE, 0),
-       fIsStopped(false)
+       fIsStopped(false),
+       fParent(parent)
 {
        SetLayout(new BGroupLayout(B_VERTICAL));
 
@@ -129,6 +130,13 @@
        switch (msg->what) {
                case P_MSG_STOP:
                        fIsStopped = true;
+                       if (fParent != NULL) {
+                               // If we have a parent defined, forward this 
message
+                               BLooper *loop = fParent->Looper();
+                               if (loop != NULL) {
+                                       loop->PostMessage(msg, fParent);
+                               }
+                       }
                        break;
                default:
                        BWindow::MessageReceived(msg);

Modified: haiku/trunk/src/apps/packageinstaller/PackageStatus.h
===================================================================
--- haiku/trunk/src/apps/packageinstaller/PackageStatus.h       2010-04-01 
18:35:48 UTC (rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/PackageStatus.h       2010-04-01 
19:02:24 UTC (rev 36020)
@@ -31,7 +31,7 @@
 class PackageStatus : public BWindow {
        public:
                PackageStatus(const char *title, const char *label = NULL,
-                               const char *trailing = NULL);
+                               const char *trailing = NULL, BHandler *parent = 
NULL);
                ~PackageStatus();
                
                void MessageReceived(BMessage *msg);
@@ -46,6 +46,7 @@
                BStatusBar *fStatus;
                StopButton *fButton;
                bool fIsStopped;
+               BHandler *fParent;
 };
 
 

Modified: haiku/trunk/src/apps/packageinstaller/PackageView.cpp
===================================================================
--- haiku/trunk/src/apps/packageinstaller/PackageView.cpp       2010-04-01 
18:35:48 UTC (rev 36019)
+++ haiku/trunk/src/apps/packageinstaller/PackageView.cpp       2010-04-01 
19:02:24 UTC (rev 36020)
@@ -63,7 +63,8 @@
                //BView("package_view", B_WILL_DRAW, new 
BGroupLayout(B_HORIZONTAL)),
        fOpenPanel(new BFilePanel(B_OPEN_PANEL, NULL, NULL,
                B_DIRECTORY_NODE, false)),
-       fInfo(ref)
+       fInfo(ref),
+       fInstallProcess(this)
 {
        _InitView();
 
@@ -121,7 +122,8 @@
                // attaching the view to the window
                _GroupChanged(0);
 
-               fStatusWindow = new PackageStatus(T("Installation progress"));
+               fStatusWindow = new PackageStatus(T("Installation progress"), 
NULL, NULL,
+                               this);
 
                // Show the splash screen, if present
                BMallocIO *image = fInfo.GetSplashScreen();
@@ -133,10 +135,10 @@
                // Show the disclaimer/info text popup, if present
                BString disclaimer = fInfo.GetDisclaimer();
                if (disclaimer.Length() != 0) {
-                       PackageTextViewer *text = new 
PackageTextViewer(disclaimer.String());
+                       PackageTextViewer *text = new 
PackageTextViewer(disclaimer.String());
                        int32 selection = text->Go();
                        // The user didn't accept our disclaimer, this means we 
cannot continue.
-                       if (selection == 0) {
+                       if (selection == 0) {
                                BWindow *parent = Window();
                                if (parent && parent->Lock())
                                        parent->Quit();
@@ -153,36 +155,11 @@
                case P_MSG_INSTALL:
                {
                        fInstall->SetEnabled(false);
+                       fInstallTypes->SetEnabled(false);
+                       fDestination->SetEnabled(false);
                        fStatusWindow->Show();
-                       BAlert *notify;
-                       status_t ret = Install();
-                       if (ret == B_OK) {
-                               notify = new BAlert("installation_success",
-                                       T("The package you requested has been 
successfully installed "
-                                               "on your system."), T("OK"));
 
-                               notify->Go();
-                               fStatusWindow->Hide();
-
-                               BWindow *parent = Window();
-                               if (parent && parent->Lock())
-                                       parent->Quit();
-                       }
-                       else if (ret == B_FILE_EXISTS)
-                               notify = new BAlert("installation_aborted",
-                                       T("The installation of the package has 
been aborted."), T("OK"));
-                       else {
-                               notify = new BAlert("installation_failed", // 
TODO: Review this
-                                       T("The requested package failed to 
install on your system. This "
-                                               "might be a problem with the 
target package file. Please consult "
-                                               "this issue with the package 
distributor."), T("OK"), NULL,
-                                       NULL, B_WIDTH_AS_USUAL, 
B_WARNING_ALERT);
-                               fprintf(stderr, "Error while installing the 
package : %s\n", strerror(ret));
-                       }
-                       notify->Go();
-                       fStatusWindow->Hide();
-                       fInstall->SetEnabled(true);
-
+                       fInstallProcess.Start();
                        break;
                }
                case P_MSG_PATH_CHANGED:
@@ -204,6 +181,65 @@
                        }
                        break;
                }
+               case P_MSG_I_FINISHED:
+               {
+                       BAlert *notify = new BAlert("installation_success",
+                               T("The package you requested has been 
successfully installed "
+                                       "on your system."), T("OK"));
+
+                       notify->Go();
+                       fStatusWindow->Hide();
+                       fInstall->SetEnabled(true);
+                       fInstallTypes->SetEnabled(true);
+                       fDestination->SetEnabled(true);
+                       fInstallProcess.Stop();
+
+                       BWindow *parent = Window();
+                       if (parent && parent->Lock())
+                               parent->Quit();
+                       break;
+               }
+               case P_MSG_I_ABORT:
+               {
+                       BAlert *notify = new BAlert("installation_aborted",
+                               T("The installation of the package has been 
aborted."), T("OK"));
+                       notify->Go();
+                       fStatusWindow->Hide();
+                       fInstall->SetEnabled(true);
+                       fInstallTypes->SetEnabled(true);
+                       fDestination->SetEnabled(true);
+                       fInstallProcess.Stop();
+                       break;
+               }
+               case P_MSG_I_ERROR:
+               {
+                       BAlert *notify = new BAlert("installation_failed", // 
TODO: Review this
+                               T("The requested package failed to install on 
your system. This "
+                                       "might be a problem with the target 
package file. Please consult "
+                                       "this issue with the package 
distributor."), T("OK"), NULL,
+                               NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
+                       fprintf(stderr, "Error while installing the package\n");
+                       notify->Go();
+                       fStatusWindow->Hide();
+                       fInstall->SetEnabled(true);
+                       fInstallTypes->SetEnabled(true);
+                       fDestination->SetEnabled(true);
+                       fInstallProcess.Stop();
+                       break;
+               }
+               case P_MSG_STOP:
+               {
+                       // This message is sent to us by the PackageStatus 
window, informing
+                       // user interruptions.
+                       // We actually use this message only when a post 
installation script
+                       // is running and we want to kill it while it's still 
running
+                       fStatusWindow->Hide();
+                       fInstall->SetEnabled(true);
+                       fInstallTypes->SetEnabled(true);
+                       fDestination->SetEnabled(true);
+                       fInstallProcess.Stop();
+                       break;
+               }
                case B_REFS_RECEIVED:
                {
                        entry_ref ref;
@@ -247,122 +283,65 @@
 }
 
 
-status_t
-PackageView::Install()
+int32
+PackageView::ItemExists(PackageItem &item, BPath &path, int32 &policy)
 {
-       pkg_profile *type = static_cast<pkg_profile 
*>(fInfo.GetProfile(fCurrentType));
-       uint32 n = type->items.CountItems();
+       int32 choice = P_EXISTS_NONE;
 
-       fStatusWindow->Reset(n + 4);
+       switch (policy) {
+               case P_EXISTS_OVERWRITE:
+                       choice = P_EXISTS_OVERWRITE;
+                       break;
 
-       fStatusWindow->StageStep(1, "Preparing package");
+               case P_EXISTS_SKIP:
+                       choice = P_EXISTS_SKIP;
+                       break;
 
-       InstalledPackageInfo packageInfo(fInfo.GetName(), fInfo.GetVersion());
+               case P_EXISTS_ASK:
+               case P_EXISTS_NONE:
+               {
+                       BString alertString = T("The ");
 
-       status_t err = packageInfo.InitCheck();
-       err = B_ENTRY_NOT_FOUND;
-       if (err == B_OK) {
-               // The package is already installed, inform the user
-               BAlert *reinstall = new BAlert("reinstall",
-                       T("The given package seems to be already installed on 
your system. "
-                               "Would you like to uninstall the existing one 
and continue the "
-                               "installation?"), T("Continue"), T("Abort"));
+                       alertString << item.ItemKind() << T(" named \'") << 
path.Leaf() << "\' ";
+                       alertString << T("already exists in the given 
path.\nReplace the file with "
+                               "the one from this package or skip it?");
 
-               if (reinstall->Go() == 0) {
-                       // Uninstall the package
-                       err = packageInfo.Uninstall();
-                       if (err != B_OK) {
-                               fprintf(stderr, "Error on uninstall\n");
-                               return err;
-                       }
+                       BAlert *alert = new BAlert(T("file_exists"), 
alertString.String(),
+                               T("Replace"), T("Skip"), T("Abort"));
 
-                       err = packageInfo.SetTo(fInfo.GetName(), 
fInfo.GetVersion(), true);
-                       if (err != B_OK) {
-                               fprintf(stderr, "Error on SetTo\n");
-                               return err;
+                       choice = alert->Go();
+                       switch (choice) {
+                               case 0:
+                                       choice = P_EXISTS_OVERWRITE;
+                                       break;
+                               case 1:
+                                       choice = P_EXISTS_SKIP;
+                                       break;
+                               default:
+                                       return P_EXISTS_ABORT;
                        }
-               }
-               else {
-                       // Abort the installation
-                       return B_FILE_EXISTS;
-               }
-       }
-       else if (err == B_ENTRY_NOT_FOUND) {
-               err = packageInfo.SetTo(fInfo.GetName(), fInfo.GetVersion(), 
true);
-               if (err != B_OK) {
-                       fprintf(stderr, "Error on SetTo\n");
-                       return err;
-               }
-       }
-       else if (fStatusWindow->Stopped())
-               return B_FILE_EXISTS;
-       else {
-               fprintf(stderr, "returning on error\n");
-               return err;
-       }
 
-       fStatusWindow->StageStep(1, "Installing files and folders");
+                       if (policy == P_EXISTS_NONE) {
+                               // TODO: Maybe add 'No, but ask again' type of 
choice as well?
+                               alertString = T("Do you want to remember this 
decision for the rest of "
+                                       "this installation?\nAll existing files 
will be ");
+                               alertString << ((choice == P_EXISTS_OVERWRITE)
+                                       ? T("replaced?") : T("skipped?"));
 
-       // Install files and directories
-       PackageItem *iter;
-       ItemState state;
-       uint32 i;
-       int32 choice;
-       BString label;
+                               alert = new BAlert(T("policy_decision"), 
alertString.String(),
+                                       T("Yes"), T("No"));
 
-       packageInfo.SetName(fInfo.GetName());
-       // TODO: Here's a small problem, since right now it's not quite sure
-       //              which description is really used as such. The one 
displayed on
-       //              the installer is mostly package installation 
description, but
-       //              most people use it for describing the application in 
more detail
-       //              then in the short description.
-       //              For now, we'll use the short description if possible.
-       BString description = fInfo.GetShortDescription();
-       if (description.Length() <= 0)
-               description = fInfo.GetDescription();
-       packageInfo.SetDescription(description.String());
-       packageInfo.SetSpaceNeeded(type->space_needed);
-
-       fItemExistsPolicy = P_EXISTS_NONE;
-
-       for (i = 0; i < n; i++) {
-               state.Reset(fItemExistsPolicy); // Reset the current item state
-               iter = static_cast<PackageItem *>(type->items.ItemAt(i));
-
-               err = iter->WriteToPath(fCurrentPath.Path(), &state);
-               if (err == B_FILE_EXISTS) {
-                       // Writing to path failed because path already exists - 
ask the user
-                       // what to do and retry the writing process
-                       choice = _ItemExists(*iter, state.destination);
-                       if (choice != P_EXISTS_ABORT) {
-                               state.policy = choice;
-                               err = iter->WriteToPath(fCurrentPath.Path(), 
&state);
+                               int32 decision = alert->Go();
+                               if (decision == 0)
+                                       policy = choice;
+                               else
+                                       policy = P_EXISTS_ASK;
                        }
+                       break;
                }
-
-               if (err != B_OK) {
-                       fprintf(stderr, "Error while writing path %s\n", 
fCurrentPath.Path());
-                       return err;
-               }
-
-               if (fStatusWindow->Stopped())
-                       return B_FILE_EXISTS;
-               label = "";
-               label << (uint32)(i + 1) << " of " << (uint32)n;
-               fStatusWindow->StageStep(1, NULL, label.String());
-
-               packageInfo.AddItem(state.destination.Path());
        }
 
-       fStatusWindow->StageStep(1, "Finishing installation", "");
-
-       err = packageInfo.Save();
-       if (err != B_OK)
-               return err;
-
-       fStatusWindow->StageStep(1, "Done");
-
-       return B_OK;
+       return choice;
 }
 
 
@@ -550,68 +529,6 @@
 }
 
 
-int32
-PackageView::_ItemExists(PackageItem &item, BPath &path)
-{
-       int32 choice = P_EXISTS_NONE;
-
-       switch (fItemExistsPolicy) {
-               case P_EXISTS_OVERWRITE:
-                       choice = P_EXISTS_OVERWRITE;
-                       break;
-
-               case P_EXISTS_SKIP:
-                       choice = P_EXISTS_SKIP;
-                       break;
-
-               case P_EXISTS_ASK:
-               case P_EXISTS_NONE:
-               {
-                       BString alertString = T("The ");
-
-                       alertString << item.ItemKind() << T(" named \'") << 
path.Leaf() << "\' ";
-                       alertString << T("already exists in the given 
path.\nReplace the file with "
-                               "the one from this package or skip it?");
-

[... truncated: 96 lines follow ...]

Other related posts:

  • » [haiku-commits] r36020 - haiku/trunk/src/apps/packageinstaller - korli