Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
comparison sbin/ftjail @ 241:acf16a85900f
Mount and unmount template datasets
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sat, 10 Sep 2022 10:09:42 +0200 |
| parents | 04fde1941966 |
| children | 59e933b81dcf |
comparison
equal
deleted
inserted
replaced
| 240:04fde1941966 | 241:acf16a85900f |
|---|---|
| 35 | 35 |
| 36 PARENT-BASE and PARENT-SKELETON must exist already and NAME must | 36 PARENT-BASE and PARENT-SKELETON must exist already and NAME must |
| 37 not exist. | 37 not exist. |
| 38 | 38 |
| 39 The datasets will not be mounted. | 39 The datasets will not be mounted. |
| 40 | |
| 41 mount-tmpl [ OPTIONS ] BASE-RO SKELETON-RW MOUNTPOINT | |
| 42 | |
| 43 Canonically mount the RO base and the RW skeleton into MOUNTPOINT and | |
| 44 MOUNTPOINT/skeleton | |
| 45 | |
| 46 -n Do not really mount but show what would be mounted where | |
| 47 -u Alias of -n | |
| 48 | |
| 49 umount-tmpl BASE-RO SKELETON_RW | |
| 50 | |
| 51 Unmount mounted datasets BASE-RO and SKELETON-RW | |
| 40 | 52 |
| 41 ENVIRONMENT: | 53 ENVIRONMENT: |
| 42 | 54 |
| 43 All environment variables that affect "zfs" are effective also. | 55 All environment variables that affect "zfs" are effective also. |
| 44 | 56 |
| 263 find "${_mp}/boot" -type f -delete | 275 find "${_mp}/boot" -type f -delete |
| 264 } | 276 } |
| 265 | 277 |
| 266 | 278 |
| 267 # | 279 # |
| 268 # "mount" -- recursively mount a dataset including subordinate datasets | 280 # _do_mount dataset mountpoint dry-run mount-natural |
| 269 # | 281 # |
| 270 # command_mount dataset mountpoint | 282 _do_mount() { |
| 271 # | 283 local _dsname _mountpoint _dry_run _mount_natural |
| 272 command_mount() { | |
| 273 local _dsname _mountpoint | |
| 274 local _name _mp _canmount _mounted | 284 local _name _mp _canmount _mounted |
| 275 local _rootds_mountpoint _relative_mp _real_mp | 285 local _rootds_mountpoint _relative_mp _real_mp |
| 276 local _dry_run _mount_outside _mount_natural | 286 |
| 277 | 287 _dsname="${1}" |
| 278 _dry_run="" | 288 _mountpoint="${2}" |
| 279 _mount_outside="" | 289 _dry_run="${3}" |
| 280 _mount_natural="" | 290 _mount_natural="${4}" |
| 281 while getopts "ONnu" _opt ; do | |
| 282 case ${_opt} in | |
| 283 O) | |
| 284 _mount_outside="yes" | |
| 285 ;; | |
| 286 N) | |
| 287 _mount_natural="yes" | |
| 288 ;; | |
| 289 n|u) | |
| 290 _dry_run="yes" | |
| 291 ;; | |
| 292 \?|:) | |
| 293 return 2; | |
| 294 ;; | |
| 295 esac | |
| 296 done | |
| 297 shift $((OPTIND-1)) | |
| 298 OPTIND=1 | |
| 299 | |
| 300 _dsname="${1-}" | |
| 301 _mountpoint="${2-}" | |
| 302 | 291 |
| 303 if [ -z "${_dsname}" ]; then | 292 if [ -z "${_dsname}" ]; then |
| 304 echo "ERROR: no dataset given" >&2 | 293 echo "ERROR: no dataset given" >&2 |
| 305 return 2 | 294 return 2 |
| 306 fi | 295 fi |
| 307 | 296 |
| 308 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || \ | 297 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || \ |
| 309 { echo "ERROR: root dataset does not exist" >&2; return 1; } | 298 { echo "ERROR: root dataset \`${_dsname}' does not exist" >&2; return 1; } |
| 310 | 299 |
| 311 if [ -z "${_mountpoint}" ]; then | 300 if [ -z "${_mountpoint}" ]; then |
| 312 if [ "${_mount_natural}" = "yes" ]; then | 301 if [ "${_mount_natural}" = "yes" ]; then |
| 313 _mountpoint="${_rootds_mountpoint}" | 302 _mountpoint="${_rootds_mountpoint}" |
| 314 else | 303 else |
| 315 echo "ERROR: no mountpoint given" >&2 | 304 echo "ERROR: no mountpoint given" >&2 |
| 316 return 2 | 305 return 2 |
| 317 fi | 306 fi |
| 318 else | 307 else |
| 319 if [ "${_mount_natural}" = "yes" ]; then | 308 if [ "${_mount_natural}" = "yes" ]; then |
| 320 echo "ERROR: Cannot have a custom mountpoint when \"-O\" is given" >&2 | 309 echo "ERROR: Cannot have a custom mountpoint when mount-natural is activated" >&2 |
| 321 return 2 | 310 return 2 |
| 322 fi | 311 fi |
| 323 fi | 312 fi |
| 324 | 313 |
| 325 # Eventually remove a trailing slash | 314 # Eventually remove a trailing slash |
| 373 echo "Mounting ${_name} on ${_real_mp}" | 362 echo "Mounting ${_name} on ${_real_mp}" |
| 374 mount -t zfs "${_name}" "${_real_mp}" || return 1 | 363 mount -t zfs "${_name}" "${_real_mp}" || return 1 |
| 375 fi | 364 fi |
| 376 ;; | 365 ;; |
| 377 *) | 366 *) |
| 378 if [ "${_mount_outside}" = "yes" ]; then | 367 echo "Skipping ${_name} because its configured ZFS mountpoint is not relative to given root dataset" 2>&1 |
| 379 if [ "${_dry_run}" = "yes" ]; then | |
| 380 echo "Would mount ${_name} on configured ZFS dataset mountpoint ${_mp}" | |
| 381 else | |
| 382 echo "Mounting ${_name} on configured ZFS dataset mountpoint ${_mp}" | |
| 383 zfs mount "${_name}" || return 1 | |
| 384 fi | |
| 385 else | |
| 386 echo "Skipping ${_name} because its configured ZFS mountpoint is not relative to given root dataset" 2>&1 | |
| 387 fi | |
| 388 ;; | 368 ;; |
| 389 esac | 369 esac |
| 390 done | 370 done |
| 391 | 371 |
| 392 return 0 | 372 return 0 |
| 393 } | 373 } |
| 394 } | 374 } |
| 395 | 375 |
| 396 | 376 |
| 397 # | 377 # |
| 398 # "umount" -- Recursively unmount ZFS datasets | 378 # "mount-tmpl" -- recursively mount a base and skeleton datasets including subordinate datasets |
| 399 # | 379 # |
| 400 # command_umount dataset | 380 # command_mount_tmpl base-ro skeleton-rw mountpoint |
| 401 # | 381 # |
| 402 command_umount() { | 382 command_mount_tmpl() { |
| 383 local _ds_base _ds_skel _mountpoint | |
| 384 | |
| 385 local _dry_run _opt | |
| 386 | |
| 387 _dry_run="" | |
| 388 | |
| 389 while getopts "nu" _opt ; do | |
| 390 case ${_opt} in | |
| 391 n|u) | |
| 392 _dry_run="yes" | |
| 393 ;; | |
| 394 \?|:) | |
| 395 return 2; | |
| 396 ;; | |
| 397 esac | |
| 398 done | |
| 399 shift $((OPTIND-1)) | |
| 400 OPTIND=1 | |
| 401 | |
| 402 _ds_base="${1-}" | |
| 403 _ds_skel="${2-}" | |
| 404 _mountpoint="${3-}" | |
| 405 | |
| 406 _do_mount "${_ds_base}" "${_mountpoint}" "${_dry_run}" "" || return | |
| 407 if [ "${_dry_run}" != "yes" ]; then | |
| 408 if [ ! -d "${_mountpoint}/skeleton" ]; then | |
| 409 mkdir "${_mountpoint}/skeleton" || return | |
| 410 fi | |
| 411 fi | |
| 412 _do_mount "${_ds_skel}" "${_mountpoint}/skeleton" "${_dry_run}" "" || return | |
| 413 | |
| 414 return 0 | |
| 415 } | |
| 416 | |
| 417 | |
| 418 # | |
| 419 # _do_umount dataset | |
| 420 # | |
| 421 _do_umount() { | |
| 403 local _dsname | 422 local _dsname |
| 404 local _name _mp _rest | 423 local _name _mp _rest |
| 405 local _rootds_mountpoint | 424 local _rootds_mountpoint |
| 406 | 425 |
| 407 _dsname="${1-}" | 426 _dsname="${1}" |
| 408 [ -z "${_dsname}" ] && \ | 427 [ -z "${_dsname}" ] && { echo "ERROR: no dataset given" >&2; return 2; } |
| 409 { echo "ERROR: no dataset given" >&2; return 2; } | |
| 410 | 428 |
| 411 # Just determine whether the given dataset name exists | 429 # Just determine whether the given dataset name exists |
| 412 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || { echo "ERROR: dataset not found" >&2; return 1; } | 430 _rootds_mountpoint="$(zfs list -H -o mountpoint -t filesystem "${_dsname}")" || \ |
| 431 { echo "ERROR: dataset not found" >&2; return 1; } | |
| 413 | 432 |
| 414 mount -t zfs -p \ | 433 mount -t zfs -p \ |
| 415 | grep -E "^${_dsname}(/|\s)" \ | 434 | grep -E "^${_dsname}(/|\s)" \ |
| 416 | sort -n -r \ | 435 | sort -n -r \ |
| 417 | { | 436 | { |
| 419 echo "Umounting ${_name} on ${_mp}" | 438 echo "Umounting ${_name} on ${_mp}" |
| 420 umount "${_mp}" || return 1 | 439 umount "${_mp}" || return 1 |
| 421 done | 440 done |
| 422 return 0 | 441 return 0 |
| 423 } | 442 } |
| 443 } | |
| 444 | |
| 445 | |
| 446 # | |
| 447 # "umount-tmpl" -- umount skeleton and base datasets | |
| 448 # | |
| 449 # command_umount_tmpl ds-base ds-skeleton | |
| 450 # | |
| 451 command_umount_tmpl() { | |
| 452 local _ds_base _ds_skel | |
| 453 | |
| 454 _ds_base="${1-}" | |
| 455 _ds_skel="${2-}" | |
| 456 | |
| 457 [ -z "${_ds_base}" ] && { echo "ERROR: no RO base dataset given" >&2; return 2; } | |
| 458 [ -z "${_ds_skel}" ] && { echo "ERROR: no RW skeleton dataset given" >&2; return 2; } | |
| 459 | |
| 460 _do_umount "${_ds_skel}" || return | |
| 461 _do_umount "${_ds_base}" || return | |
| 462 | |
| 463 return 0 | |
| 424 } | 464 } |
| 425 | 465 |
| 426 | 466 |
| 427 # | 467 # |
| 428 # Global option handling | 468 # Global option handling |
| 461 | 501 |
| 462 case "${command}" in | 502 case "${command}" in |
| 463 datasets-tmpl) | 503 datasets-tmpl) |
| 464 command_datasets_tmpl "$@" | 504 command_datasets_tmpl "$@" |
| 465 ;; | 505 ;; |
| 506 mount-tmpl) | |
| 507 command_mount_tmpl "$@" | |
| 508 ;; | |
| 509 umount-tmpl|unmount-tmpl) | |
| 510 command_umount_tmpl "$@" | |
| 511 ;; | |
| 466 populate) | 512 populate) |
| 467 command_populate "$@" | 513 command_populate "$@" |
| 468 ;; | 514 ;; |
| 469 *) | 515 *) |
| 470 echo "ERROR: unknown command \`${command}'" >&2 | 516 echo "ERROR: unknown command \`${command}'" >&2 |
