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