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