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