From: Klaus Kaempf Date: Fri, 11 Apr 2008 16:04:15 +0000 (+0000) Subject: - Implement update scripts installed by packages. After every X-Git-Tag: BASE-SuSE-Linux-11_0-Branch~272 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=353a4a565321553b3046e299fd88e4f6af03dfae;p=platform%2Fupstream%2Flibzypp.git - Implement update scripts installed by packages. After every package install /var/adm/update-scripts is scanned for the first file starting with "-.-", which is then executed. --- diff --git a/package/libzypp.changes b/package/libzypp.changes index 0bffd1d..119c57b 100644 --- a/package/libzypp.changes +++ b/package/libzypp.changes @@ -1,4 +1,13 @@ ------------------------------------------------------------------- +Fri Apr 11 18:02:14 CEST 2008 - kkaempf@suse.de + +- Implement update scripts installed by packages. After every + package install /var/adm/update-scripts is scanned for the first + file starting with "-.-", which is then + executed. +- revision 9547 + +------------------------------------------------------------------- Fri Apr 11 14:43:05 CEST 2008 - ma@suse.de - Fix SolvIterMixin to avioid multiple visits of the same Selectable. diff --git a/zypp/target/TargetImpl.cc b/zypp/target/TargetImpl.cc index 043f8ad..eab43bc 100644 --- a/zypp/target/TargetImpl.cc +++ b/zypp/target/TargetImpl.cc @@ -15,6 +15,9 @@ #include #include +#include +#include + #include "zypp/base/Logger.h" #include "zypp/base/Exception.h" #include "zypp/base/Iterator.h" @@ -65,6 +68,96 @@ namespace zypp /////////////////////////////////////////////////////////////////// namespace { ///////////////////////////////////////////////////////////////// + + // Execute file (passed as pi_t) as script + // report against report_r + // + void ExecuteScript( const Pathname & pn_r, + callback::SendReport * report) + { + PathInfo pi( pn_r ); + if ( ! pi.isFile() ) + { + std::ostringstream err; + err << "Script is not a file: " << pi.fileType() << " " << pn_r; + if (report) + (*report)->problem( err.str() ); + ZYPP_THROW(Exception(err.str())); + } + + filesystem::chmod( pn_r, S_IRUSR|S_IWUSR|S_IXUSR ); // "rwx------" + ExternalProgram prog( pn_r.asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true ); + + for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() ) + { + // hmm, this depends on a ScriptResolvableReport :-( + if ( report + && ! (*report)->progress( ScriptResolvableReport::OUTPUT, output ) ) + { + WAR << "User request to abort script." << endl; + prog.kill(); // the rest is handled by exit code evaluation. + } + } + + int exitCode = prog.close(); + if ( exitCode != 0 ) + { + std::ostringstream err; + err << "Script failed with exit code " << exitCode; + if (report) + (*report)->problem( err.str() ); + ZYPP_THROW(Exception(err.str())); + } + return; + } + + // Check for (and run) update script + // path: directory where to look + // name,version,release: Script name must match 'name-version.release-' prefix + // + void RunUpdateScript(Pathname path, std::string name, std::string version, std::string release) + { + // open the scripts directory + + DIR *dir = opendir(path.asString().c_str()); + if (!dir) + { + WAR << "Cannot access directory " << path << endl; + return; + } + + // compute the name-version.release- prefix + std::string prefix = name + "-" + version + "." + release + "-"; + size_t pfx_size = prefix.length(); + if (pfx_size > 255) + { + ERR << "Prefix size (" << pfx_size << ") larger than supported (255)" << endl; + pfx_size = 255; + } + + // scan directory for match + const char *found = NULL; + struct dirent *dentry; + while ((dentry = readdir(dir))) + { + if (strncmp( dentry->d_name, prefix.c_str(), pfx_size) == 0) { + found = dentry->d_name; + break; + } + } + if (found) + { + ExecuteScript( Pathname(found), NULL ); + } + closedir(dir); + return; + } + + // Fetch and execute remote script + // access_r: remote access handle + // script_r: script (resolvable) handle + // do_r: true for 'do', false for 'undo' + // void ExecuteScriptHelper( repo::RepoMediaAccess & access_r, Script::constPtr script_r, bool do_r ) @@ -91,35 +184,9 @@ namespace zypp (do_r ? ScriptResolvableReport::DO : ScriptResolvableReport::UNDO ) ); - PathInfo pi( localfile ); - if ( ! pi.isFile() ) - { - std::ostringstream err; - err << "Script is not a file: " << pi.fileType() << " " << localfile; - report->problem( err.str() ); - ZYPP_THROW(Exception(err.str())); - } - - filesystem::chmod( localfile, S_IRUSR|S_IWUSR|S_IXUSR ); // "rwx------" - ExternalProgram prog( localfile->asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true ); - for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() ) - { - if ( ! report->progress( ScriptResolvableReport::OUTPUT, output ) ) - { - WAR << "User request to abort script." << endl; - prog.kill(); // the rest is handled by exit code evaluation. - } - } - - int exitCode = prog.close(); - if ( exitCode != 0 ) - { - std::ostringstream err; - err << "Script failed with exit code " << exitCode; - report->problem( err.str() ); - ZYPP_THROW(Exception(err.str())); - } + ExecuteScript( localfile, &report ); report->finish(); + return; } @@ -558,6 +625,8 @@ namespace zypp if ( success && !policy_r.dryRun() ) { it->status().resetTransact( ResStatus::USER ); + // check for and run an update script + RunUpdateScript(ZConfig::instance().updateScriptsPath(), p->name(), p->edition().version(), p->edition().release()); } progress.disconnect(); }