Print this page
293 useradd/del/mod should be ZFS-aware

@@ -27,86 +27,260 @@
 
 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
 /*        All Rights Reserved   */
 
 
-#pragma ident   "%Z%%M% %I%     %E% SMI"
-
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <stdio.h>
 #include <userdefs.h>
 #include <errno.h>
 #include <strings.h>
+#include <sys/mntent.h>
+#include <sys/mnttab.h>
+#include <libzfs.h>
+#include <libgen.h>
+#include <limits.h>
+#include <deflt.h>
+
+#include "funcs.h"
 #include "messages.h"
 
 #define         SBUFSZ  256
 
-extern int rm_homedir();
+#define DEFAULT_USERADD "/etc/default/useradd"
+
+static int rm_homedir();
+static char *get_mnt_special();
 
 static char cmdbuf[ SBUFSZ ];   /* buffer for system call */
+static char dhome[ PATH_MAX + 1 ]; /* buffer for dirname */
+static char bhome[ PATH_MAX + 1 ]; /* buffer for basename */
+static char pdir[ PATH_MAX + 1 ]; /* parent directory */
+static libzfs_handle_t *g_zfs = NULL;
 
 /*
-        Create a home directory and populate with files from skeleton
-        directory.
-*/
+ * Create a home directory and populate with files from skeleton
+ * directory.
+ */
 int
-create_home(char *homedir, char *skeldir, uid_t uid, gid_t gid)
+create_home(char *homedir, char *skeldir, uid_t uid, gid_t gid, int flags)
                 /* home directory to create */
                 /* skel directory to copy if indicated */
                 /* uid of new user */
                 /* group id of new user */
