[haiku-commits] BRANCH jessicah-github.postinstall-scripts [f3f6fa85f6e3] src/servers/package

  • From: jessicah-github.postinstall-scripts <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 14 Jun 2015 08:31:46 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/jessicah-github/postinstall-scripts'
old head: 0000000000000000000000000000000000000000
new head: f3f6fa85f6e3f55306052bab620db6a5f240f78b
overview: https://github.com/jessicah/haiku/compare/f3f6fa85f6e3

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

f3f6fa85f6e3: package_daemon: save post-install scripts to run after reboot

* Saves paths of post-install scripts to run into the
administrative/queued-packages file.
* Upon reboot, post-install scripts listed in the
queued-packages file are run, and then the queued-packages
file is automatically removed.
* This should solve the issue of post-install scripts not being
run when the package is installed/upgraded along with the
system packages, as was experienced with the latest upgrade
to the bash package.

[ Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx> ]

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

Commit: f3f6fa85f6e3f55306052bab620db6a5f240f78b
Author: Jessica Hamilton <jessica.l.hamilton@xxxxxxxxx>
Date: Sun Jun 14 05:13:53 2015 UTC

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

6 files changed, 188 insertions(+), 2 deletions(-)
src/servers/package/CommitTransactionHandler.cpp | 82 ++++++++++++++++-
src/servers/package/CommitTransactionHandler.h | 8 ++
src/servers/package/Constants.cpp | 3 +
src/servers/package/Constants.h | 2 +
src/servers/package/Volume.cpp | 94 +++++++++++++++++++-
src/servers/package/Volume.h | 1 +

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

diff --git a/src/servers/package/CommitTransactionHandler.cpp
b/src/servers/package/CommitTransactionHandler.cpp
index 7336c05..62f97d6 100644
--- a/src/servers/package/CommitTransactionHandler.cpp
+++ b/src/servers/package/CommitTransactionHandler.cpp
@@ -397,7 +397,7 @@ CommitTransactionHandler::_ApplyChanges()
// run post-installation scripts
_RunPostInstallScripts();
} else {
- // TODO: Make sure the post-install scripts are run on next
boot!
+ _QueuePostInstallScripts();
}

