From: Hadi Chokr Date: Fri, 12 Dec 2025 10:18:06 +0000 (+0100) Subject: src/useradd: Support config for creating home dirs as Btrfs subvolumes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e8c105f0703264e947d8c034b90419794955d49;p=thirdparty%2Fshadow.git src/useradd: Support config for creating home dirs as Btrfs subvolumes Closes: #1162 Co-authored-by: Neal Gompa Signed-off-by: Hadi Chokr Signed-off-by: Neal Gompa Reviewed-by: Alejandro Colomar --- diff --git a/man/useradd.8.xml b/man/useradd.8.xml index e6db7f6d7..c745a6207 100644 --- a/man/useradd.8.xml +++ b/man/useradd.8.xml @@ -134,6 +134,33 @@ + + + + + + + Create the user's home directory as a Btrfs subvolume. + + + If this option is not specified, + useradd will follow the default behavior + defined by the variable + in /etc/default/useradd. + If this variable is not set, the default value is no. + + + When the command-line option + is specified, + a Btrfs subvolume is created + regardless of any configuration file settings. + + + Note: this feature works only if the underlying filesystem supports + Btrfs subvolumes. + + + ,  COMMENT diff --git a/src/useradd.c b/src/useradd.c index 899efe3c8..8433ed8a8 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -114,6 +114,7 @@ static const char *def_shell = "/bin/bash"; static const char *def_template = SKEL_DIR; static const char *def_usrtemplate = USRSKELDIR; static const char *def_create_mail_spool = "yes"; +static const char *def_btrfs_subvolume_home = "no"; static const char *def_log_init = "yes"; static long def_inactive = -1; @@ -222,6 +223,7 @@ static bool home_added = false; #define DSKEL "SKEL" #define DUSRSKEL "USRSKEL" #define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL" +#define DBTRFS_SUBVOLUME_HOME "BTRFS_SUBVOLUME_HOME" #define DLOG_INIT "LOG_INIT" /* local function prototypes */ @@ -456,6 +458,7 @@ get_defaults(const struct option_flags *flags) def_usrtemplate = xstrdup(ccp); } } + /* * Create by default user mail spool or not ? */ @@ -466,6 +469,15 @@ get_defaults(const struct option_flags *flags) def_create_mail_spool = xstrdup(ccp); } + /* + * Create home directories as Btrfs subvolumes by default? + */ + else if (streq(buf, DBTRFS_SUBVOLUME_HOME)) { + if (streq(ccp, "")) + ccp = "no"; + def_btrfs_subvolume_home = xstrdup(ccp); + } + /* * By default do we add the user to the lastlog and faillog databases ? */ @@ -500,6 +512,7 @@ static void show_defaults (void) printf ("SKEL=%s\n", def_template); printf ("USRSKEL=%s\n", def_usrtemplate); printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool); + printf ("BTRFS_SUBVOLUME_HOME=%s\n", def_btrfs_subvolume_home); printf ("LOG_INIT=%s\n", def_log_init); } @@ -523,6 +536,7 @@ set_defaults(void) bool out_skel = false; bool out_usrskel = false; bool out_create_mail_spool = false; + bool out_btrfs_subvolume_home = false; bool out_log_init = false; char buf[1024]; char *new_file = NULL; @@ -639,6 +653,11 @@ set_defaults(void) DCREATE_MAIL_SPOOL "=%s\n", def_create_mail_spool); out_create_mail_spool = true; + } else if (!out_btrfs_subvolume_home && streq(buf, DBTRFS_SUBVOLUME_HOME)) { + fprintf(ofp, + DBTRFS_SUBVOLUME_HOME "=%s\n", + def_btrfs_subvolume_home); + out_btrfs_subvolume_home = true; } else if (!out_log_init && streq(buf, DLOG_INIT)) { fprintf(ofp, DLOG_INIT "=%s\n", def_log_init); out_log_init = true; @@ -673,6 +692,8 @@ set_defaults(void) if (!out_create_mail_spool) fprintf (ofp, DCREATE_MAIL_SPOOL "=%s\n", def_create_mail_spool); + if (!out_btrfs_subvolume_home) + fprintf (ofp, DBTRFS_SUBVOLUME_HOME "=%s\n", def_btrfs_subvolume_home); if (!out_log_init) fprintf (ofp, DLOG_INIT "=%s\n", def_log_init); /* @@ -1431,6 +1452,9 @@ static void process_flags (int argc, char **argv, struct option_flags *flags) } } + if (!subvolflg && strcaseeq(def_btrfs_subvolume_home, "yes")) + subvolflg = true; + if (!gflg && !Nflg && !Uflg) { /* Get the settings from login.defs */ Uflg = getdef_bool ("USERGROUPS_ENAB");