Print this page
    
OS-3489 lxbrand 64bit LTP recvmsg01 hangs - cmsghdr size mismatch
OS-3491 lx_boot should bypass distro detection when 'docker' flag set
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-3023 lx brand installer cleanup
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/brand/shared/zone/common.ksh
          +++ new/usr/src/lib/brand/shared/zone/common.ksh
   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.
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
  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  # Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
       22 +# Copyright 2014, Joyent, Inc. All rights reserved.
  22   23  #
  23   24  
  24   25  #
  25   26  # Send the error message to the screen and to the logfile.
  26   27  #
  27   28  error()
  28   29  {
  29   30          typeset fmt="$1"
  30   31          shift
  31   32  
  32   33          printf "${MSG_PREFIX}ERROR: ${fmt}\n" "$@"
  33   34          [[ -n $LOGFILE ]] && printf "[$(date)] ERROR: ${fmt}\n" "$@" >&2
  34   35  }
  35   36  
  36   37  fatal()
  37   38  {
  38   39          typeset fmt="$1"
  39   40          shift
  40   41  
  41   42          error "$fmt" "$@"
  42   43          exit $EXIT_CODE
  43   44  }
  44   45  
  45   46  fail_fatal() {
  46   47          typeset fmt="$1"
  47   48          shift
  48   49  
  49   50          error "$fmt" "$@"
  50   51          exit $ZONE_SUBPROC_FATAL
  51   52  }
  52   53  
  53   54  #
  54   55  # Send the provided printf()-style arguments to the screen and to the logfile.
  55   56  #
  56   57  log()
  57   58  {
  58   59          typeset fmt="$1"
  59   60          shift
  60   61  
  61   62          printf "${MSG_PREFIX}${fmt}\n" "$@"
  62   63          [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
  63   64  }
  64   65  
  65   66  #
  66   67  # Print provided text to the screen if the shell variable "OPT_V" is set.
  67   68  # The text is always sent to the logfile.
  68   69  #
  69   70  vlog()
  70   71  {
  71   72          typeset fmt="$1"
  72   73          shift
  73   74  
  74   75          [[ -n $OPT_V ]] && printf "${MSG_PREFIX}${fmt}\n" "$@"
  75   76          [[ -n $LOGFILE ]] && printf "[$(date)] ${MSG_PREFIX}${fmt}\n" "$@" >&2
  76   77  }
  77   78  
  78   79  #
  79   80  # Validate that the directory is safe.
  80   81  #
  81   82  # It is possible for a malicious zone root user to modify a zone's filesystem
  82   83  # so that modifications made to the zone's filesystem by administrators in the
  83   84  # global zone modify the global zone's filesystem.  We can prevent this by
  84   85  # ensuring that all components of paths accessed by scripts are real (i.e.,
  85   86  # non-symlink) directories.
  86   87  #
  87   88  # NOTE: The specified path should be an absolute path as would be seen from
  88   89  # within the zone.  Also, this function does not check parent directories.
  
    | 
      ↓ open down ↓ | 
    57 lines elided | 
    
      ↑ open up ↑ | 
  
  89   90  # If, for example, you need to ensure that every component of the path
  90   91  # '/foo/bar/baz' is a directory and not a symlink, then do the following:
  91   92  #
  92   93  #       safe_dir /foo
  93   94  #       safe_dir /foo/bar
  94   95  #       safe_dir /foo/bar/baz
  95   96  #
  96   97  safe_dir()
  97   98  {
  98   99          typeset dir="$1"
      100 +        typeset pwd_dir=""
  99  101  
 100      -        if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
 101      -                fatal "$e_baddir" "$dir"
      102 +        if [[ -d $ZONEROOT/$dir ]]; then
      103 +                if [[ -h $ZONEROOT/$dir ]]; then
      104 +                        #
      105 +                        # When dir is a symlink to a directory, we 'cd' to that
      106 +                        # directory to ensure that's under $ZONEROOT. We use pwd
      107 +                        # from /usr/bin instead of built-in because they give
      108 +                        # different results.
      109 +                        #
      110 +                        pwd_dir=$(cd $ZONEROOT/$dir && /usr/bin/pwd)
      111 +                        if [[ $pwd_dir =~ "^$ZONEROOT" ]]; then
      112 +                                return;
      113 +                        else
      114 +                                fatal \
      115 +                                    "$e_baddir: symlink out of zoneroot" "$dir"
      116 +                        fi
      117 +                else
      118 +                        # it's a dir and not a symlink, so that's ok.
      119 +                        return
      120 +                fi
 102  121          fi
 103  122  }
 104  123  
 105  124  # Like safe_dir except the dir doesn't have to exist.
 106  125  safe_opt_dir()
 107  126  {
 108  127          typeset dir="$1"
 109  128  
 110  129          [[ ! -e $ZONEROOT/$dir ]] && return
 111  130  
 112      -        if [[ -h $ZONEROOT/$dir || ! -d $ZONEROOT/$dir ]]; then
 113      -                fatal "$e_baddir" "$dir"
 114      -        fi
      131 +        safe_dir $dir
 115  132  }
 116  133  
 117  134  # Only make a copy if we haven't already done so.
 118  135  safe_backup()
 119  136  {
 120  137          typeset src="$1"
 121  138          typeset dst="$2"
 122  139  
 123  140          if [[ ! -h $src && ! -h $dst && ! -d $dst && ! -f $dst ]]; then
 124  141                  /usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
 125  142          fi
 126  143  }
 127  144  
 128  145  # Make a copy even if the destination already exists.
 129  146  safe_copy()
 130  147  {
 131  148          typeset src="$1"
 132  149          typeset dst="$2"
 133  150  
 134  151          if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
 135  152                  /usr/bin/cp -p $src $dst || fatal "$e_badfile" "$src"
 136  153          fi
 137  154  }
 138  155  
 139  156  # Move a file
 140  157  safe_move()
 141  158  {
 142  159          typeset src="$1"
 143  160          typeset dst="$2"
 144  161  
 145  162          if [[ ! -h $src && ! -h $dst && ! -d $dst ]]; then
 146  163                  /usr/bin/mv $src $dst || fatal "$e_badfile" "$src"
 147  164          fi
 148  165  }
 149  166  
 150  167  safe_rm()
 151  168  {
 152  169          if [[ ! -h $ZONEROOT/$1 && -f $ZONEROOT/$1 ]]; then
 153  170                  rm -f "$ZONEROOT/$1"
 154  171          fi
 155  172  }
 156  173  
 157  174  #
 158  175  # Replace the file with a wrapper pointing to the native brand code.
 159  176  # However, we only do the replacement if the file hasn't already been
 160  177  # replaced with our wrapper.  This function expects the cwd to be the
 161  178  # location of the file we're replacing.
 162  179  #
 163  180  # Some of the files we're replacing are hardlinks to isaexec so we need to 'rm'
 164  181  # the file before we setup the wrapper while others are hardlinks to rc scripts
 165  182  # that we need to maintain.
 166  183  #
 167  184  safe_replace()
 168  185  {
 169  186          typeset filename="$1"
 170  187          typeset runname="$2"
 171  188          typeset mode="$3"
 172  189          typeset own="$4"
 173  190          typeset rem="$5"
 174  191  
 175  192          if [ -h $filename -o ! -f $filename ]; then
 176  193                  return
 177  194          fi
 178  195  
 179  196          egrep -s "Solaris Brand Replacement" $filename
  
    | 
      ↓ open down ↓ | 
    55 lines elided | 
    
      ↑ open up ↑ | 
  
 180  197          if [ $? -eq 0 ]; then
 181  198                  return
 182  199          fi
 183  200  
 184  201          safe_backup $filename $filename.pre_p2v
 185  202          if [ $rem = "remove" ]; then
 186  203                  rm -f $filename
 187  204          fi
 188  205  
 189  206          cat <<-END >$filename || exit 1
 190      -        #!/bin/sh -p
      207 +        #!/bin/sh
 191  208          #
 192  209          # Solaris Brand Replacement
 193  210          #
 194  211          # Attention.  This file has been replaced with a new version for
 195  212          # use in a virtualized environment.  Modification of this script is not
 196  213          # supported and all changes will be lost upon reboot.  The
 197  214          # {name}.pre_p2v version of this file is a backup copy of the
 198  215          # original and should not be deleted.
 199  216          #
 200  217          END
 201  218  
 202  219          echo ". $runname \"\$@\"" >>$filename || exit 1
 203  220  
 204  221          chmod $mode $filename
 205  222          chown $own $filename
 206  223  }
 207  224  
 208  225  safe_wrap()
 209  226  {
 210  227          typeset filename="$1"
 211  228          typeset runname="$2"
 212  229          typeset mode="$3"
 213  230          typeset own="$4"
 214  231  
 215  232          if [ -f $filename ]; then
 216  233                  log "$e_cannot_wrap" "$filename"
 217  234                  exit 1
 218  235          fi
 219  236  
 220  237          cat <<-END >$filename || exit 1
 221  238          #!/bin/sh
 222  239          #
 223  240          # Solaris Brand Wrapper
 224  241          #
 225  242          # Attention.  This file has been created for use in a
 226  243          # virtualized environment.  Modification of this script
 227  244          # is not supported and all changes will be lost upon reboot.
 228  245          #
 229  246          END
 230  247  
 231  248          echo ". $runname \"\$@\"" >>$filename || exit 1
 232  249  
 233  250          chmod $mode $filename
 234  251          chown $own $filename
 235  252  }
 236  253  
 237  254  #
 238  255  # Read zonecfg fs entries and save the relevant data, one entry per
 239  256  # line.
 240  257  # This assumes the properties from the zonecfg output, e.g.:
 241  258  #       fs:
 242  259  #               dir: /opt
 243  260  #               special: /opt
 244  261  #               raw not specified
 245  262  #               type: lofs
 246  263  #               options: [noexec,ro,noatime]
 247  264  #
 248  265  # and it assumes the order of the fs properties as above.
 249  266  #
 250  267  get_fs_info()
 251  268  {
 252  269          zonecfg -z $zonename info fs | nawk '{
 253  270                  if ($1 == "options:") {
 254  271                          # Remove brackets.
 255  272                          options=substr($2, 2, length($2) - 2);
 256  273                          printf("%s %s %s %s\n", dir, type, special, options);
 257  274                  } else if ($1 == "dir:") {
 258  275                          dir=$2;
 259  276                  } else if ($1 == "special:") {
 260  277                          special=$2;
 261  278                  } else if ($1 == "type:") {
 262  279                          type=$2
 263  280                  }
 264  281          }' >> $fstmpfile
 265  282  }
 266  283  
 267  284  #
 268  285  # Mount zonecfg fs entries into the zonepath.
 269  286  #
 270  287  mnt_fs()
 271  288  {
 272  289          if [ ! -s $fstmpfile ]; then
 273  290                  return;
 274  291          fi
 275  292  
 276  293          # Sort the fs entries so we can handle nested mounts.
 277  294          sort $fstmpfile | nawk -v zonepath=$zonepath '{
 278  295                  if (NF == 4)
 279  296                          options="-o " $4;
 280  297                  else
 281  298                          options=""
 282  299  
 283  300                  # Create the mount point.  Ignore errors since we might have
 284  301                  # a nested mount with a pre-existing mount point.
 285  302                  cmd="/usr/bin/mkdir -p " zonepath "/root" $1 " >/dev/null 2>&1"
 286  303                  system(cmd);
 287  304  
 288  305                  cmd="/usr/sbin/mount -F " $2 " " options " " $3 " " \
 289  306                      zonepath "/root" $1;
 290  307                  if (system(cmd) != 0) {
 291  308                          printf("command failed: %s\n", cmd);
 292  309                          exit 1;
 293  310                  }
 294  311          }' >>$LOGFILE
 295  312  }
 296  313  
 297  314  #
 298  315  # Unmount zonecfg fs entries from the zonepath.
 299  316  #
 300  317  umnt_fs()
 301  318  {
 302  319          if [ ! -s $fstmpfile ]; then
 303  320                  return;
 304  321          fi
 305  322  
 306  323          # Reverse sort the fs entries so we can handle nested unmounts.
 307  324          sort -r $fstmpfile | nawk -v zonepath=$zonepath '{
 308  325                  cmd="/usr/sbin/umount " zonepath "/root" $1
 309  326                  if (system(cmd) != 0) {
 310  327                          printf("command failed: %s\n", cmd);
 311  328                  }
 312  329          }' >>$LOGFILE
 313  330  }
 314  331  
 315  332  # Find the dataset mounted on the zonepath.
 316  333  get_zonepath_ds() {
 317  334          ZONEPATH_DS=`/usr/sbin/zfs list -H -t filesystem -o name,mountpoint | \
 318  335              /usr/bin/nawk -v zonepath=$1 '{
 319  336                  if ($2 == zonepath)
 320  337                          print $1
 321  338          }'`
 322  339  
 323  340          if [ -z "$ZONEPATH_DS" ]; then
 324  341                  fail_fatal "$f_no_ds"
 325  342          fi
 326  343  }
 327  344  
 328  345  #
 329  346  # Perform validation and cleanup in the zoneroot after unpacking the archive.
 330  347  #
 331  348  post_unpack()
 332  349  {
 333  350          #
 334  351          # Check if the image was created with a valid libc.so.1.
 335  352          #
 336  353          hwcap=`moe -v -32 $ZONEROOT/lib/libc.so.1 2>&1`
 337  354          if (( $? != 0 )); then
 338  355                  vlog "$f_hwcap_info" "$hwcap"
 339  356                  fail_fatal "$f_sanity_hwcap"
 340  357          fi
 341  358  
 342  359          ( cd "$ZONEROOT" && \
 343  360              find . \( -type b -o -type c \) -exec rm -f "{}" \; )
 344  361  }
 345  362  
 346  363  #
 347  364  # Determine flar compression style from identification file.
 348  365  #
 349  366  get_compression()
 350  367  {
 351  368          typeset ident=$1
 352  369          typeset line=$(grep "^files_compressed_method=" $ident)
 353  370  
 354  371          print ${line##*=}
 355  372  }
 356  373  
 357  374  #
 358  375  # Determine flar archive style from identification file.
 359  376  #
 360  377  get_archiver()
 361  378  {
 362  379          typeset ident=$1
 363  380          typeset line=$(grep "^files_archived_method=" $ident)
 364  381  
 365  382          print ${line##*=}
 366  383  }
 367  384  
 368  385  #
 369  386  # Unpack flar into current directory (which should be zoneroot).  The flash
 370  387  # archive is standard input.  See flash_archive(4) man page.
 371  388  # 
 372  389  # We can't use "flar split" since it will only unpack into a directory called
 373  390  # "archive".  We need to unpack in place in order to properly handle nested
 374  391  # fs mounts within the zone root.  This function does the unpacking into the
 375  392  # current directory.
 376  393  #
 377  394  # This code is derived from the gen_split() function in /usr/sbin/flar so
 378  395  # we keep the same style as the original.
 379  396  #
 380  397  install_flar()
 381  398  {
 382  399          typeset result
 383  400          typeset archiver_command
 384  401          typeset archiver_arguments
 385  402  
 386  403          vlog "cd $ZONEROOT && $stage1 "$insrc" | install_flar"
 387  404  
 388  405          # Read cookie
 389  406          read -r input_line
 390  407          if (( $? != 0 )); then
 391  408                  log "$not_readable" "$install_media"
 392  409                  return 1
 393  410          fi
 394  411          # The cookie has format FlAsH-aRcHiVe-m.n where m and n are integers.
 395  412          if [[ ${input_line%%-[0-9]*.[0-9]*} != "FlAsH-aRcHiVe" ]]; then
 396  413                  log "$not_flar"
 397  414                  return 1
 398  415          fi
 399  416  
 400  417          while [ true ]
 401  418          do
 402  419                  # We should always be at the start of a section here
 403  420                  read -r input_line
 404  421                  if [[ ${input_line%%=*} != "section_begin" ]]; then
 405  422                          log "$bad_flar"
 406  423                          return 1
 407  424                  fi
 408  425                  section_name=${input_line##*=}
 409  426  
 410  427                  # If we're at the archive, we're done skipping sections.
 411  428                  if [[ "$section_name" == "archive" ]]; then
 412  429                          break
 413  430                  fi
 414  431                  
 415  432                  #
 416  433                  # Save identification section to a file so we can determine
 417  434                  # how to unpack the archive.
 418  435                  #
 419  436                  if [[ "$section_name" == "identification" ]]; then
 420  437                          /usr/bin/rm -f identification
 421  438                          while read -r input_line
 422  439                          do
 423  440                                  if [[ ${input_line%%=*} == \
 424  441                                      "section_begin" ]]; then
 425  442                                          /usr/bin/rm -f identification
 426  443                                          log "$bad_flar"
 427  444                                          return 1
 428  445                                  fi
 429  446  
 430  447                                  if [[ $input_line == \
 431  448                                      "section_end=$section_name" ]]; then
 432  449                                          break;
 433  450                                  fi
 434  451                                  echo $input_line >> identification
 435  452                          done
 436  453  
 437  454                          continue
 438  455                  fi
 439  456  
 440  457                  #
 441  458                  # Otherwise skip past this section; read lines until detecting
 442  459                  # section_end.  According to flash_archive(4) we can have
 443  460                  # an arbitrary number of sections but the archive section
 444  461                  # must be last.
 445  462                  #
 446  463                  success=0
 447  464                  while read -r input_line
 448  465                  do
 449  466                          if [[ $input_line == "section_end=$section_name" ]];
 450  467                          then
 451  468                                  success=1
 452  469                                  break
 453  470                          fi
 454  471                          # Fail if we miss the end of the section
 455  472                          if [[ ${input_line%%=*} == "section_begin" ]]; then
 456  473                                  /usr/bin/rm -f identification
 457  474                                  log "$bad_flar"
 458  475                                  return 1
 459  476                          fi
 460  477                  done
 461  478                  if (( $success == 0 )); then
 462  479                          #
 463  480                          # If we get here we read to the end of the file before
 464  481                          # seeing the end of the section we were reading.
 465  482                          #
 466  483                          /usr/bin/rm -f identification
 467  484                          log "$bad_flar"
 468  485                          return 1
 469  486                  fi
 470  487          done
 471  488  
 472  489          # Check for an archive made from a ZFS root pool.
 473  490          egrep -s "^rootpool=" identification
 474  491          if (( $? == 0 )); then
 475  492                  /usr/bin/rm -f identification
 476  493                  log "$bad_zfs_flar"
 477  494                  return 1
 478  495          fi
 479  496  
 480  497          # Get the information needed to unpack the archive.
 481  498          archiver=$(get_archiver identification)
 482  499          if [[ $archiver == "pax" ]]; then
 483  500                  # pax archiver specified
 484  501                  archiver_command="/usr/bin/pax"
 485  502                  if [[ -s $fspaxfile ]]; then
 486  503                          archiver_arguments="-r -p e -c \
 487  504                              $(/usr/bin/cat $fspaxfile)"
 488  505                  else
 489  506                          archiver_arguments="-r -p e"
 490  507                  fi
 491  508          elif [[ $archiver == "cpio" || -z $archiver ]]; then
 492  509                  # cpio archived specified OR no archiver specified - use default
 493  510                  archiver_command="/usr/bin/cpio"
 494  511                  archiver_arguments="-icdumfE $fscpiofile"
 495  512          else
 496  513                  # unknown archiver specified
 497  514                  log "$unknown_archiver" $archiver
 498  515                  return 1
 499  516          fi
 500  517  
 501  518          if [[ ! -x $archiver_command ]]; then
 502  519                  /usr/bin/rm -f identification
 503  520                  log "$cmd_not_exec" $archiver_command
 504  521                  return 1
 505  522          fi 
 506  523  
 507  524          compression=$(get_compression identification)
 508  525  
 509  526          # We're done with the identification file
 510  527          /usr/bin/rm -f identification
 511  528  
 512  529          # Extract archive
 513  530          if [[ $compression == "compress" ]]; then
 514  531                  /usr/bin/zcat | \
 515  532                      $archiver_command $archiver_arguments 2>/dev/null
 516  533          else
 517  534                  $archiver_command $archiver_arguments 2>/dev/null
 518  535          fi
 519  536          result=$?
 520  537  
 521  538          post_unpack
 522  539  
 523  540          (( $result != 0 )) && return 1
 524  541  
 525  542          return 0 
 526  543  }
 527  544  
 528  545  #
 529  546  # Get the archive base.
 530  547  #
 531  548  # We must unpack the archive in the right place within the zonepath so
 532  549  # that files are installed into the various mounted filesystems that are set
 533  550  # up in the zone's configuration.  These are already mounted for us by the
 534  551  # mntfs function.
 535  552  #
 536  553  # Archives can be made of either a physical host's root file system or a
 537  554  # zone's zonepath.  For a physical system, if the archive is made using an
 538  555  # absolute path (/...) we can't use it.  For a zone the admin can make the
 539  556  # archive from a variety of locations;
 540  557  #
 541  558  #   a) zonepath itself: This will be a single dir, probably named with the
 542  559  #      zone name, it will contain a root dir and under the root we'll see all
 543  560  #      the top level dirs; etc, var, usr...  We must be above the ZONEPATH
 544  561  #      when we unpack the archive but this will only work if the the archive's
 545  562  #      top-level dir name matches the ZONEPATH base-level dir name.  If not,
 546  563  #      this is an error.
 547  564  #
 548  565  #   b) inside the zonepath: We'll see root and it will contain all the top
 549  566  #      level dirs; etc, var, usr....  We must be in the ZONEPATH when we unpack
 550  567  #      the archive.
 551  568  #
 552  569  #   c) inside the zonepath root: We'll see all the top level dirs, ./etc,
 553  570  #      ./var, ./usr....  This is also the case we see when we get an archive
 554  571  #      of a physical sytem.  We must be in ZONEROOT when we unpack the archive.
 555  572  #
 556  573  # Note that there can be a directory named "root" under the ZONEPATH/root
 557  574  # directory.
 558  575  #
 559  576  # This function handles the above possibilities so that we reject absolute
 560  577  # path archives and figure out where in the file system we need to be to
 561  578  # properly unpack the archive into the zone.  It sets the ARCHIVE_BASE
 562  579  # variable to the location where the achive should be unpacked.
 563  580  #
 564  581  get_archive_base()
 565  582  {
 566  583          stage1=$1
 567  584          archive=$2
 568  585          stage2=$3
 569  586  
 570  587          vlog "$m_analyse_archive"
 571  588  
 572  589          base=`$stage1 $archive | $stage2 2>/dev/null | nawk -F/ '{
 573  590                  # Check for an absolute path archive
 574  591                  if (substr($0, 1, 1) == "/")
 575  592                          exit 1
 576  593  
 577  594                  if ($1 != ".")
 578  595                          dirs[$1] = 1
 579  596                  else
 580  597                          dirs[$2] = 1
 581  598          }
 582  599          END {
 583  600                  for (d in dirs) {
 584  601                          cnt++
 585  602                          if (d == "bin")  sawbin = 1
 586  603                          if (d == "etc")  sawetc = 1
 587  604                          if (d == "root") sawroot = 1
 588  605                          if (d == "var")  sawvar = 1
 589  606                  }
 590  607  
 591  608                  if (cnt == 1) {
 592  609                          # If only one top-level dir named root, we are in the
 593  610                          # zonepath, otherwise this must be an archive *of*
 594  611                          # the zonepath so print the top-level dir name.
 595  612                          if (sawroot)
 596  613                                  print "*zonepath*"
 597  614                          else
 598  615                                  for (d in dirs) print d
 599  616                  } else {
 600  617                          # We are either in the zonepath or in the zonepath/root
 601  618                          # (or at the top level of a full system archive which
 602  619                          # looks like the zonepath/root case).  Figure out which
 603  620                          # one.
 604  621                          if (sawroot && !sawbin && !sawetc && !sawvar)
 605  622                                  print "*zonepath*"
 606  623                          else
 607  624                                  print "*zoneroot*"
 608  625                  }
 609  626          }'`
 610  627  
 611  628          if (( $? != 0 )); then
 612  629                  umnt_fs
 613  630                  fatal "$e_absolute_archive"
 614  631          fi
 615  632  
 616  633          if [[ "$base" == "*zoneroot*" ]]; then
 617  634                  ARCHIVE_BASE=$ZONEROOT
 618  635          elif [[ "$base" == "*zonepath*" ]]; then
 619  636                  ARCHIVE_BASE=$ZONEPATH
 620  637          else
 621  638                  # We need to be in the dir above the ZONEPATH but we need to
 622  639                  # validate that $base matches the final component of ZONEPATH.
 623  640                  bname=`basename $ZONEPATH`
 624  641  
 625  642                  if [[ "$bname" != "$base" ]]; then
 626  643                          umnt_fs
 627  644                          fatal "$e_mismatch_archive" "$base" "$bname"
 628  645                  fi
 629  646                  ARCHIVE_BASE=`dirname $ZONEPATH`
 630  647          fi
 631  648  }
 632  649  
 633  650  #
 634  651  # Unpack cpio archive into zoneroot.
 635  652  #
 636  653  install_cpio()
 637  654  {
 638  655          stage1=$1
 639  656          archive=$2
 640  657  
 641  658          get_archive_base "$stage1" "$archive" "cpio -it"
 642  659  
 643  660          cpioopts="-idmfE $fscpiofile"
 644  661  
 645  662          vlog "cd \"$ARCHIVE_BASE\" && $stage1 \"$archive\" | cpio $cpioopts"
 646  663  
 647  664          # Ignore errors from cpio since we expect some errors depending on
 648  665          # how the archive was made.
 649  666          ( cd "$ARCHIVE_BASE" && $stage1 "$archive" | cpio $cpioopts )
 650  667  
 651  668          post_unpack
 652  669  
 653  670          return 0
 654  671  }
 655  672  
 656  673  #
 657  674  # Unpack pax archive into zoneroot.
 658  675  #
 659  676  install_pax()
 660  677  {
 661  678          archive=$1
 662  679  
 663  680          get_archive_base "cat" "$archive" "pax"
 664  681  
 665  682          if [[ -s $fspaxfile ]]; then
 666  683                  filtopt="-c $(/usr/bin/cat $fspaxfile)"
 667  684          fi
 668  685  
 669  686          vlog "cd \"$ARCHIVE_BASE\" && pax -r -f \"$archive\" $filtopt"
 670  687  
 671  688          # Ignore errors from pax since we expect some errors depending on
 672  689          # how the archive was made.
 673  690          ( cd "$ARCHIVE_BASE" && pax -r -f "$archive" $filtopt )
 674  691  
 675  692          post_unpack
 676  693  
 677  694          return 0
 678  695  }
 679  696  
 680  697  #
 681  698  # Unpack UFS dump into zoneroot.
 682  699  #
 683  700  install_ufsdump()
 684  701  {
 685  702          archive=$1
 686  703  
 687  704          vlog "cd \"$ZONEROOT\" && ufsrestore rf \"$archive\""
 688  705  
 689  706          #
 690  707          # ufsrestore goes interactive if you ^C it.  To prevent that,
 691  708          # we make sure its stdin is not a terminal.
 692  709          #
 693  710          ( cd "$ZONEROOT" && ufsrestore rf "$archive" < /dev/null )
 694  711          result=$?
 695  712  
 696  713          post_unpack
 697  714  
 698  715          return $result
 699  716  }
 700  717  
 701  718  #
 702  719  # Copy directory hierarchy into zoneroot.
 703  720  #
 704  721  install_dir()
 705  722  {
 706  723          source_dir=$1
 707  724  
 708  725          cpioopts="-pdm"
 709  726  
 710  727          first=1
 711  728          filt=$(for i in $(cat $fspaxfile)
 712  729                  do
 713  730                          echo $i | egrep -s "/" && continue
 714  731                          if [[ $first == 1 ]]; then
 715  732                                  printf "^%s" $i
 716  733                                  first=0
 717  734                          else
 718  735                                  printf "|^%s" $i
 719  736                          fi
 720  737                  done)
 721  738  
 722  739          list=$(cd "$source_dir" && ls -d * | egrep -v "$filt")
 723  740          flist=$(for i in $list
 724  741          do
 725  742                  printf "%s " "$i"
 726  743          done)
 727  744          findopts="-xdev ( -type d -o -type f -o -type l ) -print"
 728  745  
 729  746          vlog "cd \"$source_dir\" && find $flist $findopts | "
 730  747          vlog "cpio $cpioopts \"$ZONEROOT\""
 731  748  
 732  749          # Ignore errors from cpio since we expect some errors depending on
 733  750          # how the archive was made.
 734  751          ( cd "$source_dir" && find $flist $findopts | \
 735  752              cpio $cpioopts "$ZONEROOT" )
 736  753  
 737  754          post_unpack
 738  755  
 739  756          return 0
 740  757  }
 741  758  
 742  759  #
 743  760  # This is a common function for laying down a zone image from a variety of
 744  761  # different sources.  This can be used to either install a fresh zone or as
 745  762  # part of zone migration during attach.
 746  763  #
 747  764  # The first argument specifies the type of image: archive, directory or stdin.
 748  765  # The second argument specifies the image itself.  In the case of stdin, the
 749  766  # second argument specifies the format of the stream (cpio, flar, etc.).
 750  767  # Any validation or post-processing on the image is done elsewhere.
 751  768  #
 752  769  # This function calls a 'sanity_check' function which must be provided by
 753  770  # the script which includes this code.
 754  771  #
 755  772  install_image()
 756  773  {
 757  774          intype=$1
 758  775          insrc=$2
 759  776  
 760  777          if [[ -z "$intype" || -z "$insrc" ]]; then
 761  778                  return 1
 762  779          fi
 763  780  
 764  781          filetype="unknown"
 765  782          filetypename="unknown"
 766  783          stage1="cat"
 767  784  
 768  785          if [[ "$intype" == "directory" ]]; then
 769  786                  if [[ "$insrc" == "-" ]]; then
 770  787                          # Indicates that the existing zonepath is prepopulated.
 771  788                          filetype="existing"
 772  789                          filetypename="existing"
 773  790                  else
 774  791                          if [[ "$(echo $insrc | cut -c 1)" != "/" ]]; then
 775  792                                  fatal "$e_path_abs" "$insrc"
 776  793                          fi
 777  794  
 778  795                          if [[ ! -e "$insrc" ]]; then
 779  796                                  log "$e_not_found" "$insrc"
 780  797                                  fatal "$e_install_abort"
 781  798                          fi
 782  799  
 783  800                          if [[ ! -r "$insrc" ]]; then
 784  801                                  log "$e_not_readable" "$insrc"
 785  802                                  fatal "$e_install_abort"
 786  803                          fi
 787  804  
 788  805                          if [[ ! -d "$insrc" ]]; then
 789  806                                  log "$e_not_dir"
 790  807                                  fatal "$e_install_abort"
 791  808                          fi
 792  809  
 793  810                          sanity_check $insrc
 794  811  
 795  812                          filetype="directory"
 796  813                          filetypename="directory"
 797  814                  fi
 798  815  
 799  816          else
 800  817                  # Common code for both archive and stdin stream.
 801  818  
 802  819                  if [[ "$intype" == "archive" ]]; then
 803  820                          if [[ ! -f "$insrc" ]]; then
 804  821                                  log "$e_unknown_archive"
 805  822                                  fatal "$e_install_abort"
 806  823                          fi
 807  824                          ftype="$(LC_ALL=C file $insrc | cut -d: -f 2)"
 808  825                  else
 809  826                          # For intype == stdin, the insrc parameter specifies
 810  827                          # the stream format coming on stdin.
 811  828                          ftype="$insrc"
 812  829                          insrc="-"
 813  830                  fi
 814  831  
 815  832                  # Setup vars for the archive type we have.
 816  833                  case "$ftype" in
 817  834                  *cpio*)         filetype="cpio"
 818  835                                  filetypename="cpio archive"
 819  836                          ;;
 820  837                  *bzip2*)        filetype="bzip2"
 821  838                                  filetypename="bzipped cpio archive"
 822  839                          ;;
 823  840                  *gzip*)         filetype="gzip"
 824  841                                  filetypename="gzipped cpio archive"
 825  842                          ;;
 826  843                  *ufsdump*)      filetype="ufsdump"
 827  844                                  filetypename="ufsdump archive"
 828  845                          ;;
 829  846                  "flar")
 830  847                                  filetype="flar"
 831  848                                  filetypename="flash archive"
 832  849                          ;;
 833  850                  "flash")
 834  851                                  filetype="flar"
 835  852                                  filetypename="flash archive"
 836  853                          ;;
 837  854                  *Flash\ Archive*)
 838  855                                  filetype="flar"
 839  856                                  filetypename="flash archive"
 840  857                          ;;
 841  858                  "tar")
 842  859                                  filetype="tar"
 843  860                                  filetypename="tar archive"
 844  861                          ;;
 845  862                  *USTAR\ tar\ archive)
 846  863                                  filetype="tar"
 847  864                                  filetypename="tar archive"
 848  865                          ;;
 849  866                  "pax")
 850  867                                  filetype="xustar"
 851  868                                  filetypename="pax (xustar) archive"
 852  869                          ;;
 853  870                  *USTAR\ tar\ archive\ extended\ format*)
 854  871                                  filetype="xustar"
 855  872                                  filetypename="pax (xustar) archive"
 856  873                          ;;
 857  874                  "zfs")
 858  875                                  filetype="zfs"
 859  876                                  filetypename="ZFS send stream"
 860  877                          ;;
 861  878                  *ZFS\ snapshot\ stream*)
 862  879                                  filetype="zfs"
 863  880                                  filetypename="ZFS send stream"
 864  881                          ;;
 865  882                  *)              log "$e_unknown_archive"
 866  883                                  fatal "$e_install_abort"
 867  884                          ;;
 868  885                  esac
 869  886          fi
 870  887  
 871  888          vlog "$filetypename"
 872  889  
 873  890          # Check for a non-empty root if no '-d -' option. 
 874  891          if [[ "$filetype" != "existing" ]]; then
 875  892                  cnt=$(ls $ZONEROOT | wc -l)
 876  893                  if (( $cnt != 0 )); then
 877  894                          fatal "$e_root_full" "$ZONEROOT"
 878  895                  fi
 879  896          fi
 880  897  
 881  898          fstmpfile=$(/usr/bin/mktemp -t -p /var/tmp)
 882  899          if [[ -z "$fstmpfile" ]]; then
 883  900                  fatal "$e_tmpfile"
 884  901          fi
 885  902  
 886  903          # Make sure we always have the files holding the directories to filter
 887  904          # out when extracting from a CPIO or PAX archive.  We'll add the fs
 888  905          # entries to these files in get_fs_info()
 889  906          fscpiofile=$(/usr/bin/mktemp -t -p /var/tmp fs.cpio.XXXXXX)
 890  907          if [[ -z "$fscpiofile" ]]; then
 891  908                  rm -f $fstmpfile
 892  909                  fatal "$e_tmpfile"
 893  910          fi
 894  911  
 895  912          # Filter out these directories.
 896  913          echo 'dev/*' >>$fscpiofile
 897  914          echo 'devices/*' >>$fscpiofile
 898  915          echo 'devices' >>$fscpiofile
 899  916          echo 'proc/*' >>$fscpiofile
 900  917          echo 'tmp/*' >>$fscpiofile
 901  918          echo 'var/run/*' >>$fscpiofile
 902  919          echo 'system/contract/*' >>$fscpiofile
 903  920          echo 'system/object/*' >>$fscpiofile
 904  921  
 905  922          fspaxfile=$(/usr/bin/mktemp -t -p /var/tmp fs.pax.XXXXXX)
 906  923          if [[ -z "$fspaxfile" ]]; then
 907  924                  rm -f $fstmpfile $fscpiofile
 908  925                  fatal "$e_tmpfile"
 909  926          fi
 910  927  
 911  928          printf "%s " \
 912  929              "dev devices proc tmp var/run system/contract system/object" \
 913  930              >>$fspaxfile
 914  931  
 915  932          # Set up any fs mounts so the archive will install into the correct
 916  933          # locations.
 917  934          get_fs_info
 918  935          mnt_fs
 919  936          if (( $? != 0 )); then
 920  937                  umnt_fs >/dev/null 2>&1
 921  938                  rm -f $fstmpfile $fscpiofile $fspaxfile
 922  939                  fatal "$mount_failed"
 923  940          fi
 924  941  
 925  942          if [[ "$filetype" == "existing" ]]; then
 926  943                  log "$no_installing"
 927  944          else
 928  945                  log "$installing"
 929  946          fi
 930  947  
 931  948          #
 932  949          # Install the image into the zonepath.
 933  950          #
 934  951          unpack_result=0
 935  952          stage1="cat"
 936  953          if [[ "$filetype" == "gzip" ]]; then
 937  954                  stage1="gzcat"
 938  955                  filetype="cpio"
 939  956          elif [[ "$filetype" == "bzip2" ]]; then
 940  957                  stage1="bzcat"
 941  958                  filetype="cpio"
 942  959          fi
 943  960  
 944  961          if [[ "$filetype" == "cpio" ]]; then
 945  962                  install_cpio "$stage1" "$insrc"
 946  963                  unpack_result=$?
 947  964  
 948  965          elif [[ "$filetype" == "flar" ]]; then
 949  966                  ( cd "$ZONEROOT" && $stage1 $insrc | install_flar )
 950  967                  unpack_result=$?
 951  968  
 952  969          elif [[ "$filetype" == "xustar" ]]; then
 953  970                  install_pax "$insrc"
 954  971                  unpack_result=$?
 955  972  
 956  973          elif [[ "$filetype" = "tar" ]]; then
 957  974                  vlog "cd \"$ZONEROOT\" && tar -xf \"$insrc\""
 958  975                  # Ignore errors from tar since we expect some errors depending
 959  976                  # on how the archive was made.
 960  977                  ( cd "$ZONEROOT" && tar -xf "$insrc" )
 961  978                  unpack_result=0
 962  979                  post_unpack
 963  980  
 964  981          elif [[ "$filetype" == "ufsdump" ]]; then
 965  982                  install_ufsdump "$insrc"
 966  983                  unpack_result=$?
 967  984  
 968  985          elif [[ "$filetype" == "directory" ]]; then
 969  986                  install_dir "$insrc"
 970  987                  unpack_result=$?
 971  988  
 972  989          elif [[ "$filetype" == "zfs" ]]; then
 973  990                  #
 974  991                  # Given a 'zfs send' stream file, receive the snapshot into
 975  992                  # the zone's dataset.  We're getting the original system's
 976  993                  # zonepath dataset.  Destroy the existing dataset created
 977  994                  # above since this recreates it.
 978  995                  #
 979  996                  if [[ -z "$DATASET" ]]; then
 980  997                          fatal "$f_nodataset"
 981  998                  fi
 982  999                  /usr/sbin/zfs destroy "$DATASET"
 983 1000                  if (( $? != 0 )); then
 984 1001                          log "$f_zfsdestroy" "$DATASET"
 985 1002                  fi
 986 1003  
 987 1004                  vlog "$stage1 $insrc | zfs receive -F $DATASET"
 988 1005                  ( $stage1 $insrc | /usr/sbin/zfs receive -F $DATASET )
 989 1006                  unpack_result=$?
 990 1007          fi
 991 1008  
 992 1009          # Clean up any fs mounts used during unpacking.
 993 1010          umnt_fs
 994 1011          rm -f $fstmpfile $fscpiofile $fspaxfile
 995 1012  
 996 1013          chmod 700 $zonepath
 997 1014  
 998 1015          (( $unpack_result != 0 )) && fatal "$f_unpack_failed"
 999 1016  
