Hello community,

here is the log from the commit of package shadow for openSUSE:Factory checked 
in at 2019-01-29 14:40:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/shadow (Old)
 and      /work/SRC/openSUSE:Factory/.shadow.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "shadow"

Tue Jan 29 14:40:11 2019 rev:29 rq:668288 version:4.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/shadow/shadow.changes    2018-11-12 
09:48:13.448573231 +0100
+++ /work/SRC/openSUSE:Factory/.shadow.new.28833/shadow.changes 2019-01-29 
14:40:13.119420021 +0100
@@ -1,0 +2,6 @@
+Wed Jan 23 09:35:01 UTC 2019 - adam.ma...@suse.de
+
+- btrfs-subvolumes.patch: implement support for creating user home
+  directories on btrfs subvolumes (fate#316134)
+
+-------------------------------------------------------------------
@@ -28 +34 @@
-  Additionally changed in that patch:
+  Additionally changed in that patch (bsc#1106914):

New:
----
  btrfs-subvolumes.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ shadow.spec ++++++
--- /var/tmp/diff_new_pack.31ONqj/_old  2019-01-29 14:40:14.199418706 +0100
+++ /var/tmp/diff_new_pack.31ONqj/_new  2019-01-29 14:40:14.199418706 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package shadow
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -12,7 +12,7 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via https://bugs.opensuse.org/
+# Please submit bugfixes or comments via http://bugs.opensuse.org/
 #
 
 
@@ -45,11 +45,15 @@
 Patch11:        useradd-mkdirs.patch
 Patch12:        shadow-4.6.0-fix-usermod-prefix-crash.patch
 Patch20:        disable_new_audit_function.patch
+Patch21:        btrfs-subvolumes.patch
 BuildRequires:  audit-devel > 2.3
+BuildRequires:  autoconf
+BuildRequires:  automake
 BuildRequires:  libacl-devel
 BuildRequires:  libattr-devel
 BuildRequires:  libselinux-devel
 BuildRequires:  libsemanage-devel
+BuildRequires:  libtool
 BuildRequires:  pam-devel
 BuildRequires:  xz
 Requires(pre):  group(root)
@@ -80,6 +84,7 @@
 %if 0%{?suse_version} < 1330
 %patch20 -p1
 %endif
+%patch21 -p1
 
 iconv -f ISO88591 -t utf-8  doc/HOWTO > doc/HOWTO.utf8
 mv -v doc/HOWTO.utf8 doc/HOWTO
@@ -88,6 +93,7 @@
 export CFLAGS="%{optflags} -fpie"
 export LDFLAGS="-pie"
 
+autoreconf -fvi
 %configure \
         --disable-shadowgrp \
        --enable-account-tools-setuid \

++++++ btrfs-subvolumes.patch ++++++
commit 52ea836ffbfa4d6797cf89d6ada58f76bee9cf6b
Author: Adam Majer <ama...@suse.de>
Date:   Wed Jan 23 16:17:05 2019 +0100

    Add autotools support for BtrFS option
    
    Feature is enabled by default, if headers are available. It can be
    turned off explictly.

commit 81ead2042afcdb8d423da855cf1528618a4e0c01
Author: Adam Majer <ama...@suse.de>
Date:   Mon Jan 21 09:32:36 2019 +0100

    Add support for btrfs subvolumes for user homes
    
    new switch added to useradd command, --btrfs-subvolume-home. When
    specified *and* the filesystem is detected as btrfs, it will create a
    subvolume for user's home instead of a plain directory. This is done via
    `btrfs subvolume` command.  Specifying the new switch while trying to
    create home on non-btrfs will result in an error.
    
    userdel -r will handle and remove this subvolume transparently via
    `btrfs subvolume` command. Previosuly this failed as you can't rmdir a
    subvolume.
    
    usermod, when moving user's home across devices, will detect if the home
    is a subvolume and issue an error messages instead of copying it. Moving
    user's home (as subvolume) on same btrfs works transparently.


--- a/configure.ac
+++ b/configure.ac
@@ -256,6 +256,9 @@ AC_ARG_WITH(audit,
 AC_ARG_WITH(libpam,
        [AC_HELP_STRING([--with-libpam], [use libpam for PAM support 
@<:@default=yes if found@:>@])],
        [with_libpam=$withval], [with_libpam=maybe])
+AC_ARG_WITH(btrfs,
+       [AC_HELP_STRING([--with-btrfs], [add BtrFS support @<:@default=yes if 
found@:>@])],
+       [with_selinux=$withval], [with_selinux=maybe])
 AC_ARG_WITH(selinux,
        [AC_HELP_STRING([--with-selinux], [use SELinux support @<:@default=yes 
if found@:>@])],
        [with_selinux=$withval], [with_selinux=maybe])
@@ -453,6 +456,20 @@ if test "$with_libcrack" = "yes"; then
                AC_DEFINE(HAVE_LIBCRACK_PW, 1, [Defined if it includes *Pw 
functions.]))
 fi
 
+if test "$with_btrfs" != "no"; then
+       AC_CHECK_HEADERS([sys/statfs.h linux/magic.h linux/btrfs_tree.h], \
+               [btrfs_headers="yes"], [btrfs_headers="no"])
+       if test "$btrfs_headers$with_btrfs" = "noyes" ; then
+               AC_MSG_ERROR([One of sys/statfs.h linux/magic.h 
linux/btrfs_tree.h is missing])
+       fi
+
+       if test "$btrfs_headers" = "yes" ; then
+               AC_DEFINE(WITH_BTRFS, 1, [Build shadow with BtrFS support])
+               with_btrfs="yes"
+       fi
+fi
+AM_CONDITIONAL(WITH_BTRFS, test x$with_btrfs = xyes)
+
 AC_SUBST(LIBSELINUX)
 AC_SUBST(LIBSEMANAGE)
 if test "$with_selinux" != "no"; then
@@ -672,6 +689,7 @@ if test "$with_libpam" = "yes"; then
 echo " suid account management tools:  $enable_acct_tools_setuid"
 fi
 echo " SELinux support:                $with_selinux"
+echo " BtrFS support:                  $with_btrfs"
 echo " ACL support:                    $with_acl"
 echo " Extended Attributes support:    $with_attr"
 echo " tcb support (incomplete):       $with_tcb"
--- a/lib/prototypes.h
+++ b/lib/prototypes.h
@@ -72,6 +72,14 @@ extern int expire (const struct passwd *
 /* isexpired.c */
 extern int isexpired (const struct passwd *, /*@null@*/const struct spwd *);
 
+/* btrfs.c */
+#ifdef WITH_BTRFS
+extern int btrfs_create_subvolume(const char *path);
+extern int btrfs_remove_subvolume(const char *path);
+extern int btrfs_is_subvolume(const char *path);
+extern int is_btrfs(const char *path);
+#endif
+
 /* basename() renamed to Basename() to avoid libc name space confusion */
 /* basename.c */
 extern /*@observer@*/const char *Basename (const char *str);
--- a/libmisc/Makefile.am
+++ b/libmisc/Makefile.am
@@ -72,3 +72,8 @@ libmisc_a_SOURCES = \
        xgetspnam.c \
        xmalloc.c \
        yesno.c
+
+if WITH_BTRFS
+libmisc_a_SOURCES += btrfs.c
+endif
+
--- /dev/null
+++ b/libmisc/btrfs.c
@@ -0,0 +1,94 @@
+#include <linux/btrfs_tree.h>
+#include <linux/magic.h>
+#include <sys/statfs.h>
+
+#include "prototypes.h"
+
+
+static int run_btrfs_subvolume_cmd(const char *subcmd, const char *arg1, const 
char *arg2)
+{
+       int status = 0;
+       const char *cmd = "/sbin/btrfs";
+       const char *argv[] = {
+               strrchr(cmd, '/'),
+               "subvolume",
+               subcmd,
+               arg1,
+               arg2,
+               NULL
+       };
+
+       if (argv[0] == NULL)
+               argv[0] = cmd;
+       else
+               argv[0] = argv[0] + 1;
+
+       if (access(cmd, X_OK)) {
+               return 1;
+       }
+
+       if (run_command(cmd, argv, NULL, &status))
+               return -1;
+       return status;
+}
+
+
+int btrfs_create_subvolume(const char *path)
+{
+       return run_btrfs_subvolume_cmd("create", path, NULL);
+}
+
+
+int btrfs_remove_subvolume(const char *path)
+{
+       return run_btrfs_subvolume_cmd("delete", "-C", path);
+}
+
+
+/* Adapted from btrfsprogs */
+/*
+ * This intentionally duplicates btrfs_util_is_subvolume_fd() instead of 
opening
+ * a file descriptor and calling it, because fstat() and fstatfs() don't accept
+ * file descriptors opened with O_PATH on old kernels (before v3.6 and before
+ * v3.12, respectively), but stat() and statfs() can be called on a path that
+ * the user doesn't have read or write permissions to.
+ *
+ * returns:
+ *   1 - btrfs subvolume
+ *   0 - not btrfs subvolume
+ *  -1 - error
+ */
+int btrfs_is_subvolume(const char *path)
+{
+       struct stat st;
+       int ret;
+
+       ret = is_btrfs(path);
+       if (ret <= 0)
+               return ret;
+
+       ret = stat(path, &st);
+       if (ret == -1)
+               return -1;
+
+       if (st.st_ino != BTRFS_FIRST_FREE_OBJECTID || !S_ISDIR(st.st_mode)) {
+               return 0;
+       }
+
+       return 1;
+}
+
+
+/* Adapted from btrfsprogs */
+int is_btrfs(const char *path)
+{
+       struct statfs sfs;
+       int ret;
+
+       ret = statfs(path, &sfs);
+       if (ret == -1)
+               return -1;
+
+       return sfs.f_type == BTRFS_SUPER_MAGIC;
+}
+
--- a/src/useradd.c
+++ b/src/useradd.c
@@ -164,6 +164,7 @@ static bool
     oflg = false,              /* permit non-unique user ID to be specified 
with -u */
     rflg = false,              /* create a system account */
     sflg = false,              /* shell program for new account */
+    subvolflg = false,         /* create subvolume home on BTRFS */
     uflg = false,              /* specify user ID for new account */
     Uflg = false;              /* create a group having the same name as the 
user */
 
@@ -805,6 +806,9 @@ static void usage (int status)
                        Prog, Prog, Prog);
        (void) fputs (_("  -b, --base-dir BASE_DIR       base directory for the 
home directory of the\n"
                        "                                new account\n"), 
usageout);
+#ifdef WITH_BTRFS
+       (void) fputs (_("      --btrfs-subvolume-home    use BTRFS subvolume 
for home directory\n"), usageout);
+#endif
        (void) fputs (_("  -c, --comment COMMENT         GECOS field of the new 
account\n"), usageout);
        (void) fputs (_("  -d, --home-dir HOME_DIR       home directory of the 
new account\n"), usageout);
        (void) fputs (_("  -D, --defaults                print or change 
default useradd configuration\n"), usageout);
@@ -1085,6 +1089,9 @@ static void process_flags (int argc, cha
                int c;
                static struct option long_options[] = {
                        {"base-dir",       required_argument, NULL, 'b'},
+#ifdef WITH_BTRFS
+                       {"btrfs-subvolume-home", no_argument, NULL, 200},
+#endif
                        {"comment",        required_argument, NULL, 'c'},
                        {"home-dir",       required_argument, NULL, 'd'},
                        {"defaults",       no_argument,       NULL, 'D'},
@@ -1131,6 +1138,9 @@ static void process_flags (int argc, cha
                                def_home = optarg;
                                bflg = true;
                                break;
+                       case 200:
+                               subvolflg = true;
+                               break;
                        case 'c':
                                if (!VALID (optarg)) {
                                        fprintf (stderr,
@@ -2049,6 +2059,37 @@ static void create_home (void)
                        strcat (path, "/");
                        strcat (path, cp);
                        if (access (path, F_OK) != 0) {
+                               /* Check if parent directory is BTRFS, fail if 
requesting
+                                  subvolume but no BTRFS. The paths cound be 
different by the
+                                  trailing slash
+                                */
+#if WITH_BTRFS
+                               if (subvolflg && (strlen(prefix_user_home) - 
(int)strlen(path)) <= 1) {
+                                       char *btrfs_check = strdup(path);
+
+                                       if (!btrfs_check) {
+                                               fprintf (stderr,
+                                                        _("%s: error while 
duplicating string in BTRFS check %s\n"),
+                                                        Prog, path);
+                                               fail_exit (E_HOMEDIR);
+                                       }
+                                       btrfs_check[strlen(path) - strlen(cp) - 
1] = '\0';
+                                       if (is_btrfs(btrfs_check) <= 0) {
+                                               fprintf (stderr,
+                                                        _("%s: home directory 
\"%s\" must be mounted on BTRFS\n"),
+                                                        Prog, path);
+                                               fail_exit (E_HOMEDIR);
+                                       }
+                                       // make subvolume to mount for user 
instead of directory
+                                       if (btrfs_create_subvolume(path)) {
+                                               fprintf (stderr,
+                                                        _("%s: failed to 
create BTRFS subvolume: %s\n"),
+                                                        Prog, path);
+                                               fail_exit (E_HOMEDIR);
+                                       }
+                               }
+                               else
+#endif
                                if (mkdir (path, 0) != 0) {
                        fprintf (stderr,
                                 _("%s: cannot create directory %s\n"),
--- a/src/userdel.c
+++ b/src/userdel.c
@@ -1273,6 +1273,23 @@ int main (int argc, char **argv)
 #endif                         /* EXTRA_CHECK_HOME_DIR */
 
        if (rflg) {
+#ifdef WITH_BTRFS
+               int is_subvolume = btrfs_is_subvolume (user_home);
+               if (is_subvolume < 0) {
+                   errors++;
+                   /* continue */
+               }
+               else if (is_subvolume > 0) {
+                       if (btrfs_remove_subvolume (user_home)) {
+                               fprintf (stderr,
+                                        _("%s: error removing subvolume %s\n"),
+                                        Prog, user_home);
+                               errors++;
+                               /* continue */
+                       }
+               }
+               else
+#endif
                if (remove_tree (user_home, true) != 0) {
                        fprintf (stderr,
                                 _("%s: error removing directory %s\n"),
--- a/src/usermod.c
+++ b/src/usermod.c
@@ -1818,6 +1818,15 @@ static void move_home (void)
                        return;
                } else {
                        if (EXDEV == errno) {
+#ifdef WITH_BTRFS
+                               if (btrfs_is_subvolume (prefix_user_home) > 0) {
+                                       fprintf (stderr,
+                                               _("%s: error: cannot move 
subvolume from %s to %s - different device\n"),
+                                               Prog, prefix_user_home, 
prefix_user_newhome);
+                                       fail_exit (E_HOMEDIR);
+                               }
+#endif
+
                                if (copy_tree (prefix_user_home, 
prefix_user_newhome, true,
                                               true,
                                               user_id,



Reply via email to