]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
support option --no-dbus for all snapper commands (#299) v0.4.0
authorArvin Schnell <aschnell@suse.com>
Fri, 16 Dec 2016 12:17:38 +0000 (13:17 +0100)
committerGitHub <noreply@github.com>
Fri, 16 Dec 2016 12:17:38 +0000 (13:17 +0100)
- make all snapper commands available with option --no-dbus by using new proxy classes

33 files changed:
LIBVERSION
VERSION
client/Makefile.am
client/cleanup.cc
client/cleanup.h
client/commands.cc
client/commands.h
client/errors.cc
client/misc.cc
client/misc.h
client/proxy-dbus.cc [new file with mode: 0644]
client/proxy-dbus.h [new file with mode: 0644]
client/proxy-lib.cc [new file with mode: 0644]
client/proxy-lib.h [new file with mode: 0644]
client/proxy.cc [new file with mode: 0644]
client/proxy.h [new file with mode: 0644]
client/snapper.cc
client/systemd-helper.cc
client/types.cc
client/types.h
doc/snapper.xml.in
examples/c++-lib/CreateNumber.cc
examples/c++-lib/CreateTimeline.cc
package/snapper.changes
server/Background.cc
server/Client.cc
snapper/Comparison.cc
snapper/Comparison.h
snapper/File.h
snapper/LvmCache.cc
snapper/Snapper.cc
snapper/Snapper.h
testsuite-real/common.cc

index fd2a01863fdd3035fac5918c59666363544bfe23..fcdb2e109f68cff5600955a73908885fe8599bb4 100644 (file)
@@ -1 +1 @@
-3.1.0
+4.0.0
diff --git a/VERSION b/VERSION
index 1c09c74e221cd58f30240fbcfd9545ed19df54d7..1d0ba9ea182b0f7354f3daf12120744ec5e0c2f8 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.3.3
+0.4.0
index c026e8b45db518f4721bc88eb343fee490a1006f..e8f9a5ebbcb63bf7beea533ae7285e9802c4b816 100644 (file)
@@ -13,6 +13,9 @@ snapper_SOURCES =                     \
        types.cc        types.h         \
        commands.cc     commands.h      \
        cleanup.cc      cleanup.h       \
+       proxy.cc        proxy.h         \
+       proxy-dbus.cc   proxy-dbus.h    \
+       proxy-lib.cc    proxy-lib.h     \
        misc.cc         misc.h          \
        errors.cc       errors.h
 
@@ -27,6 +30,9 @@ systemd_helper_SOURCES =              \
        types.cc        types.h         \
        commands.cc     commands.h      \
        cleanup.cc      cleanup.h       \
+       proxy.cc        proxy.h         \
+       proxy-dbus.cc   proxy-dbus.h    \
+       proxy-lib.cc    proxy-lib.h     \
        misc.cc         misc.h          \
        errors.cc       errors.h
 
index cb1658d1da557ededd653458d6bbf3fcb19dd7cb..0dbfc031c5720cb527d3fba0b7c35596d467b2e9 100644 (file)
  */
 
 
+#include <vector>
+
+#include "dbus/DBusMessage.h"
+#include "dbus/DBusConnection.h"
+#include "snapper/SnapperTmpl.h"
+#include "snapper/Snapper.h"
+
 #include "utils/Range.h"
 #include "utils/equal-date.h"
-#include "commands.h"
+#include "cleanup.h"
 
-#include <vector>
 
 using namespace std;
 
 
 struct Parameters
 {
-    Parameters(DBus::Connection& conn, const string& config_name);
+    Parameters(const ProxySnapper* snapper);
     virtual ~Parameters() {}
 
     virtual bool is_degenerated() const { return true; }
 
-    friend ostream& operator<<(ostream& s, const Parameters& parameters);
-
     time_t min_age;
     double space_limit;
+
+    template<typename Type>
+    void read(const ProxyConfig& config, const char* name, Type& value)
+    {
+       const map<string, string>& raw = config.getAllValues();
+       map<string, string>::const_iterator pos = raw.find(name);
+       if (pos != raw.end())
+           pos->second >> value;
+    }
 };
 
 
-Parameters::Parameters(DBus::Connection& conn, const string& config_name)
+Parameters::Parameters(const ProxySnapper* snapper)
     : min_age(1800), space_limit(0.5)
 {
-    XConfigInfo ci = command_get_xconfig(conn, config_name);
+    ProxyConfig config = snapper->getConfig();
 
-    ci.read("SPACE_LIMIT", space_limit);
+    read(config, "SPACE_LIMIT", space_limit);
 }
 
 
@@ -65,8 +78,8 @@ class Cleaner
 {
 public:
 
-    Cleaner(DBus::Connection& conn, const string& config_name, bool verbose, const Parameters& parameters)
-       : conn(conn), config_name(config_name), verbose(verbose), parameters(parameters) {}
+    Cleaner(ProxySnapper* snapper, bool verbose, const Parameters& parameters)
+       : snapper(snapper), verbose(verbose), parameters(parameters) {}
 
     virtual ~Cleaner() {}
 
@@ -74,54 +87,53 @@ public:
 
 protected:
 
-    virtual list<XSnapshots::iterator> calculate_candidates(Range::Value value) = 0;
+    virtual list<ProxySnapshots::iterator> calculate_candidates(ProxySnapshots& snapshots,
+                                                               Range::Value value) = 0;
 
     struct younger_than
     {
        younger_than(time_t t)
            : t(t) {}
-       bool operator()(XSnapshots::const_iterator it)
+       bool operator()(ProxySnapshots::const_iterator it)
            { return it->getDate() > t; }
        const time_t t;
     };
 
-    void filter(list<XSnapshots::iterator>& tmp) const;
+    void filter(ProxySnapshots& snapshots, list<ProxySnapshots::iterator>& tmp) const;
 
     // Removes snapshots younger than parameters.min_age from tmp
-    void filter_min_age(list<XSnapshots::iterator>& tmp) const;
+    void filter_min_age(ProxySnapshots& snapshots, list<ProxySnapshots::iterator>& tmp) const;
 
     // Removes pre and post snapshots from tmp that do have a corresponding
     // snapshot but which is not included in tmp.
-    void filter_pre_post(list<XSnapshots::iterator>& tmp) const;
+    void filter_pre_post(ProxySnapshots& snapshots, list<ProxySnapshots::iterator>& tmp) const;
 
-    void remove(const list<XSnapshots::iterator>& tmp);
+    void remove(const list<ProxySnapshots::iterator>& tmp);
 
     bool is_quota_aware() const;
     bool is_quota_satisfied() const;
 
-    void cleanup_quota_unaware();
-    void cleanup_quota_aware();
+    void cleanup_quota_unaware(ProxySnapshots& snapshots);
+    void cleanup_quota_aware(ProxySnapshots& snapshots);
 
-    DBus::Connection& conn;
-    const string& config_name;
+    ProxySnapper* snapper;
     bool verbose;
 
     const Parameters& parameters;
 
-    XSnapshots snapshots;
 };
 
 
 void
-Cleaner::filter(list<XSnapshots::iterator>& tmp) const
+Cleaner::filter(ProxySnapshots& snapshots, list<ProxySnapshots::iterator>& tmp) const
 {
-    filter_min_age(tmp);
-    filter_pre_post(tmp);
+    filter_min_age(snapshots, tmp);
+    filter_pre_post(snapshots, tmp);
 }
 
 
 void
-Cleaner::filter_min_age(list<XSnapshots::iterator>& tmp) const
+Cleaner::filter_min_age(ProxySnapshots& snapshots, list<ProxySnapshots::iterator>& tmp) const
 {
     time_t now = time(NULL);
     tmp.remove_if(younger_than(now - parameters.min_age));
@@ -129,15 +141,15 @@ Cleaner::filter_min_age(list<XSnapshots::iterator>& tmp) const
 
 
 void
-Cleaner::filter_pre_post(list<XSnapshots::iterator>& tmp) const
+Cleaner::filter_pre_post(ProxySnapshots& snapshots, list<ProxySnapshots::iterator>& tmp) const
 {
-    list<XSnapshots::iterator> ret;
+    list<ProxySnapshots::iterator> ret;
 
-    for (list<XSnapshots::iterator>::iterator it1 = tmp.begin(); it1 != tmp.end(); ++it1)
+    for (list<ProxySnapshots::iterator>::iterator it1 = tmp.begin(); it1 != tmp.end(); ++it1)
     {
        if ((*it1)->getType() == PRE)
        {
-           XSnapshots::const_iterator it2 = snapshots.findPost(*it1);
+           ProxySnapshots::const_iterator it2 = snapshots.findPost(*it1);
            if (it2 != snapshots.end())
            {
                if (find(tmp.begin(), tmp.end(), it2) == tmp.end())
@@ -147,7 +159,7 @@ Cleaner::filter_pre_post(list<XSnapshots::iterator>& tmp) const
 
        if ((*it1)->getType() == POST)
        {
-           XSnapshots::const_iterator it2 = snapshots.findPre(*it1);
+           ProxySnapshots::const_iterator it2 = snapshots.findPre(*it1);
            if (it2 != snapshots.end())
            {
                if (find(tmp.begin(), tmp.end(), it2) == tmp.end())
@@ -163,12 +175,11 @@ Cleaner::filter_pre_post(list<XSnapshots::iterator>& tmp) const
 
 
 void
-Cleaner::remove(const list<XSnapshots::iterator>& tmp)
+Cleaner::remove(const list<ProxySnapshots::iterator>& tmp)
 {
-    for (list<XSnapshots::iterator>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+    for (list<ProxySnapshots::iterator>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
     {
-       command_delete_xsnapshots(conn, config_name, { (*it)->getNum() }, verbose);
-       snapshots.erase(*it);
+       snapper->deleteSnapshots({ *it }, verbose);
     }
 }
 
@@ -181,7 +192,7 @@ Cleaner::is_quota_aware() const
 
     try
     {
-       command_prepare_quota(conn, config_name);
+       snapper->prepareQuota();
     }
     catch (const DBus::ErrorException& e)
     {
@@ -195,6 +206,13 @@ Cleaner::is_quota_aware() const
 
        SN_RETHROW(e);
     }
+    catch (const QuotaException& e)
+    {
+       SN_CAUGHT(e);
+
+       cerr << "quota not working (" << e.what() << ")" << endl;
+       return false;
+    }
 
     return true;
 }
@@ -203,29 +221,29 @@ Cleaner::is_quota_aware() const
 bool
 Cleaner::is_quota_satisfied() const
 {
-    XQuotaData quota_data = command_query_quota(conn, config_name);
+    QuotaData quota_data = snapper->queryQuotaData();
 
     return quota_data.used < parameters.space_limit * quota_data.size;
 }
 
 
 void
-Cleaner::cleanup_quota_unaware()
+Cleaner::cleanup_quota_unaware(ProxySnapshots& snapshots)
 {
-    list<XSnapshots::iterator> candidates = calculate_candidates(Range::MAX);
+    list<ProxySnapshots::iterator> candidates = calculate_candidates(snapshots, Range::MAX);
 
-    filter(candidates);
+    filter(snapshots, candidates);
 
     remove(candidates);
 }
 
 
 void
-Cleaner::cleanup_quota_aware()
+Cleaner::cleanup_quota_aware(ProxySnapshots& snapshots)
 {
     while (!is_quota_satisfied())
     {
-       list<XSnapshots::iterator> candidates = calculate_candidates(Range::MIN);
+       list<ProxySnapshots::iterator> candidates = calculate_candidates(snapshots, Range::MIN);
        if (candidates.empty())
        {
            // not enough candidates to satisfy quota
@@ -237,11 +255,11 @@ Cleaner::cleanup_quota_aware()
        // snapshot candidate if the post snapshot is missing so simply
        // removing the first candidate is not possible.
 
-       for (list<XSnapshots::iterator>::iterator e = candidates.begin(); e != candidates.end(); ++e)
+       for (list<ProxySnapshots::iterator>::iterator e = candidates.begin(); e != candidates.end(); ++e)
        {
-           list<XSnapshots::iterator> tmp = list<XSnapshots::iterator>(candidates.begin(), next(e));
+           list<ProxySnapshots::iterator> tmp = list<ProxySnapshots::iterator>(candidates.begin(), next(e));
 
-           filter(tmp);
+           filter(snapshots, tmp);
 
            if (!tmp.empty())
            {
@@ -263,37 +281,35 @@ Cleaner::cleanup_quota_aware()
 void
 Cleaner::cleanup()
 {
-    snapshots = command_list_xsnapshots(conn, config_name);
+    ProxySnapshots& snapshots = snapper->getSnapshots();
 
-    cleanup_quota_unaware();
+    cleanup_quota_unaware(snapshots);
 
     if (is_quota_aware())
-       cleanup_quota_aware();
+       cleanup_quota_aware(snapshots);
 }
 
 
 struct NumberParameters : public Parameters
 {
-    NumberParameters(DBus::Connection& conn, const string& config_name);
+    NumberParameters(const ProxySnapper* snapper);
 
     bool is_degenerated() const;
 
-    friend ostream& operator<<(ostream& s, const NumberParameters& parameters);
-
     Range limit;
     Range limit_important;
 };
 
 
-NumberParameters::NumberParameters(DBus::Connection& conn, const string& config_name)
-    : Parameters(conn, config_name), limit(50), limit_important(10)
+NumberParameters::NumberParameters(const ProxySnapper* snapper)
+    : Parameters(snapper), limit(50), limit_important(10)
 {
-    XConfigInfo ci = command_get_xconfig(conn, config_name);
+    ProxyConfig config = snapper->getConfig();
 
-    ci.read("NUMBER_MIN_AGE", min_age);
+    read(config, "NUMBER_MIN_AGE", min_age);
 
-    ci.read("NUMBER_LIMIT", limit);
-    ci.read("NUMBER_LIMIT_IMPORTANT", limit_important);
+    read(config, "NUMBER_LIMIT", limit);
+    read(config, "NUMBER_LIMIT_IMPORTANT", limit_important);
 }
 
 
@@ -318,28 +334,27 @@ class NumberCleaner : public Cleaner
 
 public:
 
-    NumberCleaner(DBus::Connection& conn, const string& config_name, bool verbose,
-                 const NumberParameters& parameters)
-       : Cleaner(conn, config_name, verbose, parameters) {}
+    NumberCleaner(ProxySnapper* snapper, bool verbose, const NumberParameters& parameters)
+       : Cleaner(snapper, verbose, parameters) {}
 
 private:
 
     bool
-    is_important(XSnapshots::const_iterator it1)
+    is_important(ProxySnapshots::const_iterator it1)
     {
        map<string, string>::const_iterator it2 = it1->getUserdata().find("important");
        return it2 != it1->getUserdata().end() && it2->second == "yes";
     }
 
 
-    list<XSnapshots::iterator>
-    calculate_candidates(Range::Value value)
+    list<ProxySnapshots::iterator>
+    calculate_candidates(ProxySnapshots& snapshots, Range::Value value) override
     {
        const NumberParameters& parameters = dynamic_cast<const NumberParameters&>(Cleaner::parameters);
 
-       list<XSnapshots::iterator> ret;
+       list<ProxySnapshots::iterator> ret;
 
-       for (XSnapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it)
+       for (ProxySnapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it)
        {
            if (it->getCleanup() == "number")
                ret.push_front(it);
@@ -348,7 +363,7 @@ private:
        size_t num = 0;
        size_t num_important = 0;
 
-       list<XSnapshots::iterator>::iterator it = ret.begin();
+       list<ProxySnapshots::iterator>::iterator it = ret.begin();
        while (it != ret.end())
        {
            bool keep = false;
@@ -378,17 +393,17 @@ private:
 
 
 void
-do_cleanup_number(DBus::Connection& conn, const string& config_name, bool verbose)
+do_cleanup_number(ProxySnapper* snapper, bool verbose)
 {
-    NumberParameters parameters(conn, config_name);
-    NumberCleaner cleaner(conn, config_name, verbose, parameters);
+    NumberParameters parameters(snapper);
+    NumberCleaner cleaner(snapper, verbose, parameters);
     cleaner.cleanup();
 }
 
 
 struct TimelineParameters : public Parameters
 {
-    TimelineParameters(DBus::Connection& conn, const string& config_name);
+    TimelineParameters(const ProxySnapper* snapper);
 
     bool is_degenerated() const;
 
@@ -400,19 +415,19 @@ struct TimelineParameters : public Parameters
 };
 
 
-TimelineParameters::TimelineParameters(DBus::Connection& conn, const string& config_name)
-    : Parameters(conn, config_name), limit_hourly(10), limit_daily(10), limit_monthly(10),
+TimelineParameters::TimelineParameters(const ProxySnapper* snapper)
+    : Parameters(snapper), limit_hourly(10), limit_daily(10), limit_monthly(10),
       limit_weekly(0), limit_yearly(10)
 {
-    XConfigInfo ci = command_get_xconfig(conn, config_name);
+    ProxyConfig config = snapper->getConfig();
 
-    ci.read("TIMELINE_MIN_AGE", min_age);
+    read(config, "TIMELINE_MIN_AGE", min_age);
 
-    ci.read("TIMELINE_LIMIT_HOURLY", limit_hourly);
-    ci.read("TIMELINE_LIMIT_DAILY", limit_daily);
-    ci.read("TIMELINE_LIMIT_WEEKLY", limit_weekly);
-    ci.read("TIMELINE_LIMIT_MONTHLY", limit_monthly);
-    ci.read("TIMELINE_LIMIT_YEARLY", limit_yearly);
+    read(config, "TIMELINE_LIMIT_HOURLY", limit_hourly);
+    read(config, "TIMELINE_LIMIT_DAILY", limit_daily);
+    read(config, "TIMELINE_LIMIT_WEEKLY", limit_weekly);
+    read(config, "TIMELINE_LIMIT_MONTHLY", limit_monthly);
+    read(config, "TIMELINE_LIMIT_YEARLY", limit_yearly);
 }
 
 
@@ -441,23 +456,22 @@ class TimelineCleaner : public Cleaner
 {
 public:
 
-    TimelineCleaner(DBus::Connection& conn, const string& config_name, bool verbose,
-                   const TimelineParameters& parameters)
-       : Cleaner(conn, config_name, verbose, parameters) {}
+    TimelineCleaner(ProxySnapper* snapper, bool verbose, const TimelineParameters& parameters)
+       : Cleaner(snapper, verbose, parameters) {}
 
 private:
 
     bool
-    is_first(list<XSnapshots::iterator>::const_iterator first,
-            list<XSnapshots::iterator>::const_iterator last,
-            XSnapshots::const_iterator it1,
+    is_first(list<ProxySnapshots::iterator>::const_iterator first,
+            list<ProxySnapshots::iterator>::const_iterator last,
+            ProxySnapshots::const_iterator it1,
             std::function<bool(const struct tm& tmp1, const struct tm& tmp2)> pred)
     {
        time_t t1 = it1->getDate();
        struct tm tmp1;
        localtime_r(&t1, &tmp1);
 
-       for (list<XSnapshots::iterator>::const_iterator it2 = first; it2 != last; ++it2)
+       for (list<ProxySnapshots::iterator>::const_iterator it2 = first; it2 != last; ++it2)
        {
            if (it1 == *it2)
                continue;
@@ -478,54 +492,54 @@ private:
 
 
     bool
-    is_first_yearly(list<XSnapshots::iterator>::const_iterator first,
-                   list<XSnapshots::iterator>::const_iterator last,
-                   XSnapshots::const_iterator it1)
+    is_first_yearly(list<ProxySnapshots::iterator>::const_iterator first,
+                   list<ProxySnapshots::iterator>::const_iterator last,
+                   ProxySnapshots::const_iterator it1)
     {
        return is_first(first, last, it1, equal_year);
     }
 
     bool
-    is_first_monthly(list<XSnapshots::iterator>::const_iterator first,
-                    list<XSnapshots::iterator>::const_iterator last,
-                    XSnapshots::const_iterator it1)
+    is_first_monthly(list<ProxySnapshots::iterator>::const_iterator first,
+                    list<ProxySnapshots::iterator>::const_iterator last,
+                    ProxySnapshots::const_iterator it1)
     {
        return is_first(first, last, it1, equal_month);
     }
 
     bool
-    is_first_weekly(list<XSnapshots::iterator>::const_iterator first,
-                   list<XSnapshots::iterator>::const_iterator last,
-                   XSnapshots::const_iterator it1)
+    is_first_weekly(list<ProxySnapshots::iterator>::const_iterator first,
+                   list<ProxySnapshots::iterator>::const_iterator last,
+                   ProxySnapshots::const_iterator it1)
     {
        return is_first(first, last, it1, equal_week);
     }
 
     bool
-    is_first_daily(list<XSnapshots::iterator>::const_iterator first,
-                  list<XSnapshots::iterator>::const_iterator last,
-                  XSnapshots::const_iterator it1)
+    is_first_daily(list<ProxySnapshots::iterator>::const_iterator first,
+                  list<ProxySnapshots::iterator>::const_iterator last,
+                  ProxySnapshots::const_iterator it1)
     {
        return is_first(first, last, it1, equal_day);
     }
 
     bool
-    is_first_hourly(list<XSnapshots::iterator>::const_iterator first,
-                   list<XSnapshots::iterator>::const_iterator last,
-                   XSnapshots::const_iterator it1)
+    is_first_hourly(list<ProxySnapshots::iterator>::const_iterator first,
+                   list<ProxySnapshots::iterator>::const_iterator last,
+                   ProxySnapshots::const_iterator it1)
     {
        return is_first(first, last, it1, equal_hour);
     }
 
 
-    list<XSnapshots::iterator>
-    calculate_candidates(Range::Value value)
+    list<ProxySnapshots::iterator>
+    calculate_candidates(ProxySnapshots& snapshots, Range::Value value) override
     {
        const TimelineParameters& parameters = dynamic_cast<const TimelineParameters&>(Cleaner::parameters);
 
-       list<XSnapshots::iterator> ret;
+       list<ProxySnapshots::iterator> ret;
 
-       for (XSnapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it)
+       for (ProxySnapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it)
        {
            if (it->getCleanup() == "timeline")
                ret.push_front(it);
@@ -537,7 +551,7 @@ private:
        size_t num_monthly = 0;
        size_t num_yearly = 0;
 
-       list<XSnapshots::iterator>::iterator it = ret.begin();
+       list<ProxySnapshots::iterator>::iterator it = ret.begin();
        while (it != ret.end())
        {
            bool keep = false;
@@ -582,26 +596,26 @@ private:
 
 
 void
-do_cleanup_timeline(DBus::Connection& conn, const string& config_name, bool verbose)
+do_cleanup_timeline(ProxySnapper* snapper, bool verbose)
 {
-    TimelineParameters parameters(conn, config_name);
-    TimelineCleaner cleaner(conn, config_name, verbose, parameters);
+    TimelineParameters parameters(snapper);
+    TimelineCleaner cleaner(snapper, verbose, parameters);
     cleaner.cleanup();
 }
 
 
 struct EmptyPrePostParameters : public Parameters
 {
-    EmptyPrePostParameters(DBus::Connection& conn, const string& config_name);
+    EmptyPrePostParameters(const ProxySnapper* snapper);
 };
 
 
-EmptyPrePostParameters::EmptyPrePostParameters(DBus::Connection& conn, const string& config_name)
-    : Parameters(conn, config_name)
+EmptyPrePostParameters::EmptyPrePostParameters(const ProxySnapper* snapper)
+    : Parameters(snapper)
 {
-    XConfigInfo ci = command_get_xconfig(conn, config_name);
+    ProxyConfig config = snapper->getConfig();
 
-    ci.read("EMPTY_PRE_POST_MIN_AGE", min_age);
+    read(config, "EMPTY_PRE_POST_MIN_AGE", min_age);
 }
 
 
@@ -609,36 +623,30 @@ class EmptyPrePostCleaner : public Cleaner
 {
 public:
 
-    EmptyPrePostCleaner(DBus::Connection& conn, const string& config_name, bool verbose,
+    EmptyPrePostCleaner(ProxySnapper* snapper, bool verbose,
                        const EmptyPrePostParameters& parameters)
-       : Cleaner(conn, config_name, verbose, parameters) {}
+       : Cleaner(snapper, verbose, parameters) {}
 
 private:
 
-    list<XSnapshots::iterator>
-    calculate_candidates(Range::Value value)
+    list<ProxySnapshots::iterator>
+    calculate_candidates(ProxySnapshots& snapshots, Range::Value value) override
     {
-       list<XSnapshots::iterator> ret;
+       list<ProxySnapshots::iterator> ret;
 
-       for (XSnapshots::iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
+       for (ProxySnapshots::iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
        {
            if (it1->getType() == PRE)
            {
-               XSnapshots::iterator it2 = snapshots.findPost(it1);
-
+               ProxySnapshots::iterator it2 = snapshots.findPost(it1);
                if (it2 != snapshots.end())
                {
-                   command_create_xcomparison(conn, config_name, it1->getNum(), it2->getNum());
-
-                   list<XFile> files = command_get_xfiles(conn, config_name, it1->getNum(), it2->getNum());
-
-                   if (files.empty())
+                   ProxyComparison comparison = snapper->createComparison(*it1, *it2, false);
+                   if (comparison.getFiles().empty())
                    {
                        ret.push_back(it1);
                        ret.push_back(it2);
                    }
-
-                   command_delete_xcomparison(conn, config_name, it1->getNum(), it2->getNum());
                }
            }
        }
@@ -649,9 +657,9 @@ private:
 
 
 void
-do_cleanup_empty_pre_post(DBus::Connection& conn, const string& config_name, bool verbose)
+do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose)
 {
-    EmptyPrePostParameters parameters(conn, config_name);
-    EmptyPrePostCleaner cleaner(conn, config_name, verbose, parameters);
+    EmptyPrePostParameters parameters(snapper);
+    EmptyPrePostCleaner cleaner(snapper, verbose, parameters);
     cleaner.cleanup();
 }
index 35955bf21aafec64d179c10dc55cece252bb9ab5..000b66989ecdc84ba6443bd4c46532d936646bf0 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) [2011-2012] Novell, Inc.
+ * Copyright (c) 2016 SUSE LLC
  *
  * All Rights Reserved.
  *
  */
 
 
+#include "proxy.h"
+
+
 void
-do_cleanup_number(DBus::Connection& conn, const string& config_name, bool verbose);
+do_cleanup_number(ProxySnapper* snapper, bool verbose);
 
 void
-do_cleanup_timeline(DBus::Connection& conn, const string& config_name, bool verbose);
+do_cleanup_timeline(ProxySnapper* snapper, bool verbose);
 
 void
-do_cleanup_empty_pre_post(DBus::Connection& conn, const string& config_name, bool verbose);
+do_cleanup_empty_pre_post(ProxySnapper* snapper, bool verbose);
index 8cb9fd7c117f5b7e4da709dec593db65a3d0c10a..41c4dc12eae17ec59d00919423e98cdca4d8aebe 100644 (file)
@@ -35,14 +35,14 @@ using namespace std;
 #define INTERFACE "org.opensuse.Snapper"
 
 
-list<XConfigInfo>
+vector<XConfigInfo>
 command_list_xconfigs(DBus::Connection& conn)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "ListConfigs");
 
     DBus::Message reply = conn.send_with_reply_and_block(call);
 
-    list<XConfigInfo> ret;
+    vector<XConfigInfo> ret;
 
     DBus::Hihi hihi(reply);
     hihi >> ret;
@@ -84,8 +84,8 @@ command_set_xconfig(DBus::Connection& conn, const string& config_name,
 
 
 void
-command_create_xconfig(DBus::Connection& conn, const string& config_name, const string& subvolume,
-                      const string& fstype, const string& template_name)
+command_create_config(DBus::Connection& conn, const string& config_name, const string& subvolume,
+                     const string& fstype, const string& template_name)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "CreateConfig");
 
@@ -97,7 +97,7 @@ command_create_xconfig(DBus::Connection& conn, const string& config_name, const
 
 
 void
-command_delete_xconfig(DBus::Connection& conn, const string& config_name)
+command_delete_config(DBus::Connection& conn, const string& config_name)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "DeleteConfig");
 
@@ -147,22 +147,22 @@ command_get_xsnapshot(DBus::Connection& conn, const string& config_name, unsigne
 
 
 void
-command_set_xsnapshot(DBus::Connection& conn, const string& config_name, unsigned int num,
-                     const XSnapshot& data)
+command_set_snapshot(DBus::Connection& conn, const string& config_name, unsigned int num,
+                    const SMD& smd)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "SetSnapshot");
 
     DBus::Hoho hoho(call);
-    hoho << config_name << num << data.description << data.cleanup << data.userdata;
+    hoho << config_name << num << smd.description << smd.cleanup << smd.userdata;
 
     conn.send_with_reply_and_block(call);
 }
 
 
 unsigned int
-command_create_single_xsnapshot(DBus::Connection& conn, const string& config_name,
-                               const string& description, const string& cleanup,
-                               const map<string, string>& userdata)
+command_create_single_snapshot(DBus::Connection& conn, const string& config_name,
+                              const string& description, const string& cleanup,
+                              const map<string, string>& userdata)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "CreateSingleSnapshot");
 
@@ -181,10 +181,10 @@ command_create_single_xsnapshot(DBus::Connection& conn, const string& config_nam
 
 
 unsigned int
-command_create_single_xsnapshot_v2(DBus::Connection& conn, const string& config_name,
-                                  unsigned int parent_num, bool read_only,
-                                  const string& description, const string& cleanup,
-                                  const map<string, string>& userdata)
+command_create_single_snapshot_v2(DBus::Connection& conn, const string& config_name,
+                                 unsigned int parent_num, bool read_only,
+                                 const string& description, const string& cleanup,
+                                 const map<string, string>& userdata)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "CreateSingleSnapshotV2");
 
@@ -203,10 +203,10 @@ command_create_single_xsnapshot_v2(DBus::Connection& conn, const string& config_
 
 
 unsigned int
-command_create_single_xsnapshot_of_default(DBus::Connection& conn, const string& config_name,
-                                          bool read_only, const string& description,
-                                          const string& cleanup,
-                                          const map<string, string>& userdata)
+command_create_single_snapshot_of_default(DBus::Connection& conn, const string& config_name,
+                                         bool read_only, const string& description,
+                                         const string& cleanup,
+                                         const map<string, string>& userdata)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "CreateSingleSnapshotOfDefault");
 
@@ -225,9 +225,9 @@ command_create_single_xsnapshot_of_default(DBus::Connection& conn, const string&
 
 
 unsigned int
-command_create_pre_xsnapshot(DBus::Connection& conn, const string& config_name,
-                            const string& description, const string& cleanup,
-                            const map<string, string>& userdata)
+command_create_pre_snapshot(DBus::Connection& conn, const string& config_name,
+                           const string& description, const string& cleanup,
+                           const map<string, string>& userdata)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "CreatePreSnapshot");
 
@@ -246,9 +246,9 @@ command_create_pre_xsnapshot(DBus::Connection& conn, const string& config_name,
 
 
 unsigned int
-command_create_post_xsnapshot(DBus::Connection& conn, const string& config_name,
-                             unsigned int prenum, const string& description,
-                             const string& cleanup, const map<string, string>& userdata)
+command_create_post_snapshot(DBus::Connection& conn, const string& config_name,
+                            unsigned int prenum, const string& description,
+                            const string& cleanup, const map<string, string>& userdata)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "CreatePostSnapshot");
 
@@ -267,15 +267,15 @@ command_create_post_xsnapshot(DBus::Connection& conn, const string& config_name,
 
 
 void
-command_delete_xsnapshots(DBus::Connection& conn, const string& config_name,
-                         const list<unsigned int>& nums, bool verbose)
+command_delete_snapshots(DBus::Connection& conn, const string& config_name,
+                        const vector<unsigned int>& nums, bool verbose)
 {
     if (verbose)
     {
        cout << sformat(_("Deleting snapshot from %s:", "Deleting snapshots from %s:", nums.size()),
                        config_name.c_str()) << endl;
 
-       for (list<unsigned int>::const_iterator it = nums.begin(); it != nums.end(); ++it)
+       for (vector<unsigned int>::const_iterator it = nums.begin(); it != nums.end(); ++it)
        {
            if (it != nums.begin())
                cout << ", ";
@@ -294,8 +294,8 @@ command_delete_xsnapshots(DBus::Connection& conn, const string& config_name,
 
 
 string
-command_mount_xsnapshots(DBus::Connection& conn, const string& config_name,
-                        unsigned int num, bool user_request)
+command_mount_snapshot(DBus::Connection& conn, const string& config_name,
+                      unsigned int num, bool user_request)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "MountSnapshot");
 
@@ -314,8 +314,8 @@ command_mount_xsnapshots(DBus::Connection& conn, const string& config_name,
 
 
 void
-command_umount_xsnapshots(DBus::Connection& conn, const string& config_name,
-                         unsigned int num, bool user_request)
+command_umount_snapshot(DBus::Connection& conn, const string& config_name, unsigned int num,
+                       bool user_request)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "UmountSnapshot");
 
@@ -327,8 +327,7 @@ command_umount_xsnapshots(DBus::Connection& conn, const string& config_name,
 
 
 string
-command_get_xmount_point(DBus::Connection& conn, const string& config_name,
-                        unsigned int num)
+command_get_mount_point(DBus::Connection& conn, const string& config_name, unsigned int num)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "GetMountPoint");
 
@@ -347,8 +346,8 @@ command_get_xmount_point(DBus::Connection& conn, const string& config_name,
 
 
 void
-command_create_xcomparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
-                          unsigned int number2)
+command_create_comparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
+                         unsigned int number2)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "CreateComparison");
 
@@ -360,8 +359,8 @@ command_create_xcomparison(DBus::Connection& conn, const string& config_name, un
 
 
 void
-command_delete_xcomparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
-                          unsigned int number2)
+command_delete_comparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
+                         unsigned int number2)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "DeleteComparison");
 
@@ -379,7 +378,7 @@ operator<(const XFile& lhs, const XFile& rhs)
 }
 
 
-list<XFile>
+vector<XFile>
 command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned int number1,
                   unsigned int number2)
 {
@@ -390,13 +389,13 @@ command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned i
 
     DBus::Message reply = conn.send_with_reply_and_block(call);
 
-    list<XFile> files;
+    vector<XFile> files;
 
     DBus::Hihi hihi(reply);
     hihi >> files;
 
-    files.sort();              // snapperd can have different locale than client
-                               // so sorting is required here
+    sort(files.begin(), files.end());  // snapperd can have different locale than client
+                                       // so sorting is required here
 
     return files;
 }
@@ -426,7 +425,7 @@ command_prepare_quota(DBus::Connection& conn, const string& config_name)
 }
 
 
-XQuotaData
+QuotaData
 command_query_quota(DBus::Connection& conn, const string& config_name)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "QueryQuota");
@@ -436,7 +435,7 @@ command_query_quota(DBus::Connection& conn, const string& config_name)
 
     DBus::Message reply = conn.send_with_reply_and_block(call);
 
-    XQuotaData quota_data;
+    QuotaData quota_data;
 
     DBus::Hihi hihi(reply);
     hihi >> quota_data;
@@ -446,7 +445,7 @@ command_query_quota(DBus::Connection& conn, const string& config_name)
 
 
 void
-command_xsync(DBus::Connection& conn, const string& config_name)
+command_sync(DBus::Connection& conn, const string& config_name)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "Sync");
 
@@ -458,7 +457,7 @@ command_xsync(DBus::Connection& conn, const string& config_name)
 
 
 vector<string>
-command_xdebug(DBus::Connection& conn)
+command_debug(DBus::Connection& conn)
 {
     DBus::MessageMethodCall call(SERVICE, OBJECT, INTERFACE, "Debug");
 
index 683a11a5dbd87cf9eaf000f59fc3690cf9a41c7b..b70aa9572aa352921f56153133ac61472ece25d8 100644 (file)
 
 #include <string>
 #include <vector>
-#include <list>
 #include <map>
 
 using std::string;
 using std::vector;
-using std::list;
 using std::map;
 
 #include "types.h"
 
 
-list<XConfigInfo>
+vector<XConfigInfo>
 command_list_xconfigs(DBus::Connection& conn);
 
 XConfigInfo
@@ -45,11 +43,11 @@ command_set_xconfig(DBus::Connection& conn, const string& config_name,
                    const map<string, string>& raw);
 
 void
-command_create_xconfig(DBus::Connection& conn, const string& config_name, const string& subvolume,
-                      const string& fstype, const string& template_name);
+command_create_config(DBus::Connection& conn, const string& config_name, const string& subvolume,
+                     const string& fstype, const string& template_name);
 
 void
-command_delete_xconfig(DBus::Connection& conn, const string& config_name);
+command_delete_config(DBus::Connection& conn, const string& config_name);
 
 XSnapshots
 command_list_xsnapshots(DBus::Connection& conn, const string& config_name);
@@ -58,61 +56,61 @@ XSnapshot
 command_get_xsnapshot(DBus::Connection& conn, const string& config_name, unsigned int num);
 
 void
-command_set_xsnapshot(DBus::Connection& conn, const string& config_name, unsigned int num,
-                     const XSnapshot& data);
+command_set_snapshot(DBus::Connection& conn, const string& config_name, unsigned int num,
+                    const SMD& smd);
 
 unsigned int
-command_create_single_xsnapshot(DBus::Connection& conn, const string& config_name,
-                               const string& description, const string& cleanup,
-                               const map<string, string>& userdata);
+command_create_single_snapshot(DBus::Connection& conn, const string& config_name,
+                              const string& description, const string& cleanup,
+                              const map<string, string>& userdata);
 
 unsigned int
-command_create_single_xsnapshot_v2(DBus::Connection& conn, const string& config_name,
-                                  unsigned int parent_num, bool read_only,
-                                  const string& description, const string& cleanup,
-                                  const map<string, string>& userdata);
+command_create_single_snapshot_v2(DBus::Connection& conn, const string& config_name,
+                                 unsigned int parent_num, bool read_only,
+                                 const string& description, const string& cleanup,
+                                 const map<string, string>& userdata);
 
 unsigned int
-command_create_single_xsnapshot_of_default(DBus::Connection& conn, const string& config_name,
-                                          bool read_only, const string& description,
-                                          const string& cleanup,
-                                          const map<string, string>& userdata);
+command_create_single_snapshot_of_default(DBus::Connection& conn, const string& config_name,
+                                         bool read_only, const string& description,
+                                         const string& cleanup,
+                                         const map<string, string>& userdata);
 
 unsigned int
-command_create_pre_xsnapshot(DBus::Connection& conn, const string& config_name,
-                            const string& description, const string& cleanup,
-                            const map<string, string>& userdata);
+command_create_pre_snapshot(DBus::Connection& conn, const string& config_name,
+                           const string& description, const string& cleanup,
+                           const map<string, string>& userdata);
 
 unsigned int
-command_create_post_xsnapshot(DBus::Connection& conn, const string& config_name,
-                             unsigned int prenum, const string& description,
-                             const string& cleanup, const map<string, string>& userdata);
+command_create_post_snapshot(DBus::Connection& conn, const string& config_name,
+                            unsigned int prenum, const string& description,
+                            const string& cleanup, const map<string, string>& userdata);
 
 void
-command_delete_xsnapshots(DBus::Connection& conn, const string& config_name,
-                         const list<unsigned int>& nums, bool verbose);
+command_delete_snapshots(DBus::Connection& conn, const string& config_name,
+                        const vector<unsigned int>& nums, bool verbose);
 
 string
-command_mount_xsnapshots(DBus::Connection& conn, const string& config_name,
-                        unsigned int num, bool user_request);
+command_mount_snapshot(DBus::Connection& conn, const string& config_name,
+                      unsigned int num, bool user_request);
 
 void
-command_umount_xsnapshots(DBus::Connection& conn, const string& config_name,
-                         unsigned int num, bool user_request);
+command_umount_snapshot(DBus::Connection& conn, const string& config_name,
+                       unsigned int num, bool user_request);
 
 string
-command_get_xmount_point(DBus::Connection& conn, const string& config_name,
-                        unsigned int num);
+command_get_mount_point(DBus::Connection& conn, const string& config_name,
+                       unsigned int num);
 
 void
-command_create_xcomparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
-                          unsigned int number2);
+command_create_comparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
+                         unsigned int number2);
 
 void
-command_delete_xcomparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
-                          unsigned int number2);
+command_delete_comparison(DBus::Connection& conn, const string& config_name, unsigned int number1,
+                         unsigned int number2);
 
-list<XFile>
+vector<XFile>
 command_get_xfiles(DBus::Connection& conn, const string& config_name, unsigned int number1,
                   unsigned int number2);
 
@@ -122,11 +120,11 @@ command_setup_quota(DBus::Connection& conn, const string& config_name);
 void
 command_prepare_quota(DBus::Connection& conn, const string& config_name);
 
-XQuotaData
+QuotaData
 command_query_quota(DBus::Connection& conn, const string& config_name);
 
 void
-command_xsync(DBus::Connection& conn, const string& config_name);
+command_sync(DBus::Connection& conn, const string& config_name);
 
 vector<string>
-command_xdebug(DBus::Connection& conn);
+command_debug(DBus::Connection& conn);
index f2dc43e4fa065deefa1daac5c1dd022fa78acf1c..ff16a8d0b9d57bc146dfd2c7a526db285c5e52f0 100644 (file)
@@ -50,7 +50,7 @@ error_description(const DBus::ErrorException& e)
        return _("Invalid configdata.");
 
     if (name == "error.illegal_snapshot")
-       return _("Illegal Snapshot.");
+       return _("Illegal snapshot.");
 
     if (name == "error.config_locked")
        return _("Config is locked.");
index be9bf749b2811096c8142c624b3c5f47d3cedc00..843479f2e330f73f386992db32062a44a3819440 100644 (file)
 #include "misc.h"
 
 
-Snapshots::iterator
-read_num(Snapper* snapper, const string& str)
-{
-    Snapshots& snapshots = snapper->getSnapshots();
-
-    istringstream s(str);
-    unsigned int num = 0;
-    s >> num;
-
-    if (s.fail() || !s.eof())
-    {
-       cerr << sformat(_("Invalid snapshot '%s'."), str.c_str()) << endl;
-       exit(EXIT_FAILURE);
-    }
-
-    Snapshots::iterator snap = snapshots.find(num);
-    if (snap == snapshots.end())
-    {
-       cerr << sformat(_("Snapshot '%u' not found."), num) << endl;
-       exit(EXIT_FAILURE);
-    }
-
-    return snap;
-}
-
-
 unsigned int
 read_num(const string& str)
 {
@@ -77,36 +51,6 @@ read_num(const string& str)
 }
 
 
-pair<unsigned int, unsigned int>
-read_nums(const string& str, const string& delim)
-{
-    string::size_type pos = str.find(delim);
-    if (pos == string::npos)
-    {
-       if (delim == "..")
-       {
-           cerr << _("Missing delimiter '..' between snapshot numbers.") << endl
-                << _("See 'man snapper' for further instructions.") << endl;
-           exit(EXIT_FAILURE);
-       }
-
-       cerr << _("Invalid snapshots.") << endl;
-       exit(EXIT_FAILURE);
-    }
-
-    unsigned int num1 = read_num(str.substr(0, pos));
-    unsigned int num2 = read_num(str.substr(pos + delim.size()));
-
-    if (num1 == num2)
-    {
-       cerr << _("Identical snapshots.") << endl;
-       exit(EXIT_FAILURE);
-    }
-
-    return pair<unsigned int, unsigned int>(num1, num2);
-}
-
-
 map<string, string>
 read_userdata(const string& s, const map<string, string>& old)
 {
index 6280a8e7fa2b47104f3b8a10013f57468ef9de0f..0e2af7e444c268b57670dbc8244af67f45effceb 100644 (file)
@@ -29,15 +29,9 @@ using namespace snapper;
 using namespace std;
 
 
-Snapshots::iterator
-read_num(Snapper* snapper, const string& str);
-
 unsigned int
 read_num(const string& str);
 
-pair<unsigned int, unsigned int>
-read_nums(const string& str, const string& delim = "..");
-
 map<string, string>
 read_userdata(const string& s, const map<string, string>& old = map<string, string>());
 
diff --git a/client/proxy-dbus.cc b/client/proxy-dbus.cc
new file mode 100644 (file)
index 0000000..262fc06
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2016 SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#include "proxy-dbus.h"
+#include "commands.h"
+#include "utils/text.h"
+
+
+using namespace std;
+
+
+ProxySnapshotDbus::ProxySnapshotDbus(ProxySnapshotsDbus* backref, unsigned int num)
+    : backref(backref), num(num)
+{
+    XSnapshot x = command_get_xsnapshot(conn(), configName(), num);
+
+    type = x.type;
+    date = x.date;
+    uid = x.uid;
+    pre_num = x.pre_num;
+    description = x.description;
+    cleanup = x.cleanup;
+    userdata = x.userdata;
+}
+
+
+ProxySnapshotDbus::ProxySnapshotDbus(ProxySnapshotsDbus* backref, SnapshotType type, unsigned int num,
+                                    time_t date, uid_t uid, unsigned int pre_num,
+                                    const string& description, const string& cleanup,
+                                    const map<string, string>& userdata)
+    : backref(backref), type(type), num(num), date(date), uid(uid), pre_num(pre_num),
+      description(description), cleanup(cleanup), userdata(userdata)
+{
+}
+
+
+string
+ProxySnapshotDbus::mountFilesystemSnapshot(bool user_request) const
+{
+    return command_mount_snapshot(conn(), configName(), num, user_request);
+}
+
+
+void
+ProxySnapshotDbus::umountFilesystemSnapshot(bool user_request) const
+{
+    command_umount_snapshot(conn(), configName(), num, user_request);
+}
+
+
+DBus::Connection&
+ProxySnapshotDbus::conn() const
+{
+    return backref->conn();
+}
+
+
+const string&
+ProxySnapshotDbus::configName() const
+{
+    return backref->configName();
+}
+
+
+ProxySnapshotsDbus::ProxySnapshotsDbus(ProxySnapperDbus* backref)
+    : backref(backref)
+{
+    XSnapshots tmp = command_list_xsnapshots(conn(), configName());
+    for (XSnapshots::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
+       proxy_snapshots.push_back(new ProxySnapshotDbus(this, it->getType(), it->getNum(), it->getDate(),
+                                                       it->getUid(), it->getPreNum(), it->getDescription(),
+                                                       it->getCleanup(), it->getUserdata()));
+}
+
+
+DBus::Connection&
+ProxySnapshotsDbus::conn() const
+{
+    return backref->conn();
+}
+
+
+const string&
+ProxySnapshotsDbus::configName() const
+{
+    return backref->config_name;
+}
+
+
+ProxyConfig
+ProxySnapperDbus::getConfig() const
+{
+    XConfigInfo tmp = command_get_xconfig(conn(), config_name);
+
+    return ProxyConfig(tmp.raw);
+}
+
+
+void
+ProxySnapperDbus::setConfig(const ProxyConfig& proxy_config)
+{
+    command_set_xconfig(conn(), config_name, proxy_config.getAllValues());
+}
+
+
+void
+ProxySnapperDbus::setupQuota()
+{
+    command_setup_quota(conn(), config_name);
+}
+
+
+void
+ProxySnapperDbus::prepareQuota() const
+{
+    command_prepare_quota(conn(), config_name);
+}
+
+
+QuotaData
+ProxySnapperDbus::queryQuotaData() const
+{
+    return command_query_quota(conn(), config_name);
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperDbus::createSingleSnapshot(const SCD& scd)
+{
+    unsigned int num = command_create_single_snapshot(conn(), config_name, scd.description,
+                                                     scd.cleanup, scd.userdata);
+
+    proxy_snapshots.emplace_back(new ProxySnapshotDbus(&proxy_snapshots, num));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperDbus::createSingleSnapshot(ProxySnapshots::const_iterator parent, const SCD& scd)
+{
+    unsigned int num = command_create_single_snapshot_v2(conn(), config_name, parent->getNum(),
+                                                        scd.read_only, scd.description, scd.cleanup,
+                                                        scd.userdata);
+
+    proxy_snapshots.emplace_back(new ProxySnapshotDbus(&proxy_snapshots, num));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperDbus::createSingleSnapshotOfDefault(const SCD& scd)
+{
+    unsigned int num = command_create_single_snapshot_of_default(conn(), config_name, scd.read_only,
+                                                                scd.description, scd.cleanup,
+                                                                scd.userdata);
+
+    proxy_snapshots.emplace_back(new ProxySnapshotDbus(&proxy_snapshots, num));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperDbus::createPreSnapshot(const SCD& scd)
+{
+    unsigned int num = command_create_pre_snapshot(conn(), config_name, scd.description,
+                                                  scd.cleanup, scd.userdata);
+
+    proxy_snapshots.emplace_back(new ProxySnapshotDbus(&proxy_snapshots, num));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperDbus::createPostSnapshot(ProxySnapshots::const_iterator pre, const SCD& scd)
+{
+    unsigned int num = command_create_post_snapshot(conn(), config_name, pre->getNum(),
+                                                   scd.description, scd.cleanup, scd.userdata);
+
+    proxy_snapshots.emplace_back(new ProxySnapshotDbus(&proxy_snapshots, num));
+
+    return --proxy_snapshots.end();
+}
+
+
+void
+ProxySnapperDbus::modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd)
+{
+    command_set_snapshot(conn(), config_name, snapshot->getNum(), smd);
+}
+
+
+void
+ProxySnapperDbus::deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose)
+{
+    vector<unsigned int> nums;
+    for (const ProxySnapshots::iterator& proxy_snapshot : snapshots)
+       nums.push_back(proxy_snapshot->getNum());
+
+    command_delete_snapshots(conn(), config_name, nums, verbose);
+
+    ProxySnapshots& proxy_snapshots = getSnapshots();
+    for (ProxySnapshots::iterator& proxy_snapshot : snapshots)
+       proxy_snapshots.erase(proxy_snapshot);
+}
+
+
+ProxyComparison
+ProxySnapperDbus::createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs, bool mount)
+{
+    return ProxyComparison(new ProxyComparisonDbus(this, lhs, rhs, mount));
+}
+
+
+void
+ProxySnapperDbus::syncFilesystem() const
+{
+    command_sync(conn(), config_name);
+}
+
+
+DBus::Connection&
+ProxySnapperDbus::conn() const
+{
+    return backref->conn;
+}
+
+
+void
+ProxySnappersDbus::createConfig(const string& config_name, const string& subvolume,
+                               const string& fstype, const string& template_name)
+{
+    command_create_config(conn, config_name, subvolume, fstype, template_name);
+}
+
+
+void
+ProxySnappersDbus::deleteConfig(const string& config_name)
+{
+    command_delete_config(conn, config_name);
+}
+
+
+ProxySnapper*
+ProxySnappersDbus::getSnapper(const string& config_name)
+{
+    for (unique_ptr<ProxySnapperDbus>& proxy_snapper : proxy_snappers)
+    {
+       if (proxy_snapper->config_name == config_name)
+           return proxy_snapper.get();
+    }
+
+    ProxySnapperDbus* ret = new ProxySnapperDbus(this, config_name);
+    proxy_snappers.emplace_back(ret);
+    return ret;
+}
+
+
+map<string, ProxyConfig>
+ProxySnappersDbus::getConfigs() const
+{
+    map<string, ProxyConfig> ret;
+
+    vector<XConfigInfo> config_infos = command_list_xconfigs(conn);
+    for (XConfigInfo& x : config_infos)
+       ret.emplace(make_pair(x.config_name, x.raw));
+
+    return ret;
+}
+
+
+vector<string>
+ProxySnappersDbus::debug() const
+{
+    return command_debug(conn);
+}
+
+
+ProxyComparisonDbus::ProxyComparisonDbus(ProxySnapperDbus* backref, const ProxySnapshot& lhs,
+                                        const ProxySnapshot& rhs, bool mount)
+    : backref(backref), lhs(lhs), rhs(rhs), files(&file_paths)
+{
+    command_create_comparison(conn(), configName(), lhs.getNum(), rhs.getNum());
+
+    file_paths.system_path = command_get_mount_point(backref->conn(), backref->config_name, 0);
+
+    if (mount)
+    {
+       if (!lhs.isCurrent())
+           file_paths.pre_path = command_mount_snapshot(backref->conn(), backref->config_name,
+                                                        lhs.getNum(), false);
+       else
+           file_paths.pre_path = file_paths.system_path;
+
+       if (!rhs.isCurrent())
+           file_paths.post_path = command_mount_snapshot(backref->conn(), backref->config_name,
+                                                         rhs.getNum(), false);
+       else
+           file_paths.post_path = file_paths.system_path;
+    }
+
+    vector<XFile> tmp1 = command_get_xfiles(backref->conn(), backref->config_name, lhs.getNum(),
+                                           rhs.getNum());
+
+    vector<File> tmp2;
+
+    for (const XFile& xfile : tmp1)
+       tmp2.emplace_back(&file_paths, xfile.name, xfile.status);
+
+    files = Files(&file_paths, tmp2);
+}
+
+
+ProxyComparisonDbus::~ProxyComparisonDbus()
+{
+    command_delete_comparison(conn(), configName(), lhs.getNum(), rhs.getNum());
+}
+
+
+DBus::Connection&
+ProxyComparisonDbus::conn() const
+{
+    return backref->conn();
+}
+
+
+const string&
+ProxyComparisonDbus::configName() const
+{
+    return backref->config_name;
+}
+
+
+ProxySnappers
+ProxySnappers::createDbus()
+{
+    return ProxySnappers(new ProxySnappersDbus());
+}
diff --git a/client/proxy-dbus.h b/client/proxy-dbus.h
new file mode 100644 (file)
index 0000000..0c49771
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2016 SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#ifndef SNAPPER_PROXY_DBUS_H
+#define SNAPPER_PROXY_DBUS_H
+
+
+#include "dbus/DBusMessage.h"
+#include "dbus/DBusConnection.h"
+
+#include "proxy.h"
+
+
+class ProxySnapshotDbus;
+class ProxySnapshotsDbus;
+class ProxySnapperDbus;
+class ProxySnappersDbus;
+
+
+/**
+ * Concrete class of ProxySnapshot for DBus communication. Store all snapshot
+ * data in the client to avoid numerous DBus queries.
+ */
+class ProxySnapshotDbus : public ProxySnapshot::Impl
+{
+
+public:
+
+    ProxySnapshotDbus(ProxySnapshotsDbus* backref, SnapshotType type, unsigned int num,
+                     time_t date, uid_t uid, unsigned int pre_num, const string& description,
+                     const string& cleanup, const map<string, string>& userdata);
+
+    ProxySnapshotDbus(ProxySnapshotsDbus* backref, unsigned int num);
+
+    virtual SnapshotType getType() const override { return type; }
+    virtual unsigned int getNum() const override { return num; }
+    virtual time_t getDate() const override { return date; }
+    virtual uid_t getUid() const override { return uid; }
+    virtual unsigned int getPreNum() const override { return pre_num; }
+    virtual const string& getDescription() const override { return description; }
+    virtual const string& getCleanup() const override { return cleanup; }
+    virtual const map<string, string>& getUserdata() const override { return userdata; }
+
+    virtual bool isCurrent() const override { return num == 0; }
+
+    virtual string mountFilesystemSnapshot(bool user_request) const override;
+    virtual void umountFilesystemSnapshot(bool user_request) const override;
+
+    DBus::Connection& conn() const;
+    const string& configName() const;
+
+private:
+
+    ProxySnapshotsDbus* backref;
+
+    SnapshotType type;
+    unsigned int num;
+    time_t date;
+    uid_t uid;
+    unsigned int pre_num;
+    string description;
+    string cleanup;
+    map<string, string> userdata;
+
+};
+
+
+class ProxySnapshotsDbus : public ProxySnapshots
+{
+
+public:
+
+    ProxySnapshotsDbus(ProxySnapperDbus* backref);
+
+    DBus::Connection& conn() const;
+    const string& configName() const;
+
+private:
+
+    ProxySnapperDbus* backref;
+
+};
+
+
+class ProxySnapperDbus : public ProxySnapper
+{
+
+public:
+
+    ProxySnapperDbus(ProxySnappersDbus* backref, const string& config_name)
+       : backref(backref), config_name(config_name), proxy_snapshots(this)
+    {}
+
+    virtual const string& configName() const override { return config_name; }
+
+    virtual ProxyConfig getConfig() const override;
+    virtual void setConfig(const ProxyConfig& proxy_config) override;
+
+    virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createSingleSnapshot(ProxySnapshots::const_iterator parent,
+                                                               const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createPostSnapshot(ProxySnapshots::const_iterator pre,
+                                                             const SCD& scd) override;
+
+    virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd) override;
+
+    virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose) override;
+
+    virtual ProxyComparison createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs,
+                                            bool mount) override;
+
+    virtual void syncFilesystem() const override;
+
+    virtual ProxySnapshots& getSnapshots() override { return proxy_snapshots; }
+    virtual const ProxySnapshots& getSnapshots() const override { return proxy_snapshots; }
+
+    virtual void setupQuota() override;
+
+    virtual void prepareQuota() const override;
+
+    virtual QuotaData queryQuotaData() const override;
+
+    DBus::Connection& conn() const;
+
+private:
+
+    ProxySnappersDbus* backref;
+
+public:
+
+    string config_name;
+
+    ProxySnapshotsDbus proxy_snapshots;
+
+};
+
+
+class ProxySnappersDbus : public ProxySnappers::Impl
+{
+
+public:
+
+    ProxySnappersDbus()
+       : conn(DBUS_BUS_SYSTEM)
+    {}
+
+    virtual void createConfig(const string& config_name, const string& subvolume,
+                             const string& fstype, const string& template_name) override;
+
+    virtual void deleteConfig(const string& config_name) override;
+
+    virtual ProxySnapper* getSnapper(const string& config_name) override;
+
+    virtual map<string, ProxyConfig> getConfigs() const override;
+
+    virtual vector<string> debug() const override;
+
+    mutable DBus::Connection conn;
+
+    list<std::unique_ptr<ProxySnapperDbus>> proxy_snappers;
+
+};
+
+
+class ProxyComparisonDbus : public ProxyComparison::Impl
+{
+public:
+
+    ProxyComparisonDbus(ProxySnapperDbus* backref, const ProxySnapshot& lhs,
+                       const ProxySnapshot& rhs, bool mount);
+
+    ~ProxyComparisonDbus();
+
+    virtual const Files& getFiles() const override { return files; }
+
+    DBus::Connection& conn() const;
+    const string& configName() const;
+
+private:
+
+    ProxySnapperDbus* backref;
+
+    const ProxySnapshot& lhs;
+    const ProxySnapshot& rhs;
+
+    FilePaths file_paths;
+
+    Files files;
+
+};
+
+
+#endif
diff --git a/client/proxy-lib.cc b/client/proxy-lib.cc
new file mode 100644 (file)
index 0000000..9fd7676
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016 SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#include "proxy-lib.h"
+
+
+using namespace std;
+
+
+ProxyConfig
+ProxySnapperLib::getConfig() const
+{
+    return ProxyConfig(snapper->getConfigInfo().getAllValues());
+}
+
+
+void
+ProxySnapperLib::setConfig(const ProxyConfig& proxy_config)
+{
+    snapper->setConfigInfo(proxy_config.getAllValues());
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperLib::createSingleSnapshot(const SCD& scd)
+{
+    proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshot(scd)));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperLib::createSingleSnapshot(ProxySnapshots::const_iterator parent, const SCD& scd)
+{
+    proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshot(to_lib(*parent).it, scd)));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperLib::createSingleSnapshotOfDefault(const SCD& scd)
+{
+    proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createSingleSnapshotOfDefault(scd)));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperLib::createPreSnapshot(const SCD& scd)
+{
+    proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createPreSnapshot(scd)));
+
+    return --proxy_snapshots.end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapperLib::createPostSnapshot(ProxySnapshots::const_iterator pre, const SCD& scd)
+{
+    proxy_snapshots.emplace_back(new ProxySnapshotLib(snapper->createPostSnapshot(to_lib(*pre).it, scd)));
+
+    return --proxy_snapshots.end();
+}
+
+
+void
+ProxySnapperLib::modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd)
+{
+    snapper->modifySnapshot(to_lib(*snapshot).it, smd);
+}
+
+
+void
+ProxySnapperLib::deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose)
+{
+    for (ProxySnapshots::iterator& snapshot : snapshots)
+       snapper->deleteSnapshot(to_lib(*snapshot).it);
+
+    ProxySnapshots& proxy_snapshots = getSnapshots();
+    for (ProxySnapshots::iterator& proxy_snapshot : snapshots)
+        proxy_snapshots.erase(proxy_snapshot);
+}
+
+
+ProxyComparison
+ProxySnapperLib::createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs, bool mount)
+{
+    return ProxyComparison(new ProxyComparisonLib(this, lhs, rhs, mount));
+}
+
+
+ProxySnapshotsLib::ProxySnapshotsLib(ProxySnapperLib* backref)
+    : backref(backref)
+{
+    Snapshots& tmp = backref->snapper->getSnapshots();
+    for (Snapshots::iterator it = tmp.begin(); it != tmp.end(); ++it)
+       proxy_snapshots.push_back(new ProxySnapshotLib(it));
+}
+
+
+void
+ProxySnappersLib::createConfig(const string& config_name, const string& subvolume,
+                              const string& fstype, const string& template_name)
+{
+    Snapper::createConfig(config_name, target_root, subvolume, fstype, template_name);
+}
+
+
+void
+ProxySnappersLib::deleteConfig(const string& config_name)
+{
+    Snapper::deleteConfig(config_name, target_root);
+}
+
+
+ProxySnapper*
+ProxySnappersLib::getSnapper(const string& config_name)
+{
+    for (unique_ptr<ProxySnapperLib>& proxy_snapper : proxy_snappers)
+    {
+       if (proxy_snapper->snapper->configName() == config_name)
+           return proxy_snapper.get();
+    }
+
+    ProxySnapperLib* ret = new ProxySnapperLib(config_name);
+    proxy_snappers.emplace_back(ret);
+    return ret;
+}
+
+
+map<string, ProxyConfig>
+ProxySnappersLib::getConfigs() const
+{
+    map<string, ProxyConfig> ret;
+
+    list<ConfigInfo> config_infos = Snapper::getConfigs(target_root);
+    for (const ConfigInfo& config_info : config_infos)
+       ret.emplace(make_pair(config_info.getConfigName(), config_info.getAllValues()));
+
+    return ret;
+}
+
+
+ProxyComparisonLib::ProxyComparisonLib(ProxySnapperLib* proxy_snapper, const ProxySnapshot& lhs,
+                                      const ProxySnapshot& rhs, bool mount)
+    : proxy_snapper(proxy_snapper)
+{
+    comparison.reset(new Comparison(proxy_snapper->snapper.get(), to_lib(lhs).it, to_lib(rhs).it,
+                                   mount));
+}
+
+
+ProxySnappers
+ProxySnappers::createLib(const string& target_root)
+{
+    return ProxySnappers(new ProxySnappersLib(target_root));
+}
+
+
+const ProxySnapshotLib&
+to_lib(const ProxySnapshot& proxy_snapshot)
+{
+    return dynamic_cast<const ProxySnapshotLib&>(proxy_snapshot.get_impl());
+}
diff --git a/client/proxy-lib.h b/client/proxy-lib.h
new file mode 100644 (file)
index 0000000..c8f13e7
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2016 SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#ifndef SNAPPER_PROXY_LIB_H
+#define SNAPPER_PROXY_LIB_H
+
+
+#include "proxy.h"
+
+#include <snapper/Snapper.h>
+#include <snapper/Comparison.h>
+
+
+class ProxySnapshotLib : public ProxySnapshot::Impl
+{
+
+public:
+
+    ProxySnapshotLib(Snapshots::iterator it)
+       : it(it)
+    {}
+
+    virtual SnapshotType getType() const override { return it->getType(); }
+    virtual unsigned int getNum() const override { return it->getNum(); }
+    virtual time_t getDate() const override { return it->getDate(); }
+    virtual uid_t getUid() const override { return it->getUid(); }
+    virtual unsigned int getPreNum() const override { return it->getPreNum(); }
+    virtual const string& getDescription() const override { return it->getDescription(); }
+    virtual const string& getCleanup() const override { return it->getCleanup(); }
+    virtual const map<string, string>& getUserdata() const override { return it->getUserdata(); }
+
+    virtual bool isCurrent() const override { return it->isCurrent(); }
+
+    virtual string mountFilesystemSnapshot(bool user_request) const override
+    {
+       it->mountFilesystemSnapshot(user_request);
+       return it->snapshotDir();
+    }
+
+    virtual void umountFilesystemSnapshot(bool user_request) const override
+    {
+       it->umountFilesystemSnapshot(user_request);
+    }
+
+    Snapshots::iterator it;
+
+};
+
+
+class ProxySnapperLib;
+
+
+class ProxySnapshotsLib : public ProxySnapshots
+{
+
+public:
+
+    ProxySnapshotsLib(ProxySnapperLib* backref);
+
+    ProxySnapperLib* backref;
+
+};
+
+
+class ProxySnapperLib : public ProxySnapper
+{
+
+public:
+
+    ProxySnapperLib(const string& config_name)
+       : snapper(new Snapper(config_name, "/")), proxy_snapshots(this)
+    {}
+
+    virtual const string& configName() const override { return snapper->configName(); }
+
+    virtual ProxyConfig getConfig() const override;
+    virtual void setConfig(const ProxyConfig& proxy_config) override;
+
+    virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createSingleSnapshot(ProxySnapshots::const_iterator parent,
+                                                               const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd) override;
+    virtual ProxySnapshots::const_iterator createPostSnapshot(ProxySnapshots::const_iterator pre,
+                                                             const SCD& scd) override;
+
+    virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd) override;
+
+    virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose) override;
+
+    virtual ProxyComparison createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs,
+                                            bool mount) override;
+
+    virtual void syncFilesystem() const override { snapper->syncFilesystem(); }
+
+    virtual ProxySnapshots& getSnapshots() override { return proxy_snapshots; }
+    virtual const ProxySnapshots& getSnapshots() const override { return proxy_snapshots; }
+
+    virtual void setupQuota() override { snapper->setupQuota(); }
+
+    virtual void prepareQuota() const override { snapper->prepareQuota(); }
+
+    virtual QuotaData queryQuotaData() const override { return snapper->queryQuotaData(); }
+
+    std::unique_ptr<Snapper> snapper;
+
+private:
+
+    ProxySnapshotsLib proxy_snapshots;
+
+};
+
+
+class ProxySnappersLib : public ProxySnappers::Impl
+{
+
+public:
+
+    ProxySnappersLib(const string& target_root)
+       : target_root(target_root)
+    {}
+
+    virtual void createConfig(const string& config_name, const string& subvolume,
+                             const string& fstype, const string& template_name) override;
+
+    virtual void deleteConfig(const string& config_name) override;
+
+    virtual ProxySnapper* getSnapper(const string& config_name) override;
+
+    virtual map<string, ProxyConfig> getConfigs() const override;
+
+    virtual vector<string> debug() const { return Snapper::debug(); }
+
+private:
+
+    const string target_root;
+
+    list<std::unique_ptr<ProxySnapperLib>> proxy_snappers;
+
+};
+
+
+class ProxyComparisonLib : public ProxyComparison::Impl
+{
+
+public:
+
+    ProxyComparisonLib(ProxySnapperLib* proxy_snapper, const ProxySnapshot& lhs,
+                      const ProxySnapshot& rhs, bool mount);
+
+    virtual const Files& getFiles() const override { return comparison->getFiles(); }
+
+    ProxySnapper* proxy_snapper;
+
+private:
+
+    std::unique_ptr<Comparison> comparison;
+
+};
+
+
+const ProxySnapshotLib&
+to_lib(const ProxySnapshot& proxy_snapshot);
+
+
+#endif
diff --git a/client/proxy.cc b/client/proxy.cc
new file mode 100644 (file)
index 0000000..e94a028
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016 SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#include <sstream>
+#include <iostream>
+#include <algorithm>
+
+#include <snapper/AppUtil.h>
+#include <snapper/SnapperDefines.h>
+
+#include "utils/text.h"
+#include "proxy.h"
+
+
+using namespace std;
+
+
+string
+ProxyConfig::getSubvolume() const
+{
+    string subvolume;
+    getValue(KEY_SUBVOLUME, subvolume);
+    return subvolume;
+}
+
+
+bool
+ProxyConfig::getValue(const string& key, string& value) const
+{
+    map<string, string>::const_iterator it = values.find(key);
+    if (it == values.end())
+       return false;
+
+    value = it->second;
+    return true;
+}
+
+
+ProxySnapshots::iterator
+ProxySnapshots::find(unsigned int num)
+{
+    return find_if(proxy_snapshots.begin(), proxy_snapshots.end(),
+                  [num](const ProxySnapshot& x) { return x.getNum() == num; });
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapshots::find(unsigned int num) const
+{
+    return find_if(proxy_snapshots.begin(), proxy_snapshots.end(),
+                  [num](const ProxySnapshot& x) { return x.getNum() == num; });
+}
+
+
+ProxySnapshots::iterator
+ProxySnapshots::findNum(const string& str)
+{
+    istringstream s(str);
+    unsigned int num = 0;
+    s >> num;
+
+    if (s.fail() || !s.eof())
+    {
+       cerr << sformat(_("Invalid snapshot '%s'."), str.c_str()) << endl;
+       exit(EXIT_FAILURE);
+    }
+
+    iterator ret = find(num);
+    if (ret == proxy_snapshots.end())
+    {
+       cerr << sformat(_("Snapshot '%u' not found."), num) << endl;
+       exit(EXIT_FAILURE);
+    }
+
+    return ret;
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapshots::findNum(const string& str) const
+{
+    istringstream s(str);
+    unsigned int num = 0;
+    s >> num;
+
+    if (s.fail() || !s.eof())
+    {
+       cerr << sformat(_("Invalid snapshot '%s'."), str.c_str()) << endl;
+       exit(EXIT_FAILURE);
+    }
+
+    const_iterator ret = find(num);
+    if (ret == proxy_snapshots.end())
+    {
+       cerr << sformat(_("Snapshot '%u' not found."), num) << endl;
+       exit(EXIT_FAILURE);
+    }
+
+    return ret;
+}
+
+
+pair<ProxySnapshots::iterator, ProxySnapshots::iterator>
+ProxySnapshots::findNums(const string& str, const string& delim)
+{
+    string::size_type pos = str.find(delim);
+    if (pos == string::npos)
+    {
+       if (delim == "..")
+       {
+           cerr << _("Missing delimiter '..' between snapshot numbers.") << endl
+                << _("See 'man snapper' for further instructions.") << endl;
+           exit(EXIT_FAILURE);
+       }
+
+       cerr << _("Invalid snapshots.") << endl;
+       exit(EXIT_FAILURE);
+    }
+
+    ProxySnapshots::iterator num1 = findNum(str.substr(0, pos));
+    ProxySnapshots::iterator num2 = findNum(str.substr(pos + delim.size()));
+
+    if (num1->getNum() == num2->getNum())
+    {
+       cerr << _("Identical snapshots.") << endl;
+       exit(EXIT_FAILURE);
+    }
+
+    return make_pair(num1, num2);
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapshots::findPre(const_iterator post) const
+{
+    for (const_iterator it = begin(); it != end(); ++it)
+    {
+       if (it->getType() == PRE && it->getNum() == post->getPreNum())
+           return it;
+    }
+
+    return end();
+}
+
+
+ProxySnapshots::iterator
+ProxySnapshots::findPost(iterator pre)
+{
+    for (iterator it = begin(); it != end(); ++it)
+    {
+       if (it->getType() == POST && it->getPreNum() == pre->getNum())
+           return it;
+    }
+
+    return end();
+}
+
+
+ProxySnapshots::const_iterator
+ProxySnapshots::findPost(const_iterator pre) const
+{
+    for (const_iterator it = begin(); it != end(); ++it)
+    {
+       if (it->getType() == POST && it->getPreNum() == pre->getNum())
+           return it;
+    }
+
+    return end();
+}
diff --git a/client/proxy.h b/client/proxy.h
new file mode 100644 (file)
index 0000000..d851af6
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2016 SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact Novell, Inc.
+ *
+ * To contact Novell about this file by physical or electronic mail, you may
+ * find current contact information at www.novell.com.
+ */
+
+
+#ifndef SNAPPER_PROXY_H
+#define SNAPPER_PROXY_H
+
+
+#include <memory>
+#include <vector>
+#include <list>
+#include <map>
+
+#include <snapper/Snapshot.h>
+#include <snapper/Snapper.h>
+#include <snapper/File.h>
+
+
+using namespace snapper;
+
+
+/**
+ * The proxy classes here allow clients, so far only the snapper command line
+ * interface, to work with and without DBus in a transparent way by providing
+ * the same interface in both cases.
+ *
+ * The main idea for providing the same interface is to have an abstract
+ * class, e.g. ProxySnapper, and two concrete implementation ProxySnapperDbus
+ * and ProxySnapperLib. This is done for ProxySnapshots, ProxySnapper and
+ * ProxySnappers.
+ *
+ * For ProxySnapshot the implementation is more complicated since
+ * ProxySnapshots provides an interface to list<ProxySnapshot> and thus
+ * polymorphism does not work. Instead ProxySnapshot has an implementation
+ * pointer (pimpl idiom) which ensures polymorphism. Another possibility would
+ * be to provide an interface to list<ProxySnapshot*> in ProxySnapshots but
+ * that is less intuitive to use.
+ *
+ * All objects are stored in containers or smart pointers to avoid manual
+ * cleanup.
+ *
+ * The interface copycats the classes Snapshot, Snapshots and Snapper of
+ * libsnapper. For consistency one may add a Snappers class to libsnapper.
+ *
+ * Limitations: The classes are tailored for the snapper command line
+ * interface. Other use-cases are not supported.
+ */
+
+
+// TODO maybe unique error handling, e.g. catch dbus exceptions and throw
+// snapper or new exceptions
+
+
+class ProxyConfig
+{
+
+public:
+
+    ProxyConfig(const map<string, string>& values) : values(values) {}
+
+    const map<string, string>& getAllValues() const { return values; }
+
+    string getSubvolume() const;
+
+    bool getValue(const string& key, string& value) const;
+
+private:
+
+    map<string, string> values;
+
+};
+
+
+class ProxySnapshot
+{
+
+public:
+
+    SnapshotType getType() const { return impl->getType(); }
+    unsigned int getNum() const { return impl->getNum(); }
+    time_t getDate() const { return impl->getDate(); }
+    uid_t getUid() const { return impl->getUid(); }
+    unsigned int getPreNum() const { return impl->getPreNum(); }
+    const string& getDescription() const { return impl->getDescription(); }
+    const string& getCleanup() const { return impl->getCleanup(); }
+    const map<string, string>& getUserdata() const { return impl->getUserdata(); }
+
+    bool isCurrent() const { return impl->isCurrent(); }
+
+    void mountFilesystemSnapshot(bool user_request) const
+       { impl->mountFilesystemSnapshot(user_request); }
+
+    void umountFilesystemSnapshot(bool user_request) const
+       { impl->umountFilesystemSnapshot(user_request); }
+
+public:
+
+    class Impl
+    {
+
+    public:
+
+       virtual ~Impl() {}
+
+       virtual SnapshotType getType() const = 0;
+       virtual unsigned int getNum() const = 0;
+       virtual time_t getDate() const = 0;
+       virtual uid_t getUid() const = 0;
+       virtual unsigned int getPreNum() const = 0;
+       virtual const string& getDescription() const = 0;
+       virtual const string& getCleanup() const = 0;
+       virtual const map<string, string>& getUserdata() const = 0;
+
+       virtual bool isCurrent() const = 0;
+
+       virtual string mountFilesystemSnapshot(bool user_request) const = 0;
+       virtual void umountFilesystemSnapshot(bool user_request) const = 0;
+
+    };
+
+    ProxySnapshot(Impl* impl) : impl(impl) {}
+
+    Impl& get_impl() { return *impl; }
+    const Impl& get_impl() const { return *impl; }
+
+private:
+
+    std::unique_ptr<Impl> impl;
+
+};
+
+
+class ProxySnapshots
+{
+
+public:
+
+    virtual ~ProxySnapshots() {}
+
+    typedef list<ProxySnapshot>::iterator iterator;
+    typedef list<ProxySnapshot>::const_iterator const_iterator;
+
+    iterator begin() { return proxy_snapshots.begin(); }
+    const_iterator begin() const { return proxy_snapshots.begin(); }
+
+    iterator end() { return proxy_snapshots.end(); }
+    const_iterator end() const { return proxy_snapshots.end(); }
+
+    const_iterator getCurrent() const { return proxy_snapshots.begin(); }
+
+    iterator find(unsigned int i);
+    const_iterator find(unsigned int i) const;
+
+    iterator findNum(const string& str);
+    const_iterator findNum(const string& str) const;
+
+    std::pair<iterator, iterator> findNums(const string& str, const string& delim = "..");
+
+    const_iterator findPre(const_iterator post) const;
+
+    iterator findPost(iterator pre);
+    const_iterator findPost(const_iterator pre) const;
+
+    void emplace_back(ProxySnapshot::Impl* value) { proxy_snapshots.emplace_back(value); }
+
+    void erase(iterator it) { proxy_snapshots.erase(it); }
+
+protected:
+
+    list<ProxySnapshot> proxy_snapshots;
+
+};
+
+
+class ProxyComparison;
+
+
+class ProxySnapper
+{
+
+public:
+
+    virtual ~ProxySnapper() {}
+
+    virtual const string& configName() const = 0;
+
+    virtual ProxyConfig getConfig() const = 0;
+    virtual void setConfig(const ProxyConfig& proxy_config) = 0;
+
+    virtual ProxySnapshots::const_iterator createSingleSnapshot(const SCD& scd) = 0;
+    virtual ProxySnapshots::const_iterator createSingleSnapshot(ProxySnapshots::const_iterator parent,
+                                                               const SCD& scd) = 0;
+    virtual ProxySnapshots::const_iterator createSingleSnapshotOfDefault(const SCD& scd) = 0;
+    virtual ProxySnapshots::const_iterator createPreSnapshot(const SCD& scd) = 0;
+    virtual ProxySnapshots::const_iterator createPostSnapshot(ProxySnapshots::const_iterator pre,
+                                                             const SCD& scd) = 0;
+
+    virtual void modifySnapshot(ProxySnapshots::iterator snapshot, const SMD& smd) = 0;
+
+    virtual void deleteSnapshots(vector<ProxySnapshots::iterator> snapshots, bool verbose) = 0;
+
+    virtual ProxyComparison createComparison(const ProxySnapshot& lhs, const ProxySnapshot& rhs,
+                                            bool mount) = 0;
+
+    virtual void syncFilesystem() const = 0;
+
+    virtual ProxySnapshots& getSnapshots() = 0;
+    virtual const ProxySnapshots& getSnapshots() const = 0;
+
+    virtual void setupQuota() = 0;
+
+    virtual void prepareQuota() const = 0;
+
+    virtual QuotaData queryQuotaData() const = 0;
+
+};
+
+
+class ProxySnappers
+{
+
+public:
+
+    static ProxySnappers createDbus();
+    static ProxySnappers createLib(const string& target_root);
+
+    void createConfig(const string& config_name, const string& subvolume, const string& fstype,
+                     const string& template_name)
+       { return impl->createConfig(config_name, subvolume, fstype, template_name); }
+
+    void deleteConfig(const string& config_name)
+       { return impl->deleteConfig(config_name); }
+
+    ProxySnapper* getSnapper(const string& config_name)
+       { return impl->getSnapper(config_name); }
+
+    map<string, ProxyConfig> getConfigs() const
+       { return impl->getConfigs(); }
+
+    vector<string> debug() const
+       { return impl->debug(); }
+
+public:
+
+    class Impl
+    {
+
+    public:
+
+       virtual ~Impl() {}
+
+       virtual void createConfig(const string& config_name, const string& subvolume,
+                                 const string& fstype, const string& template_name) = 0;
+
+       virtual void deleteConfig(const string& config_name) = 0;
+
+       virtual ProxySnapper* getSnapper(const string& config_name) = 0;
+
+       virtual map<string, ProxyConfig> getConfigs() const = 0;
+
+       virtual vector<string> debug() const = 0;
+
+    };
+
+    ProxySnappers(Impl* impl) : impl(impl) {}
+
+    Impl& get_impl() { return *impl; }
+    const Impl& get_impl() const { return *impl; }
+
+private:
+
+    std::unique_ptr<Impl> impl;
+
+};
+
+
+class ProxyComparison
+{
+
+public:
+
+    const Files& getFiles() const { return impl->getFiles(); }
+
+public:
+
+    class Impl
+    {
+
+    public:
+
+       virtual ~Impl() {}
+
+       virtual const Files& getFiles() const = 0;
+
+    };
+
+    ProxyComparison(Impl* impl) : impl(impl) {}
+
+    Impl& get_impl() { return *impl; }
+    const Impl& get_impl() const { return *impl; }
+
+private:
+
+    std::unique_ptr<Impl> impl;
+
+};
+
+
+#endif
index c3df0728874538584b5096c52cbd8e1ac47c83ee..28ae9d60878c62b294cca9fe0fe144022a4df4de 100644 (file)
@@ -46,9 +46,9 @@
 #include "utils/Table.h"
 #include "utils/GetOpts.h"
 
-#include "commands.h"
 #include "cleanup.h"
 #include "errors.h"
+#include "proxy.h"
 #include "misc.h"
 
 
@@ -58,29 +58,28 @@ using namespace std;
 
 struct Cmd
 {
-    typedef void (*cmd_func_t)(DBus::Connection* conn, Snapper* snapper);
+    typedef void (*cmd_func_t)(ProxySnappers* snappers, ProxySnapper* snapper);
     typedef void (*help_func_t)();
 
-    Cmd(const string& name, cmd_func_t cmd_func, help_func_t help_func,
-       bool works_without_dbus, bool needs_snapper)
-       : name(name), cmd_func(cmd_func), help_func(help_func),
-         works_without_dbus(works_without_dbus), needs_snapper(needs_snapper)
+    Cmd(const string& name, cmd_func_t cmd_func, help_func_t help_func, bool needs_snapper)
+       : name(name), aliases(), cmd_func(cmd_func), help_func(help_func),
+         needs_snapper(needs_snapper)
     {}
 
     Cmd(const string& name, const vector<string>& aliases, cmd_func_t cmd_func,
-       help_func_t help_func, bool works_without_dbus, bool needs_snapper)
+       help_func_t help_func, bool needs_snapper)
        : name(name), aliases(aliases), cmd_func(cmd_func), help_func(help_func),
-         works_without_dbus(works_without_dbus), needs_snapper(needs_snapper)
+         needs_snapper(needs_snapper)
     {}
 
     const string name;
     const vector<string> aliases;
     const cmd_func_t cmd_func;
     const help_func_t help_func;
-    const bool works_without_dbus;
     const bool needs_snapper;
 };
 
+
 GetOpts getopts;
 
 bool quiet = false;
@@ -94,10 +93,8 @@ string target_root = "/";
 
 struct MyFiles : public Files
 {
-    friend struct MyComparison;
 
-    MyFiles(const FilePaths* file_paths)
-       : Files(file_paths) {}
+    MyFiles(const Files& files) : Files(files) {}
 
     void bulk_process(FILE* file, std::function<void(File& file)> callback);
 
@@ -166,39 +163,6 @@ MyFiles::bulk_process(FILE* file, std::function<void(File& file)> callback)
 }
 
 
-struct MyComparison
-{
-    MyComparison(DBus::Connection& conn, pair<unsigned int, unsigned int> nums, bool mount)
-       : files(&file_paths)
-    {
-       command_create_xcomparison(conn, config_name, nums.first, nums.second);
-
-       file_paths.system_path = command_get_xmount_point(conn, config_name, 0);
-
-       if (mount)
-       {
-           if (nums.first != 0)
-               file_paths.pre_path = command_mount_xsnapshots(conn, config_name, nums.first, false);
-           else
-               file_paths.pre_path = file_paths.system_path;
-
-           if (nums.second != 0)
-               file_paths.post_path = command_mount_xsnapshots(conn, config_name, nums.second, false);
-           else
-               file_paths.post_path = file_paths.system_path;
-       }
-
-       list<XFile> tmp = command_get_xfiles(conn, config_name, nums.first, nums.second);
-       for (list<XFile>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
-           files.push_back(File(&file_paths, it->name, it->status));
-    }
-
-    FilePaths file_paths;
-
-    MyFiles files;
-};
-
-
 void
 help_list_configs()
 {
@@ -208,34 +172,8 @@ help_list_configs()
 }
 
 
-list<pair<string, string>>
-enum_configs(DBus::Connection* conn)
-{
-    list<pair<string, string>> configs;
-
-    if (no_dbus)
-    {
-       list<ConfigInfo> config_infos = Snapper::getConfigs(target_root);
-       for (list<ConfigInfo>::const_iterator it = config_infos.begin(); it != config_infos.end(); ++it)
-       {
-           configs.push_back(make_pair(it->getConfigName(), it->getSubvolume()));
-       }
-    }
-    else
-    {
-       list<XConfigInfo> config_infos = command_list_xconfigs(*conn);
-       for (list<XConfigInfo>::const_iterator it = config_infos.begin(); it != config_infos.end(); ++it)
-       {
-           configs.push_back(make_pair(it->config_name, it->subvolume));
-       }
-    }
-
-    return configs;
-}
-
-
 void
-command_list_configs(DBus::Connection* conn, Snapper* snapper)
+command_list_configs(ProxySnappers* snappers, ProxySnapper*)
 {
     getopts.parse("list-configs", GetOpts::no_options);
     if (getopts.hasArgs())
@@ -251,13 +189,12 @@ command_list_configs(DBus::Connection* conn, Snapper* snapper)
     header.add(_("Subvolume"));
     table.setHeader(header);
 
-    list<pair<string, string> > configs = enum_configs(conn);
-
-    for (list<pair<string,string> >::iterator it = configs.begin(); it != configs.end(); ++it)
+    map<string, ProxyConfig> configs = snappers->getConfigs();
+    for (const map<string, ProxyConfig>::value_type value : configs)
     {
        TableRow row;
-       row.add(it->first);
-       row.add(it->second);
+       row.add(value.first);
+       row.add(value.second.getSubvolume());
        table.add(row);
     }
 
@@ -279,7 +216,7 @@ help_create_config()
 
 
 void
-command_create_config(DBus::Connection* conn, Snapper* snapper)
+command_create_config(ProxySnappers* snappers, ProxySnapper*)
 {
     const struct option options[] = {
        { "fstype",             required_argument,      0,      'f' },
@@ -318,14 +255,7 @@ command_create_config(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
-    if (no_dbus)
-    {
-       Snapper::createConfig(config_name, target_root, subvolume, fstype, template_name);
-    }
-    else
-    {
-       command_create_xconfig(*conn, config_name, subvolume, fstype, template_name);
-    }
+    snappers->createConfig(config_name, subvolume, fstype, template_name);
 }
 
 
@@ -339,7 +269,7 @@ help_delete_config()
 
 
 void
-command_delete_config(DBus::Connection* conn, Snapper* snapper)
+command_delete_config(ProxySnappers* snappers, ProxySnapper*)
 {
     getopts.parse("delete-config", GetOpts::no_options);
     if (getopts.hasArgs())
@@ -348,14 +278,7 @@ command_delete_config(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
-    if (no_dbus)
-    {
-       Snapper::deleteConfig(config_name, target_root);
-    }
-    else
-    {
-       command_delete_xconfig(*conn, config_name);
-    }
+    snappers->deleteConfig(config_name);
 }
 
 
@@ -369,7 +292,7 @@ help_get_config()
 
 
 void
-command_get_config(DBus::Connection* conn, Snapper* snapper)
+command_get_config(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     getopts.parse("get-config", GetOpts::no_options);
     if (getopts.hasArgs())
@@ -385,30 +308,13 @@ command_get_config(DBus::Connection* conn, Snapper* snapper)
     header.add(_("Value"));
     table.setHeader(header);
 
-    if (no_dbus)
-    {
-       ConfigInfo config_info = Snapper::getConfig(config_name, target_root);
-       map<string, string> raw = config_info.getAllValues();
-
-       for (map<string, string>::const_iterator it = raw.begin(); it != raw.end(); ++it)
-       {
-           TableRow row;
-           row.add(it->first);
-           row.add(it->second);
-           table.add(row);
-       }
-    }
-    else
+    ProxyConfig config = snapper->getConfig();
+    for (const map<string, string>::value_type& value : config.getAllValues())
     {
-       XConfigInfo ci = command_get_xconfig(*conn, config_name);
-
-       for (map<string, string>::const_iterator it = ci.raw.begin(); it != ci.raw.end(); ++it)
-       {
-           TableRow row;
-           row.add(it->first);
-           row.add(it->second);
-           table.add(row);
-       }
+       TableRow row;
+       row.add(value.first);
+       row.add(value.second);
+       table.add(row);
     }
 
     cout << table;
@@ -425,7 +331,7 @@ help_set_config()
 
 
 void
-command_set_config(DBus::Connection* conn, Snapper* snapper)
+command_set_config(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     getopts.parse("set-config", GetOpts::no_options);
     if (!getopts.hasArgs())
@@ -434,16 +340,9 @@ command_set_config(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
-    map<string, string> raw = read_configdata(getopts.getArgs());
+    ProxyConfig config(read_configdata(getopts.getArgs()));
 
-    if (no_dbus)
-    {
-       snapper->setConfigInfo(raw);
-    }
-    else
-    {
-       command_set_xconfig(*conn, config_name, raw);
-    }
+    snapper->setConfig(config);
 }
 
 
@@ -461,10 +360,13 @@ help_list()
 
 enum ListMode { LM_ALL, LM_SINGLE, LM_PRE_POST };
 
-void list_from_one_config(DBus::Connection* conn, Snapper* snapper, string config_name, ListMode list_mode);
 
 void
-command_list(DBus::Connection* conn, Snapper* snapper)
+list_from_one_config(ProxySnapper* snapper, ListMode list_mode);
+
+
+void
+command_list(ProxySnappers* snappers, ProxySnapper*)
 {
     const struct option options[] = {
        { "type",               required_argument,      0,      't' },
@@ -498,28 +400,39 @@ command_list(DBus::Connection* conn, Snapper* snapper)
        }
     }
 
-    list<pair<string, string> > configs;
-    if ((opt = opts.find("all-configs")) != opts.end())
+    vector<string> tmp;
+
+    if ((opt = opts.find("all-configs")) == opts.end())
     {
-       configs = enum_configs(conn);
+        tmp.push_back(config_name);
     }
     else
     {
-       configs.push_back(make_pair(config_name, ""));
+        map<string, ProxyConfig> configs = snappers->getConfigs();
+        for (map<string, ProxyConfig>::value_type it : configs)
+            tmp.push_back(it.first);
     }
 
-    for (list<pair<string,string> >::iterator it = configs.begin(); it != configs.end(); ++it)
+    for (vector<string>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
     {
-       if (it != configs.begin())
-           cout << endl;
+       ProxySnapper* snapper = snappers->getSnapper(*it);
 
-       if (configs.size() > 1)
-           cout << "Config: " << it->first << ", subvolume: " << it->second << endl;
-       list_from_one_config(conn, snapper, it->first, list_mode);
+        if (it != tmp.begin())
+            cout << endl;
+
+        if (tmp.size() > 1)
+        {
+            cout << "Config: " << snapper->configName() << ", subvolume: "
+                 << snapper->getConfig().getSubvolume() << endl;
+        }
+
+        list_from_one_config(snapper, list_mode);
     }
 }
 
-void list_from_one_config(DBus::Connection* conn, Snapper* snapper, string config_name, ListMode list_mode)
+
+void
+list_from_one_config(ProxySnapper* snapper, ListMode list_mode)
 {
     Table table;
 
@@ -538,39 +451,19 @@ void list_from_one_config(DBus::Connection* conn, Snapper* snapper, string confi
            header.add(_("Userdata"));
            table.setHeader(header);
 
-           if (no_dbus)
-           {
-               const Snapshots& snapshots = snapper->getSnapshots();
-               for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
-               {
-                   TableRow row;
-                   row.add(toString(it1->getType()));
-                   row.add(decString(it1->getNum()));
-                   row.add(it1->getType() == POST ? decString(it1->getPreNum()) : "");
-                   row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), utc, iso));
-                   row.add(username(it1->getUid()));
-                   row.add(it1->getCleanup());
-                   row.add(it1->getDescription());
-                   row.add(show_userdata(it1->getUserdata()));
-                   table.add(row);
-               }
-           }
-           else
+           const ProxySnapshots& snapshots = snapper->getSnapshots();
+           for (const ProxySnapshot& snapshot : snapshots)
            {
-               XSnapshots snapshots = command_list_xsnapshots(*conn, config_name);
-               for (XSnapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
-               {
-                   TableRow row;
-                   row.add(toString(it1->getType()));
-                   row.add(decString(it1->getNum()));
-                   row.add(it1->getType() == POST ? decString(it1->getPreNum()) : "");
-                   row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), utc, iso));
-                   row.add(username(it1->getUid()));
-                   row.add(it1->getCleanup());
-                   row.add(it1->getDescription());
-                   row.add(show_userdata(it1->getUserdata()));
-                   table.add(row);
-               }
+               TableRow row;
+               row.add(toString(snapshot.getType()));
+               row.add(decString(snapshot.getNum()));
+               row.add(snapshot.getType() == POST ? decString(snapshot.getPreNum()) : "");
+               row.add(snapshot.isCurrent() ? "" : datetime(snapshot.getDate(), utc, iso));
+               row.add(username(snapshot.getUid()));
+               row.add(snapshot.getCleanup());
+               row.add(snapshot.getDescription());
+               row.add(show_userdata(snapshot.getUserdata()));
+               table.add(row);
            }
        }
        break;
@@ -585,39 +478,19 @@ void list_from_one_config(DBus::Connection* conn, Snapper* snapper, string confi
            header.add(_("Userdata"));
            table.setHeader(header);
 
-           if (no_dbus)
+           const ProxySnapshots& snapshots = snapper->getSnapshots();
+           for (const ProxySnapshot& snapshot : snapshots)
            {
-               const Snapshots& snapshots = snapper->getSnapshots();
-               for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
-               {
-                   if (it1->getType() != SINGLE)
-                       continue;
-
-                   TableRow row;
-                   row.add(decString(it1->getNum()));
-                   row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), utc, iso));
-                   row.add(username(it1->getUid()));
-                   row.add(it1->getDescription());
-                   row.add(show_userdata(it1->getUserdata()));
-                   table.add(row);
-               }
-           }
-           else
-           {
-               XSnapshots snapshots = command_list_xsnapshots(*conn, config_name);
-               for (XSnapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
-               {
-                   if (it1->getType() != SINGLE)
-                       continue;
-
-                   TableRow row;
-                   row.add(decString(it1->getNum()));
-                   row.add(it1->isCurrent() ? "" : datetime(it1->getDate(), utc, iso));
-                   row.add(username(it1->getUid()));
-                   row.add(it1->getDescription());
-                   row.add(show_userdata(it1->getUserdata()));
-                   table.add(row);
-               }
+               if (snapshot.getType() != SINGLE)
+                   continue;
+
+               TableRow row;
+               row.add(decString(snapshot.getNum()));
+               row.add(snapshot.isCurrent() ? "" : datetime(snapshot.getDate(), utc, iso));
+               row.add(username(snapshot.getUid()));
+               row.add(snapshot.getDescription());
+               row.add(show_userdata(snapshot.getUserdata()));
+               table.add(row);
            }
        }
        break;
@@ -633,49 +506,27 @@ void list_from_one_config(DBus::Connection* conn, Snapper* snapper, string confi
            header.add(_("Userdata"));
            table.setHeader(header);
 
-           if (no_dbus)
+           const ProxySnapshots& snapshots = snapper->getSnapshots();
+           for (ProxySnapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
            {
-               const Snapshots& snapshots = snapper->getSnapshots();
-               for (Snapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
-               {
-                   if (it1->getType() != PRE)
-                       continue;
-
-                   Snapshots::const_iterator it2 = snapshots.findPost(it1);
-                   if (it2 == snapshots.end())
-                       continue;
-
-                   TableRow row;
-                   row.add(decString(it1->getNum()));
-                   row.add(decString(it2->getNum()));
-                   row.add(datetime(it1->getDate(), utc, iso));
-                   row.add(datetime(it2->getDate(), utc, iso));
-                   row.add(it1->getDescription());
-                   row.add(show_userdata(it1->getUserdata()));
-                   table.add(row);
-               }
-           }
-           else
-           {
-               XSnapshots snapshots = command_list_xsnapshots(*conn, config_name);
-               for (XSnapshots::const_iterator it1 = snapshots.begin(); it1 != snapshots.end(); ++it1)
-               {
-                   if (it1->getType() != PRE)
-                       continue;
-
-                   XSnapshots::const_iterator it2 = snapshots.findPost(it1);
-                   if (it2 == snapshots.end())
-                       continue;
-
-                   TableRow row;
-                   row.add(decString(it1->getNum()));
-                   row.add(decString(it2->getNum()));
-                   row.add(datetime(it1->getDate(), utc, iso));
-                   row.add(datetime(it2->getDate(), utc, iso));
-                   row.add(it1->getDescription());
-                   row.add(show_userdata(it1->getUserdata()));
-                   table.add(row);
-               }
+               if (it1->getType() != PRE)
+                   continue;
+
+               ProxySnapshots::const_iterator it2 = snapshots.findPost(it1);
+               if (it2 == snapshots.end())
+                   continue;
+
+               const ProxySnapshot& pre = *it1;
+               const ProxySnapshot& post = *it2;
+
+               TableRow row;
+               row.add(decString(pre.getNum()));
+               row.add(decString(post.getNum()));
+               row.add(datetime(pre.getDate(), utc, iso));
+               row.add(datetime(post.getDate(), utc, iso));
+               row.add(pre.getDescription());
+               row.add(show_userdata(pre.getUserdata()));
+               table.add(row);
            }
        }
        break;
@@ -704,7 +555,7 @@ help_create()
 
 
 void
-command_create(DBus::Connection* conn, Snapper* snapper)
+command_create(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     const struct option options[] = {
        { "type",               required_argument,      0,      't' },
@@ -726,12 +577,13 @@ command_create(DBus::Connection* conn, Snapper* snapper)
 
     enum CreateType { CT_SINGLE, CT_PRE, CT_POST, CT_PRE_POST };
 
+    const ProxySnapshots& snapshots = snapper->getSnapshots();
+
     CreateType type = CT_SINGLE;
-    unsigned int num1 = 0;
+    ProxySnapshots::const_iterator snapshot1 = snapshots.end();
+    ProxySnapshots::const_iterator snapshot2 = snapshots.end();
     bool print_number = false;
-    string description;
-    string cleanup;
-    map<string, string> userdata;
+    SCD scd;
     string command;
 
     GetOpts::parsed_opts::const_iterator opt;
@@ -754,19 +606,19 @@ command_create(DBus::Connection* conn, Snapper* snapper)
     }
 
     if ((opt = opts.find("pre-number")) != opts.end())
-       num1 = read_num(opt->second);
+       snapshot1 = snapshots.findNum(opt->second);
 
     if ((opt = opts.find("print-number")) != opts.end())
        print_number = true;
 
     if ((opt = opts.find("description")) != opts.end())
-       description = opt->second;
+       scd.description = opt->second;
 
     if ((opt = opts.find("cleanup-algorithm")) != opts.end())
-       cleanup = opt->second;
+       scd.cleanup = opt->second;
 
     if ((opt = opts.find("userdata")) != opts.end())
-       userdata = read_userdata(opt->second);
+       scd.userdata = read_userdata(opt->second);
 
     if ((opt = opts.find("command")) != opts.end())
     {
@@ -774,7 +626,7 @@ command_create(DBus::Connection* conn, Snapper* snapper)
        type = CT_PRE_POST;
     }
 
-    if (type == CT_POST && (num1 == 0))
+    if (type == CT_POST && snapshot1 == snapshots.end())
     {
        cerr << _("Missing or invalid pre-number.") << endl;
        exit(EXIT_FAILURE);
@@ -789,34 +641,29 @@ command_create(DBus::Connection* conn, Snapper* snapper)
     switch (type)
     {
        case CT_SINGLE: {
-           unsigned int num1 = command_create_single_xsnapshot(*conn, config_name, description,
-                                                               cleanup, userdata);
+           snapshot1 = snapper->createSingleSnapshot(scd);
            if (print_number)
-               cout << num1 << endl;
+               cout << snapshot1->getNum() << endl;
        } break;
 
        case CT_PRE: {
-           unsigned int num1 = command_create_pre_xsnapshot(*conn, config_name, description,
-                                                            cleanup, userdata);
+           snapshot1 = snapper->createPreSnapshot(scd);
            if (print_number)
-               cout << num1 << endl;
+               cout << snapshot1->getNum() << endl;
        } break;
 
        case CT_POST: {
-           unsigned int num2 = command_create_post_xsnapshot(*conn, config_name, num1, description,
-                                                             cleanup, userdata);
+           snapshot2 = snapper->createPostSnapshot(snapshot1, scd);
            if (print_number)
-               cout << num2 << endl;
+               cout << snapshot2->getNum() << endl;
        } break;
 
        case CT_PRE_POST: {
-           unsigned int num1 = command_create_pre_xsnapshot(*conn, config_name, description,
-                                                            cleanup, userdata);
+           snapshot1 = snapper->createPreSnapshot(scd);
            system(command.c_str());
-           unsigned int num2 = command_create_post_xsnapshot(*conn, config_name, num1, "",
-                                                             cleanup, userdata);
+           snapshot2 = snapper->createPostSnapshot(snapshot1, scd);
            if (print_number)
-               cout << num1 << ".." << num2 << endl;
+               cout << snapshot1->getNum() << ".." << snapshot2->getNum() << endl;
        } break;
     }
 }
@@ -837,7 +684,7 @@ help_modify()
 
 
 void
-command_modify(DBus::Connection* conn, Snapper* snapper)
+command_modify(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     const struct option options[] = {
        { "description",        required_argument,      0,      'd' },
@@ -853,24 +700,32 @@ command_modify(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
+    ProxySnapshots& snapshots = snapper->getSnapshots();
+
     while (getopts.hasArgs())
     {
-       unsigned int num = read_num(getopts.popArg());
+       ProxySnapshots::iterator snapshot = snapshots.findNum(getopts.popArg());
 
-       XSnapshot data = command_get_xsnapshot(*conn, config_name, num);
+       SMD smd;
 
        GetOpts::parsed_opts::const_iterator opt;
 
        if ((opt = opts.find("description")) != opts.end())
-           data.description = opt->second;
+           smd.description = opt->second;
+       else
+           smd.description = snapshot->getDescription();
 
        if ((opt = opts.find("cleanup-algorithm")) != opts.end())
-           data.cleanup = opt->second;
+           smd.cleanup = opt->second;
+       else
+           smd.cleanup = snapshot->getCleanup();
 
        if ((opt = opts.find("userdata")) != opts.end())
-           data.userdata = read_userdata(opt->second, data.userdata);
+           smd.userdata = read_userdata(opt->second, snapshot->getUserdata());
+       else
+           smd.userdata = snapshot->getUserdata();
 
-       command_set_xsnapshot(*conn, config_name, num, data);
+       snapper->modifySnapshot(snapshot, smd);
     }
 }
 
@@ -888,7 +743,7 @@ help_delete()
 
 
 void
-command_delete(DBus::Connection* conn, Snapper* snapper)
+command_delete(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     const struct option options[] = {
        { "sync",               no_argument,            0,      's' },
@@ -909,9 +764,9 @@ command_delete(DBus::Connection* conn, Snapper* snapper)
     if ((opt = opts.find("sync")) != opts.end())
        sync = true;
 
-    XSnapshots snapshots = command_list_xsnapshots(*conn, config_name);
+    ProxySnapshots& snapshots = snapper->getSnapshots();
 
-    list<unsigned int> nums;
+    vector<ProxySnapshots::iterator> nums;
 
     while (getopts.hasArgs())
     {
@@ -919,31 +774,34 @@ command_delete(DBus::Connection* conn, Snapper* snapper)
 
        if (arg.find_first_of("-") == string::npos)
        {
-           unsigned int i = read_num(arg);
-           nums.push_back(i);
+           ProxySnapshots::iterator tmp = snapshots.findNum(arg);
+           nums.push_back(tmp);
        }
        else
        {
-           pair<unsigned int, unsigned int> r(read_nums(arg, "-"));
+           pair<ProxySnapshots::iterator, ProxySnapshots::iterator> range =
+               snapshots.findNums(arg, "-");
 
-           if (r.first > r.second)
-               swap(r.first, r.second);
+           if (range.first->getNum() > range.second->getNum())
+               swap(range.first, range.second);
 
-           for (unsigned int i = r.first; i <= r.second; ++i)
+           for (unsigned int i = range.first->getNum(); i <= range.second->getNum(); ++i)
            {
-               if (snapshots.find(i) != snapshots.end() &&
-                   find(nums.begin(), nums.end(), i) == nums.end())
+               ProxySnapshots::iterator x = snapshots.find(i);
+               if (x != snapshots.end())
                {
-                   nums.push_back(i);
+                   if (find_if(nums.begin(), nums.end(), [i](ProxySnapshots::iterator it)
+                               { return it->getNum() == i; }) == nums.end())
+                       nums.push_back(x);
                }
            }
        }
     }
 
-    command_delete_xsnapshots(*conn, config_name, nums, verbose);
+    snapper->deleteSnapshots(nums, verbose);
 
     if (sync)
-       command_xsync(*conn, config_name);
+       snapper->syncFilesystem();
 }
 
 
@@ -957,7 +815,7 @@ help_mount()
 
 
 void
-command_mount(DBus::Connection* conn, Snapper* snapper)
+command_mount(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     getopts.parse("mount", GetOpts::no_options);
     if (!getopts.hasArgs())
@@ -966,20 +824,12 @@ command_mount(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
+    const ProxySnapshots& snapshots = snapper->getSnapshots();
+
     while (getopts.hasArgs())
     {
-       if (no_dbus)
-       {
-           Snapshots::iterator snapshot = read_num(snapper, getopts.popArg());
-
-            snapshot->mountFilesystemSnapshot(true);
-       }
-       else
-       {
-           unsigned int num = read_num(getopts.popArg());
-
-           command_mount_xsnapshots(*conn, config_name, num, true);
-       }
+       ProxySnapshots::const_iterator snapshot = snapshots.findNum(getopts.popArg());
+       snapshot->mountFilesystemSnapshot(true);
     }
 }
 
@@ -994,29 +844,21 @@ help_umount()
 
 
 void
-command_umount(DBus::Connection* conn, Snapper* snapper)
+command_umount(ProxySnappers* snappers, ProxySnapper* snapper)
 {
-    getopts.parse("mount", GetOpts::no_options);
+    getopts.parse("umount", GetOpts::no_options);
     if (!getopts.hasArgs())
     {
-       cerr << _("Command 'mount' needs at least one argument.") << endl;
+       cerr << _("Command 'umount' needs at least one argument.") << endl;
        exit(EXIT_FAILURE);
     }
 
+    const ProxySnapshots& snapshots = snapper->getSnapshots();
+
     while (getopts.hasArgs())
     {
-       if (no_dbus)
-       {
-           Snapshots::iterator snapshot = read_num(snapper, getopts.popArg());
-
-            snapshot->umountFilesystemSnapshot(true);
-       }
-       else
-       {
-           unsigned int num = read_num(getopts.popArg());
-
-           command_umount_xsnapshots(*conn, config_name, num, true);
-       }
+       ProxySnapshots::const_iterator snapshot = snapshots.findNum(getopts.popArg());
+       snapshot->umountFilesystemSnapshot(true);
     }
 }
 
@@ -1034,7 +876,7 @@ help_status()
 
 
 void
-command_status(DBus::Connection* conn, Snapper* snapper)
+command_status(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     const struct option options[] = {
        { "output",             required_argument,      0,      'o' },
@@ -1057,10 +899,14 @@ command_status(DBus::Connection* conn, Snapper* snapper)
 
     GetOpts::parsed_opts::const_iterator opt;
 
-    pair<unsigned int, unsigned int> nums(read_nums(getopts.popArg()));
+    ProxySnapshots& snapshots = snapper->getSnapshots();
 
-    MyComparison comparison(*conn, nums, false);
-    MyFiles& files = comparison.files;
+    pair<ProxySnapshots::const_iterator, ProxySnapshots::const_iterator> range =
+       snapshots.findNums(getopts.popArg());
+
+    ProxyComparison comparison = snapper->createComparison(*range.first, *range.second, false);
+
+    MyFiles files(comparison.getFiles());
 
     FILE* file = stdout;
 
@@ -1098,7 +944,7 @@ help_diff()
 
 
 void
-command_diff(DBus::Connection* conn, Snapper* snapper)
+command_diff(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     const struct option options[] = {
        { "input",              required_argument,      0,      'i' },
@@ -1135,10 +981,14 @@ command_diff(DBus::Connection* conn, Snapper* snapper)
     if ((opt = opts.find("extensions")) != opts.end())
        differ.extensions = opt->second;
 
-    pair<unsigned int, unsigned int> nums(read_nums(getopts.popArg()));
+    ProxySnapshots& snapshots = snapper->getSnapshots();
+
+    pair<ProxySnapshots::const_iterator, ProxySnapshots::const_iterator> range =
+       snapshots.findNums(getopts.popArg());
 
-    MyComparison comparison(*conn, nums, true);
-    MyFiles& files = comparison.files;
+    ProxyComparison comparison = snapper->createComparison(*range.first, *range.second, true);
+
+    MyFiles files(comparison.getFiles());
 
     files.bulk_process(file, [differ](const File& file) {
        differ.run(file.getAbsolutePath(LOC_PRE), file.getAbsolutePath(LOC_POST));
@@ -1159,7 +1009,7 @@ help_undo()
 
 
 void
-command_undo(DBus::Connection* conn, Snapper* snapper)
+command_undo(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     const struct option options[] = {
        { "input",              required_argument,      0,      'i' },
@@ -1173,7 +1023,10 @@ command_undo(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
-    pair<unsigned int, unsigned int> nums(read_nums(getopts.popArg()));
+    ProxySnapshots& snapshots = snapper->getSnapshots();
+
+    pair<ProxySnapshots::const_iterator, ProxySnapshots::const_iterator> range =
+       snapshots.findNums(getopts.popArg());
 
     FILE* file = NULL;
 
@@ -1189,14 +1042,15 @@ command_undo(DBus::Connection* conn, Snapper* snapper)
        }
     }
 
-    if (nums.first == 0)
+    if (range.first->isCurrent())
     {
        cerr << _("Invalid snapshots.") << endl;
        exit(EXIT_FAILURE);
     }
 
-    MyComparison comparison(*conn, nums, true);
-    MyFiles& files = comparison.files;
+    ProxyComparison comparison = snapper->createComparison(*range.first, *range.second, true);
+
+    MyFiles files(comparison.getFiles());
 
     files.bulk_process(file, [](File& file) {
        file.setUndo(true);
@@ -1268,10 +1122,13 @@ command_undo(DBus::Connection* conn, Snapper* snapper)
 #ifdef ENABLE_ROLLBACK
 
 const Filesystem*
-getFilesystem(const XConfigInfo &ci, Snapper* snapper)
+getFilesystem(const ProxyConfig& config)
 {
-    map<string, string>::const_iterator it = ci.raw.find(KEY_FSTYPE);
-    if (it == ci.raw.end())
+    const map<string, string>& raw = config.getAllValues();
+
+    map<string, string>::const_iterator pos1 = raw.find(KEY_FSTYPE);
+    map<string, string>::const_iterator pos2 = raw.find(KEY_SUBVOLUME);
+    if (pos1 == raw.end() || pos2 == raw.end())
     {
        cerr << _("Failed to initialize filesystem handler.") << endl;
        exit(EXIT_FAILURE);
@@ -1279,7 +1136,7 @@ getFilesystem(const XConfigInfo &ci, Snapper* snapper)
 
     try
     {
-       return Filesystem::create(it->second, ci.subvolume, target_root);
+       return Filesystem::create(pos1->second, pos2->second, target_root);
     }
     catch (const InvalidConfigException& e)
     {
@@ -1289,19 +1146,6 @@ getFilesystem(const XConfigInfo &ci, Snapper* snapper)
     }
 }
 
-const string
-getSubvolume(const XConfigInfo &ci, Snapper* snapper)
-{
-    map<string, string>::const_iterator it = ci.raw.find(KEY_SUBVOLUME);
-    if (it == ci.raw.end())
-    {
-       cerr << _("Failed to initialize subvolume handler.") << endl;
-       exit(EXIT_FAILURE);
-    }
-
-    return it->second;
-}
-
 
 void
 help_rollback()
@@ -1319,7 +1163,7 @@ help_rollback()
 
 
 void
-command_rollback(DBus::Connection* conn, Snapper* snapper)
+command_rollback(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     const struct option options[] = {
        { "print-number",       no_argument,            0,      'p' },
@@ -1337,9 +1181,7 @@ command_rollback(DBus::Connection* conn, Snapper* snapper)
     }
 
     bool print_number = false;
-    string description;
-    string cleanup;
-    map<string, string> userdata;
+    SCD scd;
 
     GetOpts::parsed_opts::const_iterator opt;
 
@@ -1347,24 +1189,24 @@ command_rollback(DBus::Connection* conn, Snapper* snapper)
        print_number = true;
 
     if ((opt = opts.find("description")) != opts.end())
-       description = opt->second;
+       scd.description = opt->second;
 
     if ((opt = opts.find("cleanup-algorithm")) != opts.end())
-       cleanup = opt->second;
+       scd.cleanup = opt->second;
 
     if ((opt = opts.find("userdata")) != opts.end())
-       userdata = read_userdata(opt->second);
+       scd.userdata = read_userdata(opt->second);
 
-    XConfigInfo ci = command_get_xconfig(*conn, config_name);
+    ProxyConfig config = snapper->getConfig();
 
-    const Filesystem* filesystem = getFilesystem(ci, snapper);
+    const Filesystem* filesystem = getFilesystem(config);
     if (filesystem->fstype() != "btrfs")
     {
        cerr << _("Command 'rollback' only available for btrfs.") << endl;
        exit(EXIT_FAILURE);
     }
 
-    const string subvolume = getSubvolume(ci, snapper);
+    const string subvolume = config.getSubvolume();
     if (subvolume != "/")
     {
         cerr << sformat(_("Command 'rollback' cannot be used on a non-root subvolume %s."),
@@ -1372,53 +1214,63 @@ command_rollback(DBus::Connection* conn, Snapper* snapper)
         exit(EXIT_FAILURE);
     }
 
-    unsigned int num1;
-    unsigned int num2;
+    ProxySnapshots& snapshots = snapper->getSnapshots();
+
+    ProxySnapshots::const_iterator snapshot1 = snapshots.end();
+    ProxySnapshots::const_iterator snapshot2 = snapshots.end();
 
     if (getopts.numArgs() == 0)
     {
        if (!quiet)
            cout << _("Creating read-only snapshot of default subvolume.") << flush;
-       num1 = command_create_single_xsnapshot_of_default(*conn, config_name, true,
-                                                         description, cleanup,
-                                                         userdata);
+
+       scd.read_only = true;
+       snapshot1 = snapper->createSingleSnapshotOfDefault(scd);
+
        if (!quiet)
-           cout << " " << sformat(_("(Snapshot %d.)"), num1) << endl;
+           cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
 
        if (!quiet)
-           cout << _("Creating read-write snapshot of current subvolume.") <<flush;
-       num2 = command_create_single_xsnapshot_v2(*conn, config_name, 0, false, description,
-                                                 cleanup, userdata);
+           cout << _("Creating read-write snapshot of current subvolume.") << flush;
+
+       scd.read_only = false;
+       snapshot2 = snapper->createSingleSnapshot(snapshots.getCurrent(), scd);
+
        if (!quiet)
-           cout << " " << sformat(_("(Snapshot %d.)"), num2) << endl;
+           cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
     }
     else
     {
-       unsigned int tmp = read_num(getopts.popArg());
+       ProxySnapshots::const_iterator tmp = snapshots.findNum(getopts.popArg());
 
        if (!quiet)
            cout << _("Creating read-only snapshot of current system.") << flush;
-       num1 = command_create_single_xsnapshot(*conn, config_name, description,
-                                              cleanup, userdata);
+
+       snapshot1 = snapper->createSingleSnapshot(scd);
+
        if (!quiet)
-           cout << " " << sformat(_("(Snapshot %d.)"), num1) << endl;
+           cout << " " << sformat(_("(Snapshot %d.)"), snapshot1->getNum()) << endl;
 
        if (!quiet)
-           cout << sformat(_("Creating read-write snapshot of snapshot %d."), tmp) << flush;
-       num2 = command_create_single_xsnapshot_v2(*conn, config_name, tmp, false,
-                                                 description, cleanup, userdata);
+           cout << sformat(_("Creating read-write snapshot of snapshot %d."), tmp->getNum()) << flush;
+
+       scd.read_only = false;
+       snapshot2 = snapper->createSingleSnapshot(tmp, scd);
+
        if (!quiet)
-           cout << " " << sformat(_("(Snapshot %d.)"), num2) << endl;
+           cout << " " << sformat(_("(Snapshot %d.)"), snapshot2->getNum()) << endl;
     }
 
     if (!quiet)
-       cout << sformat(_("Setting default subvolume to snapshot %d."), num2) << endl;
-    filesystem->setDefault(num2);
+       cout << sformat(_("Setting default subvolume to snapshot %d."), snapshot2->getNum()) << endl;
 
-    Hooks::rollback(filesystem->snapshotDir(num1), filesystem->snapshotDir(num2));
+    filesystem->setDefault(snapshot2->getNum());
+
+    Hooks::rollback(filesystem->snapshotDir(snapshot1->getNum()),
+                   filesystem->snapshotDir(snapshot2->getNum()));
 
     if (print_number)
-       cout << num2 << endl;
+       cout << snapshot2->getNum() << endl;
 }
 
 #endif
@@ -1434,7 +1286,7 @@ help_setup_quota()
 
 
 void
-command_setup_quota(DBus::Connection* conn, Snapper* snapper)
+command_setup_quota(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     GetOpts::parsed_opts opts = getopts.parse("setup-quota", GetOpts::no_options);
     if (getopts.numArgs() != 0)
@@ -1443,14 +1295,7 @@ command_setup_quota(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
-    if (no_dbus)
-    {
-       snapper->setupQuota();
-    }
-    else
-    {
-       command_setup_quota(*conn, config_name);
-    }
+    snapper->setupQuota();
 }
 
 
@@ -1464,7 +1309,7 @@ help_cleanup()
 
 
 void
-command_cleanup(DBus::Connection* conn, Snapper* snapper)
+command_cleanup(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     GetOpts::parsed_opts opts = getopts.parse("cleanup", GetOpts::no_options);
     if (getopts.numArgs() != 1)
@@ -1477,15 +1322,15 @@ command_cleanup(DBus::Connection* conn, Snapper* snapper)
 
     if (cleanup == "number")
     {
-       do_cleanup_number(*conn, config_name, verbose);
+       do_cleanup_number(snapper, verbose);
     }
     else if (cleanup == "timeline")
     {
-       do_cleanup_timeline(*conn, config_name, verbose);
+       do_cleanup_timeline(snapper, verbose);
     }
     else if (cleanup == "empty-pre-post")
     {
-       do_cleanup_empty_pre_post(*conn, config_name, verbose);
+       do_cleanup_empty_pre_post(snapper, verbose);
     }
     else
     {
@@ -1502,7 +1347,7 @@ help_debug()
 
 
 void
-command_debug(DBus::Connection* conn, Snapper* snapper)
+command_debug(ProxySnappers* snappers, ProxySnapper*)
 {
     getopts.parse("debug", GetOpts::no_options);
     if (getopts.hasArgs())
@@ -1511,9 +1356,8 @@ command_debug(DBus::Connection* conn, Snapper* snapper)
        exit(EXIT_FAILURE);
     }
 
-    vector<string> lines = command_xdebug(*conn);
-    for (vector<string>::const_iterator it = lines.begin(); it != lines.end(); ++it)
-       cout << *it << endl;
+    for (const string& line : snappers->debug())
+       cout << line << endl;
 }
 
 
@@ -1547,7 +1391,7 @@ print_xa_diff(const string loc_pre, const string loc_post)
 }
 
 void
-command_xa_diff(DBus::Connection* conn, Snapper* snapper)
+command_xa_diff(ProxySnappers* snappers, ProxySnapper* snapper)
 {
     GetOpts::parsed_opts opts = getopts.parse("xadiff", GetOpts::no_options);
     if (getopts.numArgs() < 1)
@@ -1556,10 +1400,14 @@ command_xa_diff(DBus::Connection* conn, Snapper* snapper)
         exit(EXIT_FAILURE);
     }
 
-    pair<unsigned int, unsigned int> nums(read_nums(getopts.popArg()));
+    ProxySnapshots& snapshots = snapper->getSnapshots();
+
+    pair<ProxySnapshots::const_iterator, ProxySnapshots::const_iterator> range =
+       snapshots.findNums(getopts.popArg());
 
-    MyComparison comparison(*conn, nums, true);
-    MyFiles& files = comparison.files;
+    ProxyComparison comparison = snapper->createComparison(*range.first, *range.second, true);
+
+    MyFiles files(comparison.getFiles());
 
     if (getopts.numArgs() == 0)
     {
@@ -1655,36 +1503,36 @@ main(int argc, char** argv)
     catch (const runtime_error& e)
     {
        cerr << "Failed to set locale. Fix your system." << endl;
-       exit (EXIT_FAILURE);
+       exit(EXIT_FAILURE);
     }
 
     setLogDo(&log_do);
     setLogQuery(&log_query);
 
     const list<Cmd> cmds = {
-       Cmd("list-configs", command_list_configs, help_list_configs, true, false),
-       Cmd("create-config", command_create_config, help_create_config, true, false),
-       Cmd("delete-config", command_delete_config, help_delete_config, true, false),
-       Cmd("get-config", command_get_config, help_get_config, true, false),
-       Cmd("set-config", command_set_config, help_set_config, true, true),
-       Cmd("list", { "ls" }, command_list, help_list, true, true),
-       Cmd("create", command_create, help_create, false, true),
-       Cmd("modify", command_modify, help_modify, false, true),
-       Cmd("delete", { "remove", "rm" }, command_delete, help_delete, false, true),
-       Cmd("mount", command_mount, help_mount, true, true),
-       Cmd("umount", command_umount, help_umount, true, true),
-       Cmd("status", command_status, help_status, false, true),
-       Cmd("diff", command_diff, help_diff, false, true),
+       Cmd("list-configs", command_list_configs, help_list_configs, false),
+       Cmd("create-config", command_create_config, help_create_config, false),
+       Cmd("delete-config", command_delete_config, help_delete_config, false),
+       Cmd("get-config", command_get_config, help_get_config, true),
+       Cmd("set-config", command_set_config, help_set_config, true),
+       Cmd("list", { "ls" }, command_list, help_list, false),
+       Cmd("create", command_create, help_create, true),
+       Cmd("modify", command_modify, help_modify, true),
+       Cmd("delete", { "remove", "rm" }, command_delete, help_delete, true),
+       Cmd("mount", command_mount, help_mount, true),
+       Cmd("umount", command_umount, help_umount, true),
+       Cmd("status", command_status, help_status, true),
+       Cmd("diff", command_diff, help_diff, true),
 #ifdef ENABLE_XATTRS
-       Cmd("xadiff", command_xa_diff, help_xa_diff, false, true),
+       Cmd("xadiff", command_xa_diff, help_xa_diff, true),
 #endif
-       Cmd("undochange", command_undo, help_undo, false, true),
+       Cmd("undochange", command_undo, help_undo, true),
 #ifdef ENABLE_ROLLBACK
-       Cmd("rollback", command_rollback, help_rollback, false, true),
+       Cmd("rollback", command_rollback, help_rollback, true),
 #endif
-       Cmd("setup-quota", command_setup_quota, help_setup_quota, true, true),
-       Cmd("cleanup", command_cleanup, help_cleanup, false, true),
-       Cmd("debug", command_debug, help_debug, false, false)
+       Cmd("setup-quota", command_setup_quota, help_setup_quota, true),
+       Cmd("cleanup", command_cleanup, help_cleanup, true),
+       Cmd("debug", command_debug, help_debug, false)
     };
 
     const struct option options[] = {
@@ -1783,26 +1631,13 @@ main(int argc, char** argv)
 
     try
     {
-       if (no_dbus)
-       {
-           if (!cmd->works_without_dbus)
-           {
-               cerr << sformat(_("Command '%s' does not work without DBus."), cmd->name.c_str()) << endl;
-               exit(EXIT_FAILURE);
-           }
-
-           Snapper* snapper = cmd->needs_snapper ? new Snapper(config_name, target_root) : NULL;
-
-           (*cmd->cmd_func)(NULL, snapper);
+       ProxySnappers snappers(no_dbus ? ProxySnappers::createLib(target_root) :
+                              ProxySnappers::createDbus());
 
-           delete snapper;
-       }
+       if (cmd->needs_snapper)
+           (*cmd->cmd_func)(&snappers, snappers.getSnapper(config_name));
        else
-       {
-           DBus::Connection conn(DBUS_BUS_SYSTEM);
-
-           (*cmd->cmd_func)(&conn, NULL);
-       }
+           (*cmd->cmd_func)(&snappers, nullptr);
     }
     catch (const DBus::ErrorException& e)
     {
@@ -1824,6 +1659,12 @@ main(int argc, char** argv)
        cerr << _("Failure") << " (" << e.what() << ")." << endl;
        exit(EXIT_FAILURE);
     }
+    catch (const IllegalSnapshotException& e)
+    {
+       SN_CAUGHT(e);
+       cerr << _("Illegal snapshot.") << endl;
+       exit(EXIT_FAILURE);
+    }
     catch (const ConfigNotFoundException& e)
     {
        SN_CAUGHT(e);
@@ -1890,6 +1731,12 @@ main(int argc, char** argv)
        cerr << sformat(_("Quota error (%s)."), e.what()) << endl;
        exit(EXIT_FAILURE);
     }
+    catch (const Exception& e)
+    {
+       SN_CAUGHT(e);
+       cerr << sformat(_("Error (%s)."), e.what()) << endl;
+       exit(EXIT_FAILURE);
+    }
 
     exit(EXIT_SUCCESS);
 }
index 3c76371fb3d1d8d1ddee065c8ace930c34311335..b14bbb1c8b8aeb87f84fd0f47e6ede1098b62b35 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) [2014-2015] Novell, Inc.
+ * Copyright (c) 2016 SUSE LLC
  *
  * All Rights Reserved.
  *
@@ -28,7 +29,7 @@
 #include "utils/text.h"
 #include "utils/GetOpts.h"
 
-#include "commands.h"
+#include "proxy.h"
 #include "cleanup.h"
 #include "errors.h"
 #include "misc.h"
@@ -38,48 +39,56 @@ using namespace snapper;
 using namespace std;
 
 
-bool do_timeline = false;
-bool do_cleanup = false;
-
-
 void
-timeline(DBus::Connection* conn, const map<string, string>& userdata)
+timeline(ProxySnappers* snappers, const map<string, string>& userdata)
 {
-    list<XConfigInfo> config_infos = command_list_xconfigs(*conn);
-    for (const XConfigInfo& config_info : config_infos)
+    map<string, ProxyConfig> configs = snappers->getConfigs();
+    for (const map<string, ProxyConfig>::value_type value : configs)
     {
-       map<string, string>::const_iterator pos1 = config_info.raw.find("TIMELINE_CREATE");
-       if (pos1 != config_info.raw.end() && pos1->second == "yes")
+       const map<string, string>& raw = value.second.getAllValues();
+
+       map<string, string>::const_iterator pos1 = raw.find("TIMELINE_CREATE");
+       if (pos1 != raw.end() && pos1->second == "yes")
        {
-           command_create_single_xsnapshot(*conn, config_info.config_name, "timeline",
-                                           "timeline", userdata);
+           ProxySnapper* snapper = snappers->getSnapper(value.first);
+
+           SCD scd;
+           scd.description = "timeline";
+           scd.cleanup = "timeline";
+           scd.userdata = userdata;
+
+           snapper->createSingleSnapshot(scd);
        }
     }
 }
 
 
 void
-cleanup(DBus::Connection* conn)
+cleanup(ProxySnappers* snappers)
 {
-    list<XConfigInfo> config_infos = command_list_xconfigs(*conn);
-    for (const XConfigInfo& config_info : config_infos)
+    map<string, ProxyConfig> configs = snappers->getConfigs();
+    for (const map<string, ProxyConfig>::value_type value : configs)
     {
-       map<string, string>::const_iterator pos1 = config_info.raw.find("NUMBER_CLEANUP");
-       if (pos1 != config_info.raw.end() && pos1->second == "yes")
+       const map<string, string>& raw = value.second.getAllValues();
+
+       ProxySnapper* snapper = snappers->getSnapper(value.first);
+
+       map<string, string>::const_iterator pos1 = raw.find("NUMBER_CLEANUP");
+       if (pos1 != raw.end() && pos1->second == "yes")
        {
-           do_cleanup_number(*conn, config_info.config_name, false);
+           do_cleanup_number(snapper, false);
        }
 
-       map<string, string>::const_iterator pos2 = config_info.raw.find("TIMELINE_CLEANUP");
-       if (pos2 != config_info.raw.end() && pos2->second == "yes")
+       map<string, string>::const_iterator pos2 = raw.find("TIMELINE_CLEANUP");
+       if (pos2 != raw.end() && pos2->second == "yes")
        {
-           do_cleanup_timeline(*conn, config_info.config_name, false);
+           do_cleanup_timeline(snapper, false);
        }
 
-       map<string, string>::const_iterator pos3 = config_info.raw.find("EMPTY_PRE_POST_CLEANUP");
-       if (pos3 != config_info.raw.end() && pos3->second == "yes")
+       map<string, string>::const_iterator pos3 = raw.find("EMPTY_PRE_POST_CLEANUP");
+       if (pos3 != raw.end() && pos3->second == "yes")
        {
-           do_cleanup_empty_pre_post(*conn, config_info.config_name, false);
+           do_cleanup_empty_pre_post(snapper, false);
        }
     }
 }
@@ -97,6 +106,9 @@ main(int argc, char** argv)
        { 0, 0, 0, 0 }
     };
 
+    bool do_timeline = false;
+    bool do_cleanup = false;
+
     map<string, string> userdata;
 
     GetOpts getopts;
@@ -118,13 +130,13 @@ main(int argc, char** argv)
 
     try
     {
-       DBus::Connection conn(DBUS_BUS_SYSTEM);
+       ProxySnappers snappers(ProxySnappers::createDbus());
 
        if (do_timeline)
-           timeline(&conn, userdata);
+           timeline(&snappers, userdata);
 
        if (do_cleanup)
-           cleanup(&conn);
+           cleanup(&snappers);
     }
     catch (const DBus::ErrorException& e)
     {
index 9501435c04843cfa47efeb0be8fde61a7c4b456c..e3acbb8558513fcd78cad530879d8b3638bbb2c8 100644 (file)
 #include "types.h"
 
 
-XSnapshots::const_iterator
-XSnapshots::find(unsigned int num) const
-{
-    for (const_iterator it = begin(); it != end(); ++it)
-    {
-       if (it->getNum() == num)
-           return it;
-    }
-
-    return end();
-}
-
-
-XSnapshots::iterator
-XSnapshots::findPre(iterator post)
-{
-    if (post == entries.end() || post->isCurrent() || post->getType() != POST)
-       SN_THROW(IllegalSnapshotException());
-
-    for (iterator it = begin(); it != end(); ++it)
-    {
-       if (it->getType() == PRE && it->getNum() == post->getPreNum())
-           return it;
-    }
-
-    return end();
-}
-
-
-XSnapshots::const_iterator
-XSnapshots::findPre(const_iterator post) const
-{
-    if (post == entries.end() || post->isCurrent() || post->getType() != POST)
-       SN_THROW(IllegalSnapshotException());
-
-    for (const_iterator it = begin(); it != end(); ++it)
-    {
-       if (it->getType() == PRE && it->getNum() == post->getPreNum())
-           return it;
-    }
-
-    return end();
-}
-
-
-XSnapshots::iterator
-XSnapshots::findPost(iterator pre)
-{
-    if (pre == entries.end() || pre->isCurrent() || pre->getType() != PRE)
-       SN_THROW(IllegalSnapshotException());
-
-    for (iterator it = begin(); it != end(); ++it)
-    {
-       if (it->getType() == POST && it->getPreNum() == pre->getNum())
-           return it;
-    }
-
-    return end();
-}
-
-
-XSnapshots::const_iterator
-XSnapshots::findPost(const_iterator pre) const
-{
-    if (pre == entries.end() || pre->isCurrent() || pre->getType() != PRE)
-       SN_THROW(IllegalSnapshotException());
-
-    for (const_iterator it = begin(); it != end(); ++it)
-    {
-       if (it->getType() == POST && it->getPreNum() == pre->getNum())
-           return it;
-    }
-
-    return end();
-}
-
-
 namespace DBus
 {
     const char* TypeInfo<XConfigInfo>::signature = "(ssa{ss})";
@@ -153,7 +76,7 @@ namespace DBus
 
 
     Hihi&
-    operator>>(Hihi& hihi, XQuotaData& data)
+    operator>>(Hihi& hihi, QuotaData& data)
     {
        hihi.open_recurse();
        hihi >> data.size >> data.used;
index c2ec91b9a5f6fc4bfdad81990e59a3ff5546744f..de1a5da40aa61dab1210e3f7094b47d4a2c88fa1 100644 (file)
 
 
 #include <string>
-#include <list>
+#include <vector>
 #include <map>
 
 using std::string;
-using std::list;
+using std::vector;
 using std::map;
 
 #include "dbus/DBusMessage.h"
@@ -34,6 +34,7 @@ using std::map;
 #include "snapper/Snapshot.h"
 #include "snapper/File.h"
 #include "snapper/SnapperTmpl.h"
+#include "snapper/Snapper.h"
 
 using namespace snapper;
 
@@ -44,14 +45,6 @@ struct XConfigInfo
     string subvolume;
 
     map<string, string> raw;
-
-    template<typename Type>
-    void read(const char* name, Type& value)
-    {
-       map<string, string>::const_iterator pos = raw.find(name);
-       if (pos != raw.end())
-           pos->second >> value;
-    }
 };
 
 
@@ -60,7 +53,6 @@ struct XSnapshot
     SnapshotType getType() const { return type; }
 
     unsigned int getNum() const { return num; }
-    bool isCurrent() const { return num == 0; }
 
     time_t getDate() const { return date; }
 
@@ -87,26 +79,12 @@ struct XSnapshot
 
 struct XSnapshots
 {
-    typedef list<XSnapshot>::iterator iterator;
-    typedef list<XSnapshot>::const_iterator const_iterator;
+    typedef vector<XSnapshot>::const_iterator const_iterator;
 
-    iterator begin() { return entries.begin(); }
     const_iterator begin() const { return entries.begin(); }
-
-    iterator end() { return entries.end(); }
     const_iterator end() const { return entries.end(); }
 
-    const_iterator find(unsigned int num) const;
-
-    iterator findPre(iterator post);
-    const_iterator findPre(const_iterator post) const;
-
-    iterator findPost(iterator pre);
-    const_iterator findPost(const_iterator pre) const;
-
-    iterator erase(iterator pos) { return entries.erase(pos); }
-
-    list<XSnapshot> entries;
+    vector<XSnapshot> entries;
 };
 
 
@@ -117,13 +95,6 @@ struct XFile
 };
 
 
-struct XQuotaData
-{
-    uint64_t size;
-    uint64_t used;
-};
-
-
 namespace DBus
 {
 
@@ -140,6 +111,6 @@ namespace DBus
 
     Hihi& operator>>(Hihi& hihi, XFile& data);
 
-    Hihi& operator>>(Hihi& hihi, XQuotaData& data);
+    Hihi& operator>>(Hihi& hihi, QuotaData& data);
 
 }
index 09267034dab094b3fa50292efa1c17e4a22066bf..616e36e1b4f46fa3577b48e56e84b4a81414d012 100644 (file)
       <varlistentry>
        <term><option>--no-dbus</option></term>
        <listitem>
-         <para>Operate without a DBus connection. Only works for some commands.</para>
+         <para>Operate without a DBus connection.</para>
          <para>Use with caution since a running snapperd will not know about
          modifications made to the system.</para>
        </listitem>
index 00abab0356bdc1d3370597db4e9f097af3c4999c..46fbb1531bab03f7d07de353f1286e9ff9991a7f 100644 (file)
@@ -12,11 +12,11 @@ using namespace std;
 
 
 void
-deleteAll()
+delete_all()
 {
-    Snapper* sh = new Snapper("testsuite", "/");
+    Snapper snapper("testsuite", "/");
 
-    Snapshots snapshots = sh->getSnapshots();
+    Snapshots snapshots = snapper.getSnapshots();
 
     vector<Snapshots::iterator> tmp;
     for (Snapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it)
@@ -24,18 +24,14 @@ deleteAll()
            tmp.push_back(it);
 
     for (vector<Snapshots::iterator>::iterator it = tmp.begin(); it != tmp.end(); ++it)
-       sh->deleteSnapshot(*it);
-
-    delete sh;
+       snapper.deleteSnapshot(*it);
 }
 
 
-int
-main()
+void
+create_number()
 {
-    deleteAll();
-
-    Snapper* sh = new Snapper("testsuite", "/");
+    Snapper snapper("testsuite", "/");
 
     for (size_t i = 0; i < 100; ++i)
     {
@@ -46,10 +42,17 @@ main()
        if (i % 5 == 0)
            scd.userdata["important"] = "yes";
 
-       sh->createSingleSnapshot(scd);
+       snapper.createSingleSnapshot(scd);
     }
+}
+
+
+int
+main()
+{
+    delete_all();
 
-    delete sh;
+    create_number();
 
     exit(EXIT_SUCCESS);
 }
index c8e3221b9823d96def4cd2850af0fe4aea104277..1ae4e7c2c7fc13b3a78c50c81e12f257c24fbe18 100644 (file)
@@ -12,11 +12,11 @@ using namespace std;
 
 
 void
-deleteAll()
+delete_all()
 {
-    Snapper* sh = new Snapper("testsuite", "/");
+    Snapper snapper("testsuite", "/");
 
-    Snapshots snapshots = sh->getSnapshots();
+    Snapshots snapshots = snapper.getSnapshots();
 
     vector<Snapshots::iterator> tmp;
     for (Snapshots::iterator it = snapshots.begin(); it != snapshots.end(); ++it)
@@ -24,18 +24,14 @@ deleteAll()
            tmp.push_back(it);
 
     for (vector<Snapshots::iterator>::iterator it = tmp.begin(); it != tmp.end(); ++it)
-       sh->deleteSnapshot(*it);
-
-    delete sh;
+       snapper.deleteSnapshot(*it);
 }
 
 
-int
-main()
+void
+create_timeline()
 {
-    deleteAll();
-
-    Snapper* sh = new Snapper("testsuite", "/");
+    Snapper snapper("testsuite", "/");
 
     time_t t = time(NULL) - 100 * 24*60*60;
     while (t < time(NULL))
@@ -45,13 +41,21 @@ main()
        scd.description = "testsuite";
        scd.cleanup = "timeline";
 
-       Snapshots::iterator snap = sh->createSingleSnapshot(scd);
-       // snap->setDate(t);
+       Snapshots::iterator snapshot = snapper.createSingleSnapshot(scd);
+       // snapshot->setDate(t);
+       snapper.modifySnapshot(snapshot, scd);
 
        t += 60*60;
     }
+}
+
+
+int
+main()
+{
+    delete_all();
 
-    delete sh;
+    create_timeline();
 
     exit(EXIT_SUCCESS);
 }
index 78bc6547280b0bd676e212bee40af6403f01c007..ca3aa5139ed6f6fbf936d44c93eff4ed35b1e9d4 100644 (file)
@@ -1,3 +1,10 @@
+-------------------------------------------------------------------
+Thu Dec 15 21:36:23 CET 2016 - aschnell@suse.com
+
+- support option --no-dbus for all snapper commands (fate#319404,
+  fate#321049)
+- version 0.4.0
+
 -------------------------------------------------------------------
 Fri Nov 04 16:28:49 CET 2016 - aschnell@suse.com
 
index 32ad57c551389c8cd3644544a000cc59388989d7..004b9bdc9c8a17bb6afbed91bb02ba1585b5b9ed 100644 (file)
@@ -113,7 +113,7 @@ Backgrounds::worker()
            lock.unlock();
 
            Snapper* snapper = task.meta_snapper->getSnapper();
-           Comparison comparison(snapper, task.snapshot1, task.snapshot2);
+           Comparison comparison(snapper, task.snapshot1, task.snapshot2, false);
            task.meta_snapper->dec_use_count();
 
            lock.lock();
index c658c1679b33bbec517ada6ec441a1f24c60e990..6d69d5edd1e46d8f36c01f3cf2862cf24ebc285a 100644 (file)
@@ -1216,7 +1216,7 @@ Client::create_comparison(DBus::Connection& conn, DBus::Message& msg)
 
     lock.unlock();
 
-    Comparison* comparison = new Comparison(snapper, snapshot1, snapshot2);
+    Comparison* comparison = new Comparison(snapper, snapshot1, snapshot2, false);
 
     lock.lock();
 
index 5f39efe30eed94e5b3b75a7fb8c1b093e62e9adf..05427f8aecc83ae4f57b7d8d17362901c53b906a 100644 (file)
@@ -45,8 +45,9 @@ namespace snapper
 
 
     Comparison::Comparison(const Snapper* snapper, Snapshots::const_iterator snapshot1,
-                          Snapshots::const_iterator snapshot2)
-       : snapper(snapper), snapshot1(snapshot1), snapshot2(snapshot2), files(&file_paths)
+                          Snapshots::const_iterator snapshot2, bool mount)
+       : snapper(snapper), snapshot1(snapshot1), snapshot2(snapshot2), mount(mount),
+         files(&file_paths)
     {
        if (snapshot1 == snapper->getSnapshots().end() ||
            snapshot2 == snapper->getSnapshots().end() ||
@@ -60,6 +61,16 @@ namespace snapper
        file_paths.post_path = snapshot2->snapshotDir();
 
        initialize();
+
+       if (mount)
+           do_mount();
+    }
+
+
+    Comparison::~Comparison()
+    {
+       if (mount)
+           do_umount();
     }
 
 
@@ -102,7 +113,7 @@ namespace snapper
 
 
     void
-    Comparison::mount() const
+    Comparison::do_mount() const
     {
        if (!getSnapshot1()->isCurrent())
            getSnapshot1()->mountFilesystemSnapshot(false);
@@ -112,7 +123,7 @@ namespace snapper
 
 
     void
-    Comparison::umount() const
+    Comparison::do_umount() const
     {
        if (!getSnapshot1()->isCurrent())
            getSnapshot1()->umountFilesystemSnapshot(false);
@@ -130,7 +141,7 @@ namespace snapper
            files.push_back(File(&file_paths, name, status));
        };
 
-       mount();
+       do_mount();
 
        {
            SDir dir1 = getSnapshot1()->openSnapshotDir();
@@ -138,7 +149,7 @@ namespace snapper
            snapper->getFilesystem()->cmpDirs(dir1, dir2, cb);
        }
 
-       umount();
+       do_umount();
 
        files.sort();
 
index a99a84179fe2082f5c0e847ad80c9332b9a80637..9b3413999986b616bbc546f7ce98b9dc74e23d4e 100644 (file)
@@ -35,8 +35,16 @@ namespace snapper
     {
     public:
 
+       /**
+        * Create a comparison.
+        *
+        * The mount parameter allows to ensure that the two snapshots are
+        * mounted for the lifetime of the Comparison object.
+        */
        Comparison(const Snapper* snapper, Snapshots::const_iterator snapshot1,
-                  Snapshots::const_iterator snapshot2);
+                  Snapshots::const_iterator snapshot2, bool mount);
+
+       ~Comparison();
 
        const Snapper* getSnapper() const { return snapper; }
 
@@ -46,9 +54,6 @@ namespace snapper
        Files& getFiles() { return files; }
        const Files& getFiles() const { return files; }
 
-       void mount() const;
-       void umount() const;
-
        UndoStatistic getUndoStatistic() const;
         XAUndoStatistic getXAUndoStatistic() const;
 
@@ -64,11 +69,16 @@ namespace snapper
        void save();
        void filter();
 
+       void do_mount() const;
+       void do_umount() const;
+
        const Snapper* snapper;
 
        Snapshots::const_iterator snapshot1;
        Snapshots::const_iterator snapshot2;
 
+       const bool mount;
+
        FilePaths file_paths;
 
        Files files;
index dba89da11166faf7bd740c240dc3b491350c1b46..ade271b76f26513b2b6730ab9ee10f9f18fa6a87 100644 (file)
@@ -185,6 +185,9 @@ namespace snapper
        Files(const FilePaths* file_paths)
            : file_paths(file_paths) {}
 
+       Files(const FilePaths* file_paths, const vector<File>& entries)
+           : file_paths(file_paths), entries(entries) {}
+
        typedef vector<File>::iterator iterator;
        typedef vector<File>::const_iterator const_iterator;
        typedef vector<File>::size_type size_type;
index 78ccf6e90b052bc3fdf8eea808f6856e94f53cf8..f610b6082c67217c969c800e6e093ac999c45887 100644 (file)
@@ -21,7 +21,6 @@
 #include "config.h"
 
 #include <vector>
-
 #include <boost/algorithm/string.hpp>
 
 #include "snapper/Log.h"
index c428437b7e1191598cfa1ec13198b7e8569035ce..d6ee38023213a28a7204f586d12582cf08c0624d 100644 (file)
@@ -966,4 +966,12 @@ namespace snapper
            ;
     }
 
+
+    vector<string>
+    Snapper::debug()
+    {
+       return { "version " + string(compileVersion()),
+                "flags " + string(compileFlags()) };
+    }
+
 }
index 6f9ce8722de217194c387a5195b0f1e28bc99831..0e0f4c784f527bf016186b35a78fdf01ebb575a3 100644 (file)
@@ -153,6 +153,7 @@ namespace snapper
 
        const Filesystem* getFilesystem() const { return filesystem; }
 
+       const ConfigInfo& getConfigInfo() { return *config_info; }
        void setConfigInfo(const map<string, string>& raw);
 
        void syncAcl() const;
@@ -168,6 +169,8 @@ namespace snapper
        static const char* compileVersion();
        static const char* compileFlags();
 
+       static vector<string> debug();
+
     private:
 
        void filter1(list<Snapshots::iterator>& tmp, time_t min_age);
index 23b953ad6e3265ef4e0336397921f87703d850b3..86d009931ad483fdbb43463a752dcf873646201d 100644 (file)
@@ -70,7 +70,7 @@ second_snapshot()
 void
 check_undo_statistics(unsigned int numCreate, unsigned int numModify, unsigned int numDelete)
 {
-    Comparison comparison(sh, first, second);
+    Comparison comparison(sh, first, second, false);
 
     Files& files = comparison.getFiles();
     for (Files::iterator it = files.begin(); it != files.end(); ++it)
@@ -101,7 +101,7 @@ undo()
 
     cout << "comparing snapshots..." << flush;
 
-    Comparison comparison(sh, first, second);
+    Comparison comparison(sh, first, second, false);
 
     cout << " done" << endl;
 
@@ -158,7 +158,7 @@ check_first()
 {
     Snapshots::const_iterator current = sh->getSnapshotCurrent();
 
-    Comparison comparison(sh, first, current);
+    Comparison comparison(sh, first, current, false);
 
     const Files& files = comparison.getFiles();
     for (Files::const_iterator it = files.begin(); it != files.end(); ++it)