1000 1017          # Verify this is a valid image.
1001 1018          sanity_check $ZONEROOT
1002 1019  
1003 1020          return 0
1004 1021  }
1005 1022  
1006 1023  # Setup i18n output
1007 1024  TEXTDOMAIN="SUNW_OST_OSCMD"
1008 1025  export TEXTDOMAIN
1009 1026  
1010 1027  e_cannot_wrap=$(gettext "%s: error: wrapper file already exists")
1011 1028  e_baddir=$(gettext "Invalid '%s' directory within the zone")
1012 1029  e_badfile=$(gettext "Invalid '%s' file within the zone")
1013 1030  e_path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.")
1014 1031  e_not_found=$(gettext "%s: error: file or directory not found.")
1015 1032  e_install_abort=$(gettext "Installation aborted.")
1016 1033  e_not_readable=$(gettext "Cannot read directory '%s'")
1017 1034  e_not_dir=$(gettext "Error: must be a directory")
1018 1035  e_unknown_archive=$(gettext "Error: Unknown archive format. Must be a flash archive, a cpio archive (can also be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.")
1019 1036  e_absolute_archive=$(gettext "Error: archive contains absolute paths instead of relative paths.")
1020 1037  e_mismatch_archive=$(gettext "Error: the archive top-level directory (%s) does not match the zonepath (%s).")
1021 1038  e_tmpfile=$(gettext "Unable to create temporary file")
1022 1039  e_root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.")
1023 1040  f_mkdir=$(gettext "Unable to create directory %s.")
1024 1041  f_chmod=$(gettext "Unable to chmod directory %s.")
1025 1042  f_chown=$(gettext "Unable to chown directory %s.")
1026 1043  f_hwcap_info=$(gettext "HWCAP: %s\n")
1027 1044  f_sanity_hwcap=$(gettext \
1028 1045  "The image was created with an incompatible libc.so.1 hwcap lofs mount.\n"\
1029 1046  "       The zone will not boot on this platform.  See the zone's\n"\
1030 1047  "       documentation for the recommended way to create the archive.")
1031 1048  
1032 1049  m_analyse_archive=$(gettext "Analysing the archive")
1033 1050  
1034 1051  not_readable=$(gettext "Cannot read file '%s'")
1035 1052  not_flar=$(gettext "Input is not a flash archive")
1036 1053  bad_flar=$(gettext "Flash archive is a corrupt")
1037 1054  bad_zfs_flar=$(gettext "Flash archive contains a ZFS send stream.\n\tRecreate the flar using the -L option with cpio or pax.")
1038 1055  f_unpack_failed=$(gettext "Unpacking the archive failed")
1039 1056  unknown_archiver=$(gettext "Archiver %s is not supported")
1040 1057  cmd_not_exec=$(gettext "Required command '%s' not executable!")
1041 1058  
1042 1059  #
1043 1060  # Exit values used by the script, as #defined in <sys/zone.h>
1044 1061  #
1045 1062  #       ZONE_SUBPROC_OK
1046 1063  #       ===============
1047 1064  #       Installation was successful
1048 1065  #
1049 1066  #       ZONE_SUBPROC_USAGE
1050 1067  #       ==================
1051 1068  #       Improper arguments were passed, so print a usage message before exiting
1052 1069  #
1053 1070  #       ZONE_SUBPROC_NOTCOMPLETE
1054 1071  #       ========================
1055 1072  #       Installation did not complete, but another installation attempt can be
1056 1073  #       made without an uninstall
1057 1074  #
1058 1075  #       ZONE_SUBPROC_FATAL
1059 1076  #       ==================
1060 1077  #       Installation failed and an uninstall will be required before another
1061 1078  #       install can be attempted
1062 1079  #
1063 1080  ZONE_SUBPROC_OK=0
1064 1081  ZONE_SUBPROC_USAGE=253
1065 1082  ZONE_SUBPROC_NOTCOMPLETE=254
1066 1083  ZONE_SUBPROC_FATAL=255
1067 1084  
  
    | 
      ↓ open down ↓ | 
    867 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX