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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright 2014 Gary Mills
29 * zonecfg is a lex/yacc based command interpreter used to manage zone
30 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
31 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
32 * which takes resources and/or properties as arguments. See the block
33 * comments near the end of zonecfg_grammar.y for how the data structures
34 * which keep track of these resources and properties are built up.
36 * The resource/property data structures are inserted into a command
37 * structure (see zonecfg.h), which also keeps track of command names,
38 * miscellaneous arguments, and function handlers. The grammar selects
39 * the appropriate function handler, each of which takes a pointer to a
40 * command structure as its sole argument, and invokes it. The grammar
41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
42 * from read_input(), our main driving function. That in turn is called
43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
44 * of which is called from main() depending on how the program was invoked.
46 * The rest of this module consists of the various function handlers and
47 * their helper functions. Some of these functions, particularly the
48 * X_to_str() functions, which maps command, resource and property numbers
49 * to strings, are used quite liberally, as doing so results in a better
50 * program w/rt I18N, reducing the need for translation notes.
53 #include <sys/mntent.h>
54 #include <sys/varargs.h>
55 #include <sys/sysmacros.h>
56 #include <sys/secflags.h>
67 #include <arpa/inet.h>
76 #include <sys/brand.h>
78 #include <sys/systeminfo.h>
80 #include <libinetutil.h>
84 #include <libzonecfg.h>
87 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
88 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
91 #define PAGER "/usr/bin/more"
92 #define EXEC_PREFIX "exec "
93 #define EXEC_LEN (strlen(EXEC_PREFIX))
102 extern int yyparse(void);
103 extern int lex_lineno
;
105 #define MAX_LINE_LEN 1024
106 #define MAX_CMD_HIST 1024
107 #define MAX_CMD_LEN 1024
109 #define ONE_MB 1048576
112 * Each SHELP_ should be a simple string.
115 #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \
116 "add <property-name> <property-value>\n\t(resource scope)"
117 #define SHELP_CANCEL "cancel"
118 #define SHELP_CLEAR "clear <property-name>"
119 #define SHELP_COMMIT "commit"
120 #define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]"
121 #define SHELP_DELETE "delete [-F]"
122 #define SHELP_END "end"
123 #define SHELP_EXIT "exit [-F]"
124 #define SHELP_EXPORT "export [-f output-file]"
125 #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]"
126 #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]"
127 #define SHELP_REMOVE "remove [-F] <resource-type> " \
128 "[ <property-name>=<property-value> ]*\n" \
129 "\t(global scope)\n" \
130 "remove <property-name> <property-value>\n" \
132 #define SHELP_REVERT "revert [-F]"
133 #define SHELP_SELECT "select <resource-type> { <property-name>=" \
135 #define SHELP_SET "set <property-name>=<property-value>"
136 #define SHELP_VERIFY "verify"
138 static struct help helptab
[] = {
139 { CMD_ADD
, "add", HELP_RES_PROPS
, SHELP_ADD
, },
140 { CMD_CANCEL
, "cancel", 0, SHELP_CANCEL
, },
141 { CMD_CLEAR
, "clear", HELP_PROPS
, SHELP_CLEAR
, },
142 { CMD_COMMIT
, "commit", 0, SHELP_COMMIT
, },
143 { CMD_CREATE
, "create", 0, SHELP_CREATE
, },
144 { CMD_DELETE
, "delete", 0, SHELP_DELETE
, },
145 { CMD_END
, "end", 0, SHELP_END
, },
146 { CMD_EXIT
, "exit", 0, SHELP_EXIT
, },
147 { CMD_EXPORT
, "export", 0, SHELP_EXPORT
, },
148 { CMD_HELP
, "help", 0, SHELP_HELP
},
149 { CMD_INFO
, "info", HELP_RES_PROPS
, SHELP_INFO
, },
150 { CMD_REMOVE
, "remove", HELP_RES_PROPS
, SHELP_REMOVE
, },
151 { CMD_REVERT
, "revert", 0, SHELP_REVERT
, },
152 { CMD_SELECT
, "select", HELP_RES_PROPS
, SHELP_SELECT
, },
153 { CMD_SET
, "set", HELP_PROPS
, SHELP_SET
, },
154 { CMD_VERIFY
, "verify", 0, SHELP_VERIFY
, },
158 #define MAX_RT_STRLEN 16
160 /* These *must* match the order of the RT_ define's from zonecfg.h */
161 char *res_types
[] = {
195 /* These *must* match the order of the PT_ define's from zonecfg.h */
196 char *prop_types
[] = {
245 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
246 static char *prop_val_types
[] = {
253 * The various _cmds[] lists below are for command tab-completion.
257 * remove has a space afterwards because it has qualifiers; the other commands
258 * that have qualifiers (add, select, etc.) don't need a space here because
259 * they have their own _cmds[] lists below.
261 static const char *global_scope_cmds
[] = {
279 static const char *add_cmds
[] = {
290 "add security-flags",
294 static const char *clear_cmds
[] = {
299 "clear scheduling-class",
301 "clear " ALIAS_MAXLWPS
,
302 "clear " ALIAS_MAXSHMMEM
,
303 "clear " ALIAS_MAXSHMIDS
,
304 "clear " ALIAS_MAXMSGIDS
,
305 "clear " ALIAS_MAXSEMIDS
,
306 "clear " ALIAS_SHARES
,
307 "clear " ALIAS_MAXPROCS
,
311 static const char *remove_cmds
[] = {
318 "remove dedicated-cpu ",
319 "remove capped-cpu ",
320 "remove capped-memory ",
322 "remove security-flags",
326 static const char *select_cmds
[] = {
333 "select dedicated-cpu",
335 "select capped-memory",
337 "select security-flags",
341 static const char *set_cmds
[] = {
349 "set scheduling-class=",
351 "set " ALIAS_MAXLWPS
"=",
352 "set " ALIAS_MAXSHMMEM
"=",
353 "set " ALIAS_MAXSHMIDS
"=",
354 "set " ALIAS_MAXMSGIDS
"=",
355 "set " ALIAS_MAXSEMIDS
"=",
356 "set " ALIAS_SHARES
"=",
359 "set " ALIAS_MAXPROCS
"=",
363 static const char *info_cmds
[] = {
370 "info capped-memory",
371 "info dedicated-cpu",
373 "info security-flags",
381 "info scheduling-class",
384 "info max-shm-memory",
392 "info max-processes",
396 static const char *fs_res_scope_cmds
[] = {
412 static const char *net_res_scope_cmds
[] = {
424 static const char *device_res_scope_cmds
[] = {
434 static const char *attr_res_scope_cmds
[] = {
446 static const char *rctl_res_scope_cmds
[] = {
458 static const char *dataset_res_scope_cmds
[] = {
468 static const char *pset_res_scope_cmds
[] = {
480 static const char *pcap_res_scope_cmds
[] = {
490 static const char *mcap_res_scope_cmds
[] = {
505 static const char *admin_res_scope_cmds
[] = {
516 static const char *secflags_res_scope_cmds
[] = {
527 struct xif
*xif_next
;
528 char xif_name
[LIFNAMSIZ
];
529 boolean_t xif_has_address
;
530 boolean_t xif_has_defrouter
;
533 /* Global variables */
535 /* list of network interfaces specified for exclusive IP zone */
538 /* set early in main(), never modified thereafter, used all over the place */
539 static char *execname
;
541 /* set in main(), used all over the place */
542 static zone_dochandle_t handle
;
544 /* used all over the place */
545 static char zone
[ZONENAME_MAX
];
546 static char revert_zone
[ZONENAME_MAX
];
548 /* global brand operations */
549 static brand_handle_t brand
;
551 /* set in modifying functions, checked in read_input() */
552 static boolean_t need_to_commit
= B_FALSE
;
555 /* set in yacc parser, checked in read_input() */
556 boolean_t newline_terminated
;
558 /* set in main(), checked in lex error handler */
559 boolean_t cmd_file_mode
;
561 /* set in exit_func(), checked in read_input() */
562 static boolean_t time_to_exit
= B_FALSE
, force_exit
= B_FALSE
;
564 /* used in short_usage() and zerr() */
565 static char *cmd_file_name
= NULL
;
567 /* checked in read_input() and other places */
568 static boolean_t ok_to_prompt
= B_FALSE
;
570 /* set and checked in initialize() */
571 static boolean_t got_handle
= B_FALSE
;
573 /* initialized in do_interactive(), checked in initialize() */
574 static boolean_t interactive_mode
;
576 /* set if configuring the global zone */
577 static boolean_t global_zone
= B_FALSE
;
579 /* set in main(), checked in multiple places */
580 static boolean_t read_only_mode
;
582 /* scope is outer/global or inner/resource */
583 static boolean_t global_scope
= B_TRUE
;
584 static int resource_scope
; /* should be in the RT_ list from zonecfg.h */
585 static int end_op
= -1; /* operation on end is either add or modify */
587 int num_prop_vals
; /* for grammar */
590 * These are for keeping track of resources as they are specified as part of
591 * the multi-step process. They should be initialized by add_resource() or
592 * select_func() and filled in by add_property() or set_func().
594 static struct zone_fstab old_fstab
, in_progress_fstab
;
595 static struct zone_nwiftab old_nwiftab
, in_progress_nwiftab
;
596 static struct zone_devtab old_devtab
, in_progress_devtab
;
597 static struct zone_rctltab old_rctltab
, in_progress_rctltab
;
598 static struct zone_attrtab old_attrtab
, in_progress_attrtab
;
599 static struct zone_dstab old_dstab
, in_progress_dstab
;
600 static struct zone_psettab old_psettab
, in_progress_psettab
;
601 static struct zone_mcaptab old_mcaptab
, in_progress_mcaptab
;
602 static struct zone_admintab old_admintab
, in_progress_admintab
;
603 static struct zone_secflagstab old_secflagstab
, in_progress_secflagstab
;
605 static GetLine
*gl
; /* The gl_get_line() resource object */
607 static void bytes_to_units(char *str
, char *buf
, int bufsize
);
609 /* Functions begin here */
612 initial_match(const char *line1
, const char *line2
, int word_end
)
616 return (strncmp(line1
, line2
, word_end
) == 0);
620 add_stuff(WordCompletion
*cpl
, const char *line1
, const char **list
,
625 for (i
= 0; list
[i
] != NULL
; i
++) {
626 if (initial_match(line1
, list
[i
], word_end
)) {
627 err
= cpl_add_completion(cpl
, line1
, 0, word_end
,
628 list
[i
] + word_end
, "", "");
638 CPL_MATCH_FN(cmd_cpl_fn
)
642 * The MAX/MIN tests below are to make sure we have at least
643 * enough characters to distinguish from other prefixes (MAX)
644 * but only check MIN(what we have, what we're checking).
646 if (strncmp(line
, "add ", MAX(MIN(word_end
, 4), 1)) == 0)
647 return (add_stuff(cpl
, line
, add_cmds
, word_end
));
648 if (strncmp(line
, "clear ", MAX(MIN(word_end
, 6), 2)) == 0)
649 return (add_stuff(cpl
, line
, clear_cmds
, word_end
));
650 if (strncmp(line
, "select ", MAX(MIN(word_end
, 7), 3)) == 0)
651 return (add_stuff(cpl
, line
, select_cmds
, word_end
));
652 if (strncmp(line
, "set ", MAX(MIN(word_end
, 4), 3)) == 0)
653 return (add_stuff(cpl
, line
, set_cmds
, word_end
));
654 if (strncmp(line
, "remove ", MAX(MIN(word_end
, 7), 1)) == 0)
655 return (add_stuff(cpl
, line
, remove_cmds
, word_end
));
656 if (strncmp(line
, "info ", MAX(MIN(word_end
, 5), 1)) == 0)
657 return (add_stuff(cpl
, line
, info_cmds
, word_end
));
658 return (add_stuff(cpl
, line
, global_scope_cmds
, word_end
));
660 switch (resource_scope
) {
662 return (add_stuff(cpl
, line
, fs_res_scope_cmds
, word_end
));
664 return (add_stuff(cpl
, line
, net_res_scope_cmds
, word_end
));
666 return (add_stuff(cpl
, line
, device_res_scope_cmds
, word_end
));
668 return (add_stuff(cpl
, line
, rctl_res_scope_cmds
, word_end
));
670 return (add_stuff(cpl
, line
, attr_res_scope_cmds
, word_end
));
672 return (add_stuff(cpl
, line
, dataset_res_scope_cmds
, word_end
));
674 return (add_stuff(cpl
, line
, pset_res_scope_cmds
, word_end
));
676 return (add_stuff(cpl
, line
, pcap_res_scope_cmds
, word_end
));
678 return (add_stuff(cpl
, line
, mcap_res_scope_cmds
, word_end
));
680 return (add_stuff(cpl
, line
, admin_res_scope_cmds
, word_end
));
682 return (add_stuff(cpl
, line
, secflags_res_scope_cmds
,
690 * For the main CMD_func() functions below, several of them call getopt()
691 * then check optind against argc to make sure an extra parameter was not
692 * passed in. The reason this is not caught in the grammar is that the
693 * grammar just checks for a miscellaneous TOKEN, which is *expected* to
694 * be "-F" (for example), but could be anything. So (for example) this
695 * check will prevent "create bogus".
701 return (calloc(1, sizeof (cmd_t
)));
709 for (i
= 0; i
< MAX_EQ_PROP_PAIRS
; i
++)
710 if (cmd
->cmd_property_ptr
[i
] != NULL
) {
711 property_value_ptr_t pp
= cmd
->cmd_property_ptr
[i
];
713 switch (pp
->pv_type
) {
714 case PROP_VAL_SIMPLE
:
717 case PROP_VAL_COMPLEX
:
718 free_complex(pp
->pv_complex
);
721 free_list(pp
->pv_list
);
725 for (i
= 0; i
< cmd
->cmd_argc
; i
++)
726 free(cmd
->cmd_argv
[i
]);
730 complex_property_ptr_t
733 return (calloc(1, sizeof (complex_property_t
)));
737 free_complex(complex_property_ptr_t
complex)
741 free_complex(complex->cp_next
);
742 free(complex->cp_value
);
749 return (calloc(1, sizeof (list_property_t
)));
753 free_list(list_property_ptr_t list
)
757 free(list
->lp_simple
);
758 free_complex(list
->lp_complex
);
759 free_list(list
->lp_next
);
764 free_outer_list(list_property_ptr_t list
)
768 free_outer_list(list
->lp_next
);
772 static struct zone_rctlvaltab
*
773 alloc_rctlvaltab(void)
775 return (calloc(1, sizeof (struct zone_rctlvaltab
)));
779 rt_to_str(int res_type
)
781 assert(res_type
>= RT_MIN
&& res_type
<= RT_MAX
);
782 return (res_types
[res_type
]);
786 pt_to_str(int prop_type
)
788 assert(prop_type
>= PT_MIN
&& prop_type
<= PT_MAX
);
789 return (prop_types
[prop_type
]);
793 pvt_to_str(int pv_type
)
795 assert(pv_type
>= PROP_VAL_MIN
&& pv_type
<= PROP_VAL_MAX
);
796 return (prop_val_types
[pv_type
]);
800 cmd_to_str(int cmd_num
)
802 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
803 return (helptab
[cmd_num
].cmd_name
);
808 zerr(const char *fmt
, ...)
811 static int last_lineno
;
813 /* lex_lineno has already been incremented in the lexer; compensate */
814 if (cmd_file_mode
&& lex_lineno
> last_lineno
) {
815 if (strcmp(cmd_file_name
, "-") == 0)
816 (void) fprintf(stderr
, gettext("On line %d:\n"),
819 (void) fprintf(stderr
, gettext("On line %d of %s:\n"),
820 lex_lineno
- 1, cmd_file_name
);
821 last_lineno
= lex_lineno
;
823 va_start(alist
, fmt
);
824 (void) vfprintf(stderr
, fmt
, alist
);
825 (void) fprintf(stderr
, "\n");
830 * This is a separate function rather than a set of define's because of the
831 * gettext() wrapping.
836 * Each string below should have \t follow \n whenever needed; the
837 * initial \t and the terminal \n will be provided by the calling function.
841 long_help(int cmd_num
)
843 static char line
[1024]; /* arbitrary large amount */
845 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
848 return (gettext("Prints help message."));
850 (void) snprintf(line
, sizeof (line
),
851 gettext("Creates a configuration for the "
852 "specified zone. %s should be\n\tused to "
853 "begin configuring a new zone. If overwriting an "
854 "existing\n\tconfiguration, the -F flag can be "
855 "used to force the action. If\n\t-t template is "
856 "given, creates a configuration identical to the\n"
857 "\tspecified template, except that the zone name "
858 "is changed from\n\ttemplate to zonename. '%s -a' "
859 "creates a configuration from a\n\tdetached "
860 "zonepath. '%s -b' results in a blank "
861 "configuration.\n\t'%s' with no arguments applies "
862 "the Sun default settings."),
863 cmd_to_str(CMD_CREATE
), cmd_to_str(CMD_CREATE
),
864 cmd_to_str(CMD_CREATE
), cmd_to_str(CMD_CREATE
));
867 return (gettext("Exits the program. The -F flag can "
868 "be used to force the action."));
870 return (gettext("Prints configuration to standard "
871 "output, or to output-file if\n\tspecified, in "
872 "a form suitable for use in a command-file."));
874 return (gettext("Add specified resource to "
877 return (gettext("Deletes the specified zone. The -F "
878 "flag can be used to force the\n\taction."));
880 return (gettext("Remove specified resource from "
881 "configuration. The -F flag can be used\n\tto "
882 "force the action."));
884 (void) snprintf(line
, sizeof (line
),
885 gettext("Selects a resource to modify. "
886 "Resource modification is completed\n\twith the "
887 "command \"%s\". The property name/value pairs "
888 "must uniquely\n\tidentify a resource. Note that "
889 "the curly braces ('{', '}') mean one\n\tor more "
890 "of whatever is between them."),
891 cmd_to_str(CMD_END
));
894 return (gettext("Sets property values."));
896 return (gettext("Clears property values."));
898 return (gettext("Displays information about the "
899 "current configuration. If resource\n\ttype is "
900 "specified, displays only information about "
901 "resources of\n\tthe relevant type. If resource "
902 "id is specified, displays only\n\tinformation "
903 "about that resource."));
905 return (gettext("Verifies current configuration "
906 "for correctness (some resource types\n\thave "
907 "required properties)."));
909 (void) snprintf(line
, sizeof (line
),
910 gettext("Commits current configuration. "
911 "Configuration must be committed to\n\tbe used by "
912 "%s. Until the configuration is committed, "
913 "changes \n\tcan be removed with the %s "
914 "command. This operation is\n\tattempted "
915 "automatically upon completion of a %s "
916 "session."), "zoneadm", cmd_to_str(CMD_REVERT
),
920 return (gettext("Reverts configuration back to the "
921 "last committed state. The -F flag\n\tcan be "
922 "used to force the action."));
924 return (gettext("Cancels resource/property "
927 return (gettext("Ends resource/property "
935 * Return the input filename appended to each component of the path
936 * or the filename itself if it is absolute.
937 * Parameters: path string, file name, output string.
940 exec_cat(const char *s1
, const char *s2
, char *si
)
943 /* Number of remaining characters in s */
944 int cnt
= PATH_MAX
+ 1;
947 while (*s1
&& *s1
!= ':') { /* Copy first component of path to si */
955 if (si
!= s
&& cnt
> 0) { /* Add slash if s2 is not absolute */
959 while (*s2
&& cnt
> 0) { /* Copy s2 to si */
963 *s
= '\0'; /* Terminate the output string */
964 return (*s1
? ++s1
: NULL
); /* Return next path component or NULL */
967 /* Determine that a name exists in PATH */
969 path_find(const char *name
)
972 char fname
[PATH_MAX
+ 2];
974 struct stat stat_buf
;
976 if ((pathstr
= getenv("PATH")) == NULL
) {
977 if (geteuid() == 0 || getuid() == 0)
978 pathstr
= "/usr/sbin:/usr/bin";
980 pathstr
= "/usr/bin:";
982 cp
= strchr(name
, '/') ? (const char *) "" : pathstr
;
985 cp
= exec_cat(cp
, name
, fname
);
986 if (stat(fname
, &stat_buf
) != -1) {
987 /* successful find of the file */
990 } while (cp
!= NULL
);
1001 pager
= getenv("PAGER");
1002 if (pager
== NULL
|| *pager
== '\0')
1005 space
= strchr(pager
, ' ');
1008 if (path_find(pager
) == 0) {
1011 if ((newfp
= popen(pager
, "w")) == NULL
)
1012 zerr(gettext("PAGER open failed (%s)."),
1016 zerr(gettext("PAGER %s does not exist (%s)."),
1017 pager
, strerror(errno
));
1023 pager_close(FILE *fp
)
1027 status
= pclose(fp
);
1029 zerr(gettext("PAGER close failed (%s)."),
1034 * Called with verbose TRUE when help is explicitly requested, FALSE for
1035 * unexpected errors.
1039 usage(boolean_t verbose
, uint_t flags
)
1041 FILE *fp
= verbose
? stdout
: stderr
;
1043 boolean_t need_to_close
= B_FALSE
;
1046 /* don't page error output */
1047 if (verbose
&& interactive_mode
) {
1048 if ((newfp
= pager_open()) != NULL
) {
1049 need_to_close
= B_TRUE
;
1054 if (flags
& HELP_META
) {
1055 (void) fprintf(fp
, gettext("More help is available for the "
1057 (void) fprintf(fp
, "\n\tcommands ('%s commands')\n",
1058 cmd_to_str(CMD_HELP
));
1059 (void) fprintf(fp
, "\tsyntax ('%s syntax')\n",
1060 cmd_to_str(CMD_HELP
));
1061 (void) fprintf(fp
, "\tusage ('%s usage')\n\n",
1062 cmd_to_str(CMD_HELP
));
1063 (void) fprintf(fp
, gettext("You may also obtain help on any "
1064 "command by typing '%s <command-name>.'\n"),
1065 cmd_to_str(CMD_HELP
));
1067 if (flags
& HELP_RES_SCOPE
) {
1068 switch (resource_scope
) {
1070 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1071 "used to configure a file-system.\n"),
1072 rt_to_str(resource_scope
));
1073 (void) fprintf(fp
, gettext("Valid commands:\n"));
1074 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1075 pt_to_str(PT_DIR
), gettext("<path>"));
1076 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1077 pt_to_str(PT_SPECIAL
), gettext("<path>"));
1078 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1079 pt_to_str(PT_RAW
), gettext("<raw-device>"));
1080 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1081 pt_to_str(PT_TYPE
), gettext("<file-system type>"));
1082 (void) fprintf(fp
, "\t%s %s %s\n", cmd_to_str(CMD_ADD
),
1083 pt_to_str(PT_OPTIONS
),
1084 gettext("<file-system options>"));
1085 (void) fprintf(fp
, "\t%s %s %s\n",
1086 cmd_to_str(CMD_REMOVE
), pt_to_str(PT_OPTIONS
),
1087 gettext("<file-system options>"));
1088 (void) fprintf(fp
, gettext("Consult the file-system "
1089 "specific manual page, such as mount_ufs(1M), "
1090 "for\ndetails about file-system options. Note "
1091 "that any file-system options with an\nembedded "
1092 "'=' character must be enclosed in double quotes, "
1094 "such as \"%s=5\".\n"), MNTOPT_RETRY
);
1097 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1098 "used to configure a network interface.\n"),
1099 rt_to_str(resource_scope
));
1100 (void) fprintf(fp
, gettext("Valid commands:\n"));
1101 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1102 pt_to_str(PT_ADDRESS
), gettext("<IP-address>"));
1103 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1104 pt_to_str(PT_ALLOWED_ADDRESS
),
1105 gettext("<IP-address>"));
1106 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1107 pt_to_str(PT_PHYSICAL
), gettext("<interface>"));
1108 (void) fprintf(fp
, gettext("See ifconfig(1M) for "
1109 "details of the <interface> string.\n"));
1110 (void) fprintf(fp
, gettext("%s %s is valid "
1111 "if the %s property is set to %s, otherwise it "
1112 "must not be set.\n"),
1113 cmd_to_str(CMD_SET
), pt_to_str(PT_ADDRESS
),
1114 pt_to_str(PT_IPTYPE
), gettext("shared"));
1115 (void) fprintf(fp
, gettext("%s %s is valid "
1116 "if the %s property is set to %s, otherwise it "
1117 "must not be set.\n"),
1118 cmd_to_str(CMD_SET
), pt_to_str(PT_ALLOWED_ADDRESS
),
1119 pt_to_str(PT_IPTYPE
), gettext("exclusive"));
1120 (void) fprintf(fp
, gettext("\t%s %s=%s\n%s %s "
1121 "is valid if the %s or %s property is set, "
1122 "otherwise it must not be set\n"),
1123 cmd_to_str(CMD_SET
),
1124 pt_to_str(PT_DEFROUTER
), gettext("<IP-address>"),
1125 cmd_to_str(CMD_SET
), pt_to_str(PT_DEFROUTER
),
1126 gettext(pt_to_str(PT_ADDRESS
)),
1127 gettext(pt_to_str(PT_ALLOWED_ADDRESS
)));
1130 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1131 "used to configure a device node.\n"),
1132 rt_to_str(resource_scope
));
1133 (void) fprintf(fp
, gettext("Valid commands:\n"));
1134 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1135 pt_to_str(PT_MATCH
), gettext("<device-path>"));
1138 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1139 "used to configure a resource control.\n"),
1140 rt_to_str(resource_scope
));
1141 (void) fprintf(fp
, gettext("Valid commands:\n"));
1142 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1143 pt_to_str(PT_NAME
), gettext("<string>"));
1144 (void) fprintf(fp
, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1145 cmd_to_str(CMD_ADD
), pt_to_str(PT_VALUE
),
1146 pt_to_str(PT_PRIV
), gettext("<priv-value>"),
1147 pt_to_str(PT_LIMIT
), gettext("<number>"),
1148 pt_to_str(PT_ACTION
), gettext("<action-value>"));
1149 (void) fprintf(fp
, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1150 cmd_to_str(CMD_REMOVE
), pt_to_str(PT_VALUE
),
1151 pt_to_str(PT_PRIV
), gettext("<priv-value>"),
1152 pt_to_str(PT_LIMIT
), gettext("<number>"),
1153 pt_to_str(PT_ACTION
), gettext("<action-value>"));
1154 (void) fprintf(fp
, "%s\n\t%s := privileged\n"
1155 "\t%s := none | deny\n", gettext("Where"),
1156 gettext("<priv-value>"), gettext("<action-value>"));
1159 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1160 "used to configure a generic attribute.\n"),
1161 rt_to_str(resource_scope
));
1162 (void) fprintf(fp
, gettext("Valid commands:\n"));
1163 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1164 pt_to_str(PT_NAME
), gettext("<name>"));
1165 (void) fprintf(fp
, "\t%s %s=boolean\n",
1166 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1167 (void) fprintf(fp
, "\t%s %s=true | false\n",
1168 cmd_to_str(CMD_SET
), pt_to_str(PT_VALUE
));
1169 (void) fprintf(fp
, gettext("or\n"));
1170 (void) fprintf(fp
, "\t%s %s=int\n", cmd_to_str(CMD_SET
),
1171 pt_to_str(PT_TYPE
));
1172 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1173 pt_to_str(PT_VALUE
), gettext("<integer>"));
1174 (void) fprintf(fp
, gettext("or\n"));
1175 (void) fprintf(fp
, "\t%s %s=string\n",
1176 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1177 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1178 pt_to_str(PT_VALUE
), gettext("<string>"));
1179 (void) fprintf(fp
, gettext("or\n"));
1180 (void) fprintf(fp
, "\t%s %s=uint\n",
1181 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1182 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1183 pt_to_str(PT_VALUE
), gettext("<unsigned integer>"));
1186 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1187 "used to export ZFS datasets.\n"),
1188 rt_to_str(resource_scope
));
1189 (void) fprintf(fp
, gettext("Valid commands:\n"));
1190 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1191 pt_to_str(PT_NAME
), gettext("<name>"));
1194 (void) fprintf(fp
, gettext("The '%s' resource scope "
1195 "configures the 'pools' facility to dedicate\na "
1196 "subset of the system's processors to this zone "
1197 "while it is running.\n"),
1198 rt_to_str(resource_scope
));
1199 (void) fprintf(fp
, gettext("Valid commands:\n"));
1200 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1201 pt_to_str(PT_NCPUS
),
1202 gettext("<unsigned integer | range>"));
1203 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1204 pt_to_str(PT_IMPORTANCE
),
1205 gettext("<unsigned integer>"));
1208 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1209 "used to set an upper limit (a cap) on the\n"
1210 "percentage of CPU that can be used by this zone. "
1211 "A '%s' value of 1\ncorresponds to one cpu. The "
1212 "value can be set higher than 1, up to the total\n"
1213 "number of CPUs on the system. The value can "
1214 "also be less than 1,\nrepresenting a fraction of "
1216 rt_to_str(resource_scope
), pt_to_str(PT_NCPUS
));
1217 (void) fprintf(fp
, gettext("Valid commands:\n"));
1218 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1219 pt_to_str(PT_NCPUS
), gettext("<unsigned decimal>"));
1222 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1223 "used to set an upper limit (a cap) on the\n"
1224 "amount of physical memory, swap space and locked "
1225 "memory that can be used by\nthis zone.\n"),
1226 rt_to_str(resource_scope
));
1227 (void) fprintf(fp
, gettext("Valid commands:\n"));
1228 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1229 pt_to_str(PT_PHYSICAL
),
1230 gettext("<qualified unsigned decimal>"));
1231 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1233 gettext("<qualified unsigned decimal>"));
1234 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1235 pt_to_str(PT_LOCKED
),
1236 gettext("<qualified unsigned decimal>"));
1239 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1240 "used to delegate specific zone management\n"
1241 "rights to users and roles. These rights are "
1242 "only applicable to this zone.\n"),
1243 rt_to_str(resource_scope
));
1244 (void) fprintf(fp
, gettext("Valid commands:\n"));
1245 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1247 gettext("<single user or role name>"));
1248 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1249 pt_to_str(PT_AUTHS
),
1250 gettext("<comma separated list>"));
1253 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1254 "used to specify the default security-flags\n"
1255 "of this zone, and their upper and lower bound.\n"),
1256 rt_to_str(resource_scope
));
1257 (void) fprintf(fp
, "\t%s %s=%s\n",
1258 cmd_to_str(CMD_SET
), pt_to_str(PT_DEFAULT
),
1259 gettext("<security flags>"));
1260 (void) fprintf(fp
, "\t%s %s=%s\n",
1261 cmd_to_str(CMD_SET
), pt_to_str(PT_LOWER
),
1262 gettext("<security flags>"));
1263 (void) fprintf(fp
, "\t%s %s=%s\n",
1264 cmd_to_str(CMD_SET
), pt_to_str(PT_UPPER
),
1265 gettext("<security flags>"));
1268 (void) fprintf(fp
, gettext("And from any resource scope, you "
1270 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_END
),
1271 gettext("(to conclude this operation)"));
1272 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL
),
1273 gettext("(to cancel this operation)"));
1274 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_EXIT
),
1275 gettext("(to exit the zonecfg utility)"));
1277 if (flags
& HELP_USAGE
) {
1278 (void) fprintf(fp
, "%s:\t%s %s\n", gettext("usage"),
1279 execname
, cmd_to_str(CMD_HELP
));
1280 (void) fprintf(fp
, "\t%s -z <zone>\t\t\t(%s)\n",
1281 execname
, gettext("interactive"));
1282 (void) fprintf(fp
, "\t%s -z <zone> <command>\n", execname
);
1283 (void) fprintf(fp
, "\t%s -z <zone> -f <command-file>\n",
1286 if (flags
& HELP_SUBCMDS
) {
1287 (void) fprintf(fp
, "%s:\n\n", gettext("Commands"));
1288 for (i
= 0; i
<= CMD_MAX
; i
++) {
1289 (void) fprintf(fp
, "%s\n", helptab
[i
].short_usage
);
1291 (void) fprintf(fp
, "\t%s\n\n", long_help(i
));
1294 if (flags
& HELP_SYNTAX
) {
1296 (void) fprintf(fp
, "\n");
1297 (void) fprintf(fp
, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1298 (void) fprintf(fp
, gettext("\t(except the reserved words "
1299 "'%s' and anything starting with '%s')\n"), "global",
1302 gettext("\tName must be less than %d characters.\n"),
1305 (void) fprintf(fp
, "\n");
1307 if (flags
& HELP_NETADDR
) {
1308 (void) fprintf(fp
, gettext("\n<net-addr> :="));
1310 gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
1312 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1314 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1315 (void) fprintf(fp
, gettext("See inet(3SOCKET) for IPv4 and "
1316 "IPv6 address syntax.\n"));
1317 (void) fprintf(fp
, gettext("<IPv4-prefix-length> := [0-32]\n"));
1319 gettext("<IPv6-prefix-length> := [0-128]\n"));
1321 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1323 if (flags
& HELP_RESOURCES
) {
1324 (void) fprintf(fp
, "<%s> := %s | %s | %s | %s | %s |\n\t"
1325 "%s | %s | %s | %s | %s\n\n",
1326 gettext("resource type"), rt_to_str(RT_FS
),
1327 rt_to_str(RT_NET
), rt_to_str(RT_DEVICE
),
1328 rt_to_str(RT_RCTL
), rt_to_str(RT_ATTR
),
1329 rt_to_str(RT_DATASET
), rt_to_str(RT_DCPU
),
1330 rt_to_str(RT_PCAP
), rt_to_str(RT_MCAP
),
1331 rt_to_str(RT_ADMIN
), rt_to_str(RT_SECFLAGS
));
1333 if (flags
& HELP_PROPS
) {
1334 (void) fprintf(fp
, gettext("For resource type ... there are "
1335 "property types ...:\n"));
1336 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1337 pt_to_str(PT_ZONENAME
));
1338 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1339 pt_to_str(PT_ZONEPATH
));
1340 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1341 pt_to_str(PT_BRAND
));
1342 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1343 pt_to_str(PT_AUTOBOOT
));
1344 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1345 pt_to_str(PT_BOOTARGS
));
1346 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1347 pt_to_str(PT_POOL
));
1348 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1349 pt_to_str(PT_LIMITPRIV
));
1350 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1351 pt_to_str(PT_SCHED
));
1352 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1353 pt_to_str(PT_IPTYPE
));
1354 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1355 pt_to_str(PT_HOSTID
));
1356 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1357 pt_to_str(PT_FS_ALLOWED
));
1358 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1359 pt_to_str(PT_MAXLWPS
));
1360 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1361 pt_to_str(PT_MAXPROCS
));
1362 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1363 pt_to_str(PT_MAXSHMMEM
));
1364 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1365 pt_to_str(PT_MAXSHMIDS
));
1366 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1367 pt_to_str(PT_MAXMSGIDS
));
1368 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1369 pt_to_str(PT_MAXSEMIDS
));
1370 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1371 pt_to_str(PT_SHARES
));
1372 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s, %s, %s\n",
1373 rt_to_str(RT_FS
), pt_to_str(PT_DIR
),
1374 pt_to_str(PT_SPECIAL
), pt_to_str(PT_RAW
),
1375 pt_to_str(PT_TYPE
), pt_to_str(PT_OPTIONS
));
1376 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET
),
1377 pt_to_str(PT_ADDRESS
), pt_to_str(PT_ALLOWED_ADDRESS
),
1378 pt_to_str(PT_PHYSICAL
), pt_to_str(PT_DEFROUTER
));
1379 (void) fprintf(fp
, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE
),
1380 pt_to_str(PT_MATCH
));
1381 (void) fprintf(fp
, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL
),
1382 pt_to_str(PT_NAME
), pt_to_str(PT_VALUE
));
1383 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR
),
1384 pt_to_str(PT_NAME
), pt_to_str(PT_TYPE
),
1385 pt_to_str(PT_VALUE
));
1386 (void) fprintf(fp
, "\t%s\t\t%s\n", rt_to_str(RT_DATASET
),
1387 pt_to_str(PT_NAME
));
1388 (void) fprintf(fp
, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU
),
1389 pt_to_str(PT_NCPUS
), pt_to_str(PT_IMPORTANCE
));
1390 (void) fprintf(fp
, "\t%s\t%s\n", rt_to_str(RT_PCAP
),
1391 pt_to_str(PT_NCPUS
));
1392 (void) fprintf(fp
, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP
),
1393 pt_to_str(PT_PHYSICAL
), pt_to_str(PT_SWAP
),
1394 pt_to_str(PT_LOCKED
));
1395 (void) fprintf(fp
, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN
),
1396 pt_to_str(PT_USER
), pt_to_str(PT_AUTHS
));
1397 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s\n",
1398 rt_to_str(RT_SECFLAGS
), pt_to_str(PT_DEFAULT
),
1399 pt_to_str(PT_LOWER
), pt_to_str(PT_UPPER
));
1402 (void) pager_close(fp
);
1406 zone_perror(char *prefix
, int err
, boolean_t set_saw
)
1408 zerr("%s: %s", prefix
, zonecfg_strerror(err
));
1414 * zone_perror() expects a single string, but for remove and select
1415 * we have both the command and the resource type, so this wrapper
1416 * function serves the same purpose in a slightly different way.
1420 z_cmd_rt_perror(int cmd_num
, int res_num
, int err
, boolean_t set_saw
)
1422 zerr("%s %s: %s", cmd_to_str(cmd_num
), rt_to_str(res_num
),
1423 zonecfg_strerror(err
));
1428 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
1430 initialize(boolean_t handle_expected
)
1433 char brandname
[MAXNAMELEN
];
1435 if (zonecfg_check_handle(handle
) != Z_OK
) {
1436 if ((err
= zonecfg_get_handle(zone
, handle
)) == Z_OK
) {
1437 got_handle
= B_TRUE
;
1438 if (zonecfg_get_brand(handle
, brandname
,
1439 sizeof (brandname
)) != Z_OK
) {
1440 zerr("Zone %s is inconsistent: missing "
1441 "brand attribute", zone
);
1444 if ((brand
= brand_open(brandname
)) == NULL
) {
1445 zerr("Zone %s uses non-existent brand \"%s\"."
1446 " Unable to continue", zone
, brandname
);
1450 * If the user_attr file is newer than
1451 * the zone config file, the admins
1452 * may need to be updated since the
1453 * RBAC files are authoritative for
1454 * authorization checks.
1456 err
= zonecfg_update_userauths(handle
, zone
);
1458 zerr(gettext("The administrative rights "
1459 "were updated to match "
1460 "the current RBAC configuration.\n"
1461 "Use \"info admin\" and \"revert\" to "
1462 "compare with the previous settings."));
1463 need_to_commit
= B_TRUE
;
1464 } else if (err
!= Z_NO_ENTRY
) {
1465 zerr(gettext("failed to update "
1468 } else if (need_to_commit
) {
1469 zerr(gettext("admin rights were updated "
1470 "to match RBAC configuration."));
1473 } else if (global_zone
&& err
== Z_NO_ZONE
&& !got_handle
&&
1476 * We implicitly create the global zone config if it
1479 zone_dochandle_t tmphandle
;
1481 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1482 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1486 err
= zonecfg_get_template_handle("SUNWblank", zone
,
1490 zonecfg_fini_handle(tmphandle
);
1491 zone_perror("SUNWblank", err
, B_TRUE
);
1495 need_to_commit
= B_TRUE
;
1496 zonecfg_fini_handle(handle
);
1498 got_handle
= B_TRUE
;
1501 zone_perror(zone
, err
, handle_expected
|| got_handle
);
1502 if (err
== Z_NO_ZONE
&& !got_handle
&&
1503 interactive_mode
&& !read_only_mode
)
1504 (void) printf(gettext("Use '%s' to begin "
1505 "configuring a new zone.\n"),
1506 cmd_to_str(CMD_CREATE
));
1514 state_atleast(zone_state_t state
)
1516 zone_state_t state_num
;
1519 if ((err
= zone_get_state(zone
, &state_num
)) != Z_OK
) {
1520 /* all states are greater than "non-existent" */
1521 if (err
== Z_NO_ZONE
)
1523 zerr(gettext("Unexpectedly failed to determine state "
1524 "of zone %s: %s"), zone
, zonecfg_strerror(err
));
1527 return (state_num
>= state
);
1531 * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
1535 short_usage(int command
)
1537 /* lex_lineno has already been incremented in the lexer; compensate */
1538 if (cmd_file_mode
) {
1539 if (strcmp(cmd_file_name
, "-") == 0)
1540 (void) fprintf(stderr
,
1541 gettext("syntax error on line %d\n"),
1544 (void) fprintf(stderr
,
1545 gettext("syntax error on line %d of %s\n"),
1546 lex_lineno
- 1, cmd_file_name
);
1548 (void) fprintf(stderr
, "%s:\n%s\n", gettext("usage"),
1549 helptab
[command
].short_usage
);
1554 * long_usage() is for bad semantics: e.g., wrong property type for a given
1555 * resource type. It is also used by longer_usage() below.
1559 long_usage(uint_t cmd_num
, boolean_t set_saw
)
1561 (void) fprintf(set_saw
? stderr
: stdout
, "%s:\n%s\n", gettext("usage"),
1562 helptab
[cmd_num
].short_usage
);
1563 (void) fprintf(set_saw
? stderr
: stdout
, "\t%s\n", long_help(cmd_num
));
1569 * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
1570 * any extra usage() flags as appropriate for whatever command.
1574 longer_usage(uint_t cmd_num
)
1576 long_usage(cmd_num
, B_FALSE
);
1577 if (helptab
[cmd_num
].flags
!= 0) {
1578 (void) printf("\n");
1579 usage(B_TRUE
, helptab
[cmd_num
].flags
);
1584 * scope_usage() is simply used when a command is called from the wrong scope.
1588 scope_usage(uint_t cmd_num
)
1590 zerr(gettext("The %s command only makes sense in the %s scope."),
1591 cmd_to_str(cmd_num
),
1592 global_scope
? gettext("resource") : gettext("global"));
1597 * On input, B_TRUE => yes, B_FALSE => no.
1598 * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
1602 ask_yesno(boolean_t default_answer
, const char *question
)
1604 char line
[64]; /* should be enough to answer yes or no */
1606 if (!ok_to_prompt
) {
1611 if (printf("%s (%s)? ", question
,
1612 default_answer
? "[y]/n" : "y/[n]") < 0)
1614 if (fgets(line
, sizeof (line
), stdin
) == NULL
)
1617 if (line
[0] == '\n')
1618 return (default_answer
? 1 : 0);
1619 if (tolower(line
[0]) == 'y')
1621 if (tolower(line
[0]) == 'n')
1627 * Prints warning if zone already exists.
1628 * In interactive mode, prompts if we should continue anyway and returns Z_OK
1629 * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR.
1631 * Note that if a zone exists and its state is >= INSTALLED, an error message
1632 * will be printed and this function will return Z_ERR regardless of mode.
1636 check_if_zone_already_exists(boolean_t force
)
1638 char line
[ZONENAME_MAX
+ 128]; /* enough to ask a question */
1639 zone_dochandle_t tmphandle
;
1642 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1643 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1646 res
= zonecfg_get_handle(zone
, tmphandle
);
1647 zonecfg_fini_handle(tmphandle
);
1651 if (state_atleast(ZONE_STATE_INSTALLED
)) {
1652 zerr(gettext("Zone %s already installed; %s not allowed."),
1653 zone
, cmd_to_str(CMD_CREATE
));
1658 (void) printf(gettext("Zone %s already exists; overwriting.\n"),
1662 (void) snprintf(line
, sizeof (line
),
1663 gettext("Zone %s already exists; %s anyway"), zone
,
1664 cmd_to_str(CMD_CREATE
));
1665 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
1666 zerr(gettext("Zone exists, input not from terminal and -F not "
1667 "specified:\n%s command ignored, exiting."),
1668 cmd_to_str(CMD_CREATE
));
1671 return (answer
== 1 ? Z_OK
: Z_ERR
);
1675 zone_is_read_only(int cmd_num
)
1677 if (strncmp(zone
, "SUNW", 4) == 0) {
1678 zerr(gettext("%s: zones beginning with SUNW are read-only."),
1683 if (read_only_mode
) {
1684 zerr(gettext("%s: cannot %s in read-only mode."), zone
,
1685 cmd_to_str(cmd_num
));
1693 * Create a new configuration.
1696 create_func(cmd_t
*cmd
)
1699 char zone_template
[ZONENAME_MAX
];
1700 char attach_path
[MAXPATHLEN
];
1701 zone_dochandle_t tmphandle
;
1702 boolean_t force
= B_FALSE
;
1703 boolean_t attach
= B_FALSE
;
1704 boolean_t arg_err
= B_FALSE
;
1706 assert(cmd
!= NULL
);
1708 /* This is the default if no arguments are given. */
1709 (void) strlcpy(zone_template
, "SUNWdefault", sizeof (zone_template
));
1712 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?a:bFt:"))
1717 longer_usage(CMD_CREATE
);
1719 short_usage(CMD_CREATE
);
1723 (void) strlcpy(attach_path
, optarg
,
1724 sizeof (attach_path
));
1728 (void) strlcpy(zone_template
, "SUNWblank",
1729 sizeof (zone_template
));
1735 (void) strlcpy(zone_template
, optarg
,
1736 sizeof (zone_template
));
1739 short_usage(CMD_CREATE
);
1747 if (optind
!= cmd
->cmd_argc
) {
1748 short_usage(CMD_CREATE
);
1752 if (zone_is_read_only(CMD_CREATE
))
1755 if (check_if_zone_already_exists(force
) != Z_OK
)
1759 * Get a temporary handle first. If that fails, the old handle
1760 * will not be lost. Then finish whichever one we don't need,
1761 * to avoid leaks. Then get the handle for zone_template, and
1762 * set the name to zone: this "copy, rename" method is how
1763 * create -[b|t] works.
1765 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1766 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1771 err
= zonecfg_get_attach_handle(attach_path
, ZONE_DETACHED
,
1772 zone
, B_FALSE
, tmphandle
);
1774 err
= zonecfg_get_template_handle(zone_template
, zone
,
1778 zonecfg_fini_handle(tmphandle
);
1779 if (attach
&& err
== Z_NO_ZONE
)
1780 (void) fprintf(stderr
, gettext("invalid path to "
1781 "detached zone\n"));
1782 else if (attach
&& err
== Z_INVALID_DOCUMENT
)
1783 (void) fprintf(stderr
, gettext("Cannot attach to an "
1784 "earlier release of the operating system\n"));
1786 zone_perror(zone_template
, err
, B_TRUE
);
1790 need_to_commit
= B_TRUE
;
1791 zonecfg_fini_handle(handle
);
1793 got_handle
= B_TRUE
;
1797 * This malloc()'s memory, which must be freed by the caller.
1800 quoteit(char *instr
)
1803 size_t outstrsize
= strlen(instr
) + 3; /* 2 quotes + '\0' */
1805 if ((outstr
= malloc(outstrsize
)) == NULL
) {
1806 zone_perror(zone
, Z_NOMEM
, B_FALSE
);
1809 if (strchr(instr
, ' ') == NULL
) {
1810 (void) strlcpy(outstr
, instr
, outstrsize
);
1813 (void) snprintf(outstr
, outstrsize
, "\"%s\"", instr
);
1818 export_prop(FILE *of
, int prop_num
, char *prop_id
)
1822 if (strlen(prop_id
) == 0)
1824 quote_str
= quoteit(prop_id
);
1825 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1826 pt_to_str(prop_num
), quote_str
);
1831 export_func(cmd_t
*cmd
)
1833 struct zone_nwiftab nwiftab
;
1834 struct zone_fstab fstab
;
1835 struct zone_devtab devtab
;
1836 struct zone_attrtab attrtab
;
1837 struct zone_rctltab rctltab
;
1838 struct zone_dstab dstab
;
1839 struct zone_psettab psettab
;
1840 struct zone_mcaptab mcaptab
;
1841 struct zone_rctlvaltab
*valptr
;
1842 struct zone_admintab admintab
;
1843 struct zone_secflagstab secflagstab
;
1845 char zonepath
[MAXPATHLEN
], outfile
[MAXPATHLEN
], pool
[MAXNAMELEN
];
1846 char bootargs
[BOOTARGS_MAX
];
1847 char sched
[MAXNAMELEN
];
1848 char brand
[MAXNAMELEN
];
1849 char hostidp
[HW_HOSTID_LEN
];
1850 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
1854 zone_iptype_t iptype
;
1855 boolean_t need_to_close
= B_FALSE
;
1856 boolean_t arg_err
= B_FALSE
;
1858 assert(cmd
!= NULL
);
1862 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?f:")) != EOF
) {
1866 longer_usage(CMD_EXPORT
);
1868 short_usage(CMD_EXPORT
);
1872 (void) strlcpy(outfile
, optarg
, sizeof (outfile
));
1875 short_usage(CMD_EXPORT
);
1883 if (optind
!= cmd
->cmd_argc
) {
1884 short_usage(CMD_EXPORT
);
1887 if (strlen(outfile
) == 0) {
1890 if ((of
= fopen(outfile
, "w")) == NULL
) {
1891 zerr(gettext("opening file %s: %s"),
1892 outfile
, strerror(errno
));
1896 need_to_close
= B_TRUE
;
1899 if ((err
= initialize(B_TRUE
)) != Z_OK
)
1902 (void) fprintf(of
, "%s -b\n", cmd_to_str(CMD_CREATE
));
1904 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) == Z_OK
&&
1905 strlen(zonepath
) > 0)
1906 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1907 pt_to_str(PT_ZONEPATH
), zonepath
);
1909 if ((zone_get_brand(zone
, brand
, sizeof (brand
)) == Z_OK
) &&
1910 (strcmp(brand
, NATIVE_BRAND_NAME
) != 0))
1911 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1912 pt_to_str(PT_BRAND
), brand
);
1914 if (zonecfg_get_autoboot(handle
, &autoboot
) == Z_OK
)
1915 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1916 pt_to_str(PT_AUTOBOOT
), autoboot
? "true" : "false");
1918 if (zonecfg_get_bootargs(handle
, bootargs
, sizeof (bootargs
)) == Z_OK
&&
1919 strlen(bootargs
) > 0) {
1920 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1921 pt_to_str(PT_BOOTARGS
), bootargs
);
1924 if (zonecfg_get_pool(handle
, pool
, sizeof (pool
)) == Z_OK
&&
1926 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1927 pt_to_str(PT_POOL
), pool
);
1929 if (zonecfg_get_limitpriv(handle
, &limitpriv
) == Z_OK
&&
1930 strlen(limitpriv
) > 0) {
1931 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1932 pt_to_str(PT_LIMITPRIV
), limitpriv
);
1936 if (zonecfg_get_sched_class(handle
, sched
, sizeof (sched
)) == Z_OK
&&
1938 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1939 pt_to_str(PT_SCHED
), sched
);
1941 if (zonecfg_get_iptype(handle
, &iptype
) == Z_OK
) {
1944 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1945 pt_to_str(PT_IPTYPE
), "shared");
1948 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1949 pt_to_str(PT_IPTYPE
), "exclusive");
1954 if (zonecfg_get_hostid(handle
, hostidp
, sizeof (hostidp
)) == Z_OK
) {
1955 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1956 pt_to_str(PT_HOSTID
), hostidp
);
1959 if (zonecfg_get_fs_allowed(handle
, fsallowedp
,
1960 sizeof (fsallowedp
)) == Z_OK
) {
1961 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1962 pt_to_str(PT_FS_ALLOWED
), fsallowedp
);
1965 if ((err
= zonecfg_setfsent(handle
)) != Z_OK
) {
1966 zone_perror(zone
, err
, B_FALSE
);
1969 while (zonecfg_getfsent(handle
, &fstab
) == Z_OK
) {
1970 zone_fsopt_t
*optptr
;
1972 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
1974 export_prop(of
, PT_DIR
, fstab
.zone_fs_dir
);
1975 export_prop(of
, PT_SPECIAL
, fstab
.zone_fs_special
);
1976 export_prop(of
, PT_RAW
, fstab
.zone_fs_raw
);
1977 export_prop(of
, PT_TYPE
, fstab
.zone_fs_type
);
1978 for (optptr
= fstab
.zone_fs_options
; optptr
!= NULL
;
1979 optptr
= optptr
->zone_fsopt_next
) {
1981 * Simple property values with embedded equal signs
1982 * need to be quoted to prevent the lexer from
1983 * mis-parsing them as complex name=value pairs.
1985 if (strchr(optptr
->zone_fsopt_opt
, '='))
1986 (void) fprintf(of
, "%s %s \"%s\"\n",
1987 cmd_to_str(CMD_ADD
),
1988 pt_to_str(PT_OPTIONS
),
1989 optptr
->zone_fsopt_opt
);
1991 (void) fprintf(of
, "%s %s %s\n",
1992 cmd_to_str(CMD_ADD
),
1993 pt_to_str(PT_OPTIONS
),
1994 optptr
->zone_fsopt_opt
);
1996 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
1997 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
1999 (void) zonecfg_endfsent(handle
);
2001 if ((err
= zonecfg_setnwifent(handle
)) != Z_OK
) {
2002 zone_perror(zone
, err
, B_FALSE
);
2005 while (zonecfg_getnwifent(handle
, &nwiftab
) == Z_OK
) {
2006 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2008 export_prop(of
, PT_ADDRESS
, nwiftab
.zone_nwif_address
);
2009 export_prop(of
, PT_ALLOWED_ADDRESS
,
2010 nwiftab
.zone_nwif_allowed_address
);
2011 export_prop(of
, PT_PHYSICAL
, nwiftab
.zone_nwif_physical
);
2012 export_prop(of
, PT_DEFROUTER
, nwiftab
.zone_nwif_defrouter
);
2013 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2015 (void) zonecfg_endnwifent(handle
);
2017 if ((err
= zonecfg_setdevent(handle
)) != Z_OK
) {
2018 zone_perror(zone
, err
, B_FALSE
);
2021 while (zonecfg_getdevent(handle
, &devtab
) == Z_OK
) {
2022 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2023 rt_to_str(RT_DEVICE
));
2024 export_prop(of
, PT_MATCH
, devtab
.zone_dev_match
);
2025 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2027 (void) zonecfg_enddevent(handle
);
2029 if (zonecfg_getmcapent(handle
, &mcaptab
) == Z_OK
) {
2032 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2033 rt_to_str(RT_MCAP
));
2034 bytes_to_units(mcaptab
.zone_physmem_cap
, buf
, sizeof (buf
));
2035 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2036 pt_to_str(PT_PHYSICAL
), buf
);
2037 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2040 if ((err
= zonecfg_setrctlent(handle
)) != Z_OK
) {
2041 zone_perror(zone
, err
, B_FALSE
);
2044 while (zonecfg_getrctlent(handle
, &rctltab
) == Z_OK
) {
2045 (void) fprintf(of
, "%s rctl\n", cmd_to_str(CMD_ADD
));
2046 export_prop(of
, PT_NAME
, rctltab
.zone_rctl_name
);
2047 for (valptr
= rctltab
.zone_rctl_valptr
; valptr
!= NULL
;
2048 valptr
= valptr
->zone_rctlval_next
) {
2049 fprintf(of
, "%s %s (%s=%s,%s=%s,%s=%s)\n",
2050 cmd_to_str(CMD_ADD
), pt_to_str(PT_VALUE
),
2051 pt_to_str(PT_PRIV
), valptr
->zone_rctlval_priv
,
2052 pt_to_str(PT_LIMIT
), valptr
->zone_rctlval_limit
,
2053 pt_to_str(PT_ACTION
), valptr
->zone_rctlval_action
);
2055 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2056 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
2058 (void) zonecfg_endrctlent(handle
);
2060 if ((err
= zonecfg_setattrent(handle
)) != Z_OK
) {
2061 zone_perror(zone
, err
, B_FALSE
);
2064 while (zonecfg_getattrent(handle
, &attrtab
) == Z_OK
) {
2065 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2066 rt_to_str(RT_ATTR
));
2067 export_prop(of
, PT_NAME
, attrtab
.zone_attr_name
);
2068 export_prop(of
, PT_TYPE
, attrtab
.zone_attr_type
);
2069 export_prop(of
, PT_VALUE
, attrtab
.zone_attr_value
);
2070 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2072 (void) zonecfg_endattrent(handle
);
2074 if ((err
= zonecfg_setdsent(handle
)) != Z_OK
) {
2075 zone_perror(zone
, err
, B_FALSE
);
2078 while (zonecfg_getdsent(handle
, &dstab
) == Z_OK
) {
2079 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2080 rt_to_str(RT_DATASET
));
2081 export_prop(of
, PT_NAME
, dstab
.zone_dataset_name
);
2082 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2084 (void) zonecfg_enddsent(handle
);
2086 if (zonecfg_getpsetent(handle
, &psettab
) == Z_OK
) {
2087 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2088 rt_to_str(RT_DCPU
));
2089 if (strcmp(psettab
.zone_ncpu_min
, psettab
.zone_ncpu_max
) == 0)
2090 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2091 pt_to_str(PT_NCPUS
), psettab
.zone_ncpu_max
);
2093 (void) fprintf(of
, "%s %s=%s-%s\n", cmd_to_str(CMD_SET
),
2094 pt_to_str(PT_NCPUS
), psettab
.zone_ncpu_min
,
2095 psettab
.zone_ncpu_max
);
2096 if (psettab
.zone_importance
[0] != '\0')
2097 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2098 pt_to_str(PT_IMPORTANCE
), psettab
.zone_importance
);
2099 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2102 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
2103 zone_perror(zone
, err
, B_FALSE
);
2106 while (zonecfg_getadminent(handle
, &admintab
) == Z_OK
) {
2107 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2108 rt_to_str(RT_ADMIN
));
2109 export_prop(of
, PT_USER
, admintab
.zone_admin_user
);
2110 export_prop(of
, PT_AUTHS
, admintab
.zone_admin_auths
);
2111 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2114 (void) zonecfg_endadminent(handle
);
2116 if (zonecfg_getsecflagsent(handle
, &secflagstab
) == Z_OK
) {
2117 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2118 rt_to_str(RT_SECFLAGS
));
2119 export_prop(of
, PT_DEFAULT
, secflagstab
.zone_secflags_default
);
2120 export_prop(of
, PT_LOWER
, secflagstab
.zone_secflags_lower
);
2121 export_prop(of
, PT_UPPER
, secflagstab
.zone_secflags_upper
);
2122 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2126 * There is nothing to export for pcap since this resource is just
2127 * a container for an rctl alias.
2136 exit_func(cmd_t
*cmd
)
2139 boolean_t arg_err
= B_FALSE
;
2142 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
2145 longer_usage(CMD_EXIT
);
2149 force_exit
= B_TRUE
;
2152 short_usage(CMD_EXIT
);
2160 if (optind
< cmd
->cmd_argc
) {
2161 short_usage(CMD_EXIT
);
2165 if (global_scope
|| force_exit
) {
2166 time_to_exit
= B_TRUE
;
2170 answer
= ask_yesno(B_FALSE
, "Resource incomplete; really quit");
2172 zerr(gettext("Resource incomplete, input "
2173 "not from terminal and -F not specified:\n%s command "
2174 "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT
));
2176 } else if (answer
== 1) {
2177 time_to_exit
= B_TRUE
;
2179 /* (answer == 0) => just return */
2183 validate_zonepath_syntax(char *path
)
2185 if (path
[0] != '/') {
2186 zerr(gettext("%s is not an absolute path."), path
);
2189 /* If path is all slashes, then fail */
2190 if (strspn(path
, "/") == strlen(path
)) {
2191 zerr(gettext("/ is not allowed as a %s."),
2192 pt_to_str(PT_ZONEPATH
));
2199 add_resource(cmd_t
*cmd
)
2202 struct zone_psettab tmp_psettab
;
2203 struct zone_mcaptab tmp_mcaptab
;
2204 struct zone_secflagstab tmp_secflagstab
;
2207 char pool
[MAXNAMELEN
];
2209 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
2210 long_usage(CMD_ADD
, B_TRUE
);
2216 bzero(&in_progress_fstab
, sizeof (in_progress_fstab
));
2219 bzero(&in_progress_nwiftab
, sizeof (in_progress_nwiftab
));
2222 bzero(&in_progress_devtab
, sizeof (in_progress_devtab
));
2226 zerr(gettext("WARNING: Setting a global zone resource "
2227 "control too low could deny\nservice "
2228 "to even the root user; "
2229 "this could render the system impossible\n"
2230 "to administer. Please use caution."));
2231 bzero(&in_progress_rctltab
, sizeof (in_progress_rctltab
));
2234 bzero(&in_progress_attrtab
, sizeof (in_progress_attrtab
));
2237 bzero(&in_progress_dstab
, sizeof (in_progress_dstab
));
2240 /* Make sure there isn't already a cpu-set or cpu-cap entry. */
2241 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
2242 zerr(gettext("The %s resource already exists."),
2243 rt_to_str(RT_DCPU
));
2246 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
) !=
2248 zerr(gettext("The %s resource already exists."),
2249 rt_to_str(RT_PCAP
));
2253 /* Make sure the pool property isn't set. */
2254 if (zonecfg_get_pool(handle
, pool
, sizeof (pool
)) == Z_OK
&&
2256 zerr(gettext("The %s property is already set. "
2257 "A persistent pool is incompatible with\nthe %s "
2259 pt_to_str(PT_POOL
), rt_to_str(RT_DCPU
));
2263 bzero(&in_progress_psettab
, sizeof (in_progress_psettab
));
2267 * Make sure there isn't already a cpu-set or incompatible
2270 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
2271 zerr(gettext("The %s resource already exists."),
2272 rt_to_str(RT_DCPU
));
2276 switch (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
)) {
2277 case Z_ALIAS_DISALLOW
:
2278 zone_perror(rt_to_str(RT_PCAP
), Z_ALIAS_DISALLOW
,
2283 zerr(gettext("The %s resource already exists."),
2284 rt_to_str(RT_PCAP
));
2293 * Make sure there isn't already a mem-cap entry or max-swap
2294 * or max-locked rctl.
2296 if (zonecfg_lookup_mcap(handle
, &tmp_mcaptab
) == Z_OK
||
2297 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &tmp_mcap
)
2299 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
2300 &tmp_mcap
) == Z_OK
) {
2301 zerr(gettext("The %s resource or a related resource "
2302 "control already exists."), rt_to_str(RT_MCAP
));
2306 zerr(gettext("WARNING: Setting a global zone memory "
2307 "cap too low could deny\nservice "
2308 "to even the root user; "
2309 "this could render the system impossible\n"
2310 "to administer. Please use caution."));
2311 bzero(&in_progress_mcaptab
, sizeof (in_progress_mcaptab
));
2314 bzero(&in_progress_admintab
, sizeof (in_progress_admintab
));
2317 /* Make sure we haven't already set this */
2318 if (zonecfg_lookup_secflags(handle
, &tmp_secflagstab
) == Z_OK
)
2319 zerr(gettext("The %s resource already exists."),
2320 rt_to_str(RT_SECFLAGS
));
2321 bzero(&in_progress_secflagstab
,
2322 sizeof (in_progress_secflagstab
));
2325 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
2326 long_usage(CMD_ADD
, B_TRUE
);
2327 usage(B_FALSE
, HELP_RESOURCES
);
2330 global_scope
= B_TRUE
;
2335 do_complex_rctl_val(complex_property_ptr_t cp
)
2337 struct zone_rctlvaltab
*rctlvaltab
;
2338 complex_property_ptr_t cx
;
2339 boolean_t seen_priv
= B_FALSE
, seen_limit
= B_FALSE
,
2340 seen_action
= B_FALSE
;
2344 if ((rctlvaltab
= alloc_rctlvaltab()) == NULL
) {
2345 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
2348 for (cx
= cp
; cx
!= NULL
; cx
= cx
->cp_next
) {
2349 switch (cx
->cp_type
) {
2352 zerr(gettext("%s already specified"),
2353 pt_to_str(PT_PRIV
));
2356 (void) strlcpy(rctlvaltab
->zone_rctlval_priv
,
2358 sizeof (rctlvaltab
->zone_rctlval_priv
));
2363 zerr(gettext("%s already specified"),
2364 pt_to_str(PT_LIMIT
));
2367 (void) strlcpy(rctlvaltab
->zone_rctlval_limit
,
2369 sizeof (rctlvaltab
->zone_rctlval_limit
));
2370 seen_limit
= B_TRUE
;
2374 zerr(gettext("%s already specified"),
2375 pt_to_str(PT_ACTION
));
2378 (void) strlcpy(rctlvaltab
->zone_rctlval_action
,
2380 sizeof (rctlvaltab
->zone_rctlval_action
));
2381 seen_action
= B_TRUE
;
2384 zone_perror(pt_to_str(PT_VALUE
),
2385 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2386 long_usage(CMD_ADD
, B_TRUE
);
2387 usage(B_FALSE
, HELP_PROPS
);
2388 zonecfg_free_rctl_value_list(rctlvaltab
);
2393 zerr(gettext("%s not specified"), pt_to_str(PT_PRIV
));
2395 zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT
));
2397 zerr(gettext("%s not specified"), pt_to_str(PT_ACTION
));
2398 if (!seen_priv
|| !seen_limit
|| !seen_action
)
2400 rctlvaltab
->zone_rctlval_next
= NULL
;
2401 rctlblk
= alloca(rctlblk_size());
2403 * Make sure the rctl value looks roughly correct; we won't know if
2404 * it's truly OK until we verify the configuration on the target
2407 if (zonecfg_construct_rctlblk(rctlvaltab
, rctlblk
) != Z_OK
||
2408 !zonecfg_valid_rctlblk(rctlblk
)) {
2409 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL
),
2410 pt_to_str(PT_VALUE
));
2413 err
= zonecfg_add_rctl_value(&in_progress_rctltab
, rctlvaltab
);
2415 zone_perror(pt_to_str(PT_VALUE
), err
, B_TRUE
);
2419 zonecfg_free_rctl_value_list(rctlvaltab
);
2423 add_property(cmd_t
*cmd
)
2426 int err
, res_type
, prop_type
;
2427 property_value_ptr_t pp
;
2428 list_property_ptr_t l
;
2430 res_type
= resource_scope
;
2431 prop_type
= cmd
->cmd_prop_name
[0];
2432 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
2433 long_usage(CMD_ADD
, B_TRUE
);
2437 if (cmd
->cmd_prop_nv_pairs
!= 1) {
2438 long_usage(CMD_ADD
, B_TRUE
);
2442 if (initialize(B_TRUE
) != Z_OK
)
2447 if (prop_type
!= PT_OPTIONS
) {
2448 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
2450 long_usage(CMD_ADD
, B_TRUE
);
2451 usage(B_FALSE
, HELP_PROPS
);
2454 pp
= cmd
->cmd_property_ptr
[0];
2455 if (pp
->pv_type
!= PROP_VAL_SIMPLE
&&
2456 pp
->pv_type
!= PROP_VAL_LIST
) {
2457 zerr(gettext("A %s or %s value was expected here."),
2458 pvt_to_str(PROP_VAL_SIMPLE
),
2459 pvt_to_str(PROP_VAL_LIST
));
2463 if (pp
->pv_type
== PROP_VAL_SIMPLE
) {
2464 if (pp
->pv_simple
== NULL
) {
2465 long_usage(CMD_ADD
, B_TRUE
);
2468 prop_id
= pp
->pv_simple
;
2469 err
= zonecfg_add_fs_option(&in_progress_fstab
,
2472 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
2474 list_property_ptr_t list
;
2476 for (list
= pp
->pv_list
; list
!= NULL
;
2477 list
= list
->lp_next
) {
2478 prop_id
= list
->lp_simple
;
2479 if (prop_id
== NULL
)
2481 err
= zonecfg_add_fs_option(
2482 &in_progress_fstab
, prop_id
);
2484 zone_perror(pt_to_str(prop_type
), err
,
2490 if (prop_type
!= PT_VALUE
) {
2491 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
2493 long_usage(CMD_ADD
, B_TRUE
);
2494 usage(B_FALSE
, HELP_PROPS
);
2497 pp
= cmd
->cmd_property_ptr
[0];
2498 if (pp
->pv_type
!= PROP_VAL_COMPLEX
&&
2499 pp
->pv_type
!= PROP_VAL_LIST
) {
2500 zerr(gettext("A %s or %s value was expected here."),
2501 pvt_to_str(PROP_VAL_COMPLEX
),
2502 pvt_to_str(PROP_VAL_LIST
));
2506 if (pp
->pv_type
== PROP_VAL_COMPLEX
) {
2507 do_complex_rctl_val(pp
->pv_complex
);
2510 for (l
= pp
->pv_list
; l
!= NULL
; l
= l
->lp_next
)
2511 do_complex_rctl_val(l
->lp_complex
);
2514 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
2515 long_usage(CMD_ADD
, B_TRUE
);
2516 usage(B_FALSE
, HELP_RESOURCES
);
2522 gz_invalid_resource(int type
)
2524 return (global_zone
&& (type
== RT_FS
||
2525 type
== RT_NET
|| type
== RT_DEVICE
|| type
== RT_ATTR
||
2526 type
== RT_DATASET
));
2530 gz_invalid_rt_property(int type
)
2532 return (global_zone
&& (type
== RT_ZONENAME
|| type
== RT_ZONEPATH
||
2533 type
== RT_AUTOBOOT
|| type
== RT_LIMITPRIV
||
2534 type
== RT_BOOTARGS
|| type
== RT_BRAND
|| type
== RT_SCHED
||
2535 type
== RT_IPTYPE
|| type
== RT_HOSTID
|| type
== RT_FS_ALLOWED
));
2539 gz_invalid_property(int type
)
2541 return (global_zone
&& (type
== PT_ZONENAME
|| type
== PT_ZONEPATH
||
2542 type
== PT_AUTOBOOT
|| type
== PT_LIMITPRIV
||
2543 type
== PT_BOOTARGS
|| type
== PT_BRAND
|| type
== PT_SCHED
||
2544 type
== PT_IPTYPE
|| type
== PT_HOSTID
|| type
== PT_FS_ALLOWED
));
2548 add_func(cmd_t
*cmd
)
2551 boolean_t arg_err
= B_FALSE
;
2553 assert(cmd
!= NULL
);
2556 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
2559 longer_usage(CMD_ADD
);
2563 short_usage(CMD_ADD
);
2571 if (optind
!= cmd
->cmd_argc
) {
2572 short_usage(CMD_ADD
);
2576 if (zone_is_read_only(CMD_ADD
))
2579 if (initialize(B_TRUE
) != Z_OK
)
2582 if (gz_invalid_resource(cmd
->cmd_res_type
)) {
2583 zerr(gettext("Cannot add a %s resource to the "
2584 "global zone."), rt_to_str(cmd
->cmd_res_type
));
2589 global_scope
= B_FALSE
;
2590 resource_scope
= cmd
->cmd_res_type
;
2598 * This routine has an unusual implementation, because it tries very
2599 * hard to succeed in the face of a variety of failure modes.
2600 * The most common and most vexing occurs when the index file and
2601 * the /etc/zones/<zonename.xml> file are not both present. In
2602 * this case, delete must eradicate as much of the zone state as is left
2603 * so that the user can later create a new zone with the same name.
2606 delete_func(cmd_t
*cmd
)
2608 int err
, arg
, answer
;
2609 char line
[ZONENAME_MAX
+ 128]; /* enough to ask a question */
2610 boolean_t force
= B_FALSE
;
2611 boolean_t arg_err
= B_FALSE
;
2614 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
2617 longer_usage(CMD_DELETE
);
2624 short_usage(CMD_DELETE
);
2632 if (optind
!= cmd
->cmd_argc
) {
2633 short_usage(CMD_DELETE
);
2637 if (zone_is_read_only(CMD_DELETE
))
2642 * Initialize sets up the global called "handle" and warns the
2643 * user if the zone is not configured. In force mode, we don't
2644 * trust that evaluation, and hence skip it. (We don't need the
2645 * handle to be loaded anyway, since zonecfg_destroy is done by
2646 * zonename). However, we also have to take care to emulate the
2647 * messages spit out by initialize; see below.
2649 if (initialize(B_TRUE
) != Z_OK
)
2652 (void) snprintf(line
, sizeof (line
),
2653 gettext("Are you sure you want to delete zone %s"), zone
);
2654 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
2655 zerr(gettext("Input not from terminal and -F not "
2656 "specified:\n%s command ignored, exiting."),
2657 cmd_to_str(CMD_DELETE
));
2665 * This function removes the authorizations from user_attr
2666 * that correspond to those specified in the configuration
2668 if (initialize(B_TRUE
) == Z_OK
) {
2669 (void) zonecfg_deauthorize_users(handle
, zone
);
2671 if ((err
= zonecfg_destroy(zone
, force
)) != Z_OK
) {
2672 if ((err
== Z_BAD_ZONE_STATE
) && !force
) {
2673 zerr(gettext("Zone %s not in %s state; %s not "
2674 "allowed. Use -F to force %s."),
2675 zone
, zone_state_str(ZONE_STATE_CONFIGURED
),
2676 cmd_to_str(CMD_DELETE
), cmd_to_str(CMD_DELETE
));
2678 zone_perror(zone
, err
, B_TRUE
);
2681 need_to_commit
= B_FALSE
;
2684 * Emulate initialize's messaging; if there wasn't a valid handle to
2685 * begin with, then user had typed delete (or delete -F) multiple
2686 * times. So we emit a message.
2688 * We only do this in the 'force' case because normally, initialize()
2689 * takes care of this for us.
2691 if (force
&& zonecfg_check_handle(handle
) != Z_OK
&& interactive_mode
)
2692 (void) printf(gettext("Use '%s' to begin "
2693 "configuring a new zone.\n"), cmd_to_str(CMD_CREATE
));
2696 * Time for a new handle: finish the old one off first
2697 * then get a new one properly to avoid leaks.
2700 zonecfg_fini_handle(handle
);
2701 if ((handle
= zonecfg_init_handle()) == NULL
) {
2702 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
2705 if ((err
= zonecfg_get_handle(zone
, handle
)) != Z_OK
) {
2706 /* If there was no zone before, that's OK */
2707 if (err
!= Z_NO_ZONE
)
2708 zone_perror(zone
, err
, B_TRUE
);
2709 got_handle
= B_FALSE
;
2715 fill_in_fstab(cmd_t
*cmd
, struct zone_fstab
*fstab
, boolean_t fill_in_only
)
2718 property_value_ptr_t pp
;
2720 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2723 bzero(fstab
, sizeof (*fstab
));
2724 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2725 pp
= cmd
->cmd_property_ptr
[i
];
2726 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2727 zerr(gettext("A simple value was expected here."));
2729 return (Z_INSUFFICIENT_SPEC
);
2731 switch (cmd
->cmd_prop_name
[i
]) {
2733 (void) strlcpy(fstab
->zone_fs_dir
, pp
->pv_simple
,
2734 sizeof (fstab
->zone_fs_dir
));
2737 (void) strlcpy(fstab
->zone_fs_special
, pp
->pv_simple
,
2738 sizeof (fstab
->zone_fs_special
));
2741 (void) strlcpy(fstab
->zone_fs_raw
, pp
->pv_simple
,
2742 sizeof (fstab
->zone_fs_raw
));
2745 (void) strlcpy(fstab
->zone_fs_type
, pp
->pv_simple
,
2746 sizeof (fstab
->zone_fs_type
));
2749 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2750 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2751 return (Z_INSUFFICIENT_SPEC
);
2756 return (zonecfg_lookup_filesystem(handle
, fstab
));
2760 fill_in_nwiftab(cmd_t
*cmd
, struct zone_nwiftab
*nwiftab
,
2761 boolean_t fill_in_only
)
2764 property_value_ptr_t pp
;
2766 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2769 bzero(nwiftab
, sizeof (*nwiftab
));
2770 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2771 pp
= cmd
->cmd_property_ptr
[i
];
2772 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2773 zerr(gettext("A simple value was expected here."));
2775 return (Z_INSUFFICIENT_SPEC
);
2777 switch (cmd
->cmd_prop_name
[i
]) {
2779 (void) strlcpy(nwiftab
->zone_nwif_address
,
2780 pp
->pv_simple
, sizeof (nwiftab
->zone_nwif_address
));
2782 case PT_ALLOWED_ADDRESS
:
2783 (void) strlcpy(nwiftab
->zone_nwif_allowed_address
,
2785 sizeof (nwiftab
->zone_nwif_allowed_address
));
2788 (void) strlcpy(nwiftab
->zone_nwif_physical
,
2790 sizeof (nwiftab
->zone_nwif_physical
));
2793 (void) strlcpy(nwiftab
->zone_nwif_defrouter
,
2795 sizeof (nwiftab
->zone_nwif_defrouter
));
2798 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2799 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2800 return (Z_INSUFFICIENT_SPEC
);
2805 err
= zonecfg_lookup_nwif(handle
, nwiftab
);
2810 fill_in_devtab(cmd_t
*cmd
, struct zone_devtab
*devtab
, boolean_t fill_in_only
)
2813 property_value_ptr_t pp
;
2815 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2818 bzero(devtab
, sizeof (*devtab
));
2819 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2820 pp
= cmd
->cmd_property_ptr
[i
];
2821 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2822 zerr(gettext("A simple value was expected here."));
2824 return (Z_INSUFFICIENT_SPEC
);
2826 switch (cmd
->cmd_prop_name
[i
]) {
2828 (void) strlcpy(devtab
->zone_dev_match
, pp
->pv_simple
,
2829 sizeof (devtab
->zone_dev_match
));
2832 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2833 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2834 return (Z_INSUFFICIENT_SPEC
);
2839 err
= zonecfg_lookup_dev(handle
, devtab
);
2844 fill_in_rctltab(cmd_t
*cmd
, struct zone_rctltab
*rctltab
,
2845 boolean_t fill_in_only
)
2848 property_value_ptr_t pp
;
2850 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2853 bzero(rctltab
, sizeof (*rctltab
));
2854 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2855 pp
= cmd
->cmd_property_ptr
[i
];
2856 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2857 zerr(gettext("A simple value was expected here."));
2859 return (Z_INSUFFICIENT_SPEC
);
2861 switch (cmd
->cmd_prop_name
[i
]) {
2863 (void) strlcpy(rctltab
->zone_rctl_name
, pp
->pv_simple
,
2864 sizeof (rctltab
->zone_rctl_name
));
2867 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2868 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2869 return (Z_INSUFFICIENT_SPEC
);
2874 err
= zonecfg_lookup_rctl(handle
, rctltab
);
2879 fill_in_attrtab(cmd_t
*cmd
, struct zone_attrtab
*attrtab
,
2880 boolean_t fill_in_only
)
2883 property_value_ptr_t pp
;
2885 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2888 bzero(attrtab
, sizeof (*attrtab
));
2889 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2890 pp
= cmd
->cmd_property_ptr
[i
];
2891 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2892 zerr(gettext("A simple value was expected here."));
2894 return (Z_INSUFFICIENT_SPEC
);
2896 switch (cmd
->cmd_prop_name
[i
]) {
2898 (void) strlcpy(attrtab
->zone_attr_name
, pp
->pv_simple
,
2899 sizeof (attrtab
->zone_attr_name
));
2902 (void) strlcpy(attrtab
->zone_attr_type
, pp
->pv_simple
,
2903 sizeof (attrtab
->zone_attr_type
));
2906 (void) strlcpy(attrtab
->zone_attr_value
, pp
->pv_simple
,
2907 sizeof (attrtab
->zone_attr_value
));
2910 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2911 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2912 return (Z_INSUFFICIENT_SPEC
);
2917 err
= zonecfg_lookup_attr(handle
, attrtab
);
2922 fill_in_dstab(cmd_t
*cmd
, struct zone_dstab
*dstab
, boolean_t fill_in_only
)
2925 property_value_ptr_t pp
;
2927 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2930 dstab
->zone_dataset_name
[0] = '\0';
2931 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2932 pp
= cmd
->cmd_property_ptr
[i
];
2933 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2934 zerr(gettext("A simple value was expected here."));
2936 return (Z_INSUFFICIENT_SPEC
);
2938 switch (cmd
->cmd_prop_name
[i
]) {
2940 (void) strlcpy(dstab
->zone_dataset_name
, pp
->pv_simple
,
2941 sizeof (dstab
->zone_dataset_name
));
2944 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2945 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2946 return (Z_INSUFFICIENT_SPEC
);
2951 return (zonecfg_lookup_ds(handle
, dstab
));
2955 fill_in_admintab(cmd_t
*cmd
, struct zone_admintab
*admintab
,
2956 boolean_t fill_in_only
)
2959 property_value_ptr_t pp
;
2961 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2964 bzero(admintab
, sizeof (*admintab
));
2965 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2966 pp
= cmd
->cmd_property_ptr
[i
];
2967 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2968 zerr(gettext("A simple value was expected here."));
2970 return (Z_INSUFFICIENT_SPEC
);
2972 switch (cmd
->cmd_prop_name
[i
]) {
2974 (void) strlcpy(admintab
->zone_admin_user
, pp
->pv_simple
,
2975 sizeof (admintab
->zone_admin_user
));
2978 (void) strlcpy(admintab
->zone_admin_auths
,
2979 pp
->pv_simple
, sizeof (admintab
->zone_admin_auths
));
2982 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2983 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2984 return (Z_INSUFFICIENT_SPEC
);
2989 err
= zonecfg_lookup_admin(handle
, admintab
);
2994 fill_in_secflagstab(cmd_t
*cmd
, struct zone_secflagstab
*secflagstab
,
2995 boolean_t fill_in_only
)
2998 property_value_ptr_t pp
;
3000 if ((err
= initialize(B_TRUE
)) != Z_OK
)
3003 bzero(secflagstab
, sizeof (*secflagstab
));
3004 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
3005 pp
= cmd
->cmd_property_ptr
[i
];
3006 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
3007 zerr(gettext("A simple value was expected here."));
3009 return (Z_INSUFFICIENT_SPEC
);
3011 switch (cmd
->cmd_prop_name
[i
]) {
3013 (void) strlcpy(secflagstab
->zone_secflags_default
,
3015 sizeof (secflagstab
->zone_secflags_default
));
3018 (void) strlcpy(secflagstab
->zone_secflags_lower
,
3020 sizeof (secflagstab
->zone_secflags_lower
));
3023 (void) strlcpy(secflagstab
->zone_secflags_upper
,
3025 sizeof (secflagstab
->zone_secflags_upper
));
3028 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
3029 Z_NO_PROPERTY_TYPE
, B_TRUE
);
3030 return (Z_INSUFFICIENT_SPEC
);
3036 err
= zonecfg_lookup_secflags(handle
, secflagstab
);
3042 remove_aliased_rctl(int type
, char *name
)
3047 if ((err
= zonecfg_get_aliased_rctl(handle
, name
, &tmp
)) != Z_OK
) {
3048 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR
), pt_to_str(type
),
3049 zonecfg_strerror(err
));
3053 if ((err
= zonecfg_rm_aliased_rctl(handle
, name
)) != Z_OK
) {
3054 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR
), pt_to_str(type
),
3055 zonecfg_strerror(err
));
3058 need_to_commit
= B_TRUE
;
3063 prompt_remove_resource(cmd_t
*cmd
, char *rsrc
)
3068 boolean_t force
= B_FALSE
;
3070 boolean_t arg_err
= B_FALSE
;
3073 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "F")) != EOF
) {
3087 num
= zonecfg_num_resources(handle
, rsrc
);
3090 z_cmd_rt_perror(CMD_REMOVE
, cmd
->cmd_res_type
, Z_NO_ENTRY
,
3094 if (num
> 1 && !force
) {
3095 if (!interactive_mode
) {
3096 zerr(gettext("There are multiple instances of this "
3097 "resource. Either qualify the resource to\n"
3098 "remove a single instance or use the -F option to "
3099 "remove all instances."));
3103 (void) snprintf(prompt
, sizeof (prompt
), gettext(
3104 "Are you sure you want to remove ALL '%s' resources"),
3106 answer
= ask_yesno(B_FALSE
, prompt
);
3108 zerr(gettext("Resource incomplete."));
3118 remove_fs(cmd_t
*cmd
)
3122 /* traditional, qualified fs removal */
3123 if (cmd
->cmd_prop_nv_pairs
> 0) {
3124 struct zone_fstab fstab
;
3126 if ((err
= fill_in_fstab(cmd
, &fstab
, B_FALSE
)) != Z_OK
) {
3127 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3130 if ((err
= zonecfg_delete_filesystem(handle
, &fstab
)) != Z_OK
)
3131 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3133 need_to_commit
= B_TRUE
;
3134 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
3139 * unqualified fs removal. remove all fs's but prompt if more
3142 if (!prompt_remove_resource(cmd
, "fs"))
3145 if ((err
= zonecfg_del_all_resources(handle
, "fs")) != Z_OK
)
3146 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3148 need_to_commit
= B_TRUE
;
3152 remove_net(cmd_t
*cmd
)
3156 /* traditional, qualified net removal */
3157 if (cmd
->cmd_prop_nv_pairs
> 0) {
3158 struct zone_nwiftab nwiftab
;
3160 if ((err
= fill_in_nwiftab(cmd
, &nwiftab
, B_FALSE
)) != Z_OK
) {
3161 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3164 if ((err
= zonecfg_delete_nwif(handle
, &nwiftab
)) != Z_OK
)
3165 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3167 need_to_commit
= B_TRUE
;
3172 * unqualified net removal. remove all nets but prompt if more
3175 if (!prompt_remove_resource(cmd
, "net"))
3178 if ((err
= zonecfg_del_all_resources(handle
, "net")) != Z_OK
)
3179 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3181 need_to_commit
= B_TRUE
;
3185 remove_device(cmd_t
*cmd
)
3189 /* traditional, qualified device removal */
3190 if (cmd
->cmd_prop_nv_pairs
> 0) {
3191 struct zone_devtab devtab
;
3193 if ((err
= fill_in_devtab(cmd
, &devtab
, B_FALSE
)) != Z_OK
) {
3194 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3197 if ((err
= zonecfg_delete_dev(handle
, &devtab
)) != Z_OK
)
3198 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3200 need_to_commit
= B_TRUE
;
3205 * unqualified device removal. remove all devices but prompt if more
3208 if (!prompt_remove_resource(cmd
, "device"))
3211 if ((err
= zonecfg_del_all_resources(handle
, "device")) != Z_OK
)
3212 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3214 need_to_commit
= B_TRUE
;
3218 remove_attr(cmd_t
*cmd
)
3222 /* traditional, qualified attr removal */
3223 if (cmd
->cmd_prop_nv_pairs
> 0) {
3224 struct zone_attrtab attrtab
;
3226 if ((err
= fill_in_attrtab(cmd
, &attrtab
, B_FALSE
)) != Z_OK
) {
3227 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3230 if ((err
= zonecfg_delete_attr(handle
, &attrtab
)) != Z_OK
)
3231 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3233 need_to_commit
= B_TRUE
;
3238 * unqualified attr removal. remove all attrs but prompt if more
3241 if (!prompt_remove_resource(cmd
, "attr"))
3244 if ((err
= zonecfg_del_all_resources(handle
, "attr")) != Z_OK
)
3245 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3247 need_to_commit
= B_TRUE
;
3251 remove_dataset(cmd_t
*cmd
)
3255 /* traditional, qualified dataset removal */
3256 if (cmd
->cmd_prop_nv_pairs
> 0) {
3257 struct zone_dstab dstab
;
3259 if ((err
= fill_in_dstab(cmd
, &dstab
, B_FALSE
)) != Z_OK
) {
3260 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3263 if ((err
= zonecfg_delete_ds(handle
, &dstab
)) != Z_OK
)
3264 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3266 need_to_commit
= B_TRUE
;
3271 * unqualified dataset removal. remove all datasets but prompt if more
3274 if (!prompt_remove_resource(cmd
, "dataset"))
3277 if ((err
= zonecfg_del_all_resources(handle
, "dataset")) != Z_OK
)
3278 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3280 need_to_commit
= B_TRUE
;
3284 remove_rctl(cmd_t
*cmd
)
3288 /* traditional, qualified rctl removal */
3289 if (cmd
->cmd_prop_nv_pairs
> 0) {
3290 struct zone_rctltab rctltab
;
3292 if ((err
= fill_in_rctltab(cmd
, &rctltab
, B_FALSE
)) != Z_OK
) {
3293 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3296 if ((err
= zonecfg_delete_rctl(handle
, &rctltab
)) != Z_OK
)
3297 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3299 need_to_commit
= B_TRUE
;
3300 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
3305 * unqualified rctl removal. remove all rctls but prompt if more
3308 if (!prompt_remove_resource(cmd
, "rctl"))
3311 if ((err
= zonecfg_del_all_resources(handle
, "rctl")) != Z_OK
)
3312 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3314 need_to_commit
= B_TRUE
;
3321 struct zone_psettab psettab
;
3323 if ((err
= zonecfg_lookup_pset(handle
, &psettab
)) != Z_OK
) {
3324 z_cmd_rt_perror(CMD_REMOVE
, RT_DCPU
, err
, B_TRUE
);
3327 if ((err
= zonecfg_delete_pset(handle
)) != Z_OK
)
3328 z_cmd_rt_perror(CMD_REMOVE
, RT_DCPU
, err
, B_TRUE
);
3330 need_to_commit
= B_TRUE
;
3339 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
) != Z_OK
) {
3340 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
), rt_to_str(RT_PCAP
),
3341 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3346 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_CPUCAP
)) != Z_OK
)
3347 z_cmd_rt_perror(CMD_REMOVE
, RT_PCAP
, err
, B_TRUE
);
3349 need_to_commit
= B_TRUE
;
3355 int err
, res1
, res2
, res3
;
3357 struct zone_mcaptab mcaptab
;
3358 boolean_t revert
= B_FALSE
;
3360 res1
= zonecfg_lookup_mcap(handle
, &mcaptab
);
3361 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &tmp
);
3362 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
, &tmp
);
3364 /* if none of these exist, there is no resource to remove */
3365 if (res1
!= Z_OK
&& res2
!= Z_OK
&& res3
!= Z_OK
) {
3366 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
), rt_to_str(RT_MCAP
),
3367 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3372 if ((err
= zonecfg_delete_mcap(handle
)) != Z_OK
) {
3373 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3376 need_to_commit
= B_TRUE
;
3380 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_MAXSWAP
))
3382 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3385 need_to_commit
= B_TRUE
;
3389 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
))
3391 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3394 need_to_commit
= B_TRUE
;
3399 need_to_commit
= B_FALSE
;
3403 remove_admin(cmd_t
*cmd
)
3407 /* traditional, qualified attr removal */
3408 if (cmd
->cmd_prop_nv_pairs
> 0) {
3409 struct zone_admintab admintab
;
3411 if ((err
= fill_in_admintab(cmd
, &admintab
, B_FALSE
)) != Z_OK
) {
3412 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3416 if ((err
= zonecfg_delete_admin(handle
, &admintab
,
3419 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3422 need_to_commit
= B_TRUE
;
3426 * unqualified admin removal.
3427 * remove all admins but prompt if more
3430 if (!prompt_remove_resource(cmd
, "admin"))
3433 if ((err
= zonecfg_delete_admins(handle
, zone
))
3435 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3438 need_to_commit
= B_TRUE
;
3446 struct zone_secflagstab sectab
= { 0 };
3448 if (zonecfg_lookup_secflags(handle
, §ab
) != Z_OK
) {
3449 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
),
3450 rt_to_str(RT_SECFLAGS
),
3451 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3455 if ((err
= zonecfg_delete_secflags(handle
, §ab
)) != Z_OK
) {
3456 z_cmd_rt_perror(CMD_REMOVE
, RT_SECFLAGS
, err
, B_TRUE
);
3460 need_to_commit
= B_TRUE
;
3464 remove_resource(cmd_t
*cmd
)
3468 boolean_t arg_err
= B_FALSE
;
3470 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3471 long_usage(CMD_REMOVE
, B_TRUE
);
3476 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
3479 longer_usage(CMD_REMOVE
);
3485 short_usage(CMD_REMOVE
);
3493 if (initialize(B_TRUE
) != Z_OK
)
3513 remove_dataset(cmd
);
3531 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
3532 long_usage(CMD_REMOVE
, B_TRUE
);
3533 usage(B_FALSE
, HELP_RESOURCES
);
3539 remove_property(cmd_t
*cmd
)
3542 int err
, res_type
, prop_type
;
3543 property_value_ptr_t pp
;
3544 struct zone_rctlvaltab
*rctlvaltab
;
3545 complex_property_ptr_t cx
;
3547 res_type
= resource_scope
;
3548 prop_type
= cmd
->cmd_prop_name
[0];
3549 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
3550 long_usage(CMD_REMOVE
, B_TRUE
);
3554 if (cmd
->cmd_prop_nv_pairs
!= 1) {
3555 long_usage(CMD_ADD
, B_TRUE
);
3559 if (initialize(B_TRUE
) != Z_OK
)
3564 if (prop_type
!= PT_OPTIONS
) {
3565 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3567 long_usage(CMD_REMOVE
, B_TRUE
);
3568 usage(B_FALSE
, HELP_PROPS
);
3571 pp
= cmd
->cmd_property_ptr
[0];
3572 if (pp
->pv_type
== PROP_VAL_COMPLEX
) {
3573 zerr(gettext("A %s or %s value was expected here."),
3574 pvt_to_str(PROP_VAL_SIMPLE
),
3575 pvt_to_str(PROP_VAL_LIST
));
3579 if (pp
->pv_type
== PROP_VAL_SIMPLE
) {
3580 if (pp
->pv_simple
== NULL
) {
3581 long_usage(CMD_ADD
, B_TRUE
);
3584 prop_id
= pp
->pv_simple
;
3585 err
= zonecfg_remove_fs_option(&in_progress_fstab
,
3588 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
3590 list_property_ptr_t list
;
3592 for (list
= pp
->pv_list
; list
!= NULL
;
3593 list
= list
->lp_next
) {
3594 prop_id
= list
->lp_simple
;
3595 if (prop_id
== NULL
)
3597 err
= zonecfg_remove_fs_option(
3598 &in_progress_fstab
, prop_id
);
3600 zone_perror(pt_to_str(prop_type
), err
,
3606 if (prop_type
!= PT_VALUE
) {
3607 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3609 long_usage(CMD_REMOVE
, B_TRUE
);
3610 usage(B_FALSE
, HELP_PROPS
);
3613 pp
= cmd
->cmd_property_ptr
[0];
3614 if (pp
->pv_type
!= PROP_VAL_COMPLEX
) {
3615 zerr(gettext("A %s value was expected here."),
3616 pvt_to_str(PROP_VAL_COMPLEX
));
3620 if ((rctlvaltab
= alloc_rctlvaltab()) == NULL
) {
3621 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
3624 for (cx
= pp
->pv_complex
; cx
!= NULL
; cx
= cx
->cp_next
) {
3625 switch (cx
->cp_type
) {
3627 (void) strlcpy(rctlvaltab
->zone_rctlval_priv
,
3629 sizeof (rctlvaltab
->zone_rctlval_priv
));
3632 (void) strlcpy(rctlvaltab
->zone_rctlval_limit
,
3634 sizeof (rctlvaltab
->zone_rctlval_limit
));
3637 (void) strlcpy(rctlvaltab
->zone_rctlval_action
,
3639 sizeof (rctlvaltab
->zone_rctlval_action
));
3642 zone_perror(pt_to_str(prop_type
),
3643 Z_NO_PROPERTY_TYPE
, B_TRUE
);
3644 long_usage(CMD_ADD
, B_TRUE
);
3645 usage(B_FALSE
, HELP_PROPS
);
3646 zonecfg_free_rctl_value_list(rctlvaltab
);
3650 rctlvaltab
->zone_rctlval_next
= NULL
;
3651 err
= zonecfg_remove_rctl_value(&in_progress_rctltab
,
3654 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
3655 zonecfg_free_rctl_value_list(rctlvaltab
);
3658 if (prop_type
!= PT_DEFROUTER
) {
3659 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3661 long_usage(CMD_REMOVE
, B_TRUE
);
3662 usage(B_FALSE
, HELP_PROPS
);
3665 bzero(&in_progress_nwiftab
.zone_nwif_defrouter
,
3666 sizeof (in_progress_nwiftab
.zone_nwif_defrouter
));
3670 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
3671 long_usage(CMD_REMOVE
, B_TRUE
);
3672 usage(B_FALSE
, HELP_RESOURCES
);
3678 remove_func(cmd_t
*cmd
)
3680 if (zone_is_read_only(CMD_REMOVE
))
3683 assert(cmd
!= NULL
);
3686 if (gz_invalid_resource(cmd
->cmd_res_type
)) {
3687 zerr(gettext("%s is not a valid resource for the "
3688 "global zone."), rt_to_str(cmd
->cmd_res_type
));
3692 remove_resource(cmd
);
3694 remove_property(cmd
);
3699 clear_property(cmd_t
*cmd
)
3701 int res_type
, prop_type
;
3703 res_type
= resource_scope
;
3704 prop_type
= cmd
->cmd_res_type
;
3705 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
3706 long_usage(CMD_CLEAR
, B_TRUE
);
3710 if (initialize(B_TRUE
) != Z_OK
)
3715 if (prop_type
== PT_RAW
) {
3716 in_progress_fstab
.zone_fs_raw
[0] = '\0';
3717 need_to_commit
= B_TRUE
;
3722 if (prop_type
== PT_IMPORTANCE
) {
3723 in_progress_psettab
.zone_importance
[0] = '\0';
3724 need_to_commit
= B_TRUE
;
3729 switch (prop_type
) {
3731 in_progress_mcaptab
.zone_physmem_cap
[0] = '\0';
3732 need_to_commit
= B_TRUE
;
3735 remove_aliased_rctl(PT_SWAP
, ALIAS_MAXSWAP
);
3738 remove_aliased_rctl(PT_LOCKED
, ALIAS_MAXLOCKEDMEM
);
3743 switch (prop_type
) {
3745 in_progress_secflagstab
.zone_secflags_lower
[0] = '\0';
3746 need_to_commit
= B_TRUE
;
3749 in_progress_secflagstab
.zone_secflags_default
[0] = '\0';
3750 need_to_commit
= B_TRUE
;
3753 in_progress_secflagstab
.zone_secflags_upper
[0] = '\0';
3754 need_to_commit
= B_TRUE
;
3762 zone_perror(pt_to_str(prop_type
), Z_CLEAR_DISALLOW
, B_TRUE
);
3766 clear_global(cmd_t
*cmd
)
3770 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3771 long_usage(CMD_CLEAR
, B_TRUE
);
3775 if (initialize(B_TRUE
) != Z_OK
)
3784 zone_perror(pt_to_str(type
), Z_CLEAR_DISALLOW
, B_TRUE
);
3787 /* false is default; we'll treat as equivalent to clearing */
3788 if ((err
= zonecfg_set_autoboot(handle
, B_FALSE
)) != Z_OK
)
3789 z_cmd_rt_perror(CMD_CLEAR
, RT_AUTOBOOT
, err
, B_TRUE
);
3791 need_to_commit
= B_TRUE
;
3794 if ((err
= zonecfg_set_pool(handle
, NULL
)) != Z_OK
)
3795 z_cmd_rt_perror(CMD_CLEAR
, RT_POOL
, err
, B_TRUE
);
3797 need_to_commit
= B_TRUE
;
3800 if ((err
= zonecfg_set_limitpriv(handle
, NULL
)) != Z_OK
)
3801 z_cmd_rt_perror(CMD_CLEAR
, RT_LIMITPRIV
, err
, B_TRUE
);
3803 need_to_commit
= B_TRUE
;
3806 if ((err
= zonecfg_set_bootargs(handle
, NULL
)) != Z_OK
)
3807 z_cmd_rt_perror(CMD_CLEAR
, RT_BOOTARGS
, err
, B_TRUE
);
3809 need_to_commit
= B_TRUE
;
3812 if ((err
= zonecfg_set_sched(handle
, NULL
)) != Z_OK
)
3813 z_cmd_rt_perror(CMD_CLEAR
, RT_SCHED
, err
, B_TRUE
);
3815 need_to_commit
= B_TRUE
;
3818 /* shared is default; we'll treat as equivalent to clearing */
3819 if ((err
= zonecfg_set_iptype(handle
, ZS_SHARED
)) != Z_OK
)
3820 z_cmd_rt_perror(CMD_CLEAR
, RT_IPTYPE
, err
, B_TRUE
);
3822 need_to_commit
= B_TRUE
;
3825 remove_aliased_rctl(PT_MAXLWPS
, ALIAS_MAXLWPS
);
3828 remove_aliased_rctl(PT_MAXPROCS
, ALIAS_MAXPROCS
);
3831 remove_aliased_rctl(PT_MAXSHMMEM
, ALIAS_MAXSHMMEM
);
3834 remove_aliased_rctl(PT_MAXSHMIDS
, ALIAS_MAXSHMIDS
);
3837 remove_aliased_rctl(PT_MAXMSGIDS
, ALIAS_MAXMSGIDS
);
3840 remove_aliased_rctl(PT_MAXSEMIDS
, ALIAS_MAXSEMIDS
);
3843 remove_aliased_rctl(PT_SHARES
, ALIAS_SHARES
);
3846 if ((err
= zonecfg_set_hostid(handle
, NULL
)) != Z_OK
)
3847 z_cmd_rt_perror(CMD_CLEAR
, RT_HOSTID
, err
, B_TRUE
);
3849 need_to_commit
= B_TRUE
;
3852 if ((err
= zonecfg_set_fs_allowed(handle
, NULL
)) != Z_OK
)
3853 z_cmd_rt_perror(CMD_CLEAR
, RT_FS_ALLOWED
, err
, B_TRUE
);
3855 need_to_commit
= B_TRUE
;
3858 zone_perror(pt_to_str(type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
3859 long_usage(CMD_CLEAR
, B_TRUE
);
3860 usage(B_FALSE
, HELP_PROPS
);
3866 clear_func(cmd_t
*cmd
)
3868 if (zone_is_read_only(CMD_CLEAR
))
3871 assert(cmd
!= NULL
);
3874 if (gz_invalid_property(cmd
->cmd_res_type
)) {
3875 zerr(gettext("%s is not a valid property for the "
3876 "global zone."), pt_to_str(cmd
->cmd_res_type
));
3883 clear_property(cmd
);
3888 select_func(cmd_t
*cmd
)
3894 if (zone_is_read_only(CMD_SELECT
))
3897 assert(cmd
!= NULL
);
3900 global_scope
= B_FALSE
;
3901 resource_scope
= cmd
->cmd_res_type
;
3902 end_op
= CMD_SELECT
;
3904 scope_usage(CMD_SELECT
);
3908 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3909 long_usage(CMD_SELECT
, B_TRUE
);
3913 if (initialize(B_TRUE
) != Z_OK
)
3918 if ((err
= fill_in_fstab(cmd
, &old_fstab
, B_FALSE
)) != Z_OK
) {
3919 z_cmd_rt_perror(CMD_SELECT
, RT_FS
, err
, B_TRUE
);
3920 global_scope
= B_TRUE
;
3922 bcopy(&old_fstab
, &in_progress_fstab
,
3923 sizeof (struct zone_fstab
));
3926 if ((err
= fill_in_nwiftab(cmd
, &old_nwiftab
, B_FALSE
))
3928 z_cmd_rt_perror(CMD_SELECT
, RT_NET
, err
, B_TRUE
);
3929 global_scope
= B_TRUE
;
3931 bcopy(&old_nwiftab
, &in_progress_nwiftab
,
3932 sizeof (struct zone_nwiftab
));
3935 if ((err
= fill_in_devtab(cmd
, &old_devtab
, B_FALSE
)) != Z_OK
) {
3936 z_cmd_rt_perror(CMD_SELECT
, RT_DEVICE
, err
, B_TRUE
);
3937 global_scope
= B_TRUE
;
3939 bcopy(&old_devtab
, &in_progress_devtab
,
3940 sizeof (struct zone_devtab
));
3943 if ((err
= fill_in_rctltab(cmd
, &old_rctltab
, B_FALSE
))
3945 z_cmd_rt_perror(CMD_SELECT
, RT_RCTL
, err
, B_TRUE
);
3946 global_scope
= B_TRUE
;
3948 bcopy(&old_rctltab
, &in_progress_rctltab
,
3949 sizeof (struct zone_rctltab
));
3952 if ((err
= fill_in_attrtab(cmd
, &old_attrtab
, B_FALSE
))
3954 z_cmd_rt_perror(CMD_SELECT
, RT_ATTR
, err
, B_TRUE
);
3955 global_scope
= B_TRUE
;
3957 bcopy(&old_attrtab
, &in_progress_attrtab
,
3958 sizeof (struct zone_attrtab
));
3961 if ((err
= fill_in_dstab(cmd
, &old_dstab
, B_FALSE
)) != Z_OK
) {
3962 z_cmd_rt_perror(CMD_SELECT
, RT_DATASET
, err
, B_TRUE
);
3963 global_scope
= B_TRUE
;
3965 bcopy(&old_dstab
, &in_progress_dstab
,
3966 sizeof (struct zone_dstab
));
3969 if ((err
= zonecfg_lookup_pset(handle
, &old_psettab
)) != Z_OK
) {
3970 z_cmd_rt_perror(CMD_SELECT
, RT_DCPU
, err
, B_TRUE
);
3971 global_scope
= B_TRUE
;
3973 bcopy(&old_psettab
, &in_progress_psettab
,
3974 sizeof (struct zone_psettab
));
3977 if ((err
= zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
))
3979 z_cmd_rt_perror(CMD_SELECT
, RT_PCAP
, err
, B_TRUE
);
3980 global_scope
= B_TRUE
;
3984 /* if none of these exist, there is no resource to select */
3985 if ((res
= zonecfg_lookup_mcap(handle
, &old_mcaptab
)) != Z_OK
&&
3986 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &limit
)
3988 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
, &limit
)
3990 z_cmd_rt_perror(CMD_SELECT
, RT_MCAP
, Z_NO_RESOURCE_TYPE
,
3992 global_scope
= B_TRUE
;
3995 bcopy(&old_mcaptab
, &in_progress_mcaptab
,
3996 sizeof (struct zone_mcaptab
));
3998 bzero(&in_progress_mcaptab
,
3999 sizeof (in_progress_mcaptab
));
4002 if ((err
= fill_in_admintab(cmd
, &old_admintab
, B_FALSE
))
4004 z_cmd_rt_perror(CMD_SELECT
, RT_ADMIN
, err
,
4006 global_scope
= B_TRUE
;
4008 bcopy(&old_admintab
, &in_progress_admintab
,
4009 sizeof (struct zone_admintab
));
4012 if ((err
= fill_in_secflagstab(cmd
, &old_secflagstab
, B_FALSE
))
4014 z_cmd_rt_perror(CMD_SELECT
, RT_SECFLAGS
, err
,
4016 global_scope
= B_TRUE
;
4018 bcopy(&old_secflagstab
, &in_progress_secflagstab
,
4019 sizeof (struct zone_secflagstab
));
4022 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
4023 long_usage(CMD_SELECT
, B_TRUE
);
4024 usage(B_FALSE
, HELP_RESOURCES
);
4030 * Network "addresses" can be one of the following forms:
4032 * <IPv4 address>/<prefix length>
4033 * <IPv6 address>/<prefix length>
4035 * <host name>/<prefix length>
4036 * In other words, the "/" followed by a prefix length is allowed but not
4037 * required for IPv4 addresses and host names, and required for IPv6 addresses.
4038 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
4039 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
4040 * Host names must start with an alpha-numeric character, and all subsequent
4041 * characters must be either alpha-numeric or "-".
4043 * In some cases, e.g., the nexthop for the defrouter, the context indicates
4044 * that this is the IPV4_ABITS or IPV6_ABITS netmask, in which case we don't
4045 * require the /<prefix length> (and should ignore it if provided).
4049 validate_net_address_syntax(char *address
, boolean_t ishost
)
4051 char *slashp
, part1
[MAXHOSTNAMELEN
];
4052 struct in6_addr in6
;
4057 * Copy the part before any '/' into part1 or copy the whole
4058 * thing if there is no '/'.
4060 if ((slashp
= strchr(address
, '/')) != NULL
) {
4062 (void) strlcpy(part1
, address
, sizeof (part1
));
4064 prefixlen
= atoi(++slashp
);
4066 (void) strlcpy(part1
, address
, sizeof (part1
));
4069 if (ishost
&& slashp
!= NULL
) {
4070 zerr(gettext("Warning: prefix length in %s is not required and "
4071 "will be ignored. The default host-prefix length "
4072 "will be used"), address
);
4076 if (inet_pton(AF_INET6
, part1
, &in6
) == 1) {
4078 prefixlen
= IPV6_ABITS
;
4079 } else if (slashp
== NULL
) {
4080 zerr(gettext("%s: IPv6 addresses "
4081 "require /prefix-length suffix."), address
);
4084 if (prefixlen
< 0 || prefixlen
> 128) {
4085 zerr(gettext("%s: IPv6 address "
4086 "prefix lengths must be 0 - 128."), address
);
4092 /* At this point, any /prefix must be for IPv4. */
4094 prefixlen
= IPV4_ABITS
;
4095 else if (slashp
!= NULL
) {
4096 if (prefixlen
< 0 || prefixlen
> 32) {
4097 zerr(gettext("%s: IPv4 address "
4098 "prefix lengths must be 0 - 32."), address
);
4103 if (inet_pton(AF_INET
, part1
, &in4
) == 1)
4106 /* address may also be a host name */
4107 if (!isalnum(part1
[0])) {
4108 zerr(gettext("%s: bogus host name or network address syntax"),
4111 usage(B_FALSE
, HELP_NETADDR
);
4114 for (i
= 1; part1
[i
]; i
++)
4115 if (!isalnum(part1
[i
]) && part1
[i
] != '-' && part1
[i
] != '.') {
4116 zerr(gettext("%s: bogus host name or "
4117 "network address syntax"), part1
);
4119 usage(B_FALSE
, HELP_NETADDR
);
4126 validate_net_physical_syntax(const char *ifname
)
4128 ifspec_t ifnameprop
;
4129 zone_iptype_t iptype
;
4131 if (zonecfg_get_iptype(handle
, &iptype
) != Z_OK
) {
4132 zerr(gettext("zone configuration has an invalid or nonexistent "
4133 "ip-type property"));
4138 if (ifparse_ifspec(ifname
, &ifnameprop
) == B_FALSE
) {
4139 zerr(gettext("%s: invalid physical interface name"),
4143 if (ifnameprop
.ifsp_lunvalid
) {
4144 zerr(gettext("%s: LUNs not allowed in physical "
4145 "interface names"), ifname
);
4150 if (dladm_valid_linkname(ifname
) == B_FALSE
) {
4151 if (strchr(ifname
, ':') != NULL
)
4152 zerr(gettext("%s: physical interface name "
4153 "required; logical interface name not "
4154 "allowed"), ifname
);
4156 zerr(gettext("%s: invalid physical interface "
4166 valid_fs_type(const char *type
)
4169 * Is this a valid path component?
4171 if (strlen(type
) + 1 > MAXNAMELEN
)
4174 * Make sure a bad value for "type" doesn't make
4175 * /usr/lib/fs/<type>/mount turn into something else.
4177 if (strchr(type
, '/') != NULL
|| type
[0] == '\0' ||
4178 strcmp(type
, ".") == 0 || strcmp(type
, "..") == 0)
4181 * More detailed verification happens later by zoneadm(1m).
4190 char brand
[MAXNAMELEN
];
4193 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) != Z_OK
) {
4194 zerr("%s: %s\n", zone
, gettext("could not get zone brand"));
4197 if ((bh
= brand_open(brand
)) == NULL
) {
4198 zerr("%s: %s\n", zone
, gettext("unknown brand."));
4201 ret
= brand_allow_exclusive_ip(bh
);
4204 zerr(gettext("%s cannot be '%s' when %s is '%s'."),
4205 pt_to_str(PT_IPTYPE
), "exclusive",
4206 pt_to_str(PT_BRAND
), brand
);
4211 set_aliased_rctl(char *alias
, int prop_type
, char *s
)
4217 if (global_zone
&& strcmp(alias
, ALIAS_SHARES
) != 0)
4218 zerr(gettext("WARNING: Setting a global zone resource "
4219 "control too low could deny\nservice "
4220 "to even the root user; "
4221 "this could render the system impossible\n"
4222 "to administer. Please use caution."));
4224 /* convert memory based properties */
4225 if (prop_type
== PT_MAXSHMMEM
) {
4226 if (!zonecfg_valid_memlimit(s
, &limit
)) {
4227 zerr(gettext("A non-negative number with a required "
4228 "scale suffix (K, M, G or T) was expected\nhere."));
4233 (void) snprintf(tmp
, sizeof (tmp
), "%llu", limit
);
4237 if (!zonecfg_aliased_rctl_ok(handle
, alias
)) {
4238 zone_perror(pt_to_str(prop_type
), Z_ALIAS_DISALLOW
, B_FALSE
);
4240 } else if (!zonecfg_valid_alias_limit(alias
, s
, &limit
)) {
4241 zerr(gettext("%s property is out of range."),
4242 pt_to_str(prop_type
));
4244 } else if ((err
= zonecfg_set_aliased_rctl(handle
, alias
, limit
))
4246 zone_perror(zone
, err
, B_TRUE
);
4249 need_to_commit
= B_TRUE
;
4254 set_in_progress_nwiftab_address(char *prop_id
, int prop_type
)
4256 if (prop_type
== PT_ADDRESS
) {
4257 (void) strlcpy(in_progress_nwiftab
.zone_nwif_address
, prop_id
,
4258 sizeof (in_progress_nwiftab
.zone_nwif_address
));
4260 assert(prop_type
== PT_ALLOWED_ADDRESS
);
4261 (void) strlcpy(in_progress_nwiftab
.zone_nwif_allowed_address
,
4263 sizeof (in_progress_nwiftab
.zone_nwif_allowed_address
));
4268 set_func(cmd_t
*cmd
)
4271 int arg
, err
, res_type
, prop_type
;
4272 property_value_ptr_t pp
;
4274 zone_iptype_t iptype
;
4275 boolean_t force_set
= B_FALSE
;
4276 size_t physmem_size
= sizeof (in_progress_mcaptab
.zone_physmem_cap
);
4277 uint64_t mem_cap
, mem_limit
;
4280 struct zone_psettab tmp_psettab
;
4281 boolean_t arg_err
= B_FALSE
;
4283 if (zone_is_read_only(CMD_SET
))
4286 assert(cmd
!= NULL
);
4288 optind
= opterr
= 0;
4289 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "F")) != EOF
) {
4296 longer_usage(CMD_SET
);
4298 short_usage(CMD_SET
);
4306 prop_type
= cmd
->cmd_prop_name
[0];
4308 if (gz_invalid_property(prop_type
)) {
4309 zerr(gettext("%s is not a valid property for the "
4310 "global zone."), pt_to_str(prop_type
));
4315 if (prop_type
== PT_ZONENAME
) {
4316 res_type
= RT_ZONENAME
;
4317 } else if (prop_type
== PT_ZONEPATH
) {
4318 res_type
= RT_ZONEPATH
;
4319 } else if (prop_type
== PT_AUTOBOOT
) {
4320 res_type
= RT_AUTOBOOT
;
4321 } else if (prop_type
== PT_BRAND
) {
4322 res_type
= RT_BRAND
;
4323 } else if (prop_type
== PT_POOL
) {
4325 } else if (prop_type
== PT_LIMITPRIV
) {
4326 res_type
= RT_LIMITPRIV
;
4327 } else if (prop_type
== PT_BOOTARGS
) {
4328 res_type
= RT_BOOTARGS
;
4329 } else if (prop_type
== PT_SCHED
) {
4330 res_type
= RT_SCHED
;
4331 } else if (prop_type
== PT_IPTYPE
) {
4332 res_type
= RT_IPTYPE
;
4333 } else if (prop_type
== PT_MAXLWPS
) {
4334 res_type
= RT_MAXLWPS
;
4335 } else if (prop_type
== PT_MAXPROCS
) {
4336 res_type
= RT_MAXPROCS
;
4337 } else if (prop_type
== PT_MAXSHMMEM
) {
4338 res_type
= RT_MAXSHMMEM
;
4339 } else if (prop_type
== PT_MAXSHMIDS
) {
4340 res_type
= RT_MAXSHMIDS
;
4341 } else if (prop_type
== PT_MAXMSGIDS
) {
4342 res_type
= RT_MAXMSGIDS
;
4343 } else if (prop_type
== PT_MAXSEMIDS
) {
4344 res_type
= RT_MAXSEMIDS
;
4345 } else if (prop_type
== PT_SHARES
) {
4346 res_type
= RT_SHARES
;
4347 } else if (prop_type
== PT_HOSTID
) {
4348 res_type
= RT_HOSTID
;
4349 } else if (prop_type
== PT_FS_ALLOWED
) {
4350 res_type
= RT_FS_ALLOWED
;
4352 zerr(gettext("Cannot set a resource-specific property "
4353 "from the global scope."));
4358 res_type
= resource_scope
;
4362 if (res_type
!= RT_ZONEPATH
) {
4363 zerr(gettext("Only zonepath setting can be forced."));
4367 if (!zonecfg_in_alt_root()) {
4368 zerr(gettext("Zonepath is changeable only in an "
4369 "alternate root."));
4375 pp
= cmd
->cmd_property_ptr
[0];
4377 * A nasty expression but not that complicated:
4378 * 1. fs options are simple or list (tested below)
4379 * 2. rctl value's are complex or list (tested below)
4380 * Anything else should be simple.
4382 if (!(res_type
== RT_FS
&& prop_type
== PT_OPTIONS
) &&
4383 !(res_type
== RT_RCTL
&& prop_type
== PT_VALUE
) &&
4384 (pp
->pv_type
!= PROP_VAL_SIMPLE
||
4385 (prop_id
= pp
->pv_simple
) == NULL
)) {
4386 zerr(gettext("A %s value was expected here."),
4387 pvt_to_str(PROP_VAL_SIMPLE
));
4391 if (prop_type
== PT_UNKNOWN
) {
4392 long_usage(CMD_SET
, B_TRUE
);
4397 * Special case: the user can change the zone name prior to 'create';
4398 * if the zone already exists, we fall through letting initialize()
4399 * and the rest of the logic run.
4401 if (res_type
== RT_ZONENAME
&& got_handle
== B_FALSE
&&
4402 !state_atleast(ZONE_STATE_CONFIGURED
)) {
4403 if ((err
= zonecfg_validate_zonename(prop_id
)) != Z_OK
) {
4404 zone_perror(prop_id
, err
, B_TRUE
);
4405 usage(B_FALSE
, HELP_SYNTAX
);
4408 (void) strlcpy(zone
, prop_id
, sizeof (zone
));
4412 if (initialize(B_TRUE
) != Z_OK
)
4417 if ((err
= zonecfg_set_name(handle
, prop_id
)) != Z_OK
) {
4419 * Use prop_id instead of 'zone' here, since we're
4420 * reporting a problem about the *new* zonename.
4422 zone_perror(prop_id
, err
, B_TRUE
);
4423 usage(B_FALSE
, HELP_SYNTAX
);
4425 need_to_commit
= B_TRUE
;
4426 (void) strlcpy(zone
, prop_id
, sizeof (zone
));
4430 if (!force_set
&& state_atleast(ZONE_STATE_INSTALLED
)) {
4431 zerr(gettext("Zone %s already installed; %s %s not "
4432 "allowed."), zone
, cmd_to_str(CMD_SET
),
4433 rt_to_str(RT_ZONEPATH
));
4436 if (validate_zonepath_syntax(prop_id
) != Z_OK
) {
4440 if ((err
= zonecfg_set_zonepath(handle
, prop_id
)) != Z_OK
)
4441 zone_perror(zone
, err
, B_TRUE
);
4443 need_to_commit
= B_TRUE
;
4446 if (state_atleast(ZONE_STATE_INSTALLED
)) {
4447 zerr(gettext("Zone %s already installed; %s %s not "
4448 "allowed."), zone
, cmd_to_str(CMD_SET
),
4449 rt_to_str(RT_BRAND
));
4452 if ((err
= zonecfg_set_brand(handle
, prop_id
)) != Z_OK
)
4453 zone_perror(zone
, err
, B_TRUE
);
4455 need_to_commit
= B_TRUE
;
4458 if (strcmp(prop_id
, "true") == 0) {
4460 } else if (strcmp(prop_id
, "false") == 0) {
4463 zerr(gettext("%s value must be '%s' or '%s'."),
4464 pt_to_str(PT_AUTOBOOT
), "true", "false");
4468 if ((err
= zonecfg_set_autoboot(handle
, autoboot
)) != Z_OK
)
4469 zone_perror(zone
, err
, B_TRUE
);
4471 need_to_commit
= B_TRUE
;
4474 /* don't allow use of the reserved temporary pool names */
4475 if (strncmp("SUNW", prop_id
, 4) == 0) {
4476 zerr(gettext("pool names starting with SUNW are "
4482 /* can't set pool if dedicated-cpu exists */
4483 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
4484 zerr(gettext("The %s resource already exists. "
4485 "A persistent pool is incompatible\nwith the %s "
4486 "resource."), rt_to_str(RT_DCPU
),
4487 rt_to_str(RT_DCPU
));
4492 if ((err
= zonecfg_set_pool(handle
, prop_id
)) != Z_OK
)
4493 zone_perror(zone
, err
, B_TRUE
);
4495 need_to_commit
= B_TRUE
;
4498 if ((err
= zonecfg_set_limitpriv(handle
, prop_id
)) != Z_OK
)
4499 zone_perror(zone
, err
, B_TRUE
);
4501 need_to_commit
= B_TRUE
;
4504 if ((err
= zonecfg_set_bootargs(handle
, prop_id
)) != Z_OK
)
4505 zone_perror(zone
, err
, B_TRUE
);
4507 need_to_commit
= B_TRUE
;
4510 if ((err
= zonecfg_set_sched(handle
, prop_id
)) != Z_OK
)
4511 zone_perror(zone
, err
, B_TRUE
);
4513 need_to_commit
= B_TRUE
;
4516 if (strcmp(prop_id
, "shared") == 0) {
4518 } else if (strcmp(prop_id
, "exclusive") == 0) {
4519 iptype
= ZS_EXCLUSIVE
;
4521 zerr(gettext("%s value must be '%s' or '%s'."),
4522 pt_to_str(PT_IPTYPE
), "shared", "exclusive");
4526 if (iptype
== ZS_EXCLUSIVE
&& !allow_exclusive()) {
4530 if ((err
= zonecfg_set_iptype(handle
, iptype
)) != Z_OK
)
4531 zone_perror(zone
, err
, B_TRUE
);
4533 need_to_commit
= B_TRUE
;
4536 set_aliased_rctl(ALIAS_MAXLWPS
, prop_type
, prop_id
);
4539 set_aliased_rctl(ALIAS_MAXPROCS
, prop_type
, prop_id
);
4542 set_aliased_rctl(ALIAS_MAXSHMMEM
, prop_type
, prop_id
);
4545 set_aliased_rctl(ALIAS_MAXSHMIDS
, prop_type
, prop_id
);
4548 set_aliased_rctl(ALIAS_MAXMSGIDS
, prop_type
, prop_id
);
4551 set_aliased_rctl(ALIAS_MAXSEMIDS
, prop_type
, prop_id
);
4554 set_aliased_rctl(ALIAS_SHARES
, prop_type
, prop_id
);
4557 if ((err
= zonecfg_set_hostid(handle
, prop_id
)) != Z_OK
) {
4558 if (err
== Z_TOO_BIG
) {
4559 zerr(gettext("hostid string is too large: %s"),
4563 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
4567 need_to_commit
= B_TRUE
;
4570 if ((err
= zonecfg_set_fs_allowed(handle
, prop_id
)) != Z_OK
)
4571 zone_perror(zone
, err
, B_TRUE
);
4573 need_to_commit
= B_TRUE
;
4576 switch (prop_type
) {
4578 (void) strlcpy(in_progress_fstab
.zone_fs_dir
, prop_id
,
4579 sizeof (in_progress_fstab
.zone_fs_dir
));
4582 (void) strlcpy(in_progress_fstab
.zone_fs_special
,
4584 sizeof (in_progress_fstab
.zone_fs_special
));
4587 (void) strlcpy(in_progress_fstab
.zone_fs_raw
,
4588 prop_id
, sizeof (in_progress_fstab
.zone_fs_raw
));
4591 if (!valid_fs_type(prop_id
)) {
4592 zerr(gettext("\"%s\" is not a valid %s."),
4593 prop_id
, pt_to_str(PT_TYPE
));
4597 (void) strlcpy(in_progress_fstab
.zone_fs_type
, prop_id
,
4598 sizeof (in_progress_fstab
.zone_fs_type
));
4601 if (pp
->pv_type
!= PROP_VAL_SIMPLE
&&
4602 pp
->pv_type
!= PROP_VAL_LIST
) {
4603 zerr(gettext("A %s or %s value was expected "
4604 "here."), pvt_to_str(PROP_VAL_SIMPLE
),
4605 pvt_to_str(PROP_VAL_LIST
));
4609 zonecfg_free_fs_option_list(
4610 in_progress_fstab
.zone_fs_options
);
4611 in_progress_fstab
.zone_fs_options
= NULL
;
4612 if (!(pp
->pv_type
== PROP_VAL_LIST
&&
4613 pp
->pv_list
== NULL
))
4619 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4620 long_usage(CMD_SET
, B_TRUE
);
4621 usage(B_FALSE
, HELP_PROPS
);
4624 switch (prop_type
) {
4626 case PT_ALLOWED_ADDRESS
:
4627 if (validate_net_address_syntax(prop_id
, B_FALSE
)
4632 set_in_progress_nwiftab_address(prop_id
, prop_type
);
4635 if (validate_net_physical_syntax(prop_id
) != Z_OK
) {
4639 (void) strlcpy(in_progress_nwiftab
.zone_nwif_physical
,
4641 sizeof (in_progress_nwiftab
.zone_nwif_physical
));
4644 if (validate_net_address_syntax(prop_id
, B_TRUE
)
4649 (void) strlcpy(in_progress_nwiftab
.zone_nwif_defrouter
,
4651 sizeof (in_progress_nwiftab
.zone_nwif_defrouter
));
4654 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4656 long_usage(CMD_SET
, B_TRUE
);
4657 usage(B_FALSE
, HELP_PROPS
);
4662 switch (prop_type
) {
4664 (void) strlcpy(in_progress_devtab
.zone_dev_match
,
4666 sizeof (in_progress_devtab
.zone_dev_match
));
4669 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4671 long_usage(CMD_SET
, B_TRUE
);
4672 usage(B_FALSE
, HELP_PROPS
);
4677 switch (prop_type
) {
4679 if (!zonecfg_valid_rctlname(prop_id
)) {
4680 zerr(gettext("'%s' is not a valid zone %s "
4681 "name."), prop_id
, rt_to_str(RT_RCTL
));
4684 (void) strlcpy(in_progress_rctltab
.zone_rctl_name
,
4686 sizeof (in_progress_rctltab
.zone_rctl_name
));
4689 if (pp
->pv_type
!= PROP_VAL_COMPLEX
&&
4690 pp
->pv_type
!= PROP_VAL_LIST
) {
4691 zerr(gettext("A %s or %s value was expected "
4692 "here."), pvt_to_str(PROP_VAL_COMPLEX
),
4693 pvt_to_str(PROP_VAL_LIST
));
4697 zonecfg_free_rctl_value_list(
4698 in_progress_rctltab
.zone_rctl_valptr
);
4699 in_progress_rctltab
.zone_rctl_valptr
= NULL
;
4700 if (!(pp
->pv_type
== PROP_VAL_LIST
&&
4701 pp
->pv_list
== NULL
))
4705 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4707 long_usage(CMD_SET
, B_TRUE
);
4708 usage(B_FALSE
, HELP_PROPS
);
4713 switch (prop_type
) {
4715 (void) strlcpy(in_progress_attrtab
.zone_attr_name
,
4717 sizeof (in_progress_attrtab
.zone_attr_name
));
4720 (void) strlcpy(in_progress_attrtab
.zone_attr_type
,
4722 sizeof (in_progress_attrtab
.zone_attr_type
));
4725 (void) strlcpy(in_progress_attrtab
.zone_attr_value
,
4727 sizeof (in_progress_attrtab
.zone_attr_value
));
4730 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4732 long_usage(CMD_SET
, B_TRUE
);
4733 usage(B_FALSE
, HELP_PROPS
);
4738 switch (prop_type
) {
4740 (void) strlcpy(in_progress_dstab
.zone_dataset_name
,
4742 sizeof (in_progress_dstab
.zone_dataset_name
));
4747 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4748 long_usage(CMD_SET
, B_TRUE
);
4749 usage(B_FALSE
, HELP_PROPS
);
4752 switch (prop_type
) {
4757 if ((highp
= strchr(prop_id
, '-')) != NULL
)
4762 /* Make sure the input makes sense. */
4763 if (!zonecfg_valid_ncpus(lowp
, highp
)) {
4764 zerr(gettext("%s property is out of range."),
4765 pt_to_str(PT_NCPUS
));
4771 in_progress_psettab
.zone_ncpu_min
, lowp
,
4772 sizeof (in_progress_psettab
.zone_ncpu_min
));
4774 in_progress_psettab
.zone_ncpu_max
, highp
,
4775 sizeof (in_progress_psettab
.zone_ncpu_max
));
4778 /* Make sure the value makes sense. */
4779 if (!zonecfg_valid_importance(prop_id
)) {
4780 zerr(gettext("%s property is out of range."),
4781 pt_to_str(PT_IMPORTANCE
));
4786 (void) strlcpy(in_progress_psettab
.zone_importance
,
4788 sizeof (in_progress_psettab
.zone_importance
));
4793 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4794 long_usage(CMD_SET
, B_TRUE
);
4795 usage(B_FALSE
, HELP_PROPS
);
4798 if (prop_type
!= PT_NCPUS
) {
4799 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4801 long_usage(CMD_SET
, B_TRUE
);
4802 usage(B_FALSE
, HELP_PROPS
);
4807 * We already checked that an rctl alias is allowed in
4808 * the add_resource() function.
4811 if ((cap
= strtof(prop_id
, &unitp
)) <= 0 || *unitp
!= '\0' ||
4812 (int)(cap
* 100) < 1) {
4813 zerr(gettext("%s property is out of range."),
4814 pt_to_str(PT_NCPUS
));
4819 if ((err
= zonecfg_set_aliased_rctl(handle
, ALIAS_CPUCAP
,
4820 (int)(cap
* 100))) != Z_OK
)
4821 zone_perror(zone
, err
, B_TRUE
);
4823 need_to_commit
= B_TRUE
;
4826 switch (prop_type
) {
4828 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4829 zerr(gettext("A positive number with a "
4830 "required scale suffix (K, M, G or T) was "
4833 } else if (mem_cap
< ONE_MB
) {
4834 zerr(gettext("%s value is too small. It must "
4835 "be at least 1M."), pt_to_str(PT_PHYSICAL
));
4838 snprintf(in_progress_mcaptab
.zone_physmem_cap
,
4839 physmem_size
, "%llu", mem_cap
);
4844 * We have to check if an rctl is allowed here since
4845 * there might already be a rctl defined that blocks
4848 if (!zonecfg_aliased_rctl_ok(handle
, ALIAS_MAXSWAP
)) {
4849 zone_perror(pt_to_str(PT_MAXSWAP
),
4850 Z_ALIAS_DISALLOW
, B_FALSE
);
4856 mem_limit
= ONE_MB
* 100;
4858 mem_limit
= ONE_MB
* 50;
4860 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4861 zerr(gettext("A positive number with a "
4862 "required scale suffix (K, M, G or T) was "
4865 } else if (mem_cap
< mem_limit
) {
4868 (void) snprintf(buf
, sizeof (buf
), "%llu",
4870 bytes_to_units(buf
, buf
, sizeof (buf
));
4871 zerr(gettext("%s value is too small. It must "
4872 "be at least %s."), pt_to_str(PT_SWAP
),
4876 if ((err
= zonecfg_set_aliased_rctl(handle
,
4877 ALIAS_MAXSWAP
, mem_cap
)) != Z_OK
)
4878 zone_perror(zone
, err
, B_TRUE
);
4880 need_to_commit
= B_TRUE
;
4885 * We have to check if an rctl is allowed here since
4886 * there might already be a rctl defined that blocks
4889 if (!zonecfg_aliased_rctl_ok(handle
,
4890 ALIAS_MAXLOCKEDMEM
)) {
4891 zone_perror(pt_to_str(PT_LOCKED
),
4892 Z_ALIAS_DISALLOW
, B_FALSE
);
4897 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4898 zerr(gettext("A non-negative number with a "
4899 "required scale suffix (K, M, G or T) was "
4900 "expected\nhere."));
4903 if ((err
= zonecfg_set_aliased_rctl(handle
,
4904 ALIAS_MAXLOCKEDMEM
, mem_cap
)) != Z_OK
)
4905 zone_perror(zone
, err
, B_TRUE
);
4907 need_to_commit
= B_TRUE
;
4911 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4913 long_usage(CMD_SET
, B_TRUE
);
4914 usage(B_FALSE
, HELP_PROPS
);
4919 switch (prop_type
) {
4921 (void) strlcpy(in_progress_admintab
.zone_admin_user
,
4923 sizeof (in_progress_admintab
.zone_admin_user
));
4926 (void) strlcpy(in_progress_admintab
.zone_admin_auths
,
4928 sizeof (in_progress_admintab
.zone_admin_auths
));
4931 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4933 long_usage(CMD_SET
, B_TRUE
);
4934 usage(B_FALSE
, HELP_PROPS
);
4940 switch (prop_type
) {
4942 propstr
= in_progress_secflagstab
.zone_secflags_default
;
4945 propstr
= in_progress_secflagstab
.zone_secflags_upper
;
4948 propstr
= in_progress_secflagstab
.zone_secflags_lower
;
4951 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4953 long_usage(CMD_SET
, B_TRUE
);
4954 usage(B_FALSE
, HELP_PROPS
);
4957 (void) strlcpy(propstr
, prop_id
, ZONECFG_SECFLAGS_MAX
);
4961 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
4962 long_usage(CMD_SET
, B_TRUE
);
4963 usage(B_FALSE
, HELP_RESOURCES
);
4969 output_prop(FILE *fp
, int pnum
, char *pval
, boolean_t print_notspec
)
4973 if (*pval
!= '\0') {
4974 qstr
= quoteit(pval
);
4975 if (pnum
== PT_SWAP
|| pnum
== PT_LOCKED
)
4976 (void) fprintf(fp
, "\t[%s: %s]\n", pt_to_str(pnum
),
4979 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(pnum
), qstr
);
4981 } else if (print_notspec
)
4982 (void) fprintf(fp
, gettext("\t%s not specified\n"),
4987 info_zonename(zone_dochandle_t handle
, FILE *fp
)
4989 char zonename
[ZONENAME_MAX
];
4991 if (zonecfg_get_name(handle
, zonename
, sizeof (zonename
)) == Z_OK
)
4992 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_ZONENAME
),
4995 (void) fprintf(fp
, gettext("%s not specified\n"),
4996 pt_to_str(PT_ZONENAME
));
5000 info_zonepath(zone_dochandle_t handle
, FILE *fp
)
5002 char zonepath
[MAXPATHLEN
];
5004 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) == Z_OK
)
5005 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_ZONEPATH
),
5008 (void) fprintf(fp
, gettext("%s not specified\n"),
5009 pt_to_str(PT_ZONEPATH
));
5014 info_brand(zone_dochandle_t handle
, FILE *fp
)
5016 char brand
[MAXNAMELEN
];
5018 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) == Z_OK
)
5019 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_BRAND
),
5022 (void) fprintf(fp
, "%s %s\n", pt_to_str(PT_BRAND
),
5023 gettext("not specified"));
5027 info_autoboot(zone_dochandle_t handle
, FILE *fp
)
5032 if ((err
= zonecfg_get_autoboot(handle
, &autoboot
)) == Z_OK
)
5033 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_AUTOBOOT
),
5034 autoboot
? "true" : "false");
5036 zone_perror(zone
, err
, B_TRUE
);
5040 info_pool(zone_dochandle_t handle
, FILE *fp
)
5042 char pool
[MAXNAMELEN
];
5045 if ((err
= zonecfg_get_pool(handle
, pool
, sizeof (pool
))) == Z_OK
)
5046 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_POOL
), pool
);
5048 zone_perror(zone
, err
, B_TRUE
);
5052 info_limitpriv(zone_dochandle_t handle
, FILE *fp
)
5057 if ((err
= zonecfg_get_limitpriv(handle
, &limitpriv
)) == Z_OK
) {
5058 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_LIMITPRIV
),
5062 zone_perror(zone
, err
, B_TRUE
);
5067 info_bootargs(zone_dochandle_t handle
, FILE *fp
)
5069 char bootargs
[BOOTARGS_MAX
];
5072 if ((err
= zonecfg_get_bootargs(handle
, bootargs
,
5073 sizeof (bootargs
))) == Z_OK
) {
5074 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_BOOTARGS
),
5077 zone_perror(zone
, err
, B_TRUE
);
5082 info_sched(zone_dochandle_t handle
, FILE *fp
)
5084 char sched
[MAXNAMELEN
];
5087 if ((err
= zonecfg_get_sched_class(handle
, sched
, sizeof (sched
)))
5089 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_SCHED
), sched
);
5091 zone_perror(zone
, err
, B_TRUE
);
5096 info_iptype(zone_dochandle_t handle
, FILE *fp
)
5098 zone_iptype_t iptype
;
5101 if ((err
= zonecfg_get_iptype(handle
, &iptype
)) == Z_OK
) {
5104 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_IPTYPE
),
5108 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_IPTYPE
),
5113 zone_perror(zone
, err
, B_TRUE
);
5118 info_hostid(zone_dochandle_t handle
, FILE *fp
)
5120 char hostidp
[HW_HOSTID_LEN
];
5123 if ((err
= zonecfg_get_hostid(handle
, hostidp
,
5124 sizeof (hostidp
))) == Z_OK
) {
5125 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_HOSTID
), hostidp
);
5126 } else if (err
== Z_BAD_PROPERTY
) {
5127 (void) fprintf(fp
, "%s: \n", pt_to_str(PT_HOSTID
));
5129 zone_perror(zone
, err
, B_TRUE
);
5134 info_fs_allowed(zone_dochandle_t handle
, FILE *fp
)
5136 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
5139 if ((err
= zonecfg_get_fs_allowed(handle
, fsallowedp
,
5140 sizeof (fsallowedp
))) == Z_OK
) {
5141 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_FS_ALLOWED
),
5143 } else if (err
== Z_BAD_PROPERTY
) {
5144 (void) fprintf(fp
, "%s: \n", pt_to_str(PT_FS_ALLOWED
));
5146 zone_perror(zone
, err
, B_TRUE
);
5151 output_fs(FILE *fp
, struct zone_fstab
*fstab
)
5155 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_FS
));
5156 output_prop(fp
, PT_DIR
, fstab
->zone_fs_dir
, B_TRUE
);
5157 output_prop(fp
, PT_SPECIAL
, fstab
->zone_fs_special
, B_TRUE
);
5158 output_prop(fp
, PT_RAW
, fstab
->zone_fs_raw
, B_TRUE
);
5159 output_prop(fp
, PT_TYPE
, fstab
->zone_fs_type
, B_TRUE
);
5160 (void) fprintf(fp
, "\t%s: [", pt_to_str(PT_OPTIONS
));
5161 for (this = fstab
->zone_fs_options
; this != NULL
;
5162 this = this->zone_fsopt_next
) {
5163 if (strchr(this->zone_fsopt_opt
, '='))
5164 (void) fprintf(fp
, "\"%s\"", this->zone_fsopt_opt
);
5166 (void) fprintf(fp
, "%s", this->zone_fsopt_opt
);
5167 if (this->zone_fsopt_next
!= NULL
)
5168 (void) fprintf(fp
, ",");
5170 (void) fprintf(fp
, "]\n");
5174 info_fs(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5176 struct zone_fstab lookup
, user
;
5177 boolean_t output
= B_FALSE
;
5179 if (zonecfg_setfsent(handle
) != Z_OK
)
5181 while (zonecfg_getfsent(handle
, &lookup
) == Z_OK
) {
5182 if (cmd
->cmd_prop_nv_pairs
== 0) {
5183 output_fs(fp
, &lookup
);
5186 if (fill_in_fstab(cmd
, &user
, B_TRUE
) != Z_OK
)
5188 if (strlen(user
.zone_fs_dir
) > 0 &&
5189 strcmp(user
.zone_fs_dir
, lookup
.zone_fs_dir
) != 0)
5190 goto loopend
; /* no match */
5191 if (strlen(user
.zone_fs_special
) > 0 &&
5192 strcmp(user
.zone_fs_special
, lookup
.zone_fs_special
) != 0)
5193 goto loopend
; /* no match */
5194 if (strlen(user
.zone_fs_type
) > 0 &&
5195 strcmp(user
.zone_fs_type
, lookup
.zone_fs_type
) != 0)
5196 goto loopend
; /* no match */
5197 output_fs(fp
, &lookup
);
5200 zonecfg_free_fs_option_list(lookup
.zone_fs_options
);
5202 (void) zonecfg_endfsent(handle
);
5204 * If a property n/v pair was specified, warn the user if there was
5205 * nothing to output.
5207 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5208 (void) printf(gettext("No such %s resource.\n"),
5213 output_net(FILE *fp
, struct zone_nwiftab
*nwiftab
)
5215 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_NET
));
5216 output_prop(fp
, PT_ADDRESS
, nwiftab
->zone_nwif_address
, B_TRUE
);
5217 output_prop(fp
, PT_ALLOWED_ADDRESS
,
5218 nwiftab
->zone_nwif_allowed_address
, B_TRUE
);
5219 output_prop(fp
, PT_PHYSICAL
, nwiftab
->zone_nwif_physical
, B_TRUE
);
5220 output_prop(fp
, PT_DEFROUTER
, nwiftab
->zone_nwif_defrouter
, B_TRUE
);
5224 info_net(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5226 struct zone_nwiftab lookup
, user
;
5227 boolean_t output
= B_FALSE
;
5229 if (zonecfg_setnwifent(handle
) != Z_OK
)
5231 while (zonecfg_getnwifent(handle
, &lookup
) == Z_OK
) {
5232 if (cmd
->cmd_prop_nv_pairs
== 0) {
5233 output_net(fp
, &lookup
);
5236 if (fill_in_nwiftab(cmd
, &user
, B_TRUE
) != Z_OK
)
5238 if (strlen(user
.zone_nwif_physical
) > 0 &&
5239 strcmp(user
.zone_nwif_physical
,
5240 lookup
.zone_nwif_physical
) != 0)
5241 continue; /* no match */
5242 /* If present make sure it matches */
5243 if (strlen(user
.zone_nwif_address
) > 0 &&
5244 !zonecfg_same_net_address(user
.zone_nwif_address
,
5245 lookup
.zone_nwif_address
))
5246 continue; /* no match */
5247 output_net(fp
, &lookup
);
5250 (void) zonecfg_endnwifent(handle
);
5252 * If a property n/v pair was specified, warn the user if there was
5253 * nothing to output.
5255 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5256 (void) printf(gettext("No such %s resource.\n"),
5261 output_dev(FILE *fp
, struct zone_devtab
*devtab
)
5263 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DEVICE
));
5264 output_prop(fp
, PT_MATCH
, devtab
->zone_dev_match
, B_TRUE
);
5268 info_dev(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5270 struct zone_devtab lookup
, user
;
5271 boolean_t output
= B_FALSE
;
5273 if (zonecfg_setdevent(handle
) != Z_OK
)
5275 while (zonecfg_getdevent(handle
, &lookup
) == Z_OK
) {
5276 if (cmd
->cmd_prop_nv_pairs
== 0) {
5277 output_dev(fp
, &lookup
);
5280 if (fill_in_devtab(cmd
, &user
, B_TRUE
) != Z_OK
)
5282 if (strlen(user
.zone_dev_match
) > 0 &&
5283 strcmp(user
.zone_dev_match
, lookup
.zone_dev_match
) != 0)
5284 continue; /* no match */
5285 output_dev(fp
, &lookup
);
5288 (void) zonecfg_enddevent(handle
);
5290 * If a property n/v pair was specified, warn the user if there was
5291 * nothing to output.
5293 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5294 (void) printf(gettext("No such %s resource.\n"),
5295 rt_to_str(RT_DEVICE
));
5299 output_rctl(FILE *fp
, struct zone_rctltab
*rctltab
)
5301 struct zone_rctlvaltab
*valptr
;
5303 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_RCTL
));
5304 output_prop(fp
, PT_NAME
, rctltab
->zone_rctl_name
, B_TRUE
);
5305 for (valptr
= rctltab
->zone_rctl_valptr
; valptr
!= NULL
;
5306 valptr
= valptr
->zone_rctlval_next
) {
5307 fprintf(fp
, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
5308 pt_to_str(PT_VALUE
),
5309 pt_to_str(PT_PRIV
), valptr
->zone_rctlval_priv
,
5310 pt_to_str(PT_LIMIT
), valptr
->zone_rctlval_limit
,
5311 pt_to_str(PT_ACTION
), valptr
->zone_rctlval_action
);
5316 info_rctl(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5318 struct zone_rctltab lookup
, user
;
5319 boolean_t output
= B_FALSE
;
5321 if (zonecfg_setrctlent(handle
) != Z_OK
)
5323 while (zonecfg_getrctlent(handle
, &lookup
) == Z_OK
) {
5324 if (cmd
->cmd_prop_nv_pairs
== 0) {
5325 output_rctl(fp
, &lookup
);
5326 } else if (fill_in_rctltab(cmd
, &user
, B_TRUE
) == Z_OK
&&
5327 (strlen(user
.zone_rctl_name
) == 0 ||
5328 strcmp(user
.zone_rctl_name
, lookup
.zone_rctl_name
) == 0)) {
5329 output_rctl(fp
, &lookup
);
5332 zonecfg_free_rctl_value_list(lookup
.zone_rctl_valptr
);
5334 (void) zonecfg_endrctlent(handle
);
5336 * If a property n/v pair was specified, warn the user if there was
5337 * nothing to output.
5339 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5340 (void) printf(gettext("No such %s resource.\n"),
5341 rt_to_str(RT_RCTL
));
5345 output_attr(FILE *fp
, struct zone_attrtab
*attrtab
)
5347 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_ATTR
));
5348 output_prop(fp
, PT_NAME
, attrtab
->zone_attr_name
, B_TRUE
);
5349 output_prop(fp
, PT_TYPE
, attrtab
->zone_attr_type
, B_TRUE
);
5350 output_prop(fp
, PT_VALUE
, attrtab
->zone_attr_value
, B_TRUE
);
5354 info_attr(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5356 struct zone_attrtab lookup
, user
;
5357 boolean_t output
= B_FALSE
;
5359 if (zonecfg_setattrent(handle
) != Z_OK
)
5361 while (zonecfg_getattrent(handle
, &lookup
) == Z_OK
) {
5362 if (cmd
->cmd_prop_nv_pairs
== 0) {
5363 output_attr(fp
, &lookup
);
5366 if (fill_in_attrtab(cmd
, &user
, B_TRUE
) != Z_OK
)
5368 if (strlen(user
.zone_attr_name
) > 0 &&
5369 strcmp(user
.zone_attr_name
, lookup
.zone_attr_name
) != 0)
5370 continue; /* no match */
5371 if (strlen(user
.zone_attr_type
) > 0 &&
5372 strcmp(user
.zone_attr_type
, lookup
.zone_attr_type
) != 0)
5373 continue; /* no match */
5374 if (strlen(user
.zone_attr_value
) > 0 &&
5375 strcmp(user
.zone_attr_value
, lookup
.zone_attr_value
) != 0)
5376 continue; /* no match */
5377 output_attr(fp
, &lookup
);
5380 (void) zonecfg_endattrent(handle
);
5382 * If a property n/v pair was specified, warn the user if there was
5383 * nothing to output.
5385 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5386 (void) printf(gettext("No such %s resource.\n"),
5387 rt_to_str(RT_ATTR
));
5391 output_ds(FILE *fp
, struct zone_dstab
*dstab
)
5393 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DATASET
));
5394 output_prop(fp
, PT_NAME
, dstab
->zone_dataset_name
, B_TRUE
);
5398 info_ds(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5400 struct zone_dstab lookup
, user
;
5401 boolean_t output
= B_FALSE
;
5403 if (zonecfg_setdsent(handle
) != Z_OK
)
5405 while (zonecfg_getdsent(handle
, &lookup
) == Z_OK
) {
5406 if (cmd
->cmd_prop_nv_pairs
== 0) {
5407 output_ds(fp
, &lookup
);
5410 if (fill_in_dstab(cmd
, &user
, B_TRUE
) != Z_OK
)
5412 if (strlen(user
.zone_dataset_name
) > 0 &&
5413 strcmp(user
.zone_dataset_name
,
5414 lookup
.zone_dataset_name
) != 0)
5415 continue; /* no match */
5416 output_ds(fp
, &lookup
);
5419 (void) zonecfg_enddsent(handle
);
5421 * If a property n/v pair was specified, warn the user if there was
5422 * nothing to output.
5424 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5425 (void) printf(gettext("No such %s resource.\n"),
5426 rt_to_str(RT_DATASET
));
5430 output_pset(FILE *fp
, struct zone_psettab
*psettab
)
5432 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DCPU
));
5433 if (strcmp(psettab
->zone_ncpu_min
, psettab
->zone_ncpu_max
) == 0)
5434 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(PT_NCPUS
),
5435 psettab
->zone_ncpu_max
);
5437 (void) fprintf(fp
, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS
),
5438 psettab
->zone_ncpu_min
, psettab
->zone_ncpu_max
);
5439 if (psettab
->zone_importance
[0] != '\0')
5440 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE
),
5441 psettab
->zone_importance
);
5445 info_pset(zone_dochandle_t handle
, FILE *fp
)
5447 struct zone_psettab lookup
;
5449 if (zonecfg_getpsetent(handle
, &lookup
) == Z_OK
)
5450 output_pset(fp
, &lookup
);
5454 output_pcap(FILE *fp
)
5458 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &cap
) == Z_OK
) {
5459 float scaled
= (float)cap
/ 100;
5460 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_PCAP
));
5461 (void) fprintf(fp
, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS
),
5474 info_aliased_rctl(zone_dochandle_t handle
, FILE *fp
, char *alias
)
5478 if (zonecfg_get_aliased_rctl(handle
, alias
, &limit
) == Z_OK
) {
5479 /* convert memory based properties */
5480 if (strcmp(alias
, ALIAS_MAXSHMMEM
) == 0) {
5483 (void) snprintf(buf
, sizeof (buf
), "%llu", limit
);
5484 bytes_to_units(buf
, buf
, sizeof (buf
));
5485 (void) fprintf(fp
, "[%s: %s]\n", alias
, buf
);
5489 (void) fprintf(fp
, "[%s: %llu]\n", alias
, limit
);
5494 bytes_to_units(char *str
, char *buf
, int bufsize
)
5496 unsigned long long num
;
5497 unsigned long long save
= 0;
5498 char *units
= "BKMGT";
5501 num
= strtoll(str
, NULL
, 10);
5504 (void) snprintf(buf
, bufsize
, "%llu", num
);
5508 while ((num
>= 1024) && (*up
!= 'T')) {
5509 up
++; /* next unit of measurement */
5511 num
= (num
+ 512) >> 10;
5514 /* check if we should output a fraction. snprintf will round for us */
5515 if (save
% 1024 != 0 && ((save
>> 10) < 10))
5516 (void) snprintf(buf
, bufsize
, "%2.1f%c", ((float)save
/ 1024),
5519 (void) snprintf(buf
, bufsize
, "%llu%c", num
, *up
);
5523 output_mcap(FILE *fp
, struct zone_mcaptab
*mcaptab
, int showswap
,
5524 uint64_t maxswap
, int showlocked
, uint64_t maxlocked
)
5528 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_MCAP
));
5529 if (mcaptab
->zone_physmem_cap
[0] != '\0') {
5530 bytes_to_units(mcaptab
->zone_physmem_cap
, buf
, sizeof (buf
));
5531 output_prop(fp
, PT_PHYSICAL
, buf
, B_TRUE
);
5534 if (showswap
== Z_OK
) {
5535 (void) snprintf(buf
, sizeof (buf
), "%llu", maxswap
);
5536 bytes_to_units(buf
, buf
, sizeof (buf
));
5537 output_prop(fp
, PT_SWAP
, buf
, B_TRUE
);
5540 if (showlocked
== Z_OK
) {
5541 (void) snprintf(buf
, sizeof (buf
), "%llu", maxlocked
);
5542 bytes_to_units(buf
, buf
, sizeof (buf
));
5543 output_prop(fp
, PT_LOCKED
, buf
, B_TRUE
);
5548 info_mcap(zone_dochandle_t handle
, FILE *fp
)
5550 int res1
, res2
, res3
;
5551 uint64_t swap_limit
;
5552 uint64_t locked_limit
;
5553 struct zone_mcaptab lookup
;
5555 bzero(&lookup
, sizeof (lookup
));
5556 res1
= zonecfg_getmcapent(handle
, &lookup
);
5557 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &swap_limit
);
5558 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
5561 if (res1
== Z_OK
|| res2
== Z_OK
|| res3
== Z_OK
)
5562 output_mcap(fp
, &lookup
, res2
, swap_limit
, res3
, locked_limit
);
5566 output_auth(FILE *fp
, struct zone_admintab
*admintab
)
5568 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_ADMIN
));
5569 output_prop(fp
, PT_USER
, admintab
->zone_admin_user
, B_TRUE
);
5570 output_prop(fp
, PT_AUTHS
, admintab
->zone_admin_auths
, B_TRUE
);
5574 output_secflags(FILE *fp
, struct zone_secflagstab
*sftab
)
5576 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_SECFLAGS
));
5577 output_prop(fp
, PT_DEFAULT
, sftab
->zone_secflags_default
, B_TRUE
);
5578 output_prop(fp
, PT_LOWER
, sftab
->zone_secflags_lower
, B_TRUE
);
5579 output_prop(fp
, PT_UPPER
, sftab
->zone_secflags_upper
, B_TRUE
);
5583 info_auth(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5585 struct zone_admintab lookup
, user
;
5586 boolean_t output
= B_FALSE
;
5589 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
5590 zone_perror(zone
, err
, B_TRUE
);
5593 while (zonecfg_getadminent(handle
, &lookup
) == Z_OK
) {
5594 if (cmd
->cmd_prop_nv_pairs
== 0) {
5595 output_auth(fp
, &lookup
);
5598 if (fill_in_admintab(cmd
, &user
, B_TRUE
) != Z_OK
)
5600 if (strlen(user
.zone_admin_user
) > 0 &&
5601 strcmp(user
.zone_admin_user
, lookup
.zone_admin_user
) != 0)
5602 continue; /* no match */
5603 output_auth(fp
, &lookup
);
5606 (void) zonecfg_endadminent(handle
);
5608 * If a property n/v pair was specified, warn the user if there was
5609 * nothing to output.
5611 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5612 (void) printf(gettext("No such %s resource.\n"),
5613 rt_to_str(RT_ADMIN
));
5617 info_secflags(zone_dochandle_t handle
, FILE *fp
)
5619 struct zone_secflagstab sftab
;
5621 if (zonecfg_lookup_secflags(handle
, &sftab
) == Z_OK
) {
5622 output_secflags(fp
, &sftab
);
5627 info_func(cmd_t
*cmd
)
5630 boolean_t need_to_close
= B_FALSE
;
5633 uint64_t swap_limit
;
5634 uint64_t locked_limit
;
5636 assert(cmd
!= NULL
);
5638 if (initialize(B_TRUE
) != Z_OK
)
5641 /* don't page error output */
5642 if (interactive_mode
) {
5643 if ((fp
= pager_open()) != NULL
)
5644 need_to_close
= B_TRUE
;
5651 if (!global_scope
) {
5652 switch (resource_scope
) {
5654 output_fs(fp
, &in_progress_fstab
);
5657 output_net(fp
, &in_progress_nwiftab
);
5660 output_dev(fp
, &in_progress_devtab
);
5663 output_rctl(fp
, &in_progress_rctltab
);
5666 output_attr(fp
, &in_progress_attrtab
);
5669 output_ds(fp
, &in_progress_dstab
);
5672 output_pset(fp
, &in_progress_psettab
);
5678 res1
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
,
5680 res2
= zonecfg_get_aliased_rctl(handle
,
5681 ALIAS_MAXLOCKEDMEM
, &locked_limit
);
5682 output_mcap(fp
, &in_progress_mcaptab
, res1
, swap_limit
,
5683 res2
, locked_limit
);
5686 output_auth(fp
, &in_progress_admintab
);
5689 output_secflags(fp
, &in_progress_secflagstab
);
5695 type
= cmd
->cmd_res_type
;
5697 if (gz_invalid_rt_property(type
)) {
5698 zerr(gettext("%s is not a valid property for the global zone."),
5703 if (gz_invalid_resource(type
)) {
5704 zerr(gettext("%s is not a valid resource for the global zone."),
5709 switch (cmd
->cmd_res_type
) {
5711 info_zonename(handle
, fp
);
5713 info_zonepath(handle
, fp
);
5714 info_brand(handle
, fp
);
5715 info_autoboot(handle
, fp
);
5716 info_bootargs(handle
, fp
);
5718 info_pool(handle
, fp
);
5720 info_limitpriv(handle
, fp
);
5721 info_sched(handle
, fp
);
5722 info_iptype(handle
, fp
);
5723 info_hostid(handle
, fp
);
5724 info_fs_allowed(handle
, fp
);
5726 info_aliased_rctl(handle
, fp
, ALIAS_MAXLWPS
);
5727 info_aliased_rctl(handle
, fp
, ALIAS_MAXPROCS
);
5728 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMMEM
);
5729 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMIDS
);
5730 info_aliased_rctl(handle
, fp
, ALIAS_MAXMSGIDS
);
5731 info_aliased_rctl(handle
, fp
, ALIAS_MAXSEMIDS
);
5732 info_aliased_rctl(handle
, fp
, ALIAS_SHARES
);
5734 info_fs(handle
, fp
, cmd
);
5735 info_net(handle
, fp
, cmd
);
5736 info_dev(handle
, fp
, cmd
);
5738 info_pset(handle
, fp
);
5740 info_mcap(handle
, fp
);
5742 info_attr(handle
, fp
, cmd
);
5743 info_ds(handle
, fp
, cmd
);
5744 info_auth(handle
, fp
, cmd
);
5746 info_rctl(handle
, fp
, cmd
);
5747 info_secflags(handle
, fp
);
5750 info_zonename(handle
, fp
);
5753 info_zonepath(handle
, fp
);
5756 info_brand(handle
, fp
);
5759 info_autoboot(handle
, fp
);
5762 info_pool(handle
, fp
);
5765 info_limitpriv(handle
, fp
);
5768 info_bootargs(handle
, fp
);
5771 info_sched(handle
, fp
);
5774 info_iptype(handle
, fp
);
5777 info_aliased_rctl(handle
, fp
, ALIAS_MAXLWPS
);
5780 info_aliased_rctl(handle
, fp
, ALIAS_MAXPROCS
);
5783 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMMEM
);
5786 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMIDS
);
5789 info_aliased_rctl(handle
, fp
, ALIAS_MAXMSGIDS
);
5792 info_aliased_rctl(handle
, fp
, ALIAS_MAXSEMIDS
);
5795 info_aliased_rctl(handle
, fp
, ALIAS_SHARES
);
5798 info_fs(handle
, fp
, cmd
);
5801 info_net(handle
, fp
, cmd
);
5804 info_dev(handle
, fp
, cmd
);
5807 info_rctl(handle
, fp
, cmd
);
5810 info_attr(handle
, fp
, cmd
);
5813 info_ds(handle
, fp
, cmd
);
5816 info_pset(handle
, fp
);
5822 info_mcap(handle
, fp
);
5825 info_hostid(handle
, fp
);
5828 info_auth(handle
, fp
, cmd
);
5831 info_fs_allowed(handle
, fp
);
5834 info_secflags(handle
, fp
);
5837 zone_perror(rt_to_str(cmd
->cmd_res_type
), Z_NO_RESOURCE_TYPE
,
5843 (void) pager_close(fp
);
5847 * Helper function for verify-- checks that a required string property
5851 check_reqd_prop(char *attr
, int rt
, int pt
, int *ret_val
)
5853 if (strlen(attr
) == 0) {
5854 zerr(gettext("%s: %s not specified"), rt_to_str(rt
),
5857 if (*ret_val
== Z_OK
)
5858 *ret_val
= Z_REQD_PROPERTY_MISSING
;
5863 do_subproc(char *cmdbuf
)
5865 char inbuf
[MAX_CMD_LEN
];
5869 file
= popen(cmdbuf
, "r");
5871 zerr(gettext("Could not launch: %s"), cmdbuf
);
5875 while (fgets(inbuf
, sizeof (inbuf
), file
) != NULL
)
5876 fprintf(stderr
, "%s", inbuf
);
5877 status
= pclose(file
);
5879 if (WIFSIGNALED(status
)) {
5880 zerr(gettext("%s unexpectedly terminated due to signal %d"),
5881 cmdbuf
, WTERMSIG(status
));
5884 assert(WIFEXITED(status
));
5885 return (WEXITSTATUS(status
));
5889 brand_verify(zone_dochandle_t handle
)
5892 char cmdbuf
[MAX_CMD_LEN
];
5894 char brand
[MAXNAMELEN
];
5897 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) != Z_OK
) {
5898 zerr("%s: %s\n", zone
, gettext("could not get zone brand"));
5899 return (Z_INVALID_DOCUMENT
);
5901 if ((bh
= brand_open(brand
)) == NULL
) {
5902 zerr("%s: %s\n", zone
, gettext("unknown brand."));
5903 return (Z_INVALID_DOCUMENT
);
5907 * Fetch the verify command, if any, from the brand configuration
5908 * and build the command line to execute it.
5910 strcpy(cmdbuf
, EXEC_PREFIX
);
5911 err
= brand_get_verify_cfg(bh
, cmdbuf
+ EXEC_LEN
,
5912 sizeof (cmdbuf
) - (EXEC_LEN
+ (strlen(xml_file
) + 1)));
5915 zerr("%s: %s\n", zone
,
5916 gettext("could not get brand verification command"));
5917 return (Z_INVALID_DOCUMENT
);
5921 * If the brand doesn't provide a verification routine, we just
5924 if (strlen(cmdbuf
) == EXEC_LEN
)
5928 * Dump the current config information for this zone to a file.
5930 strcpy(xml_file
, "/tmp/zonecfg_verify.XXXXXX");
5931 if (mkstemp(xml_file
) == 0)
5932 return (Z_TEMP_FILE
);
5933 if ((err
= zonecfg_verify_save(handle
, xml_file
)) != Z_OK
) {
5934 (void) unlink(xml_file
);
5939 * Execute the verification command.
5941 if ((strlcat(cmdbuf
, " ", MAX_CMD_LEN
) >= MAX_CMD_LEN
) ||
5942 (strlcat(cmdbuf
, xml_file
, MAX_CMD_LEN
) >= MAX_CMD_LEN
)) {
5943 err
= Z_BRAND_ERROR
;
5945 err
= do_subproc(cmdbuf
);
5948 (void) unlink(xml_file
);
5949 return ((err
== Z_OK
) ? Z_OK
: Z_BRAND_ERROR
);
5953 * Track the network interfaces listed in zonecfg(1m) in a linked list
5954 * so that we can later check that defrouter is specified for an exclusive IP
5955 * zone if and only if at least one allowed-address has been specified.
5958 add_nwif(struct zone_nwiftab
*nwif
)
5962 for (tmp
= xif
; tmp
!= NULL
; tmp
= tmp
->xif_next
) {
5963 if (strcmp(tmp
->xif_name
, nwif
->zone_nwif_physical
) == 0) {
5964 if (strlen(nwif
->zone_nwif_allowed_address
) > 0)
5965 tmp
->xif_has_address
= B_TRUE
;
5966 if (strlen(nwif
->zone_nwif_defrouter
) > 0)
5967 tmp
->xif_has_defrouter
= B_TRUE
;
5972 tmp
= malloc(sizeof (*tmp
));
5974 zerr(gettext("memory allocation failed for %s"),
5975 nwif
->zone_nwif_physical
);
5978 strlcpy(tmp
->xif_name
, nwif
->zone_nwif_physical
,
5979 sizeof (tmp
->xif_name
));
5980 tmp
->xif_has_defrouter
= (strlen(nwif
->zone_nwif_defrouter
) > 0);
5981 tmp
->xif_has_address
= (strlen(nwif
->zone_nwif_allowed_address
) > 0);
5982 tmp
->xif_next
= xif
;
5988 verify_secflags(struct zone_secflagstab
*tab
)
5990 secflagdelta_t def
= {0};
5991 secflagdelta_t upper
= {0};
5992 secflagdelta_t lower
= {0};
5993 boolean_t def_set
= B_FALSE
;
5994 boolean_t upper_set
= B_FALSE
;
5995 boolean_t lower_set
= B_FALSE
;
5996 boolean_t ret
= B_TRUE
;
5998 if (strlen(tab
->zone_secflags_default
) > 0) {
6000 if (secflags_parse(NULL
, tab
->zone_secflags_default
,
6002 zerr(gettext("default security flags '%s' are invalid"),
6003 tab
->zone_secflags_default
);
6007 secflags_zero(&def
.psd_assign
);
6008 def
.psd_ass_active
= B_TRUE
;
6011 if (strlen(tab
->zone_secflags_upper
) > 0) {
6013 if (secflags_parse(NULL
, tab
->zone_secflags_upper
,
6015 zerr(gettext("upper security flags '%s' are invalid"),
6016 tab
->zone_secflags_upper
);
6020 secflags_fullset(&upper
.psd_assign
);
6021 upper
.psd_ass_active
= B_TRUE
;
6024 if (strlen(tab
->zone_secflags_lower
) > 0) {
6026 if (secflags_parse(NULL
, tab
->zone_secflags_lower
,
6028 zerr(gettext("lower security flags '%s' are invalid"),
6029 tab
->zone_secflags_lower
);
6033 secflags_zero(&lower
.psd_assign
);
6034 lower
.psd_ass_active
= B_TRUE
;
6037 if (def_set
&& !def
.psd_ass_active
) {
6038 zerr(gettext("only assignment of security flags is "
6039 "allowed (default: %s)"), tab
->zone_secflags_default
);
6042 if (lower_set
&& !lower
.psd_ass_active
) {
6043 zerr(gettext("only assignment of security flags is "
6044 "allowed (lower: %s)"), tab
->zone_secflags_lower
);
6047 if (upper_set
&& !upper
.psd_ass_active
) {
6048 zerr(gettext("only assignment of security flags is "
6049 "allowed (upper: %s)"), tab
->zone_secflags_upper
);
6052 if (def
.psd_assign
& ~upper
.psd_assign
) { /* In default but not upper */
6053 zerr(gettext("default secflags must be within the "
6057 if (lower
.psd_assign
& ~def
.psd_assign
) { /* In lower but not default */
6058 zerr(gettext("default secflags must be above the lower limit"));
6061 if (lower
.psd_assign
& ~upper
.psd_assign
) { /* In lower but not upper */
6062 zerr(gettext("lower secflags must be within the upper limit"));
6070 * See the DTD for which attributes are required for which resources.
6072 * This function can be called by commit_func(), which needs to save things,
6073 * in addition to the general call from parse_and_run(), which doesn't need
6074 * things saved. Since the parameters are standardized, we distinguish by
6075 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
6076 * that a save is needed.
6079 verify_func(cmd_t
*cmd
)
6081 struct zone_nwiftab nwiftab
;
6082 struct zone_fstab fstab
;
6083 struct zone_attrtab attrtab
;
6084 struct zone_rctltab rctltab
;
6085 struct zone_dstab dstab
;
6086 struct zone_psettab psettab
;
6087 struct zone_admintab admintab
;
6088 struct zone_secflagstab secflagstab
;
6089 char zonepath
[MAXPATHLEN
];
6090 char sched
[MAXNAMELEN
];
6091 char brand
[MAXNAMELEN
];
6092 char hostidp
[HW_HOSTID_LEN
];
6093 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
6095 char *privname
= NULL
;
6096 int err
, ret_val
= Z_OK
, arg
;
6098 boolean_t save
= B_FALSE
;
6099 boolean_t arg_err
= B_FALSE
;
6100 zone_iptype_t iptype
;
6101 boolean_t has_cpu_shares
= B_FALSE
;
6102 boolean_t has_cpu_cap
= B_FALSE
;
6106 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6109 longer_usage(CMD_VERIFY
);
6113 short_usage(CMD_VERIFY
);
6121 if (optind
> cmd
->cmd_argc
) {
6122 short_usage(CMD_VERIFY
);
6126 if (zone_is_read_only(CMD_VERIFY
))
6129 assert(cmd
!= NULL
);
6131 if (cmd
->cmd_argc
> 0 && (strcmp(cmd
->cmd_argv
[0], "save") == 0))
6133 if (initialize(B_TRUE
) != Z_OK
)
6136 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) != Z_OK
&&
6138 zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH
));
6139 ret_val
= Z_REQD_RESOURCE_MISSING
;
6142 if (strlen(zonepath
) == 0 && !global_zone
) {
6143 zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH
));
6144 ret_val
= Z_REQD_RESOURCE_MISSING
;
6148 if ((err
= zonecfg_get_brand(handle
, brand
, sizeof (brand
))) != Z_OK
) {
6149 zone_perror(zone
, err
, B_TRUE
);
6152 if ((err
= brand_verify(handle
)) != Z_OK
) {
6153 zone_perror(zone
, err
, B_TRUE
);
6157 if (zonecfg_get_iptype(handle
, &iptype
) != Z_OK
) {
6158 zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE
));
6159 ret_val
= Z_REQD_RESOURCE_MISSING
;
6163 if ((privs
= priv_allocset()) == NULL
) {
6164 zerr(gettext("%s: priv_allocset failed"), zone
);
6167 if (zonecfg_get_privset(handle
, privs
, &privname
) != Z_OK
) {
6168 zerr(gettext("%s: invalid privilege: %s"), zone
, privname
);
6169 priv_freeset(privs
);
6173 priv_freeset(privs
);
6175 if (zonecfg_get_hostid(handle
, hostidp
,
6176 sizeof (hostidp
)) == Z_INVALID_PROPERTY
) {
6177 zerr(gettext("%s: invalid hostid: %s"),
6182 if (zonecfg_get_fs_allowed(handle
, fsallowedp
,
6183 sizeof (fsallowedp
)) == Z_INVALID_PROPERTY
) {
6184 zerr(gettext("%s: invalid fs-allowed: %s"),
6189 if ((err
= zonecfg_setfsent(handle
)) != Z_OK
) {
6190 zone_perror(zone
, err
, B_TRUE
);
6193 while (zonecfg_getfsent(handle
, &fstab
) == Z_OK
) {
6194 check_reqd_prop(fstab
.zone_fs_dir
, RT_FS
, PT_DIR
, &ret_val
);
6195 check_reqd_prop(fstab
.zone_fs_special
, RT_FS
, PT_SPECIAL
,
6197 check_reqd_prop(fstab
.zone_fs_type
, RT_FS
, PT_TYPE
, &ret_val
);
6199 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
6201 (void) zonecfg_endfsent(handle
);
6203 if ((err
= zonecfg_setnwifent(handle
)) != Z_OK
) {
6204 zone_perror(zone
, err
, B_TRUE
);
6207 while (zonecfg_getnwifent(handle
, &nwiftab
) == Z_OK
) {
6209 * physical is required in all cases.
6210 * A shared IP requires an address,
6211 * and may include a default router, while
6212 * an exclusive IP must have neither an address
6213 * nor a default router.
6214 * The physical interface name must be valid in all cases.
6216 check_reqd_prop(nwiftab
.zone_nwif_physical
, RT_NET
,
6217 PT_PHYSICAL
, &ret_val
);
6218 if (validate_net_physical_syntax(nwiftab
.zone_nwif_physical
) !=
6221 if (ret_val
== Z_OK
)
6227 check_reqd_prop(nwiftab
.zone_nwif_address
, RT_NET
,
6228 PT_ADDRESS
, &ret_val
);
6229 if (strlen(nwiftab
.zone_nwif_allowed_address
) > 0) {
6230 zerr(gettext("%s: %s cannot be specified "
6231 "for a shared IP type"),
6233 pt_to_str(PT_ALLOWED_ADDRESS
));
6235 if (ret_val
== Z_OK
)
6240 if (strlen(nwiftab
.zone_nwif_address
) > 0) {
6241 zerr(gettext("%s: %s cannot be specified "
6242 "for an exclusive IP type"),
6243 rt_to_str(RT_NET
), pt_to_str(PT_ADDRESS
));
6245 if (ret_val
== Z_OK
)
6248 if (!add_nwif(&nwiftab
)) {
6250 if (ret_val
== Z_OK
)
6257 for (tmp
= xif
; tmp
!= NULL
; tmp
= tmp
->xif_next
) {
6258 if (!tmp
->xif_has_address
&& tmp
->xif_has_defrouter
) {
6259 zerr(gettext("%s: %s for %s cannot be specified "
6260 "without %s for an exclusive IP type"),
6261 rt_to_str(RT_NET
), pt_to_str(PT_DEFROUTER
),
6262 tmp
->xif_name
, pt_to_str(PT_ALLOWED_ADDRESS
));
6269 (void) zonecfg_endnwifent(handle
);
6271 if ((err
= zonecfg_setrctlent(handle
)) != Z_OK
) {
6272 zone_perror(zone
, err
, B_TRUE
);
6275 while (zonecfg_getrctlent(handle
, &rctltab
) == Z_OK
) {
6276 check_reqd_prop(rctltab
.zone_rctl_name
, RT_RCTL
, PT_NAME
,
6279 if (strcmp(rctltab
.zone_rctl_name
, "zone.cpu-shares") == 0)
6280 has_cpu_shares
= B_TRUE
;
6282 if (strcmp(rctltab
.zone_rctl_name
, "zone.cpu-cap") == 0)
6283 has_cpu_cap
= B_TRUE
;
6285 if (rctltab
.zone_rctl_valptr
== NULL
) {
6286 zerr(gettext("%s: no %s specified"),
6287 rt_to_str(RT_RCTL
), pt_to_str(PT_VALUE
));
6289 if (ret_val
== Z_OK
)
6290 ret_val
= Z_REQD_PROPERTY_MISSING
;
6292 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
6295 (void) zonecfg_endrctlent(handle
);
6297 if ((pset_res
= zonecfg_lookup_pset(handle
, &psettab
)) == Z_OK
&&
6299 zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
6300 rt_to_str(RT_RCTL
), rt_to_str(RT_DCPU
));
6302 if (ret_val
== Z_OK
)
6303 ret_val
= Z_INCOMPATIBLE
;
6306 if (has_cpu_shares
&& zonecfg_get_sched_class(handle
, sched
,
6307 sizeof (sched
)) == Z_OK
&& strlen(sched
) > 0 &&
6308 strcmp(sched
, "FSS") != 0) {
6309 zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
6311 rt_to_str(RT_RCTL
), rt_to_str(RT_SCHED
), sched
);
6313 if (ret_val
== Z_OK
)
6314 ret_val
= Z_INCOMPATIBLE
;
6317 if (pset_res
== Z_OK
&& has_cpu_cap
) {
6318 zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
6319 rt_to_str(RT_RCTL
), rt_to_str(RT_DCPU
));
6321 if (ret_val
== Z_OK
)
6322 ret_val
= Z_INCOMPATIBLE
;
6325 if ((err
= zonecfg_setattrent(handle
)) != Z_OK
) {
6326 zone_perror(zone
, err
, B_TRUE
);
6329 while (zonecfg_getattrent(handle
, &attrtab
) == Z_OK
) {
6330 check_reqd_prop(attrtab
.zone_attr_name
, RT_ATTR
, PT_NAME
,
6332 check_reqd_prop(attrtab
.zone_attr_type
, RT_ATTR
, PT_TYPE
,
6334 check_reqd_prop(attrtab
.zone_attr_value
, RT_ATTR
, PT_VALUE
,
6337 (void) zonecfg_endattrent(handle
);
6339 if ((err
= zonecfg_setdsent(handle
)) != Z_OK
) {
6340 zone_perror(zone
, err
, B_TRUE
);
6343 while (zonecfg_getdsent(handle
, &dstab
) == Z_OK
) {
6344 if (strlen(dstab
.zone_dataset_name
) == 0) {
6345 zerr("%s: %s %s", rt_to_str(RT_DATASET
),
6346 pt_to_str(PT_NAME
), gettext("not specified"));
6348 if (ret_val
== Z_OK
)
6349 ret_val
= Z_REQD_PROPERTY_MISSING
;
6350 } else if (!zfs_name_valid(dstab
.zone_dataset_name
,
6351 ZFS_TYPE_FILESYSTEM
)) {
6352 zerr("%s: %s %s", rt_to_str(RT_DATASET
),
6353 pt_to_str(PT_NAME
), gettext("invalid"));
6355 if (ret_val
== Z_OK
)
6356 ret_val
= Z_BAD_PROPERTY
;
6360 (void) zonecfg_enddsent(handle
);
6362 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
6363 zone_perror(zone
, err
, B_TRUE
);
6366 while (zonecfg_getadminent(handle
, &admintab
) == Z_OK
) {
6367 check_reqd_prop(admintab
.zone_admin_user
, RT_ADMIN
,
6369 check_reqd_prop(admintab
.zone_admin_auths
, RT_ADMIN
,
6370 PT_AUTHS
, &ret_val
);
6371 if ((ret_val
== Z_OK
) && (getpwnam(admintab
.zone_admin_user
)
6373 zerr(gettext("%s %s is not a valid username"),
6375 admintab
.zone_admin_user
);
6376 ret_val
= Z_BAD_PROPERTY
;
6378 if ((ret_val
== Z_OK
) && (!zonecfg_valid_auths(
6379 admintab
.zone_admin_auths
, zone
))) {
6380 ret_val
= Z_BAD_PROPERTY
;
6383 (void) zonecfg_endadminent(handle
);
6385 if (zonecfg_getsecflagsent(handle
, &secflagstab
) == Z_OK
) {
6387 * No properties are required, but any specified should be
6390 if (verify_secflags(&secflagstab
) != B_TRUE
) {
6391 /* Error is reported from verify_secflags */
6392 ret_val
= Z_BAD_PROPERTY
;
6396 if (!global_scope
) {
6397 zerr(gettext("resource specification incomplete"));
6399 if (ret_val
== Z_OK
)
6400 ret_val
= Z_INSUFFICIENT_SPEC
;
6404 if (ret_val
== Z_OK
) {
6405 if ((ret_val
= zonecfg_save(handle
)) == Z_OK
) {
6406 need_to_commit
= B_FALSE
;
6407 (void) strlcpy(revert_zone
, zone
,
6408 sizeof (revert_zone
));
6411 zerr(gettext("Zone %s failed to verify"), zone
);
6414 if (ret_val
!= Z_OK
)
6415 zone_perror(zone
, ret_val
, B_TRUE
);
6419 cancel_func(cmd_t
*cmd
)
6422 boolean_t arg_err
= B_FALSE
;
6424 assert(cmd
!= NULL
);
6427 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6430 longer_usage(CMD_CANCEL
);
6434 short_usage(CMD_CANCEL
);
6442 if (optind
!= cmd
->cmd_argc
) {
6443 short_usage(CMD_CANCEL
);
6448 scope_usage(CMD_CANCEL
);
6449 global_scope
= B_TRUE
;
6450 zonecfg_free_fs_option_list(in_progress_fstab
.zone_fs_options
);
6451 bzero(&in_progress_fstab
, sizeof (in_progress_fstab
));
6452 bzero(&in_progress_nwiftab
, sizeof (in_progress_nwiftab
));
6453 bzero(&in_progress_devtab
, sizeof (in_progress_devtab
));
6454 zonecfg_free_rctl_value_list(in_progress_rctltab
.zone_rctl_valptr
);
6455 bzero(&in_progress_rctltab
, sizeof (in_progress_rctltab
));
6456 bzero(&in_progress_attrtab
, sizeof (in_progress_attrtab
));
6457 bzero(&in_progress_dstab
, sizeof (in_progress_dstab
));
6461 validate_attr_name(char *name
)
6465 if (!isalnum(name
[0])) {
6466 zerr(gettext("Invalid %s %s %s: must start with an alpha-"
6467 "numeric character."), rt_to_str(RT_ATTR
),
6468 pt_to_str(PT_NAME
), name
);
6471 for (i
= 1; name
[i
]; i
++)
6472 if (!isalnum(name
[i
]) && name
[i
] != '-' && name
[i
] != '.') {
6473 zerr(gettext("Invalid %s %s %s: can only contain "
6474 "alpha-numeric characters, plus '-' and '.'."),
6475 rt_to_str(RT_ATTR
), pt_to_str(PT_NAME
), name
);
6482 validate_attr_type_val(struct zone_attrtab
*attrtab
)
6486 char strval
[MAXNAMELEN
];
6489 if (strcmp(attrtab
->zone_attr_type
, "boolean") == 0) {
6490 if (zonecfg_get_attr_boolean(attrtab
, &boolval
) == Z_OK
)
6492 zerr(gettext("invalid %s value for %s=%s"),
6493 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "boolean");
6497 if (strcmp(attrtab
->zone_attr_type
, "int") == 0) {
6498 if (zonecfg_get_attr_int(attrtab
, &intval
) == Z_OK
)
6500 zerr(gettext("invalid %s value for %s=%s"),
6501 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "int");
6505 if (strcmp(attrtab
->zone_attr_type
, "string") == 0) {
6506 if (zonecfg_get_attr_string(attrtab
, strval
,
6507 sizeof (strval
)) == Z_OK
)
6509 zerr(gettext("invalid %s value for %s=%s"),
6510 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "string");
6514 if (strcmp(attrtab
->zone_attr_type
, "uint") == 0) {
6515 if (zonecfg_get_attr_uint(attrtab
, &uintval
) == Z_OK
)
6517 zerr(gettext("invalid %s value for %s=%s"),
6518 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "uint");
6522 zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR
),
6523 pt_to_str(PT_TYPE
), attrtab
->zone_attr_type
);
6528 * Helper function for end_func-- checks the existence of a given property
6529 * and emits a message if not specified.
6532 end_check_reqd(char *attr
, int pt
, boolean_t
*validation_failed
)
6534 if (strlen(attr
) == 0) {
6535 *validation_failed
= B_TRUE
;
6536 zerr(gettext("%s not specified"), pt_to_str(pt
));
6543 net_exists_error(struct zone_nwiftab nwif
)
6545 if (strlen(nwif
.zone_nwif_address
) > 0) {
6546 zerr(gettext("A %s resource with the %s '%s', "
6547 "and %s '%s' already exists."),
6549 pt_to_str(PT_PHYSICAL
),
6550 nwif
.zone_nwif_physical
,
6551 pt_to_str(PT_ADDRESS
),
6552 in_progress_nwiftab
.zone_nwif_address
);
6554 zerr(gettext("A %s resource with the %s '%s', "
6555 "and %s '%s' already exists."),
6557 pt_to_str(PT_PHYSICAL
),
6558 nwif
.zone_nwif_physical
,
6559 pt_to_str(PT_ALLOWED_ADDRESS
),
6560 nwif
.zone_nwif_allowed_address
);
6565 end_func(cmd_t
*cmd
)
6567 boolean_t validation_failed
= B_FALSE
;
6568 boolean_t arg_err
= B_FALSE
;
6569 struct zone_fstab tmp_fstab
;
6570 struct zone_nwiftab tmp_nwiftab
;
6571 struct zone_devtab tmp_devtab
;
6572 struct zone_rctltab tmp_rctltab
;
6573 struct zone_attrtab tmp_attrtab
;
6574 struct zone_dstab tmp_dstab
;
6575 struct zone_admintab tmp_admintab
;
6576 int err
, arg
, res1
, res2
, res3
;
6577 uint64_t swap_limit
;
6578 uint64_t locked_limit
;
6581 assert(cmd
!= NULL
);
6584 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6587 longer_usage(CMD_END
);
6591 short_usage(CMD_END
);
6599 if (optind
!= cmd
->cmd_argc
) {
6600 short_usage(CMD_END
);
6605 scope_usage(CMD_END
);
6609 assert(end_op
== CMD_ADD
|| end_op
== CMD_SELECT
);
6611 switch (resource_scope
) {
6613 /* First make sure everything was filled in. */
6614 if (end_check_reqd(in_progress_fstab
.zone_fs_dir
,
6615 PT_DIR
, &validation_failed
) == Z_OK
) {
6616 if (in_progress_fstab
.zone_fs_dir
[0] != '/') {
6617 zerr(gettext("%s %s is not an absolute path."),
6619 in_progress_fstab
.zone_fs_dir
);
6620 validation_failed
= B_TRUE
;
6624 (void) end_check_reqd(in_progress_fstab
.zone_fs_special
,
6625 PT_SPECIAL
, &validation_failed
);
6627 if (in_progress_fstab
.zone_fs_raw
[0] != '\0' &&
6628 in_progress_fstab
.zone_fs_raw
[0] != '/') {
6629 zerr(gettext("%s %s is not an absolute path."),
6631 in_progress_fstab
.zone_fs_raw
);
6632 validation_failed
= B_TRUE
;
6635 (void) end_check_reqd(in_progress_fstab
.zone_fs_type
, PT_TYPE
,
6636 &validation_failed
);
6638 if (validation_failed
) {
6643 if (end_op
== CMD_ADD
) {
6644 /* Make sure there isn't already one like this. */
6645 bzero(&tmp_fstab
, sizeof (tmp_fstab
));
6646 (void) strlcpy(tmp_fstab
.zone_fs_dir
,
6647 in_progress_fstab
.zone_fs_dir
,
6648 sizeof (tmp_fstab
.zone_fs_dir
));
6649 err
= zonecfg_lookup_filesystem(handle
, &tmp_fstab
);
6650 zonecfg_free_fs_option_list(tmp_fstab
.zone_fs_options
);
6652 zerr(gettext("A %s resource "
6653 "with the %s '%s' already exists."),
6654 rt_to_str(RT_FS
), pt_to_str(PT_DIR
),
6655 in_progress_fstab
.zone_fs_dir
);
6659 err
= zonecfg_add_filesystem(handle
,
6660 &in_progress_fstab
);
6662 err
= zonecfg_modify_filesystem(handle
, &old_fstab
,
6663 &in_progress_fstab
);
6665 zonecfg_free_fs_option_list(in_progress_fstab
.zone_fs_options
);
6666 in_progress_fstab
.zone_fs_options
= NULL
;
6671 * First make sure everything was filled in.
6672 * Since we don't know whether IP will be shared
6673 * or exclusive here, some checks are deferred until
6674 * the verify command.
6676 (void) end_check_reqd(in_progress_nwiftab
.zone_nwif_physical
,
6677 PT_PHYSICAL
, &validation_failed
);
6679 if (validation_failed
) {
6683 if (end_op
== CMD_ADD
) {
6684 /* Make sure there isn't already one like this. */
6685 bzero(&tmp_nwiftab
, sizeof (tmp_nwiftab
));
6686 (void) strlcpy(tmp_nwiftab
.zone_nwif_physical
,
6687 in_progress_nwiftab
.zone_nwif_physical
,
6688 sizeof (tmp_nwiftab
.zone_nwif_physical
));
6689 (void) strlcpy(tmp_nwiftab
.zone_nwif_address
,
6690 in_progress_nwiftab
.zone_nwif_address
,
6691 sizeof (tmp_nwiftab
.zone_nwif_address
));
6692 (void) strlcpy(tmp_nwiftab
.zone_nwif_allowed_address
,
6693 in_progress_nwiftab
.zone_nwif_allowed_address
,
6694 sizeof (tmp_nwiftab
.zone_nwif_allowed_address
));
6695 (void) strlcpy(tmp_nwiftab
.zone_nwif_defrouter
,
6696 in_progress_nwiftab
.zone_nwif_defrouter
,
6697 sizeof (tmp_nwiftab
.zone_nwif_defrouter
));
6698 if (zonecfg_lookup_nwif(handle
, &tmp_nwiftab
) == Z_OK
) {
6699 net_exists_error(in_progress_nwiftab
);
6703 err
= zonecfg_add_nwif(handle
, &in_progress_nwiftab
);
6705 err
= zonecfg_modify_nwif(handle
, &old_nwiftab
,
6706 &in_progress_nwiftab
);
6711 /* First make sure everything was filled in. */
6712 (void) end_check_reqd(in_progress_devtab
.zone_dev_match
,
6713 PT_MATCH
, &validation_failed
);
6715 if (validation_failed
) {
6720 if (end_op
== CMD_ADD
) {
6721 /* Make sure there isn't already one like this. */
6722 (void) strlcpy(tmp_devtab
.zone_dev_match
,
6723 in_progress_devtab
.zone_dev_match
,
6724 sizeof (tmp_devtab
.zone_dev_match
));
6725 if (zonecfg_lookup_dev(handle
, &tmp_devtab
) == Z_OK
) {
6726 zerr(gettext("A %s resource with the %s '%s' "
6727 "already exists."), rt_to_str(RT_DEVICE
),
6728 pt_to_str(PT_MATCH
),
6729 in_progress_devtab
.zone_dev_match
);
6733 err
= zonecfg_add_dev(handle
, &in_progress_devtab
);
6735 err
= zonecfg_modify_dev(handle
, &old_devtab
,
6736 &in_progress_devtab
);
6741 /* First make sure everything was filled in. */
6742 (void) end_check_reqd(in_progress_rctltab
.zone_rctl_name
,
6743 PT_NAME
, &validation_failed
);
6745 if (in_progress_rctltab
.zone_rctl_valptr
== NULL
) {
6746 zerr(gettext("no %s specified"), pt_to_str(PT_VALUE
));
6747 validation_failed
= B_TRUE
;
6750 if (validation_failed
) {
6755 if (end_op
== CMD_ADD
) {
6756 /* Make sure there isn't already one like this. */
6757 (void) strlcpy(tmp_rctltab
.zone_rctl_name
,
6758 in_progress_rctltab
.zone_rctl_name
,
6759 sizeof (tmp_rctltab
.zone_rctl_name
));
6760 tmp_rctltab
.zone_rctl_valptr
= NULL
;
6761 err
= zonecfg_lookup_rctl(handle
, &tmp_rctltab
);
6762 zonecfg_free_rctl_value_list(
6763 tmp_rctltab
.zone_rctl_valptr
);
6765 zerr(gettext("A %s resource "
6766 "with the %s '%s' already exists."),
6767 rt_to_str(RT_RCTL
), pt_to_str(PT_NAME
),
6768 in_progress_rctltab
.zone_rctl_name
);
6772 err
= zonecfg_add_rctl(handle
, &in_progress_rctltab
);
6774 err
= zonecfg_modify_rctl(handle
, &old_rctltab
,
6775 &in_progress_rctltab
);
6778 zonecfg_free_rctl_value_list(
6779 in_progress_rctltab
.zone_rctl_valptr
);
6780 in_progress_rctltab
.zone_rctl_valptr
= NULL
;
6785 /* First make sure everything was filled in. */
6786 (void) end_check_reqd(in_progress_attrtab
.zone_attr_name
,
6787 PT_NAME
, &validation_failed
);
6788 (void) end_check_reqd(in_progress_attrtab
.zone_attr_type
,
6789 PT_TYPE
, &validation_failed
);
6790 (void) end_check_reqd(in_progress_attrtab
.zone_attr_value
,
6791 PT_VALUE
, &validation_failed
);
6793 if (validate_attr_name(in_progress_attrtab
.zone_attr_name
) !=
6795 validation_failed
= B_TRUE
;
6797 if (validate_attr_type_val(&in_progress_attrtab
) != Z_OK
)
6798 validation_failed
= B_TRUE
;
6800 if (validation_failed
) {
6804 if (end_op
== CMD_ADD
) {
6805 /* Make sure there isn't already one like this. */
6806 bzero(&tmp_attrtab
, sizeof (tmp_attrtab
));
6807 (void) strlcpy(tmp_attrtab
.zone_attr_name
,
6808 in_progress_attrtab
.zone_attr_name
,
6809 sizeof (tmp_attrtab
.zone_attr_name
));
6810 if (zonecfg_lookup_attr(handle
, &tmp_attrtab
) == Z_OK
) {
6811 zerr(gettext("An %s resource "
6812 "with the %s '%s' already exists."),
6813 rt_to_str(RT_ATTR
), pt_to_str(PT_NAME
),
6814 in_progress_attrtab
.zone_attr_name
);
6818 err
= zonecfg_add_attr(handle
, &in_progress_attrtab
);
6820 err
= zonecfg_modify_attr(handle
, &old_attrtab
,
6821 &in_progress_attrtab
);
6825 /* First make sure everything was filled in. */
6826 if (strlen(in_progress_dstab
.zone_dataset_name
) == 0) {
6827 zerr("%s %s", pt_to_str(PT_NAME
),
6828 gettext("not specified"));
6830 validation_failed
= B_TRUE
;
6832 if (validation_failed
)
6834 if (end_op
== CMD_ADD
) {
6835 /* Make sure there isn't already one like this. */
6836 bzero(&tmp_dstab
, sizeof (tmp_dstab
));
6837 (void) strlcpy(tmp_dstab
.zone_dataset_name
,
6838 in_progress_dstab
.zone_dataset_name
,
6839 sizeof (tmp_dstab
.zone_dataset_name
));
6840 err
= zonecfg_lookup_ds(handle
, &tmp_dstab
);
6842 zerr(gettext("A %s resource "
6843 "with the %s '%s' already exists."),
6844 rt_to_str(RT_DATASET
), pt_to_str(PT_NAME
),
6845 in_progress_dstab
.zone_dataset_name
);
6849 err
= zonecfg_add_ds(handle
, &in_progress_dstab
);
6851 err
= zonecfg_modify_ds(handle
, &old_dstab
,
6852 &in_progress_dstab
);
6856 /* Make sure everything was filled in. */
6857 if (end_check_reqd(in_progress_psettab
.zone_ncpu_min
,
6858 PT_NCPUS
, &validation_failed
) != Z_OK
) {
6863 if (end_op
== CMD_ADD
) {
6864 err
= zonecfg_add_pset(handle
, &in_progress_psettab
);
6866 err
= zonecfg_modify_pset(handle
, &in_progress_psettab
);
6870 /* Make sure everything was filled in. */
6871 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &proc_cap
)
6873 zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS
));
6875 validation_failed
= B_TRUE
;
6881 /* Make sure everything was filled in. */
6882 res1
= strlen(in_progress_mcaptab
.zone_physmem_cap
) == 0 ?
6884 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
,
6886 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
6889 if (res1
!= Z_OK
&& res2
!= Z_OK
&& res3
!= Z_OK
) {
6890 zerr(gettext("No property was specified. One of %s, "
6891 "%s or %s is required."), pt_to_str(PT_PHYSICAL
),
6892 pt_to_str(PT_SWAP
), pt_to_str(PT_LOCKED
));
6897 /* if phys & locked are both set, verify locked <= phys */
6898 if (res1
== Z_OK
&& res3
== Z_OK
) {
6899 uint64_t phys_limit
;
6902 phys_limit
= strtoull(
6903 in_progress_mcaptab
.zone_physmem_cap
, &endp
, 10);
6904 if (phys_limit
< locked_limit
) {
6905 zerr(gettext("The %s cap must be less than or "
6906 "equal to the %s cap."),
6907 pt_to_str(PT_LOCKED
),
6908 pt_to_str(PT_PHYSICAL
));
6917 * We could be ending from either an add operation
6918 * or a select operation. Since all of the properties
6919 * within this resource are optional, we always use
6920 * modify on the mcap entry. zonecfg_modify_mcap()
6921 * will handle both adding and modifying a memory cap.
6923 err
= zonecfg_modify_mcap(handle
, &in_progress_mcaptab
);
6924 } else if (end_op
== CMD_SELECT
) {
6926 * If we're ending from a select and the physical
6927 * memory cap is empty then the user could have cleared
6928 * the physical cap value, so try to delete the entry.
6930 (void) zonecfg_delete_mcap(handle
);
6934 /* First make sure everything was filled in. */
6935 if (end_check_reqd(in_progress_admintab
.zone_admin_user
,
6936 PT_USER
, &validation_failed
) == Z_OK
) {
6937 if (getpwnam(in_progress_admintab
.zone_admin_user
)
6939 zerr(gettext("%s %s is not a valid username"),
6941 in_progress_admintab
.zone_admin_user
);
6942 validation_failed
= B_TRUE
;
6946 if (end_check_reqd(in_progress_admintab
.zone_admin_auths
,
6947 PT_AUTHS
, &validation_failed
) == Z_OK
) {
6948 if (!zonecfg_valid_auths(
6949 in_progress_admintab
.zone_admin_auths
,
6951 validation_failed
= B_TRUE
;
6955 if (validation_failed
) {
6960 if (end_op
== CMD_ADD
) {
6961 /* Make sure there isn't already one like this. */
6962 bzero(&tmp_admintab
, sizeof (tmp_admintab
));
6963 (void) strlcpy(tmp_admintab
.zone_admin_user
,
6964 in_progress_admintab
.zone_admin_user
,
6965 sizeof (tmp_admintab
.zone_admin_user
));
6966 err
= zonecfg_lookup_admin(
6967 handle
, &tmp_admintab
);
6969 zerr(gettext("A %s resource "
6970 "with the %s '%s' already exists."),
6971 rt_to_str(RT_ADMIN
),
6973 in_progress_admintab
.zone_admin_user
);
6977 err
= zonecfg_add_admin(handle
,
6978 &in_progress_admintab
, zone
);
6980 err
= zonecfg_modify_admin(handle
,
6981 &old_admintab
, &in_progress_admintab
,
6986 if (verify_secflags(&in_progress_secflagstab
) != B_TRUE
) {
6991 if (end_op
== CMD_ADD
) {
6992 err
= zonecfg_add_secflags(handle
,
6993 &in_progress_secflagstab
);
6995 err
= zonecfg_modify_secflags(handle
,
6996 &old_secflagstab
, &in_progress_secflagstab
);
7000 zone_perror(rt_to_str(resource_scope
), Z_NO_RESOURCE_TYPE
,
7007 zone_perror(zone
, err
, B_TRUE
);
7009 need_to_commit
= B_TRUE
;
7010 global_scope
= B_TRUE
;
7016 commit_func(cmd_t
*cmd
)
7019 boolean_t arg_err
= B_FALSE
;
7022 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
7025 longer_usage(CMD_COMMIT
);
7029 short_usage(CMD_COMMIT
);
7037 if (optind
!= cmd
->cmd_argc
) {
7038 short_usage(CMD_COMMIT
);
7042 if (zone_is_read_only(CMD_COMMIT
))
7045 assert(cmd
!= NULL
);
7049 * cmd_arg normally comes from a strdup() in the lexer, and the
7050 * whole cmd structure and its (char *) attributes are freed at
7051 * the completion of each command, so the strdup() below is needed
7052 * to match this and prevent a core dump from trying to free()
7053 * something that can't be.
7055 if ((cmd
->cmd_argv
[0] = strdup("save")) == NULL
) {
7056 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
7059 cmd
->cmd_argv
[1] = NULL
;
7064 revert_func(cmd_t
*cmd
)
7066 char line
[128]; /* enough to ask a question */
7067 boolean_t force
= B_FALSE
;
7068 boolean_t arg_err
= B_FALSE
;
7069 int err
, arg
, answer
;
7072 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
7075 longer_usage(CMD_REVERT
);
7082 short_usage(CMD_REVERT
);
7090 if (optind
!= cmd
->cmd_argc
) {
7091 short_usage(CMD_REVERT
);
7095 if (zone_is_read_only(CMD_REVERT
))
7098 if (!global_scope
) {
7099 zerr(gettext("You can only use %s in the global scope.\nUse"
7100 " '%s' to cancel changes to a resource specification."),
7101 cmd_to_str(CMD_REVERT
), cmd_to_str(CMD_CANCEL
));
7106 if (zonecfg_check_handle(handle
) != Z_OK
) {
7107 zerr(gettext("No changes to revert."));
7113 (void) snprintf(line
, sizeof (line
),
7114 gettext("Are you sure you want to revert"));
7115 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
7116 zerr(gettext("Input not from terminal and -F not "
7117 "specified:\n%s command ignored, exiting."),
7118 cmd_to_str(CMD_REVERT
));
7126 * Reset any pending admins that were
7127 * removed from the previous zone
7129 zonecfg_remove_userauths(handle
, "", zone
, B_FALSE
);
7132 * Time for a new handle: finish the old one off first
7133 * then get a new one properly to avoid leaks.
7135 zonecfg_fini_handle(handle
);
7136 if ((handle
= zonecfg_init_handle()) == NULL
) {
7137 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7141 if ((err
= zonecfg_get_handle(revert_zone
, handle
)) != Z_OK
) {
7143 got_handle
= B_FALSE
;
7144 if (err
== Z_NO_ZONE
)
7145 zerr(gettext("%s: no such saved zone to revert to."),
7148 zone_perror(zone
, err
, B_TRUE
);
7150 (void) strlcpy(zone
, revert_zone
, sizeof (zone
));
7154 help_func(cmd_t
*cmd
)
7158 assert(cmd
!= NULL
);
7160 if (cmd
->cmd_argc
== 0) {
7161 usage(B_TRUE
, global_scope
? HELP_SUBCMDS
: HELP_RES_SCOPE
);
7164 if (strcmp(cmd
->cmd_argv
[0], "usage") == 0) {
7165 usage(B_TRUE
, HELP_USAGE
);
7168 if (strcmp(cmd
->cmd_argv
[0], "commands") == 0) {
7169 usage(B_TRUE
, HELP_SUBCMDS
);
7172 if (strcmp(cmd
->cmd_argv
[0], "syntax") == 0) {
7173 usage(B_TRUE
, HELP_SYNTAX
| HELP_RES_PROPS
);
7176 if (strcmp(cmd
->cmd_argv
[0], "-?") == 0) {
7177 longer_usage(CMD_HELP
);
7181 for (i
= 0; i
<= CMD_MAX
; i
++) {
7182 if (strcmp(cmd
->cmd_argv
[0], cmd_to_str(i
)) == 0) {
7187 /* We do not use zerr() here because we do not want its extra \n. */
7188 (void) fprintf(stderr
, gettext("Unknown help subject %s. "),
7190 usage(B_FALSE
, HELP_META
);
7194 string_to_yyin(char *string
)
7196 if ((yyin
= tmpfile()) == NULL
) {
7197 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7200 if (fwrite(string
, strlen(string
), 1, yyin
) != 1) {
7201 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7204 if (fseek(yyin
, 0, SEEK_SET
) != 0) {
7205 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7211 /* This is the back-end helper function for read_input() below. */
7219 if (!interactive_mode
&& !cmd_file_mode
) {
7221 * If we're not in interactive mode, and we're not in command
7222 * file mode, then we must be in commands-from-the-command-line
7223 * mode. As such, we can't loop back and ask for more input.
7224 * It was OK to prompt for such things as whether or not to
7225 * really delete a zone in the command handler called from
7226 * yyparse() above, but "really quit?" makes no sense in this
7227 * context. So disable prompting.
7229 ok_to_prompt
= B_FALSE
;
7231 if (!global_scope
) {
7232 if (!time_to_exit
) {
7234 * Just print a simple error message in the -1 case,
7235 * since exit_func() already handles that case, and
7236 * EOF means we are finished anyway.
7238 answer
= ask_yesno(B_FALSE
,
7239 gettext("Resource incomplete; really quit"));
7241 zerr(gettext("Resource incomplete."));
7253 * Make sure we tried something and that the handle checks
7254 * out, or we would get a false error trying to commit.
7256 if (need_to_commit
&& zonecfg_check_handle(handle
) == Z_OK
) {
7257 if ((cmd
= alloc_cmd()) == NULL
) {
7258 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
7262 cmd
->cmd_argv
[0] = NULL
;
7266 * need_to_commit will get set back to FALSE if the
7267 * configuration is saved successfully.
7269 if (need_to_commit
) {
7271 zerr(gettext("Configuration not saved."));
7274 answer
= ask_yesno(B_FALSE
,
7275 gettext("Configuration not saved; really quit"));
7277 zerr(gettext("Configuration not saved."));
7281 time_to_exit
= B_FALSE
;
7287 return ((need_to_commit
|| saw_error
) ? Z_ERR
: Z_OK
);
7291 * read_input() is the driver of this program. It is a wrapper around
7292 * yyparse(), printing appropriate prompts when needed, checking for
7293 * exit conditions and reacting appropriately [the latter in its cleanup()
7296 * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
7297 * so do_interactive() knows that we are not really done (i.e, we asked
7298 * the user if we should really quit and the user said no).
7303 boolean_t yyin_is_a_tty
= isatty(fileno(yyin
));
7305 * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
7306 * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
7308 char prompt
[MAXPATHLEN
+ ZONENAME_MAX
+ MAX_RT_STRLEN
+ 5], *line
;
7310 /* yyin should have been set to the appropriate (FILE *) if not stdin */
7311 newline_terminated
= B_TRUE
;
7313 if (yyin_is_a_tty
) {
7314 if (newline_terminated
) {
7316 (void) snprintf(prompt
, sizeof (prompt
),
7317 "%s:%s> ", execname
, zone
);
7319 (void) snprintf(prompt
, sizeof (prompt
),
7320 "%s:%s:%s> ", execname
, zone
,
7321 rt_to_str(resource_scope
));
7324 * If the user hits ^C then we want to catch it and
7325 * start over. If the user hits EOF then we want to
7328 line
= gl_get_line(gl
, prompt
, NULL
, -1);
7329 if (gl_return_status(gl
) == GLR_SIGNAL
) {
7330 gl_abandon_line(gl
);
7335 (void) string_to_yyin(line
);
7341 /* Bail out on an error in command file mode. */
7342 if (saw_error
&& cmd_file_mode
&& !interactive_mode
)
7343 time_to_exit
= B_TRUE
;
7344 if (time_to_exit
|| (!yyin_is_a_tty
&& feof(yyin
)))
7351 * This function is used in the zonecfg-interactive-mode scenario: it just
7352 * calls read_input() until we are done.
7356 do_interactive(void)
7360 interactive_mode
= B_TRUE
;
7361 if (!read_only_mode
) {
7363 * Try to set things up proactively in interactive mode, so
7364 * that if the zone in question does not exist yet, we can
7365 * provide the user with a clue.
7367 (void) initialize(B_FALSE
);
7371 } while (err
== Z_REPEAT
);
7376 * cmd_file is slightly more complicated, as it has to open the command file
7377 * and set yyin appropriately. Once that is done, though, it just calls
7378 * read_input(), and only once, since prompting is not possible.
7382 cmd_file(char *file
)
7386 struct stat statbuf
;
7387 boolean_t using_real_file
= (strcmp(file
, "-") != 0);
7389 if (using_real_file
) {
7391 * zerr() prints a line number in cmd_file_mode, which we do
7392 * not want here, so temporarily unset it.
7394 cmd_file_mode
= B_FALSE
;
7395 if ((infile
= fopen(file
, "r")) == NULL
) {
7396 zerr(gettext("could not open file %s: %s"),
7397 file
, strerror(errno
));
7400 if ((err
= fstat(fileno(infile
), &statbuf
)) != 0) {
7401 zerr(gettext("could not stat file %s: %s"),
7402 file
, strerror(errno
));
7406 if (!S_ISREG(statbuf
.st_mode
)) {
7407 zerr(gettext("%s is not a regular file."), file
);
7412 cmd_file_mode
= B_TRUE
;
7413 ok_to_prompt
= B_FALSE
;
7416 * "-f -" is essentially the same as interactive mode,
7417 * so treat it that way.
7419 interactive_mode
= B_TRUE
;
7421 /* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
7422 if ((err
= read_input()) == Z_REPEAT
)
7425 if (using_real_file
)
7426 (void) fclose(infile
);
7431 * Since yacc is based on reading from a (FILE *) whereas what we get from
7432 * the command line is in argv format, we need to convert when the user
7433 * gives us commands directly from the command line. That is done here by
7434 * concatenating the argv list into a space-separated string, writing it
7435 * to a temp file, and rewinding the file so yyin can be set to it. Then
7436 * we call read_input(), and only once, since prompting about whether to
7437 * continue or quit would make no sense in this context.
7441 one_command_at_a_time(int argc
, char *argv
[])
7444 size_t len
= 2; /* terminal \n\0 */
7447 for (i
= 0; i
< argc
; i
++)
7448 len
+= strlen(argv
[i
]) + 1;
7449 if ((command
= malloc(len
)) == NULL
) {
7450 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7453 (void) strlcpy(command
, argv
[0], len
);
7454 for (i
= 1; i
< argc
; i
++) {
7455 (void) strlcat(command
, " ", len
);
7456 (void) strlcat(command
, argv
[i
], len
);
7458 (void) strlcat(command
, "\n", len
);
7459 err
= string_to_yyin(command
);
7469 get_execbasename(char *execfullname
)
7471 char *last_slash
, *execbasename
;
7473 /* guard against '/' at end of command invocation */
7475 last_slash
= strrchr(execfullname
, '/');
7476 if (last_slash
== NULL
) {
7477 execbasename
= execfullname
;
7480 execbasename
= last_slash
+ 1;
7481 if (*execbasename
== '\0') {
7488 return (execbasename
);
7492 main(int argc
, char *argv
[])
7497 /* This must be before anything goes to stdout. */
7498 setbuf(stdout
, NULL
);
7500 saw_error
= B_FALSE
;
7501 cmd_file_mode
= B_FALSE
;
7502 execname
= get_execbasename(argv
[0]);
7504 (void) setlocale(LC_ALL
, "");
7505 (void) textdomain(TEXT_DOMAIN
);
7507 if (getzoneid() != GLOBAL_ZONEID
) {
7508 zerr(gettext("%s can only be run from the global zone."),
7514 usage(B_FALSE
, HELP_USAGE
| HELP_SUBCMDS
);
7517 if (strcmp(argv
[1], cmd_to_str(CMD_HELP
)) == 0) {
7518 (void) one_command_at_a_time(argc
- 1, &(argv
[1]));
7522 while ((arg
= getopt(argc
, argv
, "?f:R:z:")) != EOF
) {
7526 usage(B_TRUE
, HELP_USAGE
| HELP_SUBCMDS
);
7528 usage(B_FALSE
, HELP_USAGE
);
7532 cmd_file_name
= optarg
;
7533 cmd_file_mode
= B_TRUE
;
7536 if (*optarg
!= '/') {
7537 zerr(gettext("root path must be absolute: %s"),
7541 if (stat(optarg
, &st
) == -1 || !S_ISDIR(st
.st_mode
)) {
7543 "root path must be a directory: %s"),
7547 zonecfg_set_root(optarg
);
7550 if (strcmp(optarg
, GLOBAL_ZONENAME
) == 0) {
7551 global_zone
= B_TRUE
;
7552 } else if (zonecfg_validate_zonename(optarg
) != Z_OK
) {
7553 zone_perror(optarg
, Z_BOGUS_ZONE_NAME
, B_TRUE
);
7554 usage(B_FALSE
, HELP_SYNTAX
);
7557 (void) strlcpy(zone
, optarg
, sizeof (zone
));
7558 (void) strlcpy(revert_zone
, optarg
, sizeof (zone
));
7561 usage(B_FALSE
, HELP_USAGE
);
7566 if (optind
> argc
|| strcmp(zone
, "") == 0) {
7567 usage(B_FALSE
, HELP_USAGE
);
7571 if ((err
= zonecfg_access(zone
, W_OK
)) == Z_OK
) {
7572 read_only_mode
= B_FALSE
;
7573 } else if (err
== Z_ACCES
) {
7574 read_only_mode
= B_TRUE
;
7575 /* skip this message in one-off from command line mode */
7577 (void) fprintf(stderr
, gettext("WARNING: you do not "
7578 "have write access to this zone's configuration "
7579 "file;\ngoing into read-only mode.\n"));
7581 fprintf(stderr
, "%s: Could not access zone configuration "
7582 "store: %s\n", execname
, zonecfg_strerror(err
));
7586 if ((handle
= zonecfg_init_handle()) == NULL
) {
7587 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7592 * This may get set back to FALSE again in cmd_file() if cmd_file_name
7593 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
7595 if (isatty(STDIN_FILENO
))
7596 ok_to_prompt
= B_TRUE
;
7597 if ((gl
= new_GetLine(MAX_LINE_LEN
, MAX_CMD_HIST
)) == NULL
)
7599 if (gl_customize_completion(gl
, NULL
, cmd_cpl_fn
) != 0)
7601 (void) sigset(SIGINT
, SIG_IGN
);
7602 if (optind
== argc
) {
7604 err
= do_interactive();
7606 err
= cmd_file(cmd_file_name
);
7608 err
= one_command_at_a_time(argc
- optind
, &(argv
[optind
]));
7610 zonecfg_fini_handle(handle
);
7613 (void) del_GetLine(gl
);