1.\" 2.\" SPDX-License-Identifier: BSD-2-Clause 3.\" 4.\" Copyright (c) 2017 Kyle Kneitinger 5.\" Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org> 6.\" 7.\" Redistribution and use in source and binary forms, with or without 8.\" modification, are permitted provided that the following conditions 9.\" are met: 10.\" 1. Redistributions of source code must retain the above copyright 11.\" notice, this list of conditions and the following disclaimer. 12.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" notice, this list of conditions and the following disclaimer in the 14.\" documentation and/or other materials provided with the distribution. 15.\" 16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26.\" SUCH DAMAGE. 27.\" 28.Dd August 18, 2020 29.Dt LIBBE 3 30.Os 31.Sh NAME 32.Nm libbe 33.Nd library for creating, destroying and modifying ZFS boot environments 34.Sh LIBRARY 35.Lb libbe 36.Sh SYNOPSIS 37.In be.h 38.Ft "libbe_handle_t *hdl" Ns 39.Fn libbe_init "const char *be_root" 40.Pp 41.Ft void 42.Fn libbe_close "libbe_handle_t *hdl" 43.Pp 44.Ft const char * Ns 45.Fn be_active_name "libbe_handle_t *hdl" 46.Pp 47.Ft const char * Ns 48.Fn be_active_path "libbe_handle_t *hdl" 49.Pp 50.Ft const char * Ns 51.Fn be_nextboot_name "libbe_handle_t *hdl" 52.Pp 53.Ft const char * Ns 54.Fn be_nextboot_path "libbe_handle_t *hdl" 55.Pp 56.Ft const char * Ns 57.Fn be_root_path "libbe_handle_t *hdl" 58.Pp 59.Ft int Ns 60.Fn be_snapshot "libbe_handle_t *hdl" "const char *be_name" "const char *snap_name" "bool recursive" "char *result" 61.Pp 62.Ft bool Ns 63.Fn be_is_auto_snapshot_name "libbe_handle_t *hdl" "const char *snap" 64.Pp 65.Ft int 66.Fn be_create "libbe_handle_t *hdl" "const char *be_name" 67.Pp 68.Ft int 69.Fn be_create_depth "libbe_handle_t *hdl" "const char *be_name" "const char *snap" "int depth" 70.Pp 71.Ft int 72.Fn be_create_from_existing "libbe_handle_t *hdl" "const char *be_name" "const char *be_origin" 73.Pp 74.Ft int 75.Fn be_create_from_existing_snap "libbe_handle_t *hdl" "const char *be_name" "const char *snap" 76.Pp 77.Ft int 78.Fn be_rename "libbe_handle_t *hdl" "const char *be_old" "const char *be_new" 79.Pp 80.Ft int 81.Fn be_activate "libbe_handle_t *hdl" "const char *be_name" "bool temporary" 82.Pp 83.Ft int 84.Fn be_deactivate "libbe_handle_t *hdl" "const char *be_name" "bool temporary" 85.Pp 86.Ft int 87.Fn be_destroy "libbe_handle_t *hdl" "const char *be_name" "int options" 88.Pp 89.Ft void 90.Fn be_nicenum "uint64_t num" "char *buf" "size_t bufsz" 91.Pp 92.\" TODO: Write up of mount options 93.\" typedef enum { 94.\" BE_MNT_FORCE = 1 << 0, 95.\" BE_MNT_DEEP = 1 << 1, 96.\" } be_mount_opt_t 97.Ft int 98.Fn be_mount "libbe_handle_t *hdl" "const char *be_name" "const char *mntpoint" "int flags" "char *result" 99.Pp 100.Ft int 101.Fn be_mounted_at "libbe_handle_t *hdl" "const char *path" "nvlist_t *details" 102.Pp 103.Ft int 104.Fn be_unmount "libbe_handle_t *hdl" "const char *be_name" "int flags" 105.Pp 106.Ft int 107.Fn libbe_errno "libbe_handle_t *hdl" 108.Pp 109.Ft const char * Ns 110.Fn libbe_error_description "libbe_handle_t *hdl" 111.Pp 112.Ft void 113.Fn libbe_print_on_error "libbe_handle_t *hdl" "bool doprint" 114.Pp 115.Ft int 116.Fn be_root_concat "libbe_handle_t *hdl" "const char *be_name" "char *result" 117.Pp 118.Ft int 119.Fn be_validate_name "libbe_handle_t *hdl" "const char *be_name" 120.Pp 121.Ft int 122.Fn be_validate_snap "libbe_handle_t *hdl" "const char *snap" 123.Pp 124.Ft int 125.Fn be_exists "libbe_handle_t *hdl" "const char *be_name" 126.Pp 127.Ft int 128.Fn be_export "libbe_handle_t *hdl" "const char *be_name" "int fd" 129.Pp 130.Ft int 131.Fn be_import "libbe_handle_t *hdl" "const char *be_name" "int fd" 132.Pp 133.Ft int 134.Fn be_prop_list_alloc "nvlist_t **prop_list" 135.Pp 136.Ft int 137.Fn be_get_bootenv_props "libbe_handle_t *hdl" "nvlist_t *be_list" 138.Pp 139.Ft int 140.Fn be_get_dataset_props "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *props" 141.Pp 142.Ft int 143.Fn be_get_dataset_snapshots "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *snap_list" 144.Pp 145.Ft void 146.Fn be_prop_list_free "nvlist_t *prop_list" 147.Sh DESCRIPTION 148.Nm 149interfaces with libzfs to provide a set of functions for various operations 150regarding ZFS boot environments, including "deep" boot environments in which 151a boot environment has child datasets. 152.Pp 153A context structure is passed to each function, allowing for a small amount 154of state to be retained, such as errors from previous operations. 155.Nm 156may be configured to print the corresponding error message to 157.Dv stderr 158when an error is encountered with 159.Fn libbe_print_on_error . 160.Pp 161All functions returning an 162.Vt int 163return 0 on success, or a 164.Nm 165errno otherwise as described in 166.Sx DIAGNOSTICS . 167.Pp 168The 169.Fn libbe_init 170function takes an optional BE root and initializes 171.Nm , 172returning a 173.Vt "libbe_handle_t *" 174on success, or 175.Dv NULL 176on error. 177If a BE root is supplied, 178.Nm 179will only operate out of that pool and BE root. 180An error may occur if: 181.Bl -column 182.It /boot and / are not on the same filesystem and device, 183.It libzfs fails to initialize, 184.It The system has not been properly booted with a ZFS boot 185environment, 186.It Nm 187fails to open the zpool the active boot environment resides on, or 188.It Nm 189fails to locate the boot environment that is currently mounted. 190.El 191.Pp 192The 193.Fn libbe_close 194function frees all resources previously acquired in 195.Fn libbe_init , 196invalidating the handle in the process. 197.Pp 198The 199.Fn be_active_name 200function returns the name of the currently booted boot environment. 201This boot environment may not belong to the same BE root as the root libbe 202is operating on! 203.Pp 204The 205.Fn be_active_path 206function returns the full path of the currently booted boot environment. 207This boot environment may not belong to the same BE root as the root libbe 208is operating on! 209.Pp 210The 211.Fn be_nextboot_name 212function returns the name of the boot environment that will be active on reboot. 213.Pp 214The 215.Fn be_nextboot_path 216function returns the full path of the boot environment that will be 217active on reboot. 218.Pp 219The 220.Fn be_root_path 221function returns the boot environment root path. 222.Pp 223The 224.Fn be_snapshot 225function creates a snapshot of 226.Fa be_name 227named 228.Fa snap_name . 229A 230.Dv NULL 231.Fa snap_name 232may be used, indicating that 233.Fn be_snaphot 234should derive the snapshot name from the current date and time. 235If 236.Fa recursive 237is set, then 238.Fn be_snapshot 239will recursively snapshot the dataset. 240If 241.Fa result 242is not 243.Dv NULL , 244then it will be populated with the final 245.Dq Fa be_name Ns @ Ns Fa snap_name . 246.Pp 247The 248.Fn be_is_auto_snapshot_name 249function is used to determine if the given snapshot name matches the format that 250the 251.Fn be_snapshot 252function will use by default if it is not given a snapshot name to use. 253It returns 254.Dv true 255if the name matches the format, and 256.Dv false 257if it does not. 258.Pp 259The 260.Fn be_create 261function creates a boot environment with the given name. 262The new boot environment will be created from a recursive snapshot of the 263currently booted boot environment. 264.Pp 265The 266.Fn be_create_depth 267function creates a boot environment with the given name from an existing 268snapshot. 269The depth parameter specifies the depth of recursion that will be cloned from 270the existing snapshot. 271A depth of '0' is no recursion and '-1' is unlimited (i.e., a recursive boot 272environment). 273.Pp 274The 275.Fn be_create_from_existing 276function creates a boot environment with the given name from the name of an 277existing boot environment. 278A recursive snapshot will be made of the origin boot environment, and the new 279boot environment will be created from that. 280.Pp 281The 282.Fn be_create_from_existing_snap 283function creates a recursive boot environment with the given name from an 284existing snapshot. 285.Pp 286The 287.Fn be_rename 288function renames a boot environment without unmounting it, as if renamed with 289the 290.Fl u 291argument were passed to 292.Nm zfs 293.Cm rename 294.Pp 295The 296.Fn be_activate 297function makes a boot environment active on the next boot. 298If the 299.Fa temporary 300flag is set, then it will be active for the next boot only, as done by 301.Xr zfsbootcfg 8 . 302.Pp 303The 304.Fn be_deactivate 305function deactivates a boot environment. 306If the 307.Fa temporary 308flag is set, then it will cause removal of boot once configuration, set by 309.Fn be_activate 310function or by 311.Xr zfsbootcfg 8 . 312If the 313.Fa temporary 314flag is not set, 315.Fn be_deactivate 316function will set zfs 317.Dv canmount 318property to 319.Dv noauto . 320.Pp 321The 322.Fn be_destroy 323function will recursively destroy the given boot environment. 324It will not destroy a mounted boot environment unless the 325.Dv BE_DESTROY_FORCE 326option is set in 327.Fa options . 328If the 329.Dv BE_DESTROY_ORIGIN 330option is set in 331.Fa options , 332the 333.Fn be_destroy 334function will destroy the origin snapshot to this boot environment as well. 335.Pp 336The 337.Fn be_nicenum 338function will format 339.Fa name 340in a traditional ZFS humanized format, similar to 341.Xr humanize_number 3 . 342This function effectively proxies 343.Fn zfs_nicenum 344from libzfs. 345.Pp 346The 347.Fn be_mount 348function will mount the given boot environment. 349If 350.Fa mountpoint 351is 352.Dv NULL , 353a mount point will be generated in 354.Pa /tmp 355using 356.Xr mkdtemp 3 . 357If 358.Fa result 359is not 360.Dv NULL , 361it should be large enough to accommodate 362.Dv BE_MAXPATHLEN 363including the null terminator. 364the final mount point will be copied into it. 365Setting the 366.Dv BE_MNT_FORCE 367flag will pass 368.Dv MNT_FORCE 369to the underlying 370.Xr mount 2 371call. 372.Pp 373The 374.Fn be_mounted_at 375function will check if there is a boot environment mounted at the given 376.Fa path . 377If 378.Fa details 379is not 380.Dv NULL , 381it will be populated with a list of the mounted dataset's properties. 382This list of properties matches the properties collected by 383.Fn be_get_bootenv_props . 384.Pp 385The 386.Fn be_unmount 387function will unmount the given boot environment. 388Setting the 389.Dv BE_MNT_FORCE 390flag will pass 391.Dv MNT_FORCE 392to the underlying 393.Xr mount 2 394call. 395.Pp 396The 397.Fn libbe_errno 398function returns the 399.Nm 400errno. 401.Pp 402The 403.Fn libbe_error_description 404function returns a string description of the currently set 405.Nm 406errno. 407.Pp 408The 409.Fn libbe_print_on_error 410function will change whether or not 411.Nm 412prints the description of any encountered error to 413.Dv stderr , 414based on 415.Fa doprint . 416.Pp 417The 418.Fn be_root_concat 419function will concatenate the boot environment root and the given boot 420environment name into 421.Fa result . 422.Pp 423The 424.Fn be_validate_name 425function will validate the given boot environment name for both length 426restrictions as well as valid character restrictions. 427This function does not set the internal library error state. 428.Pp 429The 430.Fn be_validate_snap 431function will validate the given snapshot name. 432The snapshot must have a valid name, exist, and have a mountpoint of 433.Pa / . 434This function does not set the internal library error state. 435.Pp 436The 437.Fn be_exists 438function will check whether the given boot environment exists and has a 439mountpoint of 440.Pa / . 441This function does not set the internal library error state, but will return 442the appropriate error. 443.Pp 444The 445.Fn be_export 446function will export the given boot environment to the file specified by 447.Fa fd . 448A snapshot will be created of the boot environment prior to export. 449.Pp 450The 451.Fn be_import 452function will import the boot environment in the file specified by 453.Fa fd , 454and give it the name 455.Fa be_name . 456.Pp 457The 458.Fn be_prop_list_alloc 459function allocates a property list suitable for passing to 460.Fn be_get_bootenv_props , 461.Fn be_get_dataset_props , 462or 463.Fn be_get_dataset_snapshots . 464It should be freed later by 465.Fa be_prop_list_free . 466.Pp 467The 468.Fn be_get_bootenv_props 469function will populate 470.Fa be_list 471with 472.Vt nvpair_t 473of boot environment names paired with an 474.Vt nvlist_t 475of their properties. 476The following properties are currently collected as appropriate: 477.Bl -column "Returned name" 478.It Sy Returned name Ta Sy Description 479.It dataset Ta - 480.It name Ta Boot environment name 481.It mounted Ta Current mount point 482.It mountpoint Ta Do mountpoint Dc property 483.It origin Ta Do origin Dc property 484.It creation Ta Do creation Dc property 485.It active Ta Currently booted environment 486.It used Ta Literal Do used Dc property 487.It usedds Ta Literal Do usedds Dc property 488.It usedsnap Ta Literal Do usedrefreserv Dc property 489.It referenced Ta Literal Do referenced Dc property 490.It nextboot Ta Active on next boot 491.El 492.Pp 493Only the 494.Dq dataset , 495.Dq name , 496.Dq active , 497and 498.Dq nextboot 499returned values will always be present. 500All other properties may be omitted if not available. 501.Pp 502The 503.Fn be_get_dataset_props 504function will get properties of the specified dataset. 505.Fa props 506is populated directly with a list of the properties as returned by 507.Fn be_get_bootenv_props . 508.Pp 509The 510.Fn be_get_dataset_snapshots 511function will retrieve all snapshots of the given dataset. 512.Fa snap_list 513will be populated with a list of 514.Vt nvpair_t 515exactly as specified by 516.Fn be_get_bootenv_props . 517.Pp 518The 519.Fn be_prop_list_free 520function will free the property list. 521.Sh DIAGNOSTICS 522Upon error, one of the following values will be returned: 523.Bl -dash -offset indent -compact 524.It 525BE_ERR_SUCCESS 526.It 527BE_ERR_INVALIDNAME 528.It 529BE_ERR_EXISTS 530.It 531BE_ERR_NOENT 532.It 533BE_ERR_PERMS 534.It 535BE_ERR_DESTROYACT 536.It 537BE_ERR_DESTROYMNT 538.It 539BE_ERR_BADPATH 540.It 541BE_ERR_PATHBUSY 542.It 543BE_ERR_PATHLEN 544.It 545BE_ERR_BADMOUNT 546.It 547BE_ERR_NOORIGIN 548.It 549BE_ERR_MOUNTED 550.It 551BE_ERR_NOMOUNT 552.It 553BE_ERR_ZFSOPEN 554.It 555BE_ERR_ZFSCLONE 556.It 557BE_ERR_IO 558.It 559BE_ERR_NOPOOL 560.It 561BE_ERR_NOMEM 562.It 563BE_ERR_UNKNOWN 564.It 565BE_ERR_INVORIGIN 566.El 567.Sh SEE ALSO 568.Xr bectl 8 569.Sh HISTORY 570.Nm 571and its corresponding command, 572.Xr bectl 8 , 573were written as a 2017 Google Summer of Code project with Allan Jude serving 574as a mentor. 575Later work was done by 576.An Kyle Evans Aq Mt kevans@FreeBSD.org . 577