home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / modules / OSRPkg.ycp < prev    next >
Text File  |  2006-11-29  |  26KB  |  1,041 lines

  1. /**
  2.  * File:    OSRPkg.ycp
  3.  * Module:    repair
  4.  * Summary:    Packages check
  5.  * Authors:    Johannes Buchhold <jbuch@suse.de>
  6.  *
  7.  * $Id: OSRPkg.ycp 33121 2006-09-26 12:43:41Z jsuchome $
  8.  *
  9.  * Provide osr mode information.
  10.  */
  11.  
  12. {
  13.     module "OSRPkg";
  14.  
  15.     textdomain "repair";
  16.  
  17.     import "DefaultDesktop";
  18.     import "Kernel";
  19.     import "Mode";
  20.     import "Report";
  21.     import "Wizard";
  22.     import "Popup";
  23.     import "Stage";
  24.  
  25.     import "OSRCommon";
  26.     import "OSRSystem";
  27.     import "OSRExecute";
  28.     import "OSRLogFile";
  29.     import "OSRPopup";
  30.     import "OSRPkgUI";
  31.     import "OSRPkgVerify";
  32.  
  33.     /**
  34.      * Package database files
  35.      */
  36.     list<string> rpm3_db_files = [
  37.                  "/var/lib/rpm/conflictsindex.rpm",
  38.                  "/var/lib/rpm/fileindex.rpm",
  39.                  "/var/lib/rpm/groupindex.rpm",
  40.                  "/var/lib/rpm/nameindex.rpm",
  41.                  "/var/lib/rpm/packages.rpm",
  42.                  "/var/lib/rpm/providesindex.rpm",
  43.                  "/var/lib/rpm/requiredby.rpm",
  44.                  "/var/lib/rpm/triggerindex.rpm"
  45.     ];
  46.  
  47.     /**
  48.      * Package database files (version >=4)
  49.      */
  50.     list<string> rpm4_db_files = [
  51.     "/var/lib/rpm/Basenames",
  52.     "/var/lib/rpm/Conflictname",
  53.     "/var/lib/rpm/Dirnames",
  54.     "/var/lib/rpm/Filemd5s",
  55.     "/var/lib/rpm/Group",
  56.     "/var/lib/rpm/Installtid",
  57.     "/var/lib/rpm/Name",
  58.     "/var/lib/rpm/Packages",
  59.     "/var/lib/rpm/Providename",
  60.     "/var/lib/rpm/Provideversion",
  61.     "/var/lib/rpm/Pubkeys",
  62.     "/var/lib/rpm/Requirename",
  63.     "/var/lib/rpm/Requireversion",
  64.     "/var/lib/rpm/Sha1header",
  65.     "/var/lib/rpm/Sigmd5",
  66.     "/var/lib/rpm/Triggername"
  67.     ];
  68.  
  69.     /**
  70.      * Current package database files
  71.      */
  72.     list<string> rpm_db_files    = rpm3_db_files;
  73.  
  74.     /**
  75.      * if a backup (YaST) of the package  database was
  76.      * created.
  77.      * Save rpm?_db_files[X] -> rpm?_db_files[X].old
  78.      */
  79.     boolean backup_created = false;
  80.  
  81.     /**
  82.      * Mount point where the target system is mounted.
  83.      */
  84.     global string root_mountpoint = "";
  85.  
  86.     /**
  87.      * Help text to show errors.
  88.      */
  89.     global string help_text       = "";
  90.  
  91.     /**
  92.      * Error text.
  93.      */
  94.     global string error_text       = "";
  95.  
  96.     /**
  97.      * Dialog description for the install missing or damaged packages.
  98.      */
  99.     global list install_missing_dialog_data = [];
  100.  
  101.     /**
  102.      * Missing packages database files.
  103.      */
  104.     global list <string> not_found_files  = [];
  105.  
  106.     /**
  107.      * Not installed base packages or damaged packages.
  108.      */
  109.     global list <string> missing_packages = [];
  110.  
  111.     /**
  112.      * All new installed packages.
  113.      */
  114.     list <string> reinstalled_packages    = [];
  115.  
  116.     /**
  117.      * This will be local when converted to a Module::
  118.      * Has Pkg::TargetInit run?
  119.      */
  120.     boolean target_initialized = false;
  121.  
  122.     /**
  123.      * Before first opening pkg database, we need to close it preventively
  124.      * (because it could be opened with a different root path).
  125.      * This variable says, if it is first time now.
  126.      */
  127.     boolean first_time_openpkg = true;
  128.  
  129.     /**
  130.      * This will be local when converted to a Module::
  131.      * Has Pkg::SourceStartCache run?
  132.      */
  133.     boolean source_initialized = false;
  134.  
  135.     boolean package_db_repaired = false;
  136.  
  137.  
  138.     list<string> architecture_packages = [];
  139.  
  140.     // list of packages in minimal selection (read it just after pkg target is
  141.     // initialized to avoid bug #30423)
  142.     list<string> minimal_selection = [];
  143.  
  144.     // general help text about package database
  145.     string default_package_help  = _("
  146. <p>The package database administers all
  147. information of the installed software packages.
  148. The most common way to add a new program or library
  149. to a Linux system is to install a new package.
  150. In doing so, the install routine copies all files of the
  151. package to the target and registers the package in
  152. the package database.</P>
  153. ");
  154.  
  155.     // general help text about damaged package database
  156.     string damaged_package_help = _("
  157. <P>If the package database is damaged, installing
  158. and removing packages or updating the system
  159. is not possible.</P>
  160. ");
  161.  
  162.     /**
  163.      * Reset the module settings.
  164.      */
  165.     global define void Reset()``{
  166.  
  167.     not_found_files        = [];
  168.     error_text        = "";
  169.     help_text        = "";
  170.     root_mountpoint        = "";
  171.     missing_packages    = [];
  172.  
  173.     architecture_packages    = [];
  174.     package_db_repaired    = false;
  175.     reinstalled_packages    = [];
  176.     install_missing_dialog_data = [];
  177.  
  178.     if (target_initialized )
  179.     {
  180.         target_initialized = ! Pkg::TargetFinish ();
  181.     }
  182.     // don't reset source_initialized
  183.     // don't reset reinstalled_packages
  184.     OSRPkgUI::Reset();
  185.     OSRPkgVerify::Reset();
  186.     }
  187.  
  188.     /**
  189.      * Constructor.
  190.      */
  191.     global define void OSRPkg()``{
  192.     Reset();
  193.     }
  194.  
  195.     define list<string> get_minimal_selection () ``{
  196.  
  197.     if (Mode::test ())
  198.     {
  199.         return [ "test" ];
  200.     }
  201.     if (minimal_selection == [] || minimal_selection == nil)
  202.     {
  203.         DefaultDesktop::SetDesktop ("text");
  204.         list<string> pats    = DefaultDesktop::PatternsToSelect ();
  205.  
  206.         foreach (string p, pats, {
  207.         list<map> descrs = Pkg::ResolvableDependencies (p,`pattern, "");
  208.         foreach (map descr, descrs, {
  209.             foreach (map dep, (list<map>)descr["dependencies"]:[], {
  210.             if (dep["res_kind"]:"" == "package" &&
  211.                 dep["dep_kind"]:"" == "requires")
  212.             {
  213.                 minimal_selection    = add (minimal_selection,
  214.                 dep["name"]:"");
  215.             }
  216.             });
  217.         });
  218.         });
  219.     }
  220.     return minimal_selection;
  221.     }
  222.  
  223.     /**
  224.      * Open the package database.
  225.      */
  226.     global define boolean OpenPkg( string root )``{
  227.  
  228.     if (Mode::test ()) return true;
  229.  
  230.     import "Packages";
  231.  
  232.     y2milestone("Open pkg database with target system  -%1-", root );
  233.     if (root != "" && root != nil ) root_mountpoint = root;
  234.  
  235.     // open the package source
  236.     if (! Stage::initial () )
  237.     {
  238.         source_initialized = source_initialized ||
  239.         Pkg::SourceStartCache (true) != [];
  240.     }
  241.     else
  242.     {
  243.         if (! source_initialized  )
  244.         {
  245.         y2milestone("Calling package module");
  246.  
  247.         //change root for the Package module call
  248.         OSRSystem::SetOrgRoot();
  249.  
  250.         Packages::Init (true);
  251.  
  252.         architecture_packages = Packages::ComputeSystemPackageList();
  253.         y2milestone("Add architecture packages %1",
  254.             architecture_packages );
  255.  
  256.         //reset root environment
  257.         OSRSystem::ChangeRoot(root);
  258.  
  259.         source_initialized = true;
  260.         }
  261.     }
  262.  
  263.     // open target system for Pkg access
  264.     if (!target_initialized)
  265.     {
  266.         if (first_time_openpkg)
  267.         {
  268.         y2milestone ("first time initializig -> finish target before");
  269.         Pkg::TargetFinish ();
  270.         first_time_openpkg = false;
  271.         }
  272.         target_initialized = Pkg::TargetInit ( root, false);
  273.         get_minimal_selection ();
  274.     }
  275.  
  276.     // something failed
  277.     if (! target_initialized || ! source_initialized )
  278.     {
  279.         y2error("Opening the package database failed. ");
  280.         y2error("Target is initialised: %1", target_initialized);
  281.         y2error("Source is initialised: %1", source_initialized);
  282.  
  283.         // build help and error text for following repair dialog
  284.         help_text  = default_package_help + damaged_package_help;
  285.         // error popup
  286.         error_text = _("
  287. Cannot open the package database.
  288. Try rebuilding the package
  289. database or reverting to a backup.
  290. ");
  291.     }
  292.     return target_initialized && source_initialized;
  293.     }
  294.  
  295.     /**
  296.      * Check if target product is the same as the source (bug #45306)
  297.      * @return true if product are the same
  298.      */
  299.     global define boolean CheckProductVersions () {
  300.  
  301.     if (Mode::test ()) return true;
  302.  
  303.     integer source_id    = 1;
  304.  
  305.     // TODO we could use Packages::theSources
  306.     list curr_sources    = Pkg::SourceGetCurrent (true);
  307.  
  308.     source_id        = curr_sources[0]:source_id;
  309.     map source_product    = Pkg::SourceProduct (source_id);
  310.     list all_products    = Pkg::TargetProducts ();
  311.     map target_product    = all_products[0]:$[];
  312.  
  313.     y2debug ("source product: %1", source_product);
  314.     y2debug  ("target_product: %1", target_product);
  315.  
  316.     if (source_product["product"]:"" != target_product["product"]:"")
  317.     {
  318.         y2error("target product (%1) is different from source product (%2)",
  319.         target_product["product"]:"", source_product["product"]:"");
  320.         y2warning ("source product: %1", source_product);
  321.         y2warning ("target_product: %1", target_product);
  322.         return false;
  323.     }
  324.     return true;
  325.     }
  326.  
  327.     /**
  328.      * Return false if db files are missing.
  329.      * Save missing files in the list not_found_files.
  330.      */
  331.     global define boolean CheckDB (string root )``{
  332.  
  333.     if (root != "" && root != nil ) root_mountpoint = root;
  334.     not_found_files = [];
  335.  
  336.     // Now the version of pkg databse is checked
  337.     rpm_db_files = rpm3_db_files;
  338.     if (OSRExecute::Command (.local.bash, sformat("/usr/bin/test -f %1",
  339.         root_mountpoint + "/var/lib/rpm/Packages")))
  340.         rpm_db_files = rpm4_db_files;
  341.  
  342.     // check all database files
  343.     foreach(string file, rpm_db_files, ``{
  344.         if (!OSRExecute::Command (.local.bash,
  345.             sformat("/usr/bin/test -f %1", root_mountpoint + file)))
  346.         not_found_files = add(not_found_files, file);
  347.     });
  348.  
  349.     // if files are missing
  350.     if (size( not_found_files ) > 0 )
  351.     {
  352.         help_text  = default_package_help + damaged_package_help;
  353.         // error message: files (%1) not found
  354.         error_text = sformat(_("
  355. The package database was checked.
  356. The following files that belong 
  357. to the package database were not
  358. found.
  359.  
  360. %1
  361. "),mergestring(not_found_files,"\n"));
  362.  
  363.     }
  364.     else
  365.     {
  366.         // try to open the database.
  367.         // if open fails OpenPkg set help and error text
  368.         return OpenPkg( root_mountpoint );
  369.     }
  370.     return size( not_found_files ) == 0;
  371.     }
  372.  
  373.     /**
  374.      * Make a backup of the package database
  375.      * files.
  376.      */
  377.     define boolean backup_package_db()``{
  378.  
  379.     // only create one package at the
  380.     // first call of backup_package_db
  381.     if (backup_created ) return true;
  382.     list<boolean> ret = [];
  383.  
  384.     foreach(string file, rpm_db_files, ``{
  385.         string f = root_mountpoint  + file;
  386.         if (!contains (not_found_files , file))
  387.         ret = add (ret, OSRExecute::Command (.local.bash,
  388.             sformat("/bin/cp %1 %1.old",f)));
  389.     });
  390.  
  391.     // if not error was found
  392.     if (size(filter(boolean r, ret, ``( r != true ))) == 0 )
  393.     {
  394.         backup_created = true;
  395.     }
  396.     return backup_created;
  397.     }
  398.  
  399.     /**
  400.      * Revert the YaST backup of the package database.
  401.      */
  402.     define boolean revert_packages_backup()``{
  403.     if (! backup_created ) return false;
  404.  
  405.     list<boolean> ret = [];
  406.     foreach (string file, rpm_db_files, ``{
  407.         string f = root_mountpoint  + file;
  408.  
  409.         //if orginal file exists
  410.         if (! contains( not_found_files , file))
  411.         {
  412.         ret = add( ret , OSRExecute::Command(.local.bash, sformat("/bin/cp %1.old %1",f)));
  413.         }
  414.     });
  415.  
  416.     // if not error was occurred
  417.     if (size(filter(boolean r, ret, ``( r != true ))) == 0 )
  418.     {
  419.         Report::Message(_("\nReverting to the backup was successful.
  420. "));
  421.         return true;
  422.     }
  423.     else
  424.     {
  425.         // error popup
  426.         Report::Error(_("
  427. Reverting to the backup was not
  428. successful. Select another
  429. backup or try to rebuild
  430. the package database.
  431. "));
  432.         return false;
  433.     }
  434.     };
  435.  
  436.     /**
  437.      * Rebuild the package database.
  438.      */
  439.     define boolean rebuild_package_db( boolean show_message )``{
  440.  
  441.     boolean ret = true;
  442.  
  443.     UI::OpenDialog (`VBox (
  444.         `VSpacing(1),
  445.         // wait popup label
  446.         `Label(_("Rebuilding the package database...")),
  447.         `VSpacing(1)
  448.     ));
  449.  
  450.     if (backup_created || size(not_found_files ) > 0 )
  451.     {
  452.         // some package database files are missing
  453.         if ((! Mode::test ())  && size( not_found_files ) > 0 )
  454.         {
  455.         ret = WFM::Execute (.local.bash,
  456.             sformat("/bin/rpm --root %1 --initdb",root_mountpoint))== 0;
  457.         }
  458.  
  459.         // rebuild package database
  460.         ret = ret && WFM::Execute (.local.bash,
  461.         sformat("/bin/rpm --root %1 --rebuilddb",root_mountpoint)) == 0;
  462.  
  463.         package_db_repaired = true;
  464.  
  465.         UI::CloseDialog();
  466.         if (show_message )
  467.         {
  468.         if (ret )
  469.         {
  470.             Report::Message(_("
  471. Successfully rebuilt the 
  472. package database.
  473. "));
  474.         }
  475.         else
  476.         {
  477.             Report::Error(_("
  478. Could not rebuild the package
  479. database. Revert to a backup of
  480. the package database.
  481. "));
  482.         }
  483.         }
  484.     }
  485.     else {
  486.         UI::CloseDialog();
  487.         ret = false;
  488.     }
  489.     return ret;
  490.     }
  491.  
  492.  
  493.     /**
  494.      * Revert a backup of the package database
  495.      * from /var/adm/backup/rpmdb.
  496.      */
  497.     define boolean revert_daily_backup()``{
  498.  
  499.     if (!backup_created && size(not_found_files) == 0 )
  500.         return false;
  501.  
  502.     boolean ret        = false;
  503.     string file_path    = "packages.rpm";
  504.     string backup_path    = (string)
  505.         SCR::Read(.sysconfig.backup.RPMDB_BACKUP_DIR);
  506.  
  507.     if (backup_path == "" || backup_path == nil )
  508.     {
  509.         y2error ("No sysconfig backup path found. Use default /var/adm/backup/rpmdb");
  510.         backup_path = "/var/adm/backup/rpmdb";
  511.     }
  512.  
  513.     list<string> files = (list<string>) SCR::Read(.target.dir, backup_path);
  514.     files = filter(string f, files, ``(substring(f, 0, size(file_path)) == file_path ));
  515.     y2milestone("Found files for backup: %1", files );
  516.  
  517.     //packages.rpm-20021105.gz
  518.     list<string> dates = maplist(string f, files, ``(substring(f, size(file_path)+1 , 8)));
  519.     dates        = sort(string f, string ff, dates, ``( f > ff ));
  520.     dates      = maplist(string f, dates, ``(sformat("%1.%2.%3", substring( f,0,4),
  521.                              substring(f,4,2),
  522.                              substring(f,6,2))));
  523.     list<list> items = maplist(string f, dates, ``([f,""]));
  524.  
  525.     // no backup was found, %1 is path
  526.     if (size(items ) == 0 )
  527.     {
  528.         Report::Error(sformat(_("
  529. No package database backup files
  530. found. Normally, a cron job creates
  531. daily backups of the package database and
  532. stores the backups in the directory
  533. %1. However, no backup files could
  534. be found in this directory.
  535. Try another repair method.
  536. "),backup_path));
  537.         return false;
  538.     }
  539.  
  540.     string selected  = OSRPopup::RadioButtonGroupText(_("Backup to Use"),
  541.                            _("
  542. Several backups of the 
  543. package database were found.
  544. Select the date (YYYY/MM/DD)
  545. of the backup to which 
  546. to revert.\n"), items, dates[0]:"", "", false);
  547.  
  548.     y2milestone("The selected item %1", selected);
  549.  
  550.     if (selected != "" )
  551.     {
  552.         selected = find(string f, files, ``(issubstring(f, mergestring(splitstring(selected, "."),"") )));
  553.         selected = backup_path + "/"+selected;
  554.         if (OSRExecute::Command(.local.bash, sformat("/usr/bin/test -f %2/%1", selected, root_mountpoint )))
  555.         {
  556.         if (! Mode::test () && WFM::Execute(.local.bash, sformat("/bin/gunzip < %2/%1  \
  557. > %2/var/lib/rpm/packages.rpm", selected ,root_mountpoint )) == 0   )
  558.         {
  559.             if (rebuild_package_db(false) ) 
  560.             {
  561.             Report::Message(_("
  562. Reverting to the backup of the package
  563. database was successful.
  564. "));
  565.             ret = true;
  566.             }
  567.         }
  568.         else
  569.         {
  570.             Report::Error(_("
  571. Reverting to the backup of the package
  572. database was not successful.
  573. "));
  574.         }
  575.         package_db_repaired = true;
  576.         }
  577.         else
  578.         {
  579.         //should never happpen
  580.         y2error("Selected package update file not found");
  581.         }
  582.     }
  583.     return ret;
  584.     }
  585.  
  586.     /**
  587.      * Repair or initialise a damaged package
  588.      * damaged. Call CheckDB before.
  589.      */
  590.     global define symbol RepairDB()``{
  591.  
  592.     string repair_header = _("Repair Package Database");
  593.  
  594.     if (! backup_package_db())
  595.     {
  596.         y2error("Creating backup of package db was not successful");
  597.         if (size(not_found_files ) == 0 ) return `error;
  598.     }
  599.  
  600.     term r_options = `VBox (
  601.         `Left (
  602.         // popup headline
  603.         `Label(_("Repair Method"))),
  604.         `VSpacing(0.5),
  605.         `Left (
  606.         // radio button label
  607.         `RadioButton(`id(`rebuild), _("Rebuild Package Database"),true)
  608.         ),
  609.         `Left (
  610.         // radio button label
  611.         `RadioButton(`id(`daily), _("Revert to Daily Backup"), false)
  612.         )
  613.     );
  614.  
  615.     term last_entry = `RadioButton(`id(`revert ));
  616.  
  617.     if (! package_db_repaired )
  618.         last_entry = add( last_entry , `opt(`disabled ));
  619.  
  620.     last_entry = add( last_entry,  _("Revert to Orginal Package Database (saved by YaST)"));
  621.     last_entry = add( last_entry, false);
  622.     r_options  = add( r_options, last_entry);
  623.  
  624.     if (! OSRPopup::OpenMainRepairDialog( repair_header , error_text, r_options ))
  625.     {
  626.         y2error("Could not open main dialog for repairing package database.");
  627.         return `error;
  628.     }
  629.  
  630.     symbol ret = `ok;
  631.     repeat
  632.     {
  633.         ret             = (symbol)UI::UserInput();
  634.         symbol selected = (symbol)UI::QueryWidget(`id(`rb), `CurrentButton);
  635.  
  636.         if (ret == `help )
  637.         {
  638.         Popup::LongText( OSRPopup::help_headline , `RichText( help_text ), 50, 20);
  639.         }
  640.         else if (ret == `ok )
  641.         {
  642.         UI::CloseDialog();
  643.  
  644.         boolean rret = false;
  645.         // execute selected repair method
  646.         if (selected == `rebuild)
  647.             rret = rebuild_package_db(true);
  648.         else if (selected == `daily)
  649.             rret = revert_daily_backup();
  650.         else if (selected == `revert)
  651.             rret = revert_packages_backup();
  652.  
  653.         if (!rret)
  654.         {
  655.             if (!OSRPopup::OpenMainRepairDialog (repair_header,
  656.             error_text, r_options))
  657.             {
  658.             y2error("Could not open main dialog");
  659.             return `error;
  660.             }
  661.             ret = `again;
  662.         }
  663.         }
  664.     } until( ret == `cancel || ret == `abort || ret == `ok );
  665.  
  666.     if (ret != `ok )  UI::CloseDialog();
  667.  
  668.     return ret;
  669.     }
  670.  
  671.     /**
  672.      * Return all packages which should be verified
  673.      */
  674.     define list<string> get_verify_packages(string what ) ``{
  675.  
  676.     list<string>  ret = [];
  677.  
  678.     // return all packages
  679.     if (what == "all" )
  680.     {
  681.         ret = Pkg::GetPackages(`installed, true);
  682.     }
  683.     // return base packages only
  684.     else if (what == "base")
  685.     {
  686.         list<string> minimal = get_minimal_selection ();
  687.         list<string> special = [];
  688.  
  689.         minimal    = filter (string p, minimal, ``( Pkg::IsAvailable(p)));
  690.         ret        = (list<string>) union (minimal, special) ;
  691.     }
  692.     else
  693.     {
  694.         y2error("Parameter what not valid. Only all or base are allowed.");
  695.         ret =  nil;
  696.     }
  697.     if (ret != nil )
  698.     {
  699.         ret = (list<string>) union (ret, architecture_packages );
  700.     }
  701.     return ret;
  702.     }
  703.  
  704.  
  705.     /**
  706.      * Check if all minimal required packages are installed.
  707.      */
  708.     global define boolean CheckMinimum(string root )``{
  709.  
  710.     // reset missing package
  711.     missing_packages = [];
  712.  
  713.     if (root != "" && root != nil ) root_mountpoint = root;
  714.  
  715.     if (! OpenPkg( root_mountpoint ))
  716.     {
  717.         y2error("Opening the package database failed. Checking minimal package selection is not possible.");
  718.         y2error("Please call CheckDB before calling CheckMinimum");
  719.         return false;
  720.     }
  721.  
  722.     list<string> installed_packages = Pkg::GetPackages(`installed, true);
  723.     list<string> minimal_packages   = get_verify_packages( "base" );
  724.  
  725.     missing_packages = filter(string pkg_name, minimal_packages, ``( ! contains(installed_packages, pkg_name )));
  726.  
  727.     // fix Pkg bug. GetPackages get not the reinstalled_packages!!
  728.     // (seems to be fixed in 9.0 ...)
  729.     missing_packages = filter(string pkg_name, missing_packages, ``( ! contains( reinstalled_packages, pkg_name)));
  730.  
  731.  
  732.     boolean ret      = size(missing_packages) == 0;
  733.  
  734.     if (! ret )
  735.     {
  736.         y2error ("These packages belonging to the minimal selection were not found: %1", missing_packages);
  737.         // set information for repair dialog
  738.         install_missing_dialog_data = [
  739.         // headline
  740.         _("Missing Packages"),
  741.         // check for package minimum summary, 1st part (table follows)
  742.         _("
  743. The following packages are
  744. not installed."),
  745.  
  746.         // check for package minimum summary, last part (below table)
  747.         _("
  748. The listed packages belong to the minimal
  749. package selection. Installing these
  750. packages is recommended.  Press
  751. Repair  to install all selected 
  752. packages in the list.
  753. "),
  754.         // check for package minimum help text 1/2
  755.         _("
  756. <P>&product; needs at least some packages for
  757. basic system functionality. Without these
  758. packages, the system is not executable.</P>
  759. ") +
  760.  
  761.         // check for package minimum help text 2/2, %1 is tool name
  762.         sformat (_("<P>%1 checks if all required packages for a
  763. minimal system are installed. If
  764. some packages are missing, %1 offers to
  765. install the missing packages.</P>
  766. "), OSRCommon::tool_name),
  767.         // table headline (package list follows)
  768.         _("&Missing Packages to Install"),
  769.         []
  770.         ];
  771.     }
  772.     return ret;
  773.  
  774.     };
  775.  
  776.     /**
  777.      * Verify all specified packages.
  778.      * @param root The mount point where the target system is mounted.
  779.      * @param what "all" or "base" packages
  780.      * @param expert_mode Show the verify protocol too
  781.      * @param reset Clear missing_packages before start verifying.
  782.      */
  783.     global define symbol VerifyPackages(string root, string what , boolean expert_mode, boolean reset )``{
  784.  
  785.     if (Mode::test ())
  786.         return `next;
  787.  
  788.     if (root != "" && root != nil )
  789.     {
  790.         root_mountpoint = root;
  791.     }
  792.  
  793.     if (reset )
  794.     {
  795.         missing_packages = [];
  796.     }
  797.  
  798.     // open package database
  799.     if (! OpenPkg(root_mountpoint) )
  800.     {
  801.         y2error("Opening the package database failed. Verify package not possible");
  802.         return `error;
  803.     }
  804.  
  805.     if (! CheckProductVersions ())
  806.     {
  807.         return `different_products;
  808.     }
  809.  
  810.     list<string> check_packages = toset(get_verify_packages(what));
  811.  
  812.     if (check_packages == nil ||  size(check_packages) == 0 )
  813.     {
  814.         y2error("No packages to verify found. Stop verify and return error.");
  815.         return `error;
  816.     }
  817.  
  818.     // dialog headline
  819.     string headline = ( what != "all" ) ? _("Verifying Base Packages") :
  820.     // dialog headline
  821.     _("Verifying All Installed Packages");
  822.  
  823.     // open dialog
  824.     if (! OSRPkgUI::OpenVerifyDialog (size(check_packages), headline , expert_mode) )
  825.     {
  826.         y2error("Verify Dialog can not be opened");
  827.         return `error;
  828.     }
  829.  
  830.     symbol ret  = `again;
  831.     string rret = "";
  832.     repeat
  833.     {
  834.         // verify all selected packages
  835.         foreach(string p, check_packages, ``{
  836.  
  837.         if (ret != `abort )
  838.         {
  839.             rret = (string) UI::PollInput();
  840.  
  841.             if (! (rret == "" || rret == nil ))
  842.             {
  843.             ret = OSRPkgUI::EvalUserInput(rret );
  844.             if (ret == `abort ) return `abort;
  845.             if (ret == `pause )
  846.             {
  847.                 repeat
  848.                 {
  849.                 y2milestone("Starting pause loop");
  850.                 rret = (string) UI::UserInput();
  851.                 ret  = OSRPkgUI::EvalUserInput (rret);
  852.                 if (ret == `abort )
  853.                     return `abort;
  854.                 } until (ret == `continue || ret == `abort ||
  855.                      ret == `cancel);
  856.             }
  857.             }
  858.  
  859.             if (! OSRPkgVerify::PackageVerified (p) &&
  860.             ret != `abort && ret != `cancel)
  861.             {
  862.             boolean ver = OSRPkgVerify::Verify (p, root_mountpoint);
  863.             OSRPkgUI::AddPackageSummary (p);
  864.             if (!ver )
  865.             {
  866.                 missing_packages = add (missing_packages, p );
  867.             }
  868.             }
  869.         }
  870.         });
  871.         OSRPkgUI::Finish();
  872.  
  873.         // finish verified wait for user input in expert mode.
  874.         if (ret != `abort && OSRPkgUI::expert_mode )
  875.         {
  876.         check_packages = [];
  877.         rret = (string) UI::UserInput();
  878.         y2milestone(" user input get signal %1", rret);
  879.         if (ret != nil  )  // e.g.: get a `cancel or `abort
  880.         {
  881.             ret = OSRPkgUI::EvalUserInput( rret );
  882.         }
  883.         else {
  884.             ret = `next;
  885.         }
  886.  
  887.         // all packages verified.
  888.         if (ret == `abort || ret == `cancel ) ret = `next;
  889.         }
  890.         // close dialog in normal mode
  891.         else {
  892.         ret = `next;
  893.         }
  894.     } until ( ret == `next || ret == `abort || ret == `cancel );
  895.     UI::CloseDialog();
  896.  
  897.     missing_packages = OSRPkgVerify::not_successful_verified;
  898.     OSRPkgVerify::WriteVerifiedPackages( check_packages, false);
  899.  
  900.     if (size( missing_packages ) > 0)
  901.     {
  902.         // button label
  903.         string protocol_label = _("Show Log");
  904.         OSRPkgUI::expert_mode = true;
  905.         install_missing_dialog_data = [
  906.         // dialog headline
  907.         _("Unverified Packages"),
  908.         // package verification summary, 1st part (table follows)
  909.         _("
  910. Verified the installed software
  911. and found problems in the following
  912. packages.
  913. "),
  914.         // package verification summary, last part
  915.         _("
  916. These packages probably differ from their
  917. originally installed versions. Check
  918. the packages to reinstall and start
  919. the reinstallation process by pressing
  920. Repair.
  921. "),
  922.  
  923.         // package verification summary, help text (%1 is button label)
  924.         sformat (_("
  925. <p>All installed packages have been verified. Some
  926. of these packages contain errors. For details,
  927. see the log of the verification process.
  928. To open the log, press <b>%1</b>.</p>
  929. "), protocol_label) +
  930.  
  931.         // package verification summary 2/3
  932. _("<p>There, see if files of the package are
  933. missing or the data of the package in the package
  934. database differs from the installed files of the
  935. package.</P>")    +
  936.  
  937.         // package verification summary 3/3
  938. _("<p>Sometimes, verification of the package could 
  939. report errors even if the package is correctly
  940. installed and works fine. That is why you should
  941. reinstall only the packages that do not work properly.</p>
  942. "),
  943.         // table headline (package list follows)
  944.         _("Packages with Problems"),
  945.         [ [
  946.             `Right(`PushButton( `id(`protocol), protocol_label )),
  947.             `protocol, OSRPkgUI::ProtocolDialog
  948.         ] ]
  949.          ];
  950.     }
  951.     return ret;
  952.     }
  953.  
  954.     /**
  955.      * Install selected Packages. The packages are damaged or not install.
  956.      * Call CheckMinimum or VerifyPackages before.
  957.      */
  958.     global define symbol InstallMissing(boolean use_dialog )``{
  959.  
  960.     symbol ret = `ok;
  961.  
  962.     if (size(missing_packages) > 0 )
  963.     {
  964.         list<list> item_list = [];
  965.         foreach(string item, missing_packages, ``{
  966.         item_list = add( item_list, [item, false]);
  967.         });
  968.         item_list = OSRPkgUI::update_missing_packages (item_list, true);
  969.  
  970.         if (use_dialog )
  971.         {
  972.         missing_packages = OSRPopup::MultiSelectionBox (
  973.             install_missing_dialog_data[0]:"",
  974.             install_missing_dialog_data[1]:"",
  975.             install_missing_dialog_data[2]:"",
  976.             install_missing_dialog_data[3]:"",
  977.             install_missing_dialog_data[4]:"",
  978.             item_list,
  979.             install_missing_dialog_data[5]:[]
  980.         );
  981.         }
  982.  
  983.        if (missing_packages == [] )
  984.        {
  985.            y2milestone("No packages to install. User skiped reinstall.");
  986.            ret = `cancel;
  987.        }
  988.        else
  989.        {
  990.         y2milestone("Install missing or damaged packages %1", missing_packages );
  991.         if (OpenPkg(root_mountpoint ))
  992.         {
  993.             boolean ok = true;
  994.  
  995.             foreach (string p, missing_packages , ``{
  996.             ok = ok && Pkg::PkgInstall (p);
  997.             if (! ok )
  998.             {
  999.                 y2error("Change the state to install for package %1 failed", p );
  1000.             }
  1001.             });
  1002.  
  1003.             ok = ok && Pkg::PkgSolve (false);
  1004.  
  1005.             y2milestone("Solving dependencies returned %1", ok );
  1006.  
  1007.             list result = Pkg::PkgCommit (0);
  1008.             y2milestone ("PkgCommit: %1", result );
  1009.  
  1010.             ok = ok && result[1]:nil == [] && result[2]:nil == [];
  1011.             Wizard::CreateDialog ();
  1012.             Wizard::SetTitleIcon("misc");
  1013.                     WFM::CallFunction ("inst_suseconfig", [false, false]);
  1014.  
  1015.             Wizard::CloseDialog ();
  1016.  
  1017.             if (ok)
  1018.             {
  1019.             reinstalled_packages = missing_packages;
  1020.             y2milestone("All reinstalled_packages: %1",
  1021.                 reinstalled_packages );
  1022.             ret = `ok;
  1023.             }
  1024.             else ret = `error;
  1025.         }
  1026.         else {
  1027.             y2error("Opening the ppackage database failed");
  1028.             ret = `error;
  1029.         }
  1030.         }
  1031.     }
  1032.     else {
  1033.         y2error("No missing packages. Set missing_packages before.");
  1034.         ret = `cancel;
  1035.     }
  1036.     return ret;
  1037.     }
  1038.  
  1039.  
  1040. }//EOF
  1041.