[haiku-commits] haiku: hrev46882 - src/apps/packageinstaller

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 16 Feb 2014 23:39:58 +0100 (CET)

hrev46882 adds 1 changeset to branch 'master'
old head: 4407020ba450ea3f7d02db93ac9e5b2c4e22d25e
new head: 3f5014ec86d210bd1d63f14c7640d1c68b7d8684
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=3f5014e+%5E4407020

----------------------------------------------------------------------------

3f5014e: PackageInstaller: Run install scripts in the correct directory
  
   * From debugging with the Gobe and Moho installer, scripts define which
     folder to run them from. The PackageInstaller is supposed to run the script
     in that working directory. The parser seems to have the correct folder in
     "installPath" when adding the script as PackageItem, but that code is 
rather
     horrible. I've changed it so PackageScript items also set the path, use
     InitPath() to obtain the final working directory and set it before running
     the script.
   * Both Moho and Gobe create the Deskbar link from that script, the folder
     is rewritten in the script via ReplaceAll().
   * Correctly running the script makes a bug visible: Dynamically added files
     in the install location by these scripts are not removed when uninstalling
     the package. When re-installing a package, it is first uninstalled and this
     currently gives an error for both Moho and Gobe, since they create some
     links in these scripts which never worked before. To install again, the
     install folder needs to be deleted manually.
   * Some cleanup along the way... sorry.

                                      [ Stephan Aßmus <superstippi@xxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev46882
Commit:      3f5014ec86d210bd1d63f14c7640d1c68b7d8684
URL:         http://cgit.haiku-os.org/haiku/commit/?id=3f5014e
Author:      Stephan Aßmus <superstippi@xxxxxx>
Date:        Sun Feb 16 22:32:01 2014 UTC

----------------------------------------------------------------------------

5 files changed, 103 insertions(+), 62 deletions(-)
src/apps/packageinstaller/PackageInfo.cpp    |  7 +-
src/apps/packageinstaller/PackageInstall.cpp |  5 +-
src/apps/packageinstaller/PackageInstall.h   | 37 +++++-----
src/apps/packageinstaller/PackageItem.cpp    | 92 +++++++++++++++---------
src/apps/packageinstaller/PackageItem.h      | 24 ++++---

----------------------------------------------------------------------------

diff --git a/src/apps/packageinstaller/PackageInfo.cpp 
b/src/apps/packageinstaller/PackageInfo.cpp
index c141002..85668be 100644
--- a/src/apps/packageinstaller/PackageInfo.cpp
+++ b/src/apps/packageinstaller/PackageInfo.cpp
@@ -1024,8 +1024,11 @@ PackageInfo::Parse()
                                                localType, ctime, mtime, mode, 
offset, size);
                                }
                        } else if (element == P_SCRIPT) {
-                               fScripts.AddItem(new 
PackageScript(fPackageFile, offset, size,
-                                       originalSize));
+                               parser_debug("Adding the script %s!\n",
+                                       nameString.String());
+
+                               fScripts.AddItem(new PackageScript(fPackageFile,
+                                       installDirectory, 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
diff --git a/src/apps/packageinstaller/PackageInstall.cpp 
b/src/apps/packageinstaller/PackageInstall.cpp
index bbcb2d8..8028598 100644
--- a/src/apps/packageinstaller/PackageInstall.cpp
+++ b/src/apps/packageinstaller/PackageInstall.cpp
@@ -202,7 +202,7 @@ PackageInstall::_Install()
 
        fItemExistsPolicy = P_EXISTS_NONE;
 
-       const char *installPath = fParent->CurrentPath()->Path();
+       const char* installPath = fParent->CurrentPath()->Path();
        for (uint32 i = 0; i < n; i++) {
                ItemState state(fItemExistsPolicy);
                PackageItem* item = 
static_cast<PackageItem*>(type->items.ItemAt(i));
@@ -245,10 +245,11 @@ PackageInstall::_Install()
                fCurrentScriptLocker.Lock();
                fCurrentScript = script;
 
-               status_t status = script->DoInstall();
+               status_t status = script->DoInstall(installPath);
                if (status != B_OK) {
                        fprintf(stderr, "Error while running script: %s\n",
                                strerror(status));
+                       fCurrentScriptLocker.Unlock();
                        return P_MSG_I_ERROR;
                }
                fCurrentScriptLocker.Unlock();
diff --git a/src/apps/packageinstaller/PackageInstall.h 
b/src/apps/packageinstaller/PackageInstall.h
index e2dea2a..b956467 100644
--- a/src/apps/packageinstaller/PackageInstall.h
+++ b/src/apps/packageinstaller/PackageInstall.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Haiku, Inc.
+ * Copyright (c) 2010-2014, Haiku, Inc.
  * Distributed under the terms of the MIT license.
  *
  * Author:
@@ -8,8 +8,10 @@
 #ifndef PACKAGE_INSTALL_H
 #define PACKAGE_INSTALL_H
 
+
 #include <Locker.h>
 
+
 class PackageView;
 class PackageScript;
 
@@ -19,25 +21,28 @@ enum {
        P_MSG_I_ERROR = 'pier'
 };
 
+
 class PackageInstall {
-       public:
-               PackageInstall(PackageView *parent);
-               ~PackageInstall();
+public:
+                                                               
PackageInstall(PackageView* parent);
+                                                               
~PackageInstall();
 
-               status_t Start();
-               void Stop();
-               void Install();
+                       status_t                        Start();
+                       void                            Stop();
+                       void                            Install();
 
-       private:
-               uint32 _Install();
+private:
+                       uint32                          _Install();
 
-               PackageView *fParent;
-               thread_id fThreadId;
-               BLocker fIdLocker;
+private:
+                       PackageView*            fParent;
+                       thread_id                       fThreadId;
+                       BLocker                         fIdLocker;
 
-               PackageScript *fCurrentScript;
-               BLocker fCurrentScriptLocker; // XXX: will we need this?
-               int32 fItemExistsPolicy;
+                       PackageScript*          fCurrentScript;
+                       BLocker                         fCurrentScriptLocker;
+                       int32                           fItemExistsPolicy;
 };
 
-#endif
+
+#endif // PACKAGE_INSTALL_H
diff --git a/src/apps/packageinstaller/PackageItem.cpp 
b/src/apps/packageinstaller/PackageItem.cpp
index d5e9e03..8456ac8 100644
--- a/src/apps/packageinstaller/PackageItem.cpp
+++ b/src/apps/packageinstaller/PackageItem.cpp
@@ -130,10 +130,8 @@ inflate_file_to_file(BFile *in, uint64 in_size, BFile 
*out, uint64 out_size)
                                (void)inflateEnd(&stream);
                                return B_ERROR;
                        }
-               }
-               while (stream.avail_out == 0);
-       }
-       while (bytes_read != in_size);
+               } while (stream.avail_out == 0);
+       } while (bytes_read != in_size);
 
        (void)inflateEnd(&stream);
 
