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