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