zoneadm.c (45916cd2fec6e79bca5dee0421bd39e3c2910d1e) zoneadm.c (0b5de56d26c0148ad33bb3a9201091502f24d910)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 41 unchanged lines hidden (view full) ---

50#include <string.h>
51#include <wait.h>
52#include <zone.h>
53#include <priv.h>
54#include <locale.h>
55#include <libintl.h>
56#include <libzonecfg.h>
57#include <bsm/adt.h>
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 41 unchanged lines hidden (view full) ---

50#include <string.h>
51#include <wait.h>
52#include <zone.h>
53#include <priv.h>
54#include <locale.h>
55#include <libintl.h>
56#include <libzonecfg.h>
57#include <bsm/adt.h>
58#include <sys/utsname.h>
59#include <sys/param.h>
60#include <sys/types.h>
61#include <sys/stat.h>
62#include <sys/statvfs.h>
63#include <assert.h>
64#include <sys/sockio.h>
65#include <sys/mntent.h>
66#include <limits.h>
58#include <sys/param.h>
59#include <sys/types.h>
60#include <sys/stat.h>
61#include <sys/statvfs.h>
62#include <assert.h>
63#include <sys/sockio.h>
64#include <sys/mntent.h>
65#include <limits.h>
67#include <libzfs.h>
66#include <dirent.h>
68
69#include <fcntl.h>
70#include <door.h>
71#include <macros.h>
72#include <libgen.h>
73#include <fnmatch.h>
74
75#include <pool.h>
76#include <sys/pool.h>
77
67
68#include <fcntl.h>
69#include <door.h>
70#include <macros.h>
71#include <libgen.h>
72#include <fnmatch.h>
73
74#include <pool.h>
75#include <sys/pool.h>
76
77#include "zoneadm.h"
78
78#define MAXARGS 8
79
80/* Reflects kernel zone entries */
81typedef struct zone_entry {
82 zoneid_t zid;
83 char zname[ZONENAME_MAX];
84 char *zstate_str;
85 zone_state_t zstate_num;
86 char zroot[MAXPATHLEN];
87} zone_entry_t;
88
89static zone_entry_t *zents;
90static size_t nzents;
91
79#define MAXARGS 8
80
81/* Reflects kernel zone entries */
82typedef struct zone_entry {
83 zoneid_t zid;
84 char zname[ZONENAME_MAX];
85 char *zstate_str;
86 zone_state_t zstate_num;
87 char zroot[MAXPATHLEN];
88} zone_entry_t;
89
90static zone_entry_t *zents;
91static size_t nzents;
92
92#if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
93#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
94#endif
95
96#define Z_ERR 1
97#define Z_USAGE 2
98
99/* 0755 is the default directory mode. */
100#define DEFAULT_DIR_MODE \
101 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
102
93/* 0755 is the default directory mode. */
94#define DEFAULT_DIR_MODE \
95 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
96
103#define CMD_HELP 0
104#define CMD_BOOT 1
105#define CMD_HALT 2
106#define CMD_READY 3
107#define CMD_REBOOT 4
108#define CMD_LIST 5
109#define CMD_VERIFY 6
110#define CMD_INSTALL 7
111#define CMD_UNINSTALL 8
112#define CMD_MOUNT 9
113#define CMD_UNMOUNT 10
114#define CMD_CLONE 11
115#define CMD_MOVE 12
116#define CMD_DETACH 13
117#define CMD_ATTACH 14
118
119#define CMD_MIN CMD_HELP
120#define CMD_MAX CMD_ATTACH
121
122struct cmd {
123 uint_t cmd_num; /* command number */
124 char *cmd_name; /* command name */
125 char *short_usage; /* short form help */
126 int (*handler)(int argc, char *argv[]); /* function to call */
127
128};
129
130#define SHELP_HELP "help"
131#define SHELP_BOOT "boot [-s]"
132#define SHELP_HALT "halt"
133#define SHELP_READY "ready"
134#define SHELP_REBOOT "reboot"
135#define SHELP_LIST "list [-cipv]"
136#define SHELP_VERIFY "verify"
97struct cmd {
98 uint_t cmd_num; /* command number */
99 char *cmd_name; /* command name */
100 char *short_usage; /* short form help */
101 int (*handler)(int argc, char *argv[]); /* function to call */
102
103};
104
105#define SHELP_HELP "help"
106#define SHELP_BOOT "boot [-s]"
107#define SHELP_HALT "halt"
108#define SHELP_READY "ready"
109#define SHELP_REBOOT "reboot"
110#define SHELP_LIST "list [-cipv]"
111#define SHELP_VERIFY "verify"
137#define SHELP_INSTALL "install"
112#define SHELP_INSTALL "install [-x nodataset]"
138#define SHELP_UNINSTALL "uninstall [-F]"
113#define SHELP_UNINSTALL "uninstall [-F]"
139#define SHELP_CLONE "clone [-m method] zonename"
114#define SHELP_CLONE "clone [-m method] [-s <ZFS snapshot>] zonename"
140#define SHELP_MOVE "move zonepath"
141#define SHELP_DETACH "detach"
142#define SHELP_ATTACH "attach [-F]"
143
144static int help_func(int argc, char *argv[]);
145static int ready_func(int argc, char *argv[]);
146static int boot_func(int argc, char *argv[]);
147static int halt_func(int argc, char *argv[]);

--- 32 unchanged lines hidden (view full) ---

180 { CMD_DETACH, "detach", SHELP_DETACH, detach_func },
181 { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func }
182};
183
184/* global variables */
185
186/* set early in main(), never modified thereafter, used all over the place */
187static char *execname;
115#define SHELP_MOVE "move zonepath"
116#define SHELP_DETACH "detach"
117#define SHELP_ATTACH "attach [-F]"
118
119static int help_func(int argc, char *argv[]);
120static int ready_func(int argc, char *argv[]);
121static int boot_func(int argc, char *argv[]);
122static int halt_func(int argc, char *argv[]);

--- 32 unchanged lines hidden (view full) ---

155 { CMD_DETACH, "detach", SHELP_DETACH, detach_func },
156 { CMD_ATTACH, "attach", SHELP_ATTACH, attach_func }
157};
158
159/* global variables */
160
161/* set early in main(), never modified thereafter, used all over the place */
162static char *execname;
188static char *target_zone;
189static char *locale;
163static char *locale;
164char *target_zone;
190
191/* used in do_subproc() and signal handler */
192static volatile boolean_t child_killed;
193
165
166/* used in do_subproc() and signal handler */
167static volatile boolean_t child_killed;
168
194static char *
169char *
195cmd_to_str(int cmd_num)
196{
197 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
198 return (cmdtab[cmd_num].cmd_name);
199}
200
201/* This is a separate function because of gettext() wrapping. */
202static char *

--- 32 unchanged lines hidden (view full) ---

235 "machine-parsable output. The -v\n\tand -p "
236 "options are mutually exclusive. If neither -v "
237 "nor -p is used,\n\tjust the zone name is listed."));
238 case CMD_VERIFY:
239 return (gettext("Check to make sure the configuration "
240 "can safely be instantiated\n\ton the machine: "
241 "physical network interfaces exist, etc."));
242 case CMD_INSTALL:
170cmd_to_str(int cmd_num)
171{
172 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
173 return (cmdtab[cmd_num].cmd_name);
174}
175
176/* This is a separate function because of gettext() wrapping. */
177static char *

--- 32 unchanged lines hidden (view full) ---

210 "machine-parsable output. The -v\n\tand -p "
211 "options are mutually exclusive. If neither -v "
212 "nor -p is used,\n\tjust the zone name is listed."));
213 case CMD_VERIFY:
214 return (gettext("Check to make sure the configuration "
215 "can safely be instantiated\n\ton the machine: "
216 "physical network interfaces exist, etc."));
217 case CMD_INSTALL:
243 return (gettext("Install the configuration on to the system."));
218 return (gettext("Install the configuration on to the system. "
219 "The -x nodataset option\n\tcan be used to prevent the "
220 "creation of a new ZFS file system for the\n\tzone "
221 "(assuming the zonepath is within a ZFS file system)."));
244 case CMD_UNINSTALL:
245 return (gettext("Uninstall the configuration from the system. "
246 "The -F flag can be used\n\tto force the action."));
247 case CMD_CLONE:
222 case CMD_UNINSTALL:
223 return (gettext("Uninstall the configuration from the system. "
224 "The -F flag can be used\n\tto force the action."));
225 case CMD_CLONE:
248 return (gettext("Clone the installation of another zone."));
226 return (gettext("Clone the installation of another zone. "
227 "The -m option can be used to\n\tspecify 'copy' which "
228 "forces a copy of the source zone. The -s option\n\t"
229 "can be used to specify the name of a ZFS snapshot "
230 "that was taken from\n\ta previous clone command. The "
231 "snapshot will be used as the source\n\tinstead of "
232 "creating a new ZFS snapshot."));
249 case CMD_MOVE:
250 return (gettext("Move the zone to a new zonepath."));
251 case CMD_DETACH:
252 return (gettext("Detach the zone from the system. The zone "
253 "state is changed to\n\t'configured' (but the files under "
254 "the zonepath are untouched).\n\tThe zone can subsequently "
255 "be attached, or can be moved to another\n\tsystem and "
256 "attached there."));

--- 48 unchanged lines hidden (view full) ---

305}
306
307/*
308 * zperror() is like perror(3c) except that this also prints the executable
309 * name at the start of the message, and takes a boolean indicating whether
310 * to call libc'c strerror() or that from libzonecfg.
311 */
312
233 case CMD_MOVE:
234 return (gettext("Move the zone to a new zonepath."));
235 case CMD_DETACH:
236 return (gettext("Detach the zone from the system. The zone "
237 "state is changed to\n\t'configured' (but the files under "
238 "the zonepath are untouched).\n\tThe zone can subsequently "
239 "be attached, or can be moved to another\n\tsystem and "
240 "attached there."));

--- 48 unchanged lines hidden (view full) ---

