Print this page
4956 zonecfg won't use a valid pager
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/zonecfg/zonecfg.c
+++ new/usr/src/cmd/zonecfg/zonecfg.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2014 Gary Mills
25 26 */
26 27
27 28 /*
28 29 * zonecfg is a lex/yacc based command interpreter used to manage zone
29 30 * configurations. The lexer (see zonecfg_lex.l) builds up tokens, which
30 31 * the grammar (see zonecfg_grammar.y) builds up into commands, some of
31 32 * which takes resources and/or properties as arguments. See the block
32 33 * comments near the end of zonecfg_grammar.y for how the data structures
33 34 * which keep track of these resources and properties are built up.
34 35 *
35 36 * The resource/property data structures are inserted into a command
36 37 * structure (see zonecfg.h), which also keeps track of command names,
37 38 * miscellaneous arguments, and function handlers. The grammar selects
38 39 * the appropriate function handler, each of which takes a pointer to a
39 40 * command structure as its sole argument, and invokes it. The grammar
40 41 * itself is "entered" (a la the Matrix) by yyparse(), which is called
41 42 * from read_input(), our main driving function. That in turn is called
42 43 * by one of do_interactive(), cmd_file() or one_command_at_a_time(), each
43 44 * of which is called from main() depending on how the program was invoked.
44 45 *
45 46 * The rest of this module consists of the various function handlers and
46 47 * their helper functions. Some of these functions, particularly the
47 48 * X_to_str() functions, which maps command, resource and property numbers
48 49 * to strings, are used quite liberally, as doing so results in a better
49 50 * program w/rt I18N, reducing the need for translation notes.
50 51 */
51 52
52 53 #include <sys/mntent.h>
53 54 #include <sys/varargs.h>
54 55 #include <sys/sysmacros.h>
55 56
56 57 #include <errno.h>
57 58 #include <fcntl.h>
58 59 #include <strings.h>
59 60 #include <unistd.h>
60 61 #include <ctype.h>
61 62 #include <stdlib.h>
62 63 #include <assert.h>
63 64 #include <sys/stat.h>
64 65 #include <zone.h>
65 66 #include <arpa/inet.h>
66 67 #include <netdb.h>
67 68 #include <locale.h>
68 69 #include <libintl.h>
69 70 #include <alloca.h>
70 71 #include <signal.h>
71 72 #include <wait.h>
72 73 #include <libtecla.h>
73 74 #include <libzfs.h>
74 75 #include <sys/brand.h>
75 76 #include <libbrand.h>
76 77 #include <sys/systeminfo.h>
77 78 #include <libdladm.h>
78 79 #include <libinetutil.h>
79 80 #include <pwd.h>
80 81 #include <inet/ip.h>
81 82
82 83 #include <libzonecfg.h>
83 84 #include "zonecfg.h"
84 85
85 86 #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */
86 87 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
87 88 #endif
88 89
89 90 #define PAGER "/usr/bin/more"
90 91 #define EXEC_PREFIX "exec "
91 92 #define EXEC_LEN (strlen(EXEC_PREFIX))
92 93
93 94 struct help {
94 95 uint_t cmd_num;
95 96 char *cmd_name;
96 97 uint_t flags;
97 98 char *short_usage;
98 99 };
99 100
100 101 extern int yyparse(void);
101 102 extern int lex_lineno;
102 103
103 104 #define MAX_LINE_LEN 1024
104 105 #define MAX_CMD_HIST 1024
105 106 #define MAX_CMD_LEN 1024
106 107
107 108 #define ONE_MB 1048576
108 109
109 110 /*
110 111 * Each SHELP_ should be a simple string.
111 112 */
112 113
113 114 #define SHELP_ADD "add <resource-type>\n\t(global scope)\n" \
114 115 "add <property-name> <property-value>\n\t(resource scope)"
115 116 #define SHELP_CANCEL "cancel"
116 117 #define SHELP_CLEAR "clear <property-name>"
117 118 #define SHELP_COMMIT "commit"
118 119 #define SHELP_CREATE "create [-F] [ -a <path> | -b | -t <template> ]"
119 120 #define SHELP_DELETE "delete [-F]"
120 121 #define SHELP_END "end"
121 122 #define SHELP_EXIT "exit [-F]"
122 123 #define SHELP_EXPORT "export [-f output-file]"
123 124 #define SHELP_HELP "help [commands] [syntax] [usage] [<command-name>]"
124 125 #define SHELP_INFO "info [<resource-type> [property-name=property-value]*]"
125 126 #define SHELP_REMOVE "remove [-F] <resource-type> " \
126 127 "[ <property-name>=<property-value> ]*\n" \
127 128 "\t(global scope)\n" \
128 129 "remove <property-name> <property-value>\n" \
129 130 "\t(resource scope)"
130 131 #define SHELP_REVERT "revert [-F]"
131 132 #define SHELP_SELECT "select <resource-type> { <property-name>=" \
132 133 "<property-value> }"
133 134 #define SHELP_SET "set <property-name>=<property-value>"
134 135 #define SHELP_VERIFY "verify"
135 136
136 137 static struct help helptab[] = {
137 138 { CMD_ADD, "add", HELP_RES_PROPS, SHELP_ADD, },
138 139 { CMD_CANCEL, "cancel", 0, SHELP_CANCEL, },
139 140 { CMD_CLEAR, "clear", HELP_PROPS, SHELP_CLEAR, },
140 141 { CMD_COMMIT, "commit", 0, SHELP_COMMIT, },
141 142 { CMD_CREATE, "create", 0, SHELP_CREATE, },
142 143 { CMD_DELETE, "delete", 0, SHELP_DELETE, },
143 144 { CMD_END, "end", 0, SHELP_END, },
144 145 { CMD_EXIT, "exit", 0, SHELP_EXIT, },
145 146 { CMD_EXPORT, "export", 0, SHELP_EXPORT, },
146 147 { CMD_HELP, "help", 0, SHELP_HELP },
147 148 { CMD_INFO, "info", HELP_RES_PROPS, SHELP_INFO, },
148 149 { CMD_REMOVE, "remove", HELP_RES_PROPS, SHELP_REMOVE, },
149 150 { CMD_REVERT, "revert", 0, SHELP_REVERT, },
150 151 { CMD_SELECT, "select", HELP_RES_PROPS, SHELP_SELECT, },
151 152 { CMD_SET, "set", HELP_PROPS, SHELP_SET, },
152 153 { CMD_VERIFY, "verify", 0, SHELP_VERIFY, },
153 154 { 0 },
154 155 };
155 156
156 157 #define MAX_RT_STRLEN 16
157 158
158 159 /* These *must* match the order of the RT_ define's from zonecfg.h */
159 160 char *res_types[] = {
160 161 "unknown",
161 162 "zonename",
162 163 "zonepath",
163 164 "autoboot",
164 165 "pool",
165 166 "fs",
166 167 "net",
167 168 "device",
168 169 "rctl",
169 170 "attr",
170 171 "dataset",
171 172 "limitpriv",
172 173 "bootargs",
173 174 "brand",
174 175 "dedicated-cpu",
175 176 "capped-memory",
176 177 ALIAS_MAXLWPS,
177 178 ALIAS_MAXSHMMEM,
178 179 ALIAS_MAXSHMIDS,
179 180 ALIAS_MAXMSGIDS,
180 181 ALIAS_MAXSEMIDS,
181 182 ALIAS_SHARES,
182 183 "scheduling-class",
183 184 "ip-type",
184 185 "capped-cpu",
185 186 "hostid",
186 187 "admin",
187 188 "fs-allowed",
188 189 ALIAS_MAXPROCS,
189 190 NULL
190 191 };
191 192
192 193 /* These *must* match the order of the PT_ define's from zonecfg.h */
193 194 char *prop_types[] = {
194 195 "unknown",
195 196 "zonename",
196 197 "zonepath",
197 198 "autoboot",
198 199 "pool",
199 200 "dir",
200 201 "special",
201 202 "type",
202 203 "options",
203 204 "address",
204 205 "physical",
205 206 "name",
206 207 "value",
207 208 "match",
208 209 "priv",
209 210 "limit",
210 211 "action",
211 212 "raw",
212 213 "limitpriv",
213 214 "bootargs",
214 215 "brand",
215 216 "ncpus",
216 217 "importance",
217 218 "swap",
218 219 "locked",
219 220 ALIAS_SHARES,
220 221 ALIAS_MAXLWPS,
221 222 ALIAS_MAXSHMMEM,
222 223 ALIAS_MAXSHMIDS,
223 224 ALIAS_MAXMSGIDS,
224 225 ALIAS_MAXSEMIDS,
225 226 ALIAS_MAXLOCKEDMEM,
226 227 ALIAS_MAXSWAP,
227 228 "scheduling-class",
228 229 "ip-type",
229 230 "defrouter",
230 231 "hostid",
231 232 "user",
232 233 "auths",
233 234 "fs-allowed",
234 235 ALIAS_MAXPROCS,
235 236 "allowed-address",
236 237 NULL
237 238 };
238 239
239 240 /* These *must* match the order of the PROP_VAL_ define's from zonecfg.h */
240 241 static char *prop_val_types[] = {
241 242 "simple",
242 243 "complex",
243 244 "list",
244 245 };
245 246
246 247 /*
247 248 * The various _cmds[] lists below are for command tab-completion.
248 249 */
249 250
250 251 /*
251 252 * remove has a space afterwards because it has qualifiers; the other commands
252 253 * that have qualifiers (add, select, etc.) don't need a space here because
253 254 * they have their own _cmds[] lists below.
254 255 */
255 256 static const char *global_scope_cmds[] = {
256 257 "add",
257 258 "clear",
258 259 "commit",
259 260 "create",
260 261 "delete",
261 262 "exit",
262 263 "export",
263 264 "help",
264 265 "info",
265 266 "remove ",
266 267 "revert",
267 268 "select",
268 269 "set",
269 270 "verify",
270 271 NULL
271 272 };
272 273
273 274 static const char *add_cmds[] = {
274 275 "add fs",
275 276 "add net",
276 277 "add device",
277 278 "add rctl",
278 279 "add attr",
279 280 "add dataset",
280 281 "add dedicated-cpu",
281 282 "add capped-cpu",
282 283 "add capped-memory",
283 284 "add admin",
284 285 NULL
285 286 };
286 287
287 288 static const char *clear_cmds[] = {
288 289 "clear autoboot",
289 290 "clear pool",
290 291 "clear limitpriv",
291 292 "clear bootargs",
292 293 "clear scheduling-class",
293 294 "clear ip-type",
294 295 "clear " ALIAS_MAXLWPS,
295 296 "clear " ALIAS_MAXSHMMEM,
296 297 "clear " ALIAS_MAXSHMIDS,
297 298 "clear " ALIAS_MAXMSGIDS,
298 299 "clear " ALIAS_MAXSEMIDS,
299 300 "clear " ALIAS_SHARES,
300 301 "clear " ALIAS_MAXPROCS,
301 302 NULL
302 303 };
303 304
304 305 static const char *remove_cmds[] = {
305 306 "remove fs ",
306 307 "remove net ",
307 308 "remove device ",
308 309 "remove rctl ",
309 310 "remove attr ",
310 311 "remove dataset ",
311 312 "remove dedicated-cpu ",
312 313 "remove capped-cpu ",
313 314 "remove capped-memory ",
314 315 "remove admin ",
315 316 NULL
316 317 };
317 318
318 319 static const char *select_cmds[] = {
319 320 "select fs ",
320 321 "select net ",
321 322 "select device ",
322 323 "select rctl ",
323 324 "select attr ",
324 325 "select dataset ",
325 326 "select dedicated-cpu",
326 327 "select capped-cpu",
327 328 "select capped-memory",
328 329 "select admin",
329 330 NULL
330 331 };
331 332
332 333 static const char *set_cmds[] = {
333 334 "set zonename=",
334 335 "set zonepath=",
335 336 "set brand=",
336 337 "set autoboot=",
337 338 "set pool=",
338 339 "set limitpriv=",
339 340 "set bootargs=",
340 341 "set scheduling-class=",
341 342 "set ip-type=",
342 343 "set " ALIAS_MAXLWPS "=",
343 344 "set " ALIAS_MAXSHMMEM "=",
344 345 "set " ALIAS_MAXSHMIDS "=",
345 346 "set " ALIAS_MAXMSGIDS "=",
346 347 "set " ALIAS_MAXSEMIDS "=",
347 348 "set " ALIAS_SHARES "=",
348 349 "set hostid=",
349 350 "set fs-allowed=",
350 351 "set " ALIAS_MAXPROCS "=",
351 352 NULL
352 353 };
353 354
354 355 static const char *info_cmds[] = {
355 356 "info fs ",
356 357 "info net ",
357 358 "info device ",
358 359 "info rctl ",
359 360 "info attr ",
360 361 "info dataset ",
361 362 "info capped-memory",
362 363 "info dedicated-cpu",
363 364 "info capped-cpu",
364 365 "info zonename",
365 366 "info zonepath",
366 367 "info autoboot",
367 368 "info pool",
368 369 "info limitpriv",
369 370 "info bootargs",
370 371 "info brand",
371 372 "info scheduling-class",
372 373 "info ip-type",
373 374 "info max-lwps",
374 375 "info max-shm-memory",
375 376 "info max-shm-ids",
376 377 "info max-msg-ids",
377 378 "info max-sem-ids",
378 379 "info cpu-shares",
379 380 "info hostid",
380 381 "info admin",
381 382 "info fs-allowed",
382 383 "info max-processes",
383 384 NULL
384 385 };
385 386
386 387 static const char *fs_res_scope_cmds[] = {
387 388 "add options ",
388 389 "cancel",
389 390 "end",
390 391 "exit",
391 392 "help",
392 393 "info",
393 394 "remove options ",
394 395 "set dir=",
395 396 "set raw=",
396 397 "set special=",
397 398 "set type=",
398 399 "clear raw",
399 400 NULL
400 401 };
401 402
402 403 static const char *net_res_scope_cmds[] = {
403 404 "cancel",
404 405 "end",
405 406 "exit",
406 407 "help",
407 408 "info",
408 409 "set address=",
409 410 "set physical=",
410 411 "set defrouter=",
411 412 NULL
412 413 };
413 414
414 415 static const char *device_res_scope_cmds[] = {
415 416 "cancel",
416 417 "end",
417 418 "exit",
418 419 "help",
419 420 "info",
420 421 "set match=",
421 422 NULL
422 423 };
423 424
424 425 static const char *attr_res_scope_cmds[] = {
425 426 "cancel",
426 427 "end",
427 428 "exit",
428 429 "help",
429 430 "info",
430 431 "set name=",
431 432 "set type=",
432 433 "set value=",
433 434 NULL
434 435 };
435 436
436 437 static const char *rctl_res_scope_cmds[] = {
437 438 "add value ",
438 439 "cancel",
439 440 "end",
440 441 "exit",
441 442 "help",
442 443 "info",
443 444 "remove value ",
444 445 "set name=",
445 446 NULL
446 447 };
447 448
448 449 static const char *dataset_res_scope_cmds[] = {
449 450 "cancel",
450 451 "end",
451 452 "exit",
452 453 "help",
453 454 "info",
454 455 "set name=",
455 456 NULL
456 457 };
457 458
458 459 static const char *pset_res_scope_cmds[] = {
459 460 "cancel",
460 461 "end",
461 462 "exit",
462 463 "help",
463 464 "info",
464 465 "set ncpus=",
465 466 "set importance=",
466 467 "clear importance",
467 468 NULL
468 469 };
469 470
470 471 static const char *pcap_res_scope_cmds[] = {
471 472 "cancel",
472 473 "end",
473 474 "exit",
474 475 "help",
475 476 "info",
476 477 "set ncpus=",
477 478 NULL
478 479 };
479 480
480 481 static const char *mcap_res_scope_cmds[] = {
481 482 "cancel",
482 483 "end",
483 484 "exit",
484 485 "help",
485 486 "info",
486 487 "set physical=",
487 488 "set swap=",
488 489 "set locked=",
489 490 "clear physical",
490 491 "clear swap",
491 492 "clear locked",
492 493 NULL
493 494 };
494 495
495 496 static const char *admin_res_scope_cmds[] = {
496 497 "cancel",
497 498 "end",
498 499 "exit",
499 500 "help",
500 501 "info",
501 502 "set user=",
502 503 "set auths=",
503 504 NULL
504 505 };
505 506
506 507 struct xif {
507 508 struct xif *xif_next;
508 509 char xif_name[LIFNAMSIZ];
509 510 boolean_t xif_has_address;
510 511 boolean_t xif_has_defrouter;
511 512 };
512 513
513 514 /* Global variables */
514 515
515 516 /* list of network interfaces specified for exclusive IP zone */
516 517 struct xif *xif;
517 518
518 519 /* set early in main(), never modified thereafter, used all over the place */
519 520 static char *execname;
520 521
521 522 /* set in main(), used all over the place */
522 523 static zone_dochandle_t handle;
523 524
524 525 /* used all over the place */
525 526 static char zone[ZONENAME_MAX];
526 527 static char revert_zone[ZONENAME_MAX];
527 528
528 529 /* global brand operations */
529 530 static brand_handle_t brand;
530 531
531 532 /* set in modifying functions, checked in read_input() */
532 533 static boolean_t need_to_commit = B_FALSE;
533 534 boolean_t saw_error;
534 535
535 536 /* set in yacc parser, checked in read_input() */
536 537 boolean_t newline_terminated;
537 538
538 539 /* set in main(), checked in lex error handler */
539 540 boolean_t cmd_file_mode;
540 541
541 542 /* set in exit_func(), checked in read_input() */
542 543 static boolean_t time_to_exit = B_FALSE, force_exit = B_FALSE;
543 544
544 545 /* used in short_usage() and zerr() */
545 546 static char *cmd_file_name = NULL;
546 547
547 548 /* checked in read_input() and other places */
548 549 static boolean_t ok_to_prompt = B_FALSE;
549 550
550 551 /* set and checked in initialize() */
551 552 static boolean_t got_handle = B_FALSE;
552 553
553 554 /* initialized in do_interactive(), checked in initialize() */
554 555 static boolean_t interactive_mode;
555 556
556 557 /* set if configuring the global zone */
557 558 static boolean_t global_zone = B_FALSE;
558 559
559 560 /* set in main(), checked in multiple places */
560 561 static boolean_t read_only_mode;
561 562
562 563 /* scope is outer/global or inner/resource */
563 564 static boolean_t global_scope = B_TRUE;
564 565 static int resource_scope; /* should be in the RT_ list from zonecfg.h */
565 566 static int end_op = -1; /* operation on end is either add or modify */
566 567
567 568 int num_prop_vals; /* for grammar */
568 569
569 570 /*
570 571 * These are for keeping track of resources as they are specified as part of
571 572 * the multi-step process. They should be initialized by add_resource() or
572 573 * select_func() and filled in by add_property() or set_func().
573 574 */
574 575 static struct zone_fstab old_fstab, in_progress_fstab;
575 576 static struct zone_nwiftab old_nwiftab, in_progress_nwiftab;
576 577 static struct zone_devtab old_devtab, in_progress_devtab;
577 578 static struct zone_rctltab old_rctltab, in_progress_rctltab;
578 579 static struct zone_attrtab old_attrtab, in_progress_attrtab;
579 580 static struct zone_dstab old_dstab, in_progress_dstab;
580 581 static struct zone_psettab old_psettab, in_progress_psettab;
581 582 static struct zone_mcaptab old_mcaptab, in_progress_mcaptab;
582 583 static struct zone_admintab old_admintab, in_progress_admintab;
583 584
584 585 static GetLine *gl; /* The gl_get_line() resource object */
585 586
586 587 static void bytes_to_units(char *str, char *buf, int bufsize);
587 588
588 589 /* Functions begin here */
589 590
590 591 static boolean_t
591 592 initial_match(const char *line1, const char *line2, int word_end)
592 593 {
593 594 if (word_end <= 0)
594 595 return (B_TRUE);
595 596 return (strncmp(line1, line2, word_end) == 0);
596 597 }
597 598
598 599 static int
599 600 add_stuff(WordCompletion *cpl, const char *line1, const char **list,
600 601 int word_end)
601 602 {
602 603 int i, err;
603 604
604 605 for (i = 0; list[i] != NULL; i++) {
605 606 if (initial_match(line1, list[i], word_end)) {
606 607 err = cpl_add_completion(cpl, line1, 0, word_end,
607 608 list[i] + word_end, "", "");
608 609 if (err != 0)
609 610 return (err);
610 611 }
611 612 }
612 613 return (0);
613 614 }
614 615
615 616 static
616 617 /* ARGSUSED */
617 618 CPL_MATCH_FN(cmd_cpl_fn)
618 619 {
619 620 if (global_scope) {
620 621 /*
621 622 * The MAX/MIN tests below are to make sure we have at least
622 623 * enough characters to distinguish from other prefixes (MAX)
623 624 * but only check MIN(what we have, what we're checking).
624 625 */
625 626 if (strncmp(line, "add ", MAX(MIN(word_end, 4), 1)) == 0)
626 627 return (add_stuff(cpl, line, add_cmds, word_end));
627 628 if (strncmp(line, "clear ", MAX(MIN(word_end, 6), 2)) == 0)
628 629 return (add_stuff(cpl, line, clear_cmds, word_end));
629 630 if (strncmp(line, "select ", MAX(MIN(word_end, 7), 3)) == 0)
630 631 return (add_stuff(cpl, line, select_cmds, word_end));
631 632 if (strncmp(line, "set ", MAX(MIN(word_end, 4), 3)) == 0)
632 633 return (add_stuff(cpl, line, set_cmds, word_end));
633 634 if (strncmp(line, "remove ", MAX(MIN(word_end, 7), 1)) == 0)
634 635 return (add_stuff(cpl, line, remove_cmds, word_end));
635 636 if (strncmp(line, "info ", MAX(MIN(word_end, 5), 1)) == 0)
636 637 return (add_stuff(cpl, line, info_cmds, word_end));
637 638 return (add_stuff(cpl, line, global_scope_cmds, word_end));
638 639 }
639 640 switch (resource_scope) {
640 641 case RT_FS:
641 642 return (add_stuff(cpl, line, fs_res_scope_cmds, word_end));
642 643 case RT_NET:
643 644 return (add_stuff(cpl, line, net_res_scope_cmds, word_end));
644 645 case RT_DEVICE:
645 646 return (add_stuff(cpl, line, device_res_scope_cmds, word_end));
646 647 case RT_RCTL:
647 648 return (add_stuff(cpl, line, rctl_res_scope_cmds, word_end));
648 649 case RT_ATTR:
649 650 return (add_stuff(cpl, line, attr_res_scope_cmds, word_end));
650 651 case RT_DATASET:
651 652 return (add_stuff(cpl, line, dataset_res_scope_cmds, word_end));
652 653 case RT_DCPU:
653 654 return (add_stuff(cpl, line, pset_res_scope_cmds, word_end));
654 655 case RT_PCAP:
655 656 return (add_stuff(cpl, line, pcap_res_scope_cmds, word_end));
656 657 case RT_MCAP:
657 658 return (add_stuff(cpl, line, mcap_res_scope_cmds, word_end));
658 659 case RT_ADMIN:
659 660 return (add_stuff(cpl, line, admin_res_scope_cmds, word_end));
660 661 }
661 662 return (0);
662 663 }
663 664
664 665 /*
665 666 * For the main CMD_func() functions below, several of them call getopt()
666 667 * then check optind against argc to make sure an extra parameter was not
667 668 * passed in. The reason this is not caught in the grammar is that the
668 669 * grammar just checks for a miscellaneous TOKEN, which is *expected* to
669 670 * be "-F" (for example), but could be anything. So (for example) this
670 671 * check will prevent "create bogus".
671 672 */
672 673
673 674 cmd_t *
674 675 alloc_cmd(void)
675 676 {
676 677 return (calloc(1, sizeof (cmd_t)));
677 678 }
678 679
679 680 void
680 681 free_cmd(cmd_t *cmd)
681 682 {
682 683 int i;
683 684
684 685 for (i = 0; i < MAX_EQ_PROP_PAIRS; i++)
685 686 if (cmd->cmd_property_ptr[i] != NULL) {
686 687 property_value_ptr_t pp = cmd->cmd_property_ptr[i];
687 688
688 689 switch (pp->pv_type) {
689 690 case PROP_VAL_SIMPLE:
690 691 free(pp->pv_simple);
691 692 break;
692 693 case PROP_VAL_COMPLEX:
693 694 free_complex(pp->pv_complex);
694 695 break;
695 696 case PROP_VAL_LIST:
696 697 free_list(pp->pv_list);
697 698 break;
698 699 }
699 700 }
700 701 for (i = 0; i < cmd->cmd_argc; i++)
701 702 free(cmd->cmd_argv[i]);
702 703 free(cmd);
703 704 }
704 705
705 706 complex_property_ptr_t
706 707 alloc_complex(void)
707 708 {
708 709 return (calloc(1, sizeof (complex_property_t)));
709 710 }
710 711
711 712 void
712 713 free_complex(complex_property_ptr_t complex)
713 714 {
714 715 if (complex == NULL)
715 716 return;
716 717 free_complex(complex->cp_next);
717 718 if (complex->cp_value != NULL)
718 719 free(complex->cp_value);
719 720 free(complex);
720 721 }
721 722
722 723 list_property_ptr_t
723 724 alloc_list(void)
724 725 {
725 726 return (calloc(1, sizeof (list_property_t)));
726 727 }
727 728
728 729 void
729 730 free_list(list_property_ptr_t list)
730 731 {
731 732 if (list == NULL)
732 733 return;
733 734 if (list->lp_simple != NULL)
734 735 free(list->lp_simple);
735 736 free_complex(list->lp_complex);
736 737 free_list(list->lp_next);
737 738 free(list);
738 739 }
739 740
740 741 void
741 742 free_outer_list(list_property_ptr_t list)
742 743 {
743 744 if (list == NULL)
744 745 return;
745 746 free_outer_list(list->lp_next);
746 747 free(list);
747 748 }
748 749
749 750 static struct zone_rctlvaltab *
750 751 alloc_rctlvaltab(void)
751 752 {
752 753 return (calloc(1, sizeof (struct zone_rctlvaltab)));
753 754 }
754 755
755 756 static char *
756 757 rt_to_str(int res_type)
757 758 {
758 759 assert(res_type >= RT_MIN && res_type <= RT_MAX);
759 760 return (res_types[res_type]);
760 761 }
761 762
762 763 static char *
763 764 pt_to_str(int prop_type)
764 765 {
765 766 assert(prop_type >= PT_MIN && prop_type <= PT_MAX);
766 767 return (prop_types[prop_type]);
767 768 }
768 769
769 770 static char *
770 771 pvt_to_str(int pv_type)
771 772 {
772 773 assert(pv_type >= PROP_VAL_MIN && pv_type <= PROP_VAL_MAX);
773 774 return (prop_val_types[pv_type]);
774 775 }
775 776
776 777 static char *
777 778 cmd_to_str(int cmd_num)
778 779 {
779 780 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
780 781 return (helptab[cmd_num].cmd_name);
781 782 }
782 783
783 784 /* PRINTFLIKE1 */
784 785 static void
785 786 zerr(const char *fmt, ...)
786 787 {
787 788 va_list alist;
788 789 static int last_lineno;
789 790
790 791 /* lex_lineno has already been incremented in the lexer; compensate */
791 792 if (cmd_file_mode && lex_lineno > last_lineno) {
792 793 if (strcmp(cmd_file_name, "-") == 0)
793 794 (void) fprintf(stderr, gettext("On line %d:\n"),
794 795 lex_lineno - 1);
795 796 else
796 797 (void) fprintf(stderr, gettext("On line %d of %s:\n"),
797 798 lex_lineno - 1, cmd_file_name);
798 799 last_lineno = lex_lineno;
799 800 }
800 801 va_start(alist, fmt);
801 802 (void) vfprintf(stderr, fmt, alist);
802 803 (void) fprintf(stderr, "\n");
803 804 va_end(alist);
804 805 }
805 806
806 807 /*
807 808 * This is a separate function rather than a set of define's because of the
808 809 * gettext() wrapping.
809 810 */
810 811
811 812 /*
812 813 * TRANSLATION_NOTE
813 814 * Each string below should have \t follow \n whenever needed; the
814 815 * initial \t and the terminal \n will be provided by the calling function.
815 816 */
816 817
817 818 static char *
818 819 long_help(int cmd_num)
819 820 {
820 821 static char line[1024]; /* arbitrary large amount */
821 822
822 823 assert(cmd_num >= CMD_MIN && cmd_num <= CMD_MAX);
823 824 switch (cmd_num) {
824 825 case CMD_HELP:
825 826 return (gettext("Prints help message."));
826 827 case CMD_CREATE:
827 828 (void) snprintf(line, sizeof (line),
828 829 gettext("Creates a configuration for the "
829 830 "specified zone. %s should be\n\tused to "
830 831 "begin configuring a new zone. If overwriting an "
831 832 "existing\n\tconfiguration, the -F flag can be "
832 833 "used to force the action. If\n\t-t template is "
833 834 "given, creates a configuration identical to the\n"
834 835 "\tspecified template, except that the zone name "
835 836 "is changed from\n\ttemplate to zonename. '%s -a' "
836 837 "creates a configuration from a\n\tdetached "
837 838 "zonepath. '%s -b' results in a blank "
838 839 "configuration.\n\t'%s' with no arguments applies "
839 840 "the Sun default settings."),
840 841 cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE),
841 842 cmd_to_str(CMD_CREATE), cmd_to_str(CMD_CREATE));
842 843 return (line);
843 844 case CMD_EXIT:
844 845 return (gettext("Exits the program. The -F flag can "
845 846 "be used to force the action."));
846 847 case CMD_EXPORT:
847 848 return (gettext("Prints configuration to standard "
848 849 "output, or to output-file if\n\tspecified, in "
849 850 "a form suitable for use in a command-file."));
850 851 case CMD_ADD:
851 852 return (gettext("Add specified resource to "
852 853 "configuration."));
853 854 case CMD_DELETE:
854 855 return (gettext("Deletes the specified zone. The -F "
855 856 "flag can be used to force the\n\taction."));
856 857 case CMD_REMOVE:
857 858 return (gettext("Remove specified resource from "
858 859 "configuration. The -F flag can be used\n\tto "
859 860 "force the action."));
860 861 case CMD_SELECT:
861 862 (void) snprintf(line, sizeof (line),
862 863 gettext("Selects a resource to modify. "
863 864 "Resource modification is completed\n\twith the "
864 865 "command \"%s\". The property name/value pairs "
865 866 "must uniquely\n\tidentify a resource. Note that "
866 867 "the curly braces ('{', '}') mean one\n\tor more "
867 868 "of whatever is between them."),
868 869 cmd_to_str(CMD_END));
869 870 return (line);
870 871 case CMD_SET:
871 872 return (gettext("Sets property values."));
872 873 case CMD_CLEAR:
873 874 return (gettext("Clears property values."));
874 875 case CMD_INFO:
875 876 return (gettext("Displays information about the "
876 877 "current configuration. If resource\n\ttype is "
877 878 "specified, displays only information about "
878 879 "resources of\n\tthe relevant type. If resource "
879 880 "id is specified, displays only\n\tinformation "
880 881 "about that resource."));
881 882 case CMD_VERIFY:
882 883 return (gettext("Verifies current configuration "
883 884 "for correctness (some resource types\n\thave "
884 885 "required properties)."));
885 886 case CMD_COMMIT:
886 887 (void) snprintf(line, sizeof (line),
887 888 gettext("Commits current configuration. "
888 889 "Configuration must be committed to\n\tbe used by "
889 890 "%s. Until the configuration is committed, "
890 891 "changes \n\tcan be removed with the %s "
891 892 "command. This operation is\n\tattempted "
892 893 "automatically upon completion of a %s "
893 894 "session."), "zoneadm", cmd_to_str(CMD_REVERT),
894 895 "zonecfg");
895 896 return (line);
896 897 case CMD_REVERT:
897 898 return (gettext("Reverts configuration back to the "
898 899 "last committed state. The -F flag\n\tcan be "
899 900 "used to force the action."));
900 901 case CMD_CANCEL:
901 902 return (gettext("Cancels resource/property "
↓ open down ↓ |
867 lines elided |
↑ open up ↑ |
902 903 "specification."));
903 904 case CMD_END:
904 905 return (gettext("Ends resource/property "
905 906 "specification."));
906 907 }
907 908 /* NOTREACHED */
908 909 return (NULL);
909 910 }
910 911
911 912 /*
913 + * Return the input filename appended to each component of the path
914 + * or the filename itself if it is absolute.
915 + * Parameters: path string, file name, output string.
916 + */
917 +/* Copied almost verbatim from libtnfctl/prb_findexec.c */
918 +static const char *
919 +exec_cat(const char *s1, const char *s2, char *si)
920 +{
921 + char *s;
922 + /* Number of remaining characters in s */
923 + int cnt = PATH_MAX + 1;
924 +
925 + s = si;
926 + while (*s1 && *s1 != ':') { /* Copy first component of path to si */
927 + if (cnt > 0) {
928 + *s++ = *s1++;
929 + cnt--;
930 + } else {
931 + s1++;
932 + }
933 + }
934 + if (si != s && cnt > 0) { /* Add slash if s2 is not absolute */
935 + *s++ = '/';
936 + cnt--;
937 + }
938 + while (*s2 && cnt > 0) { /* Copy s2 to si */
939 + *s++ = *s2++;
940 + cnt--;
941 + }
942 + *s = '\0'; /* Terminate the output string */
943 + return (*s1 ? ++s1 : NULL); /* Return next path component or NULL */
944 +}
945 +
946 +/* Determine that a name exists in PATH */
947 +/* Copied with changes from libtnfctl/prb_findexec.c */
948 +static int
949 +path_find(const char *name)
950 +{
951 + const char *pathstr;
952 + char fname[PATH_MAX + 2];
953 + const char *cp;
954 + struct stat stat_buf;
955 +
956 + if ((pathstr = getenv("PATH")) == NULL) {
957 + if (geteuid() == 0 || getuid() == 0)
958 + pathstr = "/usr/sbin:/usr/bin";
959 + else
960 + pathstr = "/usr/bin:";
961 + }
962 + cp = strchr(name, '/') ? (const char *) "" : pathstr;
963 +
964 + do {
965 + cp = exec_cat(cp, name, fname);
966 + if (stat(fname, &stat_buf) != -1) {
967 + /* successful find of the file */
968 + return (0);
969 + }
970 + } while (cp != NULL);
971 +
972 + return (-1);
973 +}
974 +
975 +static FILE *
976 +pager_open(void) {
977 + FILE *newfp;
978 + char *pager, *space;
979 +
980 + pager = getenv("PAGER");
981 + if (pager == NULL || *pager == '\0')
982 + pager = PAGER;
983 +
984 + space = strchr(pager, ' ');
985 + if (space)
986 + *space = '\0';
987 + if (path_find(pager) == 0) {
988 + if (space)
989 + *space = ' ';
990 + if ((newfp = popen(pager, "w")) == NULL)
991 + zerr(gettext("PAGER open failed (%s)."),
992 + strerror(errno));
993 + return (newfp);
994 + } else {
995 + zerr(gettext("PAGER %s does not exist (%s)."),
996 + pager, strerror(errno));
997 + }
998 + return (NULL);
999 +}
1000 +
1001 +static void
1002 +pager_close(FILE *fp) {
1003 + int status;
1004 +
1005 + status = pclose(fp);
1006 + if (status == -1)
1007 + zerr(gettext("PAGER close failed (%s)."),
1008 + strerror(errno));
1009 +}
1010 +
1011 +/*
912 1012 * Called with verbose TRUE when help is explicitly requested, FALSE for
913 1013 * unexpected errors.
914 1014 */
915 1015
916 1016 void
917 1017 usage(boolean_t verbose, uint_t flags)
918 1018 {
919 1019 FILE *fp = verbose ? stdout : stderr;
920 1020 FILE *newfp;
921 1021 boolean_t need_to_close = B_FALSE;
922 - char *pager, *space;
923 1022 int i;
924 - struct stat statbuf;
925 1023
926 1024 /* don't page error output */
927 1025 if (verbose && interactive_mode) {
928 - if ((pager = getenv("PAGER")) == NULL)
929 - pager = PAGER;
930 -
931 - space = strchr(pager, ' ');
932 - if (space)
933 - *space = '\0';
934 - if (stat(pager, &statbuf) == 0) {
935 - if (space)
936 - *space = ' ';
937 - if ((newfp = popen(pager, "w")) != NULL) {
938 - need_to_close = B_TRUE;
939 - fp = newfp;
940 - }
941 - } else {
942 - zerr(gettext("PAGER %s does not exist (%s)."),
943 - pager, strerror(errno));
1026 + if ((newfp = pager_open()) != NULL) {
1027 + need_to_close = B_TRUE;
1028 + fp = newfp;
944 1029 }
945 1030 }
946 1031
947 1032 if (flags & HELP_META) {
948 1033 (void) fprintf(fp, gettext("More help is available for the "
949 1034 "following:\n"));
950 1035 (void) fprintf(fp, "\n\tcommands ('%s commands')\n",
951 1036 cmd_to_str(CMD_HELP));
952 1037 (void) fprintf(fp, "\tsyntax ('%s syntax')\n",
953 1038 cmd_to_str(CMD_HELP));
954 1039 (void) fprintf(fp, "\tusage ('%s usage')\n\n",
955 1040 cmd_to_str(CMD_HELP));
956 1041 (void) fprintf(fp, gettext("You may also obtain help on any "
957 1042 "command by typing '%s <command-name>.'\n"),
958 1043 cmd_to_str(CMD_HELP));
959 1044 }
960 1045 if (flags & HELP_RES_SCOPE) {
961 1046 switch (resource_scope) {
962 1047 case RT_FS:
963 1048 (void) fprintf(fp, gettext("The '%s' resource scope is "
964 1049 "used to configure a file-system.\n"),
965 1050 rt_to_str(resource_scope));
966 1051 (void) fprintf(fp, gettext("Valid commands:\n"));
967 1052 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
968 1053 pt_to_str(PT_DIR), gettext("<path>"));
969 1054 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
970 1055 pt_to_str(PT_SPECIAL), gettext("<path>"));
971 1056 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
972 1057 pt_to_str(PT_RAW), gettext("<raw-device>"));
973 1058 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
974 1059 pt_to_str(PT_TYPE), gettext("<file-system type>"));
975 1060 (void) fprintf(fp, "\t%s %s %s\n", cmd_to_str(CMD_ADD),
976 1061 pt_to_str(PT_OPTIONS),
977 1062 gettext("<file-system options>"));
978 1063 (void) fprintf(fp, "\t%s %s %s\n",
979 1064 cmd_to_str(CMD_REMOVE), pt_to_str(PT_OPTIONS),
980 1065 gettext("<file-system options>"));
981 1066 (void) fprintf(fp, gettext("Consult the file-system "
982 1067 "specific manual page, such as mount_ufs(1M), "
983 1068 "for\ndetails about file-system options. Note "
984 1069 "that any file-system options with an\nembedded "
985 1070 "'=' character must be enclosed in double quotes, "
986 1071 /*CSTYLED*/
987 1072 "such as \"%s=5\".\n"), MNTOPT_RETRY);
988 1073 break;
989 1074 case RT_NET:
990 1075 (void) fprintf(fp, gettext("The '%s' resource scope is "
991 1076 "used to configure a network interface.\n"),
992 1077 rt_to_str(resource_scope));
993 1078 (void) fprintf(fp, gettext("Valid commands:\n"));
994 1079 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
995 1080 pt_to_str(PT_ADDRESS), gettext("<IP-address>"));
996 1081 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
997 1082 pt_to_str(PT_ALLOWED_ADDRESS),
998 1083 gettext("<IP-address>"));
999 1084 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1000 1085 pt_to_str(PT_PHYSICAL), gettext("<interface>"));
1001 1086 (void) fprintf(fp, gettext("See ifconfig(1M) for "
1002 1087 "details of the <interface> string.\n"));
1003 1088 (void) fprintf(fp, gettext("%s %s is valid "
1004 1089 "if the %s property is set to %s, otherwise it "
1005 1090 "must not be set.\n"),
1006 1091 cmd_to_str(CMD_SET), pt_to_str(PT_ADDRESS),
1007 1092 pt_to_str(PT_IPTYPE), gettext("shared"));
1008 1093 (void) fprintf(fp, gettext("%s %s is valid "
1009 1094 "if the %s property is set to %s, otherwise it "
1010 1095 "must not be set.\n"),
1011 1096 cmd_to_str(CMD_SET), pt_to_str(PT_ALLOWED_ADDRESS),
1012 1097 pt_to_str(PT_IPTYPE), gettext("exclusive"));
1013 1098 (void) fprintf(fp, gettext("\t%s %s=%s\n%s %s "
1014 1099 "is valid if the %s or %s property is set, "
1015 1100 "otherwise it must not be set\n"),
1016 1101 cmd_to_str(CMD_SET),
1017 1102 pt_to_str(PT_DEFROUTER), gettext("<IP-address>"),
1018 1103 cmd_to_str(CMD_SET), pt_to_str(PT_DEFROUTER),
1019 1104 gettext(pt_to_str(PT_ADDRESS)),
1020 1105 gettext(pt_to_str(PT_ALLOWED_ADDRESS)));
1021 1106 break;
1022 1107 case RT_DEVICE:
1023 1108 (void) fprintf(fp, gettext("The '%s' resource scope is "
1024 1109 "used to configure a device node.\n"),
1025 1110 rt_to_str(resource_scope));
1026 1111 (void) fprintf(fp, gettext("Valid commands:\n"));
1027 1112 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1028 1113 pt_to_str(PT_MATCH), gettext("<device-path>"));
1029 1114 break;
1030 1115 case RT_RCTL:
1031 1116 (void) fprintf(fp, gettext("The '%s' resource scope is "
1032 1117 "used to configure a resource control.\n"),
1033 1118 rt_to_str(resource_scope));
1034 1119 (void) fprintf(fp, gettext("Valid commands:\n"));
1035 1120 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1036 1121 pt_to_str(PT_NAME), gettext("<string>"));
1037 1122 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1038 1123 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
1039 1124 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1040 1125 pt_to_str(PT_LIMIT), gettext("<number>"),
1041 1126 pt_to_str(PT_ACTION), gettext("<action-value>"));
1042 1127 (void) fprintf(fp, "\t%s %s (%s=%s,%s=%s,%s=%s)\n",
1043 1128 cmd_to_str(CMD_REMOVE), pt_to_str(PT_VALUE),
1044 1129 pt_to_str(PT_PRIV), gettext("<priv-value>"),
1045 1130 pt_to_str(PT_LIMIT), gettext("<number>"),
1046 1131 pt_to_str(PT_ACTION), gettext("<action-value>"));
1047 1132 (void) fprintf(fp, "%s\n\t%s := privileged\n"
1048 1133 "\t%s := none | deny\n", gettext("Where"),
1049 1134 gettext("<priv-value>"), gettext("<action-value>"));
1050 1135 break;
1051 1136 case RT_ATTR:
1052 1137 (void) fprintf(fp, gettext("The '%s' resource scope is "
1053 1138 "used to configure a generic attribute.\n"),
1054 1139 rt_to_str(resource_scope));
1055 1140 (void) fprintf(fp, gettext("Valid commands:\n"));
1056 1141 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1057 1142 pt_to_str(PT_NAME), gettext("<name>"));
1058 1143 (void) fprintf(fp, "\t%s %s=boolean\n",
1059 1144 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
1060 1145 (void) fprintf(fp, "\t%s %s=true | false\n",
1061 1146 cmd_to_str(CMD_SET), pt_to_str(PT_VALUE));
1062 1147 (void) fprintf(fp, gettext("or\n"));
1063 1148 (void) fprintf(fp, "\t%s %s=int\n", cmd_to_str(CMD_SET),
1064 1149 pt_to_str(PT_TYPE));
1065 1150 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1066 1151 pt_to_str(PT_VALUE), gettext("<integer>"));
1067 1152 (void) fprintf(fp, gettext("or\n"));
1068 1153 (void) fprintf(fp, "\t%s %s=string\n",
1069 1154 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
1070 1155 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1071 1156 pt_to_str(PT_VALUE), gettext("<string>"));
1072 1157 (void) fprintf(fp, gettext("or\n"));
1073 1158 (void) fprintf(fp, "\t%s %s=uint\n",
1074 1159 cmd_to_str(CMD_SET), pt_to_str(PT_TYPE));
1075 1160 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1076 1161 pt_to_str(PT_VALUE), gettext("<unsigned integer>"));
1077 1162 break;
1078 1163 case RT_DATASET:
1079 1164 (void) fprintf(fp, gettext("The '%s' resource scope is "
1080 1165 "used to export ZFS datasets.\n"),
1081 1166 rt_to_str(resource_scope));
1082 1167 (void) fprintf(fp, gettext("Valid commands:\n"));
1083 1168 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1084 1169 pt_to_str(PT_NAME), gettext("<name>"));
1085 1170 break;
1086 1171 case RT_DCPU:
1087 1172 (void) fprintf(fp, gettext("The '%s' resource scope "
1088 1173 "configures the 'pools' facility to dedicate\na "
1089 1174 "subset of the system's processors to this zone "
1090 1175 "while it is running.\n"),
1091 1176 rt_to_str(resource_scope));
1092 1177 (void) fprintf(fp, gettext("Valid commands:\n"));
1093 1178 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1094 1179 pt_to_str(PT_NCPUS),
1095 1180 gettext("<unsigned integer | range>"));
1096 1181 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1097 1182 pt_to_str(PT_IMPORTANCE),
1098 1183 gettext("<unsigned integer>"));
1099 1184 break;
1100 1185 case RT_PCAP:
1101 1186 (void) fprintf(fp, gettext("The '%s' resource scope is "
1102 1187 "used to set an upper limit (a cap) on the\n"
1103 1188 "percentage of CPU that can be used by this zone. "
1104 1189 "A '%s' value of 1\ncorresponds to one cpu. The "
1105 1190 "value can be set higher than 1, up to the total\n"
1106 1191 "number of CPUs on the system. The value can "
1107 1192 "also be less than 1,\nrepresenting a fraction of "
1108 1193 "a cpu.\n"),
1109 1194 rt_to_str(resource_scope), pt_to_str(PT_NCPUS));
1110 1195 (void) fprintf(fp, gettext("Valid commands:\n"));
1111 1196 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1112 1197 pt_to_str(PT_NCPUS), gettext("<unsigned decimal>"));
1113 1198 break;
1114 1199 case RT_MCAP:
1115 1200 (void) fprintf(fp, gettext("The '%s' resource scope is "
1116 1201 "used to set an upper limit (a cap) on the\n"
1117 1202 "amount of physical memory, swap space and locked "
1118 1203 "memory that can be used by\nthis zone.\n"),
1119 1204 rt_to_str(resource_scope));
1120 1205 (void) fprintf(fp, gettext("Valid commands:\n"));
1121 1206 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1122 1207 pt_to_str(PT_PHYSICAL),
1123 1208 gettext("<qualified unsigned decimal>"));
1124 1209 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1125 1210 pt_to_str(PT_SWAP),
1126 1211 gettext("<qualified unsigned decimal>"));
1127 1212 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1128 1213 pt_to_str(PT_LOCKED),
1129 1214 gettext("<qualified unsigned decimal>"));
1130 1215 break;
1131 1216 case RT_ADMIN:
1132 1217 (void) fprintf(fp, gettext("The '%s' resource scope is "
1133 1218 "used to delegate specific zone management\n"
1134 1219 "rights to users and roles. These rights are "
1135 1220 "only applicable to this zone.\n"),
1136 1221 rt_to_str(resource_scope));
1137 1222 (void) fprintf(fp, gettext("Valid commands:\n"));
1138 1223 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1139 1224 pt_to_str(PT_USER),
1140 1225 gettext("<single user or role name>"));
1141 1226 (void) fprintf(fp, "\t%s %s=%s\n", cmd_to_str(CMD_SET),
1142 1227 pt_to_str(PT_AUTHS),
1143 1228 gettext("<comma separated list>"));
1144 1229 break;
1145 1230 }
1146 1231 (void) fprintf(fp, gettext("And from any resource scope, you "
1147 1232 "can:\n"));
1148 1233 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_END),
1149 1234 gettext("(to conclude this operation)"));
1150 1235 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_CANCEL),
1151 1236 gettext("(to cancel this operation)"));
1152 1237 (void) fprintf(fp, "\t%s\t%s\n", cmd_to_str(CMD_EXIT),
1153 1238 gettext("(to exit the zonecfg utility)"));
1154 1239 }
1155 1240 if (flags & HELP_USAGE) {
1156 1241 (void) fprintf(fp, "%s:\t%s %s\n", gettext("usage"),
1157 1242 execname, cmd_to_str(CMD_HELP));
1158 1243 (void) fprintf(fp, "\t%s -z <zone>\t\t\t(%s)\n",
1159 1244 execname, gettext("interactive"));
1160 1245 (void) fprintf(fp, "\t%s -z <zone> <command>\n", execname);
1161 1246 (void) fprintf(fp, "\t%s -z <zone> -f <command-file>\n",
1162 1247 execname);
1163 1248 }
1164 1249 if (flags & HELP_SUBCMDS) {
1165 1250 (void) fprintf(fp, "%s:\n\n", gettext("Commands"));
1166 1251 for (i = 0; i <= CMD_MAX; i++) {
1167 1252 (void) fprintf(fp, "%s\n", helptab[i].short_usage);
1168 1253 if (verbose)
1169 1254 (void) fprintf(fp, "\t%s\n\n", long_help(i));
1170 1255 }
1171 1256 }
1172 1257 if (flags & HELP_SYNTAX) {
1173 1258 if (!verbose)
1174 1259 (void) fprintf(fp, "\n");
1175 1260 (void) fprintf(fp, "<zone> := [A-Za-z0-9][A-Za-z0-9_.-]*\n");
1176 1261 (void) fprintf(fp, gettext("\t(except the reserved words "
1177 1262 "'%s' and anything starting with '%s')\n"), "global",
1178 1263 "SUNW");
1179 1264 (void) fprintf(fp,
1180 1265 gettext("\tName must be less than %d characters.\n"),
1181 1266 ZONENAME_MAX);
1182 1267 if (verbose)
1183 1268 (void) fprintf(fp, "\n");
1184 1269 }
1185 1270 if (flags & HELP_NETADDR) {
1186 1271 (void) fprintf(fp, gettext("\n<net-addr> :="));
1187 1272 (void) fprintf(fp,
1188 1273 gettext("\t<IPv4-address>[/<IPv4-prefix-length>] |\n"));
1189 1274 (void) fprintf(fp,
1190 1275 gettext("\t\t<IPv6-address>/<IPv6-prefix-length> |\n"));
1191 1276 (void) fprintf(fp,
1192 1277 gettext("\t\t<hostname>[/<IPv4-prefix-length>]\n"));
1193 1278 (void) fprintf(fp, gettext("See inet(3SOCKET) for IPv4 and "
1194 1279 "IPv6 address syntax.\n"));
1195 1280 (void) fprintf(fp, gettext("<IPv4-prefix-length> := [0-32]\n"));
1196 1281 (void) fprintf(fp,
1197 1282 gettext("<IPv6-prefix-length> := [0-128]\n"));
1198 1283 (void) fprintf(fp,
1199 1284 gettext("<hostname> := [A-Za-z0-9][A-Za-z0-9-.]*\n"));
1200 1285 }
1201 1286 if (flags & HELP_RESOURCES) {
1202 1287 (void) fprintf(fp, "<%s> := %s | %s | %s | %s | %s |\n\t"
1203 1288 "%s | %s | %s | %s | %s\n\n",
1204 1289 gettext("resource type"), rt_to_str(RT_FS),
1205 1290 rt_to_str(RT_NET), rt_to_str(RT_DEVICE),
1206 1291 rt_to_str(RT_RCTL), rt_to_str(RT_ATTR),
1207 1292 rt_to_str(RT_DATASET), rt_to_str(RT_DCPU),
1208 1293 rt_to_str(RT_PCAP), rt_to_str(RT_MCAP),
1209 1294 rt_to_str(RT_ADMIN));
1210 1295 }
1211 1296 if (flags & HELP_PROPS) {
1212 1297 (void) fprintf(fp, gettext("For resource type ... there are "
1213 1298 "property types ...:\n"));
1214 1299 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1215 1300 pt_to_str(PT_ZONENAME));
1216 1301 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1217 1302 pt_to_str(PT_ZONEPATH));
1218 1303 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1219 1304 pt_to_str(PT_BRAND));
1220 1305 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1221 1306 pt_to_str(PT_AUTOBOOT));
1222 1307 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1223 1308 pt_to_str(PT_BOOTARGS));
1224 1309 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1225 1310 pt_to_str(PT_POOL));
1226 1311 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1227 1312 pt_to_str(PT_LIMITPRIV));
1228 1313 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1229 1314 pt_to_str(PT_SCHED));
1230 1315 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1231 1316 pt_to_str(PT_IPTYPE));
1232 1317 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1233 1318 pt_to_str(PT_HOSTID));
1234 1319 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1235 1320 pt_to_str(PT_FS_ALLOWED));
1236 1321 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1237 1322 pt_to_str(PT_MAXLWPS));
1238 1323 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1239 1324 pt_to_str(PT_MAXPROCS));
1240 1325 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1241 1326 pt_to_str(PT_MAXSHMMEM));
1242 1327 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1243 1328 pt_to_str(PT_MAXSHMIDS));
1244 1329 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1245 1330 pt_to_str(PT_MAXMSGIDS));
1246 1331 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1247 1332 pt_to_str(PT_MAXSEMIDS));
1248 1333 (void) fprintf(fp, "\t%s\t%s\n", gettext("(global)"),
1249 1334 pt_to_str(PT_SHARES));
1250 1335 (void) fprintf(fp, "\t%s\t\t%s, %s, %s, %s, %s\n",
1251 1336 rt_to_str(RT_FS), pt_to_str(PT_DIR),
1252 1337 pt_to_str(PT_SPECIAL), pt_to_str(PT_RAW),
1253 1338 pt_to_str(PT_TYPE), pt_to_str(PT_OPTIONS));
1254 1339 (void) fprintf(fp, "\t%s\t\t%s, %s, %s|%s\n", rt_to_str(RT_NET),
1255 1340 pt_to_str(PT_ADDRESS), pt_to_str(PT_ALLOWED_ADDRESS),
1256 1341 pt_to_str(PT_PHYSICAL), pt_to_str(PT_DEFROUTER));
1257 1342 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DEVICE),
1258 1343 pt_to_str(PT_MATCH));
1259 1344 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_RCTL),
1260 1345 pt_to_str(PT_NAME), pt_to_str(PT_VALUE));
1261 1346 (void) fprintf(fp, "\t%s\t\t%s, %s, %s\n", rt_to_str(RT_ATTR),
1262 1347 pt_to_str(PT_NAME), pt_to_str(PT_TYPE),
1263 1348 pt_to_str(PT_VALUE));
1264 1349 (void) fprintf(fp, "\t%s\t\t%s\n", rt_to_str(RT_DATASET),
1265 1350 pt_to_str(PT_NAME));
1266 1351 (void) fprintf(fp, "\t%s\t%s, %s\n", rt_to_str(RT_DCPU),
↓ open down ↓ |
313 lines elided |
↑ open up ↑ |
1267 1352 pt_to_str(PT_NCPUS), pt_to_str(PT_IMPORTANCE));
1268 1353 (void) fprintf(fp, "\t%s\t%s\n", rt_to_str(RT_PCAP),
1269 1354 pt_to_str(PT_NCPUS));
1270 1355 (void) fprintf(fp, "\t%s\t%s, %s, %s\n", rt_to_str(RT_MCAP),
1271 1356 pt_to_str(PT_PHYSICAL), pt_to_str(PT_SWAP),
1272 1357 pt_to_str(PT_LOCKED));
1273 1358 (void) fprintf(fp, "\t%s\t\t%s, %s\n", rt_to_str(RT_ADMIN),
1274 1359 pt_to_str(PT_USER), pt_to_str(PT_AUTHS));
1275 1360 }
1276 1361 if (need_to_close)
1277 - (void) pclose(fp);
1362 + (void) pager_close(fp);
1278 1363 }
1279 1364
1280 1365 static void
1281 1366 zone_perror(char *prefix, int err, boolean_t set_saw)
1282 1367 {
1283 1368 zerr("%s: %s", prefix, zonecfg_strerror(err));
1284 1369 if (set_saw)
1285 1370 saw_error = B_TRUE;
1286 1371 }
1287 1372
1288 1373 /*
1289 1374 * zone_perror() expects a single string, but for remove and select
1290 1375 * we have both the command and the resource type, so this wrapper
1291 1376 * function serves the same purpose in a slightly different way.
1292 1377 */
1293 1378
1294 1379 static void
1295 1380 z_cmd_rt_perror(int cmd_num, int res_num, int err, boolean_t set_saw)
1296 1381 {
1297 1382 zerr("%s %s: %s", cmd_to_str(cmd_num), rt_to_str(res_num),
1298 1383 zonecfg_strerror(err));
1299 1384 if (set_saw)
1300 1385 saw_error = B_TRUE;
1301 1386 }
1302 1387
1303 1388 /* returns Z_OK if successful, Z_foo from <libzonecfg.h> otherwise */
1304 1389 static int
1305 1390 initialize(boolean_t handle_expected)
1306 1391 {
1307 1392 int err;
1308 1393 char brandname[MAXNAMELEN];
1309 1394
1310 1395 if (zonecfg_check_handle(handle) != Z_OK) {
1311 1396 if ((err = zonecfg_get_handle(zone, handle)) == Z_OK) {
1312 1397 got_handle = B_TRUE;
1313 1398 if (zonecfg_get_brand(handle, brandname,
1314 1399 sizeof (brandname)) != Z_OK) {
1315 1400 zerr("Zone %s is inconsistent: missing "
1316 1401 "brand attribute", zone);
1317 1402 exit(Z_ERR);
1318 1403 }
1319 1404 if ((brand = brand_open(brandname)) == NULL) {
1320 1405 zerr("Zone %s uses non-existent brand \"%s\"."
1321 1406 " Unable to continue", zone, brandname);
1322 1407 exit(Z_ERR);
1323 1408 }
1324 1409 /*
1325 1410 * If the user_attr file is newer than
1326 1411 * the zone config file, the admins
1327 1412 * may need to be updated since the
1328 1413 * RBAC files are authoritative for
1329 1414 * authorization checks.
1330 1415 */
1331 1416 err = zonecfg_update_userauths(handle, zone);
1332 1417 if (err == Z_OK) {
1333 1418 zerr(gettext("The administrative rights "
1334 1419 "were updated to match "
1335 1420 "the current RBAC configuration.\n"
1336 1421 "Use \"info admin\" and \"revert\" to "
1337 1422 "compare with the previous settings."));
1338 1423 need_to_commit = B_TRUE;
1339 1424 } else if (err != Z_NO_ENTRY) {
1340 1425 zerr(gettext("failed to update "
1341 1426 "admin rights."));
1342 1427 exit(Z_ERR);
1343 1428 } else if (need_to_commit) {
1344 1429 zerr(gettext("admin rights were updated "
1345 1430 "to match RBAC configuration."));
1346 1431 }
1347 1432
1348 1433 } else if (global_zone && err == Z_NO_ZONE && !got_handle &&
1349 1434 !read_only_mode) {
1350 1435 /*
1351 1436 * We implicitly create the global zone config if it
1352 1437 * doesn't exist.
1353 1438 */
1354 1439 zone_dochandle_t tmphandle;
1355 1440
1356 1441 if ((tmphandle = zonecfg_init_handle()) == NULL) {
1357 1442 zone_perror(execname, Z_NOMEM, B_TRUE);
1358 1443 exit(Z_ERR);
1359 1444 }
1360 1445
1361 1446 err = zonecfg_get_template_handle("SUNWblank", zone,
1362 1447 tmphandle);
1363 1448
1364 1449 if (err != Z_OK) {
1365 1450 zonecfg_fini_handle(tmphandle);
1366 1451 zone_perror("SUNWblank", err, B_TRUE);
1367 1452 return (err);
1368 1453 }
1369 1454
1370 1455 need_to_commit = B_TRUE;
1371 1456 zonecfg_fini_handle(handle);
1372 1457 handle = tmphandle;
1373 1458 got_handle = B_TRUE;
1374 1459
1375 1460 } else {
1376 1461 zone_perror(zone, err, handle_expected || got_handle);
1377 1462 if (err == Z_NO_ZONE && !got_handle &&
1378 1463 interactive_mode && !read_only_mode)
1379 1464 (void) printf(gettext("Use '%s' to begin "
1380 1465 "configuring a new zone.\n"),
1381 1466 cmd_to_str(CMD_CREATE));
1382 1467 return (err);
1383 1468 }
1384 1469 }
1385 1470 return (Z_OK);
1386 1471 }
1387 1472
1388 1473 static boolean_t
1389 1474 state_atleast(zone_state_t state)
1390 1475 {
1391 1476 zone_state_t state_num;
1392 1477 int err;
1393 1478
1394 1479 if ((err = zone_get_state(zone, &state_num)) != Z_OK) {
1395 1480 /* all states are greater than "non-existent" */
1396 1481 if (err == Z_NO_ZONE)
1397 1482 return (B_FALSE);
1398 1483 zerr(gettext("Unexpectedly failed to determine state "
1399 1484 "of zone %s: %s"), zone, zonecfg_strerror(err));
1400 1485 exit(Z_ERR);
1401 1486 }
1402 1487 return (state_num >= state);
1403 1488 }
1404 1489
1405 1490 /*
1406 1491 * short_usage() is for bad syntax: getopt() issues, too many arguments, etc.
1407 1492 */
1408 1493
1409 1494 void
1410 1495 short_usage(int command)
1411 1496 {
1412 1497 /* lex_lineno has already been incremented in the lexer; compensate */
1413 1498 if (cmd_file_mode) {
1414 1499 if (strcmp(cmd_file_name, "-") == 0)
1415 1500 (void) fprintf(stderr,
1416 1501 gettext("syntax error on line %d\n"),
1417 1502 lex_lineno - 1);
1418 1503 else
1419 1504 (void) fprintf(stderr,
1420 1505 gettext("syntax error on line %d of %s\n"),
1421 1506 lex_lineno - 1, cmd_file_name);
1422 1507 }
1423 1508 (void) fprintf(stderr, "%s:\n%s\n", gettext("usage"),
1424 1509 helptab[command].short_usage);
1425 1510 saw_error = B_TRUE;
1426 1511 }
1427 1512
1428 1513 /*
1429 1514 * long_usage() is for bad semantics: e.g., wrong property type for a given
1430 1515 * resource type. It is also used by longer_usage() below.
1431 1516 */
1432 1517
1433 1518 void
1434 1519 long_usage(uint_t cmd_num, boolean_t set_saw)
1435 1520 {
1436 1521 (void) fprintf(set_saw ? stderr : stdout, "%s:\n%s\n", gettext("usage"),
1437 1522 helptab[cmd_num].short_usage);
1438 1523 (void) fprintf(set_saw ? stderr : stdout, "\t%s\n", long_help(cmd_num));
1439 1524 if (set_saw)
1440 1525 saw_error = B_TRUE;
1441 1526 }
1442 1527
1443 1528 /*
1444 1529 * longer_usage() is for 'help foo' and 'foo -?': call long_usage() and also
1445 1530 * any extra usage() flags as appropriate for whatever command.
1446 1531 */
1447 1532
1448 1533 void
1449 1534 longer_usage(uint_t cmd_num)
1450 1535 {
1451 1536 long_usage(cmd_num, B_FALSE);
1452 1537 if (helptab[cmd_num].flags != 0) {
1453 1538 (void) printf("\n");
1454 1539 usage(B_TRUE, helptab[cmd_num].flags);
1455 1540 }
1456 1541 }
1457 1542
1458 1543 /*
1459 1544 * scope_usage() is simply used when a command is called from the wrong scope.
1460 1545 */
1461 1546
1462 1547 static void
1463 1548 scope_usage(uint_t cmd_num)
1464 1549 {
1465 1550 zerr(gettext("The %s command only makes sense in the %s scope."),
1466 1551 cmd_to_str(cmd_num),
1467 1552 global_scope ? gettext("resource") : gettext("global"));
1468 1553 saw_error = B_TRUE;
1469 1554 }
1470 1555
1471 1556 /*
1472 1557 * On input, B_TRUE => yes, B_FALSE => no.
1473 1558 * On return, B_TRUE => 1, B_FALSE => no, could not ask => -1.
1474 1559 */
1475 1560
1476 1561 static int
1477 1562 ask_yesno(boolean_t default_answer, const char *question)
1478 1563 {
1479 1564 char line[64]; /* should be enough to answer yes or no */
1480 1565
1481 1566 if (!ok_to_prompt) {
1482 1567 saw_error = B_TRUE;
1483 1568 return (-1);
1484 1569 }
1485 1570 for (;;) {
1486 1571 if (printf("%s (%s)? ", question,
1487 1572 default_answer ? "[y]/n" : "y/[n]") < 0)
1488 1573 return (-1);
1489 1574 if (fgets(line, sizeof (line), stdin) == NULL)
1490 1575 return (-1);
1491 1576
1492 1577 if (line[0] == '\n')
1493 1578 return (default_answer ? 1 : 0);
1494 1579 if (tolower(line[0]) == 'y')
1495 1580 return (1);
1496 1581 if (tolower(line[0]) == 'n')
1497 1582 return (0);
1498 1583 }
1499 1584 }
1500 1585
1501 1586 /*
1502 1587 * Prints warning if zone already exists.
1503 1588 * In interactive mode, prompts if we should continue anyway and returns Z_OK
1504 1589 * if so, Z_ERR if not. In non-interactive mode, exits with Z_ERR.
1505 1590 *
1506 1591 * Note that if a zone exists and its state is >= INSTALLED, an error message
1507 1592 * will be printed and this function will return Z_ERR regardless of mode.
1508 1593 */
1509 1594
1510 1595 static int
1511 1596 check_if_zone_already_exists(boolean_t force)
1512 1597 {
1513 1598 char line[ZONENAME_MAX + 128]; /* enough to ask a question */
1514 1599 zone_dochandle_t tmphandle;
1515 1600 int res, answer;
1516 1601
1517 1602 if ((tmphandle = zonecfg_init_handle()) == NULL) {
1518 1603 zone_perror(execname, Z_NOMEM, B_TRUE);
1519 1604 exit(Z_ERR);
1520 1605 }
1521 1606 res = zonecfg_get_handle(zone, tmphandle);
1522 1607 zonecfg_fini_handle(tmphandle);
1523 1608 if (res != Z_OK)
1524 1609 return (Z_OK);
1525 1610
1526 1611 if (state_atleast(ZONE_STATE_INSTALLED)) {
1527 1612 zerr(gettext("Zone %s already installed; %s not allowed."),
1528 1613 zone, cmd_to_str(CMD_CREATE));
1529 1614 return (Z_ERR);
1530 1615 }
1531 1616
1532 1617 if (force) {
1533 1618 (void) printf(gettext("Zone %s already exists; overwriting.\n"),
1534 1619 zone);
1535 1620 return (Z_OK);
1536 1621 }
1537 1622 (void) snprintf(line, sizeof (line),
1538 1623 gettext("Zone %s already exists; %s anyway"), zone,
1539 1624 cmd_to_str(CMD_CREATE));
1540 1625 if ((answer = ask_yesno(B_FALSE, line)) == -1) {
1541 1626 zerr(gettext("Zone exists, input not from terminal and -F not "
1542 1627 "specified:\n%s command ignored, exiting."),
1543 1628 cmd_to_str(CMD_CREATE));
1544 1629 exit(Z_ERR);
1545 1630 }
1546 1631 return (answer == 1 ? Z_OK : Z_ERR);
1547 1632 }
1548 1633
1549 1634 static boolean_t
1550 1635 zone_is_read_only(int cmd_num)
1551 1636 {
1552 1637 if (strncmp(zone, "SUNW", 4) == 0) {
1553 1638 zerr(gettext("%s: zones beginning with SUNW are read-only."),
1554 1639 zone);
1555 1640 saw_error = B_TRUE;
1556 1641 return (B_TRUE);
1557 1642 }
1558 1643 if (read_only_mode) {
1559 1644 zerr(gettext("%s: cannot %s in read-only mode."), zone,
1560 1645 cmd_to_str(cmd_num));
1561 1646 saw_error = B_TRUE;
1562 1647 return (B_TRUE);
1563 1648 }
1564 1649 return (B_FALSE);
1565 1650 }
1566 1651
1567 1652 /*
1568 1653 * Create a new configuration.
1569 1654 */
1570 1655 void
1571 1656 create_func(cmd_t *cmd)
1572 1657 {
1573 1658 int err, arg;
1574 1659 char zone_template[ZONENAME_MAX];
1575 1660 char attach_path[MAXPATHLEN];
1576 1661 zone_dochandle_t tmphandle;
1577 1662 boolean_t force = B_FALSE;
1578 1663 boolean_t attach = B_FALSE;
1579 1664 boolean_t arg_err = B_FALSE;
1580 1665
1581 1666 assert(cmd != NULL);
1582 1667
1583 1668 /* This is the default if no arguments are given. */
1584 1669 (void) strlcpy(zone_template, "SUNWdefault", sizeof (zone_template));
1585 1670
1586 1671 optind = 0;
1587 1672 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?a:bFt:"))
1588 1673 != EOF) {
1589 1674 switch (arg) {
1590 1675 case '?':
1591 1676 if (optopt == '?')
1592 1677 longer_usage(CMD_CREATE);
1593 1678 else
1594 1679 short_usage(CMD_CREATE);
1595 1680 arg_err = B_TRUE;
1596 1681 break;
1597 1682 case 'a':
1598 1683 (void) strlcpy(attach_path, optarg,
1599 1684 sizeof (attach_path));
1600 1685 attach = B_TRUE;
1601 1686 break;
1602 1687 case 'b':
1603 1688 (void) strlcpy(zone_template, "SUNWblank",
1604 1689 sizeof (zone_template));
1605 1690 break;
1606 1691 case 'F':
1607 1692 force = B_TRUE;
1608 1693 break;
1609 1694 case 't':
1610 1695 (void) strlcpy(zone_template, optarg,
1611 1696 sizeof (zone_template));
1612 1697 break;
1613 1698 default:
1614 1699 short_usage(CMD_CREATE);
1615 1700 arg_err = B_TRUE;
1616 1701 break;
1617 1702 }
1618 1703 }
1619 1704 if (arg_err)
1620 1705 return;
1621 1706
1622 1707 if (optind != cmd->cmd_argc) {
1623 1708 short_usage(CMD_CREATE);
1624 1709 return;
1625 1710 }
1626 1711
1627 1712 if (zone_is_read_only(CMD_CREATE))
1628 1713 return;
1629 1714
1630 1715 if (check_if_zone_already_exists(force) != Z_OK)
1631 1716 return;
1632 1717
1633 1718 /*
1634 1719 * Get a temporary handle first. If that fails, the old handle
1635 1720 * will not be lost. Then finish whichever one we don't need,
1636 1721 * to avoid leaks. Then get the handle for zone_template, and
1637 1722 * set the name to zone: this "copy, rename" method is how
1638 1723 * create -[b|t] works.
1639 1724 */
1640 1725 if ((tmphandle = zonecfg_init_handle()) == NULL) {
1641 1726 zone_perror(execname, Z_NOMEM, B_TRUE);
1642 1727 exit(Z_ERR);
1643 1728 }
1644 1729
1645 1730 if (attach)
1646 1731 err = zonecfg_get_attach_handle(attach_path, ZONE_DETACHED,
1647 1732 zone, B_FALSE, tmphandle);
1648 1733 else
1649 1734 err = zonecfg_get_template_handle(zone_template, zone,
1650 1735 tmphandle);
1651 1736
1652 1737 if (err != Z_OK) {
1653 1738 zonecfg_fini_handle(tmphandle);
1654 1739 if (attach && err == Z_NO_ZONE)
1655 1740 (void) fprintf(stderr, gettext("invalid path to "
1656 1741 "detached zone\n"));
1657 1742 else if (attach && err == Z_INVALID_DOCUMENT)
1658 1743 (void) fprintf(stderr, gettext("Cannot attach to an "
1659 1744 "earlier release of the operating system\n"));
1660 1745 else
1661 1746 zone_perror(zone_template, err, B_TRUE);
1662 1747 return;
1663 1748 }
1664 1749
1665 1750 need_to_commit = B_TRUE;
1666 1751 zonecfg_fini_handle(handle);
1667 1752 handle = tmphandle;
1668 1753 got_handle = B_TRUE;
1669 1754 }
1670 1755
1671 1756 /*
1672 1757 * This malloc()'s memory, which must be freed by the caller.
1673 1758 */
1674 1759 static char *
1675 1760 quoteit(char *instr)
1676 1761 {
1677 1762 char *outstr;
1678 1763 size_t outstrsize = strlen(instr) + 3; /* 2 quotes + '\0' */
1679 1764
1680 1765 if ((outstr = malloc(outstrsize)) == NULL) {
1681 1766 zone_perror(zone, Z_NOMEM, B_FALSE);
1682 1767 exit(Z_ERR);
1683 1768 }
1684 1769 if (strchr(instr, ' ') == NULL) {
1685 1770 (void) strlcpy(outstr, instr, outstrsize);
1686 1771 return (outstr);
1687 1772 }
1688 1773 (void) snprintf(outstr, outstrsize, "\"%s\"", instr);
1689 1774 return (outstr);
1690 1775 }
1691 1776
1692 1777 static void
1693 1778 export_prop(FILE *of, int prop_num, char *prop_id)
1694 1779 {
1695 1780 char *quote_str;
1696 1781
1697 1782 if (strlen(prop_id) == 0)
1698 1783 return;
1699 1784 quote_str = quoteit(prop_id);
1700 1785 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1701 1786 pt_to_str(prop_num), quote_str);
1702 1787 free(quote_str);
1703 1788 }
1704 1789
1705 1790 void
1706 1791 export_func(cmd_t *cmd)
1707 1792 {
1708 1793 struct zone_nwiftab nwiftab;
1709 1794 struct zone_fstab fstab;
1710 1795 struct zone_devtab devtab;
1711 1796 struct zone_attrtab attrtab;
1712 1797 struct zone_rctltab rctltab;
1713 1798 struct zone_dstab dstab;
1714 1799 struct zone_psettab psettab;
1715 1800 struct zone_mcaptab mcaptab;
1716 1801 struct zone_rctlvaltab *valptr;
1717 1802 struct zone_admintab admintab;
1718 1803 int err, arg;
1719 1804 char zonepath[MAXPATHLEN], outfile[MAXPATHLEN], pool[MAXNAMELEN];
1720 1805 char bootargs[BOOTARGS_MAX];
1721 1806 char sched[MAXNAMELEN];
1722 1807 char brand[MAXNAMELEN];
1723 1808 char hostidp[HW_HOSTID_LEN];
1724 1809 char fsallowedp[ZONE_FS_ALLOWED_MAX];
1725 1810 char *limitpriv;
1726 1811 FILE *of;
1727 1812 boolean_t autoboot;
1728 1813 zone_iptype_t iptype;
1729 1814 boolean_t need_to_close = B_FALSE;
1730 1815 boolean_t arg_err = B_FALSE;
1731 1816
1732 1817 assert(cmd != NULL);
1733 1818
1734 1819 outfile[0] = '\0';
1735 1820 optind = 0;
1736 1821 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?f:")) != EOF) {
1737 1822 switch (arg) {
1738 1823 case '?':
1739 1824 if (optopt == '?')
1740 1825 longer_usage(CMD_EXPORT);
1741 1826 else
1742 1827 short_usage(CMD_EXPORT);
1743 1828 arg_err = B_TRUE;
1744 1829 break;
1745 1830 case 'f':
1746 1831 (void) strlcpy(outfile, optarg, sizeof (outfile));
1747 1832 break;
1748 1833 default:
1749 1834 short_usage(CMD_EXPORT);
1750 1835 arg_err = B_TRUE;
1751 1836 break;
1752 1837 }
1753 1838 }
1754 1839 if (arg_err)
1755 1840 return;
1756 1841
1757 1842 if (optind != cmd->cmd_argc) {
1758 1843 short_usage(CMD_EXPORT);
1759 1844 return;
1760 1845 }
1761 1846 if (strlen(outfile) == 0) {
1762 1847 of = stdout;
1763 1848 } else {
1764 1849 if ((of = fopen(outfile, "w")) == NULL) {
1765 1850 zerr(gettext("opening file %s: %s"),
1766 1851 outfile, strerror(errno));
1767 1852 goto done;
1768 1853 }
1769 1854 setbuf(of, NULL);
1770 1855 need_to_close = B_TRUE;
1771 1856 }
1772 1857
1773 1858 if ((err = initialize(B_TRUE)) != Z_OK)
1774 1859 goto done;
1775 1860
1776 1861 (void) fprintf(of, "%s -b\n", cmd_to_str(CMD_CREATE));
1777 1862
1778 1863 if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK &&
1779 1864 strlen(zonepath) > 0)
1780 1865 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1781 1866 pt_to_str(PT_ZONEPATH), zonepath);
1782 1867
1783 1868 if ((zone_get_brand(zone, brand, sizeof (brand)) == Z_OK) &&
1784 1869 (strcmp(brand, NATIVE_BRAND_NAME) != 0))
1785 1870 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1786 1871 pt_to_str(PT_BRAND), brand);
1787 1872
1788 1873 if (zonecfg_get_autoboot(handle, &autoboot) == Z_OK)
1789 1874 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1790 1875 pt_to_str(PT_AUTOBOOT), autoboot ? "true" : "false");
1791 1876
1792 1877 if (zonecfg_get_bootargs(handle, bootargs, sizeof (bootargs)) == Z_OK &&
1793 1878 strlen(bootargs) > 0) {
1794 1879 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1795 1880 pt_to_str(PT_BOOTARGS), bootargs);
1796 1881 }
1797 1882
1798 1883 if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
1799 1884 strlen(pool) > 0)
1800 1885 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1801 1886 pt_to_str(PT_POOL), pool);
1802 1887
1803 1888 if (zonecfg_get_limitpriv(handle, &limitpriv) == Z_OK &&
1804 1889 strlen(limitpriv) > 0) {
1805 1890 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1806 1891 pt_to_str(PT_LIMITPRIV), limitpriv);
1807 1892 free(limitpriv);
1808 1893 }
1809 1894
1810 1895 if (zonecfg_get_sched_class(handle, sched, sizeof (sched)) == Z_OK &&
1811 1896 strlen(sched) > 0)
1812 1897 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1813 1898 pt_to_str(PT_SCHED), sched);
1814 1899
1815 1900 if (zonecfg_get_iptype(handle, &iptype) == Z_OK) {
1816 1901 switch (iptype) {
1817 1902 case ZS_SHARED:
1818 1903 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1819 1904 pt_to_str(PT_IPTYPE), "shared");
1820 1905 break;
1821 1906 case ZS_EXCLUSIVE:
1822 1907 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1823 1908 pt_to_str(PT_IPTYPE), "exclusive");
1824 1909 break;
1825 1910 }
1826 1911 }
1827 1912
1828 1913 if (zonecfg_get_hostid(handle, hostidp, sizeof (hostidp)) == Z_OK) {
1829 1914 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1830 1915 pt_to_str(PT_HOSTID), hostidp);
1831 1916 }
1832 1917
1833 1918 if (zonecfg_get_fs_allowed(handle, fsallowedp,
1834 1919 sizeof (fsallowedp)) == Z_OK) {
1835 1920 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1836 1921 pt_to_str(PT_FS_ALLOWED), fsallowedp);
1837 1922 }
1838 1923
1839 1924 if ((err = zonecfg_setfsent(handle)) != Z_OK) {
1840 1925 zone_perror(zone, err, B_FALSE);
1841 1926 goto done;
1842 1927 }
1843 1928 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
1844 1929 zone_fsopt_t *optptr;
1845 1930
1846 1931 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1847 1932 rt_to_str(RT_FS));
1848 1933 export_prop(of, PT_DIR, fstab.zone_fs_dir);
1849 1934 export_prop(of, PT_SPECIAL, fstab.zone_fs_special);
1850 1935 export_prop(of, PT_RAW, fstab.zone_fs_raw);
1851 1936 export_prop(of, PT_TYPE, fstab.zone_fs_type);
1852 1937 for (optptr = fstab.zone_fs_options; optptr != NULL;
1853 1938 optptr = optptr->zone_fsopt_next) {
1854 1939 /*
1855 1940 * Simple property values with embedded equal signs
1856 1941 * need to be quoted to prevent the lexer from
1857 1942 * mis-parsing them as complex name=value pairs.
1858 1943 */
1859 1944 if (strchr(optptr->zone_fsopt_opt, '='))
1860 1945 (void) fprintf(of, "%s %s \"%s\"\n",
1861 1946 cmd_to_str(CMD_ADD),
1862 1947 pt_to_str(PT_OPTIONS),
1863 1948 optptr->zone_fsopt_opt);
1864 1949 else
1865 1950 (void) fprintf(of, "%s %s %s\n",
1866 1951 cmd_to_str(CMD_ADD),
1867 1952 pt_to_str(PT_OPTIONS),
1868 1953 optptr->zone_fsopt_opt);
1869 1954 }
1870 1955 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1871 1956 zonecfg_free_fs_option_list(fstab.zone_fs_options);
1872 1957 }
1873 1958 (void) zonecfg_endfsent(handle);
1874 1959
1875 1960 if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
1876 1961 zone_perror(zone, err, B_FALSE);
1877 1962 goto done;
1878 1963 }
1879 1964 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
1880 1965 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1881 1966 rt_to_str(RT_NET));
1882 1967 export_prop(of, PT_ADDRESS, nwiftab.zone_nwif_address);
1883 1968 export_prop(of, PT_ALLOWED_ADDRESS,
1884 1969 nwiftab.zone_nwif_allowed_address);
1885 1970 export_prop(of, PT_PHYSICAL, nwiftab.zone_nwif_physical);
1886 1971 export_prop(of, PT_DEFROUTER, nwiftab.zone_nwif_defrouter);
1887 1972 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1888 1973 }
1889 1974 (void) zonecfg_endnwifent(handle);
1890 1975
1891 1976 if ((err = zonecfg_setdevent(handle)) != Z_OK) {
1892 1977 zone_perror(zone, err, B_FALSE);
1893 1978 goto done;
1894 1979 }
1895 1980 while (zonecfg_getdevent(handle, &devtab) == Z_OK) {
1896 1981 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1897 1982 rt_to_str(RT_DEVICE));
1898 1983 export_prop(of, PT_MATCH, devtab.zone_dev_match);
1899 1984 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1900 1985 }
1901 1986 (void) zonecfg_enddevent(handle);
1902 1987
1903 1988 if (zonecfg_getmcapent(handle, &mcaptab) == Z_OK) {
1904 1989 char buf[128];
1905 1990
1906 1991 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1907 1992 rt_to_str(RT_MCAP));
1908 1993 bytes_to_units(mcaptab.zone_physmem_cap, buf, sizeof (buf));
1909 1994 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1910 1995 pt_to_str(PT_PHYSICAL), buf);
1911 1996 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1912 1997 }
1913 1998
1914 1999 if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
1915 2000 zone_perror(zone, err, B_FALSE);
1916 2001 goto done;
1917 2002 }
1918 2003 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
1919 2004 (void) fprintf(of, "%s rctl\n", cmd_to_str(CMD_ADD));
1920 2005 export_prop(of, PT_NAME, rctltab.zone_rctl_name);
1921 2006 for (valptr = rctltab.zone_rctl_valptr; valptr != NULL;
1922 2007 valptr = valptr->zone_rctlval_next) {
1923 2008 fprintf(of, "%s %s (%s=%s,%s=%s,%s=%s)\n",
1924 2009 cmd_to_str(CMD_ADD), pt_to_str(PT_VALUE),
1925 2010 pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
1926 2011 pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
1927 2012 pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
1928 2013 }
1929 2014 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1930 2015 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
1931 2016 }
1932 2017 (void) zonecfg_endrctlent(handle);
1933 2018
1934 2019 if ((err = zonecfg_setattrent(handle)) != Z_OK) {
1935 2020 zone_perror(zone, err, B_FALSE);
1936 2021 goto done;
1937 2022 }
1938 2023 while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
1939 2024 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1940 2025 rt_to_str(RT_ATTR));
1941 2026 export_prop(of, PT_NAME, attrtab.zone_attr_name);
1942 2027 export_prop(of, PT_TYPE, attrtab.zone_attr_type);
1943 2028 export_prop(of, PT_VALUE, attrtab.zone_attr_value);
1944 2029 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1945 2030 }
1946 2031 (void) zonecfg_endattrent(handle);
1947 2032
1948 2033 if ((err = zonecfg_setdsent(handle)) != Z_OK) {
1949 2034 zone_perror(zone, err, B_FALSE);
1950 2035 goto done;
1951 2036 }
1952 2037 while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
1953 2038 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1954 2039 rt_to_str(RT_DATASET));
1955 2040 export_prop(of, PT_NAME, dstab.zone_dataset_name);
1956 2041 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1957 2042 }
1958 2043 (void) zonecfg_enddsent(handle);
1959 2044
1960 2045 if (zonecfg_getpsetent(handle, &psettab) == Z_OK) {
1961 2046 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1962 2047 rt_to_str(RT_DCPU));
1963 2048 if (strcmp(psettab.zone_ncpu_min, psettab.zone_ncpu_max) == 0)
1964 2049 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1965 2050 pt_to_str(PT_NCPUS), psettab.zone_ncpu_max);
1966 2051 else
1967 2052 (void) fprintf(of, "%s %s=%s-%s\n", cmd_to_str(CMD_SET),
1968 2053 pt_to_str(PT_NCPUS), psettab.zone_ncpu_min,
1969 2054 psettab.zone_ncpu_max);
1970 2055 if (psettab.zone_importance[0] != '\0')
1971 2056 (void) fprintf(of, "%s %s=%s\n", cmd_to_str(CMD_SET),
1972 2057 pt_to_str(PT_IMPORTANCE), psettab.zone_importance);
1973 2058 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1974 2059 }
1975 2060
1976 2061 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
1977 2062 zone_perror(zone, err, B_FALSE);
1978 2063 goto done;
1979 2064 }
1980 2065 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
1981 2066 (void) fprintf(of, "%s %s\n", cmd_to_str(CMD_ADD),
1982 2067 rt_to_str(RT_ADMIN));
1983 2068 export_prop(of, PT_USER, admintab.zone_admin_user);
1984 2069 export_prop(of, PT_AUTHS, admintab.zone_admin_auths);
1985 2070 (void) fprintf(of, "%s\n", cmd_to_str(CMD_END));
1986 2071 }
1987 2072 (void) zonecfg_endadminent(handle);
1988 2073
1989 2074 /*
1990 2075 * There is nothing to export for pcap since this resource is just
1991 2076 * a container for an rctl alias.
1992 2077 */
1993 2078
1994 2079 done:
1995 2080 if (need_to_close)
1996 2081 (void) fclose(of);
1997 2082 }
1998 2083
1999 2084 void
2000 2085 exit_func(cmd_t *cmd)
2001 2086 {
2002 2087 int arg, answer;
2003 2088 boolean_t arg_err = B_FALSE;
2004 2089
2005 2090 optind = 0;
2006 2091 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2007 2092 switch (arg) {
2008 2093 case '?':
2009 2094 longer_usage(CMD_EXIT);
2010 2095 arg_err = B_TRUE;
2011 2096 break;
2012 2097 case 'F':
2013 2098 force_exit = B_TRUE;
2014 2099 break;
2015 2100 default:
2016 2101 short_usage(CMD_EXIT);
2017 2102 arg_err = B_TRUE;
2018 2103 break;
2019 2104 }
2020 2105 }
2021 2106 if (arg_err)
2022 2107 return;
2023 2108
2024 2109 if (optind < cmd->cmd_argc) {
2025 2110 short_usage(CMD_EXIT);
2026 2111 return;
2027 2112 }
2028 2113
2029 2114 if (global_scope || force_exit) {
2030 2115 time_to_exit = B_TRUE;
2031 2116 return;
2032 2117 }
2033 2118
2034 2119 answer = ask_yesno(B_FALSE, "Resource incomplete; really quit");
2035 2120 if (answer == -1) {
2036 2121 zerr(gettext("Resource incomplete, input "
2037 2122 "not from terminal and -F not specified:\n%s command "
2038 2123 "ignored, but exiting anyway."), cmd_to_str(CMD_EXIT));
2039 2124 exit(Z_ERR);
2040 2125 } else if (answer == 1) {
2041 2126 time_to_exit = B_TRUE;
2042 2127 }
2043 2128 /* (answer == 0) => just return */
2044 2129 }
2045 2130
2046 2131 static int
2047 2132 validate_zonepath_syntax(char *path)
2048 2133 {
2049 2134 if (path[0] != '/') {
2050 2135 zerr(gettext("%s is not an absolute path."), path);
2051 2136 return (Z_ERR);
2052 2137 }
2053 2138 /* If path is all slashes, then fail */
2054 2139 if (strspn(path, "/") == strlen(path)) {
2055 2140 zerr(gettext("/ is not allowed as a %s."),
2056 2141 pt_to_str(PT_ZONEPATH));
2057 2142 return (Z_ERR);
2058 2143 }
2059 2144 return (Z_OK);
2060 2145 }
2061 2146
2062 2147 static void
2063 2148 add_resource(cmd_t *cmd)
2064 2149 {
2065 2150 int type;
2066 2151 struct zone_psettab tmp_psettab;
2067 2152 struct zone_mcaptab tmp_mcaptab;
2068 2153 uint64_t tmp;
2069 2154 uint64_t tmp_mcap;
2070 2155 char pool[MAXNAMELEN];
2071 2156
2072 2157 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
2073 2158 long_usage(CMD_ADD, B_TRUE);
2074 2159 goto bad;
2075 2160 }
2076 2161
2077 2162 switch (type) {
2078 2163 case RT_FS:
2079 2164 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
2080 2165 return;
2081 2166 case RT_NET:
2082 2167 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
2083 2168 return;
2084 2169 case RT_DEVICE:
2085 2170 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
2086 2171 return;
2087 2172 case RT_RCTL:
2088 2173 if (global_zone)
2089 2174 zerr(gettext("WARNING: Setting a global zone resource "
2090 2175 "control too low could deny\nservice "
2091 2176 "to even the root user; "
2092 2177 "this could render the system impossible\n"
2093 2178 "to administer. Please use caution."));
2094 2179 bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
2095 2180 return;
2096 2181 case RT_ATTR:
2097 2182 bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
2098 2183 return;
2099 2184 case RT_DATASET:
2100 2185 bzero(&in_progress_dstab, sizeof (in_progress_dstab));
2101 2186 return;
2102 2187 case RT_DCPU:
2103 2188 /* Make sure there isn't already a cpu-set or cpu-cap entry. */
2104 2189 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
2105 2190 zerr(gettext("The %s resource already exists."),
2106 2191 rt_to_str(RT_DCPU));
2107 2192 goto bad;
2108 2193 }
2109 2194 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) !=
2110 2195 Z_NO_ENTRY) {
2111 2196 zerr(gettext("The %s resource already exists."),
2112 2197 rt_to_str(RT_PCAP));
2113 2198 goto bad;
2114 2199 }
2115 2200
2116 2201 /* Make sure the pool property isn't set. */
2117 2202 if (zonecfg_get_pool(handle, pool, sizeof (pool)) == Z_OK &&
2118 2203 strlen(pool) > 0) {
2119 2204 zerr(gettext("The %s property is already set. "
2120 2205 "A persistent pool is incompatible with\nthe %s "
2121 2206 "resource."),
2122 2207 pt_to_str(PT_POOL), rt_to_str(RT_DCPU));
2123 2208 goto bad;
2124 2209 }
2125 2210
2126 2211 bzero(&in_progress_psettab, sizeof (in_progress_psettab));
2127 2212 return;
2128 2213 case RT_PCAP:
2129 2214 /*
2130 2215 * Make sure there isn't already a cpu-set or incompatible
2131 2216 * cpu-cap rctls.
2132 2217 */
2133 2218 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
2134 2219 zerr(gettext("The %s resource already exists."),
2135 2220 rt_to_str(RT_DCPU));
2136 2221 goto bad;
2137 2222 }
2138 2223
2139 2224 switch (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp)) {
2140 2225 case Z_ALIAS_DISALLOW:
2141 2226 zone_perror(rt_to_str(RT_PCAP), Z_ALIAS_DISALLOW,
2142 2227 B_FALSE);
2143 2228 goto bad;
2144 2229
2145 2230 case Z_OK:
2146 2231 zerr(gettext("The %s resource already exists."),
2147 2232 rt_to_str(RT_PCAP));
2148 2233 goto bad;
2149 2234
2150 2235 default:
2151 2236 break;
2152 2237 }
2153 2238 return;
2154 2239 case RT_MCAP:
2155 2240 /*
2156 2241 * Make sure there isn't already a mem-cap entry or max-swap
2157 2242 * or max-locked rctl.
2158 2243 */
2159 2244 if (zonecfg_lookup_mcap(handle, &tmp_mcaptab) == Z_OK ||
2160 2245 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp_mcap)
2161 2246 == Z_OK ||
2162 2247 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
2163 2248 &tmp_mcap) == Z_OK) {
2164 2249 zerr(gettext("The %s resource or a related resource "
2165 2250 "control already exists."), rt_to_str(RT_MCAP));
2166 2251 goto bad;
2167 2252 }
2168 2253 if (global_zone)
2169 2254 zerr(gettext("WARNING: Setting a global zone memory "
2170 2255 "cap too low could deny\nservice "
2171 2256 "to even the root user; "
2172 2257 "this could render the system impossible\n"
2173 2258 "to administer. Please use caution."));
2174 2259 bzero(&in_progress_mcaptab, sizeof (in_progress_mcaptab));
2175 2260 return;
2176 2261 case RT_ADMIN:
2177 2262 bzero(&in_progress_admintab, sizeof (in_progress_admintab));
2178 2263 return;
2179 2264 default:
2180 2265 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
2181 2266 long_usage(CMD_ADD, B_TRUE);
2182 2267 usage(B_FALSE, HELP_RESOURCES);
2183 2268 }
2184 2269 bad:
2185 2270 global_scope = B_TRUE;
2186 2271 end_op = -1;
2187 2272 }
2188 2273
2189 2274 static void
2190 2275 do_complex_rctl_val(complex_property_ptr_t cp)
2191 2276 {
2192 2277 struct zone_rctlvaltab *rctlvaltab;
2193 2278 complex_property_ptr_t cx;
2194 2279 boolean_t seen_priv = B_FALSE, seen_limit = B_FALSE,
2195 2280 seen_action = B_FALSE;
2196 2281 rctlblk_t *rctlblk;
2197 2282 int err;
2198 2283
2199 2284 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
2200 2285 zone_perror(zone, Z_NOMEM, B_TRUE);
2201 2286 exit(Z_ERR);
2202 2287 }
2203 2288 for (cx = cp; cx != NULL; cx = cx->cp_next) {
2204 2289 switch (cx->cp_type) {
2205 2290 case PT_PRIV:
2206 2291 if (seen_priv) {
2207 2292 zerr(gettext("%s already specified"),
2208 2293 pt_to_str(PT_PRIV));
2209 2294 goto bad;
2210 2295 }
2211 2296 (void) strlcpy(rctlvaltab->zone_rctlval_priv,
2212 2297 cx->cp_value,
2213 2298 sizeof (rctlvaltab->zone_rctlval_priv));
2214 2299 seen_priv = B_TRUE;
2215 2300 break;
2216 2301 case PT_LIMIT:
2217 2302 if (seen_limit) {
2218 2303 zerr(gettext("%s already specified"),
2219 2304 pt_to_str(PT_LIMIT));
2220 2305 goto bad;
2221 2306 }
2222 2307 (void) strlcpy(rctlvaltab->zone_rctlval_limit,
2223 2308 cx->cp_value,
2224 2309 sizeof (rctlvaltab->zone_rctlval_limit));
2225 2310 seen_limit = B_TRUE;
2226 2311 break;
2227 2312 case PT_ACTION:
2228 2313 if (seen_action) {
2229 2314 zerr(gettext("%s already specified"),
2230 2315 pt_to_str(PT_ACTION));
2231 2316 goto bad;
2232 2317 }
2233 2318 (void) strlcpy(rctlvaltab->zone_rctlval_action,
2234 2319 cx->cp_value,
2235 2320 sizeof (rctlvaltab->zone_rctlval_action));
2236 2321 seen_action = B_TRUE;
2237 2322 break;
2238 2323 default:
2239 2324 zone_perror(pt_to_str(PT_VALUE),
2240 2325 Z_NO_PROPERTY_TYPE, B_TRUE);
2241 2326 long_usage(CMD_ADD, B_TRUE);
2242 2327 usage(B_FALSE, HELP_PROPS);
2243 2328 zonecfg_free_rctl_value_list(rctlvaltab);
2244 2329 return;
2245 2330 }
2246 2331 }
2247 2332 if (!seen_priv)
2248 2333 zerr(gettext("%s not specified"), pt_to_str(PT_PRIV));
2249 2334 if (!seen_limit)
2250 2335 zerr(gettext("%s not specified"), pt_to_str(PT_LIMIT));
2251 2336 if (!seen_action)
2252 2337 zerr(gettext("%s not specified"), pt_to_str(PT_ACTION));
2253 2338 if (!seen_priv || !seen_limit || !seen_action)
2254 2339 goto bad;
2255 2340 rctlvaltab->zone_rctlval_next = NULL;
2256 2341 rctlblk = alloca(rctlblk_size());
2257 2342 /*
2258 2343 * Make sure the rctl value looks roughly correct; we won't know if
2259 2344 * it's truly OK until we verify the configuration on the target
2260 2345 * system.
2261 2346 */
2262 2347 if (zonecfg_construct_rctlblk(rctlvaltab, rctlblk) != Z_OK ||
2263 2348 !zonecfg_valid_rctlblk(rctlblk)) {
2264 2349 zerr(gettext("Invalid %s %s specification"), rt_to_str(RT_RCTL),
2265 2350 pt_to_str(PT_VALUE));
2266 2351 goto bad;
2267 2352 }
2268 2353 err = zonecfg_add_rctl_value(&in_progress_rctltab, rctlvaltab);
2269 2354 if (err != Z_OK)
2270 2355 zone_perror(pt_to_str(PT_VALUE), err, B_TRUE);
2271 2356 return;
2272 2357
2273 2358 bad:
2274 2359 zonecfg_free_rctl_value_list(rctlvaltab);
2275 2360 }
2276 2361
2277 2362 static void
2278 2363 add_property(cmd_t *cmd)
2279 2364 {
2280 2365 char *prop_id;
2281 2366 int err, res_type, prop_type;
2282 2367 property_value_ptr_t pp;
2283 2368 list_property_ptr_t l;
2284 2369
2285 2370 res_type = resource_scope;
2286 2371 prop_type = cmd->cmd_prop_name[0];
2287 2372 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
2288 2373 long_usage(CMD_ADD, B_TRUE);
2289 2374 return;
2290 2375 }
2291 2376
2292 2377 if (cmd->cmd_prop_nv_pairs != 1) {
2293 2378 long_usage(CMD_ADD, B_TRUE);
2294 2379 return;
2295 2380 }
2296 2381
2297 2382 if (initialize(B_TRUE) != Z_OK)
2298 2383 return;
2299 2384
2300 2385 switch (res_type) {
2301 2386 case RT_FS:
2302 2387 if (prop_type != PT_OPTIONS) {
2303 2388 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2304 2389 B_TRUE);
2305 2390 long_usage(CMD_ADD, B_TRUE);
2306 2391 usage(B_FALSE, HELP_PROPS);
2307 2392 return;
2308 2393 }
2309 2394 pp = cmd->cmd_property_ptr[0];
2310 2395 if (pp->pv_type != PROP_VAL_SIMPLE &&
2311 2396 pp->pv_type != PROP_VAL_LIST) {
2312 2397 zerr(gettext("A %s or %s value was expected here."),
2313 2398 pvt_to_str(PROP_VAL_SIMPLE),
2314 2399 pvt_to_str(PROP_VAL_LIST));
2315 2400 saw_error = B_TRUE;
2316 2401 return;
2317 2402 }
2318 2403 if (pp->pv_type == PROP_VAL_SIMPLE) {
2319 2404 if (pp->pv_simple == NULL) {
2320 2405 long_usage(CMD_ADD, B_TRUE);
2321 2406 return;
2322 2407 }
2323 2408 prop_id = pp->pv_simple;
2324 2409 err = zonecfg_add_fs_option(&in_progress_fstab,
2325 2410 prop_id);
2326 2411 if (err != Z_OK)
2327 2412 zone_perror(pt_to_str(prop_type), err, B_TRUE);
2328 2413 } else {
2329 2414 list_property_ptr_t list;
2330 2415
2331 2416 for (list = pp->pv_list; list != NULL;
2332 2417 list = list->lp_next) {
2333 2418 prop_id = list->lp_simple;
2334 2419 if (prop_id == NULL)
2335 2420 break;
2336 2421 err = zonecfg_add_fs_option(
2337 2422 &in_progress_fstab, prop_id);
2338 2423 if (err != Z_OK)
2339 2424 zone_perror(pt_to_str(prop_type), err,
2340 2425 B_TRUE);
2341 2426 }
2342 2427 }
2343 2428 return;
2344 2429 case RT_RCTL:
2345 2430 if (prop_type != PT_VALUE) {
2346 2431 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
2347 2432 B_TRUE);
2348 2433 long_usage(CMD_ADD, B_TRUE);
2349 2434 usage(B_FALSE, HELP_PROPS);
2350 2435 return;
2351 2436 }
2352 2437 pp = cmd->cmd_property_ptr[0];
2353 2438 if (pp->pv_type != PROP_VAL_COMPLEX &&
2354 2439 pp->pv_type != PROP_VAL_LIST) {
2355 2440 zerr(gettext("A %s or %s value was expected here."),
2356 2441 pvt_to_str(PROP_VAL_COMPLEX),
2357 2442 pvt_to_str(PROP_VAL_LIST));
2358 2443 saw_error = B_TRUE;
2359 2444 return;
2360 2445 }
2361 2446 if (pp->pv_type == PROP_VAL_COMPLEX) {
2362 2447 do_complex_rctl_val(pp->pv_complex);
2363 2448 return;
2364 2449 }
2365 2450 for (l = pp->pv_list; l != NULL; l = l->lp_next)
2366 2451 do_complex_rctl_val(l->lp_complex);
2367 2452 return;
2368 2453 default:
2369 2454 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
2370 2455 long_usage(CMD_ADD, B_TRUE);
2371 2456 usage(B_FALSE, HELP_RESOURCES);
2372 2457 return;
2373 2458 }
2374 2459 }
2375 2460
2376 2461 static boolean_t
2377 2462 gz_invalid_resource(int type)
2378 2463 {
2379 2464 return (global_zone && (type == RT_FS ||
2380 2465 type == RT_NET || type == RT_DEVICE || type == RT_ATTR ||
2381 2466 type == RT_DATASET));
2382 2467 }
2383 2468
2384 2469 static boolean_t
2385 2470 gz_invalid_rt_property(int type)
2386 2471 {
2387 2472 return (global_zone && (type == RT_ZONENAME || type == RT_ZONEPATH ||
2388 2473 type == RT_AUTOBOOT || type == RT_LIMITPRIV ||
2389 2474 type == RT_BOOTARGS || type == RT_BRAND || type == RT_SCHED ||
2390 2475 type == RT_IPTYPE || type == RT_HOSTID || type == RT_FS_ALLOWED));
2391 2476 }
2392 2477
2393 2478 static boolean_t
2394 2479 gz_invalid_property(int type)
2395 2480 {
2396 2481 return (global_zone && (type == PT_ZONENAME || type == PT_ZONEPATH ||
2397 2482 type == PT_AUTOBOOT || type == PT_LIMITPRIV ||
2398 2483 type == PT_BOOTARGS || type == PT_BRAND || type == PT_SCHED ||
2399 2484 type == PT_IPTYPE || type == PT_HOSTID || type == PT_FS_ALLOWED));
2400 2485 }
2401 2486
2402 2487 void
2403 2488 add_func(cmd_t *cmd)
2404 2489 {
2405 2490 int arg;
2406 2491 boolean_t arg_err = B_FALSE;
2407 2492
2408 2493 assert(cmd != NULL);
2409 2494
2410 2495 optind = 0;
2411 2496 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
2412 2497 switch (arg) {
2413 2498 case '?':
2414 2499 longer_usage(CMD_ADD);
2415 2500 arg_err = B_TRUE;
2416 2501 break;
2417 2502 default:
2418 2503 short_usage(CMD_ADD);
2419 2504 arg_err = B_TRUE;
2420 2505 break;
2421 2506 }
2422 2507 }
2423 2508 if (arg_err)
2424 2509 return;
2425 2510
2426 2511 if (optind != cmd->cmd_argc) {
2427 2512 short_usage(CMD_ADD);
2428 2513 return;
2429 2514 }
2430 2515
2431 2516 if (zone_is_read_only(CMD_ADD))
2432 2517 return;
2433 2518
2434 2519 if (initialize(B_TRUE) != Z_OK)
2435 2520 return;
2436 2521 if (global_scope) {
2437 2522 if (gz_invalid_resource(cmd->cmd_res_type)) {
2438 2523 zerr(gettext("Cannot add a %s resource to the "
2439 2524 "global zone."), rt_to_str(cmd->cmd_res_type));
2440 2525 saw_error = B_TRUE;
2441 2526 return;
2442 2527 }
2443 2528
2444 2529 global_scope = B_FALSE;
2445 2530 resource_scope = cmd->cmd_res_type;
2446 2531 end_op = CMD_ADD;
2447 2532 add_resource(cmd);
2448 2533 } else
2449 2534 add_property(cmd);
2450 2535 }
2451 2536
2452 2537 /*
2453 2538 * This routine has an unusual implementation, because it tries very
2454 2539 * hard to succeed in the face of a variety of failure modes.
2455 2540 * The most common and most vexing occurs when the index file and
2456 2541 * the /etc/zones/<zonename.xml> file are not both present. In
2457 2542 * this case, delete must eradicate as much of the zone state as is left
2458 2543 * so that the user can later create a new zone with the same name.
2459 2544 */
2460 2545 void
2461 2546 delete_func(cmd_t *cmd)
2462 2547 {
2463 2548 int err, arg, answer;
2464 2549 char line[ZONENAME_MAX + 128]; /* enough to ask a question */
2465 2550 boolean_t force = B_FALSE;
2466 2551 boolean_t arg_err = B_FALSE;
2467 2552
2468 2553 optind = 0;
2469 2554 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
2470 2555 switch (arg) {
2471 2556 case '?':
2472 2557 longer_usage(CMD_DELETE);
2473 2558 arg_err = B_TRUE;
2474 2559 break;
2475 2560 case 'F':
2476 2561 force = B_TRUE;
2477 2562 break;
2478 2563 default:
2479 2564 short_usage(CMD_DELETE);
2480 2565 arg_err = B_TRUE;
2481 2566 break;
2482 2567 }
2483 2568 }
2484 2569 if (arg_err)
2485 2570 return;
2486 2571
2487 2572 if (optind != cmd->cmd_argc) {
2488 2573 short_usage(CMD_DELETE);
2489 2574 return;
2490 2575 }
2491 2576
2492 2577 if (zone_is_read_only(CMD_DELETE))
2493 2578 return;
2494 2579
2495 2580 if (!force) {
2496 2581 /*
2497 2582 * Initialize sets up the global called "handle" and warns the
2498 2583 * user if the zone is not configured. In force mode, we don't
2499 2584 * trust that evaluation, and hence skip it. (We don't need the
2500 2585 * handle to be loaded anyway, since zonecfg_destroy is done by
2501 2586 * zonename). However, we also have to take care to emulate the
2502 2587 * messages spit out by initialize; see below.
2503 2588 */
2504 2589 if (initialize(B_TRUE) != Z_OK)
2505 2590 return;
2506 2591
2507 2592 (void) snprintf(line, sizeof (line),
2508 2593 gettext("Are you sure you want to delete zone %s"), zone);
2509 2594 if ((answer = ask_yesno(B_FALSE, line)) == -1) {
2510 2595 zerr(gettext("Input not from terminal and -F not "
2511 2596 "specified:\n%s command ignored, exiting."),
2512 2597 cmd_to_str(CMD_DELETE));
2513 2598 exit(Z_ERR);
2514 2599 }
2515 2600 if (answer != 1)
2516 2601 return;
2517 2602 }
2518 2603
2519 2604 /*
2520 2605 * This function removes the authorizations from user_attr
2521 2606 * that correspond to those specified in the configuration
2522 2607 */
2523 2608 if (initialize(B_TRUE) == Z_OK) {
2524 2609 (void) zonecfg_deauthorize_users(handle, zone);
2525 2610 }
2526 2611 if ((err = zonecfg_destroy(zone, force)) != Z_OK) {
2527 2612 if ((err == Z_BAD_ZONE_STATE) && !force) {
2528 2613 zerr(gettext("Zone %s not in %s state; %s not "
2529 2614 "allowed. Use -F to force %s."),
2530 2615 zone, zone_state_str(ZONE_STATE_CONFIGURED),
2531 2616 cmd_to_str(CMD_DELETE), cmd_to_str(CMD_DELETE));
2532 2617 } else {
2533 2618 zone_perror(zone, err, B_TRUE);
2534 2619 }
2535 2620 }
2536 2621 need_to_commit = B_FALSE;
2537 2622
2538 2623 /*
2539 2624 * Emulate initialize's messaging; if there wasn't a valid handle to
2540 2625 * begin with, then user had typed delete (or delete -F) multiple
2541 2626 * times. So we emit a message.
2542 2627 *
2543 2628 * We only do this in the 'force' case because normally, initialize()
2544 2629 * takes care of this for us.
2545 2630 */
2546 2631 if (force && zonecfg_check_handle(handle) != Z_OK && interactive_mode)
2547 2632 (void) printf(gettext("Use '%s' to begin "
2548 2633 "configuring a new zone.\n"), cmd_to_str(CMD_CREATE));
2549 2634
2550 2635 /*
2551 2636 * Time for a new handle: finish the old one off first
2552 2637 * then get a new one properly to avoid leaks.
2553 2638 */
2554 2639 if (got_handle) {
2555 2640 zonecfg_fini_handle(handle);
2556 2641 if ((handle = zonecfg_init_handle()) == NULL) {
2557 2642 zone_perror(execname, Z_NOMEM, B_TRUE);
2558 2643 exit(Z_ERR);
2559 2644 }
2560 2645 if ((err = zonecfg_get_handle(zone, handle)) != Z_OK) {
2561 2646 /* If there was no zone before, that's OK */
2562 2647 if (err != Z_NO_ZONE)
2563 2648 zone_perror(zone, err, B_TRUE);
2564 2649 got_handle = B_FALSE;
2565 2650 }
2566 2651 }
2567 2652 }
2568 2653
2569 2654 static int
2570 2655 fill_in_fstab(cmd_t *cmd, struct zone_fstab *fstab, boolean_t fill_in_only)
2571 2656 {
2572 2657 int err, i;
2573 2658 property_value_ptr_t pp;
2574 2659
2575 2660 if ((err = initialize(B_TRUE)) != Z_OK)
2576 2661 return (err);
2577 2662
2578 2663 bzero(fstab, sizeof (*fstab));
2579 2664 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2580 2665 pp = cmd->cmd_property_ptr[i];
2581 2666 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2582 2667 zerr(gettext("A simple value was expected here."));
2583 2668 saw_error = B_TRUE;
2584 2669 return (Z_INSUFFICIENT_SPEC);
2585 2670 }
2586 2671 switch (cmd->cmd_prop_name[i]) {
2587 2672 case PT_DIR:
2588 2673 (void) strlcpy(fstab->zone_fs_dir, pp->pv_simple,
2589 2674 sizeof (fstab->zone_fs_dir));
2590 2675 break;
2591 2676 case PT_SPECIAL:
2592 2677 (void) strlcpy(fstab->zone_fs_special, pp->pv_simple,
2593 2678 sizeof (fstab->zone_fs_special));
2594 2679 break;
2595 2680 case PT_RAW:
2596 2681 (void) strlcpy(fstab->zone_fs_raw, pp->pv_simple,
2597 2682 sizeof (fstab->zone_fs_raw));
2598 2683 break;
2599 2684 case PT_TYPE:
2600 2685 (void) strlcpy(fstab->zone_fs_type, pp->pv_simple,
2601 2686 sizeof (fstab->zone_fs_type));
2602 2687 break;
2603 2688 default:
2604 2689 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2605 2690 Z_NO_PROPERTY_TYPE, B_TRUE);
2606 2691 return (Z_INSUFFICIENT_SPEC);
2607 2692 }
2608 2693 }
2609 2694 if (fill_in_only)
2610 2695 return (Z_OK);
2611 2696 return (zonecfg_lookup_filesystem(handle, fstab));
2612 2697 }
2613 2698
2614 2699 static int
2615 2700 fill_in_nwiftab(cmd_t *cmd, struct zone_nwiftab *nwiftab,
2616 2701 boolean_t fill_in_only)
2617 2702 {
2618 2703 int err, i;
2619 2704 property_value_ptr_t pp;
2620 2705
2621 2706 if ((err = initialize(B_TRUE)) != Z_OK)
2622 2707 return (err);
2623 2708
2624 2709 bzero(nwiftab, sizeof (*nwiftab));
2625 2710 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2626 2711 pp = cmd->cmd_property_ptr[i];
2627 2712 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2628 2713 zerr(gettext("A simple value was expected here."));
2629 2714 saw_error = B_TRUE;
2630 2715 return (Z_INSUFFICIENT_SPEC);
2631 2716 }
2632 2717 switch (cmd->cmd_prop_name[i]) {
2633 2718 case PT_ADDRESS:
2634 2719 (void) strlcpy(nwiftab->zone_nwif_address,
2635 2720 pp->pv_simple, sizeof (nwiftab->zone_nwif_address));
2636 2721 break;
2637 2722 case PT_ALLOWED_ADDRESS:
2638 2723 (void) strlcpy(nwiftab->zone_nwif_allowed_address,
2639 2724 pp->pv_simple,
2640 2725 sizeof (nwiftab->zone_nwif_allowed_address));
2641 2726 break;
2642 2727 case PT_PHYSICAL:
2643 2728 (void) strlcpy(nwiftab->zone_nwif_physical,
2644 2729 pp->pv_simple,
2645 2730 sizeof (nwiftab->zone_nwif_physical));
2646 2731 break;
2647 2732 case PT_DEFROUTER:
2648 2733 (void) strlcpy(nwiftab->zone_nwif_defrouter,
2649 2734 pp->pv_simple,
2650 2735 sizeof (nwiftab->zone_nwif_defrouter));
2651 2736 break;
2652 2737 default:
2653 2738 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2654 2739 Z_NO_PROPERTY_TYPE, B_TRUE);
2655 2740 return (Z_INSUFFICIENT_SPEC);
2656 2741 }
2657 2742 }
2658 2743 if (fill_in_only)
2659 2744 return (Z_OK);
2660 2745 err = zonecfg_lookup_nwif(handle, nwiftab);
2661 2746 return (err);
2662 2747 }
2663 2748
2664 2749 static int
2665 2750 fill_in_devtab(cmd_t *cmd, struct zone_devtab *devtab, boolean_t fill_in_only)
2666 2751 {
2667 2752 int err, i;
2668 2753 property_value_ptr_t pp;
2669 2754
2670 2755 if ((err = initialize(B_TRUE)) != Z_OK)
2671 2756 return (err);
2672 2757
2673 2758 bzero(devtab, sizeof (*devtab));
2674 2759 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2675 2760 pp = cmd->cmd_property_ptr[i];
2676 2761 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2677 2762 zerr(gettext("A simple value was expected here."));
2678 2763 saw_error = B_TRUE;
2679 2764 return (Z_INSUFFICIENT_SPEC);
2680 2765 }
2681 2766 switch (cmd->cmd_prop_name[i]) {
2682 2767 case PT_MATCH:
2683 2768 (void) strlcpy(devtab->zone_dev_match, pp->pv_simple,
2684 2769 sizeof (devtab->zone_dev_match));
2685 2770 break;
2686 2771 default:
2687 2772 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2688 2773 Z_NO_PROPERTY_TYPE, B_TRUE);
2689 2774 return (Z_INSUFFICIENT_SPEC);
2690 2775 }
2691 2776 }
2692 2777 if (fill_in_only)
2693 2778 return (Z_OK);
2694 2779 err = zonecfg_lookup_dev(handle, devtab);
2695 2780 return (err);
2696 2781 }
2697 2782
2698 2783 static int
2699 2784 fill_in_rctltab(cmd_t *cmd, struct zone_rctltab *rctltab,
2700 2785 boolean_t fill_in_only)
2701 2786 {
2702 2787 int err, i;
2703 2788 property_value_ptr_t pp;
2704 2789
2705 2790 if ((err = initialize(B_TRUE)) != Z_OK)
2706 2791 return (err);
2707 2792
2708 2793 bzero(rctltab, sizeof (*rctltab));
2709 2794 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2710 2795 pp = cmd->cmd_property_ptr[i];
2711 2796 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2712 2797 zerr(gettext("A simple value was expected here."));
2713 2798 saw_error = B_TRUE;
2714 2799 return (Z_INSUFFICIENT_SPEC);
2715 2800 }
2716 2801 switch (cmd->cmd_prop_name[i]) {
2717 2802 case PT_NAME:
2718 2803 (void) strlcpy(rctltab->zone_rctl_name, pp->pv_simple,
2719 2804 sizeof (rctltab->zone_rctl_name));
2720 2805 break;
2721 2806 default:
2722 2807 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2723 2808 Z_NO_PROPERTY_TYPE, B_TRUE);
2724 2809 return (Z_INSUFFICIENT_SPEC);
2725 2810 }
2726 2811 }
2727 2812 if (fill_in_only)
2728 2813 return (Z_OK);
2729 2814 err = zonecfg_lookup_rctl(handle, rctltab);
2730 2815 return (err);
2731 2816 }
2732 2817
2733 2818 static int
2734 2819 fill_in_attrtab(cmd_t *cmd, struct zone_attrtab *attrtab,
2735 2820 boolean_t fill_in_only)
2736 2821 {
2737 2822 int err, i;
2738 2823 property_value_ptr_t pp;
2739 2824
2740 2825 if ((err = initialize(B_TRUE)) != Z_OK)
2741 2826 return (err);
2742 2827
2743 2828 bzero(attrtab, sizeof (*attrtab));
2744 2829 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2745 2830 pp = cmd->cmd_property_ptr[i];
2746 2831 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2747 2832 zerr(gettext("A simple value was expected here."));
2748 2833 saw_error = B_TRUE;
2749 2834 return (Z_INSUFFICIENT_SPEC);
2750 2835 }
2751 2836 switch (cmd->cmd_prop_name[i]) {
2752 2837 case PT_NAME:
2753 2838 (void) strlcpy(attrtab->zone_attr_name, pp->pv_simple,
2754 2839 sizeof (attrtab->zone_attr_name));
2755 2840 break;
2756 2841 case PT_TYPE:
2757 2842 (void) strlcpy(attrtab->zone_attr_type, pp->pv_simple,
2758 2843 sizeof (attrtab->zone_attr_type));
2759 2844 break;
2760 2845 case PT_VALUE:
2761 2846 (void) strlcpy(attrtab->zone_attr_value, pp->pv_simple,
2762 2847 sizeof (attrtab->zone_attr_value));
2763 2848 break;
2764 2849 default:
2765 2850 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2766 2851 Z_NO_PROPERTY_TYPE, B_TRUE);
2767 2852 return (Z_INSUFFICIENT_SPEC);
2768 2853 }
2769 2854 }
2770 2855 if (fill_in_only)
2771 2856 return (Z_OK);
2772 2857 err = zonecfg_lookup_attr(handle, attrtab);
2773 2858 return (err);
2774 2859 }
2775 2860
2776 2861 static int
2777 2862 fill_in_dstab(cmd_t *cmd, struct zone_dstab *dstab, boolean_t fill_in_only)
2778 2863 {
2779 2864 int err, i;
2780 2865 property_value_ptr_t pp;
2781 2866
2782 2867 if ((err = initialize(B_TRUE)) != Z_OK)
2783 2868 return (err);
2784 2869
2785 2870 dstab->zone_dataset_name[0] = '\0';
2786 2871 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2787 2872 pp = cmd->cmd_property_ptr[i];
2788 2873 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2789 2874 zerr(gettext("A simple value was expected here."));
2790 2875 saw_error = B_TRUE;
2791 2876 return (Z_INSUFFICIENT_SPEC);
2792 2877 }
2793 2878 switch (cmd->cmd_prop_name[i]) {
2794 2879 case PT_NAME:
2795 2880 (void) strlcpy(dstab->zone_dataset_name, pp->pv_simple,
2796 2881 sizeof (dstab->zone_dataset_name));
2797 2882 break;
2798 2883 default:
2799 2884 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2800 2885 Z_NO_PROPERTY_TYPE, B_TRUE);
2801 2886 return (Z_INSUFFICIENT_SPEC);
2802 2887 }
2803 2888 }
2804 2889 if (fill_in_only)
2805 2890 return (Z_OK);
2806 2891 return (zonecfg_lookup_ds(handle, dstab));
2807 2892 }
2808 2893
2809 2894 static int
2810 2895 fill_in_admintab(cmd_t *cmd, struct zone_admintab *admintab,
2811 2896 boolean_t fill_in_only)
2812 2897 {
2813 2898 int err, i;
2814 2899 property_value_ptr_t pp;
2815 2900
2816 2901 if ((err = initialize(B_TRUE)) != Z_OK)
2817 2902 return (err);
2818 2903
2819 2904 bzero(admintab, sizeof (*admintab));
2820 2905 for (i = 0; i < cmd->cmd_prop_nv_pairs; i++) {
2821 2906 pp = cmd->cmd_property_ptr[i];
2822 2907 if (pp->pv_type != PROP_VAL_SIMPLE || pp->pv_simple == NULL) {
2823 2908 zerr(gettext("A simple value was expected here."));
2824 2909 saw_error = B_TRUE;
2825 2910 return (Z_INSUFFICIENT_SPEC);
2826 2911 }
2827 2912 switch (cmd->cmd_prop_name[i]) {
2828 2913 case PT_USER:
2829 2914 (void) strlcpy(admintab->zone_admin_user, pp->pv_simple,
2830 2915 sizeof (admintab->zone_admin_user));
2831 2916 break;
2832 2917 case PT_AUTHS:
2833 2918 (void) strlcpy(admintab->zone_admin_auths,
2834 2919 pp->pv_simple, sizeof (admintab->zone_admin_auths));
2835 2920 break;
2836 2921 default:
2837 2922 zone_perror(pt_to_str(cmd->cmd_prop_name[i]),
2838 2923 Z_NO_PROPERTY_TYPE, B_TRUE);
2839 2924 return (Z_INSUFFICIENT_SPEC);
2840 2925 }
2841 2926 }
2842 2927 if (fill_in_only)
2843 2928 return (Z_OK);
2844 2929 err = zonecfg_lookup_admin(handle, admintab);
2845 2930 return (err);
2846 2931 }
2847 2932
2848 2933 static void
2849 2934 remove_aliased_rctl(int type, char *name)
2850 2935 {
2851 2936 int err;
2852 2937 uint64_t tmp;
2853 2938
2854 2939 if ((err = zonecfg_get_aliased_rctl(handle, name, &tmp)) != Z_OK) {
2855 2940 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
2856 2941 zonecfg_strerror(err));
2857 2942 saw_error = B_TRUE;
2858 2943 return;
2859 2944 }
2860 2945 if ((err = zonecfg_rm_aliased_rctl(handle, name)) != Z_OK) {
2861 2946 zerr("%s %s: %s", cmd_to_str(CMD_CLEAR), pt_to_str(type),
2862 2947 zonecfg_strerror(err));
2863 2948 saw_error = B_TRUE;
2864 2949 } else {
2865 2950 need_to_commit = B_TRUE;
2866 2951 }
2867 2952 }
2868 2953
2869 2954 static boolean_t
2870 2955 prompt_remove_resource(cmd_t *cmd, char *rsrc)
2871 2956 {
2872 2957 int num;
2873 2958 int answer;
2874 2959 int arg;
2875 2960 boolean_t force = B_FALSE;
2876 2961 char prompt[128];
2877 2962 boolean_t arg_err = B_FALSE;
2878 2963
2879 2964 optind = 0;
2880 2965 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
2881 2966 switch (arg) {
2882 2967 case 'F':
2883 2968 force = B_TRUE;
2884 2969 break;
2885 2970 default:
2886 2971 arg_err = B_TRUE;
2887 2972 break;
2888 2973 }
2889 2974 }
2890 2975 if (arg_err)
2891 2976 return (B_FALSE);
2892 2977
2893 2978
2894 2979 num = zonecfg_num_resources(handle, rsrc);
2895 2980
2896 2981 if (num == 0) {
2897 2982 z_cmd_rt_perror(CMD_REMOVE, cmd->cmd_res_type, Z_NO_ENTRY,
2898 2983 B_TRUE);
2899 2984 return (B_FALSE);
2900 2985 }
2901 2986 if (num > 1 && !force) {
2902 2987 if (!interactive_mode) {
2903 2988 zerr(gettext("There are multiple instances of this "
2904 2989 "resource. Either qualify the resource to\n"
2905 2990 "remove a single instance or use the -F option to "
2906 2991 "remove all instances."));
2907 2992 saw_error = B_TRUE;
2908 2993 return (B_FALSE);
2909 2994 }
2910 2995 (void) snprintf(prompt, sizeof (prompt), gettext(
2911 2996 "Are you sure you want to remove ALL '%s' resources"),
2912 2997 rsrc);
2913 2998 answer = ask_yesno(B_FALSE, prompt);
2914 2999 if (answer == -1) {
2915 3000 zerr(gettext("Resource incomplete."));
2916 3001 return (B_FALSE);
2917 3002 }
2918 3003 if (answer != 1)
2919 3004 return (B_FALSE);
2920 3005 }
2921 3006 return (B_TRUE);
2922 3007 }
2923 3008
2924 3009 static void
2925 3010 remove_fs(cmd_t *cmd)
2926 3011 {
2927 3012 int err;
2928 3013
2929 3014 /* traditional, qualified fs removal */
2930 3015 if (cmd->cmd_prop_nv_pairs > 0) {
2931 3016 struct zone_fstab fstab;
2932 3017
2933 3018 if ((err = fill_in_fstab(cmd, &fstab, B_FALSE)) != Z_OK) {
2934 3019 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
2935 3020 return;
2936 3021 }
2937 3022 if ((err = zonecfg_delete_filesystem(handle, &fstab)) != Z_OK)
2938 3023 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
2939 3024 else
2940 3025 need_to_commit = B_TRUE;
2941 3026 zonecfg_free_fs_option_list(fstab.zone_fs_options);
2942 3027 return;
2943 3028 }
2944 3029
2945 3030 /*
2946 3031 * unqualified fs removal. remove all fs's but prompt if more
2947 3032 * than one.
2948 3033 */
2949 3034 if (!prompt_remove_resource(cmd, "fs"))
2950 3035 return;
2951 3036
2952 3037 if ((err = zonecfg_del_all_resources(handle, "fs")) != Z_OK)
2953 3038 z_cmd_rt_perror(CMD_REMOVE, RT_FS, err, B_TRUE);
2954 3039 else
2955 3040 need_to_commit = B_TRUE;
2956 3041 }
2957 3042
2958 3043 static void
2959 3044 remove_net(cmd_t *cmd)
2960 3045 {
2961 3046 int err;
2962 3047
2963 3048 /* traditional, qualified net removal */
2964 3049 if (cmd->cmd_prop_nv_pairs > 0) {
2965 3050 struct zone_nwiftab nwiftab;
2966 3051
2967 3052 if ((err = fill_in_nwiftab(cmd, &nwiftab, B_FALSE)) != Z_OK) {
2968 3053 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
2969 3054 return;
2970 3055 }
2971 3056 if ((err = zonecfg_delete_nwif(handle, &nwiftab)) != Z_OK)
2972 3057 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
2973 3058 else
2974 3059 need_to_commit = B_TRUE;
2975 3060 return;
2976 3061 }
2977 3062
2978 3063 /*
2979 3064 * unqualified net removal. remove all nets but prompt if more
2980 3065 * than one.
2981 3066 */
2982 3067 if (!prompt_remove_resource(cmd, "net"))
2983 3068 return;
2984 3069
2985 3070 if ((err = zonecfg_del_all_resources(handle, "net")) != Z_OK)
2986 3071 z_cmd_rt_perror(CMD_REMOVE, RT_NET, err, B_TRUE);
2987 3072 else
2988 3073 need_to_commit = B_TRUE;
2989 3074 }
2990 3075
2991 3076 static void
2992 3077 remove_device(cmd_t *cmd)
2993 3078 {
2994 3079 int err;
2995 3080
2996 3081 /* traditional, qualified device removal */
2997 3082 if (cmd->cmd_prop_nv_pairs > 0) {
2998 3083 struct zone_devtab devtab;
2999 3084
3000 3085 if ((err = fill_in_devtab(cmd, &devtab, B_FALSE)) != Z_OK) {
3001 3086 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3002 3087 return;
3003 3088 }
3004 3089 if ((err = zonecfg_delete_dev(handle, &devtab)) != Z_OK)
3005 3090 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3006 3091 else
3007 3092 need_to_commit = B_TRUE;
3008 3093 return;
3009 3094 }
3010 3095
3011 3096 /*
3012 3097 * unqualified device removal. remove all devices but prompt if more
3013 3098 * than one.
3014 3099 */
3015 3100 if (!prompt_remove_resource(cmd, "device"))
3016 3101 return;
3017 3102
3018 3103 if ((err = zonecfg_del_all_resources(handle, "device")) != Z_OK)
3019 3104 z_cmd_rt_perror(CMD_REMOVE, RT_DEVICE, err, B_TRUE);
3020 3105 else
3021 3106 need_to_commit = B_TRUE;
3022 3107 }
3023 3108
3024 3109 static void
3025 3110 remove_attr(cmd_t *cmd)
3026 3111 {
3027 3112 int err;
3028 3113
3029 3114 /* traditional, qualified attr removal */
3030 3115 if (cmd->cmd_prop_nv_pairs > 0) {
3031 3116 struct zone_attrtab attrtab;
3032 3117
3033 3118 if ((err = fill_in_attrtab(cmd, &attrtab, B_FALSE)) != Z_OK) {
3034 3119 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3035 3120 return;
3036 3121 }
3037 3122 if ((err = zonecfg_delete_attr(handle, &attrtab)) != Z_OK)
3038 3123 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3039 3124 else
3040 3125 need_to_commit = B_TRUE;
3041 3126 return;
3042 3127 }
3043 3128
3044 3129 /*
3045 3130 * unqualified attr removal. remove all attrs but prompt if more
3046 3131 * than one.
3047 3132 */
3048 3133 if (!prompt_remove_resource(cmd, "attr"))
3049 3134 return;
3050 3135
3051 3136 if ((err = zonecfg_del_all_resources(handle, "attr")) != Z_OK)
3052 3137 z_cmd_rt_perror(CMD_REMOVE, RT_ATTR, err, B_TRUE);
3053 3138 else
3054 3139 need_to_commit = B_TRUE;
3055 3140 }
3056 3141
3057 3142 static void
3058 3143 remove_dataset(cmd_t *cmd)
3059 3144 {
3060 3145 int err;
3061 3146
3062 3147 /* traditional, qualified dataset removal */
3063 3148 if (cmd->cmd_prop_nv_pairs > 0) {
3064 3149 struct zone_dstab dstab;
3065 3150
3066 3151 if ((err = fill_in_dstab(cmd, &dstab, B_FALSE)) != Z_OK) {
3067 3152 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3068 3153 return;
3069 3154 }
3070 3155 if ((err = zonecfg_delete_ds(handle, &dstab)) != Z_OK)
3071 3156 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3072 3157 else
3073 3158 need_to_commit = B_TRUE;
3074 3159 return;
3075 3160 }
3076 3161
3077 3162 /*
3078 3163 * unqualified dataset removal. remove all datasets but prompt if more
3079 3164 * than one.
3080 3165 */
3081 3166 if (!prompt_remove_resource(cmd, "dataset"))
3082 3167 return;
3083 3168
3084 3169 if ((err = zonecfg_del_all_resources(handle, "dataset")) != Z_OK)
3085 3170 z_cmd_rt_perror(CMD_REMOVE, RT_DATASET, err, B_TRUE);
3086 3171 else
3087 3172 need_to_commit = B_TRUE;
3088 3173 }
3089 3174
3090 3175 static void
3091 3176 remove_rctl(cmd_t *cmd)
3092 3177 {
3093 3178 int err;
3094 3179
3095 3180 /* traditional, qualified rctl removal */
3096 3181 if (cmd->cmd_prop_nv_pairs > 0) {
3097 3182 struct zone_rctltab rctltab;
3098 3183
3099 3184 if ((err = fill_in_rctltab(cmd, &rctltab, B_FALSE)) != Z_OK) {
3100 3185 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3101 3186 return;
3102 3187 }
3103 3188 if ((err = zonecfg_delete_rctl(handle, &rctltab)) != Z_OK)
3104 3189 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3105 3190 else
3106 3191 need_to_commit = B_TRUE;
3107 3192 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
3108 3193 return;
3109 3194 }
3110 3195
3111 3196 /*
3112 3197 * unqualified rctl removal. remove all rctls but prompt if more
3113 3198 * than one.
3114 3199 */
3115 3200 if (!prompt_remove_resource(cmd, "rctl"))
3116 3201 return;
3117 3202
3118 3203 if ((err = zonecfg_del_all_resources(handle, "rctl")) != Z_OK)
3119 3204 z_cmd_rt_perror(CMD_REMOVE, RT_RCTL, err, B_TRUE);
3120 3205 else
3121 3206 need_to_commit = B_TRUE;
3122 3207 }
3123 3208
3124 3209 static void
3125 3210 remove_pset()
3126 3211 {
3127 3212 int err;
3128 3213 struct zone_psettab psettab;
3129 3214
3130 3215 if ((err = zonecfg_lookup_pset(handle, &psettab)) != Z_OK) {
3131 3216 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3132 3217 return;
3133 3218 }
3134 3219 if ((err = zonecfg_delete_pset(handle)) != Z_OK)
3135 3220 z_cmd_rt_perror(CMD_REMOVE, RT_DCPU, err, B_TRUE);
3136 3221 else
3137 3222 need_to_commit = B_TRUE;
3138 3223 }
3139 3224
3140 3225 static void
3141 3226 remove_pcap()
3142 3227 {
3143 3228 int err;
3144 3229 uint64_t tmp;
3145 3230
3146 3231 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp) != Z_OK) {
3147 3232 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_PCAP),
3148 3233 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3149 3234 saw_error = B_TRUE;
3150 3235 return;
3151 3236 }
3152 3237
3153 3238 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_CPUCAP)) != Z_OK)
3154 3239 z_cmd_rt_perror(CMD_REMOVE, RT_PCAP, err, B_TRUE);
3155 3240 else
3156 3241 need_to_commit = B_TRUE;
3157 3242 }
3158 3243
3159 3244 static void
3160 3245 remove_mcap()
3161 3246 {
3162 3247 int err, res1, res2, res3;
3163 3248 uint64_t tmp;
3164 3249 struct zone_mcaptab mcaptab;
3165 3250 boolean_t revert = B_FALSE;
3166 3251
3167 3252 res1 = zonecfg_lookup_mcap(handle, &mcaptab);
3168 3253 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &tmp);
3169 3254 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &tmp);
3170 3255
3171 3256 /* if none of these exist, there is no resource to remove */
3172 3257 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
3173 3258 zerr("%s %s: %s", cmd_to_str(CMD_REMOVE), rt_to_str(RT_MCAP),
3174 3259 zonecfg_strerror(Z_NO_RESOURCE_TYPE));
3175 3260 saw_error = B_TRUE;
3176 3261 return;
3177 3262 }
3178 3263 if (res1 == Z_OK) {
3179 3264 if ((err = zonecfg_delete_mcap(handle)) != Z_OK) {
3180 3265 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3181 3266 revert = B_TRUE;
3182 3267 } else {
3183 3268 need_to_commit = B_TRUE;
3184 3269 }
3185 3270 }
3186 3271 if (res2 == Z_OK) {
3187 3272 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXSWAP))
3188 3273 != Z_OK) {
3189 3274 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3190 3275 revert = B_TRUE;
3191 3276 } else {
3192 3277 need_to_commit = B_TRUE;
3193 3278 }
3194 3279 }
3195 3280 if (res3 == Z_OK) {
3196 3281 if ((err = zonecfg_rm_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM))
3197 3282 != Z_OK) {
3198 3283 z_cmd_rt_perror(CMD_REMOVE, RT_MCAP, err, B_TRUE);
3199 3284 revert = B_TRUE;
3200 3285 } else {
3201 3286 need_to_commit = B_TRUE;
3202 3287 }
3203 3288 }
3204 3289
3205 3290 if (revert)
3206 3291 need_to_commit = B_FALSE;
3207 3292 }
3208 3293
3209 3294 static void
3210 3295 remove_admin(cmd_t *cmd)
3211 3296 {
3212 3297 int err;
3213 3298
3214 3299 /* traditional, qualified attr removal */
3215 3300 if (cmd->cmd_prop_nv_pairs > 0) {
3216 3301 struct zone_admintab admintab;
3217 3302
3218 3303 if ((err = fill_in_admintab(cmd, &admintab, B_FALSE)) != Z_OK) {
3219 3304 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3220 3305 err, B_TRUE);
3221 3306 return;
3222 3307 }
3223 3308 if ((err = zonecfg_delete_admin(handle, &admintab,
3224 3309 zone))
3225 3310 != Z_OK)
3226 3311 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3227 3312 err, B_TRUE);
3228 3313 else
3229 3314 need_to_commit = B_TRUE;
3230 3315 return;
3231 3316 } else {
3232 3317 /*
3233 3318 * unqualified admin removal.
3234 3319 * remove all admins but prompt if more
3235 3320 * than one.
3236 3321 */
3237 3322 if (!prompt_remove_resource(cmd, "admin"))
3238 3323 return;
3239 3324
3240 3325 if ((err = zonecfg_delete_admins(handle, zone))
3241 3326 != Z_OK)
3242 3327 z_cmd_rt_perror(CMD_REMOVE, RT_ADMIN,
3243 3328 err, B_TRUE);
3244 3329 else
3245 3330 need_to_commit = B_TRUE;
3246 3331 }
3247 3332 }
3248 3333
3249 3334 static void
3250 3335 remove_resource(cmd_t *cmd)
3251 3336 {
3252 3337 int type;
3253 3338 int arg;
3254 3339 boolean_t arg_err = B_FALSE;
3255 3340
3256 3341 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3257 3342 long_usage(CMD_REMOVE, B_TRUE);
3258 3343 return;
3259 3344 }
3260 3345
3261 3346 optind = 0;
3262 3347 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
3263 3348 switch (arg) {
3264 3349 case '?':
3265 3350 longer_usage(CMD_REMOVE);
3266 3351 arg_err = B_TRUE;
3267 3352 break;
3268 3353 case 'F':
3269 3354 break;
3270 3355 default:
3271 3356 short_usage(CMD_REMOVE);
3272 3357 arg_err = B_TRUE;
3273 3358 break;
3274 3359 }
3275 3360 }
3276 3361 if (arg_err)
3277 3362 return;
3278 3363
3279 3364 if (initialize(B_TRUE) != Z_OK)
3280 3365 return;
3281 3366
3282 3367 switch (type) {
3283 3368 case RT_FS:
3284 3369 remove_fs(cmd);
3285 3370 return;
3286 3371 case RT_NET:
3287 3372 remove_net(cmd);
3288 3373 return;
3289 3374 case RT_DEVICE:
3290 3375 remove_device(cmd);
3291 3376 return;
3292 3377 case RT_RCTL:
3293 3378 remove_rctl(cmd);
3294 3379 return;
3295 3380 case RT_ATTR:
3296 3381 remove_attr(cmd);
3297 3382 return;
3298 3383 case RT_DATASET:
3299 3384 remove_dataset(cmd);
3300 3385 return;
3301 3386 case RT_DCPU:
3302 3387 remove_pset();
3303 3388 return;
3304 3389 case RT_PCAP:
3305 3390 remove_pcap();
3306 3391 return;
3307 3392 case RT_MCAP:
3308 3393 remove_mcap();
3309 3394 return;
3310 3395 case RT_ADMIN:
3311 3396 remove_admin(cmd);
3312 3397 return;
3313 3398 default:
3314 3399 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3315 3400 long_usage(CMD_REMOVE, B_TRUE);
3316 3401 usage(B_FALSE, HELP_RESOURCES);
3317 3402 return;
3318 3403 }
3319 3404 }
3320 3405
3321 3406 static void
3322 3407 remove_property(cmd_t *cmd)
3323 3408 {
3324 3409 char *prop_id;
3325 3410 int err, res_type, prop_type;
3326 3411 property_value_ptr_t pp;
3327 3412 struct zone_rctlvaltab *rctlvaltab;
3328 3413 complex_property_ptr_t cx;
3329 3414
3330 3415 res_type = resource_scope;
3331 3416 prop_type = cmd->cmd_prop_name[0];
3332 3417 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3333 3418 long_usage(CMD_REMOVE, B_TRUE);
3334 3419 return;
3335 3420 }
3336 3421
3337 3422 if (cmd->cmd_prop_nv_pairs != 1) {
3338 3423 long_usage(CMD_ADD, B_TRUE);
3339 3424 return;
3340 3425 }
3341 3426
3342 3427 if (initialize(B_TRUE) != Z_OK)
3343 3428 return;
3344 3429
3345 3430 switch (res_type) {
3346 3431 case RT_FS:
3347 3432 if (prop_type != PT_OPTIONS) {
3348 3433 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3349 3434 B_TRUE);
3350 3435 long_usage(CMD_REMOVE, B_TRUE);
3351 3436 usage(B_FALSE, HELP_PROPS);
3352 3437 return;
3353 3438 }
3354 3439 pp = cmd->cmd_property_ptr[0];
3355 3440 if (pp->pv_type == PROP_VAL_COMPLEX) {
3356 3441 zerr(gettext("A %s or %s value was expected here."),
3357 3442 pvt_to_str(PROP_VAL_SIMPLE),
3358 3443 pvt_to_str(PROP_VAL_LIST));
3359 3444 saw_error = B_TRUE;
3360 3445 return;
3361 3446 }
3362 3447 if (pp->pv_type == PROP_VAL_SIMPLE) {
3363 3448 if (pp->pv_simple == NULL) {
3364 3449 long_usage(CMD_ADD, B_TRUE);
3365 3450 return;
3366 3451 }
3367 3452 prop_id = pp->pv_simple;
3368 3453 err = zonecfg_remove_fs_option(&in_progress_fstab,
3369 3454 prop_id);
3370 3455 if (err != Z_OK)
3371 3456 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3372 3457 } else {
3373 3458 list_property_ptr_t list;
3374 3459
3375 3460 for (list = pp->pv_list; list != NULL;
3376 3461 list = list->lp_next) {
3377 3462 prop_id = list->lp_simple;
3378 3463 if (prop_id == NULL)
3379 3464 break;
3380 3465 err = zonecfg_remove_fs_option(
3381 3466 &in_progress_fstab, prop_id);
3382 3467 if (err != Z_OK)
3383 3468 zone_perror(pt_to_str(prop_type), err,
3384 3469 B_TRUE);
3385 3470 }
3386 3471 }
3387 3472 return;
3388 3473 case RT_RCTL:
3389 3474 if (prop_type != PT_VALUE) {
3390 3475 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3391 3476 B_TRUE);
3392 3477 long_usage(CMD_REMOVE, B_TRUE);
3393 3478 usage(B_FALSE, HELP_PROPS);
3394 3479 return;
3395 3480 }
3396 3481 pp = cmd->cmd_property_ptr[0];
3397 3482 if (pp->pv_type != PROP_VAL_COMPLEX) {
3398 3483 zerr(gettext("A %s value was expected here."),
3399 3484 pvt_to_str(PROP_VAL_COMPLEX));
3400 3485 saw_error = B_TRUE;
3401 3486 return;
3402 3487 }
3403 3488 if ((rctlvaltab = alloc_rctlvaltab()) == NULL) {
3404 3489 zone_perror(zone, Z_NOMEM, B_TRUE);
3405 3490 exit(Z_ERR);
3406 3491 }
3407 3492 for (cx = pp->pv_complex; cx != NULL; cx = cx->cp_next) {
3408 3493 switch (cx->cp_type) {
3409 3494 case PT_PRIV:
3410 3495 (void) strlcpy(rctlvaltab->zone_rctlval_priv,
3411 3496 cx->cp_value,
3412 3497 sizeof (rctlvaltab->zone_rctlval_priv));
3413 3498 break;
3414 3499 case PT_LIMIT:
3415 3500 (void) strlcpy(rctlvaltab->zone_rctlval_limit,
3416 3501 cx->cp_value,
3417 3502 sizeof (rctlvaltab->zone_rctlval_limit));
3418 3503 break;
3419 3504 case PT_ACTION:
3420 3505 (void) strlcpy(rctlvaltab->zone_rctlval_action,
3421 3506 cx->cp_value,
3422 3507 sizeof (rctlvaltab->zone_rctlval_action));
3423 3508 break;
3424 3509 default:
3425 3510 zone_perror(pt_to_str(prop_type),
3426 3511 Z_NO_PROPERTY_TYPE, B_TRUE);
3427 3512 long_usage(CMD_ADD, B_TRUE);
3428 3513 usage(B_FALSE, HELP_PROPS);
3429 3514 zonecfg_free_rctl_value_list(rctlvaltab);
3430 3515 return;
3431 3516 }
3432 3517 }
3433 3518 rctlvaltab->zone_rctlval_next = NULL;
3434 3519 err = zonecfg_remove_rctl_value(&in_progress_rctltab,
3435 3520 rctlvaltab);
3436 3521 if (err != Z_OK)
3437 3522 zone_perror(pt_to_str(prop_type), err, B_TRUE);
3438 3523 zonecfg_free_rctl_value_list(rctlvaltab);
3439 3524 return;
3440 3525 case RT_NET:
3441 3526 if (prop_type != PT_DEFROUTER) {
3442 3527 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
3443 3528 B_TRUE);
3444 3529 long_usage(CMD_REMOVE, B_TRUE);
3445 3530 usage(B_FALSE, HELP_PROPS);
3446 3531 return;
3447 3532 } else {
3448 3533 bzero(&in_progress_nwiftab.zone_nwif_defrouter,
3449 3534 sizeof (in_progress_nwiftab.zone_nwif_defrouter));
3450 3535 return;
3451 3536 }
3452 3537 default:
3453 3538 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
3454 3539 long_usage(CMD_REMOVE, B_TRUE);
3455 3540 usage(B_FALSE, HELP_RESOURCES);
3456 3541 return;
3457 3542 }
3458 3543 }
3459 3544
3460 3545 void
3461 3546 remove_func(cmd_t *cmd)
3462 3547 {
3463 3548 if (zone_is_read_only(CMD_REMOVE))
3464 3549 return;
3465 3550
3466 3551 assert(cmd != NULL);
3467 3552
3468 3553 if (global_scope) {
3469 3554 if (gz_invalid_resource(cmd->cmd_res_type)) {
3470 3555 zerr(gettext("%s is not a valid resource for the "
3471 3556 "global zone."), rt_to_str(cmd->cmd_res_type));
3472 3557 saw_error = B_TRUE;
3473 3558 return;
3474 3559 }
3475 3560 remove_resource(cmd);
3476 3561 } else {
3477 3562 remove_property(cmd);
3478 3563 }
3479 3564 }
3480 3565
3481 3566 static void
3482 3567 clear_property(cmd_t *cmd)
3483 3568 {
3484 3569 int res_type, prop_type;
3485 3570
3486 3571 res_type = resource_scope;
3487 3572 prop_type = cmd->cmd_res_type;
3488 3573 if (res_type == RT_UNKNOWN || prop_type == PT_UNKNOWN) {
3489 3574 long_usage(CMD_CLEAR, B_TRUE);
3490 3575 return;
3491 3576 }
3492 3577
3493 3578 if (initialize(B_TRUE) != Z_OK)
3494 3579 return;
3495 3580
3496 3581 switch (res_type) {
3497 3582 case RT_FS:
3498 3583 if (prop_type == PT_RAW) {
3499 3584 in_progress_fstab.zone_fs_raw[0] = '\0';
3500 3585 need_to_commit = B_TRUE;
3501 3586 return;
3502 3587 }
3503 3588 break;
3504 3589 case RT_DCPU:
3505 3590 if (prop_type == PT_IMPORTANCE) {
3506 3591 in_progress_psettab.zone_importance[0] = '\0';
3507 3592 need_to_commit = B_TRUE;
3508 3593 return;
3509 3594 }
3510 3595 break;
3511 3596 case RT_MCAP:
3512 3597 switch (prop_type) {
3513 3598 case PT_PHYSICAL:
3514 3599 in_progress_mcaptab.zone_physmem_cap[0] = '\0';
3515 3600 need_to_commit = B_TRUE;
3516 3601 return;
3517 3602 case PT_SWAP:
3518 3603 remove_aliased_rctl(PT_SWAP, ALIAS_MAXSWAP);
3519 3604 return;
3520 3605 case PT_LOCKED:
3521 3606 remove_aliased_rctl(PT_LOCKED, ALIAS_MAXLOCKEDMEM);
3522 3607 return;
3523 3608 }
3524 3609 break;
3525 3610 default:
3526 3611 break;
3527 3612 }
3528 3613
3529 3614 zone_perror(pt_to_str(prop_type), Z_CLEAR_DISALLOW, B_TRUE);
3530 3615 }
3531 3616
3532 3617 static void
3533 3618 clear_global(cmd_t *cmd)
3534 3619 {
3535 3620 int err, type;
3536 3621
3537 3622 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3538 3623 long_usage(CMD_CLEAR, B_TRUE);
3539 3624 return;
3540 3625 }
3541 3626
3542 3627 if (initialize(B_TRUE) != Z_OK)
3543 3628 return;
3544 3629
3545 3630 switch (type) {
3546 3631 case PT_ZONENAME:
3547 3632 /* FALLTHRU */
3548 3633 case PT_ZONEPATH:
3549 3634 /* FALLTHRU */
3550 3635 case PT_BRAND:
3551 3636 zone_perror(pt_to_str(type), Z_CLEAR_DISALLOW, B_TRUE);
3552 3637 return;
3553 3638 case PT_AUTOBOOT:
3554 3639 /* false is default; we'll treat as equivalent to clearing */
3555 3640 if ((err = zonecfg_set_autoboot(handle, B_FALSE)) != Z_OK)
3556 3641 z_cmd_rt_perror(CMD_CLEAR, RT_AUTOBOOT, err, B_TRUE);
3557 3642 else
3558 3643 need_to_commit = B_TRUE;
3559 3644 return;
3560 3645 case PT_POOL:
3561 3646 if ((err = zonecfg_set_pool(handle, NULL)) != Z_OK)
3562 3647 z_cmd_rt_perror(CMD_CLEAR, RT_POOL, err, B_TRUE);
3563 3648 else
3564 3649 need_to_commit = B_TRUE;
3565 3650 return;
3566 3651 case PT_LIMITPRIV:
3567 3652 if ((err = zonecfg_set_limitpriv(handle, NULL)) != Z_OK)
3568 3653 z_cmd_rt_perror(CMD_CLEAR, RT_LIMITPRIV, err, B_TRUE);
3569 3654 else
3570 3655 need_to_commit = B_TRUE;
3571 3656 return;
3572 3657 case PT_BOOTARGS:
3573 3658 if ((err = zonecfg_set_bootargs(handle, NULL)) != Z_OK)
3574 3659 z_cmd_rt_perror(CMD_CLEAR, RT_BOOTARGS, err, B_TRUE);
3575 3660 else
3576 3661 need_to_commit = B_TRUE;
3577 3662 return;
3578 3663 case PT_SCHED:
3579 3664 if ((err = zonecfg_set_sched(handle, NULL)) != Z_OK)
3580 3665 z_cmd_rt_perror(CMD_CLEAR, RT_SCHED, err, B_TRUE);
3581 3666 else
3582 3667 need_to_commit = B_TRUE;
3583 3668 return;
3584 3669 case PT_IPTYPE:
3585 3670 /* shared is default; we'll treat as equivalent to clearing */
3586 3671 if ((err = zonecfg_set_iptype(handle, ZS_SHARED)) != Z_OK)
3587 3672 z_cmd_rt_perror(CMD_CLEAR, RT_IPTYPE, err, B_TRUE);
3588 3673 else
3589 3674 need_to_commit = B_TRUE;
3590 3675 return;
3591 3676 case PT_MAXLWPS:
3592 3677 remove_aliased_rctl(PT_MAXLWPS, ALIAS_MAXLWPS);
3593 3678 return;
3594 3679 case PT_MAXPROCS:
3595 3680 remove_aliased_rctl(PT_MAXPROCS, ALIAS_MAXPROCS);
3596 3681 return;
3597 3682 case PT_MAXSHMMEM:
3598 3683 remove_aliased_rctl(PT_MAXSHMMEM, ALIAS_MAXSHMMEM);
3599 3684 return;
3600 3685 case PT_MAXSHMIDS:
3601 3686 remove_aliased_rctl(PT_MAXSHMIDS, ALIAS_MAXSHMIDS);
3602 3687 return;
3603 3688 case PT_MAXMSGIDS:
3604 3689 remove_aliased_rctl(PT_MAXMSGIDS, ALIAS_MAXMSGIDS);
3605 3690 return;
3606 3691 case PT_MAXSEMIDS:
3607 3692 remove_aliased_rctl(PT_MAXSEMIDS, ALIAS_MAXSEMIDS);
3608 3693 return;
3609 3694 case PT_SHARES:
3610 3695 remove_aliased_rctl(PT_SHARES, ALIAS_SHARES);
3611 3696 return;
3612 3697 case PT_HOSTID:
3613 3698 if ((err = zonecfg_set_hostid(handle, NULL)) != Z_OK)
3614 3699 z_cmd_rt_perror(CMD_CLEAR, RT_HOSTID, err, B_TRUE);
3615 3700 else
3616 3701 need_to_commit = B_TRUE;
3617 3702 return;
3618 3703 case PT_FS_ALLOWED:
3619 3704 if ((err = zonecfg_set_fs_allowed(handle, NULL)) != Z_OK)
3620 3705 z_cmd_rt_perror(CMD_CLEAR, RT_FS_ALLOWED, err, B_TRUE);
3621 3706 else
3622 3707 need_to_commit = B_TRUE;
3623 3708 return;
3624 3709 default:
3625 3710 zone_perror(pt_to_str(type), Z_NO_PROPERTY_TYPE, B_TRUE);
3626 3711 long_usage(CMD_CLEAR, B_TRUE);
3627 3712 usage(B_FALSE, HELP_PROPS);
3628 3713 return;
3629 3714 }
3630 3715 }
3631 3716
3632 3717 void
3633 3718 clear_func(cmd_t *cmd)
3634 3719 {
3635 3720 if (zone_is_read_only(CMD_CLEAR))
3636 3721 return;
3637 3722
3638 3723 assert(cmd != NULL);
3639 3724
3640 3725 if (global_scope) {
3641 3726 if (gz_invalid_property(cmd->cmd_res_type)) {
3642 3727 zerr(gettext("%s is not a valid property for the "
3643 3728 "global zone."), pt_to_str(cmd->cmd_res_type));
3644 3729 saw_error = B_TRUE;
3645 3730 return;
3646 3731 }
3647 3732
3648 3733 clear_global(cmd);
3649 3734 } else {
3650 3735 clear_property(cmd);
3651 3736 }
3652 3737 }
3653 3738
3654 3739 void
3655 3740 select_func(cmd_t *cmd)
3656 3741 {
3657 3742 int type, err, res;
3658 3743 uint64_t limit;
3659 3744 uint64_t tmp;
3660 3745
3661 3746 if (zone_is_read_only(CMD_SELECT))
3662 3747 return;
3663 3748
3664 3749 assert(cmd != NULL);
3665 3750
3666 3751 if (global_scope) {
3667 3752 global_scope = B_FALSE;
3668 3753 resource_scope = cmd->cmd_res_type;
3669 3754 end_op = CMD_SELECT;
3670 3755 } else {
3671 3756 scope_usage(CMD_SELECT);
3672 3757 return;
3673 3758 }
3674 3759
3675 3760 if ((type = cmd->cmd_res_type) == RT_UNKNOWN) {
3676 3761 long_usage(CMD_SELECT, B_TRUE);
3677 3762 return;
3678 3763 }
3679 3764
3680 3765 if (initialize(B_TRUE) != Z_OK)
3681 3766 return;
3682 3767
3683 3768 switch (type) {
3684 3769 case RT_FS:
3685 3770 if ((err = fill_in_fstab(cmd, &old_fstab, B_FALSE)) != Z_OK) {
3686 3771 z_cmd_rt_perror(CMD_SELECT, RT_FS, err, B_TRUE);
3687 3772 global_scope = B_TRUE;
3688 3773 }
3689 3774 bcopy(&old_fstab, &in_progress_fstab,
3690 3775 sizeof (struct zone_fstab));
3691 3776 return;
3692 3777 case RT_NET:
3693 3778 if ((err = fill_in_nwiftab(cmd, &old_nwiftab, B_FALSE))
3694 3779 != Z_OK) {
3695 3780 z_cmd_rt_perror(CMD_SELECT, RT_NET, err, B_TRUE);
3696 3781 global_scope = B_TRUE;
3697 3782 }
3698 3783 bcopy(&old_nwiftab, &in_progress_nwiftab,
3699 3784 sizeof (struct zone_nwiftab));
3700 3785 return;
3701 3786 case RT_DEVICE:
3702 3787 if ((err = fill_in_devtab(cmd, &old_devtab, B_FALSE)) != Z_OK) {
3703 3788 z_cmd_rt_perror(CMD_SELECT, RT_DEVICE, err, B_TRUE);
3704 3789 global_scope = B_TRUE;
3705 3790 }
3706 3791 bcopy(&old_devtab, &in_progress_devtab,
3707 3792 sizeof (struct zone_devtab));
3708 3793 return;
3709 3794 case RT_RCTL:
3710 3795 if ((err = fill_in_rctltab(cmd, &old_rctltab, B_FALSE))
3711 3796 != Z_OK) {
3712 3797 z_cmd_rt_perror(CMD_SELECT, RT_RCTL, err, B_TRUE);
3713 3798 global_scope = B_TRUE;
3714 3799 }
3715 3800 bcopy(&old_rctltab, &in_progress_rctltab,
3716 3801 sizeof (struct zone_rctltab));
3717 3802 return;
3718 3803 case RT_ATTR:
3719 3804 if ((err = fill_in_attrtab(cmd, &old_attrtab, B_FALSE))
3720 3805 != Z_OK) {
3721 3806 z_cmd_rt_perror(CMD_SELECT, RT_ATTR, err, B_TRUE);
3722 3807 global_scope = B_TRUE;
3723 3808 }
3724 3809 bcopy(&old_attrtab, &in_progress_attrtab,
3725 3810 sizeof (struct zone_attrtab));
3726 3811 return;
3727 3812 case RT_DATASET:
3728 3813 if ((err = fill_in_dstab(cmd, &old_dstab, B_FALSE)) != Z_OK) {
3729 3814 z_cmd_rt_perror(CMD_SELECT, RT_DATASET, err, B_TRUE);
3730 3815 global_scope = B_TRUE;
3731 3816 }
3732 3817 bcopy(&old_dstab, &in_progress_dstab,
3733 3818 sizeof (struct zone_dstab));
3734 3819 return;
3735 3820 case RT_DCPU:
3736 3821 if ((err = zonecfg_lookup_pset(handle, &old_psettab)) != Z_OK) {
3737 3822 z_cmd_rt_perror(CMD_SELECT, RT_DCPU, err, B_TRUE);
3738 3823 global_scope = B_TRUE;
3739 3824 }
3740 3825 bcopy(&old_psettab, &in_progress_psettab,
3741 3826 sizeof (struct zone_psettab));
3742 3827 return;
3743 3828 case RT_PCAP:
3744 3829 if ((err = zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &tmp))
3745 3830 != Z_OK) {
3746 3831 z_cmd_rt_perror(CMD_SELECT, RT_PCAP, err, B_TRUE);
3747 3832 global_scope = B_TRUE;
3748 3833 }
3749 3834 return;
3750 3835 case RT_MCAP:
3751 3836 /* if none of these exist, there is no resource to select */
3752 3837 if ((res = zonecfg_lookup_mcap(handle, &old_mcaptab)) != Z_OK &&
3753 3838 zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &limit)
3754 3839 != Z_OK &&
3755 3840 zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM, &limit)
3756 3841 != Z_OK) {
3757 3842 z_cmd_rt_perror(CMD_SELECT, RT_MCAP, Z_NO_RESOURCE_TYPE,
3758 3843 B_TRUE);
3759 3844 global_scope = B_TRUE;
3760 3845 }
3761 3846 if (res == Z_OK)
3762 3847 bcopy(&old_mcaptab, &in_progress_mcaptab,
3763 3848 sizeof (struct zone_mcaptab));
3764 3849 else
3765 3850 bzero(&in_progress_mcaptab,
3766 3851 sizeof (in_progress_mcaptab));
3767 3852 return;
3768 3853 case RT_ADMIN:
3769 3854 if ((err = fill_in_admintab(cmd, &old_admintab, B_FALSE))
3770 3855 != Z_OK) {
3771 3856 z_cmd_rt_perror(CMD_SELECT, RT_ADMIN, err,
3772 3857 B_TRUE);
3773 3858 global_scope = B_TRUE;
3774 3859 }
3775 3860 bcopy(&old_admintab, &in_progress_admintab,
3776 3861 sizeof (struct zone_admintab));
3777 3862 return;
3778 3863 default:
3779 3864 zone_perror(rt_to_str(type), Z_NO_RESOURCE_TYPE, B_TRUE);
3780 3865 long_usage(CMD_SELECT, B_TRUE);
3781 3866 usage(B_FALSE, HELP_RESOURCES);
3782 3867 return;
3783 3868 }
3784 3869 }
3785 3870
3786 3871 /*
3787 3872 * Network "addresses" can be one of the following forms:
3788 3873 * <IPv4 address>
3789 3874 * <IPv4 address>/<prefix length>
3790 3875 * <IPv6 address>/<prefix length>
3791 3876 * <host name>
3792 3877 * <host name>/<prefix length>
3793 3878 * In other words, the "/" followed by a prefix length is allowed but not
3794 3879 * required for IPv4 addresses and host names, and required for IPv6 addresses.
3795 3880 * If a prefix length is given, it must be in the allowable range: 0 to 32 for
3796 3881 * IPv4 addresses and host names, 0 to 128 for IPv6 addresses.
3797 3882 * Host names must start with an alpha-numeric character, and all subsequent
3798 3883 * characters must be either alpha-numeric or "-".
3799 3884 *
3800 3885 * In some cases, e.g., the nexthop for the defrouter, the context indicates
3801 3886 * that this is the IPV4_ABITS or IPV6_ABITS netmask, in which case we don't
3802 3887 * require the /<prefix length> (and should ignore it if provided).
3803 3888 */
3804 3889
3805 3890 static int
3806 3891 validate_net_address_syntax(char *address, boolean_t ishost)
3807 3892 {
3808 3893 char *slashp, part1[MAXHOSTNAMELEN];
3809 3894 struct in6_addr in6;
3810 3895 struct in_addr in4;
3811 3896 int prefixlen, i;
3812 3897
3813 3898 /*
3814 3899 * Copy the part before any '/' into part1 or copy the whole
3815 3900 * thing if there is no '/'.
3816 3901 */
3817 3902 if ((slashp = strchr(address, '/')) != NULL) {
3818 3903 *slashp = '\0';
3819 3904 (void) strlcpy(part1, address, sizeof (part1));
3820 3905 *slashp = '/';
3821 3906 prefixlen = atoi(++slashp);
3822 3907 } else {
3823 3908 (void) strlcpy(part1, address, sizeof (part1));
3824 3909 }
3825 3910
3826 3911 if (ishost && slashp != NULL) {
3827 3912 zerr(gettext("Warning: prefix length in %s is not required and "
3828 3913 "will be ignored. The default host-prefix length "
3829 3914 "will be used"), address);
3830 3915 }
3831 3916
3832 3917
3833 3918 if (inet_pton(AF_INET6, part1, &in6) == 1) {
3834 3919 if (ishost) {
3835 3920 prefixlen = IPV6_ABITS;
3836 3921 } else if (slashp == NULL) {
3837 3922 zerr(gettext("%s: IPv6 addresses "
3838 3923 "require /prefix-length suffix."), address);
3839 3924 return (Z_ERR);
3840 3925 }
3841 3926 if (prefixlen < 0 || prefixlen > 128) {
3842 3927 zerr(gettext("%s: IPv6 address "
3843 3928 "prefix lengths must be 0 - 128."), address);
3844 3929 return (Z_ERR);
3845 3930 }
3846 3931 return (Z_OK);
3847 3932 }
3848 3933
3849 3934 /* At this point, any /prefix must be for IPv4. */
3850 3935 if (ishost)
3851 3936 prefixlen = IPV4_ABITS;
3852 3937 else if (slashp != NULL) {
3853 3938 if (prefixlen < 0 || prefixlen > 32) {
3854 3939 zerr(gettext("%s: IPv4 address "
3855 3940 "prefix lengths must be 0 - 32."), address);
3856 3941 return (Z_ERR);
3857 3942 }
3858 3943 }
3859 3944
3860 3945 if (inet_pton(AF_INET, part1, &in4) == 1)
3861 3946 return (Z_OK);
3862 3947
3863 3948 /* address may also be a host name */
3864 3949 if (!isalnum(part1[0])) {
3865 3950 zerr(gettext("%s: bogus host name or network address syntax"),
3866 3951 part1);
3867 3952 saw_error = B_TRUE;
3868 3953 usage(B_FALSE, HELP_NETADDR);
3869 3954 return (Z_ERR);
3870 3955 }
3871 3956 for (i = 1; part1[i]; i++)
3872 3957 if (!isalnum(part1[i]) && part1[i] != '-' && part1[i] != '.') {
3873 3958 zerr(gettext("%s: bogus host name or "
3874 3959 "network address syntax"), part1);
3875 3960 saw_error = B_TRUE;
3876 3961 usage(B_FALSE, HELP_NETADDR);
3877 3962 return (Z_ERR);
3878 3963 }
3879 3964 return (Z_OK);
3880 3965 }
3881 3966
3882 3967 static int
3883 3968 validate_net_physical_syntax(const char *ifname)
3884 3969 {
3885 3970 ifspec_t ifnameprop;
3886 3971 zone_iptype_t iptype;
3887 3972
3888 3973 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
3889 3974 zerr(gettext("zone configuration has an invalid or nonexistent "
3890 3975 "ip-type property"));
3891 3976 return (Z_ERR);
3892 3977 }
3893 3978 switch (iptype) {
3894 3979 case ZS_SHARED:
3895 3980 if (ifparse_ifspec(ifname, &ifnameprop) == B_FALSE) {
3896 3981 zerr(gettext("%s: invalid physical interface name"),
3897 3982 ifname);
3898 3983 return (Z_ERR);
3899 3984 }
3900 3985 if (ifnameprop.ifsp_lunvalid) {
3901 3986 zerr(gettext("%s: LUNs not allowed in physical "
3902 3987 "interface names"), ifname);
3903 3988 return (Z_ERR);
3904 3989 }
3905 3990 break;
3906 3991 case ZS_EXCLUSIVE:
3907 3992 if (dladm_valid_linkname(ifname) == B_FALSE) {
3908 3993 if (strchr(ifname, ':') != NULL)
3909 3994 zerr(gettext("%s: physical interface name "
3910 3995 "required; logical interface name not "
3911 3996 "allowed"), ifname);
3912 3997 else
3913 3998 zerr(gettext("%s: invalid physical interface "
3914 3999 "name"), ifname);
3915 4000 return (Z_ERR);
3916 4001 }
3917 4002 break;
3918 4003 }
3919 4004 return (Z_OK);
3920 4005 }
3921 4006
3922 4007 static boolean_t
3923 4008 valid_fs_type(const char *type)
3924 4009 {
3925 4010 /*
3926 4011 * Is this a valid path component?
3927 4012 */
3928 4013 if (strlen(type) + 1 > MAXNAMELEN)
3929 4014 return (B_FALSE);
3930 4015 /*
3931 4016 * Make sure a bad value for "type" doesn't make
3932 4017 * /usr/lib/fs/<type>/mount turn into something else.
3933 4018 */
3934 4019 if (strchr(type, '/') != NULL || type[0] == '\0' ||
3935 4020 strcmp(type, ".") == 0 || strcmp(type, "..") == 0)
3936 4021 return (B_FALSE);
3937 4022 /*
3938 4023 * More detailed verification happens later by zoneadm(1m).
3939 4024 */
3940 4025 return (B_TRUE);
3941 4026 }
3942 4027
3943 4028 static boolean_t
3944 4029 allow_exclusive()
3945 4030 {
3946 4031 brand_handle_t bh;
3947 4032 char brand[MAXNAMELEN];
3948 4033 boolean_t ret;
3949 4034
3950 4035 if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
3951 4036 zerr("%s: %s\n", zone, gettext("could not get zone brand"));
3952 4037 return (B_FALSE);
3953 4038 }
3954 4039 if ((bh = brand_open(brand)) == NULL) {
3955 4040 zerr("%s: %s\n", zone, gettext("unknown brand."));
3956 4041 return (B_FALSE);
3957 4042 }
3958 4043 ret = brand_allow_exclusive_ip(bh);
3959 4044 brand_close(bh);
3960 4045 if (!ret)
3961 4046 zerr(gettext("%s cannot be '%s' when %s is '%s'."),
3962 4047 pt_to_str(PT_IPTYPE), "exclusive",
3963 4048 pt_to_str(PT_BRAND), brand);
3964 4049 return (ret);
3965 4050 }
3966 4051
3967 4052 static void
3968 4053 set_aliased_rctl(char *alias, int prop_type, char *s)
3969 4054 {
3970 4055 uint64_t limit;
3971 4056 int err;
3972 4057 char tmp[128];
3973 4058
3974 4059 if (global_zone && strcmp(alias, ALIAS_SHARES) != 0)
3975 4060 zerr(gettext("WARNING: Setting a global zone resource "
3976 4061 "control too low could deny\nservice "
3977 4062 "to even the root user; "
3978 4063 "this could render the system impossible\n"
3979 4064 "to administer. Please use caution."));
3980 4065
3981 4066 /* convert memory based properties */
3982 4067 if (prop_type == PT_MAXSHMMEM) {
3983 4068 if (!zonecfg_valid_memlimit(s, &limit)) {
3984 4069 zerr(gettext("A non-negative number with a required "
3985 4070 "scale suffix (K, M, G or T) was expected\nhere."));
3986 4071 saw_error = B_TRUE;
3987 4072 return;
3988 4073 }
3989 4074
3990 4075 (void) snprintf(tmp, sizeof (tmp), "%llu", limit);
3991 4076 s = tmp;
3992 4077 }
3993 4078
3994 4079 if (!zonecfg_aliased_rctl_ok(handle, alias)) {
3995 4080 zone_perror(pt_to_str(prop_type), Z_ALIAS_DISALLOW, B_FALSE);
3996 4081 saw_error = B_TRUE;
3997 4082 } else if (!zonecfg_valid_alias_limit(alias, s, &limit)) {
3998 4083 zerr(gettext("%s property is out of range."),
3999 4084 pt_to_str(prop_type));
4000 4085 saw_error = B_TRUE;
4001 4086 } else if ((err = zonecfg_set_aliased_rctl(handle, alias, limit))
4002 4087 != Z_OK) {
4003 4088 zone_perror(zone, err, B_TRUE);
4004 4089 saw_error = B_TRUE;
4005 4090 } else {
4006 4091 need_to_commit = B_TRUE;
4007 4092 }
4008 4093 }
4009 4094
4010 4095 static void
4011 4096 set_in_progress_nwiftab_address(char *prop_id, int prop_type)
4012 4097 {
4013 4098 if (prop_type == PT_ADDRESS) {
4014 4099 (void) strlcpy(in_progress_nwiftab.zone_nwif_address, prop_id,
4015 4100 sizeof (in_progress_nwiftab.zone_nwif_address));
4016 4101 } else {
4017 4102 assert(prop_type == PT_ALLOWED_ADDRESS);
4018 4103 (void) strlcpy(in_progress_nwiftab.zone_nwif_allowed_address,
4019 4104 prop_id,
4020 4105 sizeof (in_progress_nwiftab.zone_nwif_allowed_address));
4021 4106 }
4022 4107 }
4023 4108
4024 4109 void
4025 4110 set_func(cmd_t *cmd)
4026 4111 {
4027 4112 char *prop_id;
4028 4113 int arg, err, res_type, prop_type;
4029 4114 property_value_ptr_t pp;
4030 4115 boolean_t autoboot;
4031 4116 zone_iptype_t iptype;
4032 4117 boolean_t force_set = B_FALSE;
4033 4118 size_t physmem_size = sizeof (in_progress_mcaptab.zone_physmem_cap);
4034 4119 uint64_t mem_cap, mem_limit;
4035 4120 float cap;
4036 4121 char *unitp;
4037 4122 struct zone_psettab tmp_psettab;
4038 4123 boolean_t arg_err = B_FALSE;
4039 4124
4040 4125 if (zone_is_read_only(CMD_SET))
4041 4126 return;
4042 4127
4043 4128 assert(cmd != NULL);
4044 4129
4045 4130 optind = opterr = 0;
4046 4131 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "F")) != EOF) {
4047 4132 switch (arg) {
4048 4133 case 'F':
4049 4134 force_set = B_TRUE;
4050 4135 break;
4051 4136 default:
4052 4137 if (optopt == '?')
4053 4138 longer_usage(CMD_SET);
4054 4139 else
4055 4140 short_usage(CMD_SET);
4056 4141 arg_err = B_TRUE;
4057 4142 break;
4058 4143 }
4059 4144 }
4060 4145 if (arg_err)
4061 4146 return;
4062 4147
4063 4148 prop_type = cmd->cmd_prop_name[0];
4064 4149 if (global_scope) {
4065 4150 if (gz_invalid_property(prop_type)) {
4066 4151 zerr(gettext("%s is not a valid property for the "
4067 4152 "global zone."), pt_to_str(prop_type));
4068 4153 saw_error = B_TRUE;
4069 4154 return;
4070 4155 }
4071 4156
4072 4157 if (prop_type == PT_ZONENAME) {
4073 4158 res_type = RT_ZONENAME;
4074 4159 } else if (prop_type == PT_ZONEPATH) {
4075 4160 res_type = RT_ZONEPATH;
4076 4161 } else if (prop_type == PT_AUTOBOOT) {
4077 4162 res_type = RT_AUTOBOOT;
4078 4163 } else if (prop_type == PT_BRAND) {
4079 4164 res_type = RT_BRAND;
4080 4165 } else if (prop_type == PT_POOL) {
4081 4166 res_type = RT_POOL;
4082 4167 } else if (prop_type == PT_LIMITPRIV) {
4083 4168 res_type = RT_LIMITPRIV;
4084 4169 } else if (prop_type == PT_BOOTARGS) {
4085 4170 res_type = RT_BOOTARGS;
4086 4171 } else if (prop_type == PT_SCHED) {
4087 4172 res_type = RT_SCHED;
4088 4173 } else if (prop_type == PT_IPTYPE) {
4089 4174 res_type = RT_IPTYPE;
4090 4175 } else if (prop_type == PT_MAXLWPS) {
4091 4176 res_type = RT_MAXLWPS;
4092 4177 } else if (prop_type == PT_MAXPROCS) {
4093 4178 res_type = RT_MAXPROCS;
4094 4179 } else if (prop_type == PT_MAXSHMMEM) {
4095 4180 res_type = RT_MAXSHMMEM;
4096 4181 } else if (prop_type == PT_MAXSHMIDS) {
4097 4182 res_type = RT_MAXSHMIDS;
4098 4183 } else if (prop_type == PT_MAXMSGIDS) {
4099 4184 res_type = RT_MAXMSGIDS;
4100 4185 } else if (prop_type == PT_MAXSEMIDS) {
4101 4186 res_type = RT_MAXSEMIDS;
4102 4187 } else if (prop_type == PT_SHARES) {
4103 4188 res_type = RT_SHARES;
4104 4189 } else if (prop_type == PT_HOSTID) {
4105 4190 res_type = RT_HOSTID;
4106 4191 } else if (prop_type == PT_FS_ALLOWED) {
4107 4192 res_type = RT_FS_ALLOWED;
4108 4193 } else {
4109 4194 zerr(gettext("Cannot set a resource-specific property "
4110 4195 "from the global scope."));
4111 4196 saw_error = B_TRUE;
4112 4197 return;
4113 4198 }
4114 4199 } else {
4115 4200 res_type = resource_scope;
4116 4201 }
4117 4202
4118 4203 if (force_set) {
4119 4204 if (res_type != RT_ZONEPATH) {
4120 4205 zerr(gettext("Only zonepath setting can be forced."));
4121 4206 saw_error = B_TRUE;
4122 4207 return;
4123 4208 }
4124 4209 if (!zonecfg_in_alt_root()) {
4125 4210 zerr(gettext("Zonepath is changeable only in an "
4126 4211 "alternate root."));
4127 4212 saw_error = B_TRUE;
4128 4213 return;
4129 4214 }
4130 4215 }
4131 4216
4132 4217 pp = cmd->cmd_property_ptr[0];
4133 4218 /*
4134 4219 * A nasty expression but not that complicated:
4135 4220 * 1. fs options are simple or list (tested below)
4136 4221 * 2. rctl value's are complex or list (tested below)
4137 4222 * Anything else should be simple.
4138 4223 */
4139 4224 if (!(res_type == RT_FS && prop_type == PT_OPTIONS) &&
4140 4225 !(res_type == RT_RCTL && prop_type == PT_VALUE) &&
4141 4226 (pp->pv_type != PROP_VAL_SIMPLE ||
4142 4227 (prop_id = pp->pv_simple) == NULL)) {
4143 4228 zerr(gettext("A %s value was expected here."),
4144 4229 pvt_to_str(PROP_VAL_SIMPLE));
4145 4230 saw_error = B_TRUE;
4146 4231 return;
4147 4232 }
4148 4233 if (prop_type == PT_UNKNOWN) {
4149 4234 long_usage(CMD_SET, B_TRUE);
4150 4235 return;
4151 4236 }
4152 4237
4153 4238 /*
4154 4239 * Special case: the user can change the zone name prior to 'create';
4155 4240 * if the zone already exists, we fall through letting initialize()
4156 4241 * and the rest of the logic run.
4157 4242 */
4158 4243 if (res_type == RT_ZONENAME && got_handle == B_FALSE &&
4159 4244 !state_atleast(ZONE_STATE_CONFIGURED)) {
4160 4245 if ((err = zonecfg_validate_zonename(prop_id)) != Z_OK) {
4161 4246 zone_perror(prop_id, err, B_TRUE);
4162 4247 usage(B_FALSE, HELP_SYNTAX);
4163 4248 return;
4164 4249 }
4165 4250 (void) strlcpy(zone, prop_id, sizeof (zone));
4166 4251 return;
4167 4252 }
4168 4253
4169 4254 if (initialize(B_TRUE) != Z_OK)
4170 4255 return;
4171 4256
4172 4257 switch (res_type) {
4173 4258 case RT_ZONENAME:
4174 4259 if ((err = zonecfg_set_name(handle, prop_id)) != Z_OK) {
4175 4260 /*
4176 4261 * Use prop_id instead of 'zone' here, since we're
4177 4262 * reporting a problem about the *new* zonename.
4178 4263 */
4179 4264 zone_perror(prop_id, err, B_TRUE);
4180 4265 usage(B_FALSE, HELP_SYNTAX);
4181 4266 } else {
4182 4267 need_to_commit = B_TRUE;
4183 4268 (void) strlcpy(zone, prop_id, sizeof (zone));
4184 4269 }
4185 4270 return;
4186 4271 case RT_ZONEPATH:
4187 4272 if (!force_set && state_atleast(ZONE_STATE_INSTALLED)) {
4188 4273 zerr(gettext("Zone %s already installed; %s %s not "
4189 4274 "allowed."), zone, cmd_to_str(CMD_SET),
4190 4275 rt_to_str(RT_ZONEPATH));
4191 4276 return;
4192 4277 }
4193 4278 if (validate_zonepath_syntax(prop_id) != Z_OK) {
4194 4279 saw_error = B_TRUE;
4195 4280 return;
4196 4281 }
4197 4282 if ((err = zonecfg_set_zonepath(handle, prop_id)) != Z_OK)
4198 4283 zone_perror(zone, err, B_TRUE);
4199 4284 else
4200 4285 need_to_commit = B_TRUE;
4201 4286 return;
4202 4287 case RT_BRAND:
4203 4288 if (state_atleast(ZONE_STATE_INSTALLED)) {
4204 4289 zerr(gettext("Zone %s already installed; %s %s not "
4205 4290 "allowed."), zone, cmd_to_str(CMD_SET),
4206 4291 rt_to_str(RT_BRAND));
4207 4292 return;
4208 4293 }
4209 4294 if ((err = zonecfg_set_brand(handle, prop_id)) != Z_OK)
4210 4295 zone_perror(zone, err, B_TRUE);
4211 4296 else
4212 4297 need_to_commit = B_TRUE;
4213 4298 return;
4214 4299 case RT_AUTOBOOT:
4215 4300 if (strcmp(prop_id, "true") == 0) {
4216 4301 autoboot = B_TRUE;
4217 4302 } else if (strcmp(prop_id, "false") == 0) {
4218 4303 autoboot = B_FALSE;
4219 4304 } else {
4220 4305 zerr(gettext("%s value must be '%s' or '%s'."),
4221 4306 pt_to_str(PT_AUTOBOOT), "true", "false");
4222 4307 saw_error = B_TRUE;
4223 4308 return;
4224 4309 }
4225 4310 if ((err = zonecfg_set_autoboot(handle, autoboot)) != Z_OK)
4226 4311 zone_perror(zone, err, B_TRUE);
4227 4312 else
4228 4313 need_to_commit = B_TRUE;
4229 4314 return;
4230 4315 case RT_POOL:
4231 4316 /* don't allow use of the reserved temporary pool names */
4232 4317 if (strncmp("SUNW", prop_id, 4) == 0) {
4233 4318 zerr(gettext("pool names starting with SUNW are "
4234 4319 "reserved."));
4235 4320 saw_error = B_TRUE;
4236 4321 return;
4237 4322 }
4238 4323
4239 4324 /* can't set pool if dedicated-cpu exists */
4240 4325 if (zonecfg_lookup_pset(handle, &tmp_psettab) == Z_OK) {
4241 4326 zerr(gettext("The %s resource already exists. "
4242 4327 "A persistent pool is incompatible\nwith the %s "
4243 4328 "resource."), rt_to_str(RT_DCPU),
4244 4329 rt_to_str(RT_DCPU));
4245 4330 saw_error = B_TRUE;
4246 4331 return;
4247 4332 }
4248 4333
4249 4334 if ((err = zonecfg_set_pool(handle, prop_id)) != Z_OK)
4250 4335 zone_perror(zone, err, B_TRUE);
4251 4336 else
4252 4337 need_to_commit = B_TRUE;
4253 4338 return;
4254 4339 case RT_LIMITPRIV:
4255 4340 if ((err = zonecfg_set_limitpriv(handle, prop_id)) != Z_OK)
4256 4341 zone_perror(zone, err, B_TRUE);
4257 4342 else
4258 4343 need_to_commit = B_TRUE;
4259 4344 return;
4260 4345 case RT_BOOTARGS:
4261 4346 if ((err = zonecfg_set_bootargs(handle, prop_id)) != Z_OK)
4262 4347 zone_perror(zone, err, B_TRUE);
4263 4348 else
4264 4349 need_to_commit = B_TRUE;
4265 4350 return;
4266 4351 case RT_SCHED:
4267 4352 if ((err = zonecfg_set_sched(handle, prop_id)) != Z_OK)
4268 4353 zone_perror(zone, err, B_TRUE);
4269 4354 else
4270 4355 need_to_commit = B_TRUE;
4271 4356 return;
4272 4357 case RT_IPTYPE:
4273 4358 if (strcmp(prop_id, "shared") == 0) {
4274 4359 iptype = ZS_SHARED;
4275 4360 } else if (strcmp(prop_id, "exclusive") == 0) {
4276 4361 iptype = ZS_EXCLUSIVE;
4277 4362 } else {
4278 4363 zerr(gettext("%s value must be '%s' or '%s'."),
4279 4364 pt_to_str(PT_IPTYPE), "shared", "exclusive");
4280 4365 saw_error = B_TRUE;
4281 4366 return;
4282 4367 }
4283 4368 if (iptype == ZS_EXCLUSIVE && !allow_exclusive()) {
4284 4369 saw_error = B_TRUE;
4285 4370 return;
4286 4371 }
4287 4372 if ((err = zonecfg_set_iptype(handle, iptype)) != Z_OK)
4288 4373 zone_perror(zone, err, B_TRUE);
4289 4374 else
4290 4375 need_to_commit = B_TRUE;
4291 4376 return;
4292 4377 case RT_MAXLWPS:
4293 4378 set_aliased_rctl(ALIAS_MAXLWPS, prop_type, prop_id);
4294 4379 return;
4295 4380 case RT_MAXPROCS:
4296 4381 set_aliased_rctl(ALIAS_MAXPROCS, prop_type, prop_id);
4297 4382 return;
4298 4383 case RT_MAXSHMMEM:
4299 4384 set_aliased_rctl(ALIAS_MAXSHMMEM, prop_type, prop_id);
4300 4385 return;
4301 4386 case RT_MAXSHMIDS:
4302 4387 set_aliased_rctl(ALIAS_MAXSHMIDS, prop_type, prop_id);
4303 4388 return;
4304 4389 case RT_MAXMSGIDS:
4305 4390 set_aliased_rctl(ALIAS_MAXMSGIDS, prop_type, prop_id);
4306 4391 return;
4307 4392 case RT_MAXSEMIDS:
4308 4393 set_aliased_rctl(ALIAS_MAXSEMIDS, prop_type, prop_id);
4309 4394 return;
4310 4395 case RT_SHARES:
4311 4396 set_aliased_rctl(ALIAS_SHARES, prop_type, prop_id);
4312 4397 return;
4313 4398 case RT_HOSTID:
4314 4399 if ((err = zonecfg_set_hostid(handle, prop_id)) != Z_OK) {
4315 4400 if (err == Z_TOO_BIG) {
4316 4401 zerr(gettext("hostid string is too large: %s"),
4317 4402 prop_id);
4318 4403 saw_error = B_TRUE;
4319 4404 } else {
4320 4405 zone_perror(pt_to_str(prop_type), err, B_TRUE);
4321 4406 }
4322 4407 return;
4323 4408 }
4324 4409 need_to_commit = B_TRUE;
4325 4410 return;
4326 4411 case RT_FS_ALLOWED:
4327 4412 if ((err = zonecfg_set_fs_allowed(handle, prop_id)) != Z_OK)
4328 4413 zone_perror(zone, err, B_TRUE);
4329 4414 else
4330 4415 need_to_commit = B_TRUE;
4331 4416 return;
4332 4417 case RT_FS:
4333 4418 switch (prop_type) {
4334 4419 case PT_DIR:
4335 4420 (void) strlcpy(in_progress_fstab.zone_fs_dir, prop_id,
4336 4421 sizeof (in_progress_fstab.zone_fs_dir));
4337 4422 return;
4338 4423 case PT_SPECIAL:
4339 4424 (void) strlcpy(in_progress_fstab.zone_fs_special,
4340 4425 prop_id,
4341 4426 sizeof (in_progress_fstab.zone_fs_special));
4342 4427 return;
4343 4428 case PT_RAW:
4344 4429 (void) strlcpy(in_progress_fstab.zone_fs_raw,
4345 4430 prop_id, sizeof (in_progress_fstab.zone_fs_raw));
4346 4431 return;
4347 4432 case PT_TYPE:
4348 4433 if (!valid_fs_type(prop_id)) {
4349 4434 zerr(gettext("\"%s\" is not a valid %s."),
4350 4435 prop_id, pt_to_str(PT_TYPE));
4351 4436 saw_error = B_TRUE;
4352 4437 return;
4353 4438 }
4354 4439 (void) strlcpy(in_progress_fstab.zone_fs_type, prop_id,
4355 4440 sizeof (in_progress_fstab.zone_fs_type));
4356 4441 return;
4357 4442 case PT_OPTIONS:
4358 4443 if (pp->pv_type != PROP_VAL_SIMPLE &&
4359 4444 pp->pv_type != PROP_VAL_LIST) {
4360 4445 zerr(gettext("A %s or %s value was expected "
4361 4446 "here."), pvt_to_str(PROP_VAL_SIMPLE),
4362 4447 pvt_to_str(PROP_VAL_LIST));
4363 4448 saw_error = B_TRUE;
4364 4449 return;
4365 4450 }
4366 4451 zonecfg_free_fs_option_list(
4367 4452 in_progress_fstab.zone_fs_options);
4368 4453 in_progress_fstab.zone_fs_options = NULL;
4369 4454 if (!(pp->pv_type == PROP_VAL_LIST &&
4370 4455 pp->pv_list == NULL))
4371 4456 add_property(cmd);
4372 4457 return;
4373 4458 default:
4374 4459 break;
4375 4460 }
4376 4461 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4377 4462 long_usage(CMD_SET, B_TRUE);
4378 4463 usage(B_FALSE, HELP_PROPS);
4379 4464 return;
4380 4465 case RT_NET:
4381 4466 switch (prop_type) {
4382 4467 case PT_ADDRESS:
4383 4468 case PT_ALLOWED_ADDRESS:
4384 4469 if (validate_net_address_syntax(prop_id, B_FALSE)
4385 4470 != Z_OK) {
4386 4471 saw_error = B_TRUE;
4387 4472 return;
4388 4473 }
4389 4474 set_in_progress_nwiftab_address(prop_id, prop_type);
4390 4475 break;
4391 4476 case PT_PHYSICAL:
4392 4477 if (validate_net_physical_syntax(prop_id) != Z_OK) {
4393 4478 saw_error = B_TRUE;
4394 4479 return;
4395 4480 }
4396 4481 (void) strlcpy(in_progress_nwiftab.zone_nwif_physical,
4397 4482 prop_id,
4398 4483 sizeof (in_progress_nwiftab.zone_nwif_physical));
4399 4484 break;
4400 4485 case PT_DEFROUTER:
4401 4486 if (validate_net_address_syntax(prop_id, B_TRUE)
4402 4487 != Z_OK) {
4403 4488 saw_error = B_TRUE;
4404 4489 return;
4405 4490 }
4406 4491 (void) strlcpy(in_progress_nwiftab.zone_nwif_defrouter,
4407 4492 prop_id,
4408 4493 sizeof (in_progress_nwiftab.zone_nwif_defrouter));
4409 4494 break;
4410 4495 default:
4411 4496 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4412 4497 B_TRUE);
4413 4498 long_usage(CMD_SET, B_TRUE);
4414 4499 usage(B_FALSE, HELP_PROPS);
4415 4500 return;
4416 4501 }
4417 4502 return;
4418 4503 case RT_DEVICE:
4419 4504 switch (prop_type) {
4420 4505 case PT_MATCH:
4421 4506 (void) strlcpy(in_progress_devtab.zone_dev_match,
4422 4507 prop_id,
4423 4508 sizeof (in_progress_devtab.zone_dev_match));
4424 4509 break;
4425 4510 default:
4426 4511 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4427 4512 B_TRUE);
4428 4513 long_usage(CMD_SET, B_TRUE);
4429 4514 usage(B_FALSE, HELP_PROPS);
4430 4515 return;
4431 4516 }
4432 4517 return;
4433 4518 case RT_RCTL:
4434 4519 switch (prop_type) {
4435 4520 case PT_NAME:
4436 4521 if (!zonecfg_valid_rctlname(prop_id)) {
4437 4522 zerr(gettext("'%s' is not a valid zone %s "
4438 4523 "name."), prop_id, rt_to_str(RT_RCTL));
4439 4524 return;
4440 4525 }
4441 4526 (void) strlcpy(in_progress_rctltab.zone_rctl_name,
4442 4527 prop_id,
4443 4528 sizeof (in_progress_rctltab.zone_rctl_name));
4444 4529 break;
4445 4530 case PT_VALUE:
4446 4531 if (pp->pv_type != PROP_VAL_COMPLEX &&
4447 4532 pp->pv_type != PROP_VAL_LIST) {
4448 4533 zerr(gettext("A %s or %s value was expected "
4449 4534 "here."), pvt_to_str(PROP_VAL_COMPLEX),
4450 4535 pvt_to_str(PROP_VAL_LIST));
4451 4536 saw_error = B_TRUE;
4452 4537 return;
4453 4538 }
4454 4539 zonecfg_free_rctl_value_list(
4455 4540 in_progress_rctltab.zone_rctl_valptr);
4456 4541 in_progress_rctltab.zone_rctl_valptr = NULL;
4457 4542 if (!(pp->pv_type == PROP_VAL_LIST &&
4458 4543 pp->pv_list == NULL))
4459 4544 add_property(cmd);
4460 4545 break;
4461 4546 default:
4462 4547 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4463 4548 B_TRUE);
4464 4549 long_usage(CMD_SET, B_TRUE);
4465 4550 usage(B_FALSE, HELP_PROPS);
4466 4551 return;
4467 4552 }
4468 4553 return;
4469 4554 case RT_ATTR:
4470 4555 switch (prop_type) {
4471 4556 case PT_NAME:
4472 4557 (void) strlcpy(in_progress_attrtab.zone_attr_name,
4473 4558 prop_id,
4474 4559 sizeof (in_progress_attrtab.zone_attr_name));
4475 4560 break;
4476 4561 case PT_TYPE:
4477 4562 (void) strlcpy(in_progress_attrtab.zone_attr_type,
4478 4563 prop_id,
4479 4564 sizeof (in_progress_attrtab.zone_attr_type));
4480 4565 break;
4481 4566 case PT_VALUE:
4482 4567 (void) strlcpy(in_progress_attrtab.zone_attr_value,
4483 4568 prop_id,
4484 4569 sizeof (in_progress_attrtab.zone_attr_value));
4485 4570 break;
4486 4571 default:
4487 4572 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4488 4573 B_TRUE);
4489 4574 long_usage(CMD_SET, B_TRUE);
4490 4575 usage(B_FALSE, HELP_PROPS);
4491 4576 return;
4492 4577 }
4493 4578 return;
4494 4579 case RT_DATASET:
4495 4580 switch (prop_type) {
4496 4581 case PT_NAME:
4497 4582 (void) strlcpy(in_progress_dstab.zone_dataset_name,
4498 4583 prop_id,
4499 4584 sizeof (in_progress_dstab.zone_dataset_name));
4500 4585 return;
4501 4586 default:
4502 4587 break;
4503 4588 }
4504 4589 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4505 4590 long_usage(CMD_SET, B_TRUE);
4506 4591 usage(B_FALSE, HELP_PROPS);
4507 4592 return;
4508 4593 case RT_DCPU:
4509 4594 switch (prop_type) {
4510 4595 char *lowp, *highp;
4511 4596
4512 4597 case PT_NCPUS:
4513 4598 lowp = prop_id;
4514 4599 if ((highp = strchr(prop_id, '-')) != NULL)
4515 4600 *highp++ = '\0';
4516 4601 else
4517 4602 highp = lowp;
4518 4603
4519 4604 /* Make sure the input makes sense. */
4520 4605 if (!zonecfg_valid_ncpus(lowp, highp)) {
4521 4606 zerr(gettext("%s property is out of range."),
4522 4607 pt_to_str(PT_NCPUS));
4523 4608 saw_error = B_TRUE;
4524 4609 return;
4525 4610 }
4526 4611
4527 4612 (void) strlcpy(
4528 4613 in_progress_psettab.zone_ncpu_min, lowp,
4529 4614 sizeof (in_progress_psettab.zone_ncpu_min));
4530 4615 (void) strlcpy(
4531 4616 in_progress_psettab.zone_ncpu_max, highp,
4532 4617 sizeof (in_progress_psettab.zone_ncpu_max));
4533 4618 return;
4534 4619 case PT_IMPORTANCE:
4535 4620 /* Make sure the value makes sense. */
4536 4621 if (!zonecfg_valid_importance(prop_id)) {
4537 4622 zerr(gettext("%s property is out of range."),
4538 4623 pt_to_str(PT_IMPORTANCE));
4539 4624 saw_error = B_TRUE;
4540 4625 return;
4541 4626 }
4542 4627
4543 4628 (void) strlcpy(in_progress_psettab.zone_importance,
4544 4629 prop_id,
4545 4630 sizeof (in_progress_psettab.zone_importance));
4546 4631 return;
4547 4632 default:
4548 4633 break;
4549 4634 }
4550 4635 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE, B_TRUE);
4551 4636 long_usage(CMD_SET, B_TRUE);
4552 4637 usage(B_FALSE, HELP_PROPS);
4553 4638 return;
4554 4639 case RT_PCAP:
4555 4640 if (prop_type != PT_NCPUS) {
4556 4641 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4557 4642 B_TRUE);
4558 4643 long_usage(CMD_SET, B_TRUE);
4559 4644 usage(B_FALSE, HELP_PROPS);
4560 4645 return;
4561 4646 }
4562 4647
4563 4648 /*
4564 4649 * We already checked that an rctl alias is allowed in
4565 4650 * the add_resource() function.
4566 4651 */
4567 4652
4568 4653 if ((cap = strtof(prop_id, &unitp)) <= 0 || *unitp != '\0' ||
4569 4654 (int)(cap * 100) < 1) {
4570 4655 zerr(gettext("%s property is out of range."),
4571 4656 pt_to_str(PT_NCPUS));
4572 4657 saw_error = B_TRUE;
4573 4658 return;
4574 4659 }
4575 4660
4576 4661 if ((err = zonecfg_set_aliased_rctl(handle, ALIAS_CPUCAP,
4577 4662 (int)(cap * 100))) != Z_OK)
4578 4663 zone_perror(zone, err, B_TRUE);
4579 4664 else
4580 4665 need_to_commit = B_TRUE;
4581 4666 return;
4582 4667 case RT_MCAP:
4583 4668 switch (prop_type) {
4584 4669 case PT_PHYSICAL:
4585 4670 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4586 4671 zerr(gettext("A positive number with a "
4587 4672 "required scale suffix (K, M, G or T) was "
4588 4673 "expected here."));
4589 4674 saw_error = B_TRUE;
4590 4675 } else if (mem_cap < ONE_MB) {
4591 4676 zerr(gettext("%s value is too small. It must "
4592 4677 "be at least 1M."), pt_to_str(PT_PHYSICAL));
4593 4678 saw_error = B_TRUE;
4594 4679 } else {
4595 4680 snprintf(in_progress_mcaptab.zone_physmem_cap,
4596 4681 physmem_size, "%llu", mem_cap);
4597 4682 }
4598 4683 break;
4599 4684 case PT_SWAP:
4600 4685 /*
4601 4686 * We have to check if an rctl is allowed here since
4602 4687 * there might already be a rctl defined that blocks
4603 4688 * the alias.
4604 4689 */
4605 4690 if (!zonecfg_aliased_rctl_ok(handle, ALIAS_MAXSWAP)) {
4606 4691 zone_perror(pt_to_str(PT_MAXSWAP),
4607 4692 Z_ALIAS_DISALLOW, B_FALSE);
4608 4693 saw_error = B_TRUE;
4609 4694 return;
4610 4695 }
4611 4696
4612 4697 if (global_zone)
4613 4698 mem_limit = ONE_MB * 100;
4614 4699 else
4615 4700 mem_limit = ONE_MB * 50;
4616 4701
4617 4702 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4618 4703 zerr(gettext("A positive number with a "
4619 4704 "required scale suffix (K, M, G or T) was "
4620 4705 "expected here."));
4621 4706 saw_error = B_TRUE;
4622 4707 } else if (mem_cap < mem_limit) {
4623 4708 char buf[128];
4624 4709
4625 4710 (void) snprintf(buf, sizeof (buf), "%llu",
4626 4711 mem_limit);
4627 4712 bytes_to_units(buf, buf, sizeof (buf));
4628 4713 zerr(gettext("%s value is too small. It must "
4629 4714 "be at least %s."), pt_to_str(PT_SWAP),
4630 4715 buf);
4631 4716 saw_error = B_TRUE;
4632 4717 } else {
4633 4718 if ((err = zonecfg_set_aliased_rctl(handle,
4634 4719 ALIAS_MAXSWAP, mem_cap)) != Z_OK)
4635 4720 zone_perror(zone, err, B_TRUE);
4636 4721 else
4637 4722 need_to_commit = B_TRUE;
4638 4723 }
4639 4724 break;
4640 4725 case PT_LOCKED:
4641 4726 /*
4642 4727 * We have to check if an rctl is allowed here since
4643 4728 * there might already be a rctl defined that blocks
4644 4729 * the alias.
4645 4730 */
4646 4731 if (!zonecfg_aliased_rctl_ok(handle,
4647 4732 ALIAS_MAXLOCKEDMEM)) {
4648 4733 zone_perror(pt_to_str(PT_LOCKED),
4649 4734 Z_ALIAS_DISALLOW, B_FALSE);
4650 4735 saw_error = B_TRUE;
4651 4736 return;
4652 4737 }
4653 4738
4654 4739 if (!zonecfg_valid_memlimit(prop_id, &mem_cap)) {
4655 4740 zerr(gettext("A non-negative number with a "
4656 4741 "required scale suffix (K, M, G or T) was "
4657 4742 "expected\nhere."));
4658 4743 saw_error = B_TRUE;
4659 4744 } else {
4660 4745 if ((err = zonecfg_set_aliased_rctl(handle,
4661 4746 ALIAS_MAXLOCKEDMEM, mem_cap)) != Z_OK)
4662 4747 zone_perror(zone, err, B_TRUE);
4663 4748 else
4664 4749 need_to_commit = B_TRUE;
4665 4750 }
4666 4751 break;
4667 4752 default:
4668 4753 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4669 4754 B_TRUE);
4670 4755 long_usage(CMD_SET, B_TRUE);
4671 4756 usage(B_FALSE, HELP_PROPS);
4672 4757 return;
4673 4758 }
4674 4759 return;
4675 4760 case RT_ADMIN:
4676 4761 switch (prop_type) {
4677 4762 case PT_USER:
4678 4763 (void) strlcpy(in_progress_admintab.zone_admin_user,
4679 4764 prop_id,
4680 4765 sizeof (in_progress_admintab.zone_admin_user));
4681 4766 return;
4682 4767 case PT_AUTHS:
4683 4768 (void) strlcpy(in_progress_admintab.zone_admin_auths,
4684 4769 prop_id,
4685 4770 sizeof (in_progress_admintab.zone_admin_auths));
4686 4771 return;
4687 4772 default:
4688 4773 zone_perror(pt_to_str(prop_type), Z_NO_PROPERTY_TYPE,
4689 4774 B_TRUE);
4690 4775 long_usage(CMD_SET, B_TRUE);
4691 4776 usage(B_FALSE, HELP_PROPS);
4692 4777 return;
4693 4778 }
4694 4779 default:
4695 4780 zone_perror(rt_to_str(res_type), Z_NO_RESOURCE_TYPE, B_TRUE);
4696 4781 long_usage(CMD_SET, B_TRUE);
4697 4782 usage(B_FALSE, HELP_RESOURCES);
4698 4783 return;
4699 4784 }
4700 4785 }
4701 4786
4702 4787 static void
4703 4788 output_prop(FILE *fp, int pnum, char *pval, boolean_t print_notspec)
4704 4789 {
4705 4790 char *qstr;
4706 4791
4707 4792 if (*pval != '\0') {
4708 4793 qstr = quoteit(pval);
4709 4794 if (pnum == PT_SWAP || pnum == PT_LOCKED)
4710 4795 (void) fprintf(fp, "\t[%s: %s]\n", pt_to_str(pnum),
4711 4796 qstr);
4712 4797 else
4713 4798 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(pnum), qstr);
4714 4799 free(qstr);
4715 4800 } else if (print_notspec)
4716 4801 (void) fprintf(fp, gettext("\t%s not specified\n"),
4717 4802 pt_to_str(pnum));
4718 4803 }
4719 4804
4720 4805 static void
4721 4806 info_zonename(zone_dochandle_t handle, FILE *fp)
4722 4807 {
4723 4808 char zonename[ZONENAME_MAX];
4724 4809
4725 4810 if (zonecfg_get_name(handle, zonename, sizeof (zonename)) == Z_OK)
4726 4811 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONENAME),
4727 4812 zonename);
4728 4813 else
4729 4814 (void) fprintf(fp, gettext("%s not specified\n"),
4730 4815 pt_to_str(PT_ZONENAME));
4731 4816 }
4732 4817
4733 4818 static void
4734 4819 info_zonepath(zone_dochandle_t handle, FILE *fp)
4735 4820 {
4736 4821 char zonepath[MAXPATHLEN];
4737 4822
4738 4823 if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) == Z_OK)
4739 4824 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_ZONEPATH),
4740 4825 zonepath);
4741 4826 else {
4742 4827 (void) fprintf(fp, gettext("%s not specified\n"),
4743 4828 pt_to_str(PT_ZONEPATH));
4744 4829 }
4745 4830 }
4746 4831
4747 4832 static void
4748 4833 info_brand(zone_dochandle_t handle, FILE *fp)
4749 4834 {
4750 4835 char brand[MAXNAMELEN];
4751 4836
4752 4837 if (zonecfg_get_brand(handle, brand, sizeof (brand)) == Z_OK)
4753 4838 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BRAND),
4754 4839 brand);
4755 4840 else
4756 4841 (void) fprintf(fp, "%s %s\n", pt_to_str(PT_BRAND),
4757 4842 gettext("not specified"));
4758 4843 }
4759 4844
4760 4845 static void
4761 4846 info_autoboot(zone_dochandle_t handle, FILE *fp)
4762 4847 {
4763 4848 boolean_t autoboot;
4764 4849 int err;
4765 4850
4766 4851 if ((err = zonecfg_get_autoboot(handle, &autoboot)) == Z_OK)
4767 4852 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_AUTOBOOT),
4768 4853 autoboot ? "true" : "false");
4769 4854 else
4770 4855 zone_perror(zone, err, B_TRUE);
4771 4856 }
4772 4857
4773 4858 static void
4774 4859 info_pool(zone_dochandle_t handle, FILE *fp)
4775 4860 {
4776 4861 char pool[MAXNAMELEN];
4777 4862 int err;
4778 4863
4779 4864 if ((err = zonecfg_get_pool(handle, pool, sizeof (pool))) == Z_OK)
4780 4865 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_POOL), pool);
4781 4866 else
4782 4867 zone_perror(zone, err, B_TRUE);
4783 4868 }
4784 4869
4785 4870 static void
4786 4871 info_limitpriv(zone_dochandle_t handle, FILE *fp)
4787 4872 {
4788 4873 char *limitpriv;
4789 4874 int err;
4790 4875
4791 4876 if ((err = zonecfg_get_limitpriv(handle, &limitpriv)) == Z_OK) {
4792 4877 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_LIMITPRIV),
4793 4878 limitpriv);
4794 4879 free(limitpriv);
4795 4880 } else {
4796 4881 zone_perror(zone, err, B_TRUE);
4797 4882 }
4798 4883 }
4799 4884
4800 4885 static void
4801 4886 info_bootargs(zone_dochandle_t handle, FILE *fp)
4802 4887 {
4803 4888 char bootargs[BOOTARGS_MAX];
4804 4889 int err;
4805 4890
4806 4891 if ((err = zonecfg_get_bootargs(handle, bootargs,
4807 4892 sizeof (bootargs))) == Z_OK) {
4808 4893 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_BOOTARGS),
4809 4894 bootargs);
4810 4895 } else {
4811 4896 zone_perror(zone, err, B_TRUE);
4812 4897 }
4813 4898 }
4814 4899
4815 4900 static void
4816 4901 info_sched(zone_dochandle_t handle, FILE *fp)
4817 4902 {
4818 4903 char sched[MAXNAMELEN];
4819 4904 int err;
4820 4905
4821 4906 if ((err = zonecfg_get_sched_class(handle, sched, sizeof (sched)))
4822 4907 == Z_OK) {
4823 4908 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_SCHED), sched);
4824 4909 } else {
4825 4910 zone_perror(zone, err, B_TRUE);
4826 4911 }
4827 4912 }
4828 4913
4829 4914 static void
4830 4915 info_iptype(zone_dochandle_t handle, FILE *fp)
4831 4916 {
4832 4917 zone_iptype_t iptype;
4833 4918 int err;
4834 4919
4835 4920 if ((err = zonecfg_get_iptype(handle, &iptype)) == Z_OK) {
4836 4921 switch (iptype) {
4837 4922 case ZS_SHARED:
4838 4923 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
4839 4924 "shared");
4840 4925 break;
4841 4926 case ZS_EXCLUSIVE:
4842 4927 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_IPTYPE),
4843 4928 "exclusive");
4844 4929 break;
4845 4930 }
4846 4931 } else {
4847 4932 zone_perror(zone, err, B_TRUE);
4848 4933 }
4849 4934 }
4850 4935
4851 4936 static void
4852 4937 info_hostid(zone_dochandle_t handle, FILE *fp)
4853 4938 {
4854 4939 char hostidp[HW_HOSTID_LEN];
4855 4940 int err;
4856 4941
4857 4942 if ((err = zonecfg_get_hostid(handle, hostidp,
4858 4943 sizeof (hostidp))) == Z_OK) {
4859 4944 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_HOSTID), hostidp);
4860 4945 } else if (err == Z_BAD_PROPERTY) {
4861 4946 (void) fprintf(fp, "%s: \n", pt_to_str(PT_HOSTID));
4862 4947 } else {
4863 4948 zone_perror(zone, err, B_TRUE);
4864 4949 }
4865 4950 }
4866 4951
4867 4952 static void
4868 4953 info_fs_allowed(zone_dochandle_t handle, FILE *fp)
4869 4954 {
4870 4955 char fsallowedp[ZONE_FS_ALLOWED_MAX];
4871 4956 int err;
4872 4957
4873 4958 if ((err = zonecfg_get_fs_allowed(handle, fsallowedp,
4874 4959 sizeof (fsallowedp))) == Z_OK) {
4875 4960 (void) fprintf(fp, "%s: %s\n", pt_to_str(PT_FS_ALLOWED),
4876 4961 fsallowedp);
4877 4962 } else if (err == Z_BAD_PROPERTY) {
4878 4963 (void) fprintf(fp, "%s: \n", pt_to_str(PT_FS_ALLOWED));
4879 4964 } else {
4880 4965 zone_perror(zone, err, B_TRUE);
4881 4966 }
4882 4967 }
4883 4968
4884 4969 static void
4885 4970 output_fs(FILE *fp, struct zone_fstab *fstab)
4886 4971 {
4887 4972 zone_fsopt_t *this;
4888 4973
4889 4974 (void) fprintf(fp, "%s:\n", rt_to_str(RT_FS));
4890 4975 output_prop(fp, PT_DIR, fstab->zone_fs_dir, B_TRUE);
4891 4976 output_prop(fp, PT_SPECIAL, fstab->zone_fs_special, B_TRUE);
4892 4977 output_prop(fp, PT_RAW, fstab->zone_fs_raw, B_TRUE);
4893 4978 output_prop(fp, PT_TYPE, fstab->zone_fs_type, B_TRUE);
4894 4979 (void) fprintf(fp, "\t%s: [", pt_to_str(PT_OPTIONS));
4895 4980 for (this = fstab->zone_fs_options; this != NULL;
4896 4981 this = this->zone_fsopt_next) {
4897 4982 if (strchr(this->zone_fsopt_opt, '='))
4898 4983 (void) fprintf(fp, "\"%s\"", this->zone_fsopt_opt);
4899 4984 else
4900 4985 (void) fprintf(fp, "%s", this->zone_fsopt_opt);
4901 4986 if (this->zone_fsopt_next != NULL)
4902 4987 (void) fprintf(fp, ",");
4903 4988 }
4904 4989 (void) fprintf(fp, "]\n");
4905 4990 }
4906 4991
4907 4992 static void
4908 4993 info_fs(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
4909 4994 {
4910 4995 struct zone_fstab lookup, user;
4911 4996 boolean_t output = B_FALSE;
4912 4997
4913 4998 if (zonecfg_setfsent(handle) != Z_OK)
4914 4999 return;
4915 5000 while (zonecfg_getfsent(handle, &lookup) == Z_OK) {
4916 5001 if (cmd->cmd_prop_nv_pairs == 0) {
4917 5002 output_fs(fp, &lookup);
4918 5003 goto loopend;
4919 5004 }
4920 5005 if (fill_in_fstab(cmd, &user, B_TRUE) != Z_OK)
4921 5006 goto loopend;
4922 5007 if (strlen(user.zone_fs_dir) > 0 &&
4923 5008 strcmp(user.zone_fs_dir, lookup.zone_fs_dir) != 0)
4924 5009 goto loopend; /* no match */
4925 5010 if (strlen(user.zone_fs_special) > 0 &&
4926 5011 strcmp(user.zone_fs_special, lookup.zone_fs_special) != 0)
4927 5012 goto loopend; /* no match */
4928 5013 if (strlen(user.zone_fs_type) > 0 &&
4929 5014 strcmp(user.zone_fs_type, lookup.zone_fs_type) != 0)
4930 5015 goto loopend; /* no match */
4931 5016 output_fs(fp, &lookup);
4932 5017 output = B_TRUE;
4933 5018 loopend:
4934 5019 zonecfg_free_fs_option_list(lookup.zone_fs_options);
4935 5020 }
4936 5021 (void) zonecfg_endfsent(handle);
4937 5022 /*
4938 5023 * If a property n/v pair was specified, warn the user if there was
4939 5024 * nothing to output.
4940 5025 */
4941 5026 if (!output && cmd->cmd_prop_nv_pairs > 0)
4942 5027 (void) printf(gettext("No such %s resource.\n"),
4943 5028 rt_to_str(RT_FS));
4944 5029 }
4945 5030
4946 5031 static void
4947 5032 output_net(FILE *fp, struct zone_nwiftab *nwiftab)
4948 5033 {
4949 5034 (void) fprintf(fp, "%s:\n", rt_to_str(RT_NET));
4950 5035 output_prop(fp, PT_ADDRESS, nwiftab->zone_nwif_address, B_TRUE);
4951 5036 output_prop(fp, PT_ALLOWED_ADDRESS,
4952 5037 nwiftab->zone_nwif_allowed_address, B_TRUE);
4953 5038 output_prop(fp, PT_PHYSICAL, nwiftab->zone_nwif_physical, B_TRUE);
4954 5039 output_prop(fp, PT_DEFROUTER, nwiftab->zone_nwif_defrouter, B_TRUE);
4955 5040 }
4956 5041
4957 5042 static void
4958 5043 info_net(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
4959 5044 {
4960 5045 struct zone_nwiftab lookup, user;
4961 5046 boolean_t output = B_FALSE;
4962 5047
4963 5048 if (zonecfg_setnwifent(handle) != Z_OK)
4964 5049 return;
4965 5050 while (zonecfg_getnwifent(handle, &lookup) == Z_OK) {
4966 5051 if (cmd->cmd_prop_nv_pairs == 0) {
4967 5052 output_net(fp, &lookup);
4968 5053 continue;
4969 5054 }
4970 5055 if (fill_in_nwiftab(cmd, &user, B_TRUE) != Z_OK)
4971 5056 continue;
4972 5057 if (strlen(user.zone_nwif_physical) > 0 &&
4973 5058 strcmp(user.zone_nwif_physical,
4974 5059 lookup.zone_nwif_physical) != 0)
4975 5060 continue; /* no match */
4976 5061 /* If present make sure it matches */
4977 5062 if (strlen(user.zone_nwif_address) > 0 &&
4978 5063 !zonecfg_same_net_address(user.zone_nwif_address,
4979 5064 lookup.zone_nwif_address))
4980 5065 continue; /* no match */
4981 5066 output_net(fp, &lookup);
4982 5067 output = B_TRUE;
4983 5068 }
4984 5069 (void) zonecfg_endnwifent(handle);
4985 5070 /*
4986 5071 * If a property n/v pair was specified, warn the user if there was
4987 5072 * nothing to output.
4988 5073 */
4989 5074 if (!output && cmd->cmd_prop_nv_pairs > 0)
4990 5075 (void) printf(gettext("No such %s resource.\n"),
4991 5076 rt_to_str(RT_NET));
4992 5077 }
4993 5078
4994 5079 static void
4995 5080 output_dev(FILE *fp, struct zone_devtab *devtab)
4996 5081 {
4997 5082 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DEVICE));
4998 5083 output_prop(fp, PT_MATCH, devtab->zone_dev_match, B_TRUE);
4999 5084 }
5000 5085
5001 5086 static void
5002 5087 info_dev(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5003 5088 {
5004 5089 struct zone_devtab lookup, user;
5005 5090 boolean_t output = B_FALSE;
5006 5091
5007 5092 if (zonecfg_setdevent(handle) != Z_OK)
5008 5093 return;
5009 5094 while (zonecfg_getdevent(handle, &lookup) == Z_OK) {
5010 5095 if (cmd->cmd_prop_nv_pairs == 0) {
5011 5096 output_dev(fp, &lookup);
5012 5097 continue;
5013 5098 }
5014 5099 if (fill_in_devtab(cmd, &user, B_TRUE) != Z_OK)
5015 5100 continue;
5016 5101 if (strlen(user.zone_dev_match) > 0 &&
5017 5102 strcmp(user.zone_dev_match, lookup.zone_dev_match) != 0)
5018 5103 continue; /* no match */
5019 5104 output_dev(fp, &lookup);
5020 5105 output = B_TRUE;
5021 5106 }
5022 5107 (void) zonecfg_enddevent(handle);
5023 5108 /*
5024 5109 * If a property n/v pair was specified, warn the user if there was
5025 5110 * nothing to output.
5026 5111 */
5027 5112 if (!output && cmd->cmd_prop_nv_pairs > 0)
5028 5113 (void) printf(gettext("No such %s resource.\n"),
5029 5114 rt_to_str(RT_DEVICE));
5030 5115 }
5031 5116
5032 5117 static void
5033 5118 output_rctl(FILE *fp, struct zone_rctltab *rctltab)
5034 5119 {
5035 5120 struct zone_rctlvaltab *valptr;
5036 5121
5037 5122 (void) fprintf(fp, "%s:\n", rt_to_str(RT_RCTL));
5038 5123 output_prop(fp, PT_NAME, rctltab->zone_rctl_name, B_TRUE);
5039 5124 for (valptr = rctltab->zone_rctl_valptr; valptr != NULL;
5040 5125 valptr = valptr->zone_rctlval_next) {
5041 5126 fprintf(fp, "\t%s: (%s=%s,%s=%s,%s=%s)\n",
5042 5127 pt_to_str(PT_VALUE),
5043 5128 pt_to_str(PT_PRIV), valptr->zone_rctlval_priv,
5044 5129 pt_to_str(PT_LIMIT), valptr->zone_rctlval_limit,
5045 5130 pt_to_str(PT_ACTION), valptr->zone_rctlval_action);
5046 5131 }
5047 5132 }
5048 5133
5049 5134 static void
5050 5135 info_rctl(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5051 5136 {
5052 5137 struct zone_rctltab lookup, user;
5053 5138 boolean_t output = B_FALSE;
5054 5139
5055 5140 if (zonecfg_setrctlent(handle) != Z_OK)
5056 5141 return;
5057 5142 while (zonecfg_getrctlent(handle, &lookup) == Z_OK) {
5058 5143 if (cmd->cmd_prop_nv_pairs == 0) {
5059 5144 output_rctl(fp, &lookup);
5060 5145 } else if (fill_in_rctltab(cmd, &user, B_TRUE) == Z_OK &&
5061 5146 (strlen(user.zone_rctl_name) == 0 ||
5062 5147 strcmp(user.zone_rctl_name, lookup.zone_rctl_name) == 0)) {
5063 5148 output_rctl(fp, &lookup);
5064 5149 output = B_TRUE;
5065 5150 }
5066 5151 zonecfg_free_rctl_value_list(lookup.zone_rctl_valptr);
5067 5152 }
5068 5153 (void) zonecfg_endrctlent(handle);
5069 5154 /*
5070 5155 * If a property n/v pair was specified, warn the user if there was
5071 5156 * nothing to output.
5072 5157 */
5073 5158 if (!output && cmd->cmd_prop_nv_pairs > 0)
5074 5159 (void) printf(gettext("No such %s resource.\n"),
5075 5160 rt_to_str(RT_RCTL));
5076 5161 }
5077 5162
5078 5163 static void
5079 5164 output_attr(FILE *fp, struct zone_attrtab *attrtab)
5080 5165 {
5081 5166 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ATTR));
5082 5167 output_prop(fp, PT_NAME, attrtab->zone_attr_name, B_TRUE);
5083 5168 output_prop(fp, PT_TYPE, attrtab->zone_attr_type, B_TRUE);
5084 5169 output_prop(fp, PT_VALUE, attrtab->zone_attr_value, B_TRUE);
5085 5170 }
5086 5171
5087 5172 static void
5088 5173 info_attr(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5089 5174 {
5090 5175 struct zone_attrtab lookup, user;
5091 5176 boolean_t output = B_FALSE;
5092 5177
5093 5178 if (zonecfg_setattrent(handle) != Z_OK)
5094 5179 return;
5095 5180 while (zonecfg_getattrent(handle, &lookup) == Z_OK) {
5096 5181 if (cmd->cmd_prop_nv_pairs == 0) {
5097 5182 output_attr(fp, &lookup);
5098 5183 continue;
5099 5184 }
5100 5185 if (fill_in_attrtab(cmd, &user, B_TRUE) != Z_OK)
5101 5186 continue;
5102 5187 if (strlen(user.zone_attr_name) > 0 &&
5103 5188 strcmp(user.zone_attr_name, lookup.zone_attr_name) != 0)
5104 5189 continue; /* no match */
5105 5190 if (strlen(user.zone_attr_type) > 0 &&
5106 5191 strcmp(user.zone_attr_type, lookup.zone_attr_type) != 0)
5107 5192 continue; /* no match */
5108 5193 if (strlen(user.zone_attr_value) > 0 &&
5109 5194 strcmp(user.zone_attr_value, lookup.zone_attr_value) != 0)
5110 5195 continue; /* no match */
5111 5196 output_attr(fp, &lookup);
5112 5197 output = B_TRUE;
5113 5198 }
5114 5199 (void) zonecfg_endattrent(handle);
5115 5200 /*
5116 5201 * If a property n/v pair was specified, warn the user if there was
5117 5202 * nothing to output.
5118 5203 */
5119 5204 if (!output && cmd->cmd_prop_nv_pairs > 0)
5120 5205 (void) printf(gettext("No such %s resource.\n"),
5121 5206 rt_to_str(RT_ATTR));
5122 5207 }
5123 5208
5124 5209 static void
5125 5210 output_ds(FILE *fp, struct zone_dstab *dstab)
5126 5211 {
5127 5212 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DATASET));
5128 5213 output_prop(fp, PT_NAME, dstab->zone_dataset_name, B_TRUE);
5129 5214 }
5130 5215
5131 5216 static void
5132 5217 info_ds(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5133 5218 {
5134 5219 struct zone_dstab lookup, user;
5135 5220 boolean_t output = B_FALSE;
5136 5221
5137 5222 if (zonecfg_setdsent(handle) != Z_OK)
5138 5223 return;
5139 5224 while (zonecfg_getdsent(handle, &lookup) == Z_OK) {
5140 5225 if (cmd->cmd_prop_nv_pairs == 0) {
5141 5226 output_ds(fp, &lookup);
5142 5227 continue;
5143 5228 }
5144 5229 if (fill_in_dstab(cmd, &user, B_TRUE) != Z_OK)
5145 5230 continue;
5146 5231 if (strlen(user.zone_dataset_name) > 0 &&
5147 5232 strcmp(user.zone_dataset_name,
5148 5233 lookup.zone_dataset_name) != 0)
5149 5234 continue; /* no match */
5150 5235 output_ds(fp, &lookup);
5151 5236 output = B_TRUE;
5152 5237 }
5153 5238 (void) zonecfg_enddsent(handle);
5154 5239 /*
5155 5240 * If a property n/v pair was specified, warn the user if there was
5156 5241 * nothing to output.
5157 5242 */
5158 5243 if (!output && cmd->cmd_prop_nv_pairs > 0)
5159 5244 (void) printf(gettext("No such %s resource.\n"),
5160 5245 rt_to_str(RT_DATASET));
5161 5246 }
5162 5247
5163 5248 static void
5164 5249 output_pset(FILE *fp, struct zone_psettab *psettab)
5165 5250 {
5166 5251 (void) fprintf(fp, "%s:\n", rt_to_str(RT_DCPU));
5167 5252 if (strcmp(psettab->zone_ncpu_min, psettab->zone_ncpu_max) == 0)
5168 5253 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_NCPUS),
5169 5254 psettab->zone_ncpu_max);
5170 5255 else
5171 5256 (void) fprintf(fp, "\t%s: %s-%s\n", pt_to_str(PT_NCPUS),
5172 5257 psettab->zone_ncpu_min, psettab->zone_ncpu_max);
5173 5258 if (psettab->zone_importance[0] != '\0')
5174 5259 (void) fprintf(fp, "\t%s: %s\n", pt_to_str(PT_IMPORTANCE),
5175 5260 psettab->zone_importance);
5176 5261 }
5177 5262
5178 5263 static void
5179 5264 info_pset(zone_dochandle_t handle, FILE *fp)
5180 5265 {
5181 5266 struct zone_psettab lookup;
5182 5267
5183 5268 if (zonecfg_getpsetent(handle, &lookup) == Z_OK)
5184 5269 output_pset(fp, &lookup);
5185 5270 }
5186 5271
5187 5272 static void
5188 5273 output_pcap(FILE *fp)
5189 5274 {
5190 5275 uint64_t cap;
5191 5276
5192 5277 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &cap) == Z_OK) {
5193 5278 float scaled = (float)cap / 100;
5194 5279 (void) fprintf(fp, "%s:\n", rt_to_str(RT_PCAP));
5195 5280 (void) fprintf(fp, "\t[%s: %.2f]\n", pt_to_str(PT_NCPUS),
5196 5281 scaled);
5197 5282 }
5198 5283 }
5199 5284
5200 5285 static void
5201 5286 info_pcap(FILE *fp)
5202 5287 {
5203 5288 output_pcap(fp);
5204 5289 }
5205 5290
5206 5291
5207 5292 static void
5208 5293 info_aliased_rctl(zone_dochandle_t handle, FILE *fp, char *alias)
5209 5294 {
5210 5295 uint64_t limit;
5211 5296
5212 5297 if (zonecfg_get_aliased_rctl(handle, alias, &limit) == Z_OK) {
5213 5298 /* convert memory based properties */
5214 5299 if (strcmp(alias, ALIAS_MAXSHMMEM) == 0) {
5215 5300 char buf[128];
5216 5301
5217 5302 (void) snprintf(buf, sizeof (buf), "%llu", limit);
5218 5303 bytes_to_units(buf, buf, sizeof (buf));
5219 5304 (void) fprintf(fp, "[%s: %s]\n", alias, buf);
5220 5305 return;
5221 5306 }
5222 5307
5223 5308 (void) fprintf(fp, "[%s: %llu]\n", alias, limit);
5224 5309 }
5225 5310 }
5226 5311
5227 5312 static void
5228 5313 bytes_to_units(char *str, char *buf, int bufsize)
5229 5314 {
5230 5315 unsigned long long num;
5231 5316 unsigned long long save = 0;
5232 5317 char *units = "BKMGT";
5233 5318 char *up = units;
5234 5319
5235 5320 num = strtoll(str, NULL, 10);
5236 5321
5237 5322 if (num < 1024) {
5238 5323 (void) snprintf(buf, bufsize, "%llu", num);
5239 5324 return;
5240 5325 }
5241 5326
5242 5327 while ((num >= 1024) && (*up != 'T')) {
5243 5328 up++; /* next unit of measurement */
5244 5329 save = num;
5245 5330 num = (num + 512) >> 10;
5246 5331 }
5247 5332
5248 5333 /* check if we should output a fraction. snprintf will round for us */
5249 5334 if (save % 1024 != 0 && ((save >> 10) < 10))
5250 5335 (void) snprintf(buf, bufsize, "%2.1f%c", ((float)save / 1024),
5251 5336 *up);
5252 5337 else
5253 5338 (void) snprintf(buf, bufsize, "%llu%c", num, *up);
5254 5339 }
5255 5340
5256 5341 static void
5257 5342 output_mcap(FILE *fp, struct zone_mcaptab *mcaptab, int showswap,
5258 5343 uint64_t maxswap, int showlocked, uint64_t maxlocked)
5259 5344 {
5260 5345 char buf[128];
5261 5346
5262 5347 (void) fprintf(fp, "%s:\n", rt_to_str(RT_MCAP));
5263 5348 if (mcaptab->zone_physmem_cap[0] != '\0') {
5264 5349 bytes_to_units(mcaptab->zone_physmem_cap, buf, sizeof (buf));
5265 5350 output_prop(fp, PT_PHYSICAL, buf, B_TRUE);
5266 5351 }
5267 5352
5268 5353 if (showswap == Z_OK) {
5269 5354 (void) snprintf(buf, sizeof (buf), "%llu", maxswap);
5270 5355 bytes_to_units(buf, buf, sizeof (buf));
5271 5356 output_prop(fp, PT_SWAP, buf, B_TRUE);
5272 5357 }
5273 5358
5274 5359 if (showlocked == Z_OK) {
5275 5360 (void) snprintf(buf, sizeof (buf), "%llu", maxlocked);
5276 5361 bytes_to_units(buf, buf, sizeof (buf));
5277 5362 output_prop(fp, PT_LOCKED, buf, B_TRUE);
5278 5363 }
5279 5364 }
5280 5365
5281 5366 static void
5282 5367 info_mcap(zone_dochandle_t handle, FILE *fp)
5283 5368 {
5284 5369 int res1, res2, res3;
5285 5370 uint64_t swap_limit;
5286 5371 uint64_t locked_limit;
5287 5372 struct zone_mcaptab lookup;
5288 5373
5289 5374 bzero(&lookup, sizeof (lookup));
5290 5375 res1 = zonecfg_getmcapent(handle, &lookup);
5291 5376 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP, &swap_limit);
5292 5377 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
5293 5378 &locked_limit);
5294 5379
5295 5380 if (res1 == Z_OK || res2 == Z_OK || res3 == Z_OK)
5296 5381 output_mcap(fp, &lookup, res2, swap_limit, res3, locked_limit);
5297 5382 }
5298 5383
5299 5384 static void
5300 5385 output_auth(FILE *fp, struct zone_admintab *admintab)
5301 5386 {
5302 5387 (void) fprintf(fp, "%s:\n", rt_to_str(RT_ADMIN));
5303 5388 output_prop(fp, PT_USER, admintab->zone_admin_user, B_TRUE);
5304 5389 output_prop(fp, PT_AUTHS, admintab->zone_admin_auths, B_TRUE);
5305 5390 }
5306 5391
5307 5392 static void
5308 5393 info_auth(zone_dochandle_t handle, FILE *fp, cmd_t *cmd)
5309 5394 {
5310 5395 struct zone_admintab lookup, user;
5311 5396 boolean_t output = B_FALSE;
5312 5397 int err;
5313 5398
5314 5399 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
5315 5400 zone_perror(zone, err, B_TRUE);
5316 5401 return;
5317 5402 }
5318 5403 while (zonecfg_getadminent(handle, &lookup) == Z_OK) {
5319 5404 if (cmd->cmd_prop_nv_pairs == 0) {
5320 5405 output_auth(fp, &lookup);
5321 5406 continue;
5322 5407 }
5323 5408 if (fill_in_admintab(cmd, &user, B_TRUE) != Z_OK)
5324 5409 continue;
5325 5410 if (strlen(user.zone_admin_user) > 0 &&
5326 5411 strcmp(user.zone_admin_user, lookup.zone_admin_user) != 0)
5327 5412 continue; /* no match */
5328 5413 output_auth(fp, &lookup);
5329 5414 output = B_TRUE;
5330 5415 }
5331 5416 (void) zonecfg_endadminent(handle);
5332 5417 /*
5333 5418 * If a property n/v pair was specified, warn the user if there was
5334 5419 * nothing to output.
5335 5420 */
↓ open down ↓ |
4048 lines elided |
↑ open up ↑ |
5336 5421 if (!output && cmd->cmd_prop_nv_pairs > 0)
5337 5422 (void) printf(gettext("No such %s resource.\n"),
5338 5423 rt_to_str(RT_ADMIN));
5339 5424 }
5340 5425
5341 5426 void
5342 5427 info_func(cmd_t *cmd)
5343 5428 {
5344 5429 FILE *fp = stdout;
5345 5430 boolean_t need_to_close = B_FALSE;
5346 - char *pager, *space;
5347 5431 int type;
5348 5432 int res1, res2;
5349 5433 uint64_t swap_limit;
5350 5434 uint64_t locked_limit;
5351 - struct stat statbuf;
5352 5435
5353 5436 assert(cmd != NULL);
5354 5437
5355 5438 if (initialize(B_TRUE) != Z_OK)
5356 5439 return;
5357 5440
5358 5441 /* don't page error output */
5359 5442 if (interactive_mode) {
5360 - if ((pager = getenv("PAGER")) == NULL)
5361 - pager = PAGER;
5362 - space = strchr(pager, ' ');
5363 - if (space)
5364 - *space = '\0';
5365 - if (stat(pager, &statbuf) == 0) {
5366 - if (space)
5367 - *space = ' ';
5368 - if ((fp = popen(pager, "w")) != NULL)
5369 - need_to_close = B_TRUE;
5370 - else
5371 - fp = stdout;
5372 - } else {
5373 - zerr(gettext("PAGER %s does not exist (%s)."),
5374 - pager, strerror(errno));
5375 - }
5443 + if ((fp = pager_open()) != NULL)
5444 + need_to_close = B_TRUE;
5445 + else
5446 + fp = stdout;
5376 5447
5377 5448 setbuf(fp, NULL);
5378 5449 }
5379 5450
5380 5451 if (!global_scope) {
5381 5452 switch (resource_scope) {
5382 5453 case RT_FS:
5383 5454 output_fs(fp, &in_progress_fstab);
5384 5455 break;
5385 5456 case RT_NET:
5386 5457 output_net(fp, &in_progress_nwiftab);
5387 5458 break;
5388 5459 case RT_DEVICE:
5389 5460 output_dev(fp, &in_progress_devtab);
5390 5461 break;
5391 5462 case RT_RCTL:
5392 5463 output_rctl(fp, &in_progress_rctltab);
5393 5464 break;
5394 5465 case RT_ATTR:
5395 5466 output_attr(fp, &in_progress_attrtab);
5396 5467 break;
5397 5468 case RT_DATASET:
5398 5469 output_ds(fp, &in_progress_dstab);
5399 5470 break;
5400 5471 case RT_DCPU:
5401 5472 output_pset(fp, &in_progress_psettab);
5402 5473 break;
5403 5474 case RT_PCAP:
5404 5475 output_pcap(fp);
5405 5476 break;
5406 5477 case RT_MCAP:
5407 5478 res1 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
5408 5479 &swap_limit);
5409 5480 res2 = zonecfg_get_aliased_rctl(handle,
5410 5481 ALIAS_MAXLOCKEDMEM, &locked_limit);
5411 5482 output_mcap(fp, &in_progress_mcaptab, res1, swap_limit,
5412 5483 res2, locked_limit);
5413 5484 break;
5414 5485 case RT_ADMIN:
5415 5486 output_auth(fp, &in_progress_admintab);
5416 5487 break;
5417 5488 }
5418 5489 goto cleanup;
5419 5490 }
5420 5491
5421 5492 type = cmd->cmd_res_type;
5422 5493
5423 5494 if (gz_invalid_rt_property(type)) {
5424 5495 zerr(gettext("%s is not a valid property for the global zone."),
5425 5496 rt_to_str(type));
5426 5497 goto cleanup;
5427 5498 }
5428 5499
5429 5500 if (gz_invalid_resource(type)) {
5430 5501 zerr(gettext("%s is not a valid resource for the global zone."),
5431 5502 rt_to_str(type));
5432 5503 goto cleanup;
5433 5504 }
5434 5505
5435 5506 switch (cmd->cmd_res_type) {
5436 5507 case RT_UNKNOWN:
5437 5508 info_zonename(handle, fp);
5438 5509 if (!global_zone) {
5439 5510 info_zonepath(handle, fp);
5440 5511 info_brand(handle, fp);
5441 5512 info_autoboot(handle, fp);
5442 5513 info_bootargs(handle, fp);
5443 5514 }
5444 5515 info_pool(handle, fp);
5445 5516 if (!global_zone) {
5446 5517 info_limitpriv(handle, fp);
5447 5518 info_sched(handle, fp);
5448 5519 info_iptype(handle, fp);
5449 5520 info_hostid(handle, fp);
5450 5521 info_fs_allowed(handle, fp);
5451 5522 }
5452 5523 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5453 5524 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5454 5525 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5455 5526 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5456 5527 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5457 5528 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5458 5529 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5459 5530 if (!global_zone) {
5460 5531 info_fs(handle, fp, cmd);
5461 5532 info_net(handle, fp, cmd);
5462 5533 info_dev(handle, fp, cmd);
5463 5534 }
5464 5535 info_pset(handle, fp);
5465 5536 info_pcap(fp);
5466 5537 info_mcap(handle, fp);
5467 5538 if (!global_zone) {
5468 5539 info_attr(handle, fp, cmd);
5469 5540 info_ds(handle, fp, cmd);
5470 5541 info_auth(handle, fp, cmd);
5471 5542 }
5472 5543 info_rctl(handle, fp, cmd);
5473 5544 break;
5474 5545 case RT_ZONENAME:
5475 5546 info_zonename(handle, fp);
5476 5547 break;
5477 5548 case RT_ZONEPATH:
5478 5549 info_zonepath(handle, fp);
5479 5550 break;
5480 5551 case RT_BRAND:
5481 5552 info_brand(handle, fp);
5482 5553 break;
5483 5554 case RT_AUTOBOOT:
5484 5555 info_autoboot(handle, fp);
5485 5556 break;
5486 5557 case RT_POOL:
5487 5558 info_pool(handle, fp);
5488 5559 break;
5489 5560 case RT_LIMITPRIV:
5490 5561 info_limitpriv(handle, fp);
5491 5562 break;
5492 5563 case RT_BOOTARGS:
5493 5564 info_bootargs(handle, fp);
5494 5565 break;
5495 5566 case RT_SCHED:
5496 5567 info_sched(handle, fp);
5497 5568 break;
5498 5569 case RT_IPTYPE:
5499 5570 info_iptype(handle, fp);
5500 5571 break;
5501 5572 case RT_MAXLWPS:
5502 5573 info_aliased_rctl(handle, fp, ALIAS_MAXLWPS);
5503 5574 break;
5504 5575 case RT_MAXPROCS:
5505 5576 info_aliased_rctl(handle, fp, ALIAS_MAXPROCS);
5506 5577 break;
5507 5578 case RT_MAXSHMMEM:
5508 5579 info_aliased_rctl(handle, fp, ALIAS_MAXSHMMEM);
5509 5580 break;
5510 5581 case RT_MAXSHMIDS:
5511 5582 info_aliased_rctl(handle, fp, ALIAS_MAXSHMIDS);
5512 5583 break;
5513 5584 case RT_MAXMSGIDS:
5514 5585 info_aliased_rctl(handle, fp, ALIAS_MAXMSGIDS);
5515 5586 break;
5516 5587 case RT_MAXSEMIDS:
5517 5588 info_aliased_rctl(handle, fp, ALIAS_MAXSEMIDS);
5518 5589 break;
5519 5590 case RT_SHARES:
5520 5591 info_aliased_rctl(handle, fp, ALIAS_SHARES);
5521 5592 break;
5522 5593 case RT_FS:
5523 5594 info_fs(handle, fp, cmd);
5524 5595 break;
5525 5596 case RT_NET:
5526 5597 info_net(handle, fp, cmd);
5527 5598 break;
5528 5599 case RT_DEVICE:
5529 5600 info_dev(handle, fp, cmd);
5530 5601 break;
5531 5602 case RT_RCTL:
5532 5603 info_rctl(handle, fp, cmd);
5533 5604 break;
5534 5605 case RT_ATTR:
5535 5606 info_attr(handle, fp, cmd);
5536 5607 break;
5537 5608 case RT_DATASET:
5538 5609 info_ds(handle, fp, cmd);
5539 5610 break;
5540 5611 case RT_DCPU:
5541 5612 info_pset(handle, fp);
5542 5613 break;
5543 5614 case RT_PCAP:
5544 5615 info_pcap(fp);
5545 5616 break;
5546 5617 case RT_MCAP:
5547 5618 info_mcap(handle, fp);
5548 5619 break;
5549 5620 case RT_HOSTID:
5550 5621 info_hostid(handle, fp);
5551 5622 break;
5552 5623 case RT_ADMIN:
5553 5624 info_auth(handle, fp, cmd);
5554 5625 break;
↓ open down ↓ |
169 lines elided |
↑ open up ↑ |
5555 5626 case RT_FS_ALLOWED:
5556 5627 info_fs_allowed(handle, fp);
5557 5628 break;
5558 5629 default:
5559 5630 zone_perror(rt_to_str(cmd->cmd_res_type), Z_NO_RESOURCE_TYPE,
5560 5631 B_TRUE);
5561 5632 }
5562 5633
5563 5634 cleanup:
5564 5635 if (need_to_close)
5565 - (void) pclose(fp);
5636 + (void) pager_close(fp);
5566 5637 }
5567 5638
5568 5639 /*
5569 5640 * Helper function for verify-- checks that a required string property
5570 5641 * exists.
5571 5642 */
5572 5643 static void
5573 5644 check_reqd_prop(char *attr, int rt, int pt, int *ret_val)
5574 5645 {
5575 5646 if (strlen(attr) == 0) {
5576 5647 zerr(gettext("%s: %s not specified"), rt_to_str(rt),
5577 5648 pt_to_str(pt));
5578 5649 saw_error = B_TRUE;
5579 5650 if (*ret_val == Z_OK)
5580 5651 *ret_val = Z_REQD_PROPERTY_MISSING;
5581 5652 }
5582 5653 }
5583 5654
5584 5655 static int
5585 5656 do_subproc(char *cmdbuf)
5586 5657 {
5587 5658 char inbuf[MAX_CMD_LEN];
5588 5659 FILE *file;
5589 5660 int status;
5590 5661
5591 5662 file = popen(cmdbuf, "r");
5592 5663 if (file == NULL) {
5593 5664 zerr(gettext("Could not launch: %s"), cmdbuf);
5594 5665 return (-1);
5595 5666 }
5596 5667
5597 5668 while (fgets(inbuf, sizeof (inbuf), file) != NULL)
5598 5669 fprintf(stderr, "%s", inbuf);
5599 5670 status = pclose(file);
5600 5671
5601 5672 if (WIFSIGNALED(status)) {
5602 5673 zerr(gettext("%s unexpectedly terminated due to signal %d"),
5603 5674 cmdbuf, WTERMSIG(status));
5604 5675 return (-1);
5605 5676 }
5606 5677 assert(WIFEXITED(status));
5607 5678 return (WEXITSTATUS(status));
5608 5679 }
5609 5680
5610 5681 static int
5611 5682 brand_verify(zone_dochandle_t handle)
5612 5683 {
5613 5684 char xml_file[32];
5614 5685 char cmdbuf[MAX_CMD_LEN];
5615 5686 brand_handle_t bh;
5616 5687 char brand[MAXNAMELEN];
5617 5688 int err;
5618 5689
5619 5690 if (zonecfg_get_brand(handle, brand, sizeof (brand)) != Z_OK) {
5620 5691 zerr("%s: %s\n", zone, gettext("could not get zone brand"));
5621 5692 return (Z_INVALID_DOCUMENT);
5622 5693 }
5623 5694 if ((bh = brand_open(brand)) == NULL) {
5624 5695 zerr("%s: %s\n", zone, gettext("unknown brand."));
5625 5696 return (Z_INVALID_DOCUMENT);
5626 5697 }
5627 5698
5628 5699 /*
5629 5700 * Fetch the verify command, if any, from the brand configuration
5630 5701 * and build the command line to execute it.
5631 5702 */
5632 5703 strcpy(cmdbuf, EXEC_PREFIX);
5633 5704 err = brand_get_verify_cfg(bh, cmdbuf + EXEC_LEN,
5634 5705 sizeof (cmdbuf) - (EXEC_LEN + (strlen(xml_file) + 1)));
5635 5706 brand_close(bh);
5636 5707 if (err != Z_OK) {
5637 5708 zerr("%s: %s\n", zone,
5638 5709 gettext("could not get brand verification command"));
5639 5710 return (Z_INVALID_DOCUMENT);
5640 5711 }
5641 5712
5642 5713 /*
5643 5714 * If the brand doesn't provide a verification routine, we just
5644 5715 * return success.
5645 5716 */
5646 5717 if (strlen(cmdbuf) == EXEC_LEN)
5647 5718 return (Z_OK);
5648 5719
5649 5720 /*
5650 5721 * Dump the current config information for this zone to a file.
5651 5722 */
5652 5723 strcpy(xml_file, "/tmp/zonecfg_verify.XXXXXX");
5653 5724 if (mkstemp(xml_file) == NULL)
5654 5725 return (Z_TEMP_FILE);
5655 5726 if ((err = zonecfg_verify_save(handle, xml_file)) != Z_OK) {
5656 5727 (void) unlink(xml_file);
5657 5728 return (err);
5658 5729 }
5659 5730
5660 5731 /*
5661 5732 * Execute the verification command.
5662 5733 */
5663 5734 if ((strlcat(cmdbuf, " ", MAX_CMD_LEN) >= MAX_CMD_LEN) ||
5664 5735 (strlcat(cmdbuf, xml_file, MAX_CMD_LEN) >= MAX_CMD_LEN)) {
5665 5736 err = Z_BRAND_ERROR;
5666 5737 } else {
5667 5738 err = do_subproc(cmdbuf);
5668 5739 }
5669 5740
5670 5741 (void) unlink(xml_file);
5671 5742 return ((err == Z_OK) ? Z_OK : Z_BRAND_ERROR);
5672 5743 }
5673 5744
5674 5745 /*
5675 5746 * Track the network interfaces listed in zonecfg(1m) in a linked list
5676 5747 * so that we can later check that defrouter is specified for an exclusive IP
5677 5748 * zone if and only if at least one allowed-address has been specified.
5678 5749 */
5679 5750 static boolean_t
5680 5751 add_nwif(struct zone_nwiftab *nwif)
5681 5752 {
5682 5753 struct xif *tmp;
5683 5754
5684 5755 for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
5685 5756 if (strcmp(tmp->xif_name, nwif->zone_nwif_physical) == 0) {
5686 5757 if (strlen(nwif->zone_nwif_allowed_address) > 0)
5687 5758 tmp->xif_has_address = B_TRUE;
5688 5759 if (strlen(nwif->zone_nwif_defrouter) > 0)
5689 5760 tmp->xif_has_defrouter = B_TRUE;
5690 5761 return (B_TRUE);
5691 5762 }
5692 5763 }
5693 5764
5694 5765 tmp = malloc(sizeof (*tmp));
5695 5766 if (tmp == NULL) {
5696 5767 zerr(gettext("memory allocation failed for %s"),
5697 5768 nwif->zone_nwif_physical);
5698 5769 return (B_FALSE);
5699 5770 }
5700 5771 strlcpy(tmp->xif_name, nwif->zone_nwif_physical,
5701 5772 sizeof (tmp->xif_name));
5702 5773 tmp->xif_has_defrouter = (strlen(nwif->zone_nwif_defrouter) > 0);
5703 5774 tmp->xif_has_address = (strlen(nwif->zone_nwif_allowed_address) > 0);
5704 5775 tmp->xif_next = xif;
5705 5776 xif = tmp;
5706 5777 return (B_TRUE);
5707 5778 }
5708 5779
5709 5780 /*
5710 5781 * See the DTD for which attributes are required for which resources.
5711 5782 *
5712 5783 * This function can be called by commit_func(), which needs to save things,
5713 5784 * in addition to the general call from parse_and_run(), which doesn't need
5714 5785 * things saved. Since the parameters are standardized, we distinguish by
5715 5786 * having commit_func() call here with cmd->cmd_arg set to "save" to indicate
5716 5787 * that a save is needed.
5717 5788 */
5718 5789 void
5719 5790 verify_func(cmd_t *cmd)
5720 5791 {
5721 5792 struct zone_nwiftab nwiftab;
5722 5793 struct zone_fstab fstab;
5723 5794 struct zone_attrtab attrtab;
5724 5795 struct zone_rctltab rctltab;
5725 5796 struct zone_dstab dstab;
5726 5797 struct zone_psettab psettab;
5727 5798 struct zone_admintab admintab;
5728 5799 char zonepath[MAXPATHLEN];
5729 5800 char sched[MAXNAMELEN];
5730 5801 char brand[MAXNAMELEN];
5731 5802 char hostidp[HW_HOSTID_LEN];
5732 5803 char fsallowedp[ZONE_FS_ALLOWED_MAX];
5733 5804 priv_set_t *privs;
5734 5805 char *privname = NULL;
5735 5806 int err, ret_val = Z_OK, arg;
5736 5807 int pset_res;
5737 5808 boolean_t save = B_FALSE;
5738 5809 boolean_t arg_err = B_FALSE;
5739 5810 zone_iptype_t iptype;
5740 5811 boolean_t has_cpu_shares = B_FALSE;
5741 5812 boolean_t has_cpu_cap = B_FALSE;
5742 5813 struct xif *tmp;
5743 5814
5744 5815 optind = 0;
5745 5816 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
5746 5817 switch (arg) {
5747 5818 case '?':
5748 5819 longer_usage(CMD_VERIFY);
5749 5820 arg_err = B_TRUE;
5750 5821 break;
5751 5822 default:
5752 5823 short_usage(CMD_VERIFY);
5753 5824 arg_err = B_TRUE;
5754 5825 break;
5755 5826 }
5756 5827 }
5757 5828 if (arg_err)
5758 5829 return;
5759 5830
5760 5831 if (optind > cmd->cmd_argc) {
5761 5832 short_usage(CMD_VERIFY);
5762 5833 return;
5763 5834 }
5764 5835
5765 5836 if (zone_is_read_only(CMD_VERIFY))
5766 5837 return;
5767 5838
5768 5839 assert(cmd != NULL);
5769 5840
5770 5841 if (cmd->cmd_argc > 0 && (strcmp(cmd->cmd_argv[0], "save") == 0))
5771 5842 save = B_TRUE;
5772 5843 if (initialize(B_TRUE) != Z_OK)
5773 5844 return;
5774 5845
5775 5846 if (zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath)) != Z_OK &&
5776 5847 !global_zone) {
5777 5848 zerr(gettext("%s not specified"), pt_to_str(PT_ZONEPATH));
5778 5849 ret_val = Z_REQD_RESOURCE_MISSING;
5779 5850 saw_error = B_TRUE;
5780 5851 }
5781 5852 if (strlen(zonepath) == 0 && !global_zone) {
5782 5853 zerr(gettext("%s cannot be empty."), pt_to_str(PT_ZONEPATH));
5783 5854 ret_val = Z_REQD_RESOURCE_MISSING;
5784 5855 saw_error = B_TRUE;
5785 5856 }
5786 5857
5787 5858 if ((err = zonecfg_get_brand(handle, brand, sizeof (brand))) != Z_OK) {
5788 5859 zone_perror(zone, err, B_TRUE);
5789 5860 return;
5790 5861 }
5791 5862 if ((err = brand_verify(handle)) != Z_OK) {
5792 5863 zone_perror(zone, err, B_TRUE);
5793 5864 return;
5794 5865 }
5795 5866
5796 5867 if (zonecfg_get_iptype(handle, &iptype) != Z_OK) {
5797 5868 zerr("%s %s", gettext("cannot get"), pt_to_str(PT_IPTYPE));
5798 5869 ret_val = Z_REQD_RESOURCE_MISSING;
5799 5870 saw_error = B_TRUE;
5800 5871 }
5801 5872
5802 5873 if ((privs = priv_allocset()) == NULL) {
5803 5874 zerr(gettext("%s: priv_allocset failed"), zone);
5804 5875 return;
5805 5876 }
5806 5877 if (zonecfg_get_privset(handle, privs, &privname) != Z_OK) {
5807 5878 zerr(gettext("%s: invalid privilege: %s"), zone, privname);
5808 5879 priv_freeset(privs);
5809 5880 free(privname);
5810 5881 return;
5811 5882 }
5812 5883 priv_freeset(privs);
5813 5884
5814 5885 if (zonecfg_get_hostid(handle, hostidp,
5815 5886 sizeof (hostidp)) == Z_INVALID_PROPERTY) {
5816 5887 zerr(gettext("%s: invalid hostid: %s"),
5817 5888 zone, hostidp);
5818 5889 return;
5819 5890 }
5820 5891
5821 5892 if (zonecfg_get_fs_allowed(handle, fsallowedp,
5822 5893 sizeof (fsallowedp)) == Z_INVALID_PROPERTY) {
5823 5894 zerr(gettext("%s: invalid fs-allowed: %s"),
5824 5895 zone, fsallowedp);
5825 5896 return;
5826 5897 }
5827 5898
5828 5899 if ((err = zonecfg_setfsent(handle)) != Z_OK) {
5829 5900 zone_perror(zone, err, B_TRUE);
5830 5901 return;
5831 5902 }
5832 5903 while (zonecfg_getfsent(handle, &fstab) == Z_OK) {
5833 5904 check_reqd_prop(fstab.zone_fs_dir, RT_FS, PT_DIR, &ret_val);
5834 5905 check_reqd_prop(fstab.zone_fs_special, RT_FS, PT_SPECIAL,
5835 5906 &ret_val);
5836 5907 check_reqd_prop(fstab.zone_fs_type, RT_FS, PT_TYPE, &ret_val);
5837 5908
5838 5909 zonecfg_free_fs_option_list(fstab.zone_fs_options);
5839 5910 }
5840 5911 (void) zonecfg_endfsent(handle);
5841 5912
5842 5913 if ((err = zonecfg_setnwifent(handle)) != Z_OK) {
5843 5914 zone_perror(zone, err, B_TRUE);
5844 5915 return;
5845 5916 }
5846 5917 while (zonecfg_getnwifent(handle, &nwiftab) == Z_OK) {
5847 5918 /*
5848 5919 * physical is required in all cases.
5849 5920 * A shared IP requires an address,
5850 5921 * and may include a default router, while
5851 5922 * an exclusive IP must have neither an address
5852 5923 * nor a default router.
5853 5924 * The physical interface name must be valid in all cases.
5854 5925 */
5855 5926 check_reqd_prop(nwiftab.zone_nwif_physical, RT_NET,
5856 5927 PT_PHYSICAL, &ret_val);
5857 5928 if (validate_net_physical_syntax(nwiftab.zone_nwif_physical) !=
5858 5929 Z_OK) {
5859 5930 saw_error = B_TRUE;
5860 5931 if (ret_val == Z_OK)
5861 5932 ret_val = Z_INVAL;
5862 5933 }
5863 5934
5864 5935 switch (iptype) {
5865 5936 case ZS_SHARED:
5866 5937 check_reqd_prop(nwiftab.zone_nwif_address, RT_NET,
5867 5938 PT_ADDRESS, &ret_val);
5868 5939 if (strlen(nwiftab.zone_nwif_allowed_address) > 0) {
5869 5940 zerr(gettext("%s: %s cannot be specified "
5870 5941 "for a shared IP type"),
5871 5942 rt_to_str(RT_NET),
5872 5943 pt_to_str(PT_ALLOWED_ADDRESS));
5873 5944 saw_error = B_TRUE;
5874 5945 if (ret_val == Z_OK)
5875 5946 ret_val = Z_INVAL;
5876 5947 }
5877 5948 break;
5878 5949 case ZS_EXCLUSIVE:
5879 5950 if (strlen(nwiftab.zone_nwif_address) > 0) {
5880 5951 zerr(gettext("%s: %s cannot be specified "
5881 5952 "for an exclusive IP type"),
5882 5953 rt_to_str(RT_NET), pt_to_str(PT_ADDRESS));
5883 5954 saw_error = B_TRUE;
5884 5955 if (ret_val == Z_OK)
5885 5956 ret_val = Z_INVAL;
5886 5957 } else {
5887 5958 if (!add_nwif(&nwiftab)) {
5888 5959 saw_error = B_TRUE;
5889 5960 if (ret_val == Z_OK)
5890 5961 ret_val = Z_INVAL;
5891 5962 }
5892 5963 }
5893 5964 break;
5894 5965 }
5895 5966 }
5896 5967 for (tmp = xif; tmp != NULL; tmp = tmp->xif_next) {
5897 5968 if (!tmp->xif_has_address && tmp->xif_has_defrouter) {
5898 5969 zerr(gettext("%s: %s for %s cannot be specified "
5899 5970 "without %s for an exclusive IP type"),
5900 5971 rt_to_str(RT_NET), pt_to_str(PT_DEFROUTER),
5901 5972 tmp->xif_name, pt_to_str(PT_ALLOWED_ADDRESS));
5902 5973 saw_error = B_TRUE;
5903 5974 ret_val = Z_INVAL;
5904 5975 }
5905 5976 }
5906 5977 free(xif);
5907 5978 xif = NULL;
5908 5979 (void) zonecfg_endnwifent(handle);
5909 5980
5910 5981 if ((err = zonecfg_setrctlent(handle)) != Z_OK) {
5911 5982 zone_perror(zone, err, B_TRUE);
5912 5983 return;
5913 5984 }
5914 5985 while (zonecfg_getrctlent(handle, &rctltab) == Z_OK) {
5915 5986 check_reqd_prop(rctltab.zone_rctl_name, RT_RCTL, PT_NAME,
5916 5987 &ret_val);
5917 5988
5918 5989 if (strcmp(rctltab.zone_rctl_name, "zone.cpu-shares") == 0)
5919 5990 has_cpu_shares = B_TRUE;
5920 5991
5921 5992 if (strcmp(rctltab.zone_rctl_name, "zone.cpu-cap") == 0)
5922 5993 has_cpu_cap = B_TRUE;
5923 5994
5924 5995 if (rctltab.zone_rctl_valptr == NULL) {
5925 5996 zerr(gettext("%s: no %s specified"),
5926 5997 rt_to_str(RT_RCTL), pt_to_str(PT_VALUE));
5927 5998 saw_error = B_TRUE;
5928 5999 if (ret_val == Z_OK)
5929 6000 ret_val = Z_REQD_PROPERTY_MISSING;
5930 6001 } else {
5931 6002 zonecfg_free_rctl_value_list(rctltab.zone_rctl_valptr);
5932 6003 }
5933 6004 }
5934 6005 (void) zonecfg_endrctlent(handle);
5935 6006
5936 6007 if ((pset_res = zonecfg_lookup_pset(handle, &psettab)) == Z_OK &&
5937 6008 has_cpu_shares) {
5938 6009 zerr(gettext("%s zone.cpu-shares and %s are incompatible."),
5939 6010 rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
5940 6011 saw_error = B_TRUE;
5941 6012 if (ret_val == Z_OK)
5942 6013 ret_val = Z_INCOMPATIBLE;
5943 6014 }
5944 6015
5945 6016 if (has_cpu_shares && zonecfg_get_sched_class(handle, sched,
5946 6017 sizeof (sched)) == Z_OK && strlen(sched) > 0 &&
5947 6018 strcmp(sched, "FSS") != 0) {
5948 6019 zerr(gettext("WARNING: %s zone.cpu-shares and %s=%s are "
5949 6020 "incompatible"),
5950 6021 rt_to_str(RT_RCTL), rt_to_str(RT_SCHED), sched);
5951 6022 saw_error = B_TRUE;
5952 6023 if (ret_val == Z_OK)
5953 6024 ret_val = Z_INCOMPATIBLE;
5954 6025 }
5955 6026
5956 6027 if (pset_res == Z_OK && has_cpu_cap) {
5957 6028 zerr(gettext("%s zone.cpu-cap and the %s are incompatible."),
5958 6029 rt_to_str(RT_RCTL), rt_to_str(RT_DCPU));
5959 6030 saw_error = B_TRUE;
5960 6031 if (ret_val == Z_OK)
5961 6032 ret_val = Z_INCOMPATIBLE;
5962 6033 }
5963 6034
5964 6035 if ((err = zonecfg_setattrent(handle)) != Z_OK) {
5965 6036 zone_perror(zone, err, B_TRUE);
5966 6037 return;
5967 6038 }
5968 6039 while (zonecfg_getattrent(handle, &attrtab) == Z_OK) {
5969 6040 check_reqd_prop(attrtab.zone_attr_name, RT_ATTR, PT_NAME,
5970 6041 &ret_val);
5971 6042 check_reqd_prop(attrtab.zone_attr_type, RT_ATTR, PT_TYPE,
5972 6043 &ret_val);
5973 6044 check_reqd_prop(attrtab.zone_attr_value, RT_ATTR, PT_VALUE,
5974 6045 &ret_val);
5975 6046 }
5976 6047 (void) zonecfg_endattrent(handle);
5977 6048
5978 6049 if ((err = zonecfg_setdsent(handle)) != Z_OK) {
5979 6050 zone_perror(zone, err, B_TRUE);
5980 6051 return;
5981 6052 }
5982 6053 while (zonecfg_getdsent(handle, &dstab) == Z_OK) {
5983 6054 if (strlen(dstab.zone_dataset_name) == 0) {
5984 6055 zerr("%s: %s %s", rt_to_str(RT_DATASET),
5985 6056 pt_to_str(PT_NAME), gettext("not specified"));
5986 6057 saw_error = B_TRUE;
5987 6058 if (ret_val == Z_OK)
5988 6059 ret_val = Z_REQD_PROPERTY_MISSING;
5989 6060 } else if (!zfs_name_valid(dstab.zone_dataset_name,
5990 6061 ZFS_TYPE_FILESYSTEM)) {
5991 6062 zerr("%s: %s %s", rt_to_str(RT_DATASET),
5992 6063 pt_to_str(PT_NAME), gettext("invalid"));
5993 6064 saw_error = B_TRUE;
5994 6065 if (ret_val == Z_OK)
5995 6066 ret_val = Z_BAD_PROPERTY;
5996 6067 }
5997 6068
5998 6069 }
5999 6070 (void) zonecfg_enddsent(handle);
6000 6071
6001 6072 if ((err = zonecfg_setadminent(handle)) != Z_OK) {
6002 6073 zone_perror(zone, err, B_TRUE);
6003 6074 return;
6004 6075 }
6005 6076 while (zonecfg_getadminent(handle, &admintab) == Z_OK) {
6006 6077 check_reqd_prop(admintab.zone_admin_user, RT_ADMIN,
6007 6078 PT_USER, &ret_val);
6008 6079 check_reqd_prop(admintab.zone_admin_auths, RT_ADMIN,
6009 6080 PT_AUTHS, &ret_val);
6010 6081 if ((ret_val == Z_OK) && (getpwnam(admintab.zone_admin_user)
6011 6082 == NULL)) {
6012 6083 zerr(gettext("%s %s is not a valid username"),
6013 6084 pt_to_str(PT_USER),
6014 6085 admintab.zone_admin_user);
6015 6086 ret_val = Z_BAD_PROPERTY;
6016 6087 }
6017 6088 if ((ret_val == Z_OK) && (!zonecfg_valid_auths(
6018 6089 admintab.zone_admin_auths, zone))) {
6019 6090 ret_val = Z_BAD_PROPERTY;
6020 6091 }
6021 6092 }
6022 6093 (void) zonecfg_endadminent(handle);
6023 6094
6024 6095 if (!global_scope) {
6025 6096 zerr(gettext("resource specification incomplete"));
6026 6097 saw_error = B_TRUE;
6027 6098 if (ret_val == Z_OK)
6028 6099 ret_val = Z_INSUFFICIENT_SPEC;
6029 6100 }
6030 6101
6031 6102 if (save) {
6032 6103 if (ret_val == Z_OK) {
6033 6104 if ((ret_val = zonecfg_save(handle)) == Z_OK) {
6034 6105 need_to_commit = B_FALSE;
6035 6106 (void) strlcpy(revert_zone, zone,
6036 6107 sizeof (revert_zone));
6037 6108 }
6038 6109 } else {
6039 6110 zerr(gettext("Zone %s failed to verify"), zone);
6040 6111 }
6041 6112 }
6042 6113 if (ret_val != Z_OK)
6043 6114 zone_perror(zone, ret_val, B_TRUE);
6044 6115 }
6045 6116
6046 6117 void
6047 6118 cancel_func(cmd_t *cmd)
6048 6119 {
6049 6120 int arg;
6050 6121 boolean_t arg_err = B_FALSE;
6051 6122
6052 6123 assert(cmd != NULL);
6053 6124
6054 6125 optind = 0;
6055 6126 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6056 6127 switch (arg) {
6057 6128 case '?':
6058 6129 longer_usage(CMD_CANCEL);
6059 6130 arg_err = B_TRUE;
6060 6131 break;
6061 6132 default:
6062 6133 short_usage(CMD_CANCEL);
6063 6134 arg_err = B_TRUE;
6064 6135 break;
6065 6136 }
6066 6137 }
6067 6138 if (arg_err)
6068 6139 return;
6069 6140
6070 6141 if (optind != cmd->cmd_argc) {
6071 6142 short_usage(CMD_CANCEL);
6072 6143 return;
6073 6144 }
6074 6145
6075 6146 if (global_scope)
6076 6147 scope_usage(CMD_CANCEL);
6077 6148 global_scope = B_TRUE;
6078 6149 zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
6079 6150 bzero(&in_progress_fstab, sizeof (in_progress_fstab));
6080 6151 bzero(&in_progress_nwiftab, sizeof (in_progress_nwiftab));
6081 6152 bzero(&in_progress_devtab, sizeof (in_progress_devtab));
6082 6153 zonecfg_free_rctl_value_list(in_progress_rctltab.zone_rctl_valptr);
6083 6154 bzero(&in_progress_rctltab, sizeof (in_progress_rctltab));
6084 6155 bzero(&in_progress_attrtab, sizeof (in_progress_attrtab));
6085 6156 bzero(&in_progress_dstab, sizeof (in_progress_dstab));
6086 6157 }
6087 6158
6088 6159 static int
6089 6160 validate_attr_name(char *name)
6090 6161 {
6091 6162 int i;
6092 6163
6093 6164 if (!isalnum(name[0])) {
6094 6165 zerr(gettext("Invalid %s %s %s: must start with an alpha-"
6095 6166 "numeric character."), rt_to_str(RT_ATTR),
6096 6167 pt_to_str(PT_NAME), name);
6097 6168 return (Z_INVAL);
6098 6169 }
6099 6170 for (i = 1; name[i]; i++)
6100 6171 if (!isalnum(name[i]) && name[i] != '-' && name[i] != '.') {
6101 6172 zerr(gettext("Invalid %s %s %s: can only contain "
6102 6173 "alpha-numeric characters, plus '-' and '.'."),
6103 6174 rt_to_str(RT_ATTR), pt_to_str(PT_NAME), name);
6104 6175 return (Z_INVAL);
6105 6176 }
6106 6177 return (Z_OK);
6107 6178 }
6108 6179
6109 6180 static int
6110 6181 validate_attr_type_val(struct zone_attrtab *attrtab)
6111 6182 {
6112 6183 boolean_t boolval;
6113 6184 int64_t intval;
6114 6185 char strval[MAXNAMELEN];
6115 6186 uint64_t uintval;
6116 6187
6117 6188 if (strcmp(attrtab->zone_attr_type, "boolean") == 0) {
6118 6189 if (zonecfg_get_attr_boolean(attrtab, &boolval) == Z_OK)
6119 6190 return (Z_OK);
6120 6191 zerr(gettext("invalid %s value for %s=%s"),
6121 6192 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "boolean");
6122 6193 return (Z_ERR);
6123 6194 }
6124 6195
6125 6196 if (strcmp(attrtab->zone_attr_type, "int") == 0) {
6126 6197 if (zonecfg_get_attr_int(attrtab, &intval) == Z_OK)
6127 6198 return (Z_OK);
6128 6199 zerr(gettext("invalid %s value for %s=%s"),
6129 6200 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "int");
6130 6201 return (Z_ERR);
6131 6202 }
6132 6203
6133 6204 if (strcmp(attrtab->zone_attr_type, "string") == 0) {
6134 6205 if (zonecfg_get_attr_string(attrtab, strval,
6135 6206 sizeof (strval)) == Z_OK)
6136 6207 return (Z_OK);
6137 6208 zerr(gettext("invalid %s value for %s=%s"),
6138 6209 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "string");
6139 6210 return (Z_ERR);
6140 6211 }
6141 6212
6142 6213 if (strcmp(attrtab->zone_attr_type, "uint") == 0) {
6143 6214 if (zonecfg_get_attr_uint(attrtab, &uintval) == Z_OK)
6144 6215 return (Z_OK);
6145 6216 zerr(gettext("invalid %s value for %s=%s"),
6146 6217 rt_to_str(RT_ATTR), pt_to_str(PT_TYPE), "uint");
6147 6218 return (Z_ERR);
6148 6219 }
6149 6220
6150 6221 zerr(gettext("invalid %s %s '%s'"), rt_to_str(RT_ATTR),
6151 6222 pt_to_str(PT_TYPE), attrtab->zone_attr_type);
6152 6223 return (Z_ERR);
6153 6224 }
6154 6225
6155 6226 /*
6156 6227 * Helper function for end_func-- checks the existence of a given property
6157 6228 * and emits a message if not specified.
6158 6229 */
6159 6230 static int
6160 6231 end_check_reqd(char *attr, int pt, boolean_t *validation_failed)
6161 6232 {
6162 6233 if (strlen(attr) == 0) {
6163 6234 *validation_failed = B_TRUE;
6164 6235 zerr(gettext("%s not specified"), pt_to_str(pt));
6165 6236 return (Z_ERR);
6166 6237 }
6167 6238 return (Z_OK);
6168 6239 }
6169 6240
6170 6241 static void
6171 6242 net_exists_error(struct zone_nwiftab nwif)
6172 6243 {
6173 6244 if (strlen(nwif.zone_nwif_address) > 0) {
6174 6245 zerr(gettext("A %s resource with the %s '%s', "
6175 6246 "and %s '%s' already exists."),
6176 6247 rt_to_str(RT_NET),
6177 6248 pt_to_str(PT_PHYSICAL),
6178 6249 nwif.zone_nwif_physical,
6179 6250 pt_to_str(PT_ADDRESS),
6180 6251 in_progress_nwiftab.zone_nwif_address);
6181 6252 } else {
6182 6253 zerr(gettext("A %s resource with the %s '%s', "
6183 6254 "and %s '%s' already exists."),
6184 6255 rt_to_str(RT_NET),
6185 6256 pt_to_str(PT_PHYSICAL),
6186 6257 nwif.zone_nwif_physical,
6187 6258 pt_to_str(PT_ALLOWED_ADDRESS),
6188 6259 nwif.zone_nwif_allowed_address);
6189 6260 }
6190 6261 }
6191 6262
6192 6263 void
6193 6264 end_func(cmd_t *cmd)
6194 6265 {
6195 6266 boolean_t validation_failed = B_FALSE;
6196 6267 boolean_t arg_err = B_FALSE;
6197 6268 struct zone_fstab tmp_fstab;
6198 6269 struct zone_nwiftab tmp_nwiftab;
6199 6270 struct zone_devtab tmp_devtab;
6200 6271 struct zone_rctltab tmp_rctltab;
6201 6272 struct zone_attrtab tmp_attrtab;
6202 6273 struct zone_dstab tmp_dstab;
6203 6274 struct zone_admintab tmp_admintab;
6204 6275 int err, arg, res1, res2, res3;
6205 6276 uint64_t swap_limit;
6206 6277 uint64_t locked_limit;
6207 6278 uint64_t proc_cap;
6208 6279
6209 6280 assert(cmd != NULL);
6210 6281
6211 6282 optind = 0;
6212 6283 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6213 6284 switch (arg) {
6214 6285 case '?':
6215 6286 longer_usage(CMD_END);
6216 6287 arg_err = B_TRUE;
6217 6288 break;
6218 6289 default:
6219 6290 short_usage(CMD_END);
6220 6291 arg_err = B_TRUE;
6221 6292 break;
6222 6293 }
6223 6294 }
6224 6295 if (arg_err)
6225 6296 return;
6226 6297
6227 6298 if (optind != cmd->cmd_argc) {
6228 6299 short_usage(CMD_END);
6229 6300 return;
6230 6301 }
6231 6302
6232 6303 if (global_scope) {
6233 6304 scope_usage(CMD_END);
6234 6305 return;
6235 6306 }
6236 6307
6237 6308 assert(end_op == CMD_ADD || end_op == CMD_SELECT);
6238 6309
6239 6310 switch (resource_scope) {
6240 6311 case RT_FS:
6241 6312 /* First make sure everything was filled in. */
6242 6313 if (end_check_reqd(in_progress_fstab.zone_fs_dir,
6243 6314 PT_DIR, &validation_failed) == Z_OK) {
6244 6315 if (in_progress_fstab.zone_fs_dir[0] != '/') {
6245 6316 zerr(gettext("%s %s is not an absolute path."),
6246 6317 pt_to_str(PT_DIR),
6247 6318 in_progress_fstab.zone_fs_dir);
6248 6319 validation_failed = B_TRUE;
6249 6320 }
6250 6321 }
6251 6322
6252 6323 (void) end_check_reqd(in_progress_fstab.zone_fs_special,
6253 6324 PT_SPECIAL, &validation_failed);
6254 6325
6255 6326 if (in_progress_fstab.zone_fs_raw[0] != '\0' &&
6256 6327 in_progress_fstab.zone_fs_raw[0] != '/') {
6257 6328 zerr(gettext("%s %s is not an absolute path."),
6258 6329 pt_to_str(PT_RAW),
6259 6330 in_progress_fstab.zone_fs_raw);
6260 6331 validation_failed = B_TRUE;
6261 6332 }
6262 6333
6263 6334 (void) end_check_reqd(in_progress_fstab.zone_fs_type, PT_TYPE,
6264 6335 &validation_failed);
6265 6336
6266 6337 if (validation_failed) {
6267 6338 saw_error = B_TRUE;
6268 6339 return;
6269 6340 }
6270 6341
6271 6342 if (end_op == CMD_ADD) {
6272 6343 /* Make sure there isn't already one like this. */
6273 6344 bzero(&tmp_fstab, sizeof (tmp_fstab));
6274 6345 (void) strlcpy(tmp_fstab.zone_fs_dir,
6275 6346 in_progress_fstab.zone_fs_dir,
6276 6347 sizeof (tmp_fstab.zone_fs_dir));
6277 6348 err = zonecfg_lookup_filesystem(handle, &tmp_fstab);
6278 6349 zonecfg_free_fs_option_list(tmp_fstab.zone_fs_options);
6279 6350 if (err == Z_OK) {
6280 6351 zerr(gettext("A %s resource "
6281 6352 "with the %s '%s' already exists."),
6282 6353 rt_to_str(RT_FS), pt_to_str(PT_DIR),
6283 6354 in_progress_fstab.zone_fs_dir);
6284 6355 saw_error = B_TRUE;
6285 6356 return;
6286 6357 }
6287 6358 err = zonecfg_add_filesystem(handle,
6288 6359 &in_progress_fstab);
6289 6360 } else {
6290 6361 err = zonecfg_modify_filesystem(handle, &old_fstab,
6291 6362 &in_progress_fstab);
6292 6363 }
6293 6364 zonecfg_free_fs_option_list(in_progress_fstab.zone_fs_options);
6294 6365 in_progress_fstab.zone_fs_options = NULL;
6295 6366 break;
6296 6367
6297 6368 case RT_NET:
6298 6369 /*
6299 6370 * First make sure everything was filled in.
6300 6371 * Since we don't know whether IP will be shared
6301 6372 * or exclusive here, some checks are deferred until
6302 6373 * the verify command.
6303 6374 */
6304 6375 (void) end_check_reqd(in_progress_nwiftab.zone_nwif_physical,
6305 6376 PT_PHYSICAL, &validation_failed);
6306 6377
6307 6378 if (validation_failed) {
6308 6379 saw_error = B_TRUE;
6309 6380 return;
6310 6381 }
6311 6382 if (end_op == CMD_ADD) {
6312 6383 /* Make sure there isn't already one like this. */
6313 6384 bzero(&tmp_nwiftab, sizeof (tmp_nwiftab));
6314 6385 (void) strlcpy(tmp_nwiftab.zone_nwif_physical,
6315 6386 in_progress_nwiftab.zone_nwif_physical,
6316 6387 sizeof (tmp_nwiftab.zone_nwif_physical));
6317 6388 (void) strlcpy(tmp_nwiftab.zone_nwif_address,
6318 6389 in_progress_nwiftab.zone_nwif_address,
6319 6390 sizeof (tmp_nwiftab.zone_nwif_address));
6320 6391 (void) strlcpy(tmp_nwiftab.zone_nwif_allowed_address,
6321 6392 in_progress_nwiftab.zone_nwif_allowed_address,
6322 6393 sizeof (tmp_nwiftab.zone_nwif_allowed_address));
6323 6394 (void) strlcpy(tmp_nwiftab.zone_nwif_defrouter,
6324 6395 in_progress_nwiftab.zone_nwif_defrouter,
6325 6396 sizeof (tmp_nwiftab.zone_nwif_defrouter));
6326 6397 if (zonecfg_lookup_nwif(handle, &tmp_nwiftab) == Z_OK) {
6327 6398 net_exists_error(in_progress_nwiftab);
6328 6399 saw_error = B_TRUE;
6329 6400 return;
6330 6401 }
6331 6402 err = zonecfg_add_nwif(handle, &in_progress_nwiftab);
6332 6403 } else {
6333 6404 err = zonecfg_modify_nwif(handle, &old_nwiftab,
6334 6405 &in_progress_nwiftab);
6335 6406 }
6336 6407 break;
6337 6408
6338 6409 case RT_DEVICE:
6339 6410 /* First make sure everything was filled in. */
6340 6411 (void) end_check_reqd(in_progress_devtab.zone_dev_match,
6341 6412 PT_MATCH, &validation_failed);
6342 6413
6343 6414 if (validation_failed) {
6344 6415 saw_error = B_TRUE;
6345 6416 return;
6346 6417 }
6347 6418
6348 6419 if (end_op == CMD_ADD) {
6349 6420 /* Make sure there isn't already one like this. */
6350 6421 (void) strlcpy(tmp_devtab.zone_dev_match,
6351 6422 in_progress_devtab.zone_dev_match,
6352 6423 sizeof (tmp_devtab.zone_dev_match));
6353 6424 if (zonecfg_lookup_dev(handle, &tmp_devtab) == Z_OK) {
6354 6425 zerr(gettext("A %s resource with the %s '%s' "
6355 6426 "already exists."), rt_to_str(RT_DEVICE),
6356 6427 pt_to_str(PT_MATCH),
6357 6428 in_progress_devtab.zone_dev_match);
6358 6429 saw_error = B_TRUE;
6359 6430 return;
6360 6431 }
6361 6432 err = zonecfg_add_dev(handle, &in_progress_devtab);
6362 6433 } else {
6363 6434 err = zonecfg_modify_dev(handle, &old_devtab,
6364 6435 &in_progress_devtab);
6365 6436 }
6366 6437 break;
6367 6438
6368 6439 case RT_RCTL:
6369 6440 /* First make sure everything was filled in. */
6370 6441 (void) end_check_reqd(in_progress_rctltab.zone_rctl_name,
6371 6442 PT_NAME, &validation_failed);
6372 6443
6373 6444 if (in_progress_rctltab.zone_rctl_valptr == NULL) {
6374 6445 zerr(gettext("no %s specified"), pt_to_str(PT_VALUE));
6375 6446 validation_failed = B_TRUE;
6376 6447 }
6377 6448
6378 6449 if (validation_failed) {
6379 6450 saw_error = B_TRUE;
6380 6451 return;
6381 6452 }
6382 6453
6383 6454 if (end_op == CMD_ADD) {
6384 6455 /* Make sure there isn't already one like this. */
6385 6456 (void) strlcpy(tmp_rctltab.zone_rctl_name,
6386 6457 in_progress_rctltab.zone_rctl_name,
6387 6458 sizeof (tmp_rctltab.zone_rctl_name));
6388 6459 tmp_rctltab.zone_rctl_valptr = NULL;
6389 6460 err = zonecfg_lookup_rctl(handle, &tmp_rctltab);
6390 6461 zonecfg_free_rctl_value_list(
6391 6462 tmp_rctltab.zone_rctl_valptr);
6392 6463 if (err == Z_OK) {
6393 6464 zerr(gettext("A %s resource "
6394 6465 "with the %s '%s' already exists."),
6395 6466 rt_to_str(RT_RCTL), pt_to_str(PT_NAME),
6396 6467 in_progress_rctltab.zone_rctl_name);
6397 6468 saw_error = B_TRUE;
6398 6469 return;
6399 6470 }
6400 6471 err = zonecfg_add_rctl(handle, &in_progress_rctltab);
6401 6472 } else {
6402 6473 err = zonecfg_modify_rctl(handle, &old_rctltab,
6403 6474 &in_progress_rctltab);
6404 6475 }
6405 6476 if (err == Z_OK) {
6406 6477 zonecfg_free_rctl_value_list(
6407 6478 in_progress_rctltab.zone_rctl_valptr);
6408 6479 in_progress_rctltab.zone_rctl_valptr = NULL;
6409 6480 }
6410 6481 break;
6411 6482
6412 6483 case RT_ATTR:
6413 6484 /* First make sure everything was filled in. */
6414 6485 (void) end_check_reqd(in_progress_attrtab.zone_attr_name,
6415 6486 PT_NAME, &validation_failed);
6416 6487 (void) end_check_reqd(in_progress_attrtab.zone_attr_type,
6417 6488 PT_TYPE, &validation_failed);
6418 6489 (void) end_check_reqd(in_progress_attrtab.zone_attr_value,
6419 6490 PT_VALUE, &validation_failed);
6420 6491
6421 6492 if (validate_attr_name(in_progress_attrtab.zone_attr_name) !=
6422 6493 Z_OK)
6423 6494 validation_failed = B_TRUE;
6424 6495
6425 6496 if (validate_attr_type_val(&in_progress_attrtab) != Z_OK)
6426 6497 validation_failed = B_TRUE;
6427 6498
6428 6499 if (validation_failed) {
6429 6500 saw_error = B_TRUE;
6430 6501 return;
6431 6502 }
6432 6503 if (end_op == CMD_ADD) {
6433 6504 /* Make sure there isn't already one like this. */
6434 6505 bzero(&tmp_attrtab, sizeof (tmp_attrtab));
6435 6506 (void) strlcpy(tmp_attrtab.zone_attr_name,
6436 6507 in_progress_attrtab.zone_attr_name,
6437 6508 sizeof (tmp_attrtab.zone_attr_name));
6438 6509 if (zonecfg_lookup_attr(handle, &tmp_attrtab) == Z_OK) {
6439 6510 zerr(gettext("An %s resource "
6440 6511 "with the %s '%s' already exists."),
6441 6512 rt_to_str(RT_ATTR), pt_to_str(PT_NAME),
6442 6513 in_progress_attrtab.zone_attr_name);
6443 6514 saw_error = B_TRUE;
6444 6515 return;
6445 6516 }
6446 6517 err = zonecfg_add_attr(handle, &in_progress_attrtab);
6447 6518 } else {
6448 6519 err = zonecfg_modify_attr(handle, &old_attrtab,
6449 6520 &in_progress_attrtab);
6450 6521 }
6451 6522 break;
6452 6523 case RT_DATASET:
6453 6524 /* First make sure everything was filled in. */
6454 6525 if (strlen(in_progress_dstab.zone_dataset_name) == 0) {
6455 6526 zerr("%s %s", pt_to_str(PT_NAME),
6456 6527 gettext("not specified"));
6457 6528 saw_error = B_TRUE;
6458 6529 validation_failed = B_TRUE;
6459 6530 }
6460 6531 if (validation_failed)
6461 6532 return;
6462 6533 if (end_op == CMD_ADD) {
6463 6534 /* Make sure there isn't already one like this. */
6464 6535 bzero(&tmp_dstab, sizeof (tmp_dstab));
6465 6536 (void) strlcpy(tmp_dstab.zone_dataset_name,
6466 6537 in_progress_dstab.zone_dataset_name,
6467 6538 sizeof (tmp_dstab.zone_dataset_name));
6468 6539 err = zonecfg_lookup_ds(handle, &tmp_dstab);
6469 6540 if (err == Z_OK) {
6470 6541 zerr(gettext("A %s resource "
6471 6542 "with the %s '%s' already exists."),
6472 6543 rt_to_str(RT_DATASET), pt_to_str(PT_NAME),
6473 6544 in_progress_dstab.zone_dataset_name);
6474 6545 saw_error = B_TRUE;
6475 6546 return;
6476 6547 }
6477 6548 err = zonecfg_add_ds(handle, &in_progress_dstab);
6478 6549 } else {
6479 6550 err = zonecfg_modify_ds(handle, &old_dstab,
6480 6551 &in_progress_dstab);
6481 6552 }
6482 6553 break;
6483 6554 case RT_DCPU:
6484 6555 /* Make sure everything was filled in. */
6485 6556 if (end_check_reqd(in_progress_psettab.zone_ncpu_min,
6486 6557 PT_NCPUS, &validation_failed) != Z_OK) {
6487 6558 saw_error = B_TRUE;
6488 6559 return;
6489 6560 }
6490 6561
6491 6562 if (end_op == CMD_ADD) {
6492 6563 err = zonecfg_add_pset(handle, &in_progress_psettab);
6493 6564 } else {
6494 6565 err = zonecfg_modify_pset(handle, &in_progress_psettab);
6495 6566 }
6496 6567 break;
6497 6568 case RT_PCAP:
6498 6569 /* Make sure everything was filled in. */
6499 6570 if (zonecfg_get_aliased_rctl(handle, ALIAS_CPUCAP, &proc_cap)
6500 6571 != Z_OK) {
6501 6572 zerr(gettext("%s not specified"), pt_to_str(PT_NCPUS));
6502 6573 saw_error = B_TRUE;
6503 6574 validation_failed = B_TRUE;
6504 6575 return;
6505 6576 }
6506 6577 err = Z_OK;
6507 6578 break;
6508 6579 case RT_MCAP:
6509 6580 /* Make sure everything was filled in. */
6510 6581 res1 = strlen(in_progress_mcaptab.zone_physmem_cap) == 0 ?
6511 6582 Z_ERR : Z_OK;
6512 6583 res2 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXSWAP,
6513 6584 &swap_limit);
6514 6585 res3 = zonecfg_get_aliased_rctl(handle, ALIAS_MAXLOCKEDMEM,
6515 6586 &locked_limit);
6516 6587
6517 6588 if (res1 != Z_OK && res2 != Z_OK && res3 != Z_OK) {
6518 6589 zerr(gettext("No property was specified. One of %s, "
6519 6590 "%s or %s is required."), pt_to_str(PT_PHYSICAL),
6520 6591 pt_to_str(PT_SWAP), pt_to_str(PT_LOCKED));
6521 6592 saw_error = B_TRUE;
6522 6593 return;
6523 6594 }
6524 6595
6525 6596 /* if phys & locked are both set, verify locked <= phys */
6526 6597 if (res1 == Z_OK && res3 == Z_OK) {
6527 6598 uint64_t phys_limit;
6528 6599 char *endp;
6529 6600
6530 6601 phys_limit = strtoull(
6531 6602 in_progress_mcaptab.zone_physmem_cap, &endp, 10);
6532 6603 if (phys_limit < locked_limit) {
6533 6604 zerr(gettext("The %s cap must be less than or "
6534 6605 "equal to the %s cap."),
6535 6606 pt_to_str(PT_LOCKED),
6536 6607 pt_to_str(PT_PHYSICAL));
6537 6608 saw_error = B_TRUE;
6538 6609 return;
6539 6610 }
6540 6611 }
6541 6612
6542 6613 err = Z_OK;
6543 6614 if (res1 == Z_OK) {
6544 6615 /*
6545 6616 * We could be ending from either an add operation
6546 6617 * or a select operation. Since all of the properties
6547 6618 * within this resource are optional, we always use
6548 6619 * modify on the mcap entry. zonecfg_modify_mcap()
6549 6620 * will handle both adding and modifying a memory cap.
6550 6621 */
6551 6622 err = zonecfg_modify_mcap(handle, &in_progress_mcaptab);
6552 6623 } else if (end_op == CMD_SELECT) {
6553 6624 /*
6554 6625 * If we're ending from a select and the physical
6555 6626 * memory cap is empty then the user could have cleared
6556 6627 * the physical cap value, so try to delete the entry.
6557 6628 */
6558 6629 (void) zonecfg_delete_mcap(handle);
6559 6630 }
6560 6631 break;
6561 6632 case RT_ADMIN:
6562 6633 /* First make sure everything was filled in. */
6563 6634 if (end_check_reqd(in_progress_admintab.zone_admin_user,
6564 6635 PT_USER, &validation_failed) == Z_OK) {
6565 6636 if (getpwnam(in_progress_admintab.zone_admin_user)
6566 6637 == NULL) {
6567 6638 zerr(gettext("%s %s is not a valid username"),
6568 6639 pt_to_str(PT_USER),
6569 6640 in_progress_admintab.zone_admin_user);
6570 6641 validation_failed = B_TRUE;
6571 6642 }
6572 6643 }
6573 6644
6574 6645 if (end_check_reqd(in_progress_admintab.zone_admin_auths,
6575 6646 PT_AUTHS, &validation_failed) == Z_OK) {
6576 6647 if (!zonecfg_valid_auths(
6577 6648 in_progress_admintab.zone_admin_auths,
6578 6649 zone)) {
6579 6650 validation_failed = B_TRUE;
6580 6651 }
6581 6652 }
6582 6653
6583 6654 if (validation_failed) {
6584 6655 saw_error = B_TRUE;
6585 6656 return;
6586 6657 }
6587 6658
6588 6659 if (end_op == CMD_ADD) {
6589 6660 /* Make sure there isn't already one like this. */
6590 6661 bzero(&tmp_admintab, sizeof (tmp_admintab));
6591 6662 (void) strlcpy(tmp_admintab.zone_admin_user,
6592 6663 in_progress_admintab.zone_admin_user,
6593 6664 sizeof (tmp_admintab.zone_admin_user));
6594 6665 err = zonecfg_lookup_admin(
6595 6666 handle, &tmp_admintab);
6596 6667 if (err == Z_OK) {
6597 6668 zerr(gettext("A %s resource "
6598 6669 "with the %s '%s' already exists."),
6599 6670 rt_to_str(RT_ADMIN),
6600 6671 pt_to_str(PT_USER),
6601 6672 in_progress_admintab.zone_admin_user);
6602 6673 saw_error = B_TRUE;
6603 6674 return;
6604 6675 }
6605 6676 err = zonecfg_add_admin(handle,
6606 6677 &in_progress_admintab, zone);
6607 6678 } else {
6608 6679 err = zonecfg_modify_admin(handle,
6609 6680 &old_admintab, &in_progress_admintab,
6610 6681 zone);
6611 6682 }
6612 6683 break;
6613 6684 default:
6614 6685 zone_perror(rt_to_str(resource_scope), Z_NO_RESOURCE_TYPE,
6615 6686 B_TRUE);
6616 6687 saw_error = B_TRUE;
6617 6688 return;
6618 6689 }
6619 6690
6620 6691 if (err != Z_OK) {
6621 6692 zone_perror(zone, err, B_TRUE);
6622 6693 } else {
6623 6694 need_to_commit = B_TRUE;
6624 6695 global_scope = B_TRUE;
6625 6696 end_op = -1;
6626 6697 }
6627 6698 }
6628 6699
6629 6700 void
6630 6701 commit_func(cmd_t *cmd)
6631 6702 {
6632 6703 int arg;
6633 6704 boolean_t arg_err = B_FALSE;
6634 6705
6635 6706 optind = 0;
6636 6707 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?")) != EOF) {
6637 6708 switch (arg) {
6638 6709 case '?':
6639 6710 longer_usage(CMD_COMMIT);
6640 6711 arg_err = B_TRUE;
6641 6712 break;
6642 6713 default:
6643 6714 short_usage(CMD_COMMIT);
6644 6715 arg_err = B_TRUE;
6645 6716 break;
6646 6717 }
6647 6718 }
6648 6719 if (arg_err)
6649 6720 return;
6650 6721
6651 6722 if (optind != cmd->cmd_argc) {
6652 6723 short_usage(CMD_COMMIT);
6653 6724 return;
6654 6725 }
6655 6726
6656 6727 if (zone_is_read_only(CMD_COMMIT))
6657 6728 return;
6658 6729
6659 6730 assert(cmd != NULL);
6660 6731
6661 6732 cmd->cmd_argc = 1;
6662 6733 /*
6663 6734 * cmd_arg normally comes from a strdup() in the lexer, and the
6664 6735 * whole cmd structure and its (char *) attributes are freed at
6665 6736 * the completion of each command, so the strdup() below is needed
6666 6737 * to match this and prevent a core dump from trying to free()
6667 6738 * something that can't be.
6668 6739 */
6669 6740 if ((cmd->cmd_argv[0] = strdup("save")) == NULL) {
6670 6741 zone_perror(zone, Z_NOMEM, B_TRUE);
6671 6742 exit(Z_ERR);
6672 6743 }
6673 6744 cmd->cmd_argv[1] = NULL;
6674 6745 verify_func(cmd);
6675 6746 }
6676 6747
6677 6748 void
6678 6749 revert_func(cmd_t *cmd)
6679 6750 {
6680 6751 char line[128]; /* enough to ask a question */
6681 6752 boolean_t force = B_FALSE;
6682 6753 boolean_t arg_err = B_FALSE;
6683 6754 int err, arg, answer;
6684 6755
6685 6756 optind = 0;
6686 6757 while ((arg = getopt(cmd->cmd_argc, cmd->cmd_argv, "?F")) != EOF) {
6687 6758 switch (arg) {
6688 6759 case '?':
6689 6760 longer_usage(CMD_REVERT);
6690 6761 arg_err = B_TRUE;
6691 6762 break;
6692 6763 case 'F':
6693 6764 force = B_TRUE;
6694 6765 break;
6695 6766 default:
6696 6767 short_usage(CMD_REVERT);
6697 6768 arg_err = B_TRUE;
6698 6769 break;
6699 6770 }
6700 6771 }
6701 6772 if (arg_err)
6702 6773 return;
6703 6774
6704 6775 if (optind != cmd->cmd_argc) {
6705 6776 short_usage(CMD_REVERT);
6706 6777 return;
6707 6778 }
6708 6779
6709 6780 if (zone_is_read_only(CMD_REVERT))
6710 6781 return;
6711 6782
6712 6783 if (!global_scope) {
6713 6784 zerr(gettext("You can only use %s in the global scope.\nUse"
6714 6785 " '%s' to cancel changes to a resource specification."),
6715 6786 cmd_to_str(CMD_REVERT), cmd_to_str(CMD_CANCEL));
6716 6787 saw_error = B_TRUE;
6717 6788 return;
6718 6789 }
6719 6790
6720 6791 if (zonecfg_check_handle(handle) != Z_OK) {
6721 6792 zerr(gettext("No changes to revert."));
6722 6793 saw_error = B_TRUE;
6723 6794 return;
6724 6795 }
6725 6796
6726 6797 if (!force) {
6727 6798 (void) snprintf(line, sizeof (line),
6728 6799 gettext("Are you sure you want to revert"));
6729 6800 if ((answer = ask_yesno(B_FALSE, line)) == -1) {
6730 6801 zerr(gettext("Input not from terminal and -F not "
6731 6802 "specified:\n%s command ignored, exiting."),
6732 6803 cmd_to_str(CMD_REVERT));
6733 6804 exit(Z_ERR);
6734 6805 }
6735 6806 if (answer != 1)
6736 6807 return;
6737 6808 }
6738 6809
6739 6810 /*
6740 6811 * Reset any pending admins that were
6741 6812 * removed from the previous zone
6742 6813 */
6743 6814 zonecfg_remove_userauths(handle, "", zone, B_FALSE);
6744 6815
6745 6816 /*
6746 6817 * Time for a new handle: finish the old one off first
6747 6818 * then get a new one properly to avoid leaks.
6748 6819 */
6749 6820 zonecfg_fini_handle(handle);
6750 6821 if ((handle = zonecfg_init_handle()) == NULL) {
6751 6822 zone_perror(execname, Z_NOMEM, B_TRUE);
6752 6823 exit(Z_ERR);
6753 6824 }
6754 6825
6755 6826 if ((err = zonecfg_get_handle(revert_zone, handle)) != Z_OK) {
6756 6827 saw_error = B_TRUE;
6757 6828 got_handle = B_FALSE;
6758 6829 if (err == Z_NO_ZONE)
6759 6830 zerr(gettext("%s: no such saved zone to revert to."),
6760 6831 revert_zone);
6761 6832 else
6762 6833 zone_perror(zone, err, B_TRUE);
6763 6834 }
6764 6835 (void) strlcpy(zone, revert_zone, sizeof (zone));
6765 6836 }
6766 6837
6767 6838 void
6768 6839 help_func(cmd_t *cmd)
6769 6840 {
6770 6841 int i;
6771 6842
6772 6843 assert(cmd != NULL);
6773 6844
6774 6845 if (cmd->cmd_argc == 0) {
6775 6846 usage(B_TRUE, global_scope ? HELP_SUBCMDS : HELP_RES_SCOPE);
6776 6847 return;
6777 6848 }
6778 6849 if (strcmp(cmd->cmd_argv[0], "usage") == 0) {
6779 6850 usage(B_TRUE, HELP_USAGE);
6780 6851 return;
6781 6852 }
6782 6853 if (strcmp(cmd->cmd_argv[0], "commands") == 0) {
6783 6854 usage(B_TRUE, HELP_SUBCMDS);
6784 6855 return;
6785 6856 }
6786 6857 if (strcmp(cmd->cmd_argv[0], "syntax") == 0) {
6787 6858 usage(B_TRUE, HELP_SYNTAX | HELP_RES_PROPS);
6788 6859 return;
6789 6860 }
6790 6861 if (strcmp(cmd->cmd_argv[0], "-?") == 0) {
6791 6862 longer_usage(CMD_HELP);
6792 6863 return;
6793 6864 }
6794 6865
6795 6866 for (i = 0; i <= CMD_MAX; i++) {
6796 6867 if (strcmp(cmd->cmd_argv[0], cmd_to_str(i)) == 0) {
6797 6868 longer_usage(i);
6798 6869 return;
6799 6870 }
6800 6871 }
6801 6872 /* We do not use zerr() here because we do not want its extra \n. */
6802 6873 (void) fprintf(stderr, gettext("Unknown help subject %s. "),
6803 6874 cmd->cmd_argv[0]);
6804 6875 usage(B_FALSE, HELP_META);
6805 6876 }
6806 6877
6807 6878 static int
6808 6879 string_to_yyin(char *string)
6809 6880 {
6810 6881 if ((yyin = tmpfile()) == NULL) {
6811 6882 zone_perror(execname, Z_TEMP_FILE, B_TRUE);
6812 6883 return (Z_ERR);
6813 6884 }
6814 6885 if (fwrite(string, strlen(string), 1, yyin) != 1) {
6815 6886 zone_perror(execname, Z_TEMP_FILE, B_TRUE);
6816 6887 return (Z_ERR);
6817 6888 }
6818 6889 if (fseek(yyin, 0, SEEK_SET) != 0) {
6819 6890 zone_perror(execname, Z_TEMP_FILE, B_TRUE);
6820 6891 return (Z_ERR);
6821 6892 }
6822 6893 return (Z_OK);
6823 6894 }
6824 6895
6825 6896 /* This is the back-end helper function for read_input() below. */
6826 6897
6827 6898 static int
6828 6899 cleanup()
6829 6900 {
6830 6901 int answer;
6831 6902 cmd_t *cmd;
6832 6903
6833 6904 if (!interactive_mode && !cmd_file_mode) {
6834 6905 /*
6835 6906 * If we're not in interactive mode, and we're not in command
6836 6907 * file mode, then we must be in commands-from-the-command-line
6837 6908 * mode. As such, we can't loop back and ask for more input.
6838 6909 * It was OK to prompt for such things as whether or not to
6839 6910 * really delete a zone in the command handler called from
6840 6911 * yyparse() above, but "really quit?" makes no sense in this
6841 6912 * context. So disable prompting.
6842 6913 */
6843 6914 ok_to_prompt = B_FALSE;
6844 6915 }
6845 6916 if (!global_scope) {
6846 6917 if (!time_to_exit) {
6847 6918 /*
6848 6919 * Just print a simple error message in the -1 case,
6849 6920 * since exit_func() already handles that case, and
6850 6921 * EOF means we are finished anyway.
6851 6922 */
6852 6923 answer = ask_yesno(B_FALSE,
6853 6924 gettext("Resource incomplete; really quit"));
6854 6925 if (answer == -1) {
6855 6926 zerr(gettext("Resource incomplete."));
6856 6927 return (Z_ERR);
6857 6928 }
6858 6929 if (answer != 1) {
6859 6930 yyin = stdin;
6860 6931 return (Z_REPEAT);
6861 6932 }
6862 6933 } else {
6863 6934 saw_error = B_TRUE;
6864 6935 }
6865 6936 }
6866 6937 /*
6867 6938 * Make sure we tried something and that the handle checks
6868 6939 * out, or we would get a false error trying to commit.
6869 6940 */
6870 6941 if (need_to_commit && zonecfg_check_handle(handle) == Z_OK) {
6871 6942 if ((cmd = alloc_cmd()) == NULL) {
6872 6943 zone_perror(zone, Z_NOMEM, B_TRUE);
6873 6944 return (Z_ERR);
6874 6945 }
6875 6946 cmd->cmd_argc = 0;
6876 6947 cmd->cmd_argv[0] = NULL;
6877 6948 commit_func(cmd);
6878 6949 free_cmd(cmd);
6879 6950 /*
6880 6951 * need_to_commit will get set back to FALSE if the
6881 6952 * configuration is saved successfully.
6882 6953 */
6883 6954 if (need_to_commit) {
6884 6955 if (force_exit) {
6885 6956 zerr(gettext("Configuration not saved."));
6886 6957 return (Z_ERR);
6887 6958 }
6888 6959 answer = ask_yesno(B_FALSE,
6889 6960 gettext("Configuration not saved; really quit"));
6890 6961 if (answer == -1) {
6891 6962 zerr(gettext("Configuration not saved."));
6892 6963 return (Z_ERR);
6893 6964 }
6894 6965 if (answer != 1) {
6895 6966 time_to_exit = B_FALSE;
6896 6967 yyin = stdin;
6897 6968 return (Z_REPEAT);
6898 6969 }
6899 6970 }
6900 6971 }
6901 6972 return ((need_to_commit || saw_error) ? Z_ERR : Z_OK);
6902 6973 }
6903 6974
6904 6975 /*
6905 6976 * read_input() is the driver of this program. It is a wrapper around
6906 6977 * yyparse(), printing appropriate prompts when needed, checking for
6907 6978 * exit conditions and reacting appropriately [the latter in its cleanup()
6908 6979 * helper function].
6909 6980 *
6910 6981 * Like most zonecfg functions, it returns Z_OK or Z_ERR, *or* Z_REPEAT
6911 6982 * so do_interactive() knows that we are not really done (i.e, we asked
6912 6983 * the user if we should really quit and the user said no).
6913 6984 */
6914 6985 static int
6915 6986 read_input()
6916 6987 {
6917 6988 boolean_t yyin_is_a_tty = isatty(fileno(yyin));
6918 6989 /*
6919 6990 * The prompt is "e:z> " or "e:z:r> " where e is execname, z is zone
6920 6991 * and r is resource_scope: 5 is for the two ":"s + "> " + terminator.
6921 6992 */
6922 6993 char prompt[MAXPATHLEN + ZONENAME_MAX + MAX_RT_STRLEN + 5], *line;
6923 6994
6924 6995 /* yyin should have been set to the appropriate (FILE *) if not stdin */
6925 6996 newline_terminated = B_TRUE;
6926 6997 for (;;) {
6927 6998 if (yyin_is_a_tty) {
6928 6999 if (newline_terminated) {
6929 7000 if (global_scope)
6930 7001 (void) snprintf(prompt, sizeof (prompt),
6931 7002 "%s:%s> ", execname, zone);
6932 7003 else
6933 7004 (void) snprintf(prompt, sizeof (prompt),
6934 7005 "%s:%s:%s> ", execname, zone,
6935 7006 rt_to_str(resource_scope));
6936 7007 }
6937 7008 /*
6938 7009 * If the user hits ^C then we want to catch it and
6939 7010 * start over. If the user hits EOF then we want to
6940 7011 * bail out.
6941 7012 */
6942 7013 line = gl_get_line(gl, prompt, NULL, -1);
6943 7014 if (gl_return_status(gl) == GLR_SIGNAL) {
6944 7015 gl_abandon_line(gl);
6945 7016 continue;
6946 7017 }
6947 7018 if (line == NULL)
6948 7019 break;
6949 7020 (void) string_to_yyin(line);
6950 7021 while (!feof(yyin))
6951 7022 yyparse();
6952 7023 } else {
6953 7024 yyparse();
6954 7025 }
6955 7026 /* Bail out on an error in command file mode. */
6956 7027 if (saw_error && cmd_file_mode && !interactive_mode)
6957 7028 time_to_exit = B_TRUE;
6958 7029 if (time_to_exit || (!yyin_is_a_tty && feof(yyin)))
6959 7030 break;
6960 7031 }
6961 7032 return (cleanup());
6962 7033 }
6963 7034
6964 7035 /*
6965 7036 * This function is used in the zonecfg-interactive-mode scenario: it just
6966 7037 * calls read_input() until we are done.
6967 7038 */
6968 7039
6969 7040 static int
6970 7041 do_interactive(void)
6971 7042 {
6972 7043 int err;
6973 7044
6974 7045 interactive_mode = B_TRUE;
6975 7046 if (!read_only_mode) {
6976 7047 /*
6977 7048 * Try to set things up proactively in interactive mode, so
6978 7049 * that if the zone in question does not exist yet, we can
6979 7050 * provide the user with a clue.
6980 7051 */
6981 7052 (void) initialize(B_FALSE);
6982 7053 }
6983 7054 do {
6984 7055 err = read_input();
6985 7056 } while (err == Z_REPEAT);
6986 7057 return (err);
6987 7058 }
6988 7059
6989 7060 /*
6990 7061 * cmd_file is slightly more complicated, as it has to open the command file
6991 7062 * and set yyin appropriately. Once that is done, though, it just calls
6992 7063 * read_input(), and only once, since prompting is not possible.
6993 7064 */
6994 7065
6995 7066 static int
6996 7067 cmd_file(char *file)
6997 7068 {
6998 7069 FILE *infile;
6999 7070 int err;
7000 7071 struct stat statbuf;
7001 7072 boolean_t using_real_file = (strcmp(file, "-") != 0);
7002 7073
7003 7074 if (using_real_file) {
7004 7075 /*
7005 7076 * zerr() prints a line number in cmd_file_mode, which we do
7006 7077 * not want here, so temporarily unset it.
7007 7078 */
7008 7079 cmd_file_mode = B_FALSE;
7009 7080 if ((infile = fopen(file, "r")) == NULL) {
7010 7081 zerr(gettext("could not open file %s: %s"),
7011 7082 file, strerror(errno));
7012 7083 return (Z_ERR);
7013 7084 }
7014 7085 if ((err = fstat(fileno(infile), &statbuf)) != 0) {
7015 7086 zerr(gettext("could not stat file %s: %s"),
7016 7087 file, strerror(errno));
7017 7088 err = Z_ERR;
7018 7089 goto done;
7019 7090 }
7020 7091 if (!S_ISREG(statbuf.st_mode)) {
7021 7092 zerr(gettext("%s is not a regular file."), file);
7022 7093 err = Z_ERR;
7023 7094 goto done;
7024 7095 }
7025 7096 yyin = infile;
7026 7097 cmd_file_mode = B_TRUE;
7027 7098 ok_to_prompt = B_FALSE;
7028 7099 } else {
7029 7100 /*
7030 7101 * "-f -" is essentially the same as interactive mode,
7031 7102 * so treat it that way.
7032 7103 */
7033 7104 interactive_mode = B_TRUE;
7034 7105 }
7035 7106 /* Z_REPEAT is for interactive mode; treat it like Z_ERR here. */
7036 7107 if ((err = read_input()) == Z_REPEAT)
7037 7108 err = Z_ERR;
7038 7109 done:
7039 7110 if (using_real_file)
7040 7111 (void) fclose(infile);
7041 7112 return (err);
7042 7113 }
7043 7114
7044 7115 /*
7045 7116 * Since yacc is based on reading from a (FILE *) whereas what we get from
7046 7117 * the command line is in argv format, we need to convert when the user
7047 7118 * gives us commands directly from the command line. That is done here by
7048 7119 * concatenating the argv list into a space-separated string, writing it
7049 7120 * to a temp file, and rewinding the file so yyin can be set to it. Then
7050 7121 * we call read_input(), and only once, since prompting about whether to
7051 7122 * continue or quit would make no sense in this context.
7052 7123 */
7053 7124
7054 7125 static int
7055 7126 one_command_at_a_time(int argc, char *argv[])
7056 7127 {
7057 7128 char *command;
7058 7129 size_t len = 2; /* terminal \n\0 */
7059 7130 int i, err;
7060 7131
7061 7132 for (i = 0; i < argc; i++)
7062 7133 len += strlen(argv[i]) + 1;
7063 7134 if ((command = malloc(len)) == NULL) {
7064 7135 zone_perror(execname, Z_NOMEM, B_TRUE);
7065 7136 return (Z_ERR);
7066 7137 }
7067 7138 (void) strlcpy(command, argv[0], len);
7068 7139 for (i = 1; i < argc; i++) {
7069 7140 (void) strlcat(command, " ", len);
7070 7141 (void) strlcat(command, argv[i], len);
7071 7142 }
7072 7143 (void) strlcat(command, "\n", len);
7073 7144 err = string_to_yyin(command);
7074 7145 free(command);
7075 7146 if (err != Z_OK)
7076 7147 return (err);
7077 7148 while (!feof(yyin))
7078 7149 yyparse();
7079 7150 return (cleanup());
7080 7151 }
7081 7152
7082 7153 static char *
7083 7154 get_execbasename(char *execfullname)
7084 7155 {
7085 7156 char *last_slash, *execbasename;
7086 7157
7087 7158 /* guard against '/' at end of command invocation */
7088 7159 for (;;) {
7089 7160 last_slash = strrchr(execfullname, '/');
7090 7161 if (last_slash == NULL) {
7091 7162 execbasename = execfullname;
7092 7163 break;
7093 7164 } else {
7094 7165 execbasename = last_slash + 1;
7095 7166 if (*execbasename == '\0') {
7096 7167 *last_slash = '\0';
7097 7168 continue;
7098 7169 }
7099 7170 break;
7100 7171 }
7101 7172 }
7102 7173 return (execbasename);
7103 7174 }
7104 7175
7105 7176 int
7106 7177 main(int argc, char *argv[])
7107 7178 {
7108 7179 int err, arg;
7109 7180 struct stat st;
7110 7181
7111 7182 /* This must be before anything goes to stdout. */
7112 7183 setbuf(stdout, NULL);
7113 7184
7114 7185 saw_error = B_FALSE;
7115 7186 cmd_file_mode = B_FALSE;
7116 7187 execname = get_execbasename(argv[0]);
7117 7188
7118 7189 (void) setlocale(LC_ALL, "");
7119 7190 (void) textdomain(TEXT_DOMAIN);
7120 7191
7121 7192 if (getzoneid() != GLOBAL_ZONEID) {
7122 7193 zerr(gettext("%s can only be run from the global zone."),
7123 7194 execname);
7124 7195 exit(Z_ERR);
7125 7196 }
7126 7197
7127 7198 if (argc < 2) {
7128 7199 usage(B_FALSE, HELP_USAGE | HELP_SUBCMDS);
7129 7200 exit(Z_USAGE);
7130 7201 }
7131 7202 if (strcmp(argv[1], cmd_to_str(CMD_HELP)) == 0) {
7132 7203 (void) one_command_at_a_time(argc - 1, &(argv[1]));
7133 7204 exit(Z_OK);
7134 7205 }
7135 7206
7136 7207 while ((arg = getopt(argc, argv, "?f:R:z:")) != EOF) {
7137 7208 switch (arg) {
7138 7209 case '?':
7139 7210 if (optopt == '?')
7140 7211 usage(B_TRUE, HELP_USAGE | HELP_SUBCMDS);
7141 7212 else
7142 7213 usage(B_FALSE, HELP_USAGE);
7143 7214 exit(Z_USAGE);
7144 7215 /* NOTREACHED */
7145 7216 case 'f':
7146 7217 cmd_file_name = optarg;
7147 7218 cmd_file_mode = B_TRUE;
7148 7219 break;
7149 7220 case 'R':
7150 7221 if (*optarg != '/') {
7151 7222 zerr(gettext("root path must be absolute: %s"),
7152 7223 optarg);
7153 7224 exit(Z_USAGE);
7154 7225 }
7155 7226 if (stat(optarg, &st) == -1 || !S_ISDIR(st.st_mode)) {
7156 7227 zerr(gettext(
7157 7228 "root path must be a directory: %s"),
7158 7229 optarg);
7159 7230 exit(Z_USAGE);
7160 7231 }
7161 7232 zonecfg_set_root(optarg);
7162 7233 break;
7163 7234 case 'z':
7164 7235 if (strcmp(optarg, GLOBAL_ZONENAME) == 0) {
7165 7236 global_zone = B_TRUE;
7166 7237 } else if (zonecfg_validate_zonename(optarg) != Z_OK) {
7167 7238 zone_perror(optarg, Z_BOGUS_ZONE_NAME, B_TRUE);
7168 7239 usage(B_FALSE, HELP_SYNTAX);
7169 7240 exit(Z_USAGE);
7170 7241 }
7171 7242 (void) strlcpy(zone, optarg, sizeof (zone));
7172 7243 (void) strlcpy(revert_zone, optarg, sizeof (zone));
7173 7244 break;
7174 7245 default:
7175 7246 usage(B_FALSE, HELP_USAGE);
7176 7247 exit(Z_USAGE);
7177 7248 }
7178 7249 }
7179 7250
7180 7251 if (optind > argc || strcmp(zone, "") == 0) {
7181 7252 usage(B_FALSE, HELP_USAGE);
7182 7253 exit(Z_USAGE);
7183 7254 }
7184 7255
7185 7256 if ((err = zonecfg_access(zone, W_OK)) == Z_OK) {
7186 7257 read_only_mode = B_FALSE;
7187 7258 } else if (err == Z_ACCES) {
7188 7259 read_only_mode = B_TRUE;
7189 7260 /* skip this message in one-off from command line mode */
7190 7261 if (optind == argc)
7191 7262 (void) fprintf(stderr, gettext("WARNING: you do not "
7192 7263 "have write access to this zone's configuration "
7193 7264 "file;\ngoing into read-only mode.\n"));
7194 7265 } else {
7195 7266 fprintf(stderr, "%s: Could not access zone configuration "
7196 7267 "store: %s\n", execname, zonecfg_strerror(err));
7197 7268 exit(Z_ERR);
7198 7269 }
7199 7270
7200 7271 if ((handle = zonecfg_init_handle()) == NULL) {
7201 7272 zone_perror(execname, Z_NOMEM, B_TRUE);
7202 7273 exit(Z_ERR);
7203 7274 }
7204 7275
7205 7276 /*
7206 7277 * This may get set back to FALSE again in cmd_file() if cmd_file_name
7207 7278 * is a "real" file as opposed to "-" (i.e. meaning use stdin).
7208 7279 */
7209 7280 if (isatty(STDIN_FILENO))
7210 7281 ok_to_prompt = B_TRUE;
7211 7282 if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL)
7212 7283 exit(Z_ERR);
7213 7284 if (gl_customize_completion(gl, NULL, cmd_cpl_fn) != 0)
7214 7285 exit(Z_ERR);
7215 7286 (void) sigset(SIGINT, SIG_IGN);
7216 7287 if (optind == argc) {
7217 7288 if (!cmd_file_mode)
7218 7289 err = do_interactive();
7219 7290 else
7220 7291 err = cmd_file(cmd_file_name);
7221 7292 } else {
7222 7293 err = one_command_at_a_time(argc - optind, &(argv[optind]));
7223 7294 }
7224 7295 zonecfg_fini_handle(handle);
7225 7296 if (brand != NULL)
7226 7297 brand_close(brand);
7227 7298 (void) del_GetLine(gl);
7228 7299 return (err);
7229 7300 }
↓ open down ↓ |
1654 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX