Hello community, here is the log from the commit of package snapper for openSUSE:Factory checked in at 2014-01-30 09:02:21 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/snapper (Old) and /work/SRC/openSUSE:Factory/.snapper.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "snapper" Changes: -------- --- /work/SRC/openSUSE:Factory/snapper/snapper.changes 2013-12-16 07:09:59.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.snapper.new/snapper.changes 2014-01-30 09:02:23.000000000 +0100 @@ -1,0 +2,12 @@ +Wed Jan 29 11:09:45 CET 2014 - [email protected] + +- 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 - [email protected] + +- removed grub-snapper-plugin subpackage (fate#316232) + +------------------------------------------------------------------- Old: ---- snapper-0.1.8.tar.bz2 New: ---- snapper-0.2.0.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ snapper.spec ++++++ --- /var/tmp/diff_new_pack.OBgUGO/_old 2014-01-30 09:02:23.000000000 +0100 +++ /var/tmp/diff_new_pack.OBgUGO/_new 2014-01-30 09:02:23.000000000 +0100 @@ -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 @@ -17,13 +17,14 @@ Name: snapper -Version: 0.1.8 +Version: 0.2.0 Release: 0 BuildRoot: %{_tmppath}/%{name}-%{version}-build Source: snapper-%{version}.tar.bz2 Prefix: /usr BuildRequires: boost-devel BuildRequires: gcc-c++ +BuildRequires: libacl-devel BuildRequires: libtool BuildRequires: libxml2-devel BuildRequires: pkg-config @@ -153,6 +154,7 @@ %package -n libsnapper-devel Requires: boost-devel Requires: gcc-c++ +Requires: libacl-devel Requires: libsnapper2 = %version Requires: libstdc++-devel Requires: libxml2-devel @@ -203,31 +205,6 @@ %doc %{_mandir}/*/snapper-zypp-plugin.8* %doc %{_mandir}/*/snapper-zypp-plugin.conf.5* -%package -n grub-snapper-plugin -BuildArch: noarch -Requires: python -Requires: python-xattr -Requires: snapper = %version -%if 0%{?suse_version} -Supplements: packageand(snapper-zypp-plugin:grub2) -%endif -Summary: A snapper plugin for adding snapshot metadata for grub2 -Group: System/Packages - -%description -n grub-snapper-plugin -This package contains a plugin for snapper that adds metadata to snapshots -used by grub2. - -Authors: --------- - Arvin Schnell <[email protected]> - -%files -n grub-snapper-plugin -%defattr(-,root,root) -%dir /usr/lib/snapper -%dir /usr/lib/snapper/plugins -/usr/lib/snapper/plugins/grub.py* - %package -n pam_snapper Requires: pam Requires: snapper = %version ++++++ snapper-0.1.8.tar.bz2 -> snapper-0.2.0.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/LIBVERSION new/snapper-0.2.0/LIBVERSION --- old/snapper-0.1.8/LIBVERSION 2013-10-09 09:28:53.000000000 +0200 +++ new/snapper-0.2.0/LIBVERSION 2014-01-29 16:48:30.000000000 +0100 @@ -1 +1 @@ -2.2.0 +2.3.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/VERSION new/snapper-0.2.0/VERSION --- old/snapper-0.1.8/VERSION 2013-12-02 18:32:17.000000000 +0100 +++ new/snapper-0.2.0/VERSION 2014-01-29 16:48:30.000000000 +0100 @@ -1 +1 @@ -0.1.8 +0.2.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/client/snapper.cc new/snapper-0.2.0/client/snapper.cc --- old/snapper-0.1.8/client/snapper.cc 2013-12-11 10:35:41.000000000 +0100 +++ new/snapper-0.2.0/client/snapper.cc 2014-01-29 16:48:30.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2013] Novell, Inc. + * Copyright (c) [2011-2014] Novell, Inc. * * All Rights Reserved. * @@ -488,12 +488,7 @@ 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 @@ 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 @@ 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 @@ 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); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/data/default-config new/snapper-0.2.0/data/default-config --- old/snapper-0.1.8/data/default-config 2013-10-16 17:45:43.000000000 +0200 +++ new/snapper-0.2.0/data/default-config 2014-01-29 16:48:30.000000000 +0100 @@ -5,10 +5,16 @@ # 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_ACL="no" + + # start comparing pre- and post-snapshot in background after creating # post-snapshot BACKGROUND_COMPARISON="yes" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/doc/snapper-configs.xml.in new/snapper-0.2.0/doc/snapper-configs.xml.in --- old/snapper-0.1.8/doc/snapper-configs.xml.in 2013-10-21 10:13:14.000000000 +0200 +++ new/snapper-0.2.0/doc/snapper-configs.xml.in 2014-01-29 16:48:30.000000000 +0100 @@ -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 "\".</para> + <para>Also see the PERMISSONS section in + <citerefentry><refentrytitle>snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> <para>Default value is "" but "root" is always implicitly included.</para> </listitem> @@ -68,10 +70,25 @@ <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 "\".</para> + <para>Also see the PERMISSONS section in + <citerefentry><refentrytitle>snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> <para>Default value is "".</para> </listitem> </varlistentry> + <varlistentry> + <term><option>SYNC_ACL=<replaceable>boolean</replaceable></option></term> + <listitem> + <para>Defines whether snapper will sync the users and groups from + ALLOW_USERS and ALLOW_GROUPS to the ACL of 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 "no".</para> + <para>New in version 0.2.0.</para> + </listitem> + </varlistentry> + <varlistentry> <term><option>BACKGROUND_COMPARISON=<replaceable>boolean</replaceable></option></term> <listitem> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/doc/snapper.xml.in new/snapper-0.2.0/doc/snapper.xml.in --- old/snapper-0.1.8/doc/snapper.xml.in 2013-10-31 11:25:16.000000000 +0100 +++ new/snapper-0.2.0/doc/snapper.xml.in 2014-01-29 16:48:30.000000000 +0100 @@ -2,7 +2,7 @@ <refentry id='snapper8'> <refentryinfo> - <date>2013-04-26</date> + <date>2014-01-29</date> </refentryinfo> <refmeta> @@ -490,6 +490,23 @@ 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_ACL setting in + <citerefentry><refentrytitle>snapper-configs</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para> </refsect1> <refsect1 id='files'> @@ -558,7 +575,8 @@ <citerefentry><refentrytitle>pam_snapper</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>btrfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>lvm</refentrytitle><manvolnum>8</manvolnum></citerefentry>, - <citerefentry><refentrytitle>attr</refentrytitle><manvolnum>5</manvolnum></citerefentry> + <citerefentry><refentrytitle>attr</refentrytitle><manvolnum>5</manvolnum></citerefentry>, + <citerefentry><refentrytitle>acl</refentrytitle><manvolnum>5</manvolnum></citerefentry> </para> </refsect1> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/scripts/Makefile.am new/snapper-0.2.0/scripts/Makefile.am --- old/snapper-0.1.8/scripts/Makefile.am 2013-10-15 15:27:35.000000000 +0200 +++ new/snapper-0.2.0/scripts/Makefile.am 2014-01-29 16:48:30.000000000 +0100 @@ -14,13 +14,12 @@ endif -EXTRA_DIST = snapper-hourly snapper-daily zypp-plugin.py grub-plugin.py $(pam_snapper_SCRIPTS) +EXTRA_DIST = snapper-hourly snapper-daily zypp-plugin.py $(pam_snapper_SCRIPTS) install-data-local: install -D snapper-hourly $(DESTDIR)/etc/cron.hourly/suse.de-snapper install -D snapper-daily $(DESTDIR)/etc/cron.daily/suse.de-snapper if HAVE_ZYPP install -D zypp-plugin.py $(DESTDIR)/usr/lib/zypp/plugins/commit/snapper.py - install -D grub-plugin.py $(DESTDIR)/usr/lib/snapper/plugins/grub.py endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/scripts/Makefile.in new/snapper-0.2.0/scripts/Makefile.in --- old/snapper-0.1.8/scripts/Makefile.in 2013-12-13 16:12:20.000000000 +0100 +++ new/snapper-0.2.0/scripts/Makefile.in 2014-01-29 17:28:30.000000000 +0100 @@ -291,7 +291,7 @@ @HAVE_PAM_TRUE@ pam_snapper_useradd.sh \ @HAVE_PAM_TRUE@ pam_snapper_userdel.sh -EXTRA_DIST = snapper-hourly snapper-daily zypp-plugin.py grub-plugin.py $(pam_snapper_SCRIPTS) +EXTRA_DIST = snapper-hourly snapper-daily zypp-plugin.py $(pam_snapper_SCRIPTS) all: all-am .SUFFIXES: @@ -526,7 +526,6 @@ install -D snapper-hourly $(DESTDIR)/etc/cron.hourly/suse.de-snapper install -D snapper-daily $(DESTDIR)/etc/cron.daily/suse.de-snapper @HAVE_ZYPP_TRUE@ install -D zypp-plugin.py $(DESTDIR)/usr/lib/zypp/plugins/commit/snapper.py -@HAVE_ZYPP_TRUE@ install -D grub-plugin.py $(DESTDIR)/usr/lib/snapper/plugins/grub.py # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/scripts/grub-plugin.py new/snapper-0.2.0/scripts/grub-plugin.py --- old/snapper-0.1.8/scripts/grub-plugin.py 2013-11-25 14:29:30.000000000 +0100 +++ new/snapper-0.2.0/scripts/grub-plugin.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,64 +0,0 @@ -#!/usr/bin/python -# -# Copyright (c) [2011-2013] Novell, Inc. -# -# 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. -# -# Author: Arvin Schnell <[email protected]> -# - - -from subprocess import check_output -from datetime import datetime -from xattr import xattr -from fcntl import ioctl -from os import open, close, O_RDONLY -from ctypes import c_ulonglong -from sys import argv - - -BTRFS_IOC_SUBVOL_GETFLAGS = 0x80089419 -BTRFS_IOC_SUBVOL_SETFLAGS = 0x4008941a -BTRFS_SUBVOL_RDONLY = 0x2 - - -number = argv[1] - -kernel = check_output(["ls", "-1v", "/lib/modules"]).splitlines()[-1] -date = datetime.utcnow() -important = argv[2] - - -fd = open("/.snapshots/%s/snapshot" % number, O_RDONLY) - -orig_buf = c_ulonglong() -ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, orig_buf, True) - -new_buf = c_ulonglong(orig_buf.value & ~BTRFS_SUBVOL_RDONLY) -ioctl(fd, BTRFS_IOC_SUBVOL_SETFLAGS, new_buf, True) - -x = xattr(fd) - -x.set("user.kernel", kernel) -x.set("user.date", date.strftime("%F %T")) -x.set("user.important", important) - -ioctl(fd, BTRFS_IOC_SUBVOL_SETFLAGS, orig_buf, True) - -close(fd) - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/server/Client.cc new/snapper-0.2.0/server/Client.cc --- old/snapper-0.1.8/server/Client.cc 2013-10-21 10:20:11.000000000 +0200 +++ new/snapper-0.2.0/server/Client.cc 2014-01-29 16:48:30.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) [2012-2013] Novell, Inc. + * Copyright (c) [2012-2014] Novell, Inc. * * All Rights Reserved. * @@ -1387,6 +1387,11 @@ 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 @@ 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"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/server/MetaSnapper.cc new/snapper-0.2.0/server/MetaSnapper.cc --- old/snapper-0.1.8/server/MetaSnapper.cc 2013-10-02 11:18:37.000000000 +0200 +++ new/snapper-0.2.0/server/MetaSnapper.cc 2014-01-29 16:48:30.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) [2012-2013] Novell, Inc. + * Copyright (c) [2012-2014] Novell, Inc. * * All Rights Reserved. * @@ -22,11 +22,11 @@ #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 @@ } -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 @@ 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 @@ 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 @@ } 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) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/AppUtil.cc new/snapper-0.2.0/snapper/AppUtil.cc --- old/snapper-0.1.8/snapper/AppUtil.cc 2013-06-03 15:47:12.000000000 +0200 +++ new/snapper-0.2.0/snapper/AppUtil.cc 2014-01-29 16:48:30.000000000 +0100 @@ -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 @@ } + 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); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/AppUtil.h new/snapper-0.2.0/snapper/AppUtil.h --- old/snapper-0.1.8/snapper/AppUtil.h 2013-10-07 14:47:05.000000000 +0200 +++ new/snapper-0.2.0/snapper/AppUtil.h 2014-01-29 16:48:30.000000000 +0100 @@ -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 @@ 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 { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/Exception.h new/snapper-0.2.0/snapper/Exception.h --- old/snapper-0.1.8/snapper/Exception.h 2013-07-15 15:17:38.000000000 +0200 +++ new/snapper-0.2.0/snapper/Exception.h 2014-01-29 16:48:30.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 Novell, Inc. + * Copyright (c) [2011-2014] Novell, Inc. * * All Rights Reserved. * @@ -68,6 +68,12 @@ 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 @@ 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"; } + }; + } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/Makefile.am new/snapper-0.2.0/snapper/Makefile.am --- old/snapper-0.1.8/snapper/Makefile.am 2013-10-25 11:12:41.000000000 +0200 +++ new/snapper-0.2.0/snapper/Makefile.am 2014-01-29 16:48:30.000000000 +0100 @@ -53,7 +53,7 @@ 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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/Makefile.in new/snapper-0.2.0/snapper/Makefile.in --- old/snapper-0.1.8/snapper/Makefile.in 2013-12-13 16:12:20.000000000 +0100 +++ new/snapper-0.2.0/snapper/Makefile.in 2014-01-29 17:28:30.000000000 +0100 @@ -398,7 +398,7 @@ SnapperTypes.h SnapperDefines.h Version.h $(TMP_XA) \ $(am__append_1) $(am__append_2) $(am__append_3) 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 pkginclude_HEADERS = \ Version.h \ Factory.h \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/Snapper.cc new/snapper-0.2.0/snapper/Snapper.cc --- old/snapper-0.1.8/snapper/Snapper.cc 2013-10-25 11:12:41.000000000 +0200 +++ new/snapper-0.2.0/snapper/Snapper.cc 2014-01-29 16:48:30.000000000 +0100 @@ -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 @@ 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 @@ 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 @@ } 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 @@ 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) { @@ -368,6 +371,14 @@ } filesystem->createConfig(); + +#if 1 + if (subvolume == "/" && filesystem->fstype() == "btrfs" && + access("/usr/lib/snapper/plugins/grub", X_OK) == 0) + { + SystemCmd cmd("/usr/lib/snapper/plugins/grub --enable"); + } +#endif } @@ -379,6 +390,14 @@ auto_ptr<Snapper> snapper(new Snapper(config_name)); +#if 1 + if (snapper->subvolumeDir() == "/" && snapper->getFilesystem()->fstype() == "btrfs" && + access("/usr/lib/snapper/plugins/grub", X_OK) == 0) + { + SystemCmd cmd("/usr/lib/snapper/plugins/grub --disable"); + } +#endif + Snapshots& snapshots = snapper->getSnapshots(); for (Snapshots::iterator it = snapshots.begin(); it != snapshots.end(); ) { @@ -428,6 +447,176 @@ } + 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_ACL) != raw.end()) + { + bool sync_acl; + if (config_info->getValue(KEY_SYNC_ACL, sync_acl) && sync_acl == true) + syncAcl(); + } + } + + + void + Snapper::syncAcl() 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); + } + } + + syncAcl(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::syncAcl(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) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/Snapper.h new/snapper-0.2.0/snapper/Snapper.h --- old/snapper-0.1.8/snapper/Snapper.h 2013-10-25 11:12:41.000000000 +0200 +++ new/snapper-0.2.0/snapper/Snapper.h 2014-01-29 16:48:30.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) [2011-2013] Novell, Inc. + * Copyright (c) [2011-2014] Novell, Inc. * * All Rights Reserved. * @@ -156,6 +156,10 @@ const Filesystem* getFilesystem() const { return filesystem; } + void setConfigInfo(const map<string, string>& raw); + + void syncAcl() const; + private: void filter1(list<Snapshots::iterator>& tmp, time_t min_age); @@ -163,6 +167,8 @@ void loadIgnorePatterns(); + void syncAcl(const vector<uid_t>& uids, const vector<gid_t>& gids) const; + ConfigInfo* config_info; Filesystem* filesystem; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/SnapperDefines.h new/snapper-0.2.0/snapper/SnapperDefines.h --- old/snapper-0.1.8/snapper/SnapperDefines.h 2013-02-22 10:36:22.000000000 +0100 +++ new/snapper-0.2.0/snapper/SnapperDefines.h 2014-01-29 16:48:30.000000000 +0100 @@ -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" @@ -32,4 +34,14 @@ #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_ACL "SYNC_ACL" + + #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/Snapshot.cc new/snapper-0.2.0/snapper/Snapshot.cc --- old/snapper-0.1.8/snapper/Snapshot.cc 2013-10-25 11:12:41.000000000 +0200 +++ new/snapper-0.2.0/snapper/Snapshot.cc 2014-01-29 16:48:30.000000000 +0100 @@ -669,14 +669,9 @@ #if 1 if (snapper->subvolumeDir() == "/" && snapper->getFilesystem()->fstype() == "btrfs" && - snapshot.getType() == PRE && access("/usr/lib/snapper/plugins/grub.py", X_OK) == 0) + access("/usr/lib/snapper/plugins/grub", X_OK) == 0) { - map<string, string> userdata = snapshot.getUserdata(); - map<string, string>::const_iterator it = userdata.find("important"); - bool important = it != userdata.end() && it->second == "yes"; - - SystemCmd cmd(sformat("/usr/lib/snapper/plugins/grub.py %d %s", snapshot.getNum(), - important ? "yes" : "no")); + SystemCmd cmd("/usr/lib/snapper/plugins/grub --refresh"); } #endif @@ -705,6 +700,14 @@ snapshot->userdata = userdata; snapshot->writeInfo(); + +#if 1 + if (snapper->subvolumeDir() == "/" && snapper->getFilesystem()->fstype() == "btrfs" && + access("/usr/lib/snapper/plugins/grub", X_OK) == 0) + { + SystemCmd cmd("/usr/lib/snapper/plugins/grub --refresh"); + } +#endif } @@ -739,6 +742,14 @@ infos_dir.unlink(decString(snapshot->getNum()), AT_REMOVEDIR); entries.erase(snapshot); + +#if 1 + if (snapper->subvolumeDir() == "/" && snapper->getFilesystem()->fstype() == "btrfs" && + access("/usr/lib/snapper/plugins/grub", X_OK) == 0) + { + SystemCmd cmd("/usr/lib/snapper/plugins/grub --refresh"); + } +#endif } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper/Version.h new/snapper-0.2.0/snapper/Version.h --- old/snapper-0.1.8/snapper/Version.h 2013-12-13 16:12:25.000000000 +0100 +++ new/snapper-0.2.0/snapper/Version.h 2014-01-29 17:28:32.000000000 +0100 @@ -25,7 +25,7 @@ #define LIBSNAPPER_MAJOR="2" -#define LIBSNAPPER_MINOR="2" +#define LIBSNAPPER_MINOR="3" #define LIBSNAPPER_PATCHLEVEL="0" #define LIBSNAPPER_VERSION ( LIBSNAPPER_MAJOR * 10000 + \\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/snapper-0.1.8/snapper.spec.in new/snapper-0.2.0/snapper.spec.in --- old/snapper-0.1.8/snapper.spec.in 2013-12-13 16:03:59.000000000 +0100 +++ new/snapper-0.2.0/snapper.spec.in 2014-01-29 17:28:22.000000000 +0100 @@ -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 @@ Prefix: /usr BuildRequires: boost-devel BuildRequires: gcc-c++ +BuildRequires: libacl-devel BuildRequires: libtool BuildRequires: libxml2-devel BuildRequires: pkg-config @@ -153,6 +154,7 @@ %package -n libsnapper-devel Requires: boost-devel Requires: gcc-c++ +Requires: libacl-devel Requires: libsnapper@LIBVERSION_MAJOR@ = %version Requires: libstdc++-devel Requires: libxml2-devel @@ -203,31 +205,6 @@ %doc %{_mandir}/*/snapper-zypp-plugin.8* %doc %{_mandir}/*/snapper-zypp-plugin.conf.5* -%package -n grub-snapper-plugin -BuildArch: noarch -Requires: python -Requires: python-xattr -Requires: snapper = %version -%if 0%{?suse_version} -Supplements: packageand(snapper-zypp-plugin:grub2) -%endif -Summary: A snapper plugin for adding snapshot metadata for grub2 -Group: System/Packages - -%description -n grub-snapper-plugin -This package contains a plugin for snapper that adds metadata to snapshots -used by grub2. - -Authors: --------- - Arvin Schnell <[email protected]> - -%files -n grub-snapper-plugin -%defattr(-,root,root) -%dir /usr/lib/snapper -%dir /usr/lib/snapper/plugins -/usr/lib/snapper/plugins/grub.py* - %package -n pam_snapper Requires: pam Requires: snapper = %version -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