289}
290
291/*
292 * zperror() is like perror(3c) except that this also prints the executable
293 * name at the start of the message, and takes a boolean indicating whether
294 * to call libc'c strerror() or that from libzonecfg.
295 */
296
313static void
297void
314zperror(const char *str, boolean_t zonecfg_error)
315{
316 (void) fprintf(stderr, "%s: %s: %s\n", execname, str,
317 zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
318}
319
320/*
321 * zperror2() is very similar to zperror() above, except it also prints a
322 * supplied zone name after the executable.
323 *
324 * All current consumers of this function want libzonecfg's strerror() rather
325 * than libc's; if this ever changes, this function can be made more generic
326 * like zperror() above.
327 */
328
298zperror(const char *str, boolean_t zonecfg_error)
299{
300 (void) fprintf(stderr, "%s: %s: %s\n", execname, str,
301 zonecfg_error ? zonecfg_strerror(errno) : strerror(errno));
302}
303
304/*
305 * zperror2() is very similar to zperror() above, except it also prints a
306 * supplied zone name after the executable.
307 *
308 * All current consumers of this function want libzonecfg's strerror() rather
309 * than libc's; if this ever changes, this function can be made more generic
310 * like zperror() above.
311 */
312
329static void
313void
330zperror2(const char *zone, const char *str)
331{
332 (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
333 zonecfg_strerror(errno));
334}
335
336/* PRINTFLIKE1 */
314zperror2(const char *zone, const char *str)
315{
316 (void) fprintf(stderr, "%s: %s: %s: %s\n", execname, zone, str,
317 zonecfg_strerror(errno));
318}
319
320/* PRINTFLIKE1 */
337static void
321void
338zerror(const char *fmt, ...)
339{
340 va_list alist;
341
342 va_start(alist, fmt);
343 (void) fprintf(stderr, "%s: ", execname);
344 if (target_zone != NULL)
345 (void) fprintf(stderr, "zone '%s': ", target_zone);

--- 496 unchanged lines hidden (view full) ---

842 if (!S_ISDIR(stbuf.st_mode)) {
843 (void) fprintf(stderr, gettext("%s is not a directory.\n"),
844 rpath);
845 return (Z_ERR);
846 }
847 if ((strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) ||
848 (strcmp(stbuf.st_fstype, MNTTYPE_XMEMFS) == 0)) {
849 (void) printf(gettext("WARNING: %s is on a temporary "
322zerror(const char *fmt, ...)
323{
324 va_list alist;
325
326 va_start(alist, fmt);
327 (void) fprintf(stderr, "%s: ", execname);
328 if (target_zone != NULL)
329 (void) fprintf(stderr, "zone '%s': ", target_zone);

--- 496 unchanged lines hidden (view full) ---

826 if (!S_ISDIR(stbuf.st_mode)) {
827 (void) fprintf(stderr, gettext("%s is not a directory.\n"),
828 rpath);
829 return (Z_ERR);
830 }
831 if ((strcmp(stbuf.st_fstype, MNTTYPE_TMPFS) == 0) ||
832 (strcmp(stbuf.st_fstype, MNTTYPE_XMEMFS) == 0)) {
833 (void) printf(gettext("WARNING: %s is on a temporary "
850 "file-system.\n"), rpath);
834 "file system.\n"), rpath);
851 }
852 if (crosscheck_zonepaths(rpath) != Z_OK)
853 return (Z_ERR);
854 /*
855 * Try to collect and report as many minor errors as possible
856 * before returning, so the user can learn everything that needs
857 * to be fixed up front.
858 */

--- 49 unchanged lines hidden (view full) ---

908 return (Z_ERR);
909 }
910 if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
911 /*
912 * TRANSLATION_NOTE
913 * Zonepath and NFS are literals that should not be translated.
914 */
915 (void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
835 }
836 if (crosscheck_zonepaths(rpath) != Z_OK)
837 return (Z_ERR);
838 /*
839 * Try to collect and report as many minor errors as possible
840 * before returning, so the user can learn everything that needs
841 * to be fixed up front.
842 */

--- 49 unchanged lines hidden (view full) ---

892 return (Z_ERR);
893 }
894 if (strcmp(vfsbuf.f_basetype, MNTTYPE_NFS) == 0) {
895 /*
896 * TRANSLATION_NOTE
897 * Zonepath and NFS are literals that should not be translated.
898 */
899 (void) fprintf(stderr, gettext("Zonepath %s is on an NFS "
916 "mounted file-system.\n"
917 "\tA local file-system must be used.\n"), rpath);
900 "mounted file system.\n"
901 "\tA local file system must be used.\n"), rpath);
918 return (Z_ERR);
919 }
920 if (vfsbuf.f_flag & ST_NOSUID) {
921 /*
922 * TRANSLATION_NOTE
923 * Zonepath and nosuid are literals that should not be
924 * translated.
925 */
926 (void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
902 return (Z_ERR);
903 }
904 if (vfsbuf.f_flag & ST_NOSUID) {
905 /*
906 * TRANSLATION_NOTE
907 * Zonepath and nosuid are literals that should not be
908 * translated.
909 */
910 (void) fprintf(stderr, gettext("Zonepath %s is on a nosuid "
927 "file-system.\n"), rpath);
911 "file system.\n"), rpath);
928 return (Z_ERR);
929 }
930
931 if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
932 errno = res;
933 zperror2(target_zone, gettext("could not get state"));
934 return (Z_ERR);
935 }

--- 1032 unchanged lines hidden (view full) ---

