forked from pool/shadow
This commit is contained in:
parent
e9204025f7
commit
981192bf42
@ -1,22 +1,90 @@
|
||||
commit 7561ce4594254480f42be721553dade3126e7a1c
|
||||
commit c0dea3bb7f548b93244c5da6eae805444485429f
|
||||
Author: Adam Majer <amajer@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 3ce4a86acec3b96e85cbff291035d24cdcd4b5db
|
||||
Author: Adam Majer <amajer@suse.de>
|
||||
Date: Mon Jan 21 09:32:36 2019 +0100
|
||||
|
||||
{WIP}
|
||||
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.
|
||||
|
||||
Index: shadow-4.6/configure.ac
|
||||
===================================================================
|
||||
--- shadow-4.6.orig/configure.ac
|
||||
+++ shadow-4.6/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"
|
||||
Index: shadow-4.6/lib/prototypes.h
|
||||
===================================================================
|
||||
--- shadow-4.6.orig/lib/prototypes.h
|
||||
+++ shadow-4.6/lib/prototypes.h
|
||||
@@ -72,6 +72,12 @@ extern int expire (const struct passwd *
|
||||
@@ -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 */
|
||||
@ -25,14 +93,15 @@ Index: shadow-4.6/libmisc/Makefile.am
|
||||
===================================================================
|
||||
--- shadow-4.6.orig/libmisc/Makefile.am
|
||||
+++ shadow-4.6/libmisc/Makefile.am
|
||||
@@ -10,6 +10,7 @@ libmisc_a_SOURCES = \
|
||||
age.c \
|
||||
audit_help.c \
|
||||
basename.c \
|
||||
+ btrfs.c \
|
||||
chkname.c \
|
||||
chkname.h \
|
||||
chowndir.c \
|
||||
@@ -72,3 +72,8 @@ libmisc_a_SOURCES = \
|
||||
xgetspnam.c \
|
||||
xmalloc.c \
|
||||
yesno.c
|
||||
+
|
||||
+if WITH_BTRFS
|
||||
+libmisc_a_SOURCES += btrfs.c
|
||||
+endif
|
||||
+
|
||||
Index: shadow-4.6/libmisc/btrfs.c
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
@ -136,15 +205,7 @@ Index: shadow-4.6/src/useradd.c
|
||||
===================================================================
|
||||
--- shadow-4.6.orig/src/useradd.c
|
||||
+++ shadow-4.6/src/useradd.c
|
||||
@@ -67,6 +67,7 @@
|
||||
#include "sgroupio.h"
|
||||
#endif
|
||||
#include "shadowio.h"
|
||||
+#include "spawn.h"
|
||||
#ifdef ENABLE_SUBIDS
|
||||
#include "subordinateio.h"
|
||||
#endif /* ENABLE_SUBIDS */
|
||||
@@ -164,6 +165,7 @@ static bool
|
||||
@@ -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 */
|
||||
@ -152,35 +213,46 @@ Index: shadow-4.6/src/useradd.c
|
||||
uflg = false, /* specify user ID for new account */
|
||||
Uflg = false; /* create a group having the same name as the user */
|
||||
|
||||
@@ -805,6 +807,7 @@ static void usage (int status)
|
||||
@@ -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 +1088,7 @@ static void process_flags (int argc, cha
|
||||
@@ -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'},
|
||||
@@ -1114,9 +1118,9 @@ static void process_flags (int argc, cha
|
||||
@@ -1113,11 +1120,15 @@ static void process_flags (int argc, cha
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
while ((c = getopt_long (argc, argv,
|
||||
+ "b:"
|
||||
+#ifdef WITH_BTRFS
|
||||
+ ":"
|
||||
+#endif
|
||||
+ "c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:U"
|
||||
#ifdef WITH_SELINUX
|
||||
- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:UZ:",
|
||||
+ "b::c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:UZ:",
|
||||
#else /* !WITH_SELINUX */
|
||||
-#else /* !WITH_SELINUX */
|
||||
- "b:c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:U",
|
||||
+ "b::c:d:De:f:g:G:hk:K:lmMNop:rR:P:s:u:U",
|
||||
+ "Z:"
|
||||
#endif /* !WITH_SELINUX */
|
||||
+ ,
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
@@ -1131,6 +1135,9 @@ static void process_flags (int argc, cha
|
||||
case 'b':
|
||||
@@ -1131,6 +1142,9 @@ static void process_flags (int argc, cha
|
||||
def_home = optarg;
|
||||
bflg = true;
|
||||
break;
|
||||
@ -190,15 +262,15 @@ Index: shadow-4.6/src/useradd.c
|
||||
case 'c':
|
||||
if (!VALID (optarg)) {
|
||||
fprintf (stderr,
|
||||
@@ -2049,7 +2056,35 @@ static void create_home (void)
|
||||
@@ -2049,6 +2063,37 @@ static void create_home (void)
|
||||
strcat (path, "/");
|
||||
strcat (path, cp);
|
||||
if (access (path, F_OK) != 0) {
|
||||
- if (mkdir (path, 0) != 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);
|
||||
+
|
||||
@ -223,19 +295,20 @@ Index: shadow-4.6/src/useradd.c
|
||||
+ fail_exit (E_HOMEDIR);
|
||||
+ }
|
||||
+ }
|
||||
+ else if (mkdir (path, 0) != 0) {
|
||||
+ else
|
||||
+#endif
|
||||
if (mkdir (path, 0) != 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: cannot create directory %s\n"),
|
||||
Prog, path);
|
||||
Index: shadow-4.6/src/userdel.c
|
||||
===================================================================
|
||||
--- shadow-4.6.orig/src/userdel.c
|
||||
+++ shadow-4.6/src/userdel.c
|
||||
@@ -1273,7 +1273,21 @@ int main (int argc, char **argv)
|
||||
@@ -1273,6 +1273,23 @@ int main (int argc, char **argv)
|
||||
#endif /* EXTRA_CHECK_HOME_DIR */
|
||||
|
||||
if (rflg) {
|
||||
- if (remove_tree (user_home, true) != 0) {
|
||||
+#ifdef WITH_BTRFS
|
||||
+ int is_subvolume = btrfs_is_subvolume (user_home);
|
||||
+ if (is_subvolume < 0) {
|
||||
+ errors++;
|
||||
@ -250,24 +323,27 @@ Index: shadow-4.6/src/userdel.c
|
||||
+ /* continue */
|
||||
+ }
|
||||
+ }
|
||||
+ else if (remove_tree (user_home, true) != 0) {
|
||||
+ else
|
||||
+#endif
|
||||
if (remove_tree (user_home, true) != 0) {
|
||||
fprintf (stderr,
|
||||
_("%s: error removing directory %s\n"),
|
||||
Prog, user_home);
|
||||
Index: shadow-4.6/src/usermod.c
|
||||
===================================================================
|
||||
--- shadow-4.6.orig/src/usermod.c
|
||||
+++ shadow-4.6/src/usermod.c
|
||||
@@ -1818,6 +1818,13 @@ static void move_home (void)
|
||||
@@ -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,
|
||||
|
@ -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 http://bugs.opensuse.org/
|
||||
# Please submit bugfixes or comments via https://bugs.opensuse.org/
|
||||
#
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user