Mercurial > hgrepos > FreeBSD > ports > sysutils > local-bsdtools
comparison sbin/fzfs @ 380:6be930eb7490
Implement the "fzfs create-tree" command
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 20 Feb 2023 00:43:30 +0100 |
| parents | 1fc3b04b39fa |
| children | 84d2735fe7f6 |
comparison
equal
deleted
inserted
replaced
| 379:b4173e88c57c | 380:6be930eb7490 |
|---|---|
| 26 | 26 |
| 27 -h Print this help message to stdout and exit | 27 -h Print this help message to stdout and exit |
| 28 | 28 |
| 29 COMMANDS: | 29 COMMANDS: |
| 30 | 30 |
| 31 create-tree [-A] [-M MOUNTPOINT] [-n] [-p] [-u] SOURCE-DATASET DEST-DATASET | |
| 32 | |
| 31 mount [-O] [-N] [-P] [-u] [-n] DATASET [MOUNTPOINT] | 33 mount [-O] [-N] [-P] [-u] [-n] DATASET [MOUNTPOINT] |
| 32 | 34 |
| 33 umount DATASET | 35 umount DATASET |
| 34 | 36 |
| 35 unmount | 37 unmount |
| 36 | 38 |
| 37 ' | 39 ' |
| 40 | |
| 41 | |
| 42 #: | |
| 43 #: Determine some important dataset properties that are set locally | |
| 44 #: | |
| 45 #: Args: | |
| 46 #: $1: the dataset | |
| 47 #: $2 ...: the properties to check for | |
| 48 #: | |
| 49 #: Output (stdout): | |
| 50 #: An option string suited for use in "zfs create" | |
| 51 #: | |
| 52 _get_local_properties() { | |
| 53 local ds | |
| 54 | |
| 55 local _res _prop _value _source | |
| 56 | |
| 57 ds="${1}" | |
| 58 shift | |
| 59 | |
| 60 _res="" | |
| 61 | |
| 62 for _prop in "$@" ; do | |
| 63 IFS=$'\t' read -r _value _source <<EOF73GHASGJKKJ354 | |
| 64 $(zfs get -H -p -o value,source "${_prop}" "${ds}") | |
| 65 EOF73GHASGJKKJ354 | |
| 66 case "${_source}" in | |
| 67 local) | |
| 68 if [ -z "${_res}" ]; then | |
| 69 _res="-o ${_prop}=${_value}" | |
| 70 else | |
| 71 _res="${_res} -o ${_prop}=${_value}" | |
| 72 fi | |
| 73 ;; | |
| 74 *) | |
| 75 # VOID | |
| 76 ;; | |
| 77 esac | |
| 78 done | |
| 79 echo "${_res}" | |
| 80 } | |
| 81 | |
| 38 | 82 |
| 39 # | 83 # |
| 40 #: Implementation of the "mount" command. | 84 #: Implementation of the "mount" command. |
| 41 #: | 85 #: |
| 42 #: Mount a dataset and recursively all its children datasets. | 86 #: Mount a dataset and recursively all its children datasets. |
| 201 umount "${_mp}" || return 1 | 245 umount "${_mp}" || return 1 |
| 202 done | 246 done |
| 203 } | 247 } |
| 204 return 0 | 248 return 0 |
| 205 } | 249 } |
| 250 | |
| 251 | |
| 252 #: | |
| 253 #: Implement the "create-tree" command | |
| 254 #: | |
| 255 #: Create a ZFS dataset tree from a source tree tree including important properties | |
| 256 #: | |
| 257 command_create_tree() { | |
| 258 local _source_ds _target_ds | |
| 259 local _opt_dry_run _opt_mountpoint _opt_noauto _opt_nomount _opt_canmount_parent_only | |
| 260 | |
| 261 local _opt _source_name _snapshot_name _current_name _current_type _relative_name _zfs_opts _zfs_canmount _zfs_mountpoint | |
| 262 | |
| 263 _opt_noauto="" | |
| 264 _opt_dry_run="" | |
| 265 _opt_mountpoint="" | |
| 266 _opt_nomount="" | |
| 267 _opt_canmount_parent_only="" | |
| 268 | |
| 269 while getopts "AM:npu" _opt ; do | |
| 270 case ${_opt} in | |
| 271 A) | |
| 272 _opt_noauto="-o canmount=noauto" | |
| 273 ;; | |
| 274 M) | |
| 275 _opt_mountpoint="${OPTARG}" | |
| 276 ;; | |
| 277 n) | |
| 278 _opt_dry_run="yes" | |
| 279 ;; | |
| 280 p) | |
| 281 _opt_canmount_parent_only="yes" | |
| 282 ;; | |
| 283 u) | |
| 284 _opt_nomount="-u" | |
| 285 ;; | |
| 286 \?|:) | |
| 287 return 2; | |
| 288 ;; | |
| 289 esac | |
| 290 done | |
| 291 shift $((OPTIND-1)) | |
| 292 OPTIND=1 | |
| 293 | |
| 294 _source_ds="${1-}" | |
| 295 _target_ds="${2-}" | |
| 296 | |
| 297 [ -z "${_source_ds}" ] && { echo "ERROR: no source dataset given" 1>&2; return 2; } | |
| 298 [ -z "${_target_ds}" ] && { echo "ERROR: no destination dataset given" 1>&2; return 2; } | |
| 299 | |
| 300 _source_name="${_source_ds%@*}" | |
| 301 if [ "${_source_name}" != "${_source_ds}" ]; then | |
| 302 _snapshot_name="${_source_ds##*@}" | |
| 303 else | |
| 304 _snapshot_name="" | |
| 305 fi | |
| 306 | |
| 307 [ -n "${_snapshot_name}" ] && { echo "ERROR: No snapshot sources are supported yet" 1>&2; return 2; } | |
| 308 | |
| 309 zfs list -H -r -t filesystem -o name,type "${_source_ds}" \ | |
| 310 | { | |
| 311 while IFS=$'\t' read -r _current_name _current_type ; do | |
| 312 # Determine the relative name of the dataset | |
| 313 _relative_name="${_current_name#${_source_name}}" | |
| 314 _relative_name="${_relative_name%@*}" | |
| 315 if [ "${_current_type}" != "filesystem" ]; then | |
| 316 echo "ERROR: Got a snapshot but expected a filesystem" 1>&2 | |
| 317 return 1 | |
| 318 fi | |
| 319 _zfs_opts="$(_get_local_properties "${_current_name}" atime exec setuid compression primarycache sync readonly)" | |
| 320 if [ -z "${_relative_name}" ]; then | |
| 321 # | |
| 322 # Root | |
| 323 # | |
| 324 if [ -z "${_opt_noauto}" ]; then | |
| 325 _zfs_canmount="$(_get_local_properties "${_current_name}" canmount)" | |
| 326 else | |
| 327 _zfs_canmount="${_opt_noauto}" | |
| 328 fi | |
| 329 if [ -n "${_opt_mountpoint}" ]; then | |
| 330 _zfs_mountpoint="${_opt_mountpoint}" | |
| 331 else | |
| 332 _zfs_mountpoint="" | |
| 333 fi | |
| 334 | |
| 335 if [ "${_opt_dry_run}" = "yes" ]; then | |
| 336 if [ -z "${_zfs_mountpoint}" ]; then | |
| 337 echo "Would call: zfs create ${_opt_nomount} ${_zfs_opts} ${_zfs_canmount} ${_target_ds}${_relative_name}" | |
| 338 else | |
| 339 echo "Would call: zfs create ${_opt_nomount} ${_zfs_opts} ${_zfs_canmount} -o mountpoint=${_zfs_mountpoint} ${_target_ds}${_relative_name}" | |
| 340 fi | |
| 341 else | |
| 342 if [ -z "${_zfs_mountpoint}" ]; then | |
| 343 zfs create -v ${_opt_nomount} ${_zfs_opts} ${_zfs_canmount} "${_target_ds}${_relative_name}" | |
| 344 else | |
| 345 zfs create -v ${_opt_nomount} ${_zfs_opts} ${_zfs_canmount} -o "mountpoint=${_zfs_mountpoint}" "${_target_ds}${_relative_name}" | |
| 346 fi | |
| 347 fi | |
| 348 else | |
| 349 # | |
| 350 # Children | |
| 351 # | |
| 352 if [ -z "${_opt_noauto}" ]; then | |
| 353 if [ "${_opt_canmount_parent_only}" = "yes" ]; then | |
| 354 _zfs_canmount="" | |
| 355 else | |
| 356 _zfs_canmount="$(_get_local_properties "${_current_name}" canmount)" | |
| 357 fi | |
| 358 else | |
| 359 _zfs_canmount="${_opt_noauto}" | |
| 360 fi | |
| 361 if [ "${_opt_dry_run}" = "yes" ]; then | |
| 362 echo "Would call: zfs create ${_opt_nomount} ${_zfs_opts} ${_zfs_canmount} ${_target_ds}${_relative_name}" | |
| 363 else | |
| 364 zfs create -v ${_opt_nomount} ${_zfs_opts} ${_zfs_canmount} "${_target_ds}${_relative_name}" | |
| 365 fi | |
| 366 fi | |
| 367 done | |
| 368 } | |
| 369 return 0 | |
| 370 } | |
| 371 | |
| 206 | 372 |
| 207 # | 373 # |
| 208 # Global option handling | 374 # Global option handling |
| 209 # | 375 # |
| 210 while getopts "Vh" _opt ; do | 376 while getopts "Vh" _opt ; do |
| 243 command_mount "$@" | 409 command_mount "$@" |
| 244 ;; | 410 ;; |
| 245 umount|unmount) | 411 umount|unmount) |
| 246 command_umount "$@" | 412 command_umount "$@" |
| 247 ;; | 413 ;; |
| 414 create-tree) | |
| 415 command_create_tree "$@" | |
| 416 ;; | |
| 248 *) | 417 *) |
| 249 echo "ERROR: unknown command \`${command}'" 1>&2 | 418 echo "ERROR: unknown command \`${command}'" 1>&2 |
| 250 exit 2 | 419 exit 2 |
| 251 ;; | 420 ;; |
| 252 esac | 421 esac |
