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 if (complex->cp_value
!= NULL
)
743 free(complex->cp_value
);
750 return (calloc(1, sizeof (list_property_t
)));
754 free_list(list_property_ptr_t list
)
758 if (list
->lp_simple
!= NULL
)
759 free(list
->lp_simple
);
760 free_complex(list
->lp_complex
);
761 free_list(list
->lp_next
);
766 free_outer_list(list_property_ptr_t list
)
770 free_outer_list(list
->lp_next
);
774 static struct zone_rctlvaltab
*
775 alloc_rctlvaltab(void)
777 return (calloc(1, sizeof (struct zone_rctlvaltab
)));
781 rt_to_str(int res_type
)
783 assert(res_type
>= RT_MIN
&& res_type
<= RT_MAX
);
784 return (res_types
[res_type
]);
788 pt_to_str(int prop_type
)
790 assert(prop_type
>= PT_MIN
&& prop_type
<= PT_MAX
);
791 return (prop_types
[prop_type
]);
795 pvt_to_str(int pv_type
)
797 assert(pv_type
>= PROP_VAL_MIN
&& pv_type
<= PROP_VAL_MAX
);
798 return (prop_val_types
[pv_type
]);
802 cmd_to_str(int cmd_num
)
804 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
805 return (helptab
[cmd_num
].cmd_name
);
810 zerr(const char *fmt
, ...)
813 static int last_lineno
;
815 /* lex_lineno has already been incremented in the lexer; compensate */
816 if (cmd_file_mode
&& lex_lineno
> last_lineno
) {
817 if (strcmp(cmd_file_name
, "-") == 0)
818 (void) fprintf(stderr
, gettext("On line %d:\n"),
821 (void) fprintf(stderr
, gettext("On line %d of %s:\n"),
822 lex_lineno
- 1, cmd_file_name
);
823 last_lineno
= lex_lineno
;
825 va_start(alist
, fmt
);
826 (void) vfprintf(stderr
, fmt
, alist
);
827 (void) fprintf(stderr
, "\n");
832 * This is a separate function rather than a set of define's because of the
833 * gettext() wrapping.
838 * Each string below should have \t follow \n whenever needed; the
839 * initial \t and the terminal \n will be provided by the calling function.
843 long_help(int cmd_num
)
845 static char line
[1024]; /* arbitrary large amount */
847 assert(cmd_num
>= CMD_MIN
&& cmd_num
<= CMD_MAX
);
850 return (gettext("Prints help message."));
852 (void) snprintf(line
, sizeof (line
),
853 gettext("Creates a configuration for the "
854 "specified zone. %s should be\n\tused to "
855 "begin configuring a new zone. If overwriting an "
856 "existing\n\tconfiguration, the -F flag can be "
857 "used to force the action. If\n\t-t template is "
858 "given, creates a configuration identical to the\n"
859 "\tspecified template, except that the zone name "
860 "is changed from\n\ttemplate to zonename. '%s -a' "
861 "creates a configuration from a\n\tdetached "
862 "zonepath. '%s -b' results in a blank "
863 "configuration.\n\t'%s' with no arguments applies "
864 "the Sun default settings."),
865 cmd_to_str(CMD_CREATE
), cmd_to_str(CMD_CREATE
),
866 cmd_to_str(CMD_CREATE
), cmd_to_str(CMD_CREATE
));
869 return (gettext("Exits the program. The -F flag can "
870 "be used to force the action."));
872 return (gettext("Prints configuration to standard "
873 "output, or to output-file if\n\tspecified, in "
874 "a form suitable for use in a command-file."));
876 return (gettext("Add specified resource to "
879 return (gettext("Deletes the specified zone. The -F "
880 "flag can be used to force the\n\taction."));
882 return (gettext("Remove specified resource from "
883 "configuration. The -F flag can be used\n\tto "
884 "force the action."));
886 (void) snprintf(line
, sizeof (line
),
887 gettext("Selects a resource to modify. "
888 "Resource modification is completed\n\twith the "
889 "command \"%s\". The property name/value pairs "
890 "must uniquely\n\tidentify a resource. Note that "
891 "the curly braces ('{', '}') mean one\n\tor more "
892 "of whatever is between them."),
893 cmd_to_str(CMD_END
));
896 return (gettext("Sets property values."));
898 return (gettext("Clears property values."));
900 return (gettext("Displays information about the "
901 "current configuration. If resource\n\ttype is "
902 "specified, displays only information about "
903 "resources of\n\tthe relevant type. If resource "
904 "id is specified, displays only\n\tinformation "
905 "about that resource."));
907 return (gettext("Verifies current configuration "
908 "for correctness (some resource types\n\thave "
909 "required properties)."));
911 (void) snprintf(line
, sizeof (line
),
912 gettext("Commits current configuration. "
913 "Configuration must be committed to\n\tbe used by "
914 "%s. Until the configuration is committed, "
915 "changes \n\tcan be removed with the %s "
916 "command. This operation is\n\tattempted "
917 "automatically upon completion of a %s "
918 "session."), "zoneadm", cmd_to_str(CMD_REVERT
),
922 return (gettext("Reverts configuration back to the "
923 "last committed state. The -F flag\n\tcan be "
924 "used to force the action."));
926 return (gettext("Cancels resource/property "
929 return (gettext("Ends resource/property "
937 * Return the input filename appended to each component of the path
938 * or the filename itself if it is absolute.
939 * Parameters: path string, file name, output string.
941 /* Copied almost verbatim from libtnfctl/prb_findexec.c */
943 exec_cat(const char *s1
, const char *s2
, char *si
)
946 /* Number of remaining characters in s */
947 int cnt
= PATH_MAX
+ 1;
950 while (*s1
&& *s1
!= ':') { /* Copy first component of path to si */
958 if (si
!= s
&& cnt
> 0) { /* Add slash if s2 is not absolute */
962 while (*s2
&& cnt
> 0) { /* Copy s2 to si */
966 *s
= '\0'; /* Terminate the output string */
967 return (*s1
? ++s1
: NULL
); /* Return next path component or NULL */
970 /* Determine that a name exists in PATH */
971 /* Copied with changes from libtnfctl/prb_findexec.c */
973 path_find(const char *name
)
976 char fname
[PATH_MAX
+ 2];
978 struct stat stat_buf
;
980 if ((pathstr
= getenv("PATH")) == NULL
) {
981 if (geteuid() == 0 || getuid() == 0)
982 pathstr
= "/usr/sbin:/usr/bin";
984 pathstr
= "/usr/bin:";
986 cp
= strchr(name
, '/') ? (const char *) "" : pathstr
;
989 cp
= exec_cat(cp
, name
, fname
);
990 if (stat(fname
, &stat_buf
) != -1) {
991 /* successful find of the file */
994 } while (cp
!= NULL
);
1003 char *pager
, *space
;
1005 pager
= getenv("PAGER");
1006 if (pager
== NULL
|| *pager
== '\0')
1009 space
= strchr(pager
, ' ');
1012 if (path_find(pager
) == 0) {
1015 if ((newfp
= popen(pager
, "w")) == NULL
)
1016 zerr(gettext("PAGER open failed (%s)."),
1020 zerr(gettext("PAGER %s does not exist (%s)."),
1021 pager
, strerror(errno
));
1027 pager_close(FILE *fp
)
1031 status
= pclose(fp
);
1033 zerr(gettext("PAGER close failed (%s)."),
1038 * Called with verbose TRUE when help is explicitly requested, FALSE for
1039 * unexpected errors.
1043 usage(boolean_t verbose
, uint_t flags
)
1045 FILE *fp
= verbose
? stdout
: stderr
;
1047 boolean_t need_to_close
= B_FALSE
;
1050 /* don't page error output */
1051 if (verbose
&& interactive_mode
) {
1052 if ((newfp
= pager_open()) != NULL
) {
1053 need_to_close
= B_TRUE
;
1058 if (flags
& HELP_META
) {
1059 (void) fprintf(fp
, gettext("More help is available for the "
1061 (void) fprintf(fp
, "\n\tcommands ('%s commands')\n",
1062 cmd_to_str(CMD_HELP
));
1063 (void) fprintf(fp
, "\tsyntax ('%s syntax')\n",
1064 cmd_to_str(CMD_HELP
));
1065 (void) fprintf(fp
, "\tusage ('%s usage')\n\n",
1066 cmd_to_str(CMD_HELP
));
1067 (void) fprintf(fp
, gettext("You may also obtain help on any "
1068 "command by typing '%s <command-name>.'\n"),
1069 cmd_to_str(CMD_HELP
));
1071 if (flags
& HELP_RES_SCOPE
) {
1072 switch (resource_scope
) {
1074 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1075 "used to configure a file-system.\n"),
1076 rt_to_str(resource_scope
));
1077 (void) fprintf(fp
, gettext("Valid commands:\n"));
1078 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1079 pt_to_str(PT_DIR
), gettext("<path>"));
1080 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1081 pt_to_str(PT_SPECIAL
), gettext("<path>"));
1082 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1083 pt_to_str(PT_RAW
), gettext("<raw-device>"));
1084 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1085 pt_to_str(PT_TYPE
), gettext("<file-system type>"));
1086 (void) fprintf(fp
, "\t%s %s %s\n", cmd_to_str(CMD_ADD
),
1087 pt_to_str(PT_OPTIONS
),
1088 gettext("<file-system options>"));
1089 (void) fprintf(fp
, "\t%s %s %s\n",
1090 cmd_to_str(CMD_REMOVE
), pt_to_str(PT_OPTIONS
),
1091 gettext("<file-system options>"));
1092 (void) fprintf(fp
, gettext("Consult the file-system "
1093 "specific manual page, such as mount_ufs(1M), "
1094 "for\ndetails about file-system options. Note "
1095 "that any file-system options with an\nembedded "
1096 "'=' character must be enclosed in double quotes, "
1098 "such as \"%s=5\".\n"), MNTOPT_RETRY
);
1101 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1102 "used to configure a network interface.\n"),
1103 rt_to_str(resource_scope
));
1104 (void) fprintf(fp
, gettext("Valid commands:\n"));
1105 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1106 pt_to_str(PT_ADDRESS
), gettext("<IP-address>"));
1107 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1108 pt_to_str(PT_ALLOWED_ADDRESS
),
1109 gettext("<IP-address>"));
1110 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1111 pt_to_str(PT_PHYSICAL
), gettext("<interface>"));
1112 (void) fprintf(fp
, gettext("See ifconfig(1M) for "
1113 "details of the <interface> string.\n"));
1114 (void) fprintf(fp
, gettext("%s %s is valid "
1115 "if the %s property is set to %s, otherwise it "
1116 "must not be set.\n"),
1117 cmd_to_str(CMD_SET
), pt_to_str(PT_ADDRESS
),
1118 pt_to_str(PT_IPTYPE
), gettext("shared"));
1119 (void) fprintf(fp
, gettext("%s %s is valid "
1120 "if the %s property is set to %s, otherwise it "
1121 "must not be set.\n"),
1122 cmd_to_str(CMD_SET
), pt_to_str(PT_ALLOWED_ADDRESS
),
1123 pt_to_str(PT_IPTYPE
), gettext("exclusive"));
1124 (void) fprintf(fp
, gettext("\t%s %s=%s\n%s %s "
1125 "is valid if the %s or %s property is set, "
1126 "otherwise it must not be set\n"),
1127 cmd_to_str(CMD_SET
),
1128 pt_to_str(PT_DEFROUTER
), gettext("<IP-address>"),
1129 cmd_to_str(CMD_SET
), pt_to_str(PT_DEFROUTER
),
1130 gettext(pt_to_str(PT_ADDRESS
)),
1131 gettext(pt_to_str(PT_ALLOWED_ADDRESS
)));
1134 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1135 "used to configure a device node.\n"),
1136 rt_to_str(resource_scope
));
1137 (void) fprintf(fp
, gettext("Valid commands:\n"));
1138 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1139 pt_to_str(PT_MATCH
), gettext("<device-path>"));
1142 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1143 "used to configure a resource control.\n"),
1144 rt_to_str(resource_scope
));
1145 (void) fprintf(fp
, gettext("Valid commands:\n"));
1146 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1147 pt_to_str(PT_NAME
), gettext("<string>"));
1148 (void) fprintf(fp
, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1149 cmd_to_str(CMD_ADD
), pt_to_str(PT_VALUE
),
1150 pt_to_str(PT_PRIV
), gettext("<priv-value>"),
1151 pt_to_str(PT_LIMIT
), gettext("<number>"),
1152 pt_to_str(PT_ACTION
), gettext("<action-value>"));
1153 (void) fprintf(fp
, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1154 cmd_to_str(CMD_REMOVE
), pt_to_str(PT_VALUE
),
1155 pt_to_str(PT_PRIV
), gettext("<priv-value>"),
1156 pt_to_str(PT_LIMIT
), gettext("<number>"),
1157 pt_to_str(PT_ACTION
), gettext("<action-value>"));
1158 (void) fprintf(fp
, "%s\n\t%s := privileged\n"
1159 "\t%s := none | deny\n", gettext("Where"),
1160 gettext("<priv-value>"), gettext("<action-value>"));
1163 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1164 "used to configure a generic attribute.\n"),
1165 rt_to_str(resource_scope
));
1166 (void) fprintf(fp
, gettext("Valid commands:\n"));
1167 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1168 pt_to_str(PT_NAME
), gettext("<name>"));
1169 (void) fprintf(fp
, "\t%s %s=boolean\n",
1170 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1171 (void) fprintf(fp
, "\t%s %s=true | false\n",
1172 cmd_to_str(CMD_SET
), pt_to_str(PT_VALUE
));
1173 (void) fprintf(fp
, gettext("or\n"));
1174 (void) fprintf(fp
, "\t%s %s=int\n", cmd_to_str(CMD_SET
),
1175 pt_to_str(PT_TYPE
));
1176 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1177 pt_to_str(PT_VALUE
), gettext("<integer>"));
1178 (void) fprintf(fp
, gettext("or\n"));
1179 (void) fprintf(fp
, "\t%s %s=string\n",
1180 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1181 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1182 pt_to_str(PT_VALUE
), gettext("<string>"));
1183 (void) fprintf(fp
, gettext("or\n"));
1184 (void) fprintf(fp
, "\t%s %s=uint\n",
1185 cmd_to_str(CMD_SET
), pt_to_str(PT_TYPE
));
1186 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1187 pt_to_str(PT_VALUE
), gettext("<unsigned integer>"));
1190 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1191 "used to export ZFS datasets.\n"),
1192 rt_to_str(resource_scope
));
1193 (void) fprintf(fp
, gettext("Valid commands:\n"));
1194 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1195 pt_to_str(PT_NAME
), gettext("<name>"));
1198 (void) fprintf(fp
, gettext("The '%s' resource scope "
1199 "configures the 'pools' facility to dedicate\na "
1200 "subset of the system's processors to this zone "
1201 "while it is running.\n"),
1202 rt_to_str(resource_scope
));
1203 (void) fprintf(fp
, gettext("Valid commands:\n"));
1204 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1205 pt_to_str(PT_NCPUS
),
1206 gettext("<unsigned integer | range>"));
1207 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1208 pt_to_str(PT_IMPORTANCE
),
1209 gettext("<unsigned integer>"));
1212 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1213 "used to set an upper limit (a cap) on the\n"
1214 "percentage of CPU that can be used by this zone. "
1215 "A '%s' value of 1\ncorresponds to one cpu. The "
1216 "value can be set higher than 1, up to the total\n"
1217 "number of CPUs on the system. The value can "
1218 "also be less than 1,\nrepresenting a fraction of "
1220 rt_to_str(resource_scope
), pt_to_str(PT_NCPUS
));
1221 (void) fprintf(fp
, gettext("Valid commands:\n"));
1222 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1223 pt_to_str(PT_NCPUS
), gettext("<unsigned decimal>"));
1226 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1227 "used to set an upper limit (a cap) on the\n"
1228 "amount of physical memory, swap space and locked "
1229 "memory that can be used by\nthis zone.\n"),
1230 rt_to_str(resource_scope
));
1231 (void) fprintf(fp
, gettext("Valid commands:\n"));
1232 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1233 pt_to_str(PT_PHYSICAL
),
1234 gettext("<qualified unsigned decimal>"));
1235 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1237 gettext("<qualified unsigned decimal>"));
1238 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1239 pt_to_str(PT_LOCKED
),
1240 gettext("<qualified unsigned decimal>"));
1243 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1244 "used to delegate specific zone management\n"
1245 "rights to users and roles. These rights are "
1246 "only applicable to this zone.\n"),
1247 rt_to_str(resource_scope
));
1248 (void) fprintf(fp
, gettext("Valid commands:\n"));
1249 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1251 gettext("<single user or role name>"));
1252 (void) fprintf(fp
, "\t%s %s=%s\n", cmd_to_str(CMD_SET
),
1253 pt_to_str(PT_AUTHS
),
1254 gettext("<comma separated list>"));
1257 (void) fprintf(fp
, gettext("The '%s' resource scope is "
1258 "used to specify the default security-flags\n"
1259 "of this zone, and their upper and lower bound.\n"),
1260 rt_to_str(resource_scope
));
1261 (void) fprintf(fp
, "\t%s %s=%s\n",
1262 cmd_to_str(CMD_SET
), pt_to_str(PT_DEFAULT
),
1263 gettext("<security flags>"));
1264 (void) fprintf(fp
, "\t%s %s=%s\n",
1265 cmd_to_str(CMD_SET
), pt_to_str(PT_LOWER
),
1266 gettext("<security flags>"));
1267 (void) fprintf(fp
, "\t%s %s=%s\n",
1268 cmd_to_str(CMD_SET
), pt_to_str(PT_UPPER
),
1269 gettext("<security flags>"));
1272 (void) fprintf(fp
, gettext("And from any resource scope, you "
1274 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_END
),
1275 gettext("(to conclude this operation)"));
1276 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL
),
1277 gettext("(to cancel this operation)"));
1278 (void) fprintf(fp
, "\t%s\t%s\n", cmd_to_str(CMD_EXIT
),
1279 gettext("(to exit the zonecfg utility)"));
1281 if (flags
& HELP_USAGE
) {
1282 (void) fprintf(fp
, "%s:\t%s %s\n", gettext("usage"),
1283 execname
, cmd_to_str(CMD_HELP
));
1284 (void) fprintf(fp
, "\t%s -z <zone>\t\t\t(%s)\n",
1285 execname
, gettext("interactive"));
1286 (void) fprintf(fp
, "\t%s -z <zone> <command>\n", execname
);
1287 (void) fprintf(fp
, "\t%s -z <zone> -f <command-file>\n",
1290 if (flags
& HELP_SUBCMDS
) {
1291 (void) fprintf(fp
, "%s:\n\n", gettext("Commands"));
1292 for (i
= 0; i
<= CMD_MAX
; i
++) {
1293 (void) fprintf(fp
, "%s\n", helptab
[i
].short_usage
);
1295 (void) fprintf(fp
, "\t%s\n\n", long_help(i
));
1298 if (flags
& HELP_SYNTAX
) {
1300 (void) fprintf(fp
, "\n");
1301 (void) fprintf(fp
, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1302 (void) fprintf(fp
, gettext("\t(except the reserved words "
1303 "'%s' and anything starting with '%s')\n"), "global",
1306 gettext("\tName must be less than %d characters.\n"),
1309 (void) fprintf(fp
, "\n");
1311 if (flags
& HELP_NETADDR
) {
1312 (void) fprintf(fp
, gettext("\n<net-addr> :="));
1314 gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
1316 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1318 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1319 (void) fprintf(fp
, gettext("See inet(3SOCKET) for IPv4 and "
1320 "IPv6 address syntax.\n"));
1321 (void) fprintf(fp
, gettext("<IPv4-prefix-length> := [0-32]\n"));
1323 gettext("<IPv6-prefix-length> := [0-128]\n"));
1325 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1327 if (flags
& HELP_RESOURCES
) {
1328 (void) fprintf(fp
, "<%s> := %s | %s | %s | %s | %s |\n\t"
1329 "%s | %s | %s | %s | %s\n\n",
1330 gettext("resource type"), rt_to_str(RT_FS
),
1331 rt_to_str(RT_NET
), rt_to_str(RT_DEVICE
),
1332 rt_to_str(RT_RCTL
), rt_to_str(RT_ATTR
),
1333 rt_to_str(RT_DATASET
), rt_to_str(RT_DCPU
),
1334 rt_to_str(RT_PCAP
), rt_to_str(RT_MCAP
),
1335 rt_to_str(RT_ADMIN
), rt_to_str(RT_SECFLAGS
));
1337 if (flags
& HELP_PROPS
) {
1338 (void) fprintf(fp
, gettext("For resource type ... there are "
1339 "property types ...:\n"));
1340 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1341 pt_to_str(PT_ZONENAME
));
1342 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1343 pt_to_str(PT_ZONEPATH
));
1344 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1345 pt_to_str(PT_BRAND
));
1346 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1347 pt_to_str(PT_AUTOBOOT
));
1348 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1349 pt_to_str(PT_BOOTARGS
));
1350 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1351 pt_to_str(PT_POOL
));
1352 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1353 pt_to_str(PT_LIMITPRIV
));
1354 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1355 pt_to_str(PT_SCHED
));
1356 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1357 pt_to_str(PT_IPTYPE
));
1358 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1359 pt_to_str(PT_HOSTID
));
1360 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1361 pt_to_str(PT_FS_ALLOWED
));
1362 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1363 pt_to_str(PT_MAXLWPS
));
1364 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1365 pt_to_str(PT_MAXPROCS
));
1366 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1367 pt_to_str(PT_MAXSHMMEM
));
1368 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1369 pt_to_str(PT_MAXSHMIDS
));
1370 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1371 pt_to_str(PT_MAXMSGIDS
));
1372 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1373 pt_to_str(PT_MAXSEMIDS
));
1374 (void) fprintf(fp
, "\t%s\t%s\n", gettext("(global)"),
1375 pt_to_str(PT_SHARES
));
1376 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s, %s, %s\n",
1377 rt_to_str(RT_FS
), pt_to_str(PT_DIR
),
1378 pt_to_str(PT_SPECIAL
), pt_to_str(PT_RAW
),
1379 pt_to_str(PT_TYPE
), pt_to_str(PT_OPTIONS
));
1380 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET
),
1381 pt_to_str(PT_ADDRESS
), pt_to_str(PT_ALLOWED_ADDRESS
),
1382 pt_to_str(PT_PHYSICAL
), pt_to_str(PT_DEFROUTER
));
1383 (void) fprintf(fp
, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE
),
1384 pt_to_str(PT_MATCH
));
1385 (void) fprintf(fp
, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL
),
1386 pt_to_str(PT_NAME
), pt_to_str(PT_VALUE
));
1387 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR
),
1388 pt_to_str(PT_NAME
), pt_to_str(PT_TYPE
),
1389 pt_to_str(PT_VALUE
));
1390 (void) fprintf(fp
, "\t%s\t\t%s\n", rt_to_str(RT_DATASET
),
1391 pt_to_str(PT_NAME
));
1392 (void) fprintf(fp
, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU
),
1393 pt_to_str(PT_NCPUS
), pt_to_str(PT_IMPORTANCE
));
1394 (void) fprintf(fp
, "\t%s\t%s\n", rt_to_str(RT_PCAP
),
1395 pt_to_str(PT_NCPUS
));
1396 (void) fprintf(fp
, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP
),
1397 pt_to_str(PT_PHYSICAL
), pt_to_str(PT_SWAP
),
1398 pt_to_str(PT_LOCKED
));
1399 (void) fprintf(fp
, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN
),
1400 pt_to_str(PT_USER
), pt_to_str(PT_AUTHS
));
1401 (void) fprintf(fp
, "\t%s\t\t%s, %s, %s\n",
1402 rt_to_str(RT_SECFLAGS
), pt_to_str(PT_DEFAULT
),
1403 pt_to_str(PT_LOWER
), pt_to_str(PT_UPPER
));
1406 (void) pager_close(fp
);
1410 zone_perror(char *prefix
, int err
, boolean_t set_saw
)
1412 zerr("%s: %s", prefix
, zonecfg_strerror(err
));
1418 * zone_perror() expects a single string, but for remove and select
1419 * we have both the command and the resource type, so this wrapper
1420 * function serves the same purpose in a slightly different way.
1424 z_cmd_rt_perror(int cmd_num
, int res_num
, int err
, boolean_t set_saw
)
1426 zerr("%s %s: %s", cmd_to_str(cmd_num
), rt_to_str(res_num
),
1427 zonecfg_strerror(err
));
1432 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
1434 initialize(boolean_t handle_expected
)
1437 char brandname
[MAXNAMELEN
];
1439 if (zonecfg_check_handle(handle
) != Z_OK
) {
1440 if ((err
= zonecfg_get_handle(zone
, handle
)) == Z_OK
) {
1441 got_handle
= B_TRUE
;
1442 if (zonecfg_get_brand(handle
, brandname
,
1443 sizeof (brandname
)) != Z_OK
) {
1444 zerr("Zone %s is inconsistent: missing "
1445 "brand attribute", zone
);
1448 if ((brand
= brand_open(brandname
)) == NULL
) {
1449 zerr("Zone %s uses non-existent brand \"%s\"."
1450 " Unable to continue", zone
, brandname
);
1454 * If the user_attr file is newer than
1455 * the zone config file, the admins
1456 * may need to be updated since the
1457 * RBAC files are authoritative for
1458 * authorization checks.
1460 err
= zonecfg_update_userauths(handle
, zone
);
1462 zerr(gettext("The administrative rights "
1463 "were updated to match "
1464 "the current RBAC configuration.\n"
1465 "Use \"info admin\" and \"revert\" to "
1466 "compare with the previous settings."));
1467 need_to_commit
= B_TRUE
;
1468 } else if (err
!= Z_NO_ENTRY
) {
1469 zerr(gettext("failed to update "
1472 } else if (need_to_commit
) {
1473 zerr(gettext("admin rights were updated "
1474 "to match RBAC configuration."));
1477 } else if (global_zone
&& err
== Z_NO_ZONE
&& !got_handle
&&
1480 * We implicitly create the global zone config if it
1483 zone_dochandle_t tmphandle
;
1485 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1486 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1490 err
= zonecfg_get_template_handle("SUNWblank", zone
,
1494 zonecfg_fini_handle(tmphandle
);
1495 zone_perror("SUNWblank", err
, B_TRUE
);
1499 need_to_commit
= B_TRUE
;
1500 zonecfg_fini_handle(handle
);
1502 got_handle
= B_TRUE
;
1505 zone_perror(zone
, err
, handle_expected
|| got_handle
);
1506 if (err
== Z_NO_ZONE
&& !got_handle
&&
1507 interactive_mode
&& !read_only_mode
)
1508 (void) printf(gettext("Use '%s' to begin "
1509 "configuring a new zone.\n"),
1510 cmd_to_str(CMD_CREATE
));
1518 state_atleast(zone_state_t state
)
1520 zone_state_t state_num
;
1523 if ((err
= zone_get_state(zone
, &state_num
)) != Z_OK
) {
1524 /* all states are greater than "non-existent" */
1525 if (err
== Z_NO_ZONE
)
1527 zerr(gettext("Unexpectedly failed to determine state "
1528 "of zone %s: %s"), zone
, zonecfg_strerror(err
));
1531 return (state_num
>= state
);
1535 * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
1539 short_usage(int command
)
1541 /* lex_lineno has already been incremented in the lexer; compensate */
1542 if (cmd_file_mode
) {
1543 if (strcmp(cmd_file_name
, "-") == 0)
1544 (void) fprintf(stderr
,
1545 gettext("syntax error on line %d\n"),
1548 (void) fprintf(stderr
,
1549 gettext("syntax error on line %d of %s\n"),
1550 lex_lineno
- 1, cmd_file_name
);
1552 (void) fprintf(stderr
, "%s:\n%s\n", gettext("usage"),
1553 helptab
[command
].short_usage
);
1558 * long_usage() is for bad semantics: e.g., wrong property type for a given
1559 * resource type. It is also used by longer_usage() below.
1563 long_usage(uint_t cmd_num
, boolean_t set_saw
)
1565 (void) fprintf(set_saw
? stderr
: stdout
, "%s:\n%s\n", gettext("usage"),
1566 helptab
[cmd_num
].short_usage
);
1567 (void) fprintf(set_saw
? stderr
: stdout
, "\t%s\n", long_help(cmd_num
));
1573 * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
1574 * any extra usage() flags as appropriate for whatever command.
1578 longer_usage(uint_t cmd_num
)
1580 long_usage(cmd_num
, B_FALSE
);
1581 if (helptab
[cmd_num
].flags
!= 0) {
1582 (void) printf("\n");
1583 usage(B_TRUE
, helptab
[cmd_num
].flags
);
1588 * scope_usage() is simply used when a command is called from the wrong scope.
1592 scope_usage(uint_t cmd_num
)
1594 zerr(gettext("The %s command only makes sense in the %s scope."),
1595 cmd_to_str(cmd_num
),
1596 global_scope
? gettext("resource") : gettext("global"));
1601 * On input, B_TRUE => yes, B_FALSE => no.
1602 * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
1606 ask_yesno(boolean_t default_answer
, const char *question
)
1608 char line
[64]; /* should be enough to answer yes or no */
1610 if (!ok_to_prompt
) {
1615 if (printf("%s (%s)? ", question
,
1616 default_answer
? "[y]/n" : "y/[n]") < 0)
1618 if (fgets(line
, sizeof (line
), stdin
) == NULL
)
1621 if (line
[0] == '\n')
1622 return (default_answer
? 1 : 0);
1623 if (tolower(line
[0]) == 'y')
1625 if (tolower(line
[0]) == 'n')
1631 * Prints warning if zone already exists.
1632 * In interactive mode, prompts if we should continue anyway and returns Z_OK
1633 * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR.
1635 * Note that if a zone exists and its state is >= INSTALLED, an error message
1636 * will be printed and this function will return Z_ERR regardless of mode.
1640 check_if_zone_already_exists(boolean_t force
)
1642 char line
[ZONENAME_MAX
+ 128]; /* enough to ask a question */
1643 zone_dochandle_t tmphandle
;
1646 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1647 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1650 res
= zonecfg_get_handle(zone
, tmphandle
);
1651 zonecfg_fini_handle(tmphandle
);
1655 if (state_atleast(ZONE_STATE_INSTALLED
)) {
1656 zerr(gettext("Zone %s already installed; %s not allowed."),
1657 zone
, cmd_to_str(CMD_CREATE
));
1662 (void) printf(gettext("Zone %s already exists; overwriting.\n"),
1666 (void) snprintf(line
, sizeof (line
),
1667 gettext("Zone %s already exists; %s anyway"), zone
,
1668 cmd_to_str(CMD_CREATE
));
1669 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
1670 zerr(gettext("Zone exists, input not from terminal and -F not "
1671 "specified:\n%s command ignored, exiting."),
1672 cmd_to_str(CMD_CREATE
));
1675 return (answer
== 1 ? Z_OK
: Z_ERR
);
1679 zone_is_read_only(int cmd_num
)
1681 if (strncmp(zone
, "SUNW", 4) == 0) {
1682 zerr(gettext("%s: zones beginning with SUNW are read-only."),
1687 if (read_only_mode
) {
1688 zerr(gettext("%s: cannot %s in read-only mode."), zone
,
1689 cmd_to_str(cmd_num
));
1697 * Create a new configuration.
1700 create_func(cmd_t
*cmd
)
1703 char zone_template
[ZONENAME_MAX
];
1704 char attach_path
[MAXPATHLEN
];
1705 zone_dochandle_t tmphandle
;
1706 boolean_t force
= B_FALSE
;
1707 boolean_t attach
= B_FALSE
;
1708 boolean_t arg_err
= B_FALSE
;
1710 assert(cmd
!= NULL
);
1712 /* This is the default if no arguments are given. */
1713 (void) strlcpy(zone_template
, "SUNWdefault", sizeof (zone_template
));
1716 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?a:bFt:"))
1721 longer_usage(CMD_CREATE
);
1723 short_usage(CMD_CREATE
);
1727 (void) strlcpy(attach_path
, optarg
,
1728 sizeof (attach_path
));
1732 (void) strlcpy(zone_template
, "SUNWblank",
1733 sizeof (zone_template
));
1739 (void) strlcpy(zone_template
, optarg
,
1740 sizeof (zone_template
));
1743 short_usage(CMD_CREATE
);
1751 if (optind
!= cmd
->cmd_argc
) {
1752 short_usage(CMD_CREATE
);
1756 if (zone_is_read_only(CMD_CREATE
))
1759 if (check_if_zone_already_exists(force
) != Z_OK
)
1763 * Get a temporary handle first. If that fails, the old handle
1764 * will not be lost. Then finish whichever one we don't need,
1765 * to avoid leaks. Then get the handle for zone_template, and
1766 * set the name to zone: this "copy, rename" method is how
1767 * create -[b|t] works.
1769 if ((tmphandle
= zonecfg_init_handle()) == NULL
) {
1770 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
1775 err
= zonecfg_get_attach_handle(attach_path
, ZONE_DETACHED
,
1776 zone
, B_FALSE
, tmphandle
);
1778 err
= zonecfg_get_template_handle(zone_template
, zone
,
1782 zonecfg_fini_handle(tmphandle
);
1783 if (attach
&& err
== Z_NO_ZONE
)
1784 (void) fprintf(stderr
, gettext("invalid path to "
1785 "detached zone\n"));
1786 else if (attach
&& err
== Z_INVALID_DOCUMENT
)
1787 (void) fprintf(stderr
, gettext("Cannot attach to an "
1788 "earlier release of the operating system\n"));
1790 zone_perror(zone_template
, err
, B_TRUE
);
1794 need_to_commit
= B_TRUE
;
1795 zonecfg_fini_handle(handle
);
1797 got_handle
= B_TRUE
;
1801 * This malloc()'s memory, which must be freed by the caller.
1804 quoteit(char *instr
)
1807 size_t outstrsize
= strlen(instr
) + 3; /* 2 quotes + '\0' */
1809 if ((outstr
= malloc(outstrsize
)) == NULL
) {
1810 zone_perror(zone
, Z_NOMEM
, B_FALSE
);
1813 if (strchr(instr
, ' ') == NULL
) {
1814 (void) strlcpy(outstr
, instr
, outstrsize
);
1817 (void) snprintf(outstr
, outstrsize
, "\"%s\"", instr
);
1822 export_prop(FILE *of
, int prop_num
, char *prop_id
)
1826 if (strlen(prop_id
) == 0)
1828 quote_str
= quoteit(prop_id
);
1829 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1830 pt_to_str(prop_num
), quote_str
);
1835 export_func(cmd_t
*cmd
)
1837 struct zone_nwiftab nwiftab
;
1838 struct zone_fstab fstab
;
1839 struct zone_devtab devtab
;
1840 struct zone_attrtab attrtab
;
1841 struct zone_rctltab rctltab
;
1842 struct zone_dstab dstab
;
1843 struct zone_psettab psettab
;
1844 struct zone_mcaptab mcaptab
;
1845 struct zone_rctlvaltab
*valptr
;
1846 struct zone_admintab admintab
;
1847 struct zone_secflagstab secflagstab
;
1849 char zonepath
[MAXPATHLEN
], outfile
[MAXPATHLEN
], pool
[MAXNAMELEN
];
1850 char bootargs
[BOOTARGS_MAX
];
1851 char sched
[MAXNAMELEN
];
1852 char brand
[MAXNAMELEN
];
1853 char hostidp
[HW_HOSTID_LEN
];
1854 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
1858 zone_iptype_t iptype
;
1859 boolean_t need_to_close
= B_FALSE
;
1860 boolean_t arg_err
= B_FALSE
;
1862 assert(cmd
!= NULL
);
1866 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?f:")) != EOF
) {
1870 longer_usage(CMD_EXPORT
);
1872 short_usage(CMD_EXPORT
);
1876 (void) strlcpy(outfile
, optarg
, sizeof (outfile
));
1879 short_usage(CMD_EXPORT
);
1887 if (optind
!= cmd
->cmd_argc
) {
1888 short_usage(CMD_EXPORT
);
1891 if (strlen(outfile
) == 0) {
1894 if ((of
= fopen(outfile
, "w")) == NULL
) {
1895 zerr(gettext("opening file %s: %s"),
1896 outfile
, strerror(errno
));
1900 need_to_close
= B_TRUE
;
1903 if ((err
= initialize(B_TRUE
)) != Z_OK
)
1906 (void) fprintf(of
, "%s -b\n", cmd_to_str(CMD_CREATE
));
1908 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) == Z_OK
&&
1909 strlen(zonepath
) > 0)
1910 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1911 pt_to_str(PT_ZONEPATH
), zonepath
);
1913 if ((zone_get_brand(zone
, brand
, sizeof (brand
)) == Z_OK
) &&
1914 (strcmp(brand
, NATIVE_BRAND_NAME
) != 0))
1915 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1916 pt_to_str(PT_BRAND
), brand
);
1918 if (zonecfg_get_autoboot(handle
, &autoboot
) == Z_OK
)
1919 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1920 pt_to_str(PT_AUTOBOOT
), autoboot
? "true" : "false");
1922 if (zonecfg_get_bootargs(handle
, bootargs
, sizeof (bootargs
)) == Z_OK
&&
1923 strlen(bootargs
) > 0) {
1924 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1925 pt_to_str(PT_BOOTARGS
), bootargs
);
1928 if (zonecfg_get_pool(handle
, pool
, sizeof (pool
)) == Z_OK
&&
1930 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1931 pt_to_str(PT_POOL
), pool
);
1933 if (zonecfg_get_limitpriv(handle
, &limitpriv
) == Z_OK
&&
1934 strlen(limitpriv
) > 0) {
1935 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1936 pt_to_str(PT_LIMITPRIV
), limitpriv
);
1940 if (zonecfg_get_sched_class(handle
, sched
, sizeof (sched
)) == Z_OK
&&
1942 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1943 pt_to_str(PT_SCHED
), sched
);
1945 if (zonecfg_get_iptype(handle
, &iptype
) == Z_OK
) {
1948 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1949 pt_to_str(PT_IPTYPE
), "shared");
1952 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1953 pt_to_str(PT_IPTYPE
), "exclusive");
1958 if (zonecfg_get_hostid(handle
, hostidp
, sizeof (hostidp
)) == Z_OK
) {
1959 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1960 pt_to_str(PT_HOSTID
), hostidp
);
1963 if (zonecfg_get_fs_allowed(handle
, fsallowedp
,
1964 sizeof (fsallowedp
)) == Z_OK
) {
1965 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
1966 pt_to_str(PT_FS_ALLOWED
), fsallowedp
);
1969 if ((err
= zonecfg_setfsent(handle
)) != Z_OK
) {
1970 zone_perror(zone
, err
, B_FALSE
);
1973 while (zonecfg_getfsent(handle
, &fstab
) == Z_OK
) {
1974 zone_fsopt_t
*optptr
;
1976 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
1978 export_prop(of
, PT_DIR
, fstab
.zone_fs_dir
);
1979 export_prop(of
, PT_SPECIAL
, fstab
.zone_fs_special
);
1980 export_prop(of
, PT_RAW
, fstab
.zone_fs_raw
);
1981 export_prop(of
, PT_TYPE
, fstab
.zone_fs_type
);
1982 for (optptr
= fstab
.zone_fs_options
; optptr
!= NULL
;
1983 optptr
= optptr
->zone_fsopt_next
) {
1985 * Simple property values with embedded equal signs
1986 * need to be quoted to prevent the lexer from
1987 * mis-parsing them as complex name=value pairs.
1989 if (strchr(optptr
->zone_fsopt_opt
, '='))
1990 (void) fprintf(of
, "%s %s \"%s\"\n",
1991 cmd_to_str(CMD_ADD
),
1992 pt_to_str(PT_OPTIONS
),
1993 optptr
->zone_fsopt_opt
);
1995 (void) fprintf(of
, "%s %s %s\n",
1996 cmd_to_str(CMD_ADD
),
1997 pt_to_str(PT_OPTIONS
),
1998 optptr
->zone_fsopt_opt
);
2000 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2001 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
2003 (void) zonecfg_endfsent(handle
);
2005 if ((err
= zonecfg_setnwifent(handle
)) != Z_OK
) {
2006 zone_perror(zone
, err
, B_FALSE
);
2009 while (zonecfg_getnwifent(handle
, &nwiftab
) == Z_OK
) {
2010 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2012 export_prop(of
, PT_ADDRESS
, nwiftab
.zone_nwif_address
);
2013 export_prop(of
, PT_ALLOWED_ADDRESS
,
2014 nwiftab
.zone_nwif_allowed_address
);
2015 export_prop(of
, PT_PHYSICAL
, nwiftab
.zone_nwif_physical
);
2016 export_prop(of
, PT_DEFROUTER
, nwiftab
.zone_nwif_defrouter
);
2017 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2019 (void) zonecfg_endnwifent(handle
);
2021 if ((err
= zonecfg_setdevent(handle
)) != Z_OK
) {
2022 zone_perror(zone
, err
, B_FALSE
);
2025 while (zonecfg_getdevent(handle
, &devtab
) == Z_OK
) {
2026 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2027 rt_to_str(RT_DEVICE
));
2028 export_prop(of
, PT_MATCH
, devtab
.zone_dev_match
);
2029 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2031 (void) zonecfg_enddevent(handle
);
2033 if (zonecfg_getmcapent(handle
, &mcaptab
) == Z_OK
) {
2036 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2037 rt_to_str(RT_MCAP
));
2038 bytes_to_units(mcaptab
.zone_physmem_cap
, buf
, sizeof (buf
));
2039 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2040 pt_to_str(PT_PHYSICAL
), buf
);
2041 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2044 if ((err
= zonecfg_setrctlent(handle
)) != Z_OK
) {
2045 zone_perror(zone
, err
, B_FALSE
);
2048 while (zonecfg_getrctlent(handle
, &rctltab
) == Z_OK
) {
2049 (void) fprintf(of
, "%s rctl\n", cmd_to_str(CMD_ADD
));
2050 export_prop(of
, PT_NAME
, rctltab
.zone_rctl_name
);
2051 for (valptr
= rctltab
.zone_rctl_valptr
; valptr
!= NULL
;
2052 valptr
= valptr
->zone_rctlval_next
) {
2053 fprintf(of
, "%s %s (%s=%s,%s=%s,%s=%s)\n",
2054 cmd_to_str(CMD_ADD
), pt_to_str(PT_VALUE
),
2055 pt_to_str(PT_PRIV
), valptr
->zone_rctlval_priv
,
2056 pt_to_str(PT_LIMIT
), valptr
->zone_rctlval_limit
,
2057 pt_to_str(PT_ACTION
), valptr
->zone_rctlval_action
);
2059 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2060 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
2062 (void) zonecfg_endrctlent(handle
);
2064 if ((err
= zonecfg_setattrent(handle
)) != Z_OK
) {
2065 zone_perror(zone
, err
, B_FALSE
);
2068 while (zonecfg_getattrent(handle
, &attrtab
) == Z_OK
) {
2069 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2070 rt_to_str(RT_ATTR
));
2071 export_prop(of
, PT_NAME
, attrtab
.zone_attr_name
);
2072 export_prop(of
, PT_TYPE
, attrtab
.zone_attr_type
);
2073 export_prop(of
, PT_VALUE
, attrtab
.zone_attr_value
);
2074 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2076 (void) zonecfg_endattrent(handle
);
2078 if ((err
= zonecfg_setdsent(handle
)) != Z_OK
) {
2079 zone_perror(zone
, err
, B_FALSE
);
2082 while (zonecfg_getdsent(handle
, &dstab
) == Z_OK
) {
2083 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2084 rt_to_str(RT_DATASET
));
2085 export_prop(of
, PT_NAME
, dstab
.zone_dataset_name
);
2086 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2088 (void) zonecfg_enddsent(handle
);
2090 if (zonecfg_getpsetent(handle
, &psettab
) == Z_OK
) {
2091 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2092 rt_to_str(RT_DCPU
));
2093 if (strcmp(psettab
.zone_ncpu_min
, psettab
.zone_ncpu_max
) == 0)
2094 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2095 pt_to_str(PT_NCPUS
), psettab
.zone_ncpu_max
);
2097 (void) fprintf(of
, "%s %s=%s-%s\n", cmd_to_str(CMD_SET
),
2098 pt_to_str(PT_NCPUS
), psettab
.zone_ncpu_min
,
2099 psettab
.zone_ncpu_max
);
2100 if (psettab
.zone_importance
[0] != '\0')
2101 (void) fprintf(of
, "%s %s=%s\n", cmd_to_str(CMD_SET
),
2102 pt_to_str(PT_IMPORTANCE
), psettab
.zone_importance
);
2103 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2106 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
2107 zone_perror(zone
, err
, B_FALSE
);
2110 while (zonecfg_getadminent(handle
, &admintab
) == Z_OK
) {
2111 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2112 rt_to_str(RT_ADMIN
));
2113 export_prop(of
, PT_USER
, admintab
.zone_admin_user
);
2114 export_prop(of
, PT_AUTHS
, admintab
.zone_admin_auths
);
2115 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2118 (void) zonecfg_endadminent(handle
);
2120 if (zonecfg_getsecflagsent(handle
, &secflagstab
) == Z_OK
) {
2121 (void) fprintf(of
, "%s %s\n", cmd_to_str(CMD_ADD
),
2122 rt_to_str(RT_SECFLAGS
));
2123 export_prop(of
, PT_DEFAULT
, secflagstab
.zone_secflags_default
);
2124 export_prop(of
, PT_LOWER
, secflagstab
.zone_secflags_lower
);
2125 export_prop(of
, PT_UPPER
, secflagstab
.zone_secflags_upper
);
2126 (void) fprintf(of
, "%s\n", cmd_to_str(CMD_END
));
2130 * There is nothing to export for pcap since this resource is just
2131 * a container for an rctl alias.
2140 exit_func(cmd_t
*cmd
)
2143 boolean_t arg_err
= B_FALSE
;
2146 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
2149 longer_usage(CMD_EXIT
);
2153 force_exit
= B_TRUE
;
2156 short_usage(CMD_EXIT
);
2164 if (optind
< cmd
->cmd_argc
) {
2165 short_usage(CMD_EXIT
);
2169 if (global_scope
|| force_exit
) {
2170 time_to_exit
= B_TRUE
;
2174 answer
= ask_yesno(B_FALSE
, "Resource incomplete; really quit");
2176 zerr(gettext("Resource incomplete, input "
2177 "not from terminal and -F not specified:\n%s command "
2178 "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT
));
2180 } else if (answer
== 1) {
2181 time_to_exit
= B_TRUE
;
2183 /* (answer == 0) => just return */
2187 validate_zonepath_syntax(char *path
)
2189 if (path
[0] != '/') {
2190 zerr(gettext("%s is not an absolute path."), path
);
2193 /* If path is all slashes, then fail */
2194 if (strspn(path
, "/") == strlen(path
)) {
2195 zerr(gettext("/ is not allowed as a %s."),
2196 pt_to_str(PT_ZONEPATH
));
2203 add_resource(cmd_t
*cmd
)
2206 struct zone_psettab tmp_psettab
;
2207 struct zone_mcaptab tmp_mcaptab
;
2208 struct zone_secflagstab tmp_secflagstab
;
2211 char pool
[MAXNAMELEN
];
2213 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
2214 long_usage(CMD_ADD
, B_TRUE
);
2220 bzero(&in_progress_fstab
, sizeof (in_progress_fstab
));
2223 bzero(&in_progress_nwiftab
, sizeof (in_progress_nwiftab
));
2226 bzero(&in_progress_devtab
, sizeof (in_progress_devtab
));
2230 zerr(gettext("WARNING: Setting a global zone resource "
2231 "control too low could deny\nservice "
2232 "to even the root user; "
2233 "this could render the system impossible\n"
2234 "to administer. Please use caution."));
2235 bzero(&in_progress_rctltab
, sizeof (in_progress_rctltab
));
2238 bzero(&in_progress_attrtab
, sizeof (in_progress_attrtab
));
2241 bzero(&in_progress_dstab
, sizeof (in_progress_dstab
));
2244 /* Make sure there isn't already a cpu-set or cpu-cap entry. */
2245 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
2246 zerr(gettext("The %s resource already exists."),
2247 rt_to_str(RT_DCPU
));
2250 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
) !=
2252 zerr(gettext("The %s resource already exists."),
2253 rt_to_str(RT_PCAP
));
2257 /* Make sure the pool property isn't set. */
2258 if (zonecfg_get_pool(handle
, pool
, sizeof (pool
)) == Z_OK
&&
2260 zerr(gettext("The %s property is already set. "
2261 "A persistent pool is incompatible with\nthe %s "
2263 pt_to_str(PT_POOL
), rt_to_str(RT_DCPU
));
2267 bzero(&in_progress_psettab
, sizeof (in_progress_psettab
));
2271 * Make sure there isn't already a cpu-set or incompatible
2274 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
2275 zerr(gettext("The %s resource already exists."),
2276 rt_to_str(RT_DCPU
));
2280 switch (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
)) {
2281 case Z_ALIAS_DISALLOW
:
2282 zone_perror(rt_to_str(RT_PCAP
), Z_ALIAS_DISALLOW
,
2287 zerr(gettext("The %s resource already exists."),
2288 rt_to_str(RT_PCAP
));
2297 * Make sure there isn't already a mem-cap entry or max-swap
2298 * or max-locked rctl.
2300 if (zonecfg_lookup_mcap(handle
, &tmp_mcaptab
) == Z_OK
||
2301 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &tmp_mcap
)
2303 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
2304 &tmp_mcap
) == Z_OK
) {
2305 zerr(gettext("The %s resource or a related resource "
2306 "control already exists."), rt_to_str(RT_MCAP
));
2310 zerr(gettext("WARNING: Setting a global zone memory "
2311 "cap too low could deny\nservice "
2312 "to even the root user; "
2313 "this could render the system impossible\n"
2314 "to administer. Please use caution."));
2315 bzero(&in_progress_mcaptab
, sizeof (in_progress_mcaptab
));
2318 bzero(&in_progress_admintab
, sizeof (in_progress_admintab
));
2321 /* Make sure we haven't already set this */
2322 if (zonecfg_lookup_secflags(handle
, &tmp_secflagstab
) == Z_OK
)
2323 zerr(gettext("The %s resource already exists."),
2324 rt_to_str(RT_SECFLAGS
));
2325 bzero(&in_progress_secflagstab
,
2326 sizeof (in_progress_secflagstab
));
2329 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
2330 long_usage(CMD_ADD
, B_TRUE
);
2331 usage(B_FALSE
, HELP_RESOURCES
);
2334 global_scope
= B_TRUE
;
2339 do_complex_rctl_val(complex_property_ptr_t cp
)
2341 struct zone_rctlvaltab
*rctlvaltab
;
2342 complex_property_ptr_t cx
;
2343 boolean_t seen_priv
= B_FALSE
, seen_limit
= B_FALSE
,
2344 seen_action
= B_FALSE
;
2348 if ((rctlvaltab
= alloc_rctlvaltab()) == NULL
) {
2349 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
2352 for (cx
= cp
; cx
!= NULL
; cx
= cx
->cp_next
) {
2353 switch (cx
->cp_type
) {
2356 zerr(gettext("%s already specified"),
2357 pt_to_str(PT_PRIV
));
2360 (void) strlcpy(rctlvaltab
->zone_rctlval_priv
,
2362 sizeof (rctlvaltab
->zone_rctlval_priv
));
2367 zerr(gettext("%s already specified"),
2368 pt_to_str(PT_LIMIT
));
2371 (void) strlcpy(rctlvaltab
->zone_rctlval_limit
,
2373 sizeof (rctlvaltab
->zone_rctlval_limit
));
2374 seen_limit
= B_TRUE
;
2378 zerr(gettext("%s already specified"),
2379 pt_to_str(PT_ACTION
));
2382 (void) strlcpy(rctlvaltab
->zone_rctlval_action
,
2384 sizeof (rctlvaltab
->zone_rctlval_action
));
2385 seen_action
= B_TRUE
;
2388 zone_perror(pt_to_str(PT_VALUE
),
2389 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2390 long_usage(CMD_ADD
, B_TRUE
);
2391 usage(B_FALSE
, HELP_PROPS
);
2392 zonecfg_free_rctl_value_list(rctlvaltab
);
2397 zerr(gettext("%s not specified"), pt_to_str(PT_PRIV
));
2399 zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT
));
2401 zerr(gettext("%s not specified"), pt_to_str(PT_ACTION
));
2402 if (!seen_priv
|| !seen_limit
|| !seen_action
)
2404 rctlvaltab
->zone_rctlval_next
= NULL
;
2405 rctlblk
= alloca(rctlblk_size());
2407 * Make sure the rctl value looks roughly correct; we won't know if
2408 * it's truly OK until we verify the configuration on the target
2411 if (zonecfg_construct_rctlblk(rctlvaltab
, rctlblk
) != Z_OK
||
2412 !zonecfg_valid_rctlblk(rctlblk
)) {
2413 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL
),
2414 pt_to_str(PT_VALUE
));
2417 err
= zonecfg_add_rctl_value(&in_progress_rctltab
, rctlvaltab
);
2419 zone_perror(pt_to_str(PT_VALUE
), err
, B_TRUE
);
2423 zonecfg_free_rctl_value_list(rctlvaltab
);
2427 add_property(cmd_t
*cmd
)
2430 int err
, res_type
, prop_type
;
2431 property_value_ptr_t pp
;
2432 list_property_ptr_t l
;
2434 res_type
= resource_scope
;
2435 prop_type
= cmd
->cmd_prop_name
[0];
2436 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
2437 long_usage(CMD_ADD
, B_TRUE
);
2441 if (cmd
->cmd_prop_nv_pairs
!= 1) {
2442 long_usage(CMD_ADD
, B_TRUE
);
2446 if (initialize(B_TRUE
) != Z_OK
)
2451 if (prop_type
!= PT_OPTIONS
) {
2452 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
2454 long_usage(CMD_ADD
, B_TRUE
);
2455 usage(B_FALSE
, HELP_PROPS
);
2458 pp
= cmd
->cmd_property_ptr
[0];
2459 if (pp
->pv_type
!= PROP_VAL_SIMPLE
&&
2460 pp
->pv_type
!= PROP_VAL_LIST
) {
2461 zerr(gettext("A %s or %s value was expected here."),
2462 pvt_to_str(PROP_VAL_SIMPLE
),
2463 pvt_to_str(PROP_VAL_LIST
));
2467 if (pp
->pv_type
== PROP_VAL_SIMPLE
) {
2468 if (pp
->pv_simple
== NULL
) {
2469 long_usage(CMD_ADD
, B_TRUE
);
2472 prop_id
= pp
->pv_simple
;
2473 err
= zonecfg_add_fs_option(&in_progress_fstab
,
2476 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
2478 list_property_ptr_t list
;
2480 for (list
= pp
->pv_list
; list
!= NULL
;
2481 list
= list
->lp_next
) {
2482 prop_id
= list
->lp_simple
;
2483 if (prop_id
== NULL
)
2485 err
= zonecfg_add_fs_option(
2486 &in_progress_fstab
, prop_id
);
2488 zone_perror(pt_to_str(prop_type
), err
,
2494 if (prop_type
!= PT_VALUE
) {
2495 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
2497 long_usage(CMD_ADD
, B_TRUE
);
2498 usage(B_FALSE
, HELP_PROPS
);
2501 pp
= cmd
->cmd_property_ptr
[0];
2502 if (pp
->pv_type
!= PROP_VAL_COMPLEX
&&
2503 pp
->pv_type
!= PROP_VAL_LIST
) {
2504 zerr(gettext("A %s or %s value was expected here."),
2505 pvt_to_str(PROP_VAL_COMPLEX
),
2506 pvt_to_str(PROP_VAL_LIST
));
2510 if (pp
->pv_type
== PROP_VAL_COMPLEX
) {
2511 do_complex_rctl_val(pp
->pv_complex
);
2514 for (l
= pp
->pv_list
; l
!= NULL
; l
= l
->lp_next
)
2515 do_complex_rctl_val(l
->lp_complex
);
2518 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
2519 long_usage(CMD_ADD
, B_TRUE
);
2520 usage(B_FALSE
, HELP_RESOURCES
);
2526 gz_invalid_resource(int type
)
2528 return (global_zone
&& (type
== RT_FS
||
2529 type
== RT_NET
|| type
== RT_DEVICE
|| type
== RT_ATTR
||
2530 type
== RT_DATASET
));
2534 gz_invalid_rt_property(int type
)
2536 return (global_zone
&& (type
== RT_ZONENAME
|| type
== RT_ZONEPATH
||
2537 type
== RT_AUTOBOOT
|| type
== RT_LIMITPRIV
||
2538 type
== RT_BOOTARGS
|| type
== RT_BRAND
|| type
== RT_SCHED
||
2539 type
== RT_IPTYPE
|| type
== RT_HOSTID
|| type
== RT_FS_ALLOWED
));
2543 gz_invalid_property(int type
)
2545 return (global_zone
&& (type
== PT_ZONENAME
|| type
== PT_ZONEPATH
||
2546 type
== PT_AUTOBOOT
|| type
== PT_LIMITPRIV
||
2547 type
== PT_BOOTARGS
|| type
== PT_BRAND
|| type
== PT_SCHED
||
2548 type
== PT_IPTYPE
|| type
== PT_HOSTID
|| type
== PT_FS_ALLOWED
));
2552 add_func(cmd_t
*cmd
)
2555 boolean_t arg_err
= B_FALSE
;
2557 assert(cmd
!= NULL
);
2560 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
2563 longer_usage(CMD_ADD
);
2567 short_usage(CMD_ADD
);
2575 if (optind
!= cmd
->cmd_argc
) {
2576 short_usage(CMD_ADD
);
2580 if (zone_is_read_only(CMD_ADD
))
2583 if (initialize(B_TRUE
) != Z_OK
)
2586 if (gz_invalid_resource(cmd
->cmd_res_type
)) {
2587 zerr(gettext("Cannot add a %s resource to the "
2588 "global zone."), rt_to_str(cmd
->cmd_res_type
));
2593 global_scope
= B_FALSE
;
2594 resource_scope
= cmd
->cmd_res_type
;
2602 * This routine has an unusual implementation, because it tries very
2603 * hard to succeed in the face of a variety of failure modes.
2604 * The most common and most vexing occurs when the index file and
2605 * the /etc/zones/<zonename.xml> file are not both present. In
2606 * this case, delete must eradicate as much of the zone state as is left
2607 * so that the user can later create a new zone with the same name.
2610 delete_func(cmd_t
*cmd
)
2612 int err
, arg
, answer
;
2613 char line
[ZONENAME_MAX
+ 128]; /* enough to ask a question */
2614 boolean_t force
= B_FALSE
;
2615 boolean_t arg_err
= B_FALSE
;
2618 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
2621 longer_usage(CMD_DELETE
);
2628 short_usage(CMD_DELETE
);
2636 if (optind
!= cmd
->cmd_argc
) {
2637 short_usage(CMD_DELETE
);
2641 if (zone_is_read_only(CMD_DELETE
))
2646 * Initialize sets up the global called "handle" and warns the
2647 * user if the zone is not configured. In force mode, we don't
2648 * trust that evaluation, and hence skip it. (We don't need the
2649 * handle to be loaded anyway, since zonecfg_destroy is done by
2650 * zonename). However, we also have to take care to emulate the
2651 * messages spit out by initialize; see below.
2653 if (initialize(B_TRUE
) != Z_OK
)
2656 (void) snprintf(line
, sizeof (line
),
2657 gettext("Are you sure you want to delete zone %s"), zone
);
2658 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
2659 zerr(gettext("Input not from terminal and -F not "
2660 "specified:\n%s command ignored, exiting."),
2661 cmd_to_str(CMD_DELETE
));
2669 * This function removes the authorizations from user_attr
2670 * that correspond to those specified in the configuration
2672 if (initialize(B_TRUE
) == Z_OK
) {
2673 (void) zonecfg_deauthorize_users(handle
, zone
);
2675 if ((err
= zonecfg_destroy(zone
, force
)) != Z_OK
) {
2676 if ((err
== Z_BAD_ZONE_STATE
) && !force
) {
2677 zerr(gettext("Zone %s not in %s state; %s not "
2678 "allowed. Use -F to force %s."),
2679 zone
, zone_state_str(ZONE_STATE_CONFIGURED
),
2680 cmd_to_str(CMD_DELETE
), cmd_to_str(CMD_DELETE
));
2682 zone_perror(zone
, err
, B_TRUE
);
2685 need_to_commit
= B_FALSE
;
2688 * Emulate initialize's messaging; if there wasn't a valid handle to
2689 * begin with, then user had typed delete (or delete -F) multiple
2690 * times. So we emit a message.
2692 * We only do this in the 'force' case because normally, initialize()
2693 * takes care of this for us.
2695 if (force
&& zonecfg_check_handle(handle
) != Z_OK
&& interactive_mode
)
2696 (void) printf(gettext("Use '%s' to begin "
2697 "configuring a new zone.\n"), cmd_to_str(CMD_CREATE
));
2700 * Time for a new handle: finish the old one off first
2701 * then get a new one properly to avoid leaks.
2704 zonecfg_fini_handle(handle
);
2705 if ((handle
= zonecfg_init_handle()) == NULL
) {
2706 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
2709 if ((err
= zonecfg_get_handle(zone
, handle
)) != Z_OK
) {
2710 /* If there was no zone before, that's OK */
2711 if (err
!= Z_NO_ZONE
)
2712 zone_perror(zone
, err
, B_TRUE
);
2713 got_handle
= B_FALSE
;
2719 fill_in_fstab(cmd_t
*cmd
, struct zone_fstab
*fstab
, boolean_t fill_in_only
)
2722 property_value_ptr_t pp
;
2724 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2727 bzero(fstab
, sizeof (*fstab
));
2728 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2729 pp
= cmd
->cmd_property_ptr
[i
];
2730 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2731 zerr(gettext("A simple value was expected here."));
2733 return (Z_INSUFFICIENT_SPEC
);
2735 switch (cmd
->cmd_prop_name
[i
]) {
2737 (void) strlcpy(fstab
->zone_fs_dir
, pp
->pv_simple
,
2738 sizeof (fstab
->zone_fs_dir
));
2741 (void) strlcpy(fstab
->zone_fs_special
, pp
->pv_simple
,
2742 sizeof (fstab
->zone_fs_special
));
2745 (void) strlcpy(fstab
->zone_fs_raw
, pp
->pv_simple
,
2746 sizeof (fstab
->zone_fs_raw
));
2749 (void) strlcpy(fstab
->zone_fs_type
, pp
->pv_simple
,
2750 sizeof (fstab
->zone_fs_type
));
2753 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2754 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2755 return (Z_INSUFFICIENT_SPEC
);
2760 return (zonecfg_lookup_filesystem(handle
, fstab
));
2764 fill_in_nwiftab(cmd_t
*cmd
, struct zone_nwiftab
*nwiftab
,
2765 boolean_t fill_in_only
)
2768 property_value_ptr_t pp
;
2770 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2773 bzero(nwiftab
, sizeof (*nwiftab
));
2774 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2775 pp
= cmd
->cmd_property_ptr
[i
];
2776 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2777 zerr(gettext("A simple value was expected here."));
2779 return (Z_INSUFFICIENT_SPEC
);
2781 switch (cmd
->cmd_prop_name
[i
]) {
2783 (void) strlcpy(nwiftab
->zone_nwif_address
,
2784 pp
->pv_simple
, sizeof (nwiftab
->zone_nwif_address
));
2786 case PT_ALLOWED_ADDRESS
:
2787 (void) strlcpy(nwiftab
->zone_nwif_allowed_address
,
2789 sizeof (nwiftab
->zone_nwif_allowed_address
));
2792 (void) strlcpy(nwiftab
->zone_nwif_physical
,
2794 sizeof (nwiftab
->zone_nwif_physical
));
2797 (void) strlcpy(nwiftab
->zone_nwif_defrouter
,
2799 sizeof (nwiftab
->zone_nwif_defrouter
));
2802 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2803 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2804 return (Z_INSUFFICIENT_SPEC
);
2809 err
= zonecfg_lookup_nwif(handle
, nwiftab
);
2814 fill_in_devtab(cmd_t
*cmd
, struct zone_devtab
*devtab
, boolean_t fill_in_only
)
2817 property_value_ptr_t pp
;
2819 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2822 bzero(devtab
, sizeof (*devtab
));
2823 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2824 pp
= cmd
->cmd_property_ptr
[i
];
2825 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2826 zerr(gettext("A simple value was expected here."));
2828 return (Z_INSUFFICIENT_SPEC
);
2830 switch (cmd
->cmd_prop_name
[i
]) {
2832 (void) strlcpy(devtab
->zone_dev_match
, pp
->pv_simple
,
2833 sizeof (devtab
->zone_dev_match
));
2836 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2837 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2838 return (Z_INSUFFICIENT_SPEC
);
2843 err
= zonecfg_lookup_dev(handle
, devtab
);
2848 fill_in_rctltab(cmd_t
*cmd
, struct zone_rctltab
*rctltab
,
2849 boolean_t fill_in_only
)
2852 property_value_ptr_t pp
;
2854 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2857 bzero(rctltab
, sizeof (*rctltab
));
2858 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2859 pp
= cmd
->cmd_property_ptr
[i
];
2860 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2861 zerr(gettext("A simple value was expected here."));
2863 return (Z_INSUFFICIENT_SPEC
);
2865 switch (cmd
->cmd_prop_name
[i
]) {
2867 (void) strlcpy(rctltab
->zone_rctl_name
, pp
->pv_simple
,
2868 sizeof (rctltab
->zone_rctl_name
));
2871 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2872 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2873 return (Z_INSUFFICIENT_SPEC
);
2878 err
= zonecfg_lookup_rctl(handle
, rctltab
);
2883 fill_in_attrtab(cmd_t
*cmd
, struct zone_attrtab
*attrtab
,
2884 boolean_t fill_in_only
)
2887 property_value_ptr_t pp
;
2889 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2892 bzero(attrtab
, sizeof (*attrtab
));
2893 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2894 pp
= cmd
->cmd_property_ptr
[i
];
2895 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2896 zerr(gettext("A simple value was expected here."));
2898 return (Z_INSUFFICIENT_SPEC
);
2900 switch (cmd
->cmd_prop_name
[i
]) {
2902 (void) strlcpy(attrtab
->zone_attr_name
, pp
->pv_simple
,
2903 sizeof (attrtab
->zone_attr_name
));
2906 (void) strlcpy(attrtab
->zone_attr_type
, pp
->pv_simple
,
2907 sizeof (attrtab
->zone_attr_type
));
2910 (void) strlcpy(attrtab
->zone_attr_value
, pp
->pv_simple
,
2911 sizeof (attrtab
->zone_attr_value
));
2914 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2915 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2916 return (Z_INSUFFICIENT_SPEC
);
2921 err
= zonecfg_lookup_attr(handle
, attrtab
);
2926 fill_in_dstab(cmd_t
*cmd
, struct zone_dstab
*dstab
, boolean_t fill_in_only
)
2929 property_value_ptr_t pp
;
2931 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2934 dstab
->zone_dataset_name
[0] = '\0';
2935 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2936 pp
= cmd
->cmd_property_ptr
[i
];
2937 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2938 zerr(gettext("A simple value was expected here."));
2940 return (Z_INSUFFICIENT_SPEC
);
2942 switch (cmd
->cmd_prop_name
[i
]) {
2944 (void) strlcpy(dstab
->zone_dataset_name
, pp
->pv_simple
,
2945 sizeof (dstab
->zone_dataset_name
));
2948 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2949 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2950 return (Z_INSUFFICIENT_SPEC
);
2955 return (zonecfg_lookup_ds(handle
, dstab
));
2959 fill_in_admintab(cmd_t
*cmd
, struct zone_admintab
*admintab
,
2960 boolean_t fill_in_only
)
2963 property_value_ptr_t pp
;
2965 if ((err
= initialize(B_TRUE
)) != Z_OK
)
2968 bzero(admintab
, sizeof (*admintab
));
2969 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
2970 pp
= cmd
->cmd_property_ptr
[i
];
2971 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
2972 zerr(gettext("A simple value was expected here."));
2974 return (Z_INSUFFICIENT_SPEC
);
2976 switch (cmd
->cmd_prop_name
[i
]) {
2978 (void) strlcpy(admintab
->zone_admin_user
, pp
->pv_simple
,
2979 sizeof (admintab
->zone_admin_user
));
2982 (void) strlcpy(admintab
->zone_admin_auths
,
2983 pp
->pv_simple
, sizeof (admintab
->zone_admin_auths
));
2986 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
2987 Z_NO_PROPERTY_TYPE
, B_TRUE
);
2988 return (Z_INSUFFICIENT_SPEC
);
2993 err
= zonecfg_lookup_admin(handle
, admintab
);
2998 fill_in_secflagstab(cmd_t
*cmd
, struct zone_secflagstab
*secflagstab
,
2999 boolean_t fill_in_only
)
3002 property_value_ptr_t pp
;
3004 if ((err
= initialize(B_TRUE
)) != Z_OK
)
3007 bzero(secflagstab
, sizeof (*secflagstab
));
3008 for (i
= 0; i
< cmd
->cmd_prop_nv_pairs
; i
++) {
3009 pp
= cmd
->cmd_property_ptr
[i
];
3010 if (pp
->pv_type
!= PROP_VAL_SIMPLE
|| pp
->pv_simple
== NULL
) {
3011 zerr(gettext("A simple value was expected here."));
3013 return (Z_INSUFFICIENT_SPEC
);
3015 switch (cmd
->cmd_prop_name
[i
]) {
3017 (void) strlcpy(secflagstab
->zone_secflags_default
,
3019 sizeof (secflagstab
->zone_secflags_default
));
3022 (void) strlcpy(secflagstab
->zone_secflags_lower
,
3024 sizeof (secflagstab
->zone_secflags_lower
));
3027 (void) strlcpy(secflagstab
->zone_secflags_upper
,
3029 sizeof (secflagstab
->zone_secflags_upper
));
3032 zone_perror(pt_to_str(cmd
->cmd_prop_name
[i
]),
3033 Z_NO_PROPERTY_TYPE
, B_TRUE
);
3034 return (Z_INSUFFICIENT_SPEC
);
3040 err
= zonecfg_lookup_secflags(handle
, secflagstab
);
3046 remove_aliased_rctl(int type
, char *name
)
3051 if ((err
= zonecfg_get_aliased_rctl(handle
, name
, &tmp
)) != Z_OK
) {
3052 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR
), pt_to_str(type
),
3053 zonecfg_strerror(err
));
3057 if ((err
= zonecfg_rm_aliased_rctl(handle
, name
)) != Z_OK
) {
3058 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR
), pt_to_str(type
),
3059 zonecfg_strerror(err
));
3062 need_to_commit
= B_TRUE
;
3067 prompt_remove_resource(cmd_t
*cmd
, char *rsrc
)
3072 boolean_t force
= B_FALSE
;
3074 boolean_t arg_err
= B_FALSE
;
3077 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "F")) != EOF
) {
3091 num
= zonecfg_num_resources(handle
, rsrc
);
3094 z_cmd_rt_perror(CMD_REMOVE
, cmd
->cmd_res_type
, Z_NO_ENTRY
,
3098 if (num
> 1 && !force
) {
3099 if (!interactive_mode
) {
3100 zerr(gettext("There are multiple instances of this "
3101 "resource. Either qualify the resource to\n"
3102 "remove a single instance or use the -F option to "
3103 "remove all instances."));
3107 (void) snprintf(prompt
, sizeof (prompt
), gettext(
3108 "Are you sure you want to remove ALL '%s' resources"),
3110 answer
= ask_yesno(B_FALSE
, prompt
);
3112 zerr(gettext("Resource incomplete."));
3122 remove_fs(cmd_t
*cmd
)
3126 /* traditional, qualified fs removal */
3127 if (cmd
->cmd_prop_nv_pairs
> 0) {
3128 struct zone_fstab fstab
;
3130 if ((err
= fill_in_fstab(cmd
, &fstab
, B_FALSE
)) != Z_OK
) {
3131 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3134 if ((err
= zonecfg_delete_filesystem(handle
, &fstab
)) != Z_OK
)
3135 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3137 need_to_commit
= B_TRUE
;
3138 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
3143 * unqualified fs removal. remove all fs's but prompt if more
3146 if (!prompt_remove_resource(cmd
, "fs"))
3149 if ((err
= zonecfg_del_all_resources(handle
, "fs")) != Z_OK
)
3150 z_cmd_rt_perror(CMD_REMOVE
, RT_FS
, err
, B_TRUE
);
3152 need_to_commit
= B_TRUE
;
3156 remove_net(cmd_t
*cmd
)
3160 /* traditional, qualified net removal */
3161 if (cmd
->cmd_prop_nv_pairs
> 0) {
3162 struct zone_nwiftab nwiftab
;
3164 if ((err
= fill_in_nwiftab(cmd
, &nwiftab
, B_FALSE
)) != Z_OK
) {
3165 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3168 if ((err
= zonecfg_delete_nwif(handle
, &nwiftab
)) != Z_OK
)
3169 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3171 need_to_commit
= B_TRUE
;
3176 * unqualified net removal. remove all nets but prompt if more
3179 if (!prompt_remove_resource(cmd
, "net"))
3182 if ((err
= zonecfg_del_all_resources(handle
, "net")) != Z_OK
)
3183 z_cmd_rt_perror(CMD_REMOVE
, RT_NET
, err
, B_TRUE
);
3185 need_to_commit
= B_TRUE
;
3189 remove_device(cmd_t
*cmd
)
3193 /* traditional, qualified device removal */
3194 if (cmd
->cmd_prop_nv_pairs
> 0) {
3195 struct zone_devtab devtab
;
3197 if ((err
= fill_in_devtab(cmd
, &devtab
, B_FALSE
)) != Z_OK
) {
3198 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3201 if ((err
= zonecfg_delete_dev(handle
, &devtab
)) != Z_OK
)
3202 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3204 need_to_commit
= B_TRUE
;
3209 * unqualified device removal. remove all devices but prompt if more
3212 if (!prompt_remove_resource(cmd
, "device"))
3215 if ((err
= zonecfg_del_all_resources(handle
, "device")) != Z_OK
)
3216 z_cmd_rt_perror(CMD_REMOVE
, RT_DEVICE
, err
, B_TRUE
);
3218 need_to_commit
= B_TRUE
;
3222 remove_attr(cmd_t
*cmd
)
3226 /* traditional, qualified attr removal */
3227 if (cmd
->cmd_prop_nv_pairs
> 0) {
3228 struct zone_attrtab attrtab
;
3230 if ((err
= fill_in_attrtab(cmd
, &attrtab
, B_FALSE
)) != Z_OK
) {
3231 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3234 if ((err
= zonecfg_delete_attr(handle
, &attrtab
)) != Z_OK
)
3235 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3237 need_to_commit
= B_TRUE
;
3242 * unqualified attr removal. remove all attrs but prompt if more
3245 if (!prompt_remove_resource(cmd
, "attr"))
3248 if ((err
= zonecfg_del_all_resources(handle
, "attr")) != Z_OK
)
3249 z_cmd_rt_perror(CMD_REMOVE
, RT_ATTR
, err
, B_TRUE
);
3251 need_to_commit
= B_TRUE
;
3255 remove_dataset(cmd_t
*cmd
)
3259 /* traditional, qualified dataset removal */
3260 if (cmd
->cmd_prop_nv_pairs
> 0) {
3261 struct zone_dstab dstab
;
3263 if ((err
= fill_in_dstab(cmd
, &dstab
, B_FALSE
)) != Z_OK
) {
3264 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3267 if ((err
= zonecfg_delete_ds(handle
, &dstab
)) != Z_OK
)
3268 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3270 need_to_commit
= B_TRUE
;
3275 * unqualified dataset removal. remove all datasets but prompt if more
3278 if (!prompt_remove_resource(cmd
, "dataset"))
3281 if ((err
= zonecfg_del_all_resources(handle
, "dataset")) != Z_OK
)
3282 z_cmd_rt_perror(CMD_REMOVE
, RT_DATASET
, err
, B_TRUE
);
3284 need_to_commit
= B_TRUE
;
3288 remove_rctl(cmd_t
*cmd
)
3292 /* traditional, qualified rctl removal */
3293 if (cmd
->cmd_prop_nv_pairs
> 0) {
3294 struct zone_rctltab rctltab
;
3296 if ((err
= fill_in_rctltab(cmd
, &rctltab
, B_FALSE
)) != Z_OK
) {
3297 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3300 if ((err
= zonecfg_delete_rctl(handle
, &rctltab
)) != Z_OK
)
3301 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3303 need_to_commit
= B_TRUE
;
3304 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
3309 * unqualified rctl removal. remove all rctls but prompt if more
3312 if (!prompt_remove_resource(cmd
, "rctl"))
3315 if ((err
= zonecfg_del_all_resources(handle
, "rctl")) != Z_OK
)
3316 z_cmd_rt_perror(CMD_REMOVE
, RT_RCTL
, err
, B_TRUE
);
3318 need_to_commit
= B_TRUE
;
3325 struct zone_psettab psettab
;
3327 if ((err
= zonecfg_lookup_pset(handle
, &psettab
)) != Z_OK
) {
3328 z_cmd_rt_perror(CMD_REMOVE
, RT_DCPU
, err
, B_TRUE
);
3331 if ((err
= zonecfg_delete_pset(handle
)) != Z_OK
)
3332 z_cmd_rt_perror(CMD_REMOVE
, RT_DCPU
, err
, B_TRUE
);
3334 need_to_commit
= B_TRUE
;
3343 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
) != Z_OK
) {
3344 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
), rt_to_str(RT_PCAP
),
3345 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3350 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_CPUCAP
)) != Z_OK
)
3351 z_cmd_rt_perror(CMD_REMOVE
, RT_PCAP
, err
, B_TRUE
);
3353 need_to_commit
= B_TRUE
;
3359 int err
, res1
, res2
, res3
;
3361 struct zone_mcaptab mcaptab
;
3362 boolean_t revert
= B_FALSE
;
3364 res1
= zonecfg_lookup_mcap(handle
, &mcaptab
);
3365 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &tmp
);
3366 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
, &tmp
);
3368 /* if none of these exist, there is no resource to remove */
3369 if (res1
!= Z_OK
&& res2
!= Z_OK
&& res3
!= Z_OK
) {
3370 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
), rt_to_str(RT_MCAP
),
3371 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3376 if ((err
= zonecfg_delete_mcap(handle
)) != Z_OK
) {
3377 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3380 need_to_commit
= B_TRUE
;
3384 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_MAXSWAP
))
3386 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3389 need_to_commit
= B_TRUE
;
3393 if ((err
= zonecfg_rm_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
))
3395 z_cmd_rt_perror(CMD_REMOVE
, RT_MCAP
, err
, B_TRUE
);
3398 need_to_commit
= B_TRUE
;
3403 need_to_commit
= B_FALSE
;
3407 remove_admin(cmd_t
*cmd
)
3411 /* traditional, qualified attr removal */
3412 if (cmd
->cmd_prop_nv_pairs
> 0) {
3413 struct zone_admintab admintab
;
3415 if ((err
= fill_in_admintab(cmd
, &admintab
, B_FALSE
)) != Z_OK
) {
3416 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3420 if ((err
= zonecfg_delete_admin(handle
, &admintab
,
3423 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3426 need_to_commit
= B_TRUE
;
3430 * unqualified admin removal.
3431 * remove all admins but prompt if more
3434 if (!prompt_remove_resource(cmd
, "admin"))
3437 if ((err
= zonecfg_delete_admins(handle
, zone
))
3439 z_cmd_rt_perror(CMD_REMOVE
, RT_ADMIN
,
3442 need_to_commit
= B_TRUE
;
3450 struct zone_secflagstab sectab
= { 0 };
3452 if (zonecfg_lookup_secflags(handle
, §ab
) != Z_OK
) {
3453 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE
),
3454 rt_to_str(RT_SECFLAGS
),
3455 zonecfg_strerror(Z_NO_RESOURCE_TYPE
));
3459 if ((err
= zonecfg_delete_secflags(handle
, §ab
)) != Z_OK
) {
3460 z_cmd_rt_perror(CMD_REMOVE
, RT_SECFLAGS
, err
, B_TRUE
);
3464 need_to_commit
= B_TRUE
;
3468 remove_resource(cmd_t
*cmd
)
3472 boolean_t arg_err
= B_FALSE
;
3474 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3475 long_usage(CMD_REMOVE
, B_TRUE
);
3480 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
3483 longer_usage(CMD_REMOVE
);
3489 short_usage(CMD_REMOVE
);
3497 if (initialize(B_TRUE
) != Z_OK
)
3517 remove_dataset(cmd
);
3535 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
3536 long_usage(CMD_REMOVE
, B_TRUE
);
3537 usage(B_FALSE
, HELP_RESOURCES
);
3543 remove_property(cmd_t
*cmd
)
3546 int err
, res_type
, prop_type
;
3547 property_value_ptr_t pp
;
3548 struct zone_rctlvaltab
*rctlvaltab
;
3549 complex_property_ptr_t cx
;
3551 res_type
= resource_scope
;
3552 prop_type
= cmd
->cmd_prop_name
[0];
3553 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
3554 long_usage(CMD_REMOVE
, B_TRUE
);
3558 if (cmd
->cmd_prop_nv_pairs
!= 1) {
3559 long_usage(CMD_ADD
, B_TRUE
);
3563 if (initialize(B_TRUE
) != Z_OK
)
3568 if (prop_type
!= PT_OPTIONS
) {
3569 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3571 long_usage(CMD_REMOVE
, B_TRUE
);
3572 usage(B_FALSE
, HELP_PROPS
);
3575 pp
= cmd
->cmd_property_ptr
[0];
3576 if (pp
->pv_type
== PROP_VAL_COMPLEX
) {
3577 zerr(gettext("A %s or %s value was expected here."),
3578 pvt_to_str(PROP_VAL_SIMPLE
),
3579 pvt_to_str(PROP_VAL_LIST
));
3583 if (pp
->pv_type
== PROP_VAL_SIMPLE
) {
3584 if (pp
->pv_simple
== NULL
) {
3585 long_usage(CMD_ADD
, B_TRUE
);
3588 prop_id
= pp
->pv_simple
;
3589 err
= zonecfg_remove_fs_option(&in_progress_fstab
,
3592 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
3594 list_property_ptr_t list
;
3596 for (list
= pp
->pv_list
; list
!= NULL
;
3597 list
= list
->lp_next
) {
3598 prop_id
= list
->lp_simple
;
3599 if (prop_id
== NULL
)
3601 err
= zonecfg_remove_fs_option(
3602 &in_progress_fstab
, prop_id
);
3604 zone_perror(pt_to_str(prop_type
), err
,
3610 if (prop_type
!= PT_VALUE
) {
3611 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3613 long_usage(CMD_REMOVE
, B_TRUE
);
3614 usage(B_FALSE
, HELP_PROPS
);
3617 pp
= cmd
->cmd_property_ptr
[0];
3618 if (pp
->pv_type
!= PROP_VAL_COMPLEX
) {
3619 zerr(gettext("A %s value was expected here."),
3620 pvt_to_str(PROP_VAL_COMPLEX
));
3624 if ((rctlvaltab
= alloc_rctlvaltab()) == NULL
) {
3625 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
3628 for (cx
= pp
->pv_complex
; cx
!= NULL
; cx
= cx
->cp_next
) {
3629 switch (cx
->cp_type
) {
3631 (void) strlcpy(rctlvaltab
->zone_rctlval_priv
,
3633 sizeof (rctlvaltab
->zone_rctlval_priv
));
3636 (void) strlcpy(rctlvaltab
->zone_rctlval_limit
,
3638 sizeof (rctlvaltab
->zone_rctlval_limit
));
3641 (void) strlcpy(rctlvaltab
->zone_rctlval_action
,
3643 sizeof (rctlvaltab
->zone_rctlval_action
));
3646 zone_perror(pt_to_str(prop_type
),
3647 Z_NO_PROPERTY_TYPE
, B_TRUE
);
3648 long_usage(CMD_ADD
, B_TRUE
);
3649 usage(B_FALSE
, HELP_PROPS
);
3650 zonecfg_free_rctl_value_list(rctlvaltab
);
3654 rctlvaltab
->zone_rctlval_next
= NULL
;
3655 err
= zonecfg_remove_rctl_value(&in_progress_rctltab
,
3658 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
3659 zonecfg_free_rctl_value_list(rctlvaltab
);
3662 if (prop_type
!= PT_DEFROUTER
) {
3663 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
3665 long_usage(CMD_REMOVE
, B_TRUE
);
3666 usage(B_FALSE
, HELP_PROPS
);
3669 bzero(&in_progress_nwiftab
.zone_nwif_defrouter
,
3670 sizeof (in_progress_nwiftab
.zone_nwif_defrouter
));
3674 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
3675 long_usage(CMD_REMOVE
, B_TRUE
);
3676 usage(B_FALSE
, HELP_RESOURCES
);
3682 remove_func(cmd_t
*cmd
)
3684 if (zone_is_read_only(CMD_REMOVE
))
3687 assert(cmd
!= NULL
);
3690 if (gz_invalid_resource(cmd
->cmd_res_type
)) {
3691 zerr(gettext("%s is not a valid resource for the "
3692 "global zone."), rt_to_str(cmd
->cmd_res_type
));
3696 remove_resource(cmd
);
3698 remove_property(cmd
);
3703 clear_property(cmd_t
*cmd
)
3705 int res_type
, prop_type
;
3707 res_type
= resource_scope
;
3708 prop_type
= cmd
->cmd_res_type
;
3709 if (res_type
== RT_UNKNOWN
|| prop_type
== PT_UNKNOWN
) {
3710 long_usage(CMD_CLEAR
, B_TRUE
);
3714 if (initialize(B_TRUE
) != Z_OK
)
3719 if (prop_type
== PT_RAW
) {
3720 in_progress_fstab
.zone_fs_raw
[0] = '\0';
3721 need_to_commit
= B_TRUE
;
3726 if (prop_type
== PT_IMPORTANCE
) {
3727 in_progress_psettab
.zone_importance
[0] = '\0';
3728 need_to_commit
= B_TRUE
;
3733 switch (prop_type
) {
3735 in_progress_mcaptab
.zone_physmem_cap
[0] = '\0';
3736 need_to_commit
= B_TRUE
;
3739 remove_aliased_rctl(PT_SWAP
, ALIAS_MAXSWAP
);
3742 remove_aliased_rctl(PT_LOCKED
, ALIAS_MAXLOCKEDMEM
);
3747 switch (prop_type
) {
3749 in_progress_secflagstab
.zone_secflags_lower
[0] = '\0';
3750 need_to_commit
= B_TRUE
;
3753 in_progress_secflagstab
.zone_secflags_default
[0] = '\0';
3754 need_to_commit
= B_TRUE
;
3757 in_progress_secflagstab
.zone_secflags_upper
[0] = '\0';
3758 need_to_commit
= B_TRUE
;
3766 zone_perror(pt_to_str(prop_type
), Z_CLEAR_DISALLOW
, B_TRUE
);
3770 clear_global(cmd_t
*cmd
)
3774 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3775 long_usage(CMD_CLEAR
, B_TRUE
);
3779 if (initialize(B_TRUE
) != Z_OK
)
3788 zone_perror(pt_to_str(type
), Z_CLEAR_DISALLOW
, B_TRUE
);
3791 /* false is default; we'll treat as equivalent to clearing */
3792 if ((err
= zonecfg_set_autoboot(handle
, B_FALSE
)) != Z_OK
)
3793 z_cmd_rt_perror(CMD_CLEAR
, RT_AUTOBOOT
, err
, B_TRUE
);
3795 need_to_commit
= B_TRUE
;
3798 if ((err
= zonecfg_set_pool(handle
, NULL
)) != Z_OK
)
3799 z_cmd_rt_perror(CMD_CLEAR
, RT_POOL
, err
, B_TRUE
);
3801 need_to_commit
= B_TRUE
;
3804 if ((err
= zonecfg_set_limitpriv(handle
, NULL
)) != Z_OK
)
3805 z_cmd_rt_perror(CMD_CLEAR
, RT_LIMITPRIV
, err
, B_TRUE
);
3807 need_to_commit
= B_TRUE
;
3810 if ((err
= zonecfg_set_bootargs(handle
, NULL
)) != Z_OK
)
3811 z_cmd_rt_perror(CMD_CLEAR
, RT_BOOTARGS
, err
, B_TRUE
);
3813 need_to_commit
= B_TRUE
;
3816 if ((err
= zonecfg_set_sched(handle
, NULL
)) != Z_OK
)
3817 z_cmd_rt_perror(CMD_CLEAR
, RT_SCHED
, err
, B_TRUE
);
3819 need_to_commit
= B_TRUE
;
3822 /* shared is default; we'll treat as equivalent to clearing */
3823 if ((err
= zonecfg_set_iptype(handle
, ZS_SHARED
)) != Z_OK
)
3824 z_cmd_rt_perror(CMD_CLEAR
, RT_IPTYPE
, err
, B_TRUE
);
3826 need_to_commit
= B_TRUE
;
3829 remove_aliased_rctl(PT_MAXLWPS
, ALIAS_MAXLWPS
);
3832 remove_aliased_rctl(PT_MAXPROCS
, ALIAS_MAXPROCS
);
3835 remove_aliased_rctl(PT_MAXSHMMEM
, ALIAS_MAXSHMMEM
);
3838 remove_aliased_rctl(PT_MAXSHMIDS
, ALIAS_MAXSHMIDS
);
3841 remove_aliased_rctl(PT_MAXMSGIDS
, ALIAS_MAXMSGIDS
);
3844 remove_aliased_rctl(PT_MAXSEMIDS
, ALIAS_MAXSEMIDS
);
3847 remove_aliased_rctl(PT_SHARES
, ALIAS_SHARES
);
3850 if ((err
= zonecfg_set_hostid(handle
, NULL
)) != Z_OK
)
3851 z_cmd_rt_perror(CMD_CLEAR
, RT_HOSTID
, err
, B_TRUE
);
3853 need_to_commit
= B_TRUE
;
3856 if ((err
= zonecfg_set_fs_allowed(handle
, NULL
)) != Z_OK
)
3857 z_cmd_rt_perror(CMD_CLEAR
, RT_FS_ALLOWED
, err
, B_TRUE
);
3859 need_to_commit
= B_TRUE
;
3862 zone_perror(pt_to_str(type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
3863 long_usage(CMD_CLEAR
, B_TRUE
);
3864 usage(B_FALSE
, HELP_PROPS
);
3870 clear_func(cmd_t
*cmd
)
3872 if (zone_is_read_only(CMD_CLEAR
))
3875 assert(cmd
!= NULL
);
3878 if (gz_invalid_property(cmd
->cmd_res_type
)) {
3879 zerr(gettext("%s is not a valid property for the "
3880 "global zone."), pt_to_str(cmd
->cmd_res_type
));
3887 clear_property(cmd
);
3892 select_func(cmd_t
*cmd
)
3898 if (zone_is_read_only(CMD_SELECT
))
3901 assert(cmd
!= NULL
);
3904 global_scope
= B_FALSE
;
3905 resource_scope
= cmd
->cmd_res_type
;
3906 end_op
= CMD_SELECT
;
3908 scope_usage(CMD_SELECT
);
3912 if ((type
= cmd
->cmd_res_type
) == RT_UNKNOWN
) {
3913 long_usage(CMD_SELECT
, B_TRUE
);
3917 if (initialize(B_TRUE
) != Z_OK
)
3922 if ((err
= fill_in_fstab(cmd
, &old_fstab
, B_FALSE
)) != Z_OK
) {
3923 z_cmd_rt_perror(CMD_SELECT
, RT_FS
, err
, B_TRUE
);
3924 global_scope
= B_TRUE
;
3926 bcopy(&old_fstab
, &in_progress_fstab
,
3927 sizeof (struct zone_fstab
));
3930 if ((err
= fill_in_nwiftab(cmd
, &old_nwiftab
, B_FALSE
))
3932 z_cmd_rt_perror(CMD_SELECT
, RT_NET
, err
, B_TRUE
);
3933 global_scope
= B_TRUE
;
3935 bcopy(&old_nwiftab
, &in_progress_nwiftab
,
3936 sizeof (struct zone_nwiftab
));
3939 if ((err
= fill_in_devtab(cmd
, &old_devtab
, B_FALSE
)) != Z_OK
) {
3940 z_cmd_rt_perror(CMD_SELECT
, RT_DEVICE
, err
, B_TRUE
);
3941 global_scope
= B_TRUE
;
3943 bcopy(&old_devtab
, &in_progress_devtab
,
3944 sizeof (struct zone_devtab
));
3947 if ((err
= fill_in_rctltab(cmd
, &old_rctltab
, B_FALSE
))
3949 z_cmd_rt_perror(CMD_SELECT
, RT_RCTL
, err
, B_TRUE
);
3950 global_scope
= B_TRUE
;
3952 bcopy(&old_rctltab
, &in_progress_rctltab
,
3953 sizeof (struct zone_rctltab
));
3956 if ((err
= fill_in_attrtab(cmd
, &old_attrtab
, B_FALSE
))
3958 z_cmd_rt_perror(CMD_SELECT
, RT_ATTR
, err
, B_TRUE
);
3959 global_scope
= B_TRUE
;
3961 bcopy(&old_attrtab
, &in_progress_attrtab
,
3962 sizeof (struct zone_attrtab
));
3965 if ((err
= fill_in_dstab(cmd
, &old_dstab
, B_FALSE
)) != Z_OK
) {
3966 z_cmd_rt_perror(CMD_SELECT
, RT_DATASET
, err
, B_TRUE
);
3967 global_scope
= B_TRUE
;
3969 bcopy(&old_dstab
, &in_progress_dstab
,
3970 sizeof (struct zone_dstab
));
3973 if ((err
= zonecfg_lookup_pset(handle
, &old_psettab
)) != Z_OK
) {
3974 z_cmd_rt_perror(CMD_SELECT
, RT_DCPU
, err
, B_TRUE
);
3975 global_scope
= B_TRUE
;
3977 bcopy(&old_psettab
, &in_progress_psettab
,
3978 sizeof (struct zone_psettab
));
3981 if ((err
= zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &tmp
))
3983 z_cmd_rt_perror(CMD_SELECT
, RT_PCAP
, err
, B_TRUE
);
3984 global_scope
= B_TRUE
;
3988 /* if none of these exist, there is no resource to select */
3989 if ((res
= zonecfg_lookup_mcap(handle
, &old_mcaptab
)) != Z_OK
&&
3990 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &limit
)
3992 zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
, &limit
)
3994 z_cmd_rt_perror(CMD_SELECT
, RT_MCAP
, Z_NO_RESOURCE_TYPE
,
3996 global_scope
= B_TRUE
;
3999 bcopy(&old_mcaptab
, &in_progress_mcaptab
,
4000 sizeof (struct zone_mcaptab
));
4002 bzero(&in_progress_mcaptab
,
4003 sizeof (in_progress_mcaptab
));
4006 if ((err
= fill_in_admintab(cmd
, &old_admintab
, B_FALSE
))
4008 z_cmd_rt_perror(CMD_SELECT
, RT_ADMIN
, err
,
4010 global_scope
= B_TRUE
;
4012 bcopy(&old_admintab
, &in_progress_admintab
,
4013 sizeof (struct zone_admintab
));
4016 if ((err
= fill_in_secflagstab(cmd
, &old_secflagstab
, B_FALSE
))
4018 z_cmd_rt_perror(CMD_SELECT
, RT_SECFLAGS
, err
,
4020 global_scope
= B_TRUE
;
4022 bcopy(&old_secflagstab
, &in_progress_secflagstab
,
4023 sizeof (struct zone_secflagstab
));
4026 zone_perror(rt_to_str(type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
4027 long_usage(CMD_SELECT
, B_TRUE
);
4028 usage(B_FALSE
, HELP_RESOURCES
);
4034 * Network "addresses" can be one of the following forms:
4036 * <IPv4 address>/<prefix length>
4037 * <IPv6 address>/<prefix length>
4039 * <host name>/<prefix length>
4040 * In other words, the "/" followed by a prefix length is allowed but not
4041 * required for IPv4 addresses and host names, and required for IPv6 addresses.
4042 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
4043 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
4044 * Host names must start with an alpha-numeric character, and all subsequent
4045 * characters must be either alpha-numeric or "-".
4047 * In some cases, e.g., the nexthop for the defrouter, the context indicates
4048 * that this is the IPV4_ABITS or IPV6_ABITS netmask, in which case we don't
4049 * require the /<prefix length> (and should ignore it if provided).
4053 validate_net_address_syntax(char *address
, boolean_t ishost
)
4055 char *slashp
, part1
[MAXHOSTNAMELEN
];
4056 struct in6_addr in6
;
4061 * Copy the part before any '/' into part1 or copy the whole
4062 * thing if there is no '/'.
4064 if ((slashp
= strchr(address
, '/')) != NULL
) {
4066 (void) strlcpy(part1
, address
, sizeof (part1
));
4068 prefixlen
= atoi(++slashp
);
4070 (void) strlcpy(part1
, address
, sizeof (part1
));
4073 if (ishost
&& slashp
!= NULL
) {
4074 zerr(gettext("Warning: prefix length in %s is not required and "
4075 "will be ignored. The default host-prefix length "
4076 "will be used"), address
);
4080 if (inet_pton(AF_INET6
, part1
, &in6
) == 1) {
4082 prefixlen
= IPV6_ABITS
;
4083 } else if (slashp
== NULL
) {
4084 zerr(gettext("%s: IPv6 addresses "
4085 "require /prefix-length suffix."), address
);
4088 if (prefixlen
< 0 || prefixlen
> 128) {
4089 zerr(gettext("%s: IPv6 address "
4090 "prefix lengths must be 0 - 128."), address
);
4096 /* At this point, any /prefix must be for IPv4. */
4098 prefixlen
= IPV4_ABITS
;
4099 else if (slashp
!= NULL
) {
4100 if (prefixlen
< 0 || prefixlen
> 32) {
4101 zerr(gettext("%s: IPv4 address "
4102 "prefix lengths must be 0 - 32."), address
);
4107 if (inet_pton(AF_INET
, part1
, &in4
) == 1)
4110 /* address may also be a host name */
4111 if (!isalnum(part1
[0])) {
4112 zerr(gettext("%s: bogus host name or network address syntax"),
4115 usage(B_FALSE
, HELP_NETADDR
);
4118 for (i
= 1; part1
[i
]; i
++)
4119 if (!isalnum(part1
[i
]) && part1
[i
] != '-' && part1
[i
] != '.') {
4120 zerr(gettext("%s: bogus host name or "
4121 "network address syntax"), part1
);
4123 usage(B_FALSE
, HELP_NETADDR
);
4130 validate_net_physical_syntax(const char *ifname
)
4132 ifspec_t ifnameprop
;
4133 zone_iptype_t iptype
;
4135 if (zonecfg_get_iptype(handle
, &iptype
) != Z_OK
) {
4136 zerr(gettext("zone configuration has an invalid or nonexistent "
4137 "ip-type property"));
4142 if (ifparse_ifspec(ifname
, &ifnameprop
) == B_FALSE
) {
4143 zerr(gettext("%s: invalid physical interface name"),
4147 if (ifnameprop
.ifsp_lunvalid
) {
4148 zerr(gettext("%s: LUNs not allowed in physical "
4149 "interface names"), ifname
);
4154 if (dladm_valid_linkname(ifname
) == B_FALSE
) {
4155 if (strchr(ifname
, ':') != NULL
)
4156 zerr(gettext("%s: physical interface name "
4157 "required; logical interface name not "
4158 "allowed"), ifname
);
4160 zerr(gettext("%s: invalid physical interface "
4170 valid_fs_type(const char *type
)
4173 * Is this a valid path component?
4175 if (strlen(type
) + 1 > MAXNAMELEN
)
4178 * Make sure a bad value for "type" doesn't make
4179 * /usr/lib/fs/<type>/mount turn into something else.
4181 if (strchr(type
, '/') != NULL
|| type
[0] == '\0' ||
4182 strcmp(type
, ".") == 0 || strcmp(type
, "..") == 0)
4185 * More detailed verification happens later by zoneadm(1m).
4194 char brand
[MAXNAMELEN
];
4197 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) != Z_OK
) {
4198 zerr("%s: %s\n", zone
, gettext("could not get zone brand"));
4201 if ((bh
= brand_open(brand
)) == NULL
) {
4202 zerr("%s: %s\n", zone
, gettext("unknown brand."));
4205 ret
= brand_allow_exclusive_ip(bh
);
4208 zerr(gettext("%s cannot be '%s' when %s is '%s'."),
4209 pt_to_str(PT_IPTYPE
), "exclusive",
4210 pt_to_str(PT_BRAND
), brand
);
4215 set_aliased_rctl(char *alias
, int prop_type
, char *s
)
4221 if (global_zone
&& strcmp(alias
, ALIAS_SHARES
) != 0)
4222 zerr(gettext("WARNING: Setting a global zone resource "
4223 "control too low could deny\nservice "
4224 "to even the root user; "
4225 "this could render the system impossible\n"
4226 "to administer. Please use caution."));
4228 /* convert memory based properties */
4229 if (prop_type
== PT_MAXSHMMEM
) {
4230 if (!zonecfg_valid_memlimit(s
, &limit
)) {
4231 zerr(gettext("A non-negative number with a required "
4232 "scale suffix (K, M, G or T) was expected\nhere."));
4237 (void) snprintf(tmp
, sizeof (tmp
), "%llu", limit
);
4241 if (!zonecfg_aliased_rctl_ok(handle
, alias
)) {
4242 zone_perror(pt_to_str(prop_type
), Z_ALIAS_DISALLOW
, B_FALSE
);
4244 } else if (!zonecfg_valid_alias_limit(alias
, s
, &limit
)) {
4245 zerr(gettext("%s property is out of range."),
4246 pt_to_str(prop_type
));
4248 } else if ((err
= zonecfg_set_aliased_rctl(handle
, alias
, limit
))
4250 zone_perror(zone
, err
, B_TRUE
);
4253 need_to_commit
= B_TRUE
;
4258 set_in_progress_nwiftab_address(char *prop_id
, int prop_type
)
4260 if (prop_type
== PT_ADDRESS
) {
4261 (void) strlcpy(in_progress_nwiftab
.zone_nwif_address
, prop_id
,
4262 sizeof (in_progress_nwiftab
.zone_nwif_address
));
4264 assert(prop_type
== PT_ALLOWED_ADDRESS
);
4265 (void) strlcpy(in_progress_nwiftab
.zone_nwif_allowed_address
,
4267 sizeof (in_progress_nwiftab
.zone_nwif_allowed_address
));
4272 set_func(cmd_t
*cmd
)
4275 int arg
, err
, res_type
, prop_type
;
4276 property_value_ptr_t pp
;
4278 zone_iptype_t iptype
;
4279 boolean_t force_set
= B_FALSE
;
4280 size_t physmem_size
= sizeof (in_progress_mcaptab
.zone_physmem_cap
);
4281 uint64_t mem_cap
, mem_limit
;
4284 struct zone_psettab tmp_psettab
;
4285 boolean_t arg_err
= B_FALSE
;
4287 if (zone_is_read_only(CMD_SET
))
4290 assert(cmd
!= NULL
);
4292 optind
= opterr
= 0;
4293 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "F")) != EOF
) {
4300 longer_usage(CMD_SET
);
4302 short_usage(CMD_SET
);
4310 prop_type
= cmd
->cmd_prop_name
[0];
4312 if (gz_invalid_property(prop_type
)) {
4313 zerr(gettext("%s is not a valid property for the "
4314 "global zone."), pt_to_str(prop_type
));
4319 if (prop_type
== PT_ZONENAME
) {
4320 res_type
= RT_ZONENAME
;
4321 } else if (prop_type
== PT_ZONEPATH
) {
4322 res_type
= RT_ZONEPATH
;
4323 } else if (prop_type
== PT_AUTOBOOT
) {
4324 res_type
= RT_AUTOBOOT
;
4325 } else if (prop_type
== PT_BRAND
) {
4326 res_type
= RT_BRAND
;
4327 } else if (prop_type
== PT_POOL
) {
4329 } else if (prop_type
== PT_LIMITPRIV
) {
4330 res_type
= RT_LIMITPRIV
;
4331 } else if (prop_type
== PT_BOOTARGS
) {
4332 res_type
= RT_BOOTARGS
;
4333 } else if (prop_type
== PT_SCHED
) {
4334 res_type
= RT_SCHED
;
4335 } else if (prop_type
== PT_IPTYPE
) {
4336 res_type
= RT_IPTYPE
;
4337 } else if (prop_type
== PT_MAXLWPS
) {
4338 res_type
= RT_MAXLWPS
;
4339 } else if (prop_type
== PT_MAXPROCS
) {
4340 res_type
= RT_MAXPROCS
;
4341 } else if (prop_type
== PT_MAXSHMMEM
) {
4342 res_type
= RT_MAXSHMMEM
;
4343 } else if (prop_type
== PT_MAXSHMIDS
) {
4344 res_type
= RT_MAXSHMIDS
;
4345 } else if (prop_type
== PT_MAXMSGIDS
) {
4346 res_type
= RT_MAXMSGIDS
;
4347 } else if (prop_type
== PT_MAXSEMIDS
) {
4348 res_type
= RT_MAXSEMIDS
;
4349 } else if (prop_type
== PT_SHARES
) {
4350 res_type
= RT_SHARES
;
4351 } else if (prop_type
== PT_HOSTID
) {
4352 res_type
= RT_HOSTID
;
4353 } else if (prop_type
== PT_FS_ALLOWED
) {
4354 res_type
= RT_FS_ALLOWED
;
4356 zerr(gettext("Cannot set a resource-specific property "
4357 "from the global scope."));
4362 res_type
= resource_scope
;
4366 if (res_type
!= RT_ZONEPATH
) {
4367 zerr(gettext("Only zonepath setting can be forced."));
4371 if (!zonecfg_in_alt_root()) {
4372 zerr(gettext("Zonepath is changeable only in an "
4373 "alternate root."));
4379 pp
= cmd
->cmd_property_ptr
[0];
4381 * A nasty expression but not that complicated:
4382 * 1. fs options are simple or list (tested below)
4383 * 2. rctl value's are complex or list (tested below)
4384 * Anything else should be simple.
4386 if (!(res_type
== RT_FS
&& prop_type
== PT_OPTIONS
) &&
4387 !(res_type
== RT_RCTL
&& prop_type
== PT_VALUE
) &&
4388 (pp
->pv_type
!= PROP_VAL_SIMPLE
||
4389 (prop_id
= pp
->pv_simple
) == NULL
)) {
4390 zerr(gettext("A %s value was expected here."),
4391 pvt_to_str(PROP_VAL_SIMPLE
));
4395 if (prop_type
== PT_UNKNOWN
) {
4396 long_usage(CMD_SET
, B_TRUE
);
4401 * Special case: the user can change the zone name prior to 'create';
4402 * if the zone already exists, we fall through letting initialize()
4403 * and the rest of the logic run.
4405 if (res_type
== RT_ZONENAME
&& got_handle
== B_FALSE
&&
4406 !state_atleast(ZONE_STATE_CONFIGURED
)) {
4407 if ((err
= zonecfg_validate_zonename(prop_id
)) != Z_OK
) {
4408 zone_perror(prop_id
, err
, B_TRUE
);
4409 usage(B_FALSE
, HELP_SYNTAX
);
4412 (void) strlcpy(zone
, prop_id
, sizeof (zone
));
4416 if (initialize(B_TRUE
) != Z_OK
)
4421 if ((err
= zonecfg_set_name(handle
, prop_id
)) != Z_OK
) {
4423 * Use prop_id instead of 'zone' here, since we're
4424 * reporting a problem about the *new* zonename.
4426 zone_perror(prop_id
, err
, B_TRUE
);
4427 usage(B_FALSE
, HELP_SYNTAX
);
4429 need_to_commit
= B_TRUE
;
4430 (void) strlcpy(zone
, prop_id
, sizeof (zone
));
4434 if (!force_set
&& state_atleast(ZONE_STATE_INSTALLED
)) {
4435 zerr(gettext("Zone %s already installed; %s %s not "
4436 "allowed."), zone
, cmd_to_str(CMD_SET
),
4437 rt_to_str(RT_ZONEPATH
));
4440 if (validate_zonepath_syntax(prop_id
) != Z_OK
) {
4444 if ((err
= zonecfg_set_zonepath(handle
, prop_id
)) != Z_OK
)
4445 zone_perror(zone
, err
, B_TRUE
);
4447 need_to_commit
= B_TRUE
;
4450 if (state_atleast(ZONE_STATE_INSTALLED
)) {
4451 zerr(gettext("Zone %s already installed; %s %s not "
4452 "allowed."), zone
, cmd_to_str(CMD_SET
),
4453 rt_to_str(RT_BRAND
));
4456 if ((err
= zonecfg_set_brand(handle
, prop_id
)) != Z_OK
)
4457 zone_perror(zone
, err
, B_TRUE
);
4459 need_to_commit
= B_TRUE
;
4462 if (strcmp(prop_id
, "true") == 0) {
4464 } else if (strcmp(prop_id
, "false") == 0) {
4467 zerr(gettext("%s value must be '%s' or '%s'."),
4468 pt_to_str(PT_AUTOBOOT
), "true", "false");
4472 if ((err
= zonecfg_set_autoboot(handle
, autoboot
)) != Z_OK
)
4473 zone_perror(zone
, err
, B_TRUE
);
4475 need_to_commit
= B_TRUE
;
4478 /* don't allow use of the reserved temporary pool names */
4479 if (strncmp("SUNW", prop_id
, 4) == 0) {
4480 zerr(gettext("pool names starting with SUNW are "
4486 /* can't set pool if dedicated-cpu exists */
4487 if (zonecfg_lookup_pset(handle
, &tmp_psettab
) == Z_OK
) {
4488 zerr(gettext("The %s resource already exists. "
4489 "A persistent pool is incompatible\nwith the %s "
4490 "resource."), rt_to_str(RT_DCPU
),
4491 rt_to_str(RT_DCPU
));
4496 if ((err
= zonecfg_set_pool(handle
, prop_id
)) != Z_OK
)
4497 zone_perror(zone
, err
, B_TRUE
);
4499 need_to_commit
= B_TRUE
;
4502 if ((err
= zonecfg_set_limitpriv(handle
, prop_id
)) != Z_OK
)
4503 zone_perror(zone
, err
, B_TRUE
);
4505 need_to_commit
= B_TRUE
;
4508 if ((err
= zonecfg_set_bootargs(handle
, prop_id
)) != Z_OK
)
4509 zone_perror(zone
, err
, B_TRUE
);
4511 need_to_commit
= B_TRUE
;
4514 if ((err
= zonecfg_set_sched(handle
, prop_id
)) != Z_OK
)
4515 zone_perror(zone
, err
, B_TRUE
);
4517 need_to_commit
= B_TRUE
;
4520 if (strcmp(prop_id
, "shared") == 0) {
4522 } else if (strcmp(prop_id
, "exclusive") == 0) {
4523 iptype
= ZS_EXCLUSIVE
;
4525 zerr(gettext("%s value must be '%s' or '%s'."),
4526 pt_to_str(PT_IPTYPE
), "shared", "exclusive");
4530 if (iptype
== ZS_EXCLUSIVE
&& !allow_exclusive()) {
4534 if ((err
= zonecfg_set_iptype(handle
, iptype
)) != Z_OK
)
4535 zone_perror(zone
, err
, B_TRUE
);
4537 need_to_commit
= B_TRUE
;
4540 set_aliased_rctl(ALIAS_MAXLWPS
, prop_type
, prop_id
);
4543 set_aliased_rctl(ALIAS_MAXPROCS
, prop_type
, prop_id
);
4546 set_aliased_rctl(ALIAS_MAXSHMMEM
, prop_type
, prop_id
);
4549 set_aliased_rctl(ALIAS_MAXSHMIDS
, prop_type
, prop_id
);
4552 set_aliased_rctl(ALIAS_MAXMSGIDS
, prop_type
, prop_id
);
4555 set_aliased_rctl(ALIAS_MAXSEMIDS
, prop_type
, prop_id
);
4558 set_aliased_rctl(ALIAS_SHARES
, prop_type
, prop_id
);
4561 if ((err
= zonecfg_set_hostid(handle
, prop_id
)) != Z_OK
) {
4562 if (err
== Z_TOO_BIG
) {
4563 zerr(gettext("hostid string is too large: %s"),
4567 zone_perror(pt_to_str(prop_type
), err
, B_TRUE
);
4571 need_to_commit
= B_TRUE
;
4574 if ((err
= zonecfg_set_fs_allowed(handle
, prop_id
)) != Z_OK
)
4575 zone_perror(zone
, err
, B_TRUE
);
4577 need_to_commit
= B_TRUE
;
4580 switch (prop_type
) {
4582 (void) strlcpy(in_progress_fstab
.zone_fs_dir
, prop_id
,
4583 sizeof (in_progress_fstab
.zone_fs_dir
));
4586 (void) strlcpy(in_progress_fstab
.zone_fs_special
,
4588 sizeof (in_progress_fstab
.zone_fs_special
));
4591 (void) strlcpy(in_progress_fstab
.zone_fs_raw
,
4592 prop_id
, sizeof (in_progress_fstab
.zone_fs_raw
));
4595 if (!valid_fs_type(prop_id
)) {
4596 zerr(gettext("\"%s\" is not a valid %s."),
4597 prop_id
, pt_to_str(PT_TYPE
));
4601 (void) strlcpy(in_progress_fstab
.zone_fs_type
, prop_id
,
4602 sizeof (in_progress_fstab
.zone_fs_type
));
4605 if (pp
->pv_type
!= PROP_VAL_SIMPLE
&&
4606 pp
->pv_type
!= PROP_VAL_LIST
) {
4607 zerr(gettext("A %s or %s value was expected "
4608 "here."), pvt_to_str(PROP_VAL_SIMPLE
),
4609 pvt_to_str(PROP_VAL_LIST
));
4613 zonecfg_free_fs_option_list(
4614 in_progress_fstab
.zone_fs_options
);
4615 in_progress_fstab
.zone_fs_options
= NULL
;
4616 if (!(pp
->pv_type
== PROP_VAL_LIST
&&
4617 pp
->pv_list
== NULL
))
4623 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4624 long_usage(CMD_SET
, B_TRUE
);
4625 usage(B_FALSE
, HELP_PROPS
);
4628 switch (prop_type
) {
4630 case PT_ALLOWED_ADDRESS
:
4631 if (validate_net_address_syntax(prop_id
, B_FALSE
)
4636 set_in_progress_nwiftab_address(prop_id
, prop_type
);
4639 if (validate_net_physical_syntax(prop_id
) != Z_OK
) {
4643 (void) strlcpy(in_progress_nwiftab
.zone_nwif_physical
,
4645 sizeof (in_progress_nwiftab
.zone_nwif_physical
));
4648 if (validate_net_address_syntax(prop_id
, B_TRUE
)
4653 (void) strlcpy(in_progress_nwiftab
.zone_nwif_defrouter
,
4655 sizeof (in_progress_nwiftab
.zone_nwif_defrouter
));
4658 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4660 long_usage(CMD_SET
, B_TRUE
);
4661 usage(B_FALSE
, HELP_PROPS
);
4666 switch (prop_type
) {
4668 (void) strlcpy(in_progress_devtab
.zone_dev_match
,
4670 sizeof (in_progress_devtab
.zone_dev_match
));
4673 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4675 long_usage(CMD_SET
, B_TRUE
);
4676 usage(B_FALSE
, HELP_PROPS
);
4681 switch (prop_type
) {
4683 if (!zonecfg_valid_rctlname(prop_id
)) {
4684 zerr(gettext("'%s' is not a valid zone %s "
4685 "name."), prop_id
, rt_to_str(RT_RCTL
));
4688 (void) strlcpy(in_progress_rctltab
.zone_rctl_name
,
4690 sizeof (in_progress_rctltab
.zone_rctl_name
));
4693 if (pp
->pv_type
!= PROP_VAL_COMPLEX
&&
4694 pp
->pv_type
!= PROP_VAL_LIST
) {
4695 zerr(gettext("A %s or %s value was expected "
4696 "here."), pvt_to_str(PROP_VAL_COMPLEX
),
4697 pvt_to_str(PROP_VAL_LIST
));
4701 zonecfg_free_rctl_value_list(
4702 in_progress_rctltab
.zone_rctl_valptr
);
4703 in_progress_rctltab
.zone_rctl_valptr
= NULL
;
4704 if (!(pp
->pv_type
== PROP_VAL_LIST
&&
4705 pp
->pv_list
== NULL
))
4709 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4711 long_usage(CMD_SET
, B_TRUE
);
4712 usage(B_FALSE
, HELP_PROPS
);
4717 switch (prop_type
) {
4719 (void) strlcpy(in_progress_attrtab
.zone_attr_name
,
4721 sizeof (in_progress_attrtab
.zone_attr_name
));
4724 (void) strlcpy(in_progress_attrtab
.zone_attr_type
,
4726 sizeof (in_progress_attrtab
.zone_attr_type
));
4729 (void) strlcpy(in_progress_attrtab
.zone_attr_value
,
4731 sizeof (in_progress_attrtab
.zone_attr_value
));
4734 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4736 long_usage(CMD_SET
, B_TRUE
);
4737 usage(B_FALSE
, HELP_PROPS
);
4742 switch (prop_type
) {
4744 (void) strlcpy(in_progress_dstab
.zone_dataset_name
,
4746 sizeof (in_progress_dstab
.zone_dataset_name
));
4751 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4752 long_usage(CMD_SET
, B_TRUE
);
4753 usage(B_FALSE
, HELP_PROPS
);
4756 switch (prop_type
) {
4761 if ((highp
= strchr(prop_id
, '-')) != NULL
)
4766 /* Make sure the input makes sense. */
4767 if (!zonecfg_valid_ncpus(lowp
, highp
)) {
4768 zerr(gettext("%s property is out of range."),
4769 pt_to_str(PT_NCPUS
));
4775 in_progress_psettab
.zone_ncpu_min
, lowp
,
4776 sizeof (in_progress_psettab
.zone_ncpu_min
));
4778 in_progress_psettab
.zone_ncpu_max
, highp
,
4779 sizeof (in_progress_psettab
.zone_ncpu_max
));
4782 /* Make sure the value makes sense. */
4783 if (!zonecfg_valid_importance(prop_id
)) {
4784 zerr(gettext("%s property is out of range."),
4785 pt_to_str(PT_IMPORTANCE
));
4790 (void) strlcpy(in_progress_psettab
.zone_importance
,
4792 sizeof (in_progress_psettab
.zone_importance
));
4797 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
, B_TRUE
);
4798 long_usage(CMD_SET
, B_TRUE
);
4799 usage(B_FALSE
, HELP_PROPS
);
4802 if (prop_type
!= PT_NCPUS
) {
4803 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4805 long_usage(CMD_SET
, B_TRUE
);
4806 usage(B_FALSE
, HELP_PROPS
);
4811 * We already checked that an rctl alias is allowed in
4812 * the add_resource() function.
4815 if ((cap
= strtof(prop_id
, &unitp
)) <= 0 || *unitp
!= '\0' ||
4816 (int)(cap
* 100) < 1) {
4817 zerr(gettext("%s property is out of range."),
4818 pt_to_str(PT_NCPUS
));
4823 if ((err
= zonecfg_set_aliased_rctl(handle
, ALIAS_CPUCAP
,
4824 (int)(cap
* 100))) != Z_OK
)
4825 zone_perror(zone
, err
, B_TRUE
);
4827 need_to_commit
= B_TRUE
;
4830 switch (prop_type
) {
4832 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4833 zerr(gettext("A positive number with a "
4834 "required scale suffix (K, M, G or T) was "
4837 } else if (mem_cap
< ONE_MB
) {
4838 zerr(gettext("%s value is too small. It must "
4839 "be at least 1M."), pt_to_str(PT_PHYSICAL
));
4842 snprintf(in_progress_mcaptab
.zone_physmem_cap
,
4843 physmem_size
, "%llu", mem_cap
);
4848 * We have to check if an rctl is allowed here since
4849 * there might already be a rctl defined that blocks
4852 if (!zonecfg_aliased_rctl_ok(handle
, ALIAS_MAXSWAP
)) {
4853 zone_perror(pt_to_str(PT_MAXSWAP
),
4854 Z_ALIAS_DISALLOW
, B_FALSE
);
4860 mem_limit
= ONE_MB
* 100;
4862 mem_limit
= ONE_MB
* 50;
4864 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4865 zerr(gettext("A positive number with a "
4866 "required scale suffix (K, M, G or T) was "
4869 } else if (mem_cap
< mem_limit
) {
4872 (void) snprintf(buf
, sizeof (buf
), "%llu",
4874 bytes_to_units(buf
, buf
, sizeof (buf
));
4875 zerr(gettext("%s value is too small. It must "
4876 "be at least %s."), pt_to_str(PT_SWAP
),
4880 if ((err
= zonecfg_set_aliased_rctl(handle
,
4881 ALIAS_MAXSWAP
, mem_cap
)) != Z_OK
)
4882 zone_perror(zone
, err
, B_TRUE
);
4884 need_to_commit
= B_TRUE
;
4889 * We have to check if an rctl is allowed here since
4890 * there might already be a rctl defined that blocks
4893 if (!zonecfg_aliased_rctl_ok(handle
,
4894 ALIAS_MAXLOCKEDMEM
)) {
4895 zone_perror(pt_to_str(PT_LOCKED
),
4896 Z_ALIAS_DISALLOW
, B_FALSE
);
4901 if (!zonecfg_valid_memlimit(prop_id
, &mem_cap
)) {
4902 zerr(gettext("A non-negative number with a "
4903 "required scale suffix (K, M, G or T) was "
4904 "expected\nhere."));
4907 if ((err
= zonecfg_set_aliased_rctl(handle
,
4908 ALIAS_MAXLOCKEDMEM
, mem_cap
)) != Z_OK
)
4909 zone_perror(zone
, err
, B_TRUE
);
4911 need_to_commit
= B_TRUE
;
4915 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4917 long_usage(CMD_SET
, B_TRUE
);
4918 usage(B_FALSE
, HELP_PROPS
);
4923 switch (prop_type
) {
4925 (void) strlcpy(in_progress_admintab
.zone_admin_user
,
4927 sizeof (in_progress_admintab
.zone_admin_user
));
4930 (void) strlcpy(in_progress_admintab
.zone_admin_auths
,
4932 sizeof (in_progress_admintab
.zone_admin_auths
));
4935 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4937 long_usage(CMD_SET
, B_TRUE
);
4938 usage(B_FALSE
, HELP_PROPS
);
4944 switch (prop_type
) {
4946 propstr
= in_progress_secflagstab
.zone_secflags_default
;
4949 propstr
= in_progress_secflagstab
.zone_secflags_upper
;
4952 propstr
= in_progress_secflagstab
.zone_secflags_lower
;
4955 zone_perror(pt_to_str(prop_type
), Z_NO_PROPERTY_TYPE
,
4957 long_usage(CMD_SET
, B_TRUE
);
4958 usage(B_FALSE
, HELP_PROPS
);
4961 (void) strlcpy(propstr
, prop_id
, ZONECFG_SECFLAGS_MAX
);
4965 zone_perror(rt_to_str(res_type
), Z_NO_RESOURCE_TYPE
, B_TRUE
);
4966 long_usage(CMD_SET
, B_TRUE
);
4967 usage(B_FALSE
, HELP_RESOURCES
);
4973 output_prop(FILE *fp
, int pnum
, char *pval
, boolean_t print_notspec
)
4977 if (*pval
!= '\0') {
4978 qstr
= quoteit(pval
);
4979 if (pnum
== PT_SWAP
|| pnum
== PT_LOCKED
)
4980 (void) fprintf(fp
, "\t[%s: %s]\n", pt_to_str(pnum
),
4983 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(pnum
), qstr
);
4985 } else if (print_notspec
)
4986 (void) fprintf(fp
, gettext("\t%s not specified\n"),
4991 info_zonename(zone_dochandle_t handle
, FILE *fp
)
4993 char zonename
[ZONENAME_MAX
];
4995 if (zonecfg_get_name(handle
, zonename
, sizeof (zonename
)) == Z_OK
)
4996 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_ZONENAME
),
4999 (void) fprintf(fp
, gettext("%s not specified\n"),
5000 pt_to_str(PT_ZONENAME
));
5004 info_zonepath(zone_dochandle_t handle
, FILE *fp
)
5006 char zonepath
[MAXPATHLEN
];
5008 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) == Z_OK
)
5009 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_ZONEPATH
),
5012 (void) fprintf(fp
, gettext("%s not specified\n"),
5013 pt_to_str(PT_ZONEPATH
));
5018 info_brand(zone_dochandle_t handle
, FILE *fp
)
5020 char brand
[MAXNAMELEN
];
5022 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) == Z_OK
)
5023 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_BRAND
),
5026 (void) fprintf(fp
, "%s %s\n", pt_to_str(PT_BRAND
),
5027 gettext("not specified"));
5031 info_autoboot(zone_dochandle_t handle
, FILE *fp
)
5036 if ((err
= zonecfg_get_autoboot(handle
, &autoboot
)) == Z_OK
)
5037 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_AUTOBOOT
),
5038 autoboot
? "true" : "false");
5040 zone_perror(zone
, err
, B_TRUE
);
5044 info_pool(zone_dochandle_t handle
, FILE *fp
)
5046 char pool
[MAXNAMELEN
];
5049 if ((err
= zonecfg_get_pool(handle
, pool
, sizeof (pool
))) == Z_OK
)
5050 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_POOL
), pool
);
5052 zone_perror(zone
, err
, B_TRUE
);
5056 info_limitpriv(zone_dochandle_t handle
, FILE *fp
)
5061 if ((err
= zonecfg_get_limitpriv(handle
, &limitpriv
)) == Z_OK
) {
5062 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_LIMITPRIV
),
5066 zone_perror(zone
, err
, B_TRUE
);
5071 info_bootargs(zone_dochandle_t handle
, FILE *fp
)
5073 char bootargs
[BOOTARGS_MAX
];
5076 if ((err
= zonecfg_get_bootargs(handle
, bootargs
,
5077 sizeof (bootargs
))) == Z_OK
) {
5078 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_BOOTARGS
),
5081 zone_perror(zone
, err
, B_TRUE
);
5086 info_sched(zone_dochandle_t handle
, FILE *fp
)
5088 char sched
[MAXNAMELEN
];
5091 if ((err
= zonecfg_get_sched_class(handle
, sched
, sizeof (sched
)))
5093 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_SCHED
), sched
);
5095 zone_perror(zone
, err
, B_TRUE
);
5100 info_iptype(zone_dochandle_t handle
, FILE *fp
)
5102 zone_iptype_t iptype
;
5105 if ((err
= zonecfg_get_iptype(handle
, &iptype
)) == Z_OK
) {
5108 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_IPTYPE
),
5112 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_IPTYPE
),
5117 zone_perror(zone
, err
, B_TRUE
);
5122 info_hostid(zone_dochandle_t handle
, FILE *fp
)
5124 char hostidp
[HW_HOSTID_LEN
];
5127 if ((err
= zonecfg_get_hostid(handle
, hostidp
,
5128 sizeof (hostidp
))) == Z_OK
) {
5129 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_HOSTID
), hostidp
);
5130 } else if (err
== Z_BAD_PROPERTY
) {
5131 (void) fprintf(fp
, "%s: \n", pt_to_str(PT_HOSTID
));
5133 zone_perror(zone
, err
, B_TRUE
);
5138 info_fs_allowed(zone_dochandle_t handle
, FILE *fp
)
5140 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
5143 if ((err
= zonecfg_get_fs_allowed(handle
, fsallowedp
,
5144 sizeof (fsallowedp
))) == Z_OK
) {
5145 (void) fprintf(fp
, "%s: %s\n", pt_to_str(PT_FS_ALLOWED
),
5147 } else if (err
== Z_BAD_PROPERTY
) {
5148 (void) fprintf(fp
, "%s: \n", pt_to_str(PT_FS_ALLOWED
));
5150 zone_perror(zone
, err
, B_TRUE
);
5155 output_fs(FILE *fp
, struct zone_fstab
*fstab
)
5159 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_FS
));
5160 output_prop(fp
, PT_DIR
, fstab
->zone_fs_dir
, B_TRUE
);
5161 output_prop(fp
, PT_SPECIAL
, fstab
->zone_fs_special
, B_TRUE
);
5162 output_prop(fp
, PT_RAW
, fstab
->zone_fs_raw
, B_TRUE
);
5163 output_prop(fp
, PT_TYPE
, fstab
->zone_fs_type
, B_TRUE
);
5164 (void) fprintf(fp
, "\t%s: [", pt_to_str(PT_OPTIONS
));
5165 for (this = fstab
->zone_fs_options
; this != NULL
;
5166 this = this->zone_fsopt_next
) {
5167 if (strchr(this->zone_fsopt_opt
, '='))
5168 (void) fprintf(fp
, "\"%s\"", this->zone_fsopt_opt
);
5170 (void) fprintf(fp
, "%s", this->zone_fsopt_opt
);
5171 if (this->zone_fsopt_next
!= NULL
)
5172 (void) fprintf(fp
, ",");
5174 (void) fprintf(fp
, "]\n");
5178 info_fs(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5180 struct zone_fstab lookup
, user
;
5181 boolean_t output
= B_FALSE
;
5183 if (zonecfg_setfsent(handle
) != Z_OK
)
5185 while (zonecfg_getfsent(handle
, &lookup
) == Z_OK
) {
5186 if (cmd
->cmd_prop_nv_pairs
== 0) {
5187 output_fs(fp
, &lookup
);
5190 if (fill_in_fstab(cmd
, &user
, B_TRUE
) != Z_OK
)
5192 if (strlen(user
.zone_fs_dir
) > 0 &&
5193 strcmp(user
.zone_fs_dir
, lookup
.zone_fs_dir
) != 0)
5194 goto loopend
; /* no match */
5195 if (strlen(user
.zone_fs_special
) > 0 &&
5196 strcmp(user
.zone_fs_special
, lookup
.zone_fs_special
) != 0)
5197 goto loopend
; /* no match */
5198 if (strlen(user
.zone_fs_type
) > 0 &&
5199 strcmp(user
.zone_fs_type
, lookup
.zone_fs_type
) != 0)
5200 goto loopend
; /* no match */
5201 output_fs(fp
, &lookup
);
5204 zonecfg_free_fs_option_list(lookup
.zone_fs_options
);
5206 (void) zonecfg_endfsent(handle
);
5208 * If a property n/v pair was specified, warn the user if there was
5209 * nothing to output.
5211 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5212 (void) printf(gettext("No such %s resource.\n"),
5217 output_net(FILE *fp
, struct zone_nwiftab
*nwiftab
)
5219 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_NET
));
5220 output_prop(fp
, PT_ADDRESS
, nwiftab
->zone_nwif_address
, B_TRUE
);
5221 output_prop(fp
, PT_ALLOWED_ADDRESS
,
5222 nwiftab
->zone_nwif_allowed_address
, B_TRUE
);
5223 output_prop(fp
, PT_PHYSICAL
, nwiftab
->zone_nwif_physical
, B_TRUE
);
5224 output_prop(fp
, PT_DEFROUTER
, nwiftab
->zone_nwif_defrouter
, B_TRUE
);
5228 info_net(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5230 struct zone_nwiftab lookup
, user
;
5231 boolean_t output
= B_FALSE
;
5233 if (zonecfg_setnwifent(handle
) != Z_OK
)
5235 while (zonecfg_getnwifent(handle
, &lookup
) == Z_OK
) {
5236 if (cmd
->cmd_prop_nv_pairs
== 0) {
5237 output_net(fp
, &lookup
);
5240 if (fill_in_nwiftab(cmd
, &user
, B_TRUE
) != Z_OK
)
5242 if (strlen(user
.zone_nwif_physical
) > 0 &&
5243 strcmp(user
.zone_nwif_physical
,
5244 lookup
.zone_nwif_physical
) != 0)
5245 continue; /* no match */
5246 /* If present make sure it matches */
5247 if (strlen(user
.zone_nwif_address
) > 0 &&
5248 !zonecfg_same_net_address(user
.zone_nwif_address
,
5249 lookup
.zone_nwif_address
))
5250 continue; /* no match */
5251 output_net(fp
, &lookup
);
5254 (void) zonecfg_endnwifent(handle
);
5256 * If a property n/v pair was specified, warn the user if there was
5257 * nothing to output.
5259 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5260 (void) printf(gettext("No such %s resource.\n"),
5265 output_dev(FILE *fp
, struct zone_devtab
*devtab
)
5267 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DEVICE
));
5268 output_prop(fp
, PT_MATCH
, devtab
->zone_dev_match
, B_TRUE
);
5272 info_dev(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5274 struct zone_devtab lookup
, user
;
5275 boolean_t output
= B_FALSE
;
5277 if (zonecfg_setdevent(handle
) != Z_OK
)
5279 while (zonecfg_getdevent(handle
, &lookup
) == Z_OK
) {
5280 if (cmd
->cmd_prop_nv_pairs
== 0) {
5281 output_dev(fp
, &lookup
);
5284 if (fill_in_devtab(cmd
, &user
, B_TRUE
) != Z_OK
)
5286 if (strlen(user
.zone_dev_match
) > 0 &&
5287 strcmp(user
.zone_dev_match
, lookup
.zone_dev_match
) != 0)
5288 continue; /* no match */
5289 output_dev(fp
, &lookup
);
5292 (void) zonecfg_enddevent(handle
);
5294 * If a property n/v pair was specified, warn the user if there was
5295 * nothing to output.
5297 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5298 (void) printf(gettext("No such %s resource.\n"),
5299 rt_to_str(RT_DEVICE
));
5303 output_rctl(FILE *fp
, struct zone_rctltab
*rctltab
)
5305 struct zone_rctlvaltab
*valptr
;
5307 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_RCTL
));
5308 output_prop(fp
, PT_NAME
, rctltab
->zone_rctl_name
, B_TRUE
);
5309 for (valptr
= rctltab
->zone_rctl_valptr
; valptr
!= NULL
;
5310 valptr
= valptr
->zone_rctlval_next
) {
5311 fprintf(fp
, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
5312 pt_to_str(PT_VALUE
),
5313 pt_to_str(PT_PRIV
), valptr
->zone_rctlval_priv
,
5314 pt_to_str(PT_LIMIT
), valptr
->zone_rctlval_limit
,
5315 pt_to_str(PT_ACTION
), valptr
->zone_rctlval_action
);
5320 info_rctl(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5322 struct zone_rctltab lookup
, user
;
5323 boolean_t output
= B_FALSE
;
5325 if (zonecfg_setrctlent(handle
) != Z_OK
)
5327 while (zonecfg_getrctlent(handle
, &lookup
) == Z_OK
) {
5328 if (cmd
->cmd_prop_nv_pairs
== 0) {
5329 output_rctl(fp
, &lookup
);
5330 } else if (fill_in_rctltab(cmd
, &user
, B_TRUE
) == Z_OK
&&
5331 (strlen(user
.zone_rctl_name
) == 0 ||
5332 strcmp(user
.zone_rctl_name
, lookup
.zone_rctl_name
) == 0)) {
5333 output_rctl(fp
, &lookup
);
5336 zonecfg_free_rctl_value_list(lookup
.zone_rctl_valptr
);
5338 (void) zonecfg_endrctlent(handle
);
5340 * If a property n/v pair was specified, warn the user if there was
5341 * nothing to output.
5343 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5344 (void) printf(gettext("No such %s resource.\n"),
5345 rt_to_str(RT_RCTL
));
5349 output_attr(FILE *fp
, struct zone_attrtab
*attrtab
)
5351 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_ATTR
));
5352 output_prop(fp
, PT_NAME
, attrtab
->zone_attr_name
, B_TRUE
);
5353 output_prop(fp
, PT_TYPE
, attrtab
->zone_attr_type
, B_TRUE
);
5354 output_prop(fp
, PT_VALUE
, attrtab
->zone_attr_value
, B_TRUE
);
5358 info_attr(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5360 struct zone_attrtab lookup
, user
;
5361 boolean_t output
= B_FALSE
;
5363 if (zonecfg_setattrent(handle
) != Z_OK
)
5365 while (zonecfg_getattrent(handle
, &lookup
) == Z_OK
) {
5366 if (cmd
->cmd_prop_nv_pairs
== 0) {
5367 output_attr(fp
, &lookup
);
5370 if (fill_in_attrtab(cmd
, &user
, B_TRUE
) != Z_OK
)
5372 if (strlen(user
.zone_attr_name
) > 0 &&
5373 strcmp(user
.zone_attr_name
, lookup
.zone_attr_name
) != 0)
5374 continue; /* no match */
5375 if (strlen(user
.zone_attr_type
) > 0 &&
5376 strcmp(user
.zone_attr_type
, lookup
.zone_attr_type
) != 0)
5377 continue; /* no match */
5378 if (strlen(user
.zone_attr_value
) > 0 &&
5379 strcmp(user
.zone_attr_value
, lookup
.zone_attr_value
) != 0)
5380 continue; /* no match */
5381 output_attr(fp
, &lookup
);
5384 (void) zonecfg_endattrent(handle
);
5386 * If a property n/v pair was specified, warn the user if there was
5387 * nothing to output.
5389 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5390 (void) printf(gettext("No such %s resource.\n"),
5391 rt_to_str(RT_ATTR
));
5395 output_ds(FILE *fp
, struct zone_dstab
*dstab
)
5397 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DATASET
));
5398 output_prop(fp
, PT_NAME
, dstab
->zone_dataset_name
, B_TRUE
);
5402 info_ds(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5404 struct zone_dstab lookup
, user
;
5405 boolean_t output
= B_FALSE
;
5407 if (zonecfg_setdsent(handle
) != Z_OK
)
5409 while (zonecfg_getdsent(handle
, &lookup
) == Z_OK
) {
5410 if (cmd
->cmd_prop_nv_pairs
== 0) {
5411 output_ds(fp
, &lookup
);
5414 if (fill_in_dstab(cmd
, &user
, B_TRUE
) != Z_OK
)
5416 if (strlen(user
.zone_dataset_name
) > 0 &&
5417 strcmp(user
.zone_dataset_name
,
5418 lookup
.zone_dataset_name
) != 0)
5419 continue; /* no match */
5420 output_ds(fp
, &lookup
);
5423 (void) zonecfg_enddsent(handle
);
5425 * If a property n/v pair was specified, warn the user if there was
5426 * nothing to output.
5428 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5429 (void) printf(gettext("No such %s resource.\n"),
5430 rt_to_str(RT_DATASET
));
5434 output_pset(FILE *fp
, struct zone_psettab
*psettab
)
5436 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_DCPU
));
5437 if (strcmp(psettab
->zone_ncpu_min
, psettab
->zone_ncpu_max
) == 0)
5438 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(PT_NCPUS
),
5439 psettab
->zone_ncpu_max
);
5441 (void) fprintf(fp
, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS
),
5442 psettab
->zone_ncpu_min
, psettab
->zone_ncpu_max
);
5443 if (psettab
->zone_importance
[0] != '\0')
5444 (void) fprintf(fp
, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE
),
5445 psettab
->zone_importance
);
5449 info_pset(zone_dochandle_t handle
, FILE *fp
)
5451 struct zone_psettab lookup
;
5453 if (zonecfg_getpsetent(handle
, &lookup
) == Z_OK
)
5454 output_pset(fp
, &lookup
);
5458 output_pcap(FILE *fp
)
5462 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &cap
) == Z_OK
) {
5463 float scaled
= (float)cap
/ 100;
5464 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_PCAP
));
5465 (void) fprintf(fp
, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS
),
5478 info_aliased_rctl(zone_dochandle_t handle
, FILE *fp
, char *alias
)
5482 if (zonecfg_get_aliased_rctl(handle
, alias
, &limit
) == Z_OK
) {
5483 /* convert memory based properties */
5484 if (strcmp(alias
, ALIAS_MAXSHMMEM
) == 0) {
5487 (void) snprintf(buf
, sizeof (buf
), "%llu", limit
);
5488 bytes_to_units(buf
, buf
, sizeof (buf
));
5489 (void) fprintf(fp
, "[%s: %s]\n", alias
, buf
);
5493 (void) fprintf(fp
, "[%s: %llu]\n", alias
, limit
);
5498 bytes_to_units(char *str
, char *buf
, int bufsize
)
5500 unsigned long long num
;
5501 unsigned long long save
= 0;
5502 char *units
= "BKMGT";
5505 num
= strtoll(str
, NULL
, 10);
5508 (void) snprintf(buf
, bufsize
, "%llu", num
);
5512 while ((num
>= 1024) && (*up
!= 'T')) {
5513 up
++; /* next unit of measurement */
5515 num
= (num
+ 512) >> 10;
5518 /* check if we should output a fraction. snprintf will round for us */
5519 if (save
% 1024 != 0 && ((save
>> 10) < 10))
5520 (void) snprintf(buf
, bufsize
, "%2.1f%c", ((float)save
/ 1024),
5523 (void) snprintf(buf
, bufsize
, "%llu%c", num
, *up
);
5527 output_mcap(FILE *fp
, struct zone_mcaptab
*mcaptab
, int showswap
,
5528 uint64_t maxswap
, int showlocked
, uint64_t maxlocked
)
5532 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_MCAP
));
5533 if (mcaptab
->zone_physmem_cap
[0] != '\0') {
5534 bytes_to_units(mcaptab
->zone_physmem_cap
, buf
, sizeof (buf
));
5535 output_prop(fp
, PT_PHYSICAL
, buf
, B_TRUE
);
5538 if (showswap
== Z_OK
) {
5539 (void) snprintf(buf
, sizeof (buf
), "%llu", maxswap
);
5540 bytes_to_units(buf
, buf
, sizeof (buf
));
5541 output_prop(fp
, PT_SWAP
, buf
, B_TRUE
);
5544 if (showlocked
== Z_OK
) {
5545 (void) snprintf(buf
, sizeof (buf
), "%llu", maxlocked
);
5546 bytes_to_units(buf
, buf
, sizeof (buf
));
5547 output_prop(fp
, PT_LOCKED
, buf
, B_TRUE
);
5552 info_mcap(zone_dochandle_t handle
, FILE *fp
)
5554 int res1
, res2
, res3
;
5555 uint64_t swap_limit
;
5556 uint64_t locked_limit
;
5557 struct zone_mcaptab lookup
;
5559 bzero(&lookup
, sizeof (lookup
));
5560 res1
= zonecfg_getmcapent(handle
, &lookup
);
5561 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
, &swap_limit
);
5562 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
5565 if (res1
== Z_OK
|| res2
== Z_OK
|| res3
== Z_OK
)
5566 output_mcap(fp
, &lookup
, res2
, swap_limit
, res3
, locked_limit
);
5570 output_auth(FILE *fp
, struct zone_admintab
*admintab
)
5572 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_ADMIN
));
5573 output_prop(fp
, PT_USER
, admintab
->zone_admin_user
, B_TRUE
);
5574 output_prop(fp
, PT_AUTHS
, admintab
->zone_admin_auths
, B_TRUE
);
5578 output_secflags(FILE *fp
, struct zone_secflagstab
*sftab
)
5580 (void) fprintf(fp
, "%s:\n", rt_to_str(RT_SECFLAGS
));
5581 output_prop(fp
, PT_DEFAULT
, sftab
->zone_secflags_default
, B_TRUE
);
5582 output_prop(fp
, PT_LOWER
, sftab
->zone_secflags_lower
, B_TRUE
);
5583 output_prop(fp
, PT_UPPER
, sftab
->zone_secflags_upper
, B_TRUE
);
5587 info_auth(zone_dochandle_t handle
, FILE *fp
, cmd_t
*cmd
)
5589 struct zone_admintab lookup
, user
;
5590 boolean_t output
= B_FALSE
;
5593 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
5594 zone_perror(zone
, err
, B_TRUE
);
5597 while (zonecfg_getadminent(handle
, &lookup
) == Z_OK
) {
5598 if (cmd
->cmd_prop_nv_pairs
== 0) {
5599 output_auth(fp
, &lookup
);
5602 if (fill_in_admintab(cmd
, &user
, B_TRUE
) != Z_OK
)
5604 if (strlen(user
.zone_admin_user
) > 0 &&
5605 strcmp(user
.zone_admin_user
, lookup
.zone_admin_user
) != 0)
5606 continue; /* no match */
5607 output_auth(fp
, &lookup
);
5610 (void) zonecfg_endadminent(handle
);
5612 * If a property n/v pair was specified, warn the user if there was
5613 * nothing to output.
5615 if (!output
&& cmd
->cmd_prop_nv_pairs
> 0)
5616 (void) printf(gettext("No such %s resource.\n"),
5617 rt_to_str(RT_ADMIN
));
5621 info_secflags(zone_dochandle_t handle
, FILE *fp
)
5623 struct zone_secflagstab sftab
;
5625 if (zonecfg_lookup_secflags(handle
, &sftab
) == Z_OK
) {
5626 output_secflags(fp
, &sftab
);
5631 info_func(cmd_t
*cmd
)
5634 boolean_t need_to_close
= B_FALSE
;
5637 uint64_t swap_limit
;
5638 uint64_t locked_limit
;
5640 assert(cmd
!= NULL
);
5642 if (initialize(B_TRUE
) != Z_OK
)
5645 /* don't page error output */
5646 if (interactive_mode
) {
5647 if ((fp
= pager_open()) != NULL
)
5648 need_to_close
= B_TRUE
;
5655 if (!global_scope
) {
5656 switch (resource_scope
) {
5658 output_fs(fp
, &in_progress_fstab
);
5661 output_net(fp
, &in_progress_nwiftab
);
5664 output_dev(fp
, &in_progress_devtab
);
5667 output_rctl(fp
, &in_progress_rctltab
);
5670 output_attr(fp
, &in_progress_attrtab
);
5673 output_ds(fp
, &in_progress_dstab
);
5676 output_pset(fp
, &in_progress_psettab
);
5682 res1
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
,
5684 res2
= zonecfg_get_aliased_rctl(handle
,
5685 ALIAS_MAXLOCKEDMEM
, &locked_limit
);
5686 output_mcap(fp
, &in_progress_mcaptab
, res1
, swap_limit
,
5687 res2
, locked_limit
);
5690 output_auth(fp
, &in_progress_admintab
);
5693 output_secflags(fp
, &in_progress_secflagstab
);
5699 type
= cmd
->cmd_res_type
;
5701 if (gz_invalid_rt_property(type
)) {
5702 zerr(gettext("%s is not a valid property for the global zone."),
5707 if (gz_invalid_resource(type
)) {
5708 zerr(gettext("%s is not a valid resource for the global zone."),
5713 switch (cmd
->cmd_res_type
) {
5715 info_zonename(handle
, fp
);
5717 info_zonepath(handle
, fp
);
5718 info_brand(handle
, fp
);
5719 info_autoboot(handle
, fp
);
5720 info_bootargs(handle
, fp
);
5722 info_pool(handle
, fp
);
5724 info_limitpriv(handle
, fp
);
5725 info_sched(handle
, fp
);
5726 info_iptype(handle
, fp
);
5727 info_hostid(handle
, fp
);
5728 info_fs_allowed(handle
, fp
);
5730 info_aliased_rctl(handle
, fp
, ALIAS_MAXLWPS
);
5731 info_aliased_rctl(handle
, fp
, ALIAS_MAXPROCS
);
5732 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMMEM
);
5733 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMIDS
);
5734 info_aliased_rctl(handle
, fp
, ALIAS_MAXMSGIDS
);
5735 info_aliased_rctl(handle
, fp
, ALIAS_MAXSEMIDS
);
5736 info_aliased_rctl(handle
, fp
, ALIAS_SHARES
);
5738 info_fs(handle
, fp
, cmd
);
5739 info_net(handle
, fp
, cmd
);
5740 info_dev(handle
, fp
, cmd
);
5742 info_pset(handle
, fp
);
5744 info_mcap(handle
, fp
);
5746 info_attr(handle
, fp
, cmd
);
5747 info_ds(handle
, fp
, cmd
);
5748 info_auth(handle
, fp
, cmd
);
5750 info_rctl(handle
, fp
, cmd
);
5751 info_secflags(handle
, fp
);
5754 info_zonename(handle
, fp
);
5757 info_zonepath(handle
, fp
);
5760 info_brand(handle
, fp
);
5763 info_autoboot(handle
, fp
);
5766 info_pool(handle
, fp
);
5769 info_limitpriv(handle
, fp
);
5772 info_bootargs(handle
, fp
);
5775 info_sched(handle
, fp
);
5778 info_iptype(handle
, fp
);
5781 info_aliased_rctl(handle
, fp
, ALIAS_MAXLWPS
);
5784 info_aliased_rctl(handle
, fp
, ALIAS_MAXPROCS
);
5787 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMMEM
);
5790 info_aliased_rctl(handle
, fp
, ALIAS_MAXSHMIDS
);
5793 info_aliased_rctl(handle
, fp
, ALIAS_MAXMSGIDS
);
5796 info_aliased_rctl(handle
, fp
, ALIAS_MAXSEMIDS
);
5799 info_aliased_rctl(handle
, fp
, ALIAS_SHARES
);
5802 info_fs(handle
, fp
, cmd
);
5805 info_net(handle
, fp
, cmd
);
5808 info_dev(handle
, fp
, cmd
);
5811 info_rctl(handle
, fp
, cmd
);
5814 info_attr(handle
, fp
, cmd
);
5817 info_ds(handle
, fp
, cmd
);
5820 info_pset(handle
, fp
);
5826 info_mcap(handle
, fp
);
5829 info_hostid(handle
, fp
);
5832 info_auth(handle
, fp
, cmd
);
5835 info_fs_allowed(handle
, fp
);
5838 info_secflags(handle
, fp
);
5841 zone_perror(rt_to_str(cmd
->cmd_res_type
), Z_NO_RESOURCE_TYPE
,
5847 (void) pager_close(fp
);
5851 * Helper function for verify-- checks that a required string property
5855 check_reqd_prop(char *attr
, int rt
, int pt
, int *ret_val
)
5857 if (strlen(attr
) == 0) {
5858 zerr(gettext("%s: %s not specified"), rt_to_str(rt
),
5861 if (*ret_val
== Z_OK
)
5862 *ret_val
= Z_REQD_PROPERTY_MISSING
;
5867 do_subproc(char *cmdbuf
)
5869 char inbuf
[MAX_CMD_LEN
];
5873 file
= popen(cmdbuf
, "r");
5875 zerr(gettext("Could not launch: %s"), cmdbuf
);
5879 while (fgets(inbuf
, sizeof (inbuf
), file
) != NULL
)
5880 fprintf(stderr
, "%s", inbuf
);
5881 status
= pclose(file
);
5883 if (WIFSIGNALED(status
)) {
5884 zerr(gettext("%s unexpectedly terminated due to signal %d"),
5885 cmdbuf
, WTERMSIG(status
));
5888 assert(WIFEXITED(status
));
5889 return (WEXITSTATUS(status
));
5893 brand_verify(zone_dochandle_t handle
)
5896 char cmdbuf
[MAX_CMD_LEN
];
5898 char brand
[MAXNAMELEN
];
5901 if (zonecfg_get_brand(handle
, brand
, sizeof (brand
)) != Z_OK
) {
5902 zerr("%s: %s\n", zone
, gettext("could not get zone brand"));
5903 return (Z_INVALID_DOCUMENT
);
5905 if ((bh
= brand_open(brand
)) == NULL
) {
5906 zerr("%s: %s\n", zone
, gettext("unknown brand."));
5907 return (Z_INVALID_DOCUMENT
);
5911 * Fetch the verify command, if any, from the brand configuration
5912 * and build the command line to execute it.
5914 strcpy(cmdbuf
, EXEC_PREFIX
);
5915 err
= brand_get_verify_cfg(bh
, cmdbuf
+ EXEC_LEN
,
5916 sizeof (cmdbuf
) - (EXEC_LEN
+ (strlen(xml_file
) + 1)));
5919 zerr("%s: %s\n", zone
,
5920 gettext("could not get brand verification command"));
5921 return (Z_INVALID_DOCUMENT
);
5925 * If the brand doesn't provide a verification routine, we just
5928 if (strlen(cmdbuf
) == EXEC_LEN
)
5932 * Dump the current config information for this zone to a file.
5934 strcpy(xml_file
, "/tmp/zonecfg_verify.XXXXXX");
5935 if (mkstemp(xml_file
) == NULL
)
5936 return (Z_TEMP_FILE
);
5937 if ((err
= zonecfg_verify_save(handle
, xml_file
)) != Z_OK
) {
5938 (void) unlink(xml_file
);
5943 * Execute the verification command.
5945 if ((strlcat(cmdbuf
, " ", MAX_CMD_LEN
) >= MAX_CMD_LEN
) ||
5946 (strlcat(cmdbuf
, xml_file
, MAX_CMD_LEN
) >= MAX_CMD_LEN
)) {
5947 err
= Z_BRAND_ERROR
;
5949 err
= do_subproc(cmdbuf
);
5952 (void) unlink(xml_file
);
5953 return ((err
== Z_OK
) ? Z_OK
: Z_BRAND_ERROR
);
5957 * Track the network interfaces listed in zonecfg(1m) in a linked list
5958 * so that we can later check that defrouter is specified for an exclusive IP
5959 * zone if and only if at least one allowed-address has been specified.
5962 add_nwif(struct zone_nwiftab
*nwif
)
5966 for (tmp
= xif
; tmp
!= NULL
; tmp
= tmp
->xif_next
) {
5967 if (strcmp(tmp
->xif_name
, nwif
->zone_nwif_physical
) == 0) {
5968 if (strlen(nwif
->zone_nwif_allowed_address
) > 0)
5969 tmp
->xif_has_address
= B_TRUE
;
5970 if (strlen(nwif
->zone_nwif_defrouter
) > 0)
5971 tmp
->xif_has_defrouter
= B_TRUE
;
5976 tmp
= malloc(sizeof (*tmp
));
5978 zerr(gettext("memory allocation failed for %s"),
5979 nwif
->zone_nwif_physical
);
5982 strlcpy(tmp
->xif_name
, nwif
->zone_nwif_physical
,
5983 sizeof (tmp
->xif_name
));
5984 tmp
->xif_has_defrouter
= (strlen(nwif
->zone_nwif_defrouter
) > 0);
5985 tmp
->xif_has_address
= (strlen(nwif
->zone_nwif_allowed_address
) > 0);
5986 tmp
->xif_next
= xif
;
5992 verify_secflags(struct zone_secflagstab
*tab
)
5994 secflagdelta_t def
= {0};
5995 secflagdelta_t upper
= {0};
5996 secflagdelta_t lower
= {0};
5997 boolean_t def_set
= B_FALSE
;
5998 boolean_t upper_set
= B_FALSE
;
5999 boolean_t lower_set
= B_FALSE
;
6000 boolean_t ret
= B_TRUE
;
6002 if (strlen(tab
->zone_secflags_default
) > 0) {
6004 if (secflags_parse(NULL
, tab
->zone_secflags_default
,
6006 zerr(gettext("default security flags '%s' are invalid"),
6007 tab
->zone_secflags_default
);
6011 secflags_zero(&def
.psd_assign
);
6012 def
.psd_ass_active
= B_TRUE
;
6015 if (strlen(tab
->zone_secflags_upper
) > 0) {
6017 if (secflags_parse(NULL
, tab
->zone_secflags_upper
,
6019 zerr(gettext("upper security flags '%s' are invalid"),
6020 tab
->zone_secflags_upper
);
6024 secflags_fullset(&upper
.psd_assign
);
6025 upper
.psd_ass_active
= B_TRUE
;
6028 if (strlen(tab
->zone_secflags_lower
) > 0) {
6030 if (secflags_parse(NULL
, tab
->zone_secflags_lower
,
6032 zerr(gettext("lower security flags '%s' are invalid"),
6033 tab
->zone_secflags_lower
);
6037 secflags_zero(&lower
.psd_assign
);
6038 lower
.psd_ass_active
= B_TRUE
;
6041 if (def_set
&& !def
.psd_ass_active
) {
6042 zerr(gettext("only assignment of security flags is "
6043 "allowed (default: %s)"), tab
->zone_secflags_default
);
6046 if (lower_set
&& !lower
.psd_ass_active
) {
6047 zerr(gettext("only assignment of security flags is "
6048 "allowed (lower: %s)"), tab
->zone_secflags_lower
);
6051 if (upper_set
&& !upper
.psd_ass_active
) {
6052 zerr(gettext("only assignment of security flags is "
6053 "allowed (upper: %s)"), tab
->zone_secflags_upper
);
6056 if (def
.psd_assign
& ~upper
.psd_assign
) { /* In default but not upper */
6057 zerr(gettext("default secflags must be within the "
6061 if (lower
.psd_assign
& ~def
.psd_assign
) { /* In lower but not default */
6062 zerr(gettext("default secflags must be above the lower limit"));
6065 if (lower
.psd_assign
& ~upper
.psd_assign
) { /* In lower but not upper */
6066 zerr(gettext("lower secflags must be within the upper limit"));
6074 * See the DTD for which attributes are required for which resources.
6076 * This function can be called by commit_func(), which needs to save things,
6077 * in addition to the general call from parse_and_run(), which doesn't need
6078 * things saved. Since the parameters are standardized, we distinguish by
6079 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
6080 * that a save is needed.
6083 verify_func(cmd_t
*cmd
)
6085 struct zone_nwiftab nwiftab
;
6086 struct zone_fstab fstab
;
6087 struct zone_attrtab attrtab
;
6088 struct zone_rctltab rctltab
;
6089 struct zone_dstab dstab
;
6090 struct zone_psettab psettab
;
6091 struct zone_admintab admintab
;
6092 struct zone_secflagstab secflagstab
;
6093 char zonepath
[MAXPATHLEN
];
6094 char sched
[MAXNAMELEN
];
6095 char brand
[MAXNAMELEN
];
6096 char hostidp
[HW_HOSTID_LEN
];
6097 char fsallowedp
[ZONE_FS_ALLOWED_MAX
];
6099 char *privname
= NULL
;
6100 int err
, ret_val
= Z_OK
, arg
;
6102 boolean_t save
= B_FALSE
;
6103 boolean_t arg_err
= B_FALSE
;
6104 zone_iptype_t iptype
;
6105 boolean_t has_cpu_shares
= B_FALSE
;
6106 boolean_t has_cpu_cap
= B_FALSE
;
6110 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6113 longer_usage(CMD_VERIFY
);
6117 short_usage(CMD_VERIFY
);
6125 if (optind
> cmd
->cmd_argc
) {
6126 short_usage(CMD_VERIFY
);
6130 if (zone_is_read_only(CMD_VERIFY
))
6133 assert(cmd
!= NULL
);
6135 if (cmd
->cmd_argc
> 0 && (strcmp(cmd
->cmd_argv
[0], "save") == 0))
6137 if (initialize(B_TRUE
) != Z_OK
)
6140 if (zonecfg_get_zonepath(handle
, zonepath
, sizeof (zonepath
)) != Z_OK
&&
6142 zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH
));
6143 ret_val
= Z_REQD_RESOURCE_MISSING
;
6146 if (strlen(zonepath
) == 0 && !global_zone
) {
6147 zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH
));
6148 ret_val
= Z_REQD_RESOURCE_MISSING
;
6152 if ((err
= zonecfg_get_brand(handle
, brand
, sizeof (brand
))) != Z_OK
) {
6153 zone_perror(zone
, err
, B_TRUE
);
6156 if ((err
= brand_verify(handle
)) != Z_OK
) {
6157 zone_perror(zone
, err
, B_TRUE
);
6161 if (zonecfg_get_iptype(handle
, &iptype
) != Z_OK
) {
6162 zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE
));
6163 ret_val
= Z_REQD_RESOURCE_MISSING
;
6167 if ((privs
= priv_allocset()) == NULL
) {
6168 zerr(gettext("%s: priv_allocset failed"), zone
);
6171 if (zonecfg_get_privset(handle
, privs
, &privname
) != Z_OK
) {
6172 zerr(gettext("%s: invalid privilege: %s"), zone
, privname
);
6173 priv_freeset(privs
);
6177 priv_freeset(privs
);
6179 if (zonecfg_get_hostid(handle
, hostidp
,
6180 sizeof (hostidp
)) == Z_INVALID_PROPERTY
) {
6181 zerr(gettext("%s: invalid hostid: %s"),
6186 if (zonecfg_get_fs_allowed(handle
, fsallowedp
,
6187 sizeof (fsallowedp
)) == Z_INVALID_PROPERTY
) {
6188 zerr(gettext("%s: invalid fs-allowed: %s"),
6193 if ((err
= zonecfg_setfsent(handle
)) != Z_OK
) {
6194 zone_perror(zone
, err
, B_TRUE
);
6197 while (zonecfg_getfsent(handle
, &fstab
) == Z_OK
) {
6198 check_reqd_prop(fstab
.zone_fs_dir
, RT_FS
, PT_DIR
, &ret_val
);
6199 check_reqd_prop(fstab
.zone_fs_special
, RT_FS
, PT_SPECIAL
,
6201 check_reqd_prop(fstab
.zone_fs_type
, RT_FS
, PT_TYPE
, &ret_val
);
6203 zonecfg_free_fs_option_list(fstab
.zone_fs_options
);
6205 (void) zonecfg_endfsent(handle
);
6207 if ((err
= zonecfg_setnwifent(handle
)) != Z_OK
) {
6208 zone_perror(zone
, err
, B_TRUE
);
6211 while (zonecfg_getnwifent(handle
, &nwiftab
) == Z_OK
) {
6213 * physical is required in all cases.
6214 * A shared IP requires an address,
6215 * and may include a default router, while
6216 * an exclusive IP must have neither an address
6217 * nor a default router.
6218 * The physical interface name must be valid in all cases.
6220 check_reqd_prop(nwiftab
.zone_nwif_physical
, RT_NET
,
6221 PT_PHYSICAL
, &ret_val
);
6222 if (validate_net_physical_syntax(nwiftab
.zone_nwif_physical
) !=
6225 if (ret_val
== Z_OK
)
6231 check_reqd_prop(nwiftab
.zone_nwif_address
, RT_NET
,
6232 PT_ADDRESS
, &ret_val
);
6233 if (strlen(nwiftab
.zone_nwif_allowed_address
) > 0) {
6234 zerr(gettext("%s: %s cannot be specified "
6235 "for a shared IP type"),
6237 pt_to_str(PT_ALLOWED_ADDRESS
));
6239 if (ret_val
== Z_OK
)
6244 if (strlen(nwiftab
.zone_nwif_address
) > 0) {
6245 zerr(gettext("%s: %s cannot be specified "
6246 "for an exclusive IP type"),
6247 rt_to_str(RT_NET
), pt_to_str(PT_ADDRESS
));
6249 if (ret_val
== Z_OK
)
6252 if (!add_nwif(&nwiftab
)) {
6254 if (ret_val
== Z_OK
)
6261 for (tmp
= xif
; tmp
!= NULL
; tmp
= tmp
->xif_next
) {
6262 if (!tmp
->xif_has_address
&& tmp
->xif_has_defrouter
) {
6263 zerr(gettext("%s: %s for %s cannot be specified "
6264 "without %s for an exclusive IP type"),
6265 rt_to_str(RT_NET
), pt_to_str(PT_DEFROUTER
),
6266 tmp
->xif_name
, pt_to_str(PT_ALLOWED_ADDRESS
));
6273 (void) zonecfg_endnwifent(handle
);
6275 if ((err
= zonecfg_setrctlent(handle
)) != Z_OK
) {
6276 zone_perror(zone
, err
, B_TRUE
);
6279 while (zonecfg_getrctlent(handle
, &rctltab
) == Z_OK
) {
6280 check_reqd_prop(rctltab
.zone_rctl_name
, RT_RCTL
, PT_NAME
,
6283 if (strcmp(rctltab
.zone_rctl_name
, "zone.cpu-shares") == 0)
6284 has_cpu_shares
= B_TRUE
;
6286 if (strcmp(rctltab
.zone_rctl_name
, "zone.cpu-cap") == 0)
6287 has_cpu_cap
= B_TRUE
;
6289 if (rctltab
.zone_rctl_valptr
== NULL
) {
6290 zerr(gettext("%s: no %s specified"),
6291 rt_to_str(RT_RCTL
), pt_to_str(PT_VALUE
));
6293 if (ret_val
== Z_OK
)
6294 ret_val
= Z_REQD_PROPERTY_MISSING
;
6296 zonecfg_free_rctl_value_list(rctltab
.zone_rctl_valptr
);
6299 (void) zonecfg_endrctlent(handle
);
6301 if ((pset_res
= zonecfg_lookup_pset(handle
, &psettab
)) == Z_OK
&&
6303 zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
6304 rt_to_str(RT_RCTL
), rt_to_str(RT_DCPU
));
6306 if (ret_val
== Z_OK
)
6307 ret_val
= Z_INCOMPATIBLE
;
6310 if (has_cpu_shares
&& zonecfg_get_sched_class(handle
, sched
,
6311 sizeof (sched
)) == Z_OK
&& strlen(sched
) > 0 &&
6312 strcmp(sched
, "FSS") != 0) {
6313 zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
6315 rt_to_str(RT_RCTL
), rt_to_str(RT_SCHED
), sched
);
6317 if (ret_val
== Z_OK
)
6318 ret_val
= Z_INCOMPATIBLE
;
6321 if (pset_res
== Z_OK
&& has_cpu_cap
) {
6322 zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
6323 rt_to_str(RT_RCTL
), rt_to_str(RT_DCPU
));
6325 if (ret_val
== Z_OK
)
6326 ret_val
= Z_INCOMPATIBLE
;
6329 if ((err
= zonecfg_setattrent(handle
)) != Z_OK
) {
6330 zone_perror(zone
, err
, B_TRUE
);
6333 while (zonecfg_getattrent(handle
, &attrtab
) == Z_OK
) {
6334 check_reqd_prop(attrtab
.zone_attr_name
, RT_ATTR
, PT_NAME
,
6336 check_reqd_prop(attrtab
.zone_attr_type
, RT_ATTR
, PT_TYPE
,
6338 check_reqd_prop(attrtab
.zone_attr_value
, RT_ATTR
, PT_VALUE
,
6341 (void) zonecfg_endattrent(handle
);
6343 if ((err
= zonecfg_setdsent(handle
)) != Z_OK
) {
6344 zone_perror(zone
, err
, B_TRUE
);
6347 while (zonecfg_getdsent(handle
, &dstab
) == Z_OK
) {
6348 if (strlen(dstab
.zone_dataset_name
) == 0) {
6349 zerr("%s: %s %s", rt_to_str(RT_DATASET
),
6350 pt_to_str(PT_NAME
), gettext("not specified"));
6352 if (ret_val
== Z_OK
)
6353 ret_val
= Z_REQD_PROPERTY_MISSING
;
6354 } else if (!zfs_name_valid(dstab
.zone_dataset_name
,
6355 ZFS_TYPE_FILESYSTEM
)) {
6356 zerr("%s: %s %s", rt_to_str(RT_DATASET
),
6357 pt_to_str(PT_NAME
), gettext("invalid"));
6359 if (ret_val
== Z_OK
)
6360 ret_val
= Z_BAD_PROPERTY
;
6364 (void) zonecfg_enddsent(handle
);
6366 if ((err
= zonecfg_setadminent(handle
)) != Z_OK
) {
6367 zone_perror(zone
, err
, B_TRUE
);
6370 while (zonecfg_getadminent(handle
, &admintab
) == Z_OK
) {
6371 check_reqd_prop(admintab
.zone_admin_user
, RT_ADMIN
,
6373 check_reqd_prop(admintab
.zone_admin_auths
, RT_ADMIN
,
6374 PT_AUTHS
, &ret_val
);
6375 if ((ret_val
== Z_OK
) && (getpwnam(admintab
.zone_admin_user
)
6377 zerr(gettext("%s %s is not a valid username"),
6379 admintab
.zone_admin_user
);
6380 ret_val
= Z_BAD_PROPERTY
;
6382 if ((ret_val
== Z_OK
) && (!zonecfg_valid_auths(
6383 admintab
.zone_admin_auths
, zone
))) {
6384 ret_val
= Z_BAD_PROPERTY
;
6387 (void) zonecfg_endadminent(handle
);
6389 if (zonecfg_getsecflagsent(handle
, &secflagstab
) == Z_OK
) {
6391 * No properties are required, but any specified should be
6394 if (verify_secflags(&secflagstab
) != B_TRUE
) {
6395 /* Error is reported from verify_secflags */
6396 ret_val
= Z_BAD_PROPERTY
;
6400 if (!global_scope
) {
6401 zerr(gettext("resource specification incomplete"));
6403 if (ret_val
== Z_OK
)
6404 ret_val
= Z_INSUFFICIENT_SPEC
;
6408 if (ret_val
== Z_OK
) {
6409 if ((ret_val
= zonecfg_save(handle
)) == Z_OK
) {
6410 need_to_commit
= B_FALSE
;
6411 (void) strlcpy(revert_zone
, zone
,
6412 sizeof (revert_zone
));
6415 zerr(gettext("Zone %s failed to verify"), zone
);
6418 if (ret_val
!= Z_OK
)
6419 zone_perror(zone
, ret_val
, B_TRUE
);
6423 cancel_func(cmd_t
*cmd
)
6426 boolean_t arg_err
= B_FALSE
;
6428 assert(cmd
!= NULL
);
6431 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6434 longer_usage(CMD_CANCEL
);
6438 short_usage(CMD_CANCEL
);
6446 if (optind
!= cmd
->cmd_argc
) {
6447 short_usage(CMD_CANCEL
);
6452 scope_usage(CMD_CANCEL
);
6453 global_scope
= B_TRUE
;
6454 zonecfg_free_fs_option_list(in_progress_fstab
.zone_fs_options
);
6455 bzero(&in_progress_fstab
, sizeof (in_progress_fstab
));
6456 bzero(&in_progress_nwiftab
, sizeof (in_progress_nwiftab
));
6457 bzero(&in_progress_devtab
, sizeof (in_progress_devtab
));
6458 zonecfg_free_rctl_value_list(in_progress_rctltab
.zone_rctl_valptr
);
6459 bzero(&in_progress_rctltab
, sizeof (in_progress_rctltab
));
6460 bzero(&in_progress_attrtab
, sizeof (in_progress_attrtab
));
6461 bzero(&in_progress_dstab
, sizeof (in_progress_dstab
));
6465 validate_attr_name(char *name
)
6469 if (!isalnum(name
[0])) {
6470 zerr(gettext("Invalid %s %s %s: must start with an alpha-"
6471 "numeric character."), rt_to_str(RT_ATTR
),
6472 pt_to_str(PT_NAME
), name
);
6475 for (i
= 1; name
[i
]; i
++)
6476 if (!isalnum(name
[i
]) && name
[i
] != '-' && name
[i
] != '.') {
6477 zerr(gettext("Invalid %s %s %s: can only contain "
6478 "alpha-numeric characters, plus '-' and '.'."),
6479 rt_to_str(RT_ATTR
), pt_to_str(PT_NAME
), name
);
6486 validate_attr_type_val(struct zone_attrtab
*attrtab
)
6490 char strval
[MAXNAMELEN
];
6493 if (strcmp(attrtab
->zone_attr_type
, "boolean") == 0) {
6494 if (zonecfg_get_attr_boolean(attrtab
, &boolval
) == Z_OK
)
6496 zerr(gettext("invalid %s value for %s=%s"),
6497 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "boolean");
6501 if (strcmp(attrtab
->zone_attr_type
, "int") == 0) {
6502 if (zonecfg_get_attr_int(attrtab
, &intval
) == Z_OK
)
6504 zerr(gettext("invalid %s value for %s=%s"),
6505 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "int");
6509 if (strcmp(attrtab
->zone_attr_type
, "string") == 0) {
6510 if (zonecfg_get_attr_string(attrtab
, strval
,
6511 sizeof (strval
)) == Z_OK
)
6513 zerr(gettext("invalid %s value for %s=%s"),
6514 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "string");
6518 if (strcmp(attrtab
->zone_attr_type
, "uint") == 0) {
6519 if (zonecfg_get_attr_uint(attrtab
, &uintval
) == Z_OK
)
6521 zerr(gettext("invalid %s value for %s=%s"),
6522 rt_to_str(RT_ATTR
), pt_to_str(PT_TYPE
), "uint");
6526 zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR
),
6527 pt_to_str(PT_TYPE
), attrtab
->zone_attr_type
);
6532 * Helper function for end_func-- checks the existence of a given property
6533 * and emits a message if not specified.
6536 end_check_reqd(char *attr
, int pt
, boolean_t
*validation_failed
)
6538 if (strlen(attr
) == 0) {
6539 *validation_failed
= B_TRUE
;
6540 zerr(gettext("%s not specified"), pt_to_str(pt
));
6547 net_exists_error(struct zone_nwiftab nwif
)
6549 if (strlen(nwif
.zone_nwif_address
) > 0) {
6550 zerr(gettext("A %s resource with the %s '%s', "
6551 "and %s '%s' already exists."),
6553 pt_to_str(PT_PHYSICAL
),
6554 nwif
.zone_nwif_physical
,
6555 pt_to_str(PT_ADDRESS
),
6556 in_progress_nwiftab
.zone_nwif_address
);
6558 zerr(gettext("A %s resource with the %s '%s', "
6559 "and %s '%s' already exists."),
6561 pt_to_str(PT_PHYSICAL
),
6562 nwif
.zone_nwif_physical
,
6563 pt_to_str(PT_ALLOWED_ADDRESS
),
6564 nwif
.zone_nwif_allowed_address
);
6569 end_func(cmd_t
*cmd
)
6571 boolean_t validation_failed
= B_FALSE
;
6572 boolean_t arg_err
= B_FALSE
;
6573 struct zone_fstab tmp_fstab
;
6574 struct zone_nwiftab tmp_nwiftab
;
6575 struct zone_devtab tmp_devtab
;
6576 struct zone_rctltab tmp_rctltab
;
6577 struct zone_attrtab tmp_attrtab
;
6578 struct zone_dstab tmp_dstab
;
6579 struct zone_admintab tmp_admintab
;
6580 int err
, arg
, res1
, res2
, res3
;
6581 uint64_t swap_limit
;
6582 uint64_t locked_limit
;
6585 assert(cmd
!= NULL
);
6588 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
6591 longer_usage(CMD_END
);
6595 short_usage(CMD_END
);
6603 if (optind
!= cmd
->cmd_argc
) {
6604 short_usage(CMD_END
);
6609 scope_usage(CMD_END
);
6613 assert(end_op
== CMD_ADD
|| end_op
== CMD_SELECT
);
6615 switch (resource_scope
) {
6617 /* First make sure everything was filled in. */
6618 if (end_check_reqd(in_progress_fstab
.zone_fs_dir
,
6619 PT_DIR
, &validation_failed
) == Z_OK
) {
6620 if (in_progress_fstab
.zone_fs_dir
[0] != '/') {
6621 zerr(gettext("%s %s is not an absolute path."),
6623 in_progress_fstab
.zone_fs_dir
);
6624 validation_failed
= B_TRUE
;
6628 (void) end_check_reqd(in_progress_fstab
.zone_fs_special
,
6629 PT_SPECIAL
, &validation_failed
);
6631 if (in_progress_fstab
.zone_fs_raw
[0] != '\0' &&
6632 in_progress_fstab
.zone_fs_raw
[0] != '/') {
6633 zerr(gettext("%s %s is not an absolute path."),
6635 in_progress_fstab
.zone_fs_raw
);
6636 validation_failed
= B_TRUE
;
6639 (void) end_check_reqd(in_progress_fstab
.zone_fs_type
, PT_TYPE
,
6640 &validation_failed
);
6642 if (validation_failed
) {
6647 if (end_op
== CMD_ADD
) {
6648 /* Make sure there isn't already one like this. */
6649 bzero(&tmp_fstab
, sizeof (tmp_fstab
));
6650 (void) strlcpy(tmp_fstab
.zone_fs_dir
,
6651 in_progress_fstab
.zone_fs_dir
,
6652 sizeof (tmp_fstab
.zone_fs_dir
));
6653 err
= zonecfg_lookup_filesystem(handle
, &tmp_fstab
);
6654 zonecfg_free_fs_option_list(tmp_fstab
.zone_fs_options
);
6656 zerr(gettext("A %s resource "
6657 "with the %s '%s' already exists."),
6658 rt_to_str(RT_FS
), pt_to_str(PT_DIR
),
6659 in_progress_fstab
.zone_fs_dir
);
6663 err
= zonecfg_add_filesystem(handle
,
6664 &in_progress_fstab
);
6666 err
= zonecfg_modify_filesystem(handle
, &old_fstab
,
6667 &in_progress_fstab
);
6669 zonecfg_free_fs_option_list(in_progress_fstab
.zone_fs_options
);
6670 in_progress_fstab
.zone_fs_options
= NULL
;
6675 * First make sure everything was filled in.
6676 * Since we don't know whether IP will be shared
6677 * or exclusive here, some checks are deferred until
6678 * the verify command.
6680 (void) end_check_reqd(in_progress_nwiftab
.zone_nwif_physical
,
6681 PT_PHYSICAL
, &validation_failed
);
6683 if (validation_failed
) {
6687 if (end_op
== CMD_ADD
) {
6688 /* Make sure there isn't already one like this. */
6689 bzero(&tmp_nwiftab
, sizeof (tmp_nwiftab
));
6690 (void) strlcpy(tmp_nwiftab
.zone_nwif_physical
,
6691 in_progress_nwiftab
.zone_nwif_physical
,
6692 sizeof (tmp_nwiftab
.zone_nwif_physical
));
6693 (void) strlcpy(tmp_nwiftab
.zone_nwif_address
,
6694 in_progress_nwiftab
.zone_nwif_address
,
6695 sizeof (tmp_nwiftab
.zone_nwif_address
));
6696 (void) strlcpy(tmp_nwiftab
.zone_nwif_allowed_address
,
6697 in_progress_nwiftab
.zone_nwif_allowed_address
,
6698 sizeof (tmp_nwiftab
.zone_nwif_allowed_address
));
6699 (void) strlcpy(tmp_nwiftab
.zone_nwif_defrouter
,
6700 in_progress_nwiftab
.zone_nwif_defrouter
,
6701 sizeof (tmp_nwiftab
.zone_nwif_defrouter
));
6702 if (zonecfg_lookup_nwif(handle
, &tmp_nwiftab
) == Z_OK
) {
6703 net_exists_error(in_progress_nwiftab
);
6707 err
= zonecfg_add_nwif(handle
, &in_progress_nwiftab
);
6709 err
= zonecfg_modify_nwif(handle
, &old_nwiftab
,
6710 &in_progress_nwiftab
);
6715 /* First make sure everything was filled in. */
6716 (void) end_check_reqd(in_progress_devtab
.zone_dev_match
,
6717 PT_MATCH
, &validation_failed
);
6719 if (validation_failed
) {
6724 if (end_op
== CMD_ADD
) {
6725 /* Make sure there isn't already one like this. */
6726 (void) strlcpy(tmp_devtab
.zone_dev_match
,
6727 in_progress_devtab
.zone_dev_match
,
6728 sizeof (tmp_devtab
.zone_dev_match
));
6729 if (zonecfg_lookup_dev(handle
, &tmp_devtab
) == Z_OK
) {
6730 zerr(gettext("A %s resource with the %s '%s' "
6731 "already exists."), rt_to_str(RT_DEVICE
),
6732 pt_to_str(PT_MATCH
),
6733 in_progress_devtab
.zone_dev_match
);
6737 err
= zonecfg_add_dev(handle
, &in_progress_devtab
);
6739 err
= zonecfg_modify_dev(handle
, &old_devtab
,
6740 &in_progress_devtab
);
6745 /* First make sure everything was filled in. */
6746 (void) end_check_reqd(in_progress_rctltab
.zone_rctl_name
,
6747 PT_NAME
, &validation_failed
);
6749 if (in_progress_rctltab
.zone_rctl_valptr
== NULL
) {
6750 zerr(gettext("no %s specified"), pt_to_str(PT_VALUE
));
6751 validation_failed
= B_TRUE
;
6754 if (validation_failed
) {
6759 if (end_op
== CMD_ADD
) {
6760 /* Make sure there isn't already one like this. */
6761 (void) strlcpy(tmp_rctltab
.zone_rctl_name
,
6762 in_progress_rctltab
.zone_rctl_name
,
6763 sizeof (tmp_rctltab
.zone_rctl_name
));
6764 tmp_rctltab
.zone_rctl_valptr
= NULL
;
6765 err
= zonecfg_lookup_rctl(handle
, &tmp_rctltab
);
6766 zonecfg_free_rctl_value_list(
6767 tmp_rctltab
.zone_rctl_valptr
);
6769 zerr(gettext("A %s resource "
6770 "with the %s '%s' already exists."),
6771 rt_to_str(RT_RCTL
), pt_to_str(PT_NAME
),
6772 in_progress_rctltab
.zone_rctl_name
);
6776 err
= zonecfg_add_rctl(handle
, &in_progress_rctltab
);
6778 err
= zonecfg_modify_rctl(handle
, &old_rctltab
,
6779 &in_progress_rctltab
);
6782 zonecfg_free_rctl_value_list(
6783 in_progress_rctltab
.zone_rctl_valptr
);
6784 in_progress_rctltab
.zone_rctl_valptr
= NULL
;
6789 /* First make sure everything was filled in. */
6790 (void) end_check_reqd(in_progress_attrtab
.zone_attr_name
,
6791 PT_NAME
, &validation_failed
);
6792 (void) end_check_reqd(in_progress_attrtab
.zone_attr_type
,
6793 PT_TYPE
, &validation_failed
);
6794 (void) end_check_reqd(in_progress_attrtab
.zone_attr_value
,
6795 PT_VALUE
, &validation_failed
);
6797 if (validate_attr_name(in_progress_attrtab
.zone_attr_name
) !=
6799 validation_failed
= B_TRUE
;
6801 if (validate_attr_type_val(&in_progress_attrtab
) != Z_OK
)
6802 validation_failed
= B_TRUE
;
6804 if (validation_failed
) {
6808 if (end_op
== CMD_ADD
) {
6809 /* Make sure there isn't already one like this. */
6810 bzero(&tmp_attrtab
, sizeof (tmp_attrtab
));
6811 (void) strlcpy(tmp_attrtab
.zone_attr_name
,
6812 in_progress_attrtab
.zone_attr_name
,
6813 sizeof (tmp_attrtab
.zone_attr_name
));
6814 if (zonecfg_lookup_attr(handle
, &tmp_attrtab
) == Z_OK
) {
6815 zerr(gettext("An %s resource "
6816 "with the %s '%s' already exists."),
6817 rt_to_str(RT_ATTR
), pt_to_str(PT_NAME
),
6818 in_progress_attrtab
.zone_attr_name
);
6822 err
= zonecfg_add_attr(handle
, &in_progress_attrtab
);
6824 err
= zonecfg_modify_attr(handle
, &old_attrtab
,
6825 &in_progress_attrtab
);
6829 /* First make sure everything was filled in. */
6830 if (strlen(in_progress_dstab
.zone_dataset_name
) == 0) {
6831 zerr("%s %s", pt_to_str(PT_NAME
),
6832 gettext("not specified"));
6834 validation_failed
= B_TRUE
;
6836 if (validation_failed
)
6838 if (end_op
== CMD_ADD
) {
6839 /* Make sure there isn't already one like this. */
6840 bzero(&tmp_dstab
, sizeof (tmp_dstab
));
6841 (void) strlcpy(tmp_dstab
.zone_dataset_name
,
6842 in_progress_dstab
.zone_dataset_name
,
6843 sizeof (tmp_dstab
.zone_dataset_name
));
6844 err
= zonecfg_lookup_ds(handle
, &tmp_dstab
);
6846 zerr(gettext("A %s resource "
6847 "with the %s '%s' already exists."),
6848 rt_to_str(RT_DATASET
), pt_to_str(PT_NAME
),
6849 in_progress_dstab
.zone_dataset_name
);
6853 err
= zonecfg_add_ds(handle
, &in_progress_dstab
);
6855 err
= zonecfg_modify_ds(handle
, &old_dstab
,
6856 &in_progress_dstab
);
6860 /* Make sure everything was filled in. */
6861 if (end_check_reqd(in_progress_psettab
.zone_ncpu_min
,
6862 PT_NCPUS
, &validation_failed
) != Z_OK
) {
6867 if (end_op
== CMD_ADD
) {
6868 err
= zonecfg_add_pset(handle
, &in_progress_psettab
);
6870 err
= zonecfg_modify_pset(handle
, &in_progress_psettab
);
6874 /* Make sure everything was filled in. */
6875 if (zonecfg_get_aliased_rctl(handle
, ALIAS_CPUCAP
, &proc_cap
)
6877 zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS
));
6879 validation_failed
= B_TRUE
;
6885 /* Make sure everything was filled in. */
6886 res1
= strlen(in_progress_mcaptab
.zone_physmem_cap
) == 0 ?
6888 res2
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXSWAP
,
6890 res3
= zonecfg_get_aliased_rctl(handle
, ALIAS_MAXLOCKEDMEM
,
6893 if (res1
!= Z_OK
&& res2
!= Z_OK
&& res3
!= Z_OK
) {
6894 zerr(gettext("No property was specified. One of %s, "
6895 "%s or %s is required."), pt_to_str(PT_PHYSICAL
),
6896 pt_to_str(PT_SWAP
), pt_to_str(PT_LOCKED
));
6901 /* if phys & locked are both set, verify locked <= phys */
6902 if (res1
== Z_OK
&& res3
== Z_OK
) {
6903 uint64_t phys_limit
;
6906 phys_limit
= strtoull(
6907 in_progress_mcaptab
.zone_physmem_cap
, &endp
, 10);
6908 if (phys_limit
< locked_limit
) {
6909 zerr(gettext("The %s cap must be less than or "
6910 "equal to the %s cap."),
6911 pt_to_str(PT_LOCKED
),
6912 pt_to_str(PT_PHYSICAL
));
6921 * We could be ending from either an add operation
6922 * or a select operation. Since all of the properties
6923 * within this resource are optional, we always use
6924 * modify on the mcap entry. zonecfg_modify_mcap()
6925 * will handle both adding and modifying a memory cap.
6927 err
= zonecfg_modify_mcap(handle
, &in_progress_mcaptab
);
6928 } else if (end_op
== CMD_SELECT
) {
6930 * If we're ending from a select and the physical
6931 * memory cap is empty then the user could have cleared
6932 * the physical cap value, so try to delete the entry.
6934 (void) zonecfg_delete_mcap(handle
);
6938 /* First make sure everything was filled in. */
6939 if (end_check_reqd(in_progress_admintab
.zone_admin_user
,
6940 PT_USER
, &validation_failed
) == Z_OK
) {
6941 if (getpwnam(in_progress_admintab
.zone_admin_user
)
6943 zerr(gettext("%s %s is not a valid username"),
6945 in_progress_admintab
.zone_admin_user
);
6946 validation_failed
= B_TRUE
;
6950 if (end_check_reqd(in_progress_admintab
.zone_admin_auths
,
6951 PT_AUTHS
, &validation_failed
) == Z_OK
) {
6952 if (!zonecfg_valid_auths(
6953 in_progress_admintab
.zone_admin_auths
,
6955 validation_failed
= B_TRUE
;
6959 if (validation_failed
) {
6964 if (end_op
== CMD_ADD
) {
6965 /* Make sure there isn't already one like this. */
6966 bzero(&tmp_admintab
, sizeof (tmp_admintab
));
6967 (void) strlcpy(tmp_admintab
.zone_admin_user
,
6968 in_progress_admintab
.zone_admin_user
,
6969 sizeof (tmp_admintab
.zone_admin_user
));
6970 err
= zonecfg_lookup_admin(
6971 handle
, &tmp_admintab
);
6973 zerr(gettext("A %s resource "
6974 "with the %s '%s' already exists."),
6975 rt_to_str(RT_ADMIN
),
6977 in_progress_admintab
.zone_admin_user
);
6981 err
= zonecfg_add_admin(handle
,
6982 &in_progress_admintab
, zone
);
6984 err
= zonecfg_modify_admin(handle
,
6985 &old_admintab
, &in_progress_admintab
,
6990 if (verify_secflags(&in_progress_secflagstab
) != B_TRUE
) {
6995 if (end_op
== CMD_ADD
) {
6996 err
= zonecfg_add_secflags(handle
,
6997 &in_progress_secflagstab
);
6999 err
= zonecfg_modify_secflags(handle
,
7000 &old_secflagstab
, &in_progress_secflagstab
);
7004 zone_perror(rt_to_str(resource_scope
), Z_NO_RESOURCE_TYPE
,
7011 zone_perror(zone
, err
, B_TRUE
);
7013 need_to_commit
= B_TRUE
;
7014 global_scope
= B_TRUE
;
7020 commit_func(cmd_t
*cmd
)
7023 boolean_t arg_err
= B_FALSE
;
7026 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?")) != EOF
) {
7029 longer_usage(CMD_COMMIT
);
7033 short_usage(CMD_COMMIT
);
7041 if (optind
!= cmd
->cmd_argc
) {
7042 short_usage(CMD_COMMIT
);
7046 if (zone_is_read_only(CMD_COMMIT
))
7049 assert(cmd
!= NULL
);
7053 * cmd_arg normally comes from a strdup() in the lexer, and the
7054 * whole cmd structure and its (char *) attributes are freed at
7055 * the completion of each command, so the strdup() below is needed
7056 * to match this and prevent a core dump from trying to free()
7057 * something that can't be.
7059 if ((cmd
->cmd_argv
[0] = strdup("save")) == NULL
) {
7060 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
7063 cmd
->cmd_argv
[1] = NULL
;
7068 revert_func(cmd_t
*cmd
)
7070 char line
[128]; /* enough to ask a question */
7071 boolean_t force
= B_FALSE
;
7072 boolean_t arg_err
= B_FALSE
;
7073 int err
, arg
, answer
;
7076 while ((arg
= getopt(cmd
->cmd_argc
, cmd
->cmd_argv
, "?F")) != EOF
) {
7079 longer_usage(CMD_REVERT
);
7086 short_usage(CMD_REVERT
);
7094 if (optind
!= cmd
->cmd_argc
) {
7095 short_usage(CMD_REVERT
);
7099 if (zone_is_read_only(CMD_REVERT
))
7102 if (!global_scope
) {
7103 zerr(gettext("You can only use %s in the global scope.\nUse"
7104 " '%s' to cancel changes to a resource specification."),
7105 cmd_to_str(CMD_REVERT
), cmd_to_str(CMD_CANCEL
));
7110 if (zonecfg_check_handle(handle
) != Z_OK
) {
7111 zerr(gettext("No changes to revert."));
7117 (void) snprintf(line
, sizeof (line
),
7118 gettext("Are you sure you want to revert"));
7119 if ((answer
= ask_yesno(B_FALSE
, line
)) == -1) {
7120 zerr(gettext("Input not from terminal and -F not "
7121 "specified:\n%s command ignored, exiting."),
7122 cmd_to_str(CMD_REVERT
));
7130 * Reset any pending admins that were
7131 * removed from the previous zone
7133 zonecfg_remove_userauths(handle
, "", zone
, B_FALSE
);
7136 * Time for a new handle: finish the old one off first
7137 * then get a new one properly to avoid leaks.
7139 zonecfg_fini_handle(handle
);
7140 if ((handle
= zonecfg_init_handle()) == NULL
) {
7141 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7145 if ((err
= zonecfg_get_handle(revert_zone
, handle
)) != Z_OK
) {
7147 got_handle
= B_FALSE
;
7148 if (err
== Z_NO_ZONE
)
7149 zerr(gettext("%s: no such saved zone to revert to."),
7152 zone_perror(zone
, err
, B_TRUE
);
7154 (void) strlcpy(zone
, revert_zone
, sizeof (zone
));
7158 help_func(cmd_t
*cmd
)
7162 assert(cmd
!= NULL
);
7164 if (cmd
->cmd_argc
== 0) {
7165 usage(B_TRUE
, global_scope
? HELP_SUBCMDS
: HELP_RES_SCOPE
);
7168 if (strcmp(cmd
->cmd_argv
[0], "usage") == 0) {
7169 usage(B_TRUE
, HELP_USAGE
);
7172 if (strcmp(cmd
->cmd_argv
[0], "commands") == 0) {
7173 usage(B_TRUE
, HELP_SUBCMDS
);
7176 if (strcmp(cmd
->cmd_argv
[0], "syntax") == 0) {
7177 usage(B_TRUE
, HELP_SYNTAX
| HELP_RES_PROPS
);
7180 if (strcmp(cmd
->cmd_argv
[0], "-?") == 0) {
7181 longer_usage(CMD_HELP
);
7185 for (i
= 0; i
<= CMD_MAX
; i
++) {
7186 if (strcmp(cmd
->cmd_argv
[0], cmd_to_str(i
)) == 0) {
7191 /* We do not use zerr() here because we do not want its extra \n. */
7192 (void) fprintf(stderr
, gettext("Unknown help subject %s. "),
7194 usage(B_FALSE
, HELP_META
);
7198 string_to_yyin(char *string
)
7200 if ((yyin
= tmpfile()) == NULL
) {
7201 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7204 if (fwrite(string
, strlen(string
), 1, yyin
) != 1) {
7205 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7208 if (fseek(yyin
, 0, SEEK_SET
) != 0) {
7209 zone_perror(execname
, Z_TEMP_FILE
, B_TRUE
);
7215 /* This is the back-end helper function for read_input() below. */
7223 if (!interactive_mode
&& !cmd_file_mode
) {
7225 * If we're not in interactive mode, and we're not in command
7226 * file mode, then we must be in commands-from-the-command-line
7227 * mode. As such, we can't loop back and ask for more input.
7228 * It was OK to prompt for such things as whether or not to
7229 * really delete a zone in the command handler called from
7230 * yyparse() above, but "really quit?" makes no sense in this
7231 * context. So disable prompting.
7233 ok_to_prompt
= B_FALSE
;
7235 if (!global_scope
) {
7236 if (!time_to_exit
) {
7238 * Just print a simple error message in the -1 case,
7239 * since exit_func() already handles that case, and
7240 * EOF means we are finished anyway.
7242 answer
= ask_yesno(B_FALSE
,
7243 gettext("Resource incomplete; really quit"));
7245 zerr(gettext("Resource incomplete."));
7257 * Make sure we tried something and that the handle checks
7258 * out, or we would get a false error trying to commit.
7260 if (need_to_commit
&& zonecfg_check_handle(handle
) == Z_OK
) {
7261 if ((cmd
= alloc_cmd()) == NULL
) {
7262 zone_perror(zone
, Z_NOMEM
, B_TRUE
);
7266 cmd
->cmd_argv
[0] = NULL
;
7270 * need_to_commit will get set back to FALSE if the
7271 * configuration is saved successfully.
7273 if (need_to_commit
) {
7275 zerr(gettext("Configuration not saved."));
7278 answer
= ask_yesno(B_FALSE
,
7279 gettext("Configuration not saved; really quit"));
7281 zerr(gettext("Configuration not saved."));
7285 time_to_exit
= B_FALSE
;
7291 return ((need_to_commit
|| saw_error
) ? Z_ERR
: Z_OK
);
7295 * read_input() is the driver of this program. It is a wrapper around
7296 * yyparse(), printing appropriate prompts when needed, checking for
7297 * exit conditions and reacting appropriately [the latter in its cleanup()
7300 * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
7301 * so do_interactive() knows that we are not really done (i.e, we asked
7302 * the user if we should really quit and the user said no).
7307 boolean_t yyin_is_a_tty
= isatty(fileno(yyin
));
7309 * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
7310 * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
7312 char prompt
[MAXPATHLEN
+ ZONENAME_MAX
+ MAX_RT_STRLEN
+ 5], *line
;
7314 /* yyin should have been set to the appropriate (FILE *) if not stdin */
7315 newline_terminated
= B_TRUE
;
7317 if (yyin_is_a_tty
) {
7318 if (newline_terminated
) {
7320 (void) snprintf(prompt
, sizeof (prompt
),
7321 "%s:%s> ", execname
, zone
);
7323 (void) snprintf(prompt
, sizeof (prompt
),
7324 "%s:%s:%s> ", execname
, zone
,
7325 rt_to_str(resource_scope
));
7328 * If the user hits ^C then we want to catch it and
7329 * start over. If the user hits EOF then we want to
7332 line
= gl_get_line(gl
, prompt
, NULL
, -1);
7333 if (gl_return_status(gl
) == GLR_SIGNAL
) {
7334 gl_abandon_line(gl
);
7339 (void) string_to_yyin(line
);
7345 /* Bail out on an error in command file mode. */
7346 if (saw_error
&& cmd_file_mode
&& !interactive_mode
)
7347 time_to_exit
= B_TRUE
;
7348 if (time_to_exit
|| (!yyin_is_a_tty
&& feof(yyin
)))
7355 * This function is used in the zonecfg-interactive-mode scenario: it just
7356 * calls read_input() until we are done.
7360 do_interactive(void)
7364 interactive_mode
= B_TRUE
;
7365 if (!read_only_mode
) {
7367 * Try to set things up proactively in interactive mode, so
7368 * that if the zone in question does not exist yet, we can
7369 * provide the user with a clue.
7371 (void) initialize(B_FALSE
);
7375 } while (err
== Z_REPEAT
);
7380 * cmd_file is slightly more complicated, as it has to open the command file
7381 * and set yyin appropriately. Once that is done, though, it just calls
7382 * read_input(), and only once, since prompting is not possible.
7386 cmd_file(char *file
)
7390 struct stat statbuf
;
7391 boolean_t using_real_file
= (strcmp(file
, "-") != 0);
7393 if (using_real_file
) {
7395 * zerr() prints a line number in cmd_file_mode, which we do
7396 * not want here, so temporarily unset it.
7398 cmd_file_mode
= B_FALSE
;
7399 if ((infile
= fopen(file
, "r")) == NULL
) {
7400 zerr(gettext("could not open file %s: %s"),
7401 file
, strerror(errno
));
7404 if ((err
= fstat(fileno(infile
), &statbuf
)) != 0) {
7405 zerr(gettext("could not stat file %s: %s"),
7406 file
, strerror(errno
));
7410 if (!S_ISREG(statbuf
.st_mode
)) {
7411 zerr(gettext("%s is not a regular file."), file
);
7416 cmd_file_mode
= B_TRUE
;
7417 ok_to_prompt
= B_FALSE
;
7420 * "-f -" is essentially the same as interactive mode,
7421 * so treat it that way.
7423 interactive_mode
= B_TRUE
;
7425 /* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
7426 if ((err
= read_input()) == Z_REPEAT
)
7429 if (using_real_file
)
7430 (void) fclose(infile
);
7435 * Since yacc is based on reading from a (FILE *) whereas what we get from
7436 * the command line is in argv format, we need to convert when the user
7437 * gives us commands directly from the command line. That is done here by
7438 * concatenating the argv list into a space-separated string, writing it
7439 * to a temp file, and rewinding the file so yyin can be set to it. Then
7440 * we call read_input(), and only once, since prompting about whether to
7441 * continue or quit would make no sense in this context.
7445 one_command_at_a_time(int argc
, char *argv
[])
7448 size_t len
= 2; /* terminal \n\0 */
7451 for (i
= 0; i
< argc
; i
++)
7452 len
+= strlen(argv
[i
]) + 1;
7453 if ((command
= malloc(len
)) == NULL
) {
7454 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7457 (void) strlcpy(command
, argv
[0], len
);
7458 for (i
= 1; i
< argc
; i
++) {
7459 (void) strlcat(command
, " ", len
);
7460 (void) strlcat(command
, argv
[i
], len
);
7462 (void) strlcat(command
, "\n", len
);
7463 err
= string_to_yyin(command
);
7473 get_execbasename(char *execfullname
)
7475 char *last_slash
, *execbasename
;
7477 /* guard against '/' at end of command invocation */
7479 last_slash
= strrchr(execfullname
, '/');
7480 if (last_slash
== NULL
) {
7481 execbasename
= execfullname
;
7484 execbasename
= last_slash
+ 1;
7485 if (*execbasename
== '\0') {
7492 return (execbasename
);
7496 main(int argc
, char *argv
[])
7501 /* This must be before anything goes to stdout. */
7502 setbuf(stdout
, NULL
);
7504 saw_error
= B_FALSE
;
7505 cmd_file_mode
= B_FALSE
;
7506 execname
= get_execbasename(argv
[0]);
7508 (void) setlocale(LC_ALL
, "");
7509 (void) textdomain(TEXT_DOMAIN
);
7511 if (getzoneid() != GLOBAL_ZONEID
) {
7512 zerr(gettext("%s can only be run from the global zone."),
7518 usage(B_FALSE
, HELP_USAGE
| HELP_SUBCMDS
);
7521 if (strcmp(argv
[1], cmd_to_str(CMD_HELP
)) == 0) {
7522 (void) one_command_at_a_time(argc
- 1, &(argv
[1]));
7526 while ((arg
= getopt(argc
, argv
, "?f:R:z:")) != EOF
) {
7530 usage(B_TRUE
, HELP_USAGE
| HELP_SUBCMDS
);
7532 usage(B_FALSE
, HELP_USAGE
);
7536 cmd_file_name
= optarg
;
7537 cmd_file_mode
= B_TRUE
;
7540 if (*optarg
!= '/') {
7541 zerr(gettext("root path must be absolute: %s"),
7545 if (stat(optarg
, &st
) == -1 || !S_ISDIR(st
.st_mode
)) {
7547 "root path must be a directory: %s"),
7551 zonecfg_set_root(optarg
);
7554 if (strcmp(optarg
, GLOBAL_ZONENAME
) == 0) {
7555 global_zone
= B_TRUE
;
7556 } else if (zonecfg_validate_zonename(optarg
) != Z_OK
) {
7557 zone_perror(optarg
, Z_BOGUS_ZONE_NAME
, B_TRUE
);
7558 usage(B_FALSE
, HELP_SYNTAX
);
7561 (void) strlcpy(zone
, optarg
, sizeof (zone
));
7562 (void) strlcpy(revert_zone
, optarg
, sizeof (zone
));
7565 usage(B_FALSE
, HELP_USAGE
);
7570 if (optind
> argc
|| strcmp(zone
, "") == 0) {
7571 usage(B_FALSE
, HELP_USAGE
);
7575 if ((err
= zonecfg_access(zone
, W_OK
)) == Z_OK
) {
7576 read_only_mode
= B_FALSE
;
7577 } else if (err
== Z_ACCES
) {
7578 read_only_mode
= B_TRUE
;
7579 /* skip this message in one-off from command line mode */
7581 (void) fprintf(stderr
, gettext("WARNING: you do not "
7582 "have write access to this zone's configuration "
7583 "file;\ngoing into read-only mode.\n"));
7585 fprintf(stderr
, "%s: Could not access zone configuration "
7586 "store: %s\n", execname
, zonecfg_strerror(err
));
7590 if ((handle
= zonecfg_init_handle()) == NULL
) {
7591 zone_perror(execname
, Z_NOMEM
, B_TRUE
);
7596 * This may get set back to FALSE again in cmd_file() if cmd_file_name
7597 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
7599 if (isatty(STDIN_FILENO
))
7600 ok_to_prompt
= B_TRUE
;
7601 if ((gl
= new_GetLine(MAX_LINE_LEN
, MAX_CMD_HIST
)) == NULL
)
7603 if (gl_customize_completion(gl
, NULL
, cmd_cpl_fn
) != 0)
7605 (void) sigset(SIGINT
, SIG_IGN
);
7606 if (optind
== argc
) {
7608 err
= do_interactive();
7610 err
= cmd_file(cmd_file_name
);
7612 err
= one_command_at_a_time(argc
- optind
, &(argv
[optind
]));
7614 zonecfg_fini_handle(handle
);
7617 (void) del_GetLine(gl
);