]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
Add support for skeleton files from /usr/etc/skel
authorMichael Vetter <jubalh@iodoru.org>
Wed, 9 Nov 2022 13:41:31 +0000 (14:41 +0100)
committerSerge Hallyn <serge@hallyn.com>
Mon, 19 Dec 2022 15:43:03 +0000 (09:43 -0600)
This patch is used by openSUSE to make useradd look for
skeleton files in /usr/etc/skel additionally to /etc/skel
in accordance with
https://uapi-group.org/specifications/specs/base_directory_specification/

libmisc/copydir.c
src/useradd.c

index b692aa95d1d32e032872335abcb35eb1bfc56df6..5e569b8f68fa2b2c850a72e0f7c097cb8c4e6533 100644 (file)
@@ -448,6 +448,14 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst,
                                        old_uid, new_uid, old_gid, new_gid);
                }
 
+               /*
+                * If the destination already exists do nothing.
+                * This is after the copy_dir above to still iterate into subdirectories.
+                */
+               if (fstatat(dst->dirfd, dst->name, &sb, AT_SYMLINK_NOFOLLOW) != -1) {
+                       return 0;
+               }
+
                /*
                 * Copy any symbolic links
                 */
@@ -507,6 +515,7 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
                      gid_t old_gid, gid_t new_gid)
 {
        int err = 0;
+       struct stat dst_sb;
 
        /*
         * Create a new target directory, make it owned by
@@ -518,6 +527,15 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst,
                return -1;
        }
 #endif                         /* WITH_SELINUX */
+        /*
+         * If the destination is already a directory, don't change it
+         * but copy into it (recursively).
+        */
+        if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) {
+            return (copy_tree (src, dst, false, reset_selinux,
+                           old_uid, new_uid, old_gid, new_gid) != 0);
+        }
+
        if (   (mkdirat (dst->dirfd, dst->name, 0700) != 0)
            || (chownat_if_needed (dst, statp,
                                 old_uid, new_uid, old_gid, new_gid) != 0)
index 87abd6e338d8cf5767971f41dacb148614d5e6a5..d167e9e9c3748a9190a34c115c2aa68b9df34d47 100644 (file)
@@ -61,6 +61,9 @@
 #ifndef SKEL_DIR
 #define SKEL_DIR "/etc/skel"
 #endif
+#ifndef USRSKELDIR
+#define USRSKELDIR "/usr/etc/skel"
+#endif
 #ifndef USER_DEFAULTS_FILE
 #define USER_DEFAULTS_FILE "/etc/default/useradd"
 #define NEW_USER_FILE "/etc/default/nuaddXXXXXX"
@@ -85,6 +88,7 @@ static const char *def_gname = "other";
 static const char *def_home = "/home";
 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_log_init = "yes";
 
@@ -190,6 +194,7 @@ static bool home_added = false;
 #define DINACT                 "INACTIVE="
 #define DEXPIRE                        "EXPIRE="
 #define DSKEL                  "SKEL="
+#define DUSRSKEL               "USRSKEL="
 #define DCREATE_MAIL_SPOOL     "CREATE_MAIL_SPOOL="
 #define DLOG_INIT      "LOG_INIT="
 
@@ -473,6 +478,29 @@ static void get_defaults (void)
                        }
                }
 
+               /*
+                * Default Usr Skeleton information
+                */
+               else if (MATCH (buf, DUSRSKEL)) {
+                       if ('\0' == *cp) {
+                               cp = USRSKELDIR;        /* XXX warning: const */
+                       }
+
+                       if(prefix[0]) {
+                               size_t len;
+                               int wlen;
+                               char* _def_usrtemplate; /* avoid const warning */
+
+                               len = strlen(prefix) + strlen(cp) + 2;
+                               _def_usrtemplate = xmalloc(len);
+                               wlen = snprintf(_def_usrtemplate, len, "%s/%s", prefix, cp);
+                               assert (wlen == (int) len -1);
+                               def_usrtemplate = _def_usrtemplate;
+                       }
+                       else {
+                               def_usrtemplate = xstrdup (cp);
+                       }
+               }
                /*
                 * Create by default user mail spool or not ?
                 */
@@ -516,6 +544,7 @@ static void show_defaults (void)
        printf ("EXPIRE=%s\n", def_expire);
        printf ("SHELL=%s\n", def_shell);
        printf ("SKEL=%s\n", def_template);
+       printf ("USRSKEL=%s\n", def_usrtemplate);
        printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool);
        printf ("LOG_INIT=%s\n", def_log_init);
 }
@@ -545,6 +574,7 @@ static int set_defaults (void)
        bool out_expire = false;
        bool out_shell = false;
        bool out_skel = false;
+       bool out_usrskel = false;
        bool out_create_mail_spool = false;
        bool out_log_init = false;
        size_t len;
@@ -661,6 +691,9 @@ static int set_defaults (void)
                } else if (!out_skel && MATCH (buf, DSKEL)) {
                        fprintf (ofp, DSKEL "%s\n", def_template);
                        out_skel = true;
+               } else if (!out_usrskel && MATCH (buf, DUSRSKEL)) {
+                       fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate);
+                       out_usrskel = true;
                } else if (!out_create_mail_spool
                           && MATCH (buf, DCREATE_MAIL_SPOOL)) {
                        fprintf (ofp,
@@ -698,6 +731,8 @@ static int set_defaults (void)
                fprintf (ofp, DSHELL "%s\n", def_shell);
        if (!out_skel)
                fprintf (ofp, DSKEL "%s\n", def_template);
+       if (!out_usrskel)
+               fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate);
 
        if (!out_create_mail_spool)
                fprintf (ofp, DCREATE_MAIL_SPOOL "%s\n", def_create_mail_spool);
@@ -2745,6 +2780,8 @@ int main (int argc, char **argv)
                if (home_added) {
                        copy_tree (def_template, prefix_user_home, false, true,
                                   (uid_t)-1, user_id, (gid_t)-1, user_gid);
+                       copy_tree (def_usrtemplate, prefix_user_home, false, false,
+                                  (uid_t)-1, user_id, (gid_t)-1, user_gid);
                } else {
                        fprintf (stderr,
                                 _("%s: warning: the home directory %s already exists.\n"