@@ -144,7 +142,7 @@ inflate_file_to_file(BFile *in, uint64 in_size, BFile *out, 
uint64 out_size)
 // #pragma mark - PackageItem
 
 
-PackageItem::PackageItem(BFile *parent, const BString &path, uint8 type,
+PackageItem::PackageItem(BFile* parent, const BString& path, uint8 type,
        uint32 ctime, uint32 mtime, uint64 offset, uint64 size)
 {
        SetTo(parent, path, type, ctime, mtime, offset, size);
@@ -157,7 +155,7 @@ PackageItem::~PackageItem()
 
 
 void
-PackageItem::SetTo(BFile *parent, const BString &path, uint8 type, uint32 
ctime,
+PackageItem::SetTo(BFile* parent, const BString& path, uint8 type, uint32 
ctime,
        uint32 mtime, uint64 offset, uint64 size)
 {
        fPackage = parent;
@@ -172,7 +170,7 @@ PackageItem::SetTo(BFile *parent, const BString &path, 
uint8 type, uint32 ctime,
 
 
 status_t
-PackageItem::InitPath(const char *path, BPath *destination)
+PackageItem::InitPath(const char* path, BPath* destination)
 {
        status_t ret = B_OK;
 
@@ -300,10 +298,10 @@ PackageItem::HandleAttributes(BPath *destination, BNode 
*node,
 
 
 status_t
-PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
-       uint32 *nameSize, uint32 *attrType, uint8 **attrData, uint64 *dataSize,
-       uint8 **temp, uint64 *tempSize, uint64 *attrCSize, uint64 *attrOSize,
-       bool *attrStarted, bool *done)
+PackageItem::ParseAttribute(uint8* buffer, BNode* node, char** attrName,
+       uint32* nameSize, uint32* attrType, uint8** attrData, uint64* dataSize,
+       uint8** temp, uint64* tempSize, uint64* attrCSize, uint64* attrOSize,
+       bool* attrStarted, bool* done)
 {
        status_t ret = B_OK;
        uint32 length;
@@ -415,7 +413,7 @@ PackageItem::ParseAttribute(uint8 *buffer, BNode *node, 
char **attrName,
 
 
 status_t
-PackageItem::SkipAttribute(uint8 *buffer, bool *attrStarted, bool *done)
+PackageItem::SkipAttribute(uint8* buffer, bool* attrStarted, bool* done)
 {
        status_t ret = B_OK;
        uint32 length;
@@ -477,7 +475,7 @@ PackageItem::SkipAttribute(uint8 *buffer, bool 
*attrStarted, bool *done)
 
 
 status_t
-PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
+PackageItem::ParseData(uint8* buffer, BFile* file, uint64 originalSize,
        bool *done)
 {
        status_t ret = B_OK;
@@ -513,12 +511,10 @@ PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 
originalSize,
                        return ret;
                }
                parser_debug(" File data inflation complete!\n");
-       }
-       else if (!memcmp(buffer, padding, 7)) {
+       } else if (!memcmp(buffer, padding, 7)) {
                *done = true;
                return ret;
-       }
-       else {
+       } else {
                parser_debug("_ParseData unknown tag\n");
                ret = B_ERROR;
        }
@@ -530,10 +526,10 @@ PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 
originalSize,
 // #pragma mark - PackageScript
 
 
-PackageScript::PackageScript(BFile *parent, uint64 offset, uint64 size,
-               uint64 originalSize)
+PackageScript::PackageScript(BFile* parent, const BString& path, uint64 offset,
+               uint64 size, uint64 originalSize)
        :
-       PackageItem(parent, NULL, 0, 0, 0, offset, size),
+       PackageItem(parent, path, P_INSTALL_PATH, 0, 0, offset, size),
        fOriginalSize(originalSize),
        fThreadId(-1)
 {
@@ -541,7 +537,7 @@ PackageScript::PackageScript(BFile *parent, uint64 offset, 
uint64 size,
 
 
 status_t
-PackageScript::DoInstall(const char *path, ItemState *state)
+PackageScript::DoInstall(const char* path, ItemState* state)
 {
        status_t ret = B_OK;
        parser_debug("Script: DoInstall() called!\n");
@@ -579,8 +575,29 @@ PackageScript::DoInstall(const char *path, ItemState 
*state)
                                        break;
 
                                case P_DATA:
-                                       ret = _ParseScript(buffer, 
fOriginalSize, &done);
+                               {
+                                       BString script;
+                                       ret = _ParseScript(buffer, 
fOriginalSize, script, &done);
+                                       if (ret == B_OK) {
+                                               // Rewrite Deskbar entry 
targets. NOTE: It would
+                                               // also work to 
Replace("/config/be", "/config...")
+                                               // but it would be less save. 
For example, an app
+                                               // could have a folder named 
"config/be..." inside
+                                               // its installation folder.
+                                               script.ReplaceAll(
+                                                       "~/config/be",
+                                                       
"~/config/settings/deskbar/menu");
+                                               script.ReplaceAll(
+                                                       "/boot/home/config/be",
+                                                       
"/boot/home/config/settings/deskbar/menu");
+
+                                               BPath workingDirectory;
+                                               ret = InitPath(path, 
&workingDirectory);
+                                               if (ret == B_OK)
+                                                       ret = 
_RunScript(workingDirectory.Path(), script);
+                                       }
                                        break;
+                               }
 
                                default:
                                        return B_ERROR;
@@ -604,7 +621,8 @@ PackageScript::ItemKind()
 
 
 status_t
-PackageScript::_ParseScript(uint8 *buffer, uint64 originalSize, bool *done)
+PackageScript::_ParseScript(uint8 *buffer, uint64 originalSize,
+       BString& _script, bool *done)
 {
        status_t ret = B_OK;
 
@@ -640,7 +658,7 @@ PackageScript::_ParseScript(uint8 *buffer, uint64 
originalSize, bool *done)
                        return B_ERROR;
                }
 
-               uint8 *script = new uint8[original];
+               uint8* script = new uint8[original];
                ret = inflate_data(temp, compressed, script, original);
                if (ret != B_OK) {
                        parser_debug(" inflate_data failed\n");
@@ -649,7 +667,8 @@ PackageScript::_ParseScript(uint8 *buffer, uint64 
originalSize, bool *done)
                        return ret;
                }
 
-               ret = _RunScript(script, originalSize);
+               _script.SetTo((char*)script, originalSize);
+
                delete[] script;
                delete[] temp;
                parser_debug(" Script data inflation complete!\n");
@@ -666,18 +685,23 @@ PackageScript::_ParseScript(uint8 *buffer, uint64 
originalSize, bool *done)
 
 
 status_t
-PackageScript::_RunScript(uint8 *script, uint32 len)
+PackageScript::_RunScript(const char* workingDirectory, const BString& script)
 {
        // 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
 
+       // Change current working directory to install path
+       char oldWorkingDirectory[B_PATH_NAME_LENGTH];
+       getcwd(oldWorkingDirectory, sizeof(oldWorkingDirectory));
+       chdir(workingDirectory);
+
        // 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 */
@@ -714,12 +738,16 @@ PackageScript::_RunScript(uint8 *script, uint32 len)
        resume_thread(fThreadId);
 
        // Write the script
-       if (write(in, script, len) != (int32)len || write(in, "\nexit\n", 6) != 
6) {
+       if (write(in, script.String(), script.Length() - 1) != script.Length() 
- 1
+               || write(in, "\nexit\n", 6) != 6) {
                parser_debug("Writing script failed\n");
                kill_thread(fThreadId);
                return B_ERROR;
        }
 
+       // Restore current working directory
+       chdir(oldWorkingDirectory);
+
        return B_OK;
 }
 
@@ -727,7 +755,7 @@ PackageScript::_RunScript(uint8 *script, uint32 len)
 // #pragma mark - PackageDirectory
 
 
-PackageDirectory::PackageDirectory(BFile *parent, const BString &path,
+PackageDirectory::PackageDirectory(BFile* parent, const BString& path,
                uint8 type, uint32 ctime, uint32 mtime, uint64 offset, uint64 
size)
        :
        PackageItem(parent, path, type, ctime, mtime, offset, size)
@@ -736,7 +764,7 @@ PackageDirectory::PackageDirectory(BFile *parent, const 
BString &path,
 
 
 status_t
-PackageDirectory::DoInstall(const char *path, ItemState *state)
+PackageDirectory::DoInstall(const char* path, ItemState* state)
 {
        BPath &destination = state->destination;
        status_t ret;
@@ -798,12 +826,12 @@ PackageFile::PackageFile(BFile *parent, const BString 
&path, uint8 type,
 
 
 status_t
-PackageFile::DoInstall(const char *path, ItemState *state)
+PackageFile::DoInstall(const char* path, ItemState* state)
 {
        if (state == NULL)
                return B_ERROR;
 
-       BPath &destination = state->destination;
+       BPath& destination = state->destination;
        status_t ret = B_OK;
        parser_debug("File: %s DoInstall() called!\n", fPath.String());
 
diff --git a/src/apps/packageinstaller/PackageItem.h 
b/src/apps/packageinstaller/PackageItem.h
index bb22e67..9e66b15 100644
--- a/src/apps/packageinstaller/PackageItem.h
+++ b/src/apps/packageinstaller/PackageItem.h
@@ -85,7 +85,7 @@ public:
                                                                uint64 offset = 
0, uint64 size = 0);
        virtual const uint32    ItemKind() {return P_NO_KIND;};
 
-       protected:
+protected:
                        status_t                InitPath(const char* path, 
BPath* destination);
                        status_t                HandleAttributes(BPath* 
destination, BNode* node,
                                                                const char* 
header);
@@ -97,11 +97,12 @@ public:
                                                                uint64* 
tempSize, uint64* attrCSize,
                                                                uint64* 
attrOSize, bool* attrStarted,
                                                                bool* done);
-                       status_t                SkipAttribute(uint8 *buffer, 
bool *attrStarted, 
-                                                               bool *done);
+                       status_t                SkipAttribute(uint8* buffer, 
bool* attrStarted, 
+                                                               bool* done);
                        status_t                ParseData(uint8* buffer, BFile* 
file,
                                                                uint64 
originalSize, bool* done);
 
+protected:
                        BString                 fPath;
                        uint64                  fOffset;
                        uint64                  fSize;
@@ -120,15 +121,16 @@ public:
                                                                uint64 offset = 
0, uint64 size = 0);
 
        virtual status_t                DoInstall(const char* path = NULL,
-                                                               ItemState 
*state = NULL);
+                                                               ItemState* 
state = NULL);
        virtual const uint32    ItemKind();
 };
 
 
 class PackageScript : public PackageItem {
 public:
-                                                       PackageScript(BFile* 
parent, uint64 offset = 0, 
-                                                               uint64 size = 
0, uint64 originalSize = 0);
+                                                       PackageScript(BFile* 
parent, const BString& path,
+                                                               uint64 offset = 
0,  uint64 size = 0,
+                                                               uint64 
originalSize = 0);
 
        virtual status_t                DoInstall(const char* path = NULL,
                                                                ItemState 
*state = NULL);
@@ -138,10 +140,12 @@ public:
                        void                    SetThreadId(thread_id id) { 
fThreadId = id; }
 
 private:
-                       status_t                _ParseScript(uint8 *buffer, 
uint64 originalSize, 
-                                                               bool *done);
-                       status_t                _RunScript(uint8 *script, 
uint32 len);
+                       status_t                _ParseScript(uint8* buffer, 
uint64 originalSize, 
+                                                               BString& 
script, bool* done);
+                       status_t                _RunScript(const char* 
workingDirectory,
+                                                               const BString& 
script);
 
+private:
                        uint64                  fOriginalSize;
                        thread_id               fThreadId;
 };
@@ -156,7 +160,7 @@ public:
                                                                const BString& 
signature, uint32 mode);
 
        virtual status_t                DoInstall(const char* path = NULL,
-                                                               ItemState 
*state = NULL);
+                                                               ItemState* 
state = NULL);
        virtual const uint32    ItemKind();
 
 private:


Other related posts: