Author: jsrain
Date: Tue Mar 11 16:22:54 2008
New Revision: 45356
URL: http://svn.opensuse.org/viewcvs/yast?rev=45356&view=rev
Log:
added infrastructure to detect configuration files changed not by YaST and warn users about such changes possibly getting lost (fate #303374)
Added:
trunk/yast2/library/system/src/FileChanges.ycp
trunk/yast2/library/system/testsuite/tests/filechanges.err
trunk/yast2/library/system/testsuite/tests/filechanges.out
trunk/yast2/library/system/testsuite/tests/filechanges.ycp
Modified:
trunk/yast2/package/yast2.changes
Added: trunk/yast2/library/system/src/FileChanges.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/yast2/library/system/src/FileChanges.ycp?rev=45356&view=auto
==============================================================================
--- trunk/yast2/library/system/src/FileChanges.ycp (added)
+++ trunk/yast2/library/system/src/FileChanges.ycp Tue Mar 11 16:22:54 2008
@@ -0,0 +1,167 @@
+/**
+ * File: modules/FileChanges.ycp
+ * Module: yast2
+ * Summary: Detect if a configuratil file was changed
+ * Authors: Jiri Srain
+ *
+ * Support routines for detecting changes of configuration files being done
+ * externally (not by YaST) to prevent the changes from being lost because
+ * of YaST not handling the configuration files correctly (eg. removing
+ * comments in some cases, changing order of options,...)
+ *
+ * Warns user if such change is detected.
+ *
+ * Usage:
+ * Before reading the configuration file:
+ * call boolean CheckFiles (list<string>) with all files. If any of them
+ * is detected to be changed, YaST asks a popup for you.
+ * alternatively use boolean FileChanged (string) for each file (does not
+ * ask any question, immediatelly returns status of the file
+ *
+ * After writing the configuraiton file:
+ * call void StoreFileCheckSum (string) for each file to store recent
+ * checksum. YaST will use this checksum next time checking.
+ *
+ */
+
+{
+
+module "FileChanges";
+
+textdomain "base";
+
+import "Mode";
+import "Popup";
+
+string data_file = "/var/lib/YaST2/file_checksums.ycp";
+
+map file_checksums = $[];
+
+/**
+ * Read the data file containing file checksums
+ */
+void ReadSettings () {
+ if ((integer)SCR::Read (.target.size, data_file) <= 0)
+ {
+ file_checksums = $[];
+ return;
+ }
+ file_checksums = (map)SCR::Read (.target.ycp, data_file);
+ if (file_checksums == nil)
+ file_checksums = $[];
+}
+
+/**
+ * Write the data file containing checksums
+ */
+void WriteSettings () {
+ SCR::Write (.target.ycp, data_file, file_checksums);
+}
+
+/**
+ * Compute the checksum of a file
+ * @param file string the file to compute checksum of
+ * @return string the checksum
+ */
+string ComputeFileChecksum (string file) {
+ string cmd = sformat ("/usr/bin/md5sum %1", file);
+ map out = (map)SCR::Execute (.target.bash_output, cmd);
+ // note: it also contains file name, but since it is only to be compared
+ // it does not matter
+ string sum = out["stdout"]:"";
+ return sum;
+}
+
+/**
+ * Check if file was modified compared to the one distributed
+ * with the RPM package
+ * @param file string the file to check
+ * @return boolean true of was changed
+ */
+boolean FileChangedFromPackage (string file) {
+ string cmd = sformat ("/bin/rpm -qf %1", file);
+ map out = (map)SCR::Execute (.target.bash_output, cmd);
+ string package = out["stdout"]:"";
+ y2milestone ("Package owning %1: %2", file, package);
+ if (package == "")
+ return false;
+ // FIXME: /bin/xx finds also /usr/bin/xx
+ cmd = sformat ("rpm -V %1 |grep %2", package, file);
+ out = (map)SCR::Execute (.target.bash_output, cmd);
+ string changes = out["stdout"]:"";
+ y2milestone ("File possibly changed: %1", changes);
+ list<string> lines = splitstring (changes, "\n");
+ boolean changed = false;
+ foreach (string line, lines, {
+ if (regexpmatch (line, "^S"))
+ changed = true;
+ if (regexpmatch (line, "^..5"))
+ changed = true;
+ if (regexpmatch (line, "^.......T"))
+ changed = true;
+ });
+ return changed;
+}
+
+/**
+ * Check if a file was modified externally (without YaST)
+ * @param file string boolean the file to check
+ * @return boolean true if was changed externally
+ */
+global boolean FileChanged (string file) {
+ // when generating AutoYaST configuration, they are not written back
+ if (Mode::config ())
+ return false;
+ ReadSettings ();
+ boolean ret = false;
+ if (haskey (file_checksums, file))
+ {
+ y2milestone ("Comparing file %1 to stored checksum", file);
+ string sum = ComputeFileChecksum (file);
+ ret = ! (sum == file_checksums[file]:"");
+ }
+ else
+ {
+ y2milestone ("Comparing file %1 to RPM database", file);
+ ret = FileChangedFromPackage (file);
+ }
+ y2milestone ("File differs: %1", ret);
+ return ret;
+}
+
+/**
+ * Store checksum of a file to the store
+ * @param file string filename to compute and store
+ */
+global void StoreFileCheckSum (string file) {
+ ReadSettings ();
+ string sum = ComputeFileChecksum (file);
+ file_checksums[file] = sum;
+ WriteSettings ();
+}
+
+/**
+ * Check files if any of them were changed
+ * Issue a question whether to continue if some were chaned
+ * @param files a list of files to check
+ * @return boolean true if either none was changed or user agreed
+ * to continue
+ */
+global boolean CheckFiles (list<string> files) {
+ files = filter (string f, files, { return FileChanged (f); });
+ if (size (files) > 0)
+ {
+ // Continue/Cancel question, %1 is a file name
+ string msg = _("File %1 has been changed manually.
+YaST might lose some of the changes");
+ if (size (files) > 1)
+ // Continue/Cancel question, %1 is a coma separated list of file names
+ msg = _("Files %1 have been changed manually.
+YaST might lose some of the changes");
+ msg = sformat (msg, mergestring (files, ", "));
+ return Popup::ContinueCancel (msg);
+ }
+ return true;
+}
+
+}
Added: trunk/yast2/library/system/testsuite/tests/filechanges.err
URL: http://svn.opensuse.org/viewcvs/yast/trunk/yast2/library/system/testsuite/tests/filechanges.err?rev=45356&view=auto
==============================================================================
(empty)
Added: trunk/yast2/library/system/testsuite/tests/filechanges.out
URL: http://svn.opensuse.org/viewcvs/yast/trunk/yast2/library/system/testsuite/tests/filechanges.out?rev=45356&view=auto
==============================================================================
--- trunk/yast2/library/system/testsuite/tests/filechanges.out (added)
+++ trunk/yast2/library/system/testsuite/tests/filechanges.out Tue Mar 11 16:22:54 2008
@@ -0,0 +1,3 @@
+Return true
+Return true
+Return false
Added: trunk/yast2/library/system/testsuite/tests/filechanges.ycp
URL: http://svn.opensuse.org/viewcvs/yast/trunk/yast2/library/system/testsuite/tests/filechanges.ycp?rev=45356&view=auto
==============================================================================
--- trunk/yast2/library/system/testsuite/tests/filechanges.ycp (added)
+++ trunk/yast2/library/system/testsuite/tests/filechanges.ycp Tue Mar 11 16:22:54 2008
@@ -0,0 +1,73 @@
+/**
+ * File:
+ * filechanges.ycp
+ *
+ * Module:
+ * Base
+ *
+ * Summary:
+ * testsuite for filechanges module
+ *
+ * Authors:
+ * Jiri Srain
+ *
+ * $Id: kernel.ycp 26253 2005-11-22 14:59:29Z lslezak $
+ *
+ */
+
+// testedfiles: Kernel.ycp Testsuite.ycp
+
+{
+ include "testsuite.ycp";
+
+ // minimal "don't care" SCR data to work with the constructor
+ map READ = $[
+ "target" : $[
+ "string" : "",
+ "tmpdir" : "/tmp",
+ "size" : 5,
+ "ycp" : $[
+ ],
+ ],
+ ];
+ map WRITE = $[];
+ list EXECL = [ $[
+ "target" : $[
+ "bash_output" : $[
+ "exit" : "0",
+ "stdout" : "ntp.rpm",
+ ],
+ ],
+ ],
+ $[
+ "target" : $[
+ "bash_output" : $[
+ "exit" : "0",
+ "stdout" : "S.?....T /etc/ntp.conf
+..?..... c /var/lib/ntp/etc/ntp.conf.iburst",
+ ],
+ ],
+ ],
+ ];
+
+ TESTSUITE_INIT ([READ, $[], $[]], 0);
+
+ import "FileChanges";
+ import "Mode";
+
+ Mode::SetTest ("testsuite");
+ TEST (``(FileChanges::FileChanged ("/etc/ntp.conf")), [READ, WRITE, EXECL], nil);
+ READ["target", "ycp", "/etc/ntp.conf"] = "incorrect checksum";
+ map EXEC = $[
+ "target" : $[
+ "bash_output" : $[
+ "exit" : "0",
+ "stdout" : "f210720e1362615ac0ecc544b35abb73 /etc/ntp.conf",
+ ],
+ ],
+ ];
+
+ TEST (``(FileChanges::FileChanged ("/etc/ntp.conf")), [READ, WRITE, EXEC], nil);
+ READ["target", "ycp", "/etc/ntp.conf"] = "f210720e1362615ac0ecc544b35abb73 /etc/ntp.conf";
+ TEST (``(FileChanges::FileChanged ("/etc/ntp.conf")), [READ, WRITE, EXEC], nil);
+}
Modified: trunk/yast2/package/yast2.changes
URL: http://svn.opensuse.org/viewcvs/yast/trunk/yast2/package/yast2.changes?rev=45356&r1=45355&r2=45356&view=diff
==============================================================================
--- trunk/yast2/package/yast2.changes (original)
+++ trunk/yast2/package/yast2.changes Tue Mar 11 16:22:54 2008
@@ -1,4 +1,11 @@
-------------------------------------------------------------------
+Tue Mar 11 16:14:30 CET 2008 - jsrain@suse.cz
+
+- added infrastructure to detect configuration files changed not
+ by YaST and warn users about such changes possibly getting lost
+ (fate #303374)
+
+-------------------------------------------------------------------
Tue Mar 11 13:00:07 CET 2008 - lslezak@suse.cz
- improved String::FormatRateMessage() (needed for #168935)
--
To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org
For additional commands, e-mail: yast-commit+help@opensuse.org