+                /* miscellaneous flags */
 {
-        if( mkdir(homedir, 0775) != 0 ) {
-                errmsg(M_OOPS, "create the home directory", strerror(errno));
-                return( EX_HOMEDIR );
+        struct stat stbuf;
+        char *dataset;
+        char *dname, *bname;
+
+        if (g_zfs == NULL)
+                g_zfs = libzfs_init();
+
+        (void) strcpy(dhome, homedir);
+        (void) strcpy(bhome, homedir);
+        dname = dirname(dhome);
+        bname = basename(bhome);
+        (void) strcpy(pdir, dname);
+
+        if ((stat(pdir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) {
+                errmsg(M_OOPS, "access the parent directory", strerror(errno));
+                if (g_zfs) {
+                        libzfs_fini(g_zfs);
+                        g_zfs = NULL;
+                }
+                return (EX_HOMEDIR);
+        }
+
+        if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) &&
+            (g_zfs != NULL) && (flags & CHANGE_ZFS_FS) &&
+            ((dataset = get_mnt_special(pdir, stbuf.st_fstype)) != NULL)) {
+                char nm[ZFS_MAXNAMELEN];
+                zfs_handle_t *zhp;
+
+                (void) snprintf(nm, ZFS_MAXNAMELEN, "%s/%s", dataset, bname);
+
+                if ((zfs_create(g_zfs, nm, ZFS_TYPE_FILESYSTEM, NULL) != 0) ||
+                    ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) ==
+                    NULL)) {
+                        errmsg(M_OOPS, "create the home directory",
+                            libzfs_error_description(g_zfs));
+                        libzfs_fini(g_zfs);
+                        g_zfs = NULL;
+                        return (EX_HOMEDIR);
+                }
+
+                if (zfs_mount(zhp, NULL, 0) != 0) {
+                        errmsg(M_OOPS, "mount the home directory",
+                            libzfs_error_description(g_zfs));
+                        (void) zfs_destroy(zhp, B_FALSE);
+                        zfs_close(zhp);
+                        libzfs_fini(g_zfs);
+                        g_zfs = NULL;
+                        return (EX_HOMEDIR);
+                }
+
+                zfs_close(zhp);
+
+                if (chmod(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+                        != 0) {
+                        errmsg(M_OOPS, "change permissions of home directory",
+                            strerror(errno));
+                        libzfs_fini(g_zfs);
+                        g_zfs = NULL;
+                        return (EX_HOMEDIR);
+                }
+        } else {
+                if (mkdir(homedir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+                        != 0) {
+                        errmsg(M_OOPS, "create the home directory",
+                            strerror(errno));
+                        if (g_zfs) {
+                                libzfs_fini(g_zfs);
+                                g_zfs = NULL;
+                        }
+                        return (EX_HOMEDIR);
+                }
         }
 
-        if( chown(homedir, uid, gid) != 0 ) {
+        if (chown(homedir, uid, gid) != 0) {
                 errmsg(M_OOPS, "change ownership of home directory", 
                     strerror(errno));
-                return( EX_HOMEDIR );
+                if (g_zfs) {
+                        libzfs_fini(g_zfs);
+                        g_zfs = NULL;
+                }
+                return (EX_HOMEDIR);
         }
 
-        if(skeldir) {
+        if (skeldir) {
                 /* copy the skel_dir into the home directory */
-                (void) sprintf( cmdbuf, "cd %s && find . -print | cpio -pd %s",
+                (void) sprintf(cmdbuf, "cd %s && find . -print | cpio -pd %s",
                         skeldir, homedir);
 
-                if( system( cmdbuf ) != 0 ) {
+                if (system(cmdbuf) != 0) {
                         errmsg(M_OOPS, "copy skeleton directory into home "
                             "directory", strerror(errno));
-                        (void) rm_homedir( homedir );
-                        return( EX_HOMEDIR );
+                        (void) rm_homedir(homedir, flags);
+                        if (g_zfs) {
+                                libzfs_fini(g_zfs);
+                                g_zfs = NULL;
+                        }
+                        return (EX_HOMEDIR);
                 }
 
                 /* make sure contents in the home dirctory have correct owner */
-                (void) sprintf( cmdbuf,"cd %s && find . -exec chown %ld {} \\;",
-                        homedir, uid );
-                if( system( cmdbuf ) != 0) {
-                        errmsg(M_OOPS, "change owner of files home directory",
+                (void) sprintf(cmdbuf,
+                    "cd %s && find . -exec chown %ld:%ld {} \\;",
+                    homedir, uid, gid);
+                if (system(cmdbuf) != 0) {
+                        errmsg(M_OOPS,
+                            "change owner and group of files home directory",
                             strerror(errno));
-
-                        (void) rm_homedir( homedir );
-                        return( EX_HOMEDIR );
+                        (void) rm_homedir(homedir, flags);
+                        if (g_zfs) {
+                                libzfs_fini(g_zfs);
+                                g_zfs = NULL;
+                        }
+                        return (EX_HOMEDIR);
                 }
 
-                /* and group....... */
-                (void) sprintf( cmdbuf, "cd %s && find . -exec chgrp %ld {} \\;",
-                        homedir, gid );
-                if( system( cmdbuf ) != 0) {
-                        errmsg(M_OOPS, "change group of files home directory",
-                            strerror(errno));
-                        (void) rm_homedir( homedir );
-                        return( EX_HOMEDIR );
                 }
+        if (g_zfs) {
+                libzfs_fini(g_zfs);
+                g_zfs = NULL;
         }
-        return( EX_SUCCESS );
+        return (EX_SUCCESS);
 }
 
 /* Remove a home directory structure */
 int
-rm_homedir(char *dir)
+rm_homedir(char *dir, int flags)
 {
-        (void) sprintf( cmdbuf, "rm -rf %s", dir );
+        struct stat stbuf;
+        char *nm;
+
+        if ((stat(dir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode))
+                return (0);
+
+        if (g_zfs == NULL)
+                g_zfs = libzfs_init();
+
+        if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) &&
+            (flags & CHANGE_ZFS_FS) &&
+            (g_zfs != NULL) &&
+            ((nm = get_mnt_special(dir, stbuf.st_fstype)) != NULL)) {
+                zfs_handle_t *zhp;
+
+                if ((zhp = zfs_open(g_zfs, nm, ZFS_TYPE_FILESYSTEM)) != NULL) {
+                        if ((zfs_unmount(zhp, NULL, 0) == 0) &&
+                            (zfs_destroy(zhp, B_FALSE) == 0)) {
+                                zfs_close(zhp);
+                                return (0);
+                        }
+
+                        (void) zfs_mount(zhp, NULL, 0);
+                        zfs_close(zhp);
+                }
+        }
+
+        (void) sprintf(cmdbuf, "rm -rf %s", dir);
+
+        return (system(cmdbuf));
+}
+
+int
+rm_files(char *homedir, char *user, int flags)
+{
+        if (rm_homedir(homedir, flags) != 0) {
+                errmsg(M_RMFILES);
+                return (EX_HOMEDIR);
+        }
+
+        return (EX_SUCCESS);
+}
+
+int
+get_default_zfs_flags()
+{
+        int flags = 0;
+
+        if (defopen(DEFAULT_USERADD) == 0) {
+                char *defptr;
+
+                if ((defptr = defread(CHANGE_ZFS_FS_OPT)) != NULL) {
+                        char let = tolower(*defptr);
+
+                        switch (let) {
+                                case 'y':       /* yes */
+                                        flags |= CHANGE_ZFS_FS;
+                                case 'n':       /* no */
+                                        break;
+                        }
+                }
+                (void) defopen((char *)NULL);
+        }
+        return (flags);
+}
+
+/* Get the name of a mounted filesytem */
+char *
+get_mnt_special(char *mountp, char *fstype)
+{
+        struct mnttab entry, search;
+        char *special = NULL;
+        FILE *fp;
+
+        search.mnt_special = search.mnt_mntopts = search.mnt_time = NULL;
+        search.mnt_mountp = mountp;
+        search.mnt_fstype = fstype;
+
+        if ((fp = fopen(MNTTAB, "r")) != NULL) {
+                if (getmntany(fp, &entry, &search) == 0)
+                        special = entry.mnt_special;
+
+                (void) fclose(fp);
+        }
                 
-        return( system( cmdbuf ) );
+        return (special);
 }