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