diff --git a/src/apps/packageinstaller/PackageInfo.cpp b/src/apps/packageinstaller/PackageInfo.cpp index c1410029bf..85668be81c 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 bbcb2d8a1d..80285987d5 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(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 e2dea2ab6d..b9564676c0 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 + 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 d5e9e0371c..8456ac8084 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 // 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 bb22e67a08..9e66b15e23 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: