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