/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "funcs.h" #include "messages.h" #define SBUFSZ 256 #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. */ int 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 */ { struct stat stbuf; char *dataset; char *dname, *bname, *rp; int created_fs = 0; rp = realpath(homedir, NULL); if (rp && (strcmp(rp, "/") == 0)) { return (EX_HOMEDIR); } (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)); return (EX_HOMEDIR); } if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && (flags & MANAGE_ZFS)) { if (g_zfs == NULL) g_zfs = libzfs_init(); if (g_zfs == NULL) { errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); return (EX_HOMEDIR); } if ((dataset = get_mnt_special(pdir, stbuf.st_fstype)) != NULL) { char nm[ZFS_MAX_DATASET_NAME_LEN]; zfs_handle_t *zhp; (void) snprintf(nm, sizeof (nm), "%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); } created_fs = 1; } else { errmsg(M_NO_ZFS_MOUNTPOINT, pdir); } } if (!created_fs) { 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 != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_HOMEDIR); } } if (chown(homedir, uid, gid) != 0) { errmsg(M_OOPS, "change ownership of home directory", strerror(errno)); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_HOMEDIR); } if (skeldir != NULL) { /* copy the skel_dir into the home directory */ (void) sprintf(cmdbuf, "cd %s && find . -print | cpio -pd %s", skeldir, homedir); if (system(cmdbuf) != 0) { errmsg(M_OOPS, "copy skeleton directory into home " "directory", strerror(errno)); (void) rm_homedir(homedir, flags); if (g_zfs != NULL) { 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:%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, flags); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_HOMEDIR); } } if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } return (EX_SUCCESS); } /* Remove a home directory structure */ int rm_homedir(char *dir, int flags) { struct stat stbuf; char *nm, *rp; rp = realpath(dir, NULL); if (rp && (strcmp(rp, "/") == 0)) { return (0); } if ((stat(dir, &stbuf) != 0) || !S_ISDIR(stbuf.st_mode)) return (0); if ((strcmp(stbuf.st_fstype, MNTTYPE_ZFS) == 0) && (flags & MANAGE_ZFS)) { if (g_zfs == NULL) g_zfs = libzfs_init(); if (g_zfs == NULL) { errmsg(M_OOPS, "libzfs_init failure", strerror(errno)); return (EX_HOMEDIR); } if ((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); libzfs_fini(g_zfs); g_zfs = NULL; return (0); } errmsg(M_OOPS, "destroy the home directory", libzfs_error_description(g_zfs)); (void) zfs_mount(zhp, NULL, 0); zfs_close(zhp); libzfs_fini(g_zfs); g_zfs = NULL; return (EX_HOMEDIR); } } } (void) sprintf(cmdbuf, "rm -rf %s", dir); if (g_zfs != NULL) { libzfs_fini(g_zfs); g_zfs = NULL; } 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(MANAGE_ZFS_OPT)) != NULL) { char let = tolower(*defptr); switch (let) { case 'y': /* yes */ flags |= MANAGE_ZFS; case 'n': /* no */ break; } } (void) defopen((char *)NULL); } return (flags); } /* Get the name of a mounted filesystem */ 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 (special); }