// removed packages have been deleted, new packages shall not be deleted
@@ -1352,6 +1352,86 @@ CommitTransactionHandler::_RunPostInstallScript(Package*
package,


void
+CommitTransactionHandler::_QueuePostInstallScripts()
+{
+ // write the temporary queued scripts file
+ BEntry queuedScriptsEntry;
+ _WriteQueuedScriptsFile(RelativePath(kAdminDirectoryName),
+ kTemporaryQueuedScriptsFileName, queuedScriptsEntry);
+
+ /// rename the temporary activation file to the final file
+ status_t error = queuedScriptsEntry.Rename(kQueuedScriptsFileName,
true);
+ if (error != B_OK) {
+ throw Exception(B_TRANSACTION_FAILED_TO_MOVE_FILE)
+ .SetPath1(_GetPath(
+ FSUtils::Entry(queuedScriptsEntry),
+ queuedScriptsEntry.Name()))
+ .SetPath2(kQueuedScriptsFileName)
+ .SetSystemError(error);
+ }
+}
+
+
+void
+CommitTransactionHandler::_WriteQueuedScriptsFile(
+ const RelativePath& directoryPath, const char* fileName,
+ BEntry& _entry)
+{
+ BString queuedScriptsContent;
+ for (PackageSet::iterator it = fAddedPackages.begin();
+ it != fAddedPackages.end(); ++it) {
+ Package* package = *it;
+ _CreateQueuedScriptsContent(package, queuedScriptsContent);
+ }
+
+ status_t error = _WriteTextFile(directoryPath, fileName,
+ queuedScriptsContent, _entry);
+ if (error != B_OK) {
+ BString filePath = directoryPath.ToString() << '/' << fileName;
+ throw Exception(B_TRANSACTION_FAILED_TO_ACCESS_ENTRY)
+ .SetPath1(_GetPath(
+ FSUtils::Entry(fVolume->PackagesDirectoryRef(),
filePath),
+ filePath))
+ .SetSystemError(error);
+ }
+}
+
+
+void
+CommitTransactionHandler::_CreateQueuedScriptsContent(Package* package,
+ BString& _content)
+{
+ BString queuedScriptsContent;
+ BDirectory rootDir(&fVolume->RootDirectoryRef());
+ const BStringList& scripts = package->Info().PostInstallScripts();
+ for (int32 i = 0; i < scripts.CountStrings(); i++) {
+ BPath scriptPath(&rootDir, scripts.StringAt(i));
+ status_t error = scriptPath.InitCheck();
+ if (error != B_OK) {
+
ERROR("Volume::CommitTransactionHandler::_RunPostInstallScript(): "
+ "failed get path of post-installation script
\"%s\" of package "
+ "%s: %s\n", scriptPath.Path(),
package->FileName().String(),
+ strerror(error));
+ _AddIssue(TransactionIssueBuilder(
+
BTransactionIssue::B_POST_INSTALL_SCRIPT_NOT_FOUND)
+ .SetPath1(scripts.StringAt(i))
+ .SetSystemError(error));
+ continue;
+ }
+
+ int32 length = queuedScriptsContent.Length();
+ queuedScriptsContent << scriptPath.Path() << '\n';
+ if (queuedScriptsContent.Length()
+ < length + scripts.StringAt(i).Length() + 1) {
+ throw Exception(B_TRANSACTION_NO_MEMORY);
+ }
+ }
+
+ _content = queuedScriptsContent;
+}
+
+
+void
CommitTransactionHandler::_ExtractPackageContent(Package* package,
const BStringList& contentPaths, BDirectory& targetDirectory,
BDirectory& _extractedFilesDirectory)
diff --git a/src/servers/package/CommitTransactionHandler.h
b/src/servers/package/CommitTransactionHandler.h
index bf6a4b8..2deffb6 100644
--- a/src/servers/package/CommitTransactionHandler.h
+++ b/src/servers/package/CommitTransactionHandler.h
@@ -100,6 +100,14 @@ private:
void
_RunPostInstallScript(Package* package,
const
BString& script);

+ void
_QueuePostInstallScripts();
+ void _WriteQueuedScriptsFile(
+ const
RelativePath& directoryPath,
+ const
char* fileName,
+ BEntry&
_entry);
+ void
_CreateQueuedScriptsContent(Package* package,
+
BString& _content);
+
void
_ExtractPackageContent(Package* package,
const
BStringList& contentPaths,

BDirectory& targetDirectory,
diff --git a/src/servers/package/Constants.cpp
b/src/servers/package/Constants.cpp
index ed0f7c5..0b65e53 100644
--- a/src/servers/package/Constants.cpp
+++ b/src/servers/package/Constants.cpp
@@ -14,5 +14,8 @@ const char* const kAdminDirectoryName =
PACKAGES_DIRECTORY_ADMIN_DIRECTORY;
const char* const kActivationFileName = PACKAGES_DIRECTORY_ACTIVATION_FILE;
const char* const kTemporaryActivationFileName
= PACKAGES_DIRECTORY_ACTIVATION_FILE ".tmp";
+const char* const kQueuedScriptsFileName = "queued-scripts";
+const char* const kTemporaryQueuedScriptsFileName
+ = "queued-scripts.tmp";
const char* const kWritableFilesDirectoryName = "writable-files";
const char* const kPackageFileAttribute = "SYS:PACKAGE";
diff --git a/src/servers/package/Constants.h b/src/servers/package/Constants.h
index d3c8686..5ab487c 100644
--- a/src/servers/package/Constants.h
+++ b/src/servers/package/Constants.h
@@ -13,6 +13,8 @@ extern const char* const kPackageFileNameExtension;
extern const char* const kAdminDirectoryName;
extern const char* const kActivationFileName;
extern const char* const kTemporaryActivationFileName;
+extern const char* const kQueuedScriptsFileName;
+extern const char* const kTemporaryQueuedScriptsFileName;
extern const char* const kWritableFilesDirectoryName;
extern const char* const kPackageFileAttribute;

diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp
index 38453dd..dce66b6 100644
--- a/src/servers/package/Volume.cpp
+++ b/src/servers/package/Volume.cpp
@@ -329,6 +329,8 @@ Volume::InitPackages(Listener* listener)
if (error != B_OK)
RETURN_ERROR(error);

+ _RunQueuedScripts();
+
// create the admin directory, if it doesn't exist yet
BDirectory packagesDirectory;
if (packagesDirectory.SetTo(&PackagesDirectoryRef()) == B_OK) {
@@ -993,7 +995,7 @@ Volume::_InitLatestStateFromActivatedPackages()
off_t size;
error = file.GetSize(&size);
if (error != B_OK) {
- ERROR("Failed to packages activation file size: %s\n",
+ ERROR("Failed to get packages activation file size: %s\n",
strerror(error));
RETURN_ERROR(error);
}
@@ -1130,6 +1132,96 @@ Volume::_GetActivePackages(int fd)
}


+void
+Volume::_RunQueuedScripts()
+{
+ // try reading the queued post-install scripts file
+ NotOwningEntryRef entryRef(PackagesDirectoryRef(),
kQueuedScriptsFileName);
+ BFile file;
+ status_t error = file.SetTo(&entryRef, B_READ_ONLY);
+ if (error != B_OK)
+ return;
+
+ // read the whole file into memory to simplify things
+ off_t size;
+ error = file.GetSize(&size);
+ if (error != B_OK) {
+ ERROR("Failed to get queued post-install scripts file size:
%s\n",
+ strerror(error));
+ return;
+ }
+
+ if (size > (off_t)kMaxActivationFileSize) {
+ ERROR("The queued post-install scripts file is too big.\n");
+ return;
+ }
+
+ char* fileContent = (char*)malloc(size + 1);
+ if (fileContent == NULL)
+ return;
+ MemoryDeleter fileContentDeleter(fileContent);
+
+ ssize_t bytesRead = file.Read(fileContent, size);
+ if (bytesRead < 0) {
+ ERROR("Failed to read queued post-install scripts file: %s\n",
+ strerror(bytesRead));
+ return;
+ }
+
+ if (bytesRead != size) {
+ ERROR("Failed to read whole queued post-install scripts
file.\n");
+ return;
+ }
+
+ // null-terminate to simplify parsing
+ fileContent[size] = '\0';
+
+ AutoLocker<BLocker> locker(fLock);
+
+ // parse the file and run the queued post-install scripts
+ const char* scriptName = fileContent;
+ char* const fileContentEnd = fileContent + size;
+ while (scriptName < fileContentEnd) {
+ char* scriptNameEnd = strchr(scriptName, '\n');
+ if (scriptNameEnd == NULL)
+ scriptNameEnd = fileContentEnd;
+
+ // skip empty lines
+ if (scriptName == scriptNameEnd) {
+ scriptName++;
+ continue;
+ }
+ *scriptNameEnd = '\0';
+
+ if (scriptNameEnd - scriptName >= B_FILE_NAME_LENGTH) {
+ INFORM("Invalid queued post-install scripts file
content.\n");
+ continue;
+ }
+
+ BPath scriptPath(scriptName);
+ status_t error = scriptPath.InitCheck();
+ if (error != B_OK) {
+ INFORM("Failed to get path of post-installation script
\"%s\"\n",
+ strerror(error));
+ continue;
+ }
+
+ errno = 0;
+ int result = system(scriptPath.Path());
+ if (result != 0) {
+ INFORM("Running post-installation script \"%s\" "
+ "failed: %d (errno: %s)\n", scriptName, errno,
strerror(errno));
+ continue;
+ }
+
+ scriptName = scriptNameEnd + 1;
+ }
+
+ // remove the queued post-installation script file
+ BEntry(&entryRef).Remove();
+}
+
+
bool
Volume::_CheckActivePackagesMatchLatestState(
PackageFSGetPackageInfosRequest* request)
diff --git a/src/servers/package/Volume.h b/src/servers/package/Volume.h
index f083860..164a3a6 100644
--- a/src/servers/package/Volume.h
+++ b/src/servers/package/Volume.h
@@ -160,6 +160,7 @@ private:
status_t _InitLatestState();
status_t
_InitLatestStateFromActivatedPackages();
status_t _GetActivePackages(int
fd);
+ void _RunQueuedScripts();
bool
_CheckActivePackagesMatchLatestState(

PackageFSGetPackageInfosRequest* request);
void
_SetLatestState(VolumeState* state,


Other related posts:

  • » [haiku-commits] BRANCH jessicah-github.postinstall-scripts [f3f6fa85f6e3] src/servers/package - jessicah-github . postinstall-scripts