]> git.ipfire.org Git - thirdparty/snapper.git/commitdiff
- allow to sync ALLOW_USERS and ALLOW_GROUPS to ACL of .snapshots directory (see...
authorArvin Schnell <aschnell@suse.de>
Wed, 29 Jan 2014 10:59:44 +0000 (11:59 +0100)
committerArvin Schnell <aschnell@suse.de>
Wed, 29 Jan 2014 10:59:44 +0000 (11:59 +0100)
17 files changed:
LIBVERSION
VERSION
client/snapper.cc
data/default-config
doc/snapper-configs.xml.in
doc/snapper.xml.in
package/snapper.changes
server/Client.cc
server/MetaSnapper.cc
snapper.spec.in
snapper/AppUtil.cc
snapper/AppUtil.h
snapper/Exception.h
snapper/Makefile.am
snapper/Snapper.cc
snapper/Snapper.h
snapper/SnapperDefines.h

index ccbccc3dc62631f22ff358ac418e52401ec770b4..276cbf9e2858c779297bb9f73b34170302949ec4 100644 (file)
@@ -1 +1 @@
-2.2.0
+2.3.0
diff --git a/VERSION b/VERSION
index 699c6c6d4e07f86a8d38c36dd55684a10554df8b..0ea3a944b399d25f7e1b8fe684d754eb8da9fe7f 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.8
+0.2.0
index e79b526e1e903295e07d7721e51ae77fa6574de7..886803eaf4517937f3eb5ae735512eedf328a4d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2011-2013] Novell, Inc.
+ * Copyright (c) [2011-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -488,12 +488,7 @@ command_set_config(DBus::Connection* conn, Snapper* snapper)
 
     if (no_dbus)
     {
-       ConfigInfo config_info = Snapper::getConfig(config_name);
-
-       for (map<string, string>::const_iterator it = raw.begin(); it != raw.end(); ++it)
-           config_info.setValue(it->first, it->second);
-
-       config_info.save();
+       snapper->setConfigInfo(raw);
     }
     else
     {
@@ -1511,7 +1506,7 @@ main(int argc, char** argv)
     cmds.push_back(Cmd("create-config", command_create_config, help_create_config, true, false));
     cmds.push_back(Cmd("delete-config", command_delete_config, help_delete_config, true, false));
     cmds.push_back(Cmd("get-config", command_get_config, help_get_config, true, false));
-    cmds.push_back(Cmd("set-config", command_set_config, help_set_config, true, false));
+    cmds.push_back(Cmd("set-config", command_set_config, help_set_config, true, true));
     cmds.push_back(Cmd("list", command_list, help_list, true, true));
     cmds.push_back(Cmd("create", command_create, help_create, false, true));
     cmds.push_back(Cmd("modify", command_modify, help_modify, false, true));
@@ -1647,6 +1642,21 @@ main(int argc, char** argv)
            cerr << _("Invalid configdata.") << endl;
            exit(EXIT_FAILURE);
        }
+       catch (const AclException& e)
+       {
+           cerr << _("ACL error.") << endl;
+           exit(EXIT_FAILURE);
+       }
+       catch (const InvalidUserException& e)
+       {
+           cerr << _("Invalid user.") << endl;
+           exit(EXIT_FAILURE);
+       }
+       catch (const InvalidGroupException& e)
+       {
+           cerr << _("Invalid group.") << endl;
+           exit(EXIT_FAILURE);
+       }
     }
     else
     {
@@ -1687,6 +1697,12 @@ main(int argc, char** argv)
                cerr << _("Creating snapshot failed.") << endl;
            else if (name == "error.delete_snapshot_failed")
                cerr << _("Deleting snapshot failed.") << endl;
+           else if (name == "error.invalid_user")
+               cerr << _("Invalid user.") << endl;
+           else if (name == "error.invalid_group")
+               cerr << _("Invalid group.") << endl;
+           else if (name == "error.acl_error")
+               cerr << _("ACL error.") << endl;
            else
                cerr << _("Failure") << " (" << name << ")." << endl;
            exit(EXIT_FAILURE);
index 71c80c8d4ebebf728d10bd698ef401fa58177a6d..2c5f0c526bdaa3c8b43fcf5750510620bfc61f5d 100644 (file)
@@ -5,10 +5,16 @@ SUBVOLUME="/"
 # filesystem type
 FSTYPE="btrfs"
 
+
 # users and groups allowed to work with config
 ALLOW_USERS=""
 ALLOW_GROUPS=""
 
+# sync users and groups from ALLOW_USERS and ALLOW_GROUPS to .snapshots
+# directory
+SYNC_ACLS="no"
+
+
 # start comparing pre- and post-snapshot in background after creating
 # post-snapshot
 BACKGROUND_COMPARISON="yes"
index 8fb52135ebd9298fb267a7abaf05d5acd04a579c..896aa77336a7feeddd6f1c8d06d8a296b0168071 100644 (file)
@@ -2,7 +2,7 @@
 <refentry id='snapper-configs5'>
 
   <refentryinfo>
-    <date>2013-07-09</date>
+    <date>2014-01-29</date>
   </refentryinfo>
 
   <refmeta>
@@ -57,6 +57,8 @@
          <para>List of users allowed to operate with the config. The user-names
          must be separated by spaces. Spaces in usernames can be escaped with a
          &quot;\&quot;.</para>
+         <para>Also see the PERMISSONS section in
+         <citerefentry><refentrytitle>snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
          <para>Default value is &quot;&quot; but &quot;root&quot; is always
          implicitly included.</para>
        </listitem>
          <para>List of groups allowed to operate with the config. The group-names
          must be separated by spaces. Spaces in group-names can be escaped with a
          &quot;\&quot;.</para>
+         <para>Also see the PERMISSONS section in
+         <citerefentry><refentrytitle>snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
          <para>Default value is &quot;&quot;.</para>
        </listitem>
       </varlistentry>
 
+      <varlistentry>
+       <term><option>SYNC_ACLS=<replaceable>boolean</replaceable></option></term>
+       <listitem>
+         <para>Defines whether snapper will sync the users and groups from
+         ALLOW_USERS and ALLOW_GROUPS to the <filename>.snapshots</filename>
+         directory.</para>
+         <para>Also see the PERMISSONS section in
+         <citerefentry><refentrytitle>snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+         <para>Default value is &quot;no&quot;.</para>
+         <para>New in version 0.2.0.</para>
+       </listitem>
+      </varlistentry>
+
       <varlistentry>
        <term><option>BACKGROUND_COMPARISON=<replaceable>boolean</replaceable></option></term>
        <listitem>
index d13a006e81e25ac6652287203911450cd4b011b1..54fc1e399014493b49716a798ef7902161c4d51e 100644 (file)
@@ -2,7 +2,7 @@
 <refentry id='snapper8'>
 
   <refentryinfo>
-    <date>2013-04-26</date>
+    <date>2014-01-29</date>
   </refentryinfo>
 
   <refmeta>
     user must also be able to read and access the <filename>.snapshots</filename>
     directory inside the subvolume. The <filename>.snapshots</filename> directory
     must be owned by root and must not be writable by anybody else.</para>
+    <para>Here are some methods how to achieve that:</para>
+    <itemizedlist>
+      <listitem>
+       <para>Make the directory accessible for everyone:</para>
+       <para><command>chmod a+rx .snapshots</command></para>
+      </listitem>
+      <listitem>
+       <para>Make the directory accessible for a group the user belongs to, e.g.:</para>
+       <para><command>chown :users .snapshots</command></para>
+      </listitem>
+      <listitem>
+       <para>Make the directory accessible for the user using ACLs, e.g.:</para>
+       <para><command>setfacl -m u:tux:rx .snapshots</command></para>
+      </listitem>
+    </itemizedlist>
+    <para>The last method can be performed by snapper, see the SYNC_ACLS setting in
+    <citerefentry><refentrytitle>snapper-configs</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
   </refsect1>
 
   <refsect1 id='files'>
index 212331415865e05cf9d786c55c1a9f8fdfb9d2cf..f265d8b46f0ce49393472c7aac6b0849ba6261b4 100644 (file)
@@ -1,3 +1,10 @@
+-------------------------------------------------------------------
+Wed Jan 29 11:09:45 CET 2014 - aschnell@suse.de
+
+- allow to sync ALLOW_USERS and ALLOW_GROUPS to ACL of .snapshots
+  directory (see bnc#860116)
+- 0.2.0
+
 -------------------------------------------------------------------
 Fri Jan 24 10:01:35 CET 2014 - aschnell@suse.de
 
index e88fefdf4a3b1d5e838827b691178c3fd98790c1..651dc1f19ba444274a64519131f3a6658ce5f760 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2012-2013] Novell, Inc.
+ * Copyright (c) [2012-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -1387,6 +1387,11 @@ Client::dispatch(DBus::Connection& conn, DBus::Message& msg)
        DBus::MessageError reply(msg, "error.invalid_userdata", DBUS_ERROR_FAILED);
        conn.send(reply);
     }
+    catch (const AclException& e)
+    {
+       DBus::MessageError reply(msg, "error.acl_error", DBUS_ERROR_FAILED);
+       conn.send(reply);
+    }
     catch (const IOErrorException& e)
     {
        DBus::MessageError reply(msg, "error.io_error", DBUS_ERROR_FAILED);
@@ -1407,6 +1412,16 @@ Client::dispatch(DBus::Connection& conn, DBus::Message& msg)
        DBus::MessageError reply(msg, "error.umount_snapshot", DBUS_ERROR_FAILED);
        conn.send(reply);
     }
+    catch (const InvalidUserException& e)
+    {
+       DBus::MessageError reply(msg, "error.invalid_user", DBUS_ERROR_FAILED);
+       conn.send(reply);
+    }
+    catch (const InvalidGroupException& e)
+    {
+       DBus::MessageError reply(msg, "error.invalid_group", DBUS_ERROR_FAILED);
+       conn.send(reply);
+    }
     catch (...)
     {
        y2err("caught unknown exception");
index 501f927484919f35e04337b2f9b5cce25149b756..31686965d6a902e6fd8c20d4370a7802f6d0722d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2012-2013] Novell, Inc.
+ * Copyright (c) [2012-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
 
 #include <string.h>
 #include <sys/types.h>
-#include <pwd.h>
-#include <grp.h>
 #include <boost/algorithm/string.hpp>
 
 #include <snapper/Log.h>
+#include <snapper/AppUtil.h>
+#include <snapper/SnapperDefines.h>
 
 #include "MetaSnapper.h"
 
@@ -105,59 +105,6 @@ RefCounter::monotonic_time()
 }
 
 
-bool
-get_user_uid(const char* username, uid_t& uid)
-{
-    struct passwd pwd;
-    struct passwd* result;
-
-    long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
-    char buf[bufsize];
-
-    if (getpwnam_r(username, &pwd, buf, bufsize, &result) != 0 || result != &pwd)
-    {
-       y2war("couldn't find username '" << username << "'");
-       return false;
-    }
-
-    memset(pwd.pw_passwd, 0, strlen(pwd.pw_passwd));
-
-    uid = pwd.pw_uid;
-
-    return true;
-}
-
-
-bool
-get_group_uids(const char* groupname, vector<uid_t>& uids)
-{
-    struct group grp;
-    struct group* result;
-
-    long bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
-    char buf[bufsize];
-
-    if (getgrnam_r(groupname, &grp, buf, bufsize, &result) != 0 || result != &grp)
-    {
-       y2war("couldn't find groupname '" << groupname << "'");
-       return false;
-    }
-
-    memset(grp.gr_passwd, 0, strlen(grp.gr_passwd));
-
-    uids.clear();
-
-    for (char** p = grp.gr_mem; *p != NULL; ++p)
-    {
-       uid_t uid;
-       if (get_user_uid(*p, uid))
-           uids.push_back(uid);
-    }
-
-    return true;
-}
-
-
 MetaSnapper::MetaSnapper(ConfigInfo& config_info)
     : config_info(config_info), snapper(NULL)
 {
@@ -177,9 +124,9 @@ MetaSnapper::setConfigInfo(const map<string, string>& raw)
     for (map<string, string>::const_iterator it = raw.begin(); it != raw.end(); ++it)
        config_info.setValue(it->first, it->second);
 
-    config_info.save();
+    getSnapper()->setConfigInfo(raw);
 
-    if (raw.find("ALLOW_USERS") != raw.end() || raw.find("ALLOW_GROUPS") != raw.end())
+    if (raw.find(KEY_ALLOW_USERS) != raw.end() || raw.find(KEY_ALLOW_GROUPS) != raw.end())
        set_permissions();
 }
 
@@ -190,7 +137,7 @@ MetaSnapper::set_permissions()
     uids.clear();
 
     vector<string> users;
-    if (config_info.getValue("ALLOW_USERS", users))
+    if (config_info.getValue(KEY_ALLOW_USERS, users))
     {
        for (vector<string>::const_iterator it = users.begin(); it != users.end(); ++it)
        {
@@ -201,7 +148,7 @@ MetaSnapper::set_permissions()
     }
 
     vector<string> groups;
-    if (config_info.getValue("ALLOW_GROUPS", groups))
+    if (config_info.getValue(KEY_ALLOW_GROUPS, groups))
     {
        for (vector<string>::const_iterator it = groups.begin(); it != groups.end(); ++it)
        {
index 87e0a2731a6ab1f9c25363747e040da5a3d36316..a391b847ca8cf0a07cefa76491d9eed6fed994ae 100644 (file)
@@ -1,7 +1,7 @@
 #
 # spec file for package snapper
 #
-# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,6 +24,7 @@ Source:         snapper-%{version}.tar.bz2
 Prefix:         /usr
 BuildRequires:  boost-devel
 BuildRequires:  gcc-c++
+BuildRequires:  libacl-devel
 BuildRequires:  libtool
 BuildRequires:  libxml2-devel
 BuildRequires:  pkg-config
index 267230cfd2bd3ace3ad81bd9bceb679e036a4a8c..24791c6c6f7009e7b2e378550f86e12407ab4a16 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2004-2012] Novell, Inc.
+ * Copyright (c) [2004-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -32,7 +32,6 @@
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/sendfile.h>
-#include <pwd.h>
 #include <dirent.h>
 #include <mntent.h>
 #include <boost/algorithm/string.hpp>
@@ -281,6 +280,82 @@ namespace snapper
     }
 
 
+    bool
+    get_user_uid(const char* username, uid_t& uid)
+    {
+       struct passwd pwd;
+       struct passwd* result;
+
+       long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+       char buf[bufsize];
+
+       if (getpwnam_r(username, &pwd, buf, bufsize, &result) != 0 || result != &pwd)
+       {
+           y2war("couldn't find username '" << username << "'");
+           return false;
+       }
+
+       memset(pwd.pw_passwd, 0, strlen(pwd.pw_passwd));
+
+       uid = pwd.pw_uid;
+
+       return true;
+    }
+
+
+    bool
+    get_group_uids(const char* groupname, vector<uid_t>& uids)
+    {
+       struct group grp;
+       struct group* result;
+
+       long bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
+       char buf[bufsize];
+
+       if (getgrnam_r(groupname, &grp, buf, bufsize, &result) != 0 || result != &grp)
+       {
+           y2war("couldn't find groupname '" << groupname << "'");
+           return false;
+       }
+
+       memset(grp.gr_passwd, 0, strlen(grp.gr_passwd));
+
+       uids.clear();
+
+       for (char** p = grp.gr_mem; *p != NULL; ++p)
+       {
+           uid_t uid;
+           if (get_user_uid(*p, uid))
+               uids.push_back(uid);
+       }
+
+       return true;
+    }
+
+
+    bool
+    get_group_gid(const char* groupname, gid_t& gid)
+    {
+       struct group grp;
+       struct group* result;
+
+       long bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
+       char buf[bufsize];
+
+       if (getgrnam_r(groupname, &grp, buf, bufsize, &result) != 0 || result != &grp)
+       {
+           y2war("couldn't find groupname '" << groupname << "'");
+           return false;
+       }
+
+       memset(grp.gr_passwd, 0, strlen(grp.gr_passwd));
+
+       gid = grp.gr_gid;
+
+       return true;
+    }
+
+
     StopWatch::StopWatch()
     {
        gettimeofday(&start_tv, NULL);
index 3304030a34c817763cbe26f662384e104d9efca2..5b9bfd8e070653d333b6878e1760945d59ada412 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2004-2012] Novell, Inc.
+ * Copyright (c) [2004-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -25,6 +25,8 @@
 
 #include <sys/time.h>
 #include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
 #include <sstream>
 #include <locale>
 #include <string>
@@ -84,6 +86,10 @@ namespace snapper
 
     string username(uid_t uid);
 
+    bool get_user_uid(const char* username, uid_t& uid);
+    bool get_group_gid(const char* groupname, gid_t& gid);
+    bool get_group_uids(const char* groupname, vector<uid_t>& uids);
+
 
     class StopWatch
     {
index 5deadd996a766f2b6c36eef20bab9ebc7270d074..aeba0cecc9744da605bc6f51c826f4015a6c6560 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Novell, Inc.
+ * Copyright (c) [2011-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -68,6 +68,12 @@ namespace snapper
        virtual const char* what() const throw() { return "IO error"; }
     };
 
+    struct AclException : public IOErrorException
+    {
+       explicit AclException() throw() {}
+       virtual const char* what() const throw() { return "ACL error"; }
+    };
+
     struct ProgramNotInstalledException : public SnapperException
     {
        explicit ProgramNotInstalledException(const char* msg) throw() : msg(msg) {}
@@ -81,6 +87,18 @@ namespace snapper
        virtual const char* what() const throw() { return "XAttributes error"; }
     };
 
+    struct InvalidUserException : public SnapperException
+    {
+       explicit InvalidUserException() throw() {}
+       virtual const char* what() const throw() { return "invalid user"; }
+    };
+
+    struct InvalidGroupException : public SnapperException
+    {
+       explicit InvalidGroupException() throw() {}
+       virtual const char* what() const throw() { return "invalid group"; }
+    };
+
 }
 
 
index a4a8c6020933d0a3e282454c5a76f96b1a8d28c0..a6975afaae32f63f6193a69427787c737c2c3b59 100644 (file)
@@ -53,7 +53,7 @@ endif
 
 
 libsnapper_la_LDFLAGS = -version-info @LIBVERSION_INFO@
-libsnapper_la_LIBADD = -lboost_thread-mt -lboost_system-mt -lxml2 -lz -lm
+libsnapper_la_LIBADD = -lboost_thread-mt -lboost_system-mt -lxml2 -lacl -lz -lm
 
 pkgincludedir = $(includedir)/snapper
 
index 400ced6fbf1a5baf26d44b667acf84d7b25e108d..08fa70b99c53d500cb60f11c8425b7f0722d9a4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2011-2013] Novell, Inc.
+ * Copyright (c) [2011-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -27,6 +27,9 @@
 #include <glob.h>
 #include <string.h>
 #include <mntent.h>
+#include <sys/acl.h>
+#include <acl/libacl.h>
+#include <set>
 #include <boost/algorithm/string.hpp>
 
 #include "snapper/Snapper.h"
@@ -50,7 +53,7 @@ namespace snapper
     ConfigInfo::ConfigInfo(const string& config_name)
        : SysconfigFile(CONFIGSDIR "/" + config_name), config_name(config_name), subvolume("/")
     {
-       if (!getValue("SUBVOLUME", subvolume))
+       if (!getValue(KEY_SUBVOLUME, subvolume))
            throw InvalidConfigException();
     }
 
@@ -58,7 +61,7 @@ namespace snapper
     void
     ConfigInfo::checkKey(const string& key) const
     {
-       if (key == "SUBVOLUME" || key == "FSTYPE")
+       if (key == KEY_SUBVOLUME || key == KEY_FSTYPE)
            throw InvalidConfigdataException();
 
        try
@@ -89,7 +92,7 @@ namespace snapper
        }
 
        string fstype = "btrfs";
-       config_info->getValue("FSTYPE", fstype);
+       config_info->getValue(KEY_FSTYPE, fstype);
        filesystem = Filesystem::create(fstype, config_info->getSubvolume());
 
        y2mil("subvolume:" << config_info->getSubvolume() << " filesystem:" <<
@@ -359,8 +362,8 @@ namespace snapper
        try
        {
            SysconfigFile config(CONFIGSDIR "/" + config_name);
-           config.setValue("SUBVOLUME", subvolume);
-           config.setValue("FSTYPE", filesystem->fstype());
+           config.setValue(KEY_SUBVOLUME, subvolume);
+           config.setValue(KEY_FSTYPE, filesystem->fstype());
        }
        catch (const FileNotFoundException& e)
        {
@@ -444,6 +447,176 @@ namespace snapper
     }
 
 
+    void
+    Snapper::setConfigInfo(const map<string, string>& raw)
+    {
+       for (map<string, string>::const_iterator it = raw.begin(); it != raw.end(); ++it)
+           config_info->setValue(it->first, it->second);
+
+       config_info->save();
+
+       if (raw.find(KEY_ALLOW_USERS) != raw.end() || raw.find(KEY_ALLOW_GROUPS) != raw.end() ||
+           raw.find(KEY_SYNC_ACLS) != raw.end())
+       {
+           bool sync_acl;
+           if (config_info->getValue(KEY_SYNC_ACLS, sync_acl) && sync_acl == true)
+               syncAcls();
+       }
+    }
+
+
+    void
+    Snapper::syncAcls() const
+    {
+       vector<uid_t> uids;
+       vector<string> users;
+       if (config_info->getValue(KEY_ALLOW_USERS, users))
+       {
+           for (vector<string>::const_iterator it = users.begin(); it != users.end(); ++it)
+           {
+               uid_t uid;
+               if (!get_user_uid(it->c_str(), uid))
+                   throw InvalidUserException();
+               uids.push_back(uid);
+           }
+       }
+
+       vector<gid_t> gids;
+       vector<string> groups;
+       if (config_info->getValue(KEY_ALLOW_GROUPS, groups))
+       {
+           for (vector<string>::const_iterator it = groups.begin(); it != groups.end(); ++it)
+           {
+               gid_t gid;
+               if (!get_group_gid(it->c_str(), gid))
+                   throw InvalidGroupException();
+               gids.push_back(gid);
+           }
+       }
+
+       syncAcls(uids, gids);
+    }
+
+
+    static void
+    set_acl_permissions(acl_entry_t entry)
+    {
+       acl_permset_t permset;
+       if (acl_get_permset(entry, &permset) != 0)
+           throw AclException();
+
+       if (acl_add_perm(permset, ACL_READ) != 0 || acl_delete_perm(permset, ACL_WRITE) != 0 ||
+           acl_add_perm(permset, ACL_EXECUTE) != 0)
+           throw AclException();
+    };
+
+
+    static void
+    add_acl_permissions(acl_t* acl, acl_tag_t tag, const void* qualifier)
+    {
+       acl_entry_t entry;
+       if (acl_create_entry(acl, &entry) != 0)
+           throw AclException();
+
+       if (acl_set_tag_type(entry, tag) != 0)
+           throw AclException();
+
+       if (acl_set_qualifier(entry, qualifier) != 0)
+           throw AclException();
+
+       set_acl_permissions(entry);
+    };
+
+
+    void
+    Snapper::syncAcls(const vector<uid_t>& uids, const vector<gid_t>& gids) const
+    {
+       SDir infos_dir = openInfosDir();
+
+       acl_t acl = acl_get_fd(infos_dir.fd());
+       if (!acl)
+           throw AclException();
+
+       set<uid_t> remaining_uids = set<uid_t>(uids.begin(), uids.end());
+       set<gid_t> remaining_gids = set<gid_t>(gids.begin(), gids.end());
+
+       acl_entry_t entry;
+       if (acl_get_entry(acl, ACL_FIRST_ENTRY, &entry) == 1)
+       {
+           do {
+
+               acl_tag_t tag;
+               if (acl_get_tag_type(entry, &tag) != 0)
+                   throw AclException();
+
+               switch (tag)
+               {
+                   case ACL_USER: {
+
+                       uid_t* uid = (uid_t*) acl_get_qualifier(entry);
+                       if (!uid)
+                           throw AclException();
+
+                       if (contains(remaining_uids, *uid))
+                       {
+                           remaining_uids.erase(*uid);
+
+                           set_acl_permissions(entry);
+                       }
+                       else
+                       {
+                           if (acl_delete_entry(acl, entry) != 0)
+                               throw AclException();
+                       }
+
+                   } break;
+
+                   case ACL_GROUP: {
+
+                       gid_t* gid = (gid_t*) acl_get_qualifier(entry);
+                       if (!gid)
+                           throw AclException();
+
+                       if (contains(remaining_gids, *gid))
+                       {
+                           remaining_gids.erase(*gid);
+
+                           set_acl_permissions(entry);
+                       }
+                       else
+                       {
+                           if (acl_delete_entry(acl, entry) != 0)
+                               throw AclException();
+                       }
+
+                   } break;
+
+               }
+
+           } while (acl_get_entry(acl, ACL_NEXT_ENTRY, &entry) == 1);
+       }
+
+       for (set<uid_t>::const_iterator it = remaining_uids.begin(); it != remaining_uids.end(); ++it)
+       {
+           add_acl_permissions(&acl, ACL_USER, &(*it));
+       }
+
+       for (set<gid_t>::const_iterator it = remaining_gids.begin(); it != remaining_gids.end(); ++it)
+       {
+           add_acl_permissions(&acl, ACL_GROUP, &(*it));
+       }
+
+       if (acl_calc_mask(&acl) != 0)
+           throw AclException();
+
+       if (acl_set_fd(infos_dir.fd(), acl) != 0)
+           throw AclException();
+
+       if (acl_free(acl) != 0)
+           throw AclException();
+    }
+
+
     static bool
     is_subpath(const string& a, const string& b)
     {
index 1f30b74a907ca855bcdc2cd5d91eaa3c64a7b1de..730ac8b66bb92c51c3b71f56d34e6548a7d47d08 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2011-2013] Novell, Inc.
+ * Copyright (c) [2011-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -156,6 +156,10 @@ namespace snapper
 
        const Filesystem* getFilesystem() const { return filesystem; }
 
+       void setConfigInfo(const map<string, string>& raw);
+
+       void syncAcls() const;
+
     private:
 
        void filter1(list<Snapshots::iterator>& tmp, time_t min_age);
@@ -163,6 +167,8 @@ namespace snapper
 
        void loadIgnorePatterns();
 
+       void syncAcls(const vector<uid_t>& uids, const vector<gid_t>& gids) const;
+
        ConfigInfo* config_info;
 
        Filesystem* filesystem;
index 240a6bd4e029490e61ae61033cd88448f96a806b..c26ad10f857f876960228bc2e817cbd3ef5d81c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) [2004-2013] Novell, Inc.
+ * Copyright (c) [2004-2014] Novell, Inc.
  *
  * All Rights Reserved.
  *
@@ -24,6 +24,8 @@
 #define SNAPPER_SNAPPER_DEFINES_H
 
 
+// path definitions
+
 #define SYSCONFIGFILE CONFDIR "/snapper"
 
 #define CONFIGSDIR "/etc/snapper/configs"
 #define FILTERSDIR "/etc/snapper/filters"
 
 
+// keys from the config files
+
+#define KEY_SUBVOLUME "SUBVOLUME"
+#define KEY_FSTYPE "FSTYPE"
+
+#define KEY_ALLOW_USERS "ALLOW_USERS"
+#define KEY_ALLOW_GROUPS "ALLOW_GROUPS"
+#define KEY_SYNC_ACLS "SYNC_ACLS"
+
+
 #endif