1968 }
1969 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
1970 /*
1971 * TRANSLATION_NOTE
1972 * inherit-pkg-dir and NFS are literals that should
1973 * not be translated.
1974 */
1975 (void) fprintf(stderr, gettext("cannot verify "
912 return (Z_ERR);
913 }
914
915 if ((res = zone_get_state(target_zone, &state)) != Z_OK) {
916 errno = res;
917 zperror2(target_zone, gettext("could not get state"));
918 return (Z_ERR);
919 }

--- 1032 unchanged lines hidden (view full) ---

1952 }
1953 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
1954 /*
1955 * TRANSLATION_NOTE
1956 * inherit-pkg-dir and NFS are literals that should
1957 * not be translated.
1958 */
1959 (void) fprintf(stderr, gettext("cannot verify "
1976 "inherit-pkg-dir %s: NFS mounted file-system.\n"
1977 "\tA local file-system must be used.\n"),
1960 "inherit-pkg-dir %s: NFS mounted file system.\n"
1961 "\tA local file system must be used.\n"),
1978 fstab.zone_fs_dir);
1979 return_code = Z_ERR;
1980 }
1981 }
1982 (void) zonecfg_endipdent(handle);
1983
1984 return (return_code);
1985}
1986
1962 fstab.zone_fs_dir);
1963 return_code = Z_ERR;
1964 }
1965 }
1966 (void) zonecfg_endipdent(handle);
1967
1968 return (return_code);
1969}
1970
1987/* ARGSUSED */
1988static void
1989zfs_fs_err_handler(const char *fmt, va_list ap)
1990{
1991 /*
1992 * Do nothing - do not print the libzfs error messages.
1993 */
1994}
1995
1996/*
1971/*
1997 * Verify that the ZFS dataset exists, and its mountpoint
1998 * property is set to "legacy".
1972 * Verify that the special device/file system exists and is valid.
1999 */
2000static int
1973 */
1974static int
2001verify_fs_zfs(struct zone_fstab *fstab)
2002{
2003 zfs_handle_t *zhp;
2004 char propbuf[ZFS_MAXPROPLEN];
2005
2006 zfs_set_error_handler(zfs_fs_err_handler);
2007
2008 if ((zhp = zfs_open(fstab->zone_fs_special, ZFS_TYPE_ANY)) == NULL) {
2009 (void) fprintf(stderr, gettext("could not verify fs %s: "
2010 "could not access zfs dataset '%s'\n"),
2011 fstab->zone_fs_dir, fstab->zone_fs_special);
2012 return (Z_ERR);
2013 }
2014
2015 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) {
2016 (void) fprintf(stderr, gettext("cannot verify fs %s: "
2017 "'%s' is not a filesystem\n"),
2018 fstab->zone_fs_dir, fstab->zone_fs_special);
2019 zfs_close(zhp);
2020 return (Z_ERR);
2021 }
2022
2023 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf, sizeof (propbuf),
2024 NULL, NULL, 0, 0) != 0 || strcmp(propbuf, "legacy") != 0) {
2025 (void) fprintf(stderr, gettext("could not verify fs %s: "
2026 "zfs '%s' mountpoint is not \"legacy\"\n"),
2027 fstab->zone_fs_dir, fstab->zone_fs_special);
2028 zfs_close(zhp);
2029 return (Z_ERR);
2030 }
2031
2032 zfs_close(zhp);
2033 return (Z_OK);
2034}
2035
2036/*
2037 * Verify that the special device/filesystem exists and is valid.
2038 */
2039static int
2040verify_fs_special(struct zone_fstab *fstab)
2041{
2042 struct stat st;
2043
2044 if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
2045 return (verify_fs_zfs(fstab));
2046
2047 if (stat(fstab->zone_fs_special, &st) != 0) {

--- 5 unchanged lines hidden (view full) ---

2053
2054 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
2055 /*
2056 * TRANSLATION_NOTE
2057 * fs and NFS are literals that should
2058 * not be translated.
2059 */
2060 (void) fprintf(stderr, gettext("cannot verify "
1975verify_fs_special(struct zone_fstab *fstab)
1976{
1977 struct stat st;
1978
1979 if (strcmp(fstab->zone_fs_type, MNTTYPE_ZFS) == 0)
1980 return (verify_fs_zfs(fstab));
1981
1982 if (stat(fstab->zone_fs_special, &st) != 0) {

--- 5 unchanged lines hidden (view full) ---

1988
1989 if (strcmp(st.st_fstype, MNTTYPE_NFS) == 0) {
1990 /*
1991 * TRANSLATION_NOTE
1992 * fs and NFS are literals that should
1993 * not be translated.
1994 */
1995 (void) fprintf(stderr, gettext("cannot verify "
2061 "fs %s: NFS mounted file-system.\n"
2062 "\tA local file-system must be used.\n"),
1996 "fs %s: NFS mounted file system.\n"
1997 "\tA local file system must be used.\n"),
2063 fstab->zone_fs_special);
2064 return (Z_ERR);
2065 }
2066
2067 return (Z_OK);
2068}
2069
2070static int
2071verify_filesystems(zone_dochandle_t handle)
2072{
2073 int return_code = Z_OK;
2074 struct zone_fstab fstab;
2075 char cmdbuf[MAXPATHLEN];
2076 struct stat st;
2077
2078 /*
2079 * No need to verify inherit-pkg-dir fs types, as their type is
2080 * implicitly lofs, which is known. Therefore, the types are only
1998 fstab->zone_fs_special);
1999 return (Z_ERR);
2000 }
2001
2002 return (Z_OK);
2003}
2004
2005static int
2006verify_filesystems(zone_dochandle_t handle)
2007{
2008 int return_code = Z_OK;
2009 struct zone_fstab fstab;
2010 char cmdbuf[MAXPATHLEN];
2011 struct stat st;
2012
2013 /*
2014 * No need to verify inherit-pkg-dir fs types, as their type is
2015 * implicitly lofs, which is known. Therefore, the types are only
2081 * verified for regular filesystems below.
2016 * verified for regular file systems below.
2082 *
2083 * Since the actual mount point is not known until the dependent mounts
2084 * are performed, we don't attempt any path validation here: that will
2085 * happen later when zoneadmd actually does the mounts.
2086 */
2087 if (zonecfg_setfsent(handle) != Z_OK) {
2017 *
2018 * Since the actual mount point is not known until the dependent mounts
2019 * are performed, we don't attempt any path validation here: that will
2020 * happen later when zoneadmd actually does the mounts.
2021 */
2022 if (zonecfg_setfsent(handle) != Z_OK) {
2088 (void) fprintf(stderr, gettext("could not verify file-systems: "
2023 (void) fprintf(stderr, gettext("could not verify file systems: "
2089 "unable to enumerate mounts\n"));
2090 return (Z_ERR);
2091 }
2092 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2093 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
2094 (void) fprintf(stderr, gettext("cannot verify fs %s: "
2095 "type %s is not allowed.\n"), fstab.zone_fs_dir,
2096 fstab.zone_fs_type);

--- 35 unchanged lines hidden (view full) ---

2132 "type %s is too long.\n"), fstab.zone_fs_dir,
2133 fstab.zone_fs_type);
2134 return_code = Z_ERR;
2135 goto next_fs;
2136 }
2137 if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) {
2138 (void) fprintf(stderr, gettext("could not verify fs "
2139 "%s: must specify 'raw' device for %s "
2024 "unable to enumerate mounts\n"));
2025 return (Z_ERR);
2026 }
2027 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
2028 if (!zonecfg_valid_fs_type(fstab.zone_fs_type)) {
2029 (void) fprintf(stderr, gettext("cannot verify fs %s: "
2030 "type %s is not allowed.\n"), fstab.zone_fs_dir,
2031 fstab.zone_fs_type);

--- 35 unchanged lines hidden (view full) ---

2067 "type %s is too long.\n"), fstab.zone_fs_dir,
2068 fstab.zone_fs_type);
2069 return_code = Z_ERR;
2070 goto next_fs;
2071 }
2072 if (fstab.zone_fs_raw[0] == '\0' && stat(cmdbuf, &st) == 0) {
2073 (void) fprintf(stderr, gettext("could not verify fs "
2074 "%s: must specify 'raw' device for %s "
2140 "file-systems\n"),
2075 "file systems\n"),
2141 fstab.zone_fs_dir, fstab.zone_fs_type);
2142 return_code = Z_ERR;
2143 goto next_fs;
2144 }
2145 if (fstab.zone_fs_raw[0] != '\0' &&
2146 (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
2147 (void) fprintf(stderr, gettext("cannot verify fs %s: "
2148 "'raw' device specified but "

--- 23 unchanged lines hidden (view full) ---

2172next_fs:
2173 zonecfg_free_fs_option_list(fstab.zone_fs_options);
2174 }
2175 (void) zonecfg_endfsent(handle);
2176
2177 return (return_code);
2178}
2179
2076 fstab.zone_fs_dir, fstab.zone_fs_type);
2077 return_code = Z_ERR;
2078 goto next_fs;
2079 }
2080 if (fstab.zone_fs_raw[0] != '\0' &&
2081 (stat(cmdbuf, &st) != 0 || !S_ISREG(st.st_mode))) {
2082 (void) fprintf(stderr, gettext("cannot verify fs %s: "
2083 "'raw' device specified but "

--- 23 unchanged lines hidden (view full) ---

2107next_fs:
2108 zonecfg_free_fs_option_list(fstab.zone_fs_options);
2109 }
2110 (void) zonecfg_endfsent(handle);
2111
2112 return (return_code);
2113}
2114
2180const char *current_dataset;
2181
2182/*
2183 * Custom error handler for errors incurred as part of the checks below. We
2184 * want to trim off the leading 'cannot open ...' to create a better error
2185 * message. The only other way this can fail is if we fail to set the 'zoned'
2186 * property. In this case we just pass the error on verbatim.
2187 */
2188static void
2189zfs_error_handler(const char *fmt, va_list ap)
2190{
2191 char buf[1024];
2192
2193 (void) vsnprintf(buf, sizeof (buf), fmt, ap);
2194
2195 if (strncmp(gettext("cannot open "), buf,
2196 strlen(gettext("cannot open "))) == 0)
2197 /*
2198 * TRANSLATION_NOTE
2199 * zfs and dataset are literals that should not be translated.
2200 */
2201 (void) fprintf(stderr, gettext("could not verify zfs "
2202 "dataset %s%s\n"), current_dataset, strchr(buf, ':'));
2203 else
2204 (void) fprintf(stderr, gettext("could not verify zfs dataset "
2205 "%s: %s\n"), current_dataset, buf);
2206}
2207
2208/* ARGSUSED */
2209static int
2115static int
2210check_zvol(zfs_handle_t *zhp, void *unused)
2211{
2212 int ret;
2213
2214 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
2215 /*
2216 * TRANSLATION_NOTE
2217 * zfs and dataset are literals that should not be translated.
2218 */
2219 (void) fprintf(stderr, gettext("cannot verify zfs dataset %s: "
2220 "volumes cannot be specified as a zone dataset resource\n"),
2221 zfs_get_name(zhp));
2222 ret = -1;
2223 } else {
2224 ret = zfs_iter_children(zhp, check_zvol, NULL);
2225 }
2226
2227 zfs_close(zhp);
2228
2229 return (ret);
2230}
2231
2232/*
2233 * Validate that the given dataset exists on the system, and that neither it nor
2234 * its children are zvols.
2235 *
2236 * Note that we don't do anything with the 'zoned' property here. All
2237 * management is done in zoneadmd when the zone is actually rebooted. This
2238 * allows us to automatically set the zoned property even when a zone is
2239 * rebooted by the administrator.
2240 */
2241static int
2242verify_datasets(zone_dochandle_t handle)
2243{
2244 int return_code = Z_OK;
2245 struct zone_dstab dstab;
2246 zfs_handle_t *zhp;
2247 char propbuf[ZFS_MAXPROPLEN];
2248 char source[ZFS_MAXNAMELEN];
2249 zfs_source_t srctype;
2250
2251 if (zonecfg_setdsent(handle) != Z_OK) {
2252 /*
2253 * TRANSLATION_NOTE
2254 * zfs and dataset are literals that should not be translated.
2255 */
2256 (void) fprintf(stderr, gettext("could not verify zfs datasets: "
2257 "unable to enumerate datasets\n"));
2258 return (Z_ERR);
2259 }
2260
2261 zfs_set_error_handler(zfs_error_handler);
2262
2263 while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
2264
2265 current_dataset = dstab.zone_dataset_name;
2266
2267 if ((zhp = zfs_open(dstab.zone_dataset_name,
2268 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) == NULL) {
2269 return_code = Z_ERR;
2270 continue;
2271 }
2272
2273 if (zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, propbuf,
2274 sizeof (propbuf), &srctype, source,
2275 sizeof (source), 0) == 0 &&
2276 (srctype == ZFS_SRC_INHERITED)) {
2277 (void) fprintf(stderr, gettext("could not verify zfs "
2278 "dataset %s: mountpoint cannot be inherited\n"),
2279 dstab.zone_dataset_name);
2280 return_code = Z_ERR;
2281 zfs_close(zhp);
2282 continue;
2283 }
2284
2285 if (zfs_get_type(zhp) == ZFS_TYPE_VOLUME) {
2286 (void) fprintf(stderr, gettext("cannot verify zfs "
2287 "dataset %s: volumes cannot be specified as a "
2288 "zone dataset resource\n"),
2289 dstab.zone_dataset_name);
2290 return_code = Z_ERR;
2291 }
2292
2293 if (zfs_iter_children(zhp, check_zvol, NULL) != 0)
2294 return_code = Z_ERR;
2295
2296 zfs_close(zhp);
2297 }
2298 (void) zonecfg_enddsent(handle);
2299
2300 return (return_code);
2301}
2302
2303static int
2304verify_limitpriv(zone_dochandle_t handle)
2305{
2306 char *privname = NULL;
2307 int err;
2308 priv_set_t *privs;
2309
2310 if ((privs = priv_allocset()) == NULL) {
2311 zperror(gettext("failed to allocate privilege set"), B_FALSE);

--- 194 unchanged lines hidden (view full) ---

2506install_func(int argc, char *argv[])
2507{
2508 /* 9: "exec " and " -z " */
2509 char cmdbuf[sizeof (LUCREATEZONE) + ZONENAME_MAX + 9];
2510 int lockfd;
2511 int err, arg;
2512 char zonepath[MAXPATHLEN];
2513 int status;
2116verify_limitpriv(zone_dochandle_t handle)
2117{
2118 char *privname = NULL;
2119 int err;
2120 priv_set_t *privs;
2121
2122 if ((privs = priv_allocset()) == NULL) {
2123 zperror(gettext("failed to allocate privilege set"), B_FALSE);

--- 194 unchanged lines hidden (view full) ---

2318install_func(int argc, char *argv[])
2319{
2320 /* 9: "exec " and " -z " */
2321 char cmdbuf[sizeof (LUCREATEZONE) + ZONENAME_MAX + 9];
2322 int lockfd;
2323 int err, arg;
2324 char zonepath[MAXPATHLEN];
2325 int status;
2326 boolean_t nodataset = B_FALSE;
2514
2515 if (zonecfg_in_alt_root()) {
2516 zerror(gettext("cannot install zone in alternate root"));
2517 return (Z_ERR);
2518 }
2519
2520 optind = 0;
2327
2328 if (zonecfg_in_alt_root()) {
2329 zerror(gettext("cannot install zone in alternate root"));
2330 return (Z_ERR);
2331 }
2332
2333 optind = 0;
2521 if ((arg = getopt(argc, argv, "?")) != EOF) {
2334 if ((arg = getopt(argc, argv, "?x:")) != EOF) {
2522 switch (arg) {
2523 case '?':
2524 sub_usage(SHELP_INSTALL, CMD_INSTALL);
2525 return (optopt == '?' ? Z_OK : Z_USAGE);
2335 switch (arg) {
2336 case '?':
2337 sub_usage(SHELP_INSTALL, CMD_INSTALL);
2338 return (optopt == '?' ? Z_OK : Z_USAGE);
2339 case 'x':
2340 if (strcmp(optarg, "nodataset") != 0) {
2341 sub_usage(SHELP_INSTALL, CMD_INSTALL);
2342 return (Z_USAGE);
2343 }
2344 nodataset = B_TRUE;
2345 break;
2526 default:
2527 sub_usage(SHELP_INSTALL, CMD_INSTALL);
2528 return (Z_USAGE);
2529 }
2530 }
2531 if (argc > optind) {
2532 sub_usage(SHELP_INSTALL, CMD_INSTALL);
2533 return (Z_USAGE);

--- 26 unchanged lines hidden (view full) ---

2560 * path to the zone is again restricted.
2561 */
2562 if ((err = zone_get_zonepath(target_zone, zonepath,
2563 sizeof (zonepath))) != Z_OK) {
2564 errno = err;
2565 zperror2(target_zone, gettext("could not get zone path"));
2566 goto done;
2567 }
2346 default:
2347 sub_usage(SHELP_INSTALL, CMD_INSTALL);
2348 return (Z_USAGE);
2349 }
2350 }
2351 if (argc > optind) {
2352 sub_usage(SHELP_INSTALL, CMD_INSTALL);
2353 return (Z_USAGE);

--- 26 unchanged lines hidden (view full) ---

2380 * path to the zone is again restricted.
2381 */
2382 if ((err = zone_get_zonepath(target_zone, zonepath,
2383 sizeof (zonepath))) != Z_OK) {
2384 errno = err;
2385 zperror2(target_zone, gettext("could not get zone path"));
2386 goto done;
2387 }
2388
2389 if (!nodataset)
2390 create_zfs_zonepath(zonepath);
2391
2568 if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) {
2569 zperror(zonepath, B_FALSE);
2570 err = Z_ERR;
2571 goto done;
2572 }
2573
2574 /*
2575 * "exec" the command so that the returned status is that of

--- 174 unchanged lines hidden (view full) ---

2750 if (strcmp(p, opt) == 0)
2751 return (B_TRUE);
2752 }
2753 }
2754
2755 return (B_FALSE);
2756}
2757
2392 if (chmod(zonepath, DEFAULT_DIR_MODE) != 0) {
2393 zperror(zonepath, B_FALSE);
2394 err = Z_ERR;
2395 goto done;
2396 }
2397
2398 /*
2399 * "exec" the command so that the returned status is that of

--- 174 unchanged lines hidden (view full) ---

2574 if (strcmp(p, opt) == 0)
2575 return (B_TRUE);
2576 }
2577 }
2578
2579 return (B_FALSE);
2580}
2581
2758#define RW_LOFS "WARNING: read-write lofs file-system on '%s' is configured " \
2582#define RW_LOFS "WARNING: read-write lofs file system on '%s' is configured " \
2759 "in both zones.\n"
2760
2761static void
2762print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab)
2763{
2764 /*
2765 * It is ok to have shared lofs mounted fs but we want to warn if
2766 * either is rw since this will effect the other zone.

--- 27 unchanged lines hidden (view full) ---

2794 }
2795 }
2796
2797 return;
2798 }
2799
2800 /*
2801 * TRANSLATION_NOTE
2583 "in both zones.\n"
2584
2585static void
2586print_fs_warnings(struct zone_fstab *s_fstab, struct zone_fstab *t_fstab)
2587{
2588 /*
2589 * It is ok to have shared lofs mounted fs but we want to warn if
2590 * either is rw since this will effect the other zone.

--- 27 unchanged lines hidden (view full) ---

2618 }
2619 }
2620
2621 return;
2622 }
2623
2624 /*
2625 * TRANSLATION_NOTE
2802 * The first variable is the file-system type and the second is
2803 * the file-system special device. For example,
2804 * WARNING: ufs file-system on '/dev/dsk/c0t0d0s0' ...
2626 * The first variable is the file system type and the second is
2627 * the file system special device. For example,
2628 * WARNING: ufs file system on '/dev/dsk/c0t0d0s0' ...
2805 */
2629 */
2806 (void) fprintf(stderr, gettext("WARNING: %s file-system on '%s' "
2630 (void) fprintf(stderr, gettext("WARNING: %s file system on '%s' "
2807 "is configured in both zones.\n"), t_fstab->zone_fs_type,
2808 t_fstab->zone_fs_special);
2809}
2810
2811static void
2812warn_fs_match(zone_dochandle_t s_handle, char *source_zone,
2813 zone_dochandle_t t_handle, char *target_zone)
2814{
2815 int err;
2816 struct zone_fstab s_fstab;
2817 struct zone_fstab t_fstab;
2818
2819 if ((err = zonecfg_setfsent(t_handle)) != Z_OK) {
2820 errno = err;
2821 zperror2(target_zone,
2631 "is configured in both zones.\n"), t_fstab->zone_fs_type,
2632 t_fstab->zone_fs_special);
2633}
2634
2635static void
2636warn_fs_match(zone_dochandle_t s_handle, char *source_zone,
2637 zone_dochandle_t t_handle, char *target_zone)
2638{
2639 int err;
2640 struct zone_fstab s_fstab;
2641 struct zone_fstab t_fstab;
2642
2643 if ((err = zonecfg_setfsent(t_handle)) != Z_OK) {
2644 errno = err;
2645 zperror2(target_zone,
2822 gettext("could not enumerate file-systems"));
2646 gettext("could not enumerate file systems"));
2823 return;
2824 }
2825
2826 while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) {
2827 if ((err = zonecfg_setfsent(s_handle)) != Z_OK) {
2828 errno = err;
2829 zperror2(source_zone,
2647 return;
2648 }
2649
2650 while (zonecfg_getfsent(t_handle, &t_fstab) == Z_OK) {
2651 if ((err = zonecfg_setfsent(s_handle)) != Z_OK) {
2652 errno = err;
2653 zperror2(source_zone,
2830 gettext("could not enumerate file-systems"));
2654 gettext("could not enumerate file systems"));
2831 (void) zonecfg_endfsent(t_handle);
2832 return;
2833 }
2834
2835 while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) {
2836 if (strcmp(t_fstab.zone_fs_special,
2837 s_fstab.zone_fs_special) == 0) {
2838 print_fs_warnings(&s_fstab, &t_fstab);

--- 163 unchanged lines hidden (view full) ---

3002 char *outfile;
3003 char cmdbuf[MAXPATHLEN * 2 + 128];
3004
3005 if ((outfile = tempnam("/var/log", "zone")) == NULL) {
3006 outfile = "/dev/null";
3007 out_null = B_TRUE;
3008 }
3009
2655 (void) zonecfg_endfsent(t_handle);
2656 return;
2657 }
2658
2659 while (zonecfg_getfsent(s_handle, &s_fstab) == Z_OK) {
2660 if (strcmp(t_fstab.zone_fs_special,
2661 s_fstab.zone_fs_special) == 0) {
2662 print_fs_warnings(&s_fstab, &t_fstab);

--- 163 unchanged lines hidden (view full) ---

2826 char *outfile;
2827 char cmdbuf[MAXPATHLEN * 2 + 128];
2828
2829 if ((outfile = tempnam("/var/log", "zone")) == NULL) {
2830 outfile = "/dev/null";
2831 out_null = B_TRUE;
2832 }
2833
2834 /*
2835 * Use find to get the list of files to copy. We need to skip
2836 * files of type "socket" since cpio can't handle those but that
2837 * should be ok since the app will recreate the socket when it runs.
2838 * We also need to filter out anything under the .zfs subdir. Since
2839 * find is running depth-first, we need the extra egrep to filter .zfs.
2840 */
3010 (void) snprintf(cmdbuf, sizeof (cmdbuf),
2841 (void) snprintf(cmdbuf, sizeof (cmdbuf),
3011 "cd %s && /usr/bin/find . -depth -print | "
2842 "cd %s && /usr/bin/find . -type s -prune -o -depth -print | "
3012 "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | "
3013 "/usr/bin/cpio -pdmuP@ %s > %s 2>&1",
3014 src, dst, outfile);
3015
3016 status = do_subproc(cmdbuf);
3017
3018 if ((err = subproc_status("copy", status)) != Z_OK) {
3019 if (!out_null)

--- 68 unchanged lines hidden (view full) ---

3088 (void) fprintf(stderr, gettext("could not unmount zone\n"));
3089 return (Z_ERR);
3090 }
3091
3092 return ((err == Z_OK) ? Z_OK : Z_ERR);
3093}
3094
3095/* ARGSUSED */
2843 "/usr/bin/egrep -v '^\\./\\.zfs$|^\\./\\.zfs/' | "
2844 "/usr/bin/cpio -pdmuP@ %s > %s 2>&1",
2845 src, dst, outfile);
2846
2847 status = do_subproc(cmdbuf);
2848
2849 if ((err = subproc_status("copy", status)) != Z_OK) {
2850 if (!out_null)

--- 68 unchanged lines hidden (view full) ---

2919 (void) fprintf(stderr, gettext("could not unmount zone\n"));
2920 return (Z_ERR);
2921 }
2922
2923 return ((err == Z_OK) ? Z_OK : Z_ERR);
2924}
2925
2926/* ARGSUSED */
3096int
2927static int
3097zfm_print(const char *p, void *r) {
3098 zerror(" %s\n", p);
3099 return (0);
3100}
3101
2928zfm_print(const char *p, void *r) {
2929 zerror(" %s\n", p);
2930 return (0);
2931}
2932
2933int
2934clone_copy(char *source_zonepath, char *zonepath)
2935{
2936 int err;
2937
2938 /* Don't clone the zone if anything is still mounted there */
2939 if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) {
2940 zerror(gettext("These file systems are mounted on "
2941 "subdirectories of %s.\n"), source_zonepath);
2942 (void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL);
2943 return (Z_ERR);
2944 }
2945
2946 /*
2947 * Attempt to create a ZFS fs for the zonepath. As usual, we don't
2948 * care if this works or not since we always have the default behavior
2949 * of a simple directory for the zonepath.
2950 */
2951 create_zfs_zonepath(zonepath);
2952
2953 (void) printf(gettext("Copying %s..."), source_zonepath);
2954 (void) fflush(stdout);
2955
2956 err = copy_zone(source_zonepath, zonepath);
2957
2958 (void) printf("\n");
2959
2960 return (err);
2961}
2962
3102static int
3103clone_func(int argc, char *argv[])
3104{
3105 char *source_zone = NULL;
3106 int lockfd;
3107 int err, arg;
3108 char zonepath[MAXPATHLEN];
3109 char source_zonepath[MAXPATHLEN];
3110 zone_state_t state;
3111 zone_entry_t *zent;
2963static int
2964clone_func(int argc, char *argv[])
2965{
2966 char *source_zone = NULL;
2967 int lockfd;
2968 int err, arg;
2969 char zonepath[MAXPATHLEN];
2970 char source_zonepath[MAXPATHLEN];
2971 zone_state_t state;
2972 zone_entry_t *zent;
3112 char *method = "copy";
2973 char *method = NULL;
2974 char *snapshot = NULL;
3113
3114 if (zonecfg_in_alt_root()) {
3115 zerror(gettext("cannot clone zone in alternate root"));
3116 return (Z_ERR);
3117 }
3118
3119 optind = 0;
2975
2976 if (zonecfg_in_alt_root()) {
2977 zerror(gettext("cannot clone zone in alternate root"));
2978 return (Z_ERR);
2979 }
2980
2981 optind = 0;
3120 if ((arg = getopt(argc, argv, "?m:")) != EOF) {
2982 if ((arg = getopt(argc, argv, "?m:s:")) != EOF) {
3121 switch (arg) {
3122 case '?':
3123 sub_usage(SHELP_CLONE, CMD_CLONE);
3124 return (optopt == '?' ? Z_OK : Z_USAGE);
3125 case 'm':
3126 method = optarg;
3127 break;
2983 switch (arg) {
2984 case '?':
2985 sub_usage(SHELP_CLONE, CMD_CLONE);
2986 return (optopt == '?' ? Z_OK : Z_USAGE);
2987 case 'm':
2988 method = optarg;
2989 break;
2990 case 's':
2991 snapshot = optarg;
2992 break;
3128 default:
3129 sub_usage(SHELP_CLONE, CMD_CLONE);
3130 return (Z_USAGE);
3131 }
3132 }
2993 default:
2994 sub_usage(SHELP_CLONE, CMD_CLONE);
2995 return (Z_USAGE);
2996 }
2997 }
3133 if (argc != (optind + 1) || strcmp(method, "copy") != 0) {
2998 if (argc != (optind + 1) ||
2999 (method != NULL && strcmp(method, "copy") != 0)) {
3134 sub_usage(SHELP_CLONE, CMD_CLONE);
3135 return (Z_USAGE);
3136 }
3137 source_zone = argv[optind];
3138 if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE) != Z_OK)
3139 return (Z_ERR);
3140 if (verify_details(CMD_CLONE) != Z_OK)
3141 return (Z_ERR);
3142
3143 /*
3144 * We also need to do some extra validation on the source zone.
3145 */
3000 sub_usage(SHELP_CLONE, CMD_CLONE);
3001 return (Z_USAGE);
3002 }
3003 source_zone = argv[optind];
3004 if (sanity_check(target_zone, CMD_CLONE, B_FALSE, B_TRUE) != Z_OK)
3005 return (Z_ERR);
3006 if (verify_details(CMD_CLONE) != Z_OK)
3007 return (Z_ERR);
3008
3009 /*
3010 * We also need to do some extra validation on the source zone.
3011 */
3146
3147 if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) {
3148 zerror(gettext("%s operation is invalid for the global zone."),
3149 cmd_to_str(CMD_CLONE));
3150 return (Z_ERR);
3151 }
3152
3153 if (strncmp(source_zone, "SUNW", 4) == 0) {
3154 zerror(gettext("%s operation is invalid for zones starting "

--- 53 unchanged lines hidden (view full) ---

3208
3209 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3210 != Z_OK) {
3211 errno = err;
3212 zperror2(target_zone, gettext("could not get zone path"));
3213 goto done;
3214 }
3215
3012 if (strcmp(source_zone, GLOBAL_ZONENAME) == 0) {
3013 zerror(gettext("%s operation is invalid for the global zone."),
3014 cmd_to_str(CMD_CLONE));
3015 return (Z_ERR);
3016 }
3017
3018 if (strncmp(source_zone, "SUNW", 4) == 0) {
3019 zerror(gettext("%s operation is invalid for zones starting "

--- 53 unchanged lines hidden (view full) ---

3073
3074 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3075 != Z_OK) {
3076 errno = err;
3077 zperror2(target_zone, gettext("could not get zone path"));
3078 goto done;
3079 }
3080
3216 /* Don't clone the zone if anything is still mounted there */
3217 if (zonecfg_find_mounts(source_zonepath, NULL, NULL)) {
3218 zerror(gettext("These file-systems are mounted on "
3219 "subdirectories of %s.\n"), source_zonepath);
3220 (void) zonecfg_find_mounts(source_zonepath, zfm_print, NULL);
3221 err = Z_ERR;
3222 goto done;
3223 }
3224
3225 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
3226 != Z_OK) {
3227 errno = err;
3228 zperror2(target_zone, gettext("could not set state"));
3229 goto done;
3230 }
3231
3081 if ((err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE))
3082 != Z_OK) {
3083 errno = err;
3084 zperror2(target_zone, gettext("could not set state"));
3085 goto done;
3086 }
3087
3232 (void) printf(gettext("Cloning zonepath %s..."), source_zonepath);
3233 (void) fflush(stdout);
3088 if (snapshot != NULL) {
3089 err = clone_snapshot_zfs(snapshot, zonepath);
3090 } else {
3091 /*
3092 * We always copy the clone unless the source is ZFS and a
3093 * ZFS clone worked. We fallback to copying if the ZFS clone
3094 * fails for some reason.
3095 */
3096 err = Z_ERR;
3097 if (method == NULL && is_zonepath_zfs(source_zonepath))
3098 err = clone_zfs(source_zone, source_zonepath, zonepath);
3234
3099
3235 err = copy_zone(source_zonepath, zonepath);
3236 (void) printf("\n");
3237 if (err != Z_OK)
3238 goto done;
3100 if (err != Z_OK)
3101 err = clone_copy(source_zonepath, zonepath);
3102 }
3239
3103
3240 err = unconfigure_zone(zonepath);
3104 if (err == Z_OK)
3105 err = unconfigure_zone(zonepath);
3241
3242done:
3243 release_lock_file(lockfd);
3244 return ((err == Z_OK) ? Z_OK : Z_ERR);
3245}
3246
3247#define RMCOMMAND "/usr/bin/rm -rf"
3248
3249/*
3106
3107done:
3108 release_lock_file(lockfd);
3109 return ((err == Z_OK) ? Z_OK : Z_ERR);
3110}
3111
3112#define RMCOMMAND "/usr/bin/rm -rf"
3113
3114/*
3250 * Used when moving a zonepath (via copying) to clean up the old path or
3251 * the new path if there was an error.
3115 * Used when removing a zonepath after uninstalling or cleaning up after
3116 * the move subcommand. This handles a zonepath that has non-standard
3117 * contents so that we will only cleanup the stuff we know about and leave
3118 * any user data alone.
3252 *
3119 *
3253 * This function handles the case of a zonepath being a zfs filesystem.
3254 * If it is a zfs filesystem, we cannot just remove the whole zonepath
3255 * since we can't remove the filesystem itself. Instead, we have to remove
3256 * the contents of the filesystem, but not the .zfs directory.
3120 * If the "all" parameter is true then we should remove the whole zonepath
3121 * even if it has non-standard files/directories in it. This can be used when
3122 * we need to cleanup after moving the zonepath across file systems.
3123 *
3124 * We "exec" the RMCOMMAND so that the returned status is that of RMCOMMAND
3125 * and not the shell.
3257 */
3258static int
3126 */
3127static int
3259remove_zonepath(char *zonepath)
3128cleanup_zonepath(char *zonepath, boolean_t all)
3260{
3129{
3261 int status;
3262 boolean_t is_zfs = B_FALSE;
3263 struct stat buf;
3264 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 128];
3130 int status;
3131 int i;
3132 boolean_t non_std = B_FALSE;
3133 struct dirent *dp;
3134 DIR *dirp;
3135 char *std_entries[] = {"dev", "lu", "root", NULL};
3136 /* (MAXPATHLEN * 3) is for the 3 std_entries dirs */
3137 char cmdbuf[sizeof (RMCOMMAND) + (MAXPATHLEN * 3) + 64];
3265
3138
3266 (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s/.zfs", zonepath);
3139 /*
3140 * We shouldn't need these checks but lets be paranoid since we
3141 * could blow away the whole system here if we got the wrong zonepath.
3142 */
3143 if (*zonepath == NULL || strcmp(zonepath, "/") == 0) {
3144 (void) fprintf(stderr, "invalid zonepath '%s'\n", zonepath);
3145 return (Z_INVAL);
3146 }
3267
3147
3268 if (stat(cmdbuf, &buf) == 0 && S_ISDIR(buf.st_mode))
3269 is_zfs = B_TRUE;
3148 /*
3149 * If the dirpath is already gone (maybe it was manually removed) then
3150 * we just return Z_OK so that the cleanup is successful.
3151 */
3152 if ((dirp = opendir(zonepath)) == NULL)
3153 return (Z_OK);
3270
3154
3271 if (is_zfs) {
3155 /*
3156 * Look through the zonepath directory to see if there are any
3157 * non-standard files/dirs. Also skip .zfs since that might be
3158 * there but we'll handle ZFS file systems as a special case.
3159 */
3160 while ((dp = readdir(dirp)) != NULL) {
3161 if (strcmp(dp->d_name, ".") == 0 ||
3162 strcmp(dp->d_name, "..") == 0 ||
3163 strcmp(dp->d_name, ".zfs") == 0)
3164 continue;
3165
3166 for (i = 0; std_entries[i] != NULL; i++)
3167 if (strcmp(dp->d_name, std_entries[i]) == 0)
3168 break;
3169
3170 if (std_entries[i] == NULL)
3171 non_std = B_TRUE;
3172 }
3173 (void) closedir(dirp);
3174
3175 if (!all && non_std) {
3272 /*
3176 /*
3273 * This doesn't handle the (unlikely) case that there are
3274 * directories or files in the top-level zonepath with white
3275 * space in the names.
3177 * There are extra, non-standard directories/files in the
3178 * zonepath so we don't want to remove the zonepath. We
3179 * just want to remove the standard directories and leave
3180 * the user data alone.
3276 */
3181 */
3277 (void) snprintf(cmdbuf, sizeof (cmdbuf),
3278 "cd %s && /usr/bin/ls -A | /usr/bin/egrep -v '^\\.zfs$' | "
3279 "/usr/bin/xargs " RMCOMMAND, zonepath);
3280 } else {
3281 /*
3282 * "exec" the command so that the returned status is
3283 * that of rm and not the shell.
3284 */
3285 (void) snprintf(cmdbuf, sizeof (cmdbuf),
3286 "exec " RMCOMMAND " %s", zonepath);
3287 }
3182 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND);
3288
3183
3289 status = do_subproc(cmdbuf);
3184 for (i = 0; std_entries[i] != NULL; i++) {
3185 char tmpbuf[MAXPATHLEN];
3290
3186
3291 return (subproc_status("rm", status));
3187 if (snprintf(tmpbuf, sizeof (tmpbuf), " %s/%s",
3188 zonepath, std_entries[i]) >= sizeof (tmpbuf) ||
3189 strlcat(cmdbuf, tmpbuf, sizeof (cmdbuf)) >=
3190 sizeof (cmdbuf)) {
3191 (void) fprintf(stderr,
3192 gettext("path is too long\n"));
3193 return (Z_INVAL);
3194 }
3195 }
3292
3196
3197 status = do_subproc(cmdbuf);
3198
3199 (void) fprintf(stderr, gettext("WARNING: Unable to completely "
3200 "remove %s\nbecause it contains additional user data. "
3201 "Only the standard directory\nentries have been "
3202 "removed.\n"),
3203 zonepath);
3204
3205 return (subproc_status(RMCOMMAND, status));
3206 }
3207
3208 /*
3209 * There is nothing unexpected in the zonepath, try to get rid of the
3210 * whole zonepath directory.
3211 *
3212 * If the zonepath is its own zfs file system, try to destroy the
3213 * file system. If that fails for some reason (e.g. it has clones)
3214 * then we'll just remove the contents of the zonepath.
3215 */
3216 if (is_zonepath_zfs(zonepath)) {
3217 if (destroy_zfs(zonepath) == Z_OK)
3218 return (Z_OK);
3219 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND
3220 " %s/*", zonepath);
3221 status = do_subproc(cmdbuf);
3222 return (subproc_status(RMCOMMAND, status));
3223 }
3224
3225 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
3226 zonepath);
3227 status = do_subproc(cmdbuf);
3228 return (subproc_status(RMCOMMAND, status));
3293}
3294
3295static int
3296move_func(int argc, char *argv[])
3297{
3298 char *new_zonepath = NULL;
3299 int lockfd;
3300 int err, arg;
3301 char zonepath[MAXPATHLEN];
3302 zone_dochandle_t handle;
3303 boolean_t fast;
3229}
3230
3231static int
3232move_func(int argc, char *argv[])
3233{
3234 char *new_zonepath = NULL;
3235 int lockfd;
3236 int err, arg;
3237 char zonepath[MAXPATHLEN];
3238 zone_dochandle_t handle;
3239 boolean_t fast;
3240 boolean_t is_zfs = B_FALSE;
3241 struct dirent *dp;
3242 DIR *dirp;
3243 boolean_t empty = B_TRUE;
3304 boolean_t revert;
3305 struct stat zonepath_buf;
3306 struct stat new_zonepath_buf;
3307
3308 if (zonecfg_in_alt_root()) {
3309 zerror(gettext("cannot move zone in alternate root"));
3310 return (Z_ERR);
3311 }

--- 17 unchanged lines hidden (view full) ---

3329 if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE) != Z_OK)
3330 return (Z_ERR);
3331 if (verify_details(CMD_MOVE) != Z_OK)
3332 return (Z_ERR);
3333
3334 /*
3335 * Check out the new zonepath. This has the side effect of creating
3336 * a directory for the new zonepath. We depend on this later when we
3244 boolean_t revert;
3245 struct stat zonepath_buf;
3246 struct stat new_zonepath_buf;
3247
3248 if (zonecfg_in_alt_root()) {
3249 zerror(gettext("cannot move zone in alternate root"));
3250 return (Z_ERR);
3251 }

--- 17 unchanged lines hidden (view full) ---

3269 if (sanity_check(target_zone, CMD_MOVE, B_FALSE, B_TRUE) != Z_OK)
3270 return (Z_ERR);
3271 if (verify_details(CMD_MOVE) != Z_OK)
3272 return (Z_ERR);
3273
3274 /*
3275 * Check out the new zonepath. This has the side effect of creating
3276 * a directory for the new zonepath. We depend on this later when we
3337 * stat to see if we are doing a cross file-system move or not.
3277 * stat to see if we are doing a cross file system move or not.
3338 */
3339 if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK)
3340 return (Z_ERR);
3341
3342 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3343 != Z_OK) {
3344 errno = err;
3345 zperror2(target_zone, gettext("could not get zone path"));

--- 5 unchanged lines hidden (view full) ---

3351 return (Z_ERR);
3352 }
3353
3354 if (stat(new_zonepath, &new_zonepath_buf) == -1) {
3355 zperror(gettext("could not stat new zone path"), B_FALSE);
3356 return (Z_ERR);
3357 }
3358
3278 */
3279 if (validate_zonepath(new_zonepath, CMD_MOVE) != Z_OK)
3280 return (Z_ERR);
3281
3282 if ((err = zone_get_zonepath(target_zone, zonepath, sizeof (zonepath)))
3283 != Z_OK) {
3284 errno = err;
3285 zperror2(target_zone, gettext("could not get zone path"));

--- 5 unchanged lines hidden (view full) ---

3291 return (Z_ERR);
3292 }
3293
3294 if (stat(new_zonepath, &new_zonepath_buf) == -1) {
3295 zperror(gettext("could not stat new zone path"), B_FALSE);
3296 return (Z_ERR);
3297 }
3298
3299 /*
3300 * Check if the destination directory is empty.
3301 */
3302 if ((dirp = opendir(new_zonepath)) == NULL) {
3303 zperror(gettext("could not open new zone path"), B_FALSE);
3304 return (Z_ERR);
3305 }
3306 while ((dp = readdir(dirp)) != (struct dirent *)0) {
3307 if (strcmp(dp->d_name, ".") == 0 ||
3308 strcmp(dp->d_name, "..") == 0)
3309 continue;
3310 empty = B_FALSE;
3311 break;
3312 }
3313 (void) closedir(dirp);
3314
3315 /* Error if there is anything in the destination directory. */
3316 if (!empty) {
3317 (void) fprintf(stderr, gettext("could not move zone to %s: "
3318 "directory not empty\n"), new_zonepath);
3319 return (Z_ERR);
3320 }
3321
3359 /* Don't move the zone if anything is still mounted there */
3360 if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
3322 /* Don't move the zone if anything is still mounted there */
3323 if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
3361 zerror(gettext("These file-systems are mounted on "
3324 zerror(gettext("These file systems are mounted on "
3362 "subdirectories of %s.\n"), zonepath);
3363 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
3364 return (Z_ERR);
3365 }
3366
3367 /*
3325 "subdirectories of %s.\n"), zonepath);
3326 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
3327 return (Z_ERR);
3328 }
3329
3330 /*
3368 * Check if we are moving in the same filesystem and can do a fast
3369 * move or if we are crossing filesystems and have to copy the data.
3331 * Check if we are moving in the same file system and can do a fast
3332 * move or if we are crossing file systems and have to copy the data.
3370 */
3371 fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev);
3372
3373 if ((handle = zonecfg_init_handle()) == NULL) {
3374 zperror(cmd_to_str(CMD_MOVE), B_TRUE);
3375 return (Z_ERR);
3376 }
3377

--- 7 unchanged lines hidden (view full) ---

3385 if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3386 zerror(gettext("another %s may have an operation in progress."),
3387 "zoneadm");
3388 zonecfg_fini_handle(handle);
3389 return (Z_ERR);
3390 }
3391
3392 /*
3333 */
3334 fast = (zonepath_buf.st_dev == new_zonepath_buf.st_dev);
3335
3336 if ((handle = zonecfg_init_handle()) == NULL) {
3337 zperror(cmd_to_str(CMD_MOVE), B_TRUE);
3338 return (Z_ERR);
3339 }
3340

--- 7 unchanged lines hidden (view full) ---

3348 if (grab_lock_file(target_zone, &lockfd) != Z_OK) {
3349 zerror(gettext("another %s may have an operation in progress."),
3350 "zoneadm");
3351 zonecfg_fini_handle(handle);
3352 return (Z_ERR);
3353 }
3354
3355 /*
3393 * We're making some file-system changes now so we have to clean up
3394 * the file-system before we are done. This will either clean up the
3356 * We're making some file system changes now so we have to clean up
3357 * the file system before we are done. This will either clean up the
3395 * new zonepath if the zonecfg update failed or it will clean up the
3396 * old zonepath if everything is ok.
3397 */
3398 revert = B_TRUE;
3399
3358 * new zonepath if the zonecfg update failed or it will clean up the
3359 * old zonepath if everything is ok.
3360 */
3361 revert = B_TRUE;
3362
3400 if (fast) {
3401 /* same filesystem, use rename for a quick move */
3363 if (is_zonepath_zfs(zonepath) &&
3364 move_zfs(zonepath, new_zonepath) != Z_ERR) {
3365 is_zfs = B_TRUE;
3402
3366
3367 } else if (fast) {
3368 /* same file system, use rename for a quick move */
3369
3403 /*
3404 * Remove the new_zonepath directory that got created above
3405 * during the validation. It gets in the way of the rename.
3406 */
3407 if (rmdir(new_zonepath) != 0) {
3408 zperror(gettext("could not rmdir new zone path"),
3409 B_FALSE);
3410 zonecfg_fini_handle(handle);

--- 9 unchanged lines hidden (view full) ---

3420 */
3421 zperror(gettext("could not move zone"), B_FALSE);
3422 zonecfg_fini_handle(handle);
3423 release_lock_file(lockfd);
3424 return (Z_ERR);
3425 }
3426
3427 } else {
3370 /*
3371 * Remove the new_zonepath directory that got created above
3372 * during the validation. It gets in the way of the rename.
3373 */
3374 if (rmdir(new_zonepath) != 0) {
3375 zperror(gettext("could not rmdir new zone path"),
3376 B_FALSE);
3377 zonecfg_fini_handle(handle);

--- 9 unchanged lines hidden (view full) ---

3387 */
3388 zperror(gettext("could not move zone"), B_FALSE);
3389 zonecfg_fini_handle(handle);
3390 release_lock_file(lockfd);
3391 return (Z_ERR);
3392 }
3393
3394 } else {
3395 /*
3396 * Attempt to create a ZFS fs for the new zonepath. As usual,
3397 * we don't care if this works or not since we always have the
3398 * default behavior of a simple directory for the zonepath.
3399 */
3400 create_zfs_zonepath(new_zonepath);
3401
3428 (void) printf(gettext(
3402 (void) printf(gettext(
3429 "Moving across file-systems; copying zonepath %s..."),
3403 "Moving across file systems; copying zonepath %s..."),
3430 zonepath);
3431 (void) fflush(stdout);
3432
3433 err = copy_zone(zonepath, new_zonepath);
3434
3435 (void) printf("\n");
3436 if (err != Z_OK)
3437 goto done;

--- 13 unchanged lines hidden (view full) ---

3451
3452 revert = B_FALSE;
3453
3454done:
3455 zonecfg_fini_handle(handle);
3456 release_lock_file(lockfd);
3457
3458 /*
3404 zonepath);
3405 (void) fflush(stdout);
3406
3407 err = copy_zone(zonepath, new_zonepath);
3408
3409 (void) printf("\n");
3410 if (err != Z_OK)
3411 goto done;

--- 13 unchanged lines hidden (view full) ---

3425
3426 revert = B_FALSE;
3427
3428done:
3429 zonecfg_fini_handle(handle);
3430 release_lock_file(lockfd);
3431
3432 /*
3459 * Clean up the file-system based on how things went. We either
3433 * Clean up the file system based on how things went. We either
3460 * clean up the new zonepath if the operation failed for some reason
3461 * or we clean up the old zonepath if everything is ok.
3462 */
3463 if (revert) {
3464 /* The zonecfg update failed, cleanup the new zonepath. */
3434 * clean up the new zonepath if the operation failed for some reason
3435 * or we clean up the old zonepath if everything is ok.
3436 */
3437 if (revert) {
3438 /* The zonecfg update failed, cleanup the new zonepath. */
3465 if (fast) {
3439 if (is_zfs) {
3440 if (move_zfs(new_zonepath, zonepath) == Z_ERR) {
3441 (void) fprintf(stderr, gettext("could not "
3442 "restore zonepath, the zfs mountpoint is "
3443 "set as:\n%s\n"), new_zonepath);
3444 /*
3445 * err is already != Z_OK since we're reverting
3446 */
3447 }
3448
3449 } else if (fast) {
3466 if (rename(new_zonepath, zonepath) != 0) {
3467 zperror(gettext("could not restore zonepath"),
3468 B_FALSE);
3469 /*
3470 * err is already != Z_OK since we're reverting
3471 */
3472 }
3473 } else {
3474 (void) printf(gettext("Cleaning up zonepath %s..."),
3475 new_zonepath);
3476 (void) fflush(stdout);
3450 if (rename(new_zonepath, zonepath) != 0) {
3451 zperror(gettext("could not restore zonepath"),
3452 B_FALSE);
3453 /*
3454 * err is already != Z_OK since we're reverting
3455 */
3456 }
3457 } else {
3458 (void) printf(gettext("Cleaning up zonepath %s..."),
3459 new_zonepath);
3460 (void) fflush(stdout);
3477 err = remove_zonepath(new_zonepath);
3461 err = cleanup_zonepath(new_zonepath, B_TRUE);
3478 (void) printf("\n");
3479
3480 if (err != Z_OK) {
3481 errno = err;
3482 zperror(gettext("could not remove new "
3483 "zonepath"), B_TRUE);
3484 } else {
3485 /*
3486 * Because we're reverting we know the mainline
3487 * code failed but we just reused the err
3488 * variable so we reset it back to Z_ERR.
3489 */
3490 err = Z_ERR;
3491 }
3492 }
3493
3494 } else {
3495 /* The move was successful, cleanup the old zonepath. */
3462 (void) printf("\n");
3463
3464 if (err != Z_OK) {
3465 errno = err;
3466 zperror(gettext("could not remove new "
3467 "zonepath"), B_TRUE);
3468 } else {
3469 /*
3470 * Because we're reverting we know the mainline
3471 * code failed but we just reused the err
3472 * variable so we reset it back to Z_ERR.
3473 */
3474 err = Z_ERR;
3475 }
3476 }
3477
3478 } else {
3479 /* The move was successful, cleanup the old zonepath. */
3496 if (!fast) {
3480 if (!is_zfs && !fast) {
3497 (void) printf(
3498 gettext("Cleaning up zonepath %s..."), zonepath);
3499 (void) fflush(stdout);
3481 (void) printf(
3482 gettext("Cleaning up zonepath %s..."), zonepath);
3483 (void) fflush(stdout);
3500 err = remove_zonepath(zonepath);
3484 err = cleanup_zonepath(zonepath, B_TRUE);
3501 (void) printf("\n");
3502
3503 if (err != Z_OK) {
3504 errno = err;
3505 zperror(gettext("could not remove zonepath"),
3506 B_TRUE);
3507 }
3508 }

--- 35 unchanged lines hidden (view full) ---

3544 != Z_OK) {
3545 errno = err;
3546 zperror2(target_zone, gettext("could not get zone path"));
3547 return (Z_ERR);
3548 }
3549
3550 /* Don't detach the zone if anything is still mounted there */
3551 if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
3485 (void) printf("\n");
3486
3487 if (err != Z_OK) {
3488 errno = err;
3489 zperror(gettext("could not remove zonepath"),
3490 B_TRUE);
3491 }
3492 }

--- 35 unchanged lines hidden (view full) ---

3528 != Z_OK) {
3529 errno = err;
3530 zperror2(target_zone, gettext("could not get zone path"));
3531 return (Z_ERR);
3532 }
3533
3534 /* Don't detach the zone if anything is still mounted there */
3535 if (zonecfg_find_mounts(zonepath, NULL, NULL)) {
3552 zerror(gettext("These file-systems are mounted on "
3536 zerror(gettext("These file systems are mounted on "
3553 "subdirectories of %s.\n"), zonepath);
3554 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
3555 return (Z_ERR);
3556 }
3557
3558 if ((handle = zonecfg_init_handle()) == NULL) {
3559 zperror(cmd_to_str(CMD_DETACH), B_TRUE);
3560 return (Z_ERR);

--- 35 unchanged lines hidden (view full) ---

3596done:
3597 zonecfg_fini_handle(handle);
3598 release_lock_file(lockfd);
3599
3600 return ((err == Z_OK) ? Z_OK : Z_ERR);
3601}
3602
3603/*
3537 "subdirectories of %s.\n"), zonepath);
3538 (void) zonecfg_find_mounts(zonepath, zfm_print, NULL);
3539 return (Z_ERR);
3540 }
3541
3542 if ((handle = zonecfg_init_handle()) == NULL) {
3543 zperror(cmd_to_str(CMD_DETACH), B_TRUE);
3544 return (Z_ERR);

--- 35 unchanged lines hidden (view full) ---

3580done:
3581 zonecfg_fini_handle(handle);
3582 release_lock_file(lockfd);
3583
3584 return ((err == Z_OK) ? Z_OK : Z_ERR);
3585}
3586
3587/*
3604 * Find the specified package in the sw inventory on the handle and check
3605 * if the version matches what is passed in.
3606 * Return 0 if the packages match
3607 * 1 if the package is found but we have a version mismatch
3608 * -1 if the package is not found
3609 */
3610static int
3611pkg_cmp(zone_dochandle_t handle, char *pkg_name, char *pkg_vers,
3612 char *return_vers, int vers_size)
3613{
3614 int res = -1;
3615 struct zone_pkgtab pkgtab;
3616
3617 if (zonecfg_setpkgent(handle) != Z_OK) {
3618 (void) fprintf(stderr,
3619 gettext("unable to enumerate packages\n"));
3620 return (Z_ERR);
3621 }
3622
3623 while (zonecfg_getpkgent(handle, &pkgtab) == Z_OK) {
3624 if (strcmp(pkg_name, pkgtab.zone_pkg_name) != 0)
3625 continue;
3626
3627 if (strcmp(pkg_vers, pkgtab.zone_pkg_version) == 0) {
3628 res = 0;
3629 break;
3630 }
3631
3632 (void) strlcpy(return_vers, pkgtab.zone_pkg_version, vers_size);
3633 res = 1;
3634 break;
3635 }
3636
3637 (void) zonecfg_endpkgent(handle);
3638 return (res);
3639}
3640
3641/*
3642 * Used in software comparisons to check the packages between the two zone
3643 * handles. The packages have to match or we print a message telling the
3644 * user what is out of sync. The src_cmp flag tells us if the first handle
3645 * is the source machine global zone or not. This is used to enable the
3646 * right messages to be printed and also to enable extra version checking
3647 * that is not needed for the opposite comparison.
3648 */
3649static int
3650pkg_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2,
3651 boolean_t src_cmp)
3652{
3653 int err;
3654 int res = Z_OK;
3655 boolean_t do_header = B_TRUE;
3656 char other_vers[ZONE_PKG_VERSMAX];
3657 struct zone_pkgtab pkgtab;
3658
3659 if (zonecfg_setpkgent(handle1) != Z_OK) {
3660 (void) fprintf(stderr,
3661 gettext("unable to enumerate packages\n"));
3662 return (Z_ERR);
3663 }
3664
3665 while (zonecfg_getpkgent(handle1, &pkgtab) == Z_OK) {
3666 if ((err = pkg_cmp(handle2, pkgtab.zone_pkg_name,
3667 pkgtab.zone_pkg_version, other_vers, sizeof (other_vers)))
3668 != 0) {
3669 if (do_header && (err < 0 || src_cmp)) {
3670 /* LINTED E_SEC_PRINTF_VAR_FMT */
3671 (void) fprintf(stderr, header);
3672 do_header = B_FALSE;
3673 }
3674 if (err < 0) {
3675 (void) fprintf(stderr,
3676 (src_cmp == B_TRUE) ?
3677 gettext("\t%s: not installed\n\t\t(%s)\n") :
3678 gettext("\t%s (%s)\n"),
3679 pkgtab.zone_pkg_name,
3680 pkgtab.zone_pkg_version);
3681 res = Z_ERR;
3682 } else if (src_cmp) {
3683 (void) fprintf(stderr, gettext(
3684 "\t%s: version mismatch\n\t\t(%s)"
3685 "\n\t\t(%s)\n"),
3686 pkgtab.zone_pkg_name,
3687 pkgtab.zone_pkg_version, other_vers);
3688 res = Z_ERR;
3689 }
3690 }
3691 }
3692
3693 (void) zonecfg_endpkgent(handle1);
3694
3695 return (res);
3696}
3697
3698/*
3699 * Find the specified patch in the sw inventory on the handle and check
3700 * if the version matches what is passed in.
3701 * Return 0 if the patches match
3702 * 1 if the patches is found but we have a version mismatch
3703 * -1 if the patches is not found
3704 */
3705static int
3706patch_cmp(zone_dochandle_t handle, char *patch_id, char *patch_vers,
3707 char *return_vers, int vers_size)
3708{
3709 int res = -1;
3710 struct zone_patchtab patchtab;
3711
3712 if (zonecfg_setpatchent(handle) != Z_OK) {
3713 (void) fprintf(stderr,
3714 gettext("unable to enumerate patches\n"));
3715 return (Z_ERR);
3716 }
3717
3718 while (zonecfg_getpatchent(handle, &patchtab) == Z_OK) {
3719 char *p;
3720
3721 if ((p = strchr(patchtab.zone_patch_id, '-')) != NULL)
3722 *p++ = '\0';
3723 else
3724 p = "";
3725
3726 if (strcmp(patch_id, patchtab.zone_patch_id) != 0)
3727 continue;
3728
3729 if (strcmp(patch_vers, p) == 0) {
3730 res = 0;
3731 break;
3732 }
3733
3734 (void) strlcpy(return_vers, p, vers_size);
3735 /*
3736 * Keep checking. This handles the case where multiple
3737 * versions of the same patch is installed.
3738 */
3739 res = 1;
3740 }
3741
3742 (void) zonecfg_endpatchent(handle);
3743 return (res);
3744}
3745
3746/*
3747 * Used in software comparisons to check the patches between the two zone
3748 * handles. The patches have to match or we print a message telling the
3749 * user what is out of sync. The src_cmp flag tells us if the first handle
3750 * is the source machine global zone or not. This is used to enable the
3751 * right messages to be printed and also to enable extra version checking
3752 * that is not needed for the opposite comparison.
3753 */
3754static int
3755patch_check(char *header, zone_dochandle_t handle1, zone_dochandle_t handle2,
3756 boolean_t src_cmp)
3757{
3758 int err;
3759 int res = Z_OK;
3760 boolean_t do_header = B_TRUE;
3761 char other_vers[MAXNAMELEN];
3762 struct zone_patchtab patchtab;
3763
3764 if (zonecfg_setpatchent(handle1) != Z_OK) {
3765 (void) fprintf(stderr,
3766 gettext("unable to enumerate patches\n"));
3767 return (Z_ERR);
3768 }
3769
3770 while (zonecfg_getpatchent(handle1, &patchtab) == Z_OK) {
3771 char *patch_vers;
3772
3773 if ((patch_vers = strchr(patchtab.zone_patch_id, '-')) != NULL)
3774 *patch_vers++ = '\0';
3775 else
3776 patch_vers = "";
3777
3778 if ((err = patch_cmp(handle2, patchtab.zone_patch_id,
3779 patch_vers, other_vers, sizeof (other_vers))) != 0) {
3780 if (do_header && (err < 0 || src_cmp)) {
3781 /* LINTED E_SEC_PRINTF_VAR_FMT */
3782 (void) fprintf(stderr, header);
3783 do_header = B_FALSE;
3784 }
3785 if (err < 0) {
3786 (void) fprintf(stderr,
3787 (src_cmp == B_TRUE) ?
3788 gettext("\t%s: not installed\n") :
3789 gettext("\t%s\n"),
3790 patchtab.zone_patch_id);
3791 res = Z_ERR;
3792 } else if (src_cmp) {
3793 (void) fprintf(stderr,
3794 gettext("\t%s: version mismatch\n\t\t(%s) "
3795 "(%s)\n"), patchtab.zone_patch_id,
3796 patch_vers, other_vers);
3797 res = Z_ERR;
3798 }
3799 }
3800 }
3801
3802 (void) zonecfg_endpatchent(handle1);
3803
3804 return (res);
3805}
3806
3807/*
3808 * Compare the software on the local global zone and source system global
3809 * zone. Used when we are trying to attach a zone during migration.
3810 * l_handle is for the local system and s_handle is for the source system.
3811 * These have a snapshot of the appropriate packages and patches in the global
3812 * zone for the two machines.
3813 * The functions called here will print any messages that are needed to
3814 * inform the user about package or patch problems.
3815 */
3816static int
3817sw_cmp(zone_dochandle_t l_handle, zone_dochandle_t s_handle)
3818{
3819 char *hdr;
3820 int res = Z_OK;
3821
3822 /*
3823 * Check the source host for pkgs (and versions) that are not on the
3824 * local host.
3825 */
3826 hdr = gettext("These packages installed on the source system are "
3827 "inconsistent with this system:\n");
3828 if (pkg_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK)
3829 res = Z_ERR;
3830
3831 /*
3832 * Now check the local host for pkgs that were not on the source host.
3833 * We already handled version mismatches in the loop above.
3834 */
3835 hdr = gettext("These packages installed on this system were "
3836 "not installed on the source system:\n");
3837 if (pkg_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK)
3838 res = Z_ERR;
3839
3840 /*
3841 * Check the source host for patches that are not on the local host.
3842 */
3843 hdr = gettext("These patches installed on the source system are "
3844 "inconsistent with this system:\n");
3845 if (patch_check(hdr, s_handle, l_handle, B_TRUE) != Z_OK)
3846 res = Z_ERR;
3847
3848 /*
3849 * Check the local host for patches that were not on the source host.
3850 * We already handled version mismatches in the loop above.
3851 */
3852 hdr = gettext("These patches installed on this system were "
3853 "not installed on the source system:\n");
3854 if (patch_check(hdr, l_handle, s_handle, B_FALSE) != Z_OK)
3855 res = Z_ERR;
3856
3857 return (res);
3858}
3859
3860/*
3861 * During attach we go through and fix up the /dev entries for the zone
3862 * we are attaching. In order to regenerate /dev with the correct devices,
3863 * the old /dev will be removed, the zone readied (which generates a new
3864 * /dev) then halted, then we use the info from the manifest to update
3865 * the modes, owners, etc. on the new /dev.
3866 */
3867static int
3868dev_fix(zone_dochandle_t handle)

--- 156 unchanged lines hidden (view full) ---

4025 if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) {
4026 errno = err;
4027 zperror(gettext("getting the attach information failed"),
4028 B_TRUE);
4029 goto done;
4030 }
4031
4032 /* sw_cmp prints error msgs as necessary */
3588 * During attach we go through and fix up the /dev entries for the zone
3589 * we are attaching. In order to regenerate /dev with the correct devices,
3590 * the old /dev will be removed, the zone readied (which generates a new
3591 * /dev) then halted, then we use the info from the manifest to update
3592 * the modes, owners, etc. on the new /dev.
3593 */
3594static int
3595dev_fix(zone_dochandle_t handle)

--- 156 unchanged lines hidden (view full) ---

3752 if ((err = zonecfg_get_detach_info(handle, B_FALSE)) != Z_OK) {
3753 errno = err;
3754 zperror(gettext("getting the attach information failed"),
3755 B_TRUE);
3756 goto done;
3757 }
3758
3759 /* sw_cmp prints error msgs as necessary */
4033 if ((err = sw_cmp(handle, athandle)) != Z_OK)
3760 if ((err = sw_cmp(handle, athandle, SW_CMP_NONE)) != Z_OK)
4034 goto done;
4035
4036 if ((err = dev_fix(athandle)) != Z_OK)
4037 goto done;
4038
4039forced:
4040
4041 zonecfg_rm_detached(handle, force);

--- 35 unchanged lines hidden (view full) ---

4077 if (tolower(line[0]) == 'n')
4078 return (0);
4079 }
4080}
4081
4082static int
4083uninstall_func(int argc, char *argv[])
4084{
3761 goto done;
3762
3763 if ((err = dev_fix(athandle)) != Z_OK)
3764 goto done;
3765
3766forced:
3767
3768 zonecfg_rm_detached(handle, force);

--- 35 unchanged lines hidden (view full) ---

3804 if (tolower(line[0]) == 'n')
3805 return (0);
3806 }
3807}
3808
3809static int
3810uninstall_func(int argc, char *argv[])
3811{
4085 /* 6: "exec " and " " */
4086 char cmdbuf[sizeof (RMCOMMAND) + MAXPATHLEN + 6];
4087 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */
3812 char line[ZONENAME_MAX + 128]; /* Enough for "Are you sure ..." */
4088 char rootpath[MAXPATHLEN], devpath[MAXPATHLEN];
3813 char rootpath[MAXPATHLEN], zonepath[MAXPATHLEN];
4089 boolean_t force = B_FALSE;
4090 int lockfd, answer;
4091 int err, arg;
3814 boolean_t force = B_FALSE;
3815 int lockfd, answer;
3816 int err, arg;
4092 int status;
4093
4094 if (zonecfg_in_alt_root()) {
4095 zerror(gettext("cannot uninstall zone in alternate root"));
4096 return (Z_ERR);
4097 }
4098
4099 optind = 0;
4100 while ((arg = getopt(argc, argv, "?F")) != EOF) {

--- 26 unchanged lines hidden (view full) ---

4127 } else if (answer == -1) {
4128 zerror(gettext("Input not from terminal and -F "
4129 "not specified: %s not done."),
4130 cmd_to_str(CMD_UNINSTALL));
4131 return (Z_ERR);
4132 }
4133 }
4134
3817
3818 if (zonecfg_in_alt_root()) {
3819 zerror(gettext("cannot uninstall zone in alternate root"));
3820 return (Z_ERR);
3821 }
3822
3823 optind = 0;
3824 while ((arg = getopt(argc, argv, "?F")) != EOF) {

--- 26 unchanged lines hidden (view full) ---

3851 } else if (answer == -1) {
3852 zerror(gettext("Input not from terminal and -F "
3853 "not specified: %s not done."),
3854 cmd_to_str(CMD_UNINSTALL));
3855 return (Z_ERR);
3856 }
3857 }
3858
4135 if ((err = zone_get_zonepath(target_zone, devpath,
4136 sizeof (devpath))) != Z_OK) {
3859 if ((err = zone_get_zonepath(target_zone, zonepath,
3860 sizeof (zonepath))) != Z_OK) {
4137 errno = err;
4138 zperror2(target_zone, gettext("could not get zone path"));
4139 return (Z_ERR);
4140 }
3861 errno = err;
3862 zperror2(target_zone, gettext("could not get zone path"));
3863 return (Z_ERR);
3864 }
4141 (void) strlcat(devpath, "/dev", sizeof (devpath));
4142 if ((err = zone_get_rootpath(target_zone, rootpath,
4143 sizeof (rootpath))) != Z_OK) {
4144 errno = err;
4145 zperror2(target_zone, gettext("could not get root path"));
4146 return (Z_ERR);
4147 }
4148
4149 /*

--- 12 unchanged lines hidden (view full) ---

4162 zerror(gettext("another %s may have an operation in progress."),
4163 "zoneadm");
4164 return (Z_ERR);
4165 }
4166
4167 /* Don't uninstall the zone if anything is mounted there */
4168 err = zonecfg_find_mounts(rootpath, NULL, NULL);
4169 if (err) {
3865 if ((err = zone_get_rootpath(target_zone, rootpath,
3866 sizeof (rootpath))) != Z_OK) {
3867 errno = err;
3868 zperror2(target_zone, gettext("could not get root path"));
3869 return (Z_ERR);
3870 }
3871
3872 /*

--- 12 unchanged lines hidden (view full) ---

3885 zerror(gettext("another %s may have an operation in progress."),
3886 "zoneadm");
3887 return (Z_ERR);
3888 }
3889
3890 /* Don't uninstall the zone if anything is mounted there */
3891 err = zonecfg_find_mounts(rootpath, NULL, NULL);
3892 if (err) {
4170 zerror(gettext("These file-systems are mounted on "
3893 zerror(gettext("These file systems are mounted on "
4171 "subdirectories of %s.\n"), rootpath);
4172 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL);
4173 return (Z_ERR);
4174 }
4175
4176 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
4177 if (err != Z_OK) {
4178 errno = err;
4179 zperror2(target_zone, gettext("could not set state"));
4180 goto bad;
4181 }
4182
3894 "subdirectories of %s.\n"), rootpath);
3895 (void) zonecfg_find_mounts(rootpath, zfm_print, NULL);
3896 return (Z_ERR);
3897 }
3898
3899 err = zone_set_state(target_zone, ZONE_STATE_INCOMPLETE);
3900 if (err != Z_OK) {
3901 errno = err;
3902 zperror2(target_zone, gettext("could not set state"));
3903 goto bad;
3904 }
3905
4183 /*
4184 * "exec" the command so that the returned status is that of
4185 * RMCOMMAND and not the shell.
4186 */
4187 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
4188 devpath);
4189 status = do_subproc(cmdbuf);
4190 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK)
3906 if ((err = cleanup_zonepath(zonepath, B_FALSE)) != Z_OK) {
3907 errno = err;
3908 zperror2(target_zone, gettext("cleaning up zonepath failed"));
4191 goto bad;
3909 goto bad;
4192 (void) snprintf(cmdbuf, sizeof (cmdbuf), "exec " RMCOMMAND " %s",
4193 rootpath);
4194 status = do_subproc(cmdbuf);
4195 if ((err = subproc_status(RMCOMMAND, status)) != Z_OK)
4196 goto bad;
3910 }
3911
4197 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
4198 if (err != Z_OK) {
4199 errno = err;
4200 zperror2(target_zone, gettext("could not reset state"));
4201 }
4202bad:
4203 release_lock_file(lockfd);
4204 return (err);

--- 177 unchanged lines hidden ---
3912 err = zone_set_state(target_zone, ZONE_STATE_CONFIGURED);
3913 if (err != Z_OK) {
3914 errno = err;
3915 zperror2(target_zone, gettext("could not reset state"));
3916 }
3917bad:
3918 release_lock_file(lockfd);
3919 return (err);

--- 177 unchanged lines hidden ---