package_daemon: queue post-install scripts to run after reboot
* Creates symlinks to the post-install scripts into the administrative/queued-scripts directory. * Upon reboot, post-install scripts in the queued-scripts are run, and then the symlinks to the scripts removed. * This solves the issue of post-install scripts not being run when the package is installed/upgraded along with the system packages, as experienced with the latest upgrade to the bash package.
This commit is contained in:
parent
5b57e337e9
commit
6f19d31cd4
@ -15,6 +15,7 @@
|
||||
|
||||
#include <File.h>
|
||||
#include <Path.h>
|
||||
#include <SymLink.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <CopyEngine.h>
|
||||
@ -397,7 +398,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
|
||||
@ -1351,6 +1352,52 @@ CommitTransactionHandler::_RunPostInstallScript(Package* package,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CommitTransactionHandler::_QueuePostInstallScripts()
|
||||
{
|
||||
BDirectory adminDirectory;
|
||||
status_t error = _OpenPackagesSubDirectory(
|
||||
RelativePath(kAdminDirectoryName), true, adminDirectory);
|
||||
if (error != B_OK) {
|
||||
ERROR("Failed to open administrative directory: %s\n", strerror(error));
|
||||
return;
|
||||
}
|
||||
|
||||
BDirectory scriptsDirectory;
|
||||
error = scriptsDirectory.SetTo(&adminDirectory, kQueuedScriptsDirectoryName);
|
||||
if (error == B_ENTRY_NOT_FOUND)
|
||||
error = adminDirectory.CreateDirectory(kQueuedScriptsDirectoryName, &scriptsDirectory);
|
||||
if (error != B_OK) {
|
||||
ERROR("Failed to open queued scripts directory: %s\n", strerror(error));
|
||||
return;
|
||||
}
|
||||
|
||||
BDirectory rootDir(&fVolume->RootDirectoryRef());
|
||||
for (PackageSet::iterator it = fAddedPackages.begin();
|
||||
it != fAddedPackages.end(); ++it) {
|
||||
Package* package = *it;
|
||||
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("Can't find script: %s\n", scripts.StringAt(i).String());
|
||||
continue;
|
||||
}
|
||||
|
||||
// symlink to the script
|
||||
BSymLink scriptLink;
|
||||
scriptsDirectory.CreateSymLink(scriptPath.Leaf(),
|
||||
scriptPath.Path(), &scriptLink);
|
||||
if (scriptLink.InitCheck() != B_OK) {
|
||||
ERROR("Creating symlink failed: %s\n", strerror(scriptLink.InitCheck()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CommitTransactionHandler::_ExtractPackageContent(Package* package,
|
||||
const BStringList& contentPaths, BDirectory& targetDirectory,
|
||||
|
@ -100,6 +100,8 @@ private:
|
||||
void _RunPostInstallScript(Package* package,
|
||||
const BString& script);
|
||||
|
||||
void _QueuePostInstallScripts();
|
||||
|
||||
void _ExtractPackageContent(Package* package,
|
||||
const BStringList& contentPaths,
|
||||
BDirectory& targetDirectory,
|
||||
|
@ -16,3 +16,4 @@ const char* const kTemporaryActivationFileName
|
||||
= PACKAGES_DIRECTORY_ACTIVATION_FILE ".tmp";
|
||||
const char* const kWritableFilesDirectoryName = "writable-files";
|
||||
const char* const kPackageFileAttribute = "SYS:PACKAGE";
|
||||
const char* const kQueuedScriptsDirectoryName = "queued-scripts";
|
||||
|
@ -15,6 +15,7 @@ extern const char* const kActivationFileName;
|
||||
extern const char* const kTemporaryActivationFileName;
|
||||
extern const char* const kWritableFilesDirectoryName;
|
||||
extern const char* const kPackageFileAttribute;
|
||||
extern const char* const kQueuedScriptsDirectoryName;
|
||||
|
||||
static const bigtime_t kHandleNodeMonitorEvents = 'nmon';
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <Roster.h>
|
||||
#include <SymLink.h>
|
||||
|
||||
#include <package/CommitTransactionResult.h>
|
||||
#include <package/PackageRoster.h>
|
||||
@ -1130,6 +1131,49 @@ Volume::_GetActivePackages(int fd)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Volume::_RunQueuedScripts()
|
||||
{
|
||||
BDirectory adminDirectory;
|
||||
status_t error = _OpenPackagesSubDirectory(
|
||||
RelativePath(kAdminDirectoryName), false, adminDirectory);
|
||||
if (error != B_OK)
|
||||
return;
|
||||
|
||||
BDirectory scriptsDirectory;
|
||||
error = scriptsDirectory.SetTo(&adminDirectory, kQueuedScriptsDirectoryName);
|
||||
if (error != B_OK)
|
||||
return;
|
||||
|
||||
// enumerate all the symlinks in the queued scripts directory
|
||||
BEntry scriptEntry;
|
||||
while (scriptsDirectory.GetNextEntry(&scriptEntry, false) == B_OK) {
|
||||
BPath scriptPath;
|
||||
scriptEntry.GetPath(&scriptPath);
|
||||
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", scriptPath.Leaf(), errno, strerror(errno));
|
||||
}
|
||||
|
||||
// remove the symlink, now that we've run the post-installation script
|
||||
error = scriptEntry.Remove();
|
||||
if (error != B_OK) {
|
||||
INFORM("removing queued post-install script failed \"%s\"\n",
|
||||
strerror(error));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Volume::_CheckActivePackagesMatchLatestState(
|
||||
PackageFSGetPackageInfosRequest* request)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user