From e4d8c9fb33af0a59fa41cde0be4ee33239321d0a Mon Sep 17 00:00:00 2001 From: kevans Date: Sun, 6 Jan 2019 02:15:09 +0000 Subject: [PATCH] Revert r342807, mistakenly including libbe(3)/bectl(8) MFC --- Makefile.inc1 | 10 +- ObsoleteFiles.inc | 2 - contrib/mdocml/lib.in | 1 - lib/Makefile | 1 - lib/libbe/Makefile | 31 - lib/libbe/be.c | 1010 ---------------------- lib/libbe/be.h | 131 --- lib/libbe/be_access.c | 215 ----- lib/libbe/be_error.c | 133 --- lib/libbe/be_impl.h | 72 -- lib/libbe/be_info.c | 318 ------- lib/libbe/libbe.3 | 469 ---------- sbin/Makefile | 1 - sbin/bectl/Makefile | 19 - sbin/bectl/bectl.8 | 287 ------ sbin/bectl/bectl.c | 525 ----------- sbin/bectl/bectl.h | 37 - sbin/bectl/bectl_jail.c | 416 --------- sbin/bectl/bectl_list.c | 419 --------- share/mk/bsd.libnames.mk | 1 - share/mk/src.libnames.mk | 4 - sys/amd64/conf/GENERIC | 41 - sys/amd64/conf/MINIMAL | 3 - tools/build/mk/OptionalObsoleteFiles.inc | 2 +- usr.sbin/config/config.y | 37 +- 25 files changed, 18 insertions(+), 4167 deletions(-) delete mode 100644 lib/libbe/Makefile delete mode 100644 lib/libbe/be.c delete mode 100644 lib/libbe/be.h delete mode 100644 lib/libbe/be_access.c delete mode 100644 lib/libbe/be_error.c delete mode 100644 lib/libbe/be_impl.h delete mode 100644 lib/libbe/be_info.c delete mode 100644 lib/libbe/libbe.3 delete mode 100644 sbin/bectl/Makefile delete mode 100644 sbin/bectl/bectl.8 delete mode 100644 sbin/bectl/bectl.c delete mode 100644 sbin/bectl/bectl.h delete mode 100644 sbin/bectl/bectl_jail.c delete mode 100644 sbin/bectl/bectl_list.c diff --git a/Makefile.inc1 b/Makefile.inc1 index 2205ece00f2..0d0e0b639d7 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -2144,7 +2144,7 @@ _prebuild_libs= ${_kerberos5_lib_libasn1} \ ${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \ ${_cddl_lib_libuutil} \ ${_cddl_lib_libavl} \ - ${_cddl_lib_libzfs_core} ${_cddl_lib_libzfs} \ + ${_cddl_lib_libzfs_core} \ ${_cddl_lib_libctf} \ lib/libutil lib/libpjdlog ${_lib_libypclnt} lib/libz lib/msun \ ${_secure_lib_libcrypto} ${_lib_libldns} \ @@ -2213,15 +2213,7 @@ _cddl_lib_libavl= cddl/lib/libavl _cddl_lib_libuutil= cddl/lib/libuutil .if ${MK_ZFS} != "no" _cddl_lib_libzfs_core= cddl/lib/libzfs_core -_cddl_lib_libzfs= cddl/lib/libzfs - cddl/lib/libzfs_core__L: cddl/lib/libnvpair__L - -cddl/lib/libzfs__L: cddl/lib/libzfs_core__L lib/msun__L lib/libutil__L -cddl/lib/libzfs__L: lib/libthr__L lib/libmd__L lib/libz__L cddl/lib/libumem__L -cddl/lib/libzfs__L: cddl/lib/libuutil__L cddl/lib/libavl__L lib/libgeom__L - -lib/libbe__L: cddl/lib/libzfs__L .endif _cddl_lib_libctf= cddl/lib/libctf _cddl_lib= cddl/lib diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index bcc99de7541..536f447f510 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,8 +38,6 @@ # xargs -n1 | sort | uniq -d; # done -# 20181115: libbe(3) SHLIBDIR fixed to reflect correct location -OLD_LIBS+=usr/lib/libbe.so.1 # 20180812: move of libmlx5.so.1 and libibverbs.so.1 OLD_LIBS+=usr/lib/libmlx5.so.1 OLD_LIBS+=usr/lib/libibverbs.so.1 diff --git a/contrib/mdocml/lib.in b/contrib/mdocml/lib.in index 646c9a2407f..76691ecf01c 100644 --- a/contrib/mdocml/lib.in +++ b/contrib/mdocml/lib.in @@ -28,7 +28,6 @@ LINE("lib80211", "802.11 Wireless Network Management Library (lib80211, \\-l8021 LINE("libarchive", "Streaming Archive Library (libarchive, \\-larchive)") LINE("libarm", "ARM Architecture Library (libarm, \\-larm)") LINE("libarm32", "ARM32 Architecture Library (libarm32, \\-larm32)") -LINE("libbe", "Boot Environment Library (libbe, \\-lbe)") LINE("libbluetooth", "Bluetooth Library (libbluetooth, \\-lbluetooth)") LINE("libbsm", "Basic Security Module Library (libbsm, \\-lbsm)") LINE("libc", "Standard C\\~Library (libc, \\-lc)") diff --git a/lib/Makefile b/lib/Makefile index 5d22d0ac009..a2287b1f10a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -289,7 +289,6 @@ _libproc= libproc _librtld_db= librtld_db .endif SUBDIR.${MK_OFED}+= ofed -SUBDIR.${MK_ZFS}+= libbe .if ${MK_OPENSSL} != "no" _libmp= libmp diff --git a/lib/libbe/Makefile b/lib/libbe/Makefile deleted file mode 100644 index 5fada3204fb..00000000000 --- a/lib/libbe/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# $FreeBSD$ - -PACKAGE= lib${LIB} -LIB= be -SHLIBDIR?= /lib -SHLIB_MAJOR= 1 -SHLIB_MINOR= 0 - -SRCS= be.c be_access.c be_error.c be_info.c -INCS= be.h -MAN= libbe.3 - -WARNS?= 2 -IGNORE_PRAGMA= yes - -LIBADD+= zfs -LIBADD+= nvpair - -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common -CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris -CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include -CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/lib/libumem -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzpool/common -CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/zfs -CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/fs/zfs -CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/head - -CFLAGS+= -DNEED_SOLARIS_BOOLEAN - -.include diff --git a/lib/libbe/be.c b/lib/libbe/be.c deleted file mode 100644 index 540fe44ea1e..00000000000 --- a/lib/libbe/be.c +++ /dev/null @@ -1,1010 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2017 Kyle J. Kneitinger - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "be.h" -#include "be_impl.h" - -#if SOON -static int be_create_child_noent(libbe_handle_t *lbh, const char *active, - const char *child_path); -static int be_create_child_cloned(libbe_handle_t *lbh, const char *active); -#endif - -/* - * Iterator function for locating the rootfs amongst the children of the - * zfs_be_root set by loader(8). data is expected to be a libbe_handle_t *. - */ -static int -be_locate_rootfs(zfs_handle_t *chkds, void *data) -{ - libbe_handle_t *lbh; - char *mntpoint; - - lbh = (libbe_handle_t *)data; - if (lbh == NULL) - return (1); - - mntpoint = NULL; - if (zfs_is_mounted(chkds, &mntpoint) && strcmp(mntpoint, "/") == 0) { - strlcpy(lbh->rootfs, zfs_get_name(chkds), sizeof(lbh->rootfs)); - free(mntpoint); - return (1); - } else if(mntpoint != NULL) - free(mntpoint); - - return (0); -} - -/* - * Initializes the libbe context to operate in the root boot environment - * dataset, for example, zroot/ROOT. - */ -libbe_handle_t * -libbe_init(void) -{ - struct stat sb; - dev_t root_dev, boot_dev; - libbe_handle_t *lbh; - zfs_handle_t *rootds; - char *poolname, *pos; - int pnamelen; - - lbh = NULL; - poolname = pos = NULL; - rootds = NULL; - - /* Verify that /boot and / are mounted on the same filesystem */ - /* TODO: use errno here?? */ - if (stat("/", &sb) != 0) - goto err; - - root_dev = sb.st_dev; - - if (stat("/boot", &sb) != 0) - goto err; - - boot_dev = sb.st_dev; - - if (root_dev != boot_dev) { - fprintf(stderr, "/ and /boot not on same device, quitting\n"); - goto err; - } - - if ((lbh = calloc(1, sizeof(libbe_handle_t))) == NULL) - goto err; - - if ((lbh->lzh = libzfs_init()) == NULL) - goto err; - - /* Obtain path to boot environment root */ - if ((kenv(KENV_GET, "zfs_be_root", lbh->root, - sizeof(lbh->root))) == -1) - goto err; - - /* Remove leading 'zfs:' if present, otherwise use value as-is */ - if (strcmp(lbh->root, "zfs:") == 0) - strlcpy(lbh->root, strchr(lbh->root, ':') + sizeof(char), - sizeof(lbh->root)); - - if ((pos = strchr(lbh->root, '/')) == NULL) - goto err; - - pnamelen = pos - lbh->root; - poolname = malloc(pnamelen + 1); - if (poolname == NULL) - goto err; - - strlcpy(poolname, lbh->root, pnamelen + 1); - if ((lbh->active_phandle = zpool_open(lbh->lzh, poolname)) == NULL) - goto err; - free(poolname); - poolname = NULL; - - if (zpool_get_prop(lbh->active_phandle, ZPOOL_PROP_BOOTFS, lbh->bootfs, - sizeof(lbh->bootfs), NULL, true) != 0) - goto err; - - /* Obtain path to boot environment rootfs (currently booted) */ - /* XXX Get dataset mounted at / by kenv/GUID from mountroot? */ - if ((rootds = zfs_open(lbh->lzh, lbh->root, ZFS_TYPE_DATASET)) == NULL) - goto err; - - zfs_iter_filesystems(rootds, be_locate_rootfs, lbh); - zfs_close(rootds); - rootds = NULL; - if (*lbh->rootfs == '\0') - goto err; - - return (lbh); -err: - if (lbh != NULL) { - if (lbh->active_phandle != NULL) - zpool_close(lbh->active_phandle); - if (lbh->lzh != NULL) - libzfs_fini(lbh->lzh); - free(lbh); - } - free(poolname); - return (NULL); -} - - -/* - * Free memory allocated by libbe_init() - */ -void -libbe_close(libbe_handle_t *lbh) -{ - - if (lbh->active_phandle != NULL) - zpool_close(lbh->active_phandle); - libzfs_fini(lbh->lzh); - free(lbh); -} - -/* - * Proxy through to libzfs for the moment. - */ -void -be_nicenum(uint64_t num, char *buf, size_t buflen) -{ - - zfs_nicenum(num, buf, buflen); -} - -static int -be_destroy_cb(zfs_handle_t *zfs_hdl, void *data) -{ - int err; - - if ((err = zfs_iter_children(zfs_hdl, be_destroy_cb, data)) != 0) - return (err); - if ((err = zfs_destroy(zfs_hdl, false)) != 0) - return (err); - return (0); -} - -/* - * Destroy the boot environment or snapshot specified by the name - * parameter. Options are or'd together with the possible values: - * BE_DESTROY_FORCE : forces operation on mounted datasets - */ -int -be_destroy(libbe_handle_t *lbh, const char *name, int options) -{ - zfs_handle_t *fs; - char path[BE_MAXPATHLEN]; - char *p; - int err, force, mounted; - - p = path; - force = options & BE_DESTROY_FORCE; - - be_root_concat(lbh, name, path); - - if (strchr(name, '@') == NULL) { - if (!zfs_dataset_exists(lbh->lzh, path, ZFS_TYPE_FILESYSTEM)) - return (set_error(lbh, BE_ERR_NOENT)); - - if (strcmp(path, lbh->rootfs) == 0) - return (set_error(lbh, BE_ERR_DESTROYACT)); - - fs = zfs_open(lbh->lzh, p, ZFS_TYPE_FILESYSTEM); - } else { - - if (!zfs_dataset_exists(lbh->lzh, path, ZFS_TYPE_SNAPSHOT)) - return (set_error(lbh, BE_ERR_NOENT)); - - fs = zfs_open(lbh->lzh, p, ZFS_TYPE_SNAPSHOT); - } - - if (fs == NULL) - return (set_error(lbh, BE_ERR_ZFSOPEN)); - - /* Check if mounted, unmount if force is specified */ - if ((mounted = zfs_is_mounted(fs, NULL)) != 0) { - if (force) - zfs_unmount(fs, NULL, 0); - else - return (set_error(lbh, BE_ERR_DESTROYMNT)); - } - - if ((err = be_destroy_cb(fs, NULL)) != 0) { - /* Children are still present or the mount is referenced */ - if (err == EBUSY) - return (set_error(lbh, BE_ERR_DESTROYMNT)); - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - - return (0); -} - - -int -be_snapshot(libbe_handle_t *lbh, const char *source, const char *snap_name, - bool recursive, char *result) -{ - char buf[BE_MAXPATHLEN]; - time_t rawtime; - int len, err; - - be_root_concat(lbh, source, buf); - - if ((err = be_exists(lbh, buf)) != 0) - return (set_error(lbh, err)); - - if (snap_name != NULL) { - if (strlcat(buf, "@", sizeof(buf)) >= sizeof(buf)) - return (set_error(lbh, BE_ERR_INVALIDNAME)); - - if (strlcat(buf, snap_name, sizeof(buf)) >= sizeof(buf)) - return (set_error(lbh, BE_ERR_INVALIDNAME)); - - if (result != NULL) - snprintf(result, BE_MAXPATHLEN, "%s@%s", source, - snap_name); - } else { - time(&rawtime); - len = strlen(buf); - strftime(buf + len, sizeof(buf) - len, - "@%F-%T", localtime(&rawtime)); - if (result != NULL && strlcpy(result, strrchr(buf, '/') + 1, - sizeof(buf)) >= sizeof(buf)) - return (set_error(lbh, BE_ERR_INVALIDNAME)); - } - - if ((err = zfs_snapshot(lbh->lzh, buf, recursive, NULL)) != 0) { - switch (err) { - case EZFS_INVALIDNAME: - return (set_error(lbh, BE_ERR_INVALIDNAME)); - - default: - /* - * The other errors that zfs_ioc_snapshot might return - * shouldn't happen if we've set things up properly, so - * we'll gloss over them and call it UNKNOWN as it will - * require further triage. - */ - if (errno == ENOTSUP) - return (set_error(lbh, BE_ERR_NOPOOL)); - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - } - - return (BE_ERR_SUCCESS); -} - - -/* - * Create the boot environment specified by the name parameter - */ -int -be_create(libbe_handle_t *lbh, const char *name) -{ - int err; - - err = be_create_from_existing(lbh, name, be_active_path(lbh)); - - return (set_error(lbh, err)); -} - - -static int -be_deep_clone_prop(int prop, void *cb) -{ - int err; - struct libbe_dccb *dccb; - zprop_source_t src; - char pval[BE_MAXPATHLEN]; - char source[BE_MAXPATHLEN]; - - dccb = cb; - /* Skip some properties we don't want to touch */ - if (prop == ZFS_PROP_CANMOUNT) - return (ZPROP_CONT); - - /* Don't copy readonly properties */ - if (zfs_prop_readonly(prop)) - return (ZPROP_CONT); - - if ((err = zfs_prop_get(dccb->zhp, prop, (char *)&pval, - sizeof(pval), &src, (char *)&source, sizeof(source), false))) - /* Just continue if we fail to read a property */ - return (ZPROP_CONT); - - /* Only copy locally defined properties */ - if (src != ZPROP_SRC_LOCAL) - return (ZPROP_CONT); - - nvlist_add_string(dccb->props, zfs_prop_to_name(prop), (char *)pval); - - return (ZPROP_CONT); -} - -static int -be_deep_clone(zfs_handle_t *ds, void *data) -{ - int err; - char be_path[BE_MAXPATHLEN]; - char snap_path[BE_MAXPATHLEN]; - const char *dspath; - char *dsname; - zfs_handle_t *snap_hdl; - nvlist_t *props; - struct libbe_deep_clone *isdc, sdc; - struct libbe_dccb dccb; - - isdc = (struct libbe_deep_clone *)data; - dspath = zfs_get_name(ds); - if ((dsname = strrchr(dspath, '/')) == NULL) - return (BE_ERR_UNKNOWN); - dsname++; - - if (isdc->bename == NULL) - snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, dsname); - else - snprintf(be_path, sizeof(be_path), "%s/%s", isdc->be_root, isdc->bename); - - snprintf(snap_path, sizeof(snap_path), "%s@%s", dspath, isdc->snapname); - - if (zfs_dataset_exists(isdc->lbh->lzh, be_path, ZFS_TYPE_DATASET)) - return (set_error(isdc->lbh, BE_ERR_EXISTS)); - - if ((snap_hdl = - zfs_open(isdc->lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL) - return (set_error(isdc->lbh, BE_ERR_ZFSOPEN)); - - nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); - nvlist_add_string(props, "canmount", "noauto"); - - dccb.zhp = ds; - dccb.props = props; - if (zprop_iter(be_deep_clone_prop, &dccb, B_FALSE, B_FALSE, - ZFS_TYPE_FILESYSTEM) == ZPROP_INVAL) - return (-1); - - if ((err = zfs_clone(snap_hdl, be_path, props)) != 0) - err = BE_ERR_ZFSCLONE; - - nvlist_free(props); - zfs_close(snap_hdl); - - /* Failed to clone */ - if (err != BE_ERR_SUCCESS) - return (set_error(isdc->lbh, err)); - - sdc.lbh = isdc->lbh; - sdc.bename = NULL; - sdc.snapname = isdc->snapname; - sdc.be_root = (char *)&be_path; - - err = zfs_iter_filesystems(ds, be_deep_clone, &sdc); - - return (err); -} - -/* - * Create the boot environment from pre-existing snapshot - */ -int -be_create_from_existing_snap(libbe_handle_t *lbh, const char *name, - const char *snap) -{ - int err; - char be_path[BE_MAXPATHLEN]; - char snap_path[BE_MAXPATHLEN]; - const char *bename; - char *parentname, *snapname; - zfs_handle_t *parent_hdl; - struct libbe_deep_clone sdc; - - if ((err = be_validate_name(lbh, name)) != 0) - return (set_error(lbh, err)); - if ((err = be_root_concat(lbh, snap, snap_path)) != 0) - return (set_error(lbh, err)); - if ((err = be_validate_snap(lbh, snap_path)) != 0) - return (set_error(lbh, err)); - - if ((err = be_root_concat(lbh, name, be_path)) != 0) - return (set_error(lbh, err)); - - if ((bename = strrchr(name, '/')) == NULL) - bename = name; - else - bename++; - - if ((parentname = strdup(snap_path)) == NULL) - return (set_error(lbh, BE_ERR_UNKNOWN)); - - snapname = strchr(parentname, '@'); - if (snapname == NULL) { - free(parentname); - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - *snapname = '\0'; - snapname++; - - sdc.lbh = lbh; - sdc.bename = bename; - sdc.snapname = snapname; - sdc.be_root = lbh->root; - - parent_hdl = zfs_open(lbh->lzh, parentname, ZFS_TYPE_DATASET); - err = be_deep_clone(parent_hdl, &sdc); - - free(parentname); - return (set_error(lbh, err)); -} - - -/* - * Create a boot environment from an existing boot environment - */ -int -be_create_from_existing(libbe_handle_t *lbh, const char *name, const char *old) -{ - int err; - char buf[BE_MAXPATHLEN]; - - if ((err = be_snapshot(lbh, old, NULL, true, (char *)&buf)) != 0) - return (set_error(lbh, err)); - - err = be_create_from_existing_snap(lbh, name, (char *)buf); - - return (set_error(lbh, err)); -} - - -/* - * Verifies that a snapshot has a valid name, exists, and has a mountpoint of - * '/'. Returns BE_ERR_SUCCESS (0), upon success, or the relevant BE_ERR_* upon - * failure. Does not set the internal library error state. - */ -int -be_validate_snap(libbe_handle_t *lbh, const char *snap_name) -{ - zfs_handle_t *zfs_hdl; - char buf[BE_MAXPATHLEN]; - char *delim_pos; - int err = BE_ERR_SUCCESS; - - if (strlen(snap_name) >= BE_MAXPATHLEN) - return (BE_ERR_PATHLEN); - - if (!zfs_dataset_exists(lbh->lzh, snap_name, - ZFS_TYPE_SNAPSHOT)) - return (BE_ERR_NOENT); - - strlcpy(buf, snap_name, sizeof(buf)); - - /* Find the base filesystem of the snapshot */ - if ((delim_pos = strchr(buf, '@')) == NULL) - return (BE_ERR_INVALIDNAME); - *delim_pos = '\0'; - - if ((zfs_hdl = - zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL) - return (BE_ERR_NOORIGIN); - - if ((err = zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, - sizeof(buf), NULL, NULL, 0, 1)) != 0) - err = BE_ERR_BADMOUNT; - - if ((err != 0) && (strncmp(buf, "/", sizeof(buf)) != 0)) - err = BE_ERR_BADMOUNT; - - zfs_close(zfs_hdl); - - return (err); -} - - -/* - * Idempotently appends the name argument to the root boot environment path - * and copies the resulting string into the result buffer (which is assumed - * to be at least BE_MAXPATHLEN characters long. Returns BE_ERR_SUCCESS upon - * success, BE_ERR_PATHLEN if the resulting path is longer than BE_MAXPATHLEN, - * or BE_ERR_INVALIDNAME if the name is a path that does not begin with - * zfs_be_root. Does not set internal library error state. - */ -int -be_root_concat(libbe_handle_t *lbh, const char *name, char *result) -{ - size_t name_len, root_len; - - name_len = strlen(name); - root_len = strlen(lbh->root); - - /* Act idempotently; return be name if it is already a full path */ - if (strrchr(name, '/') != NULL) { - if (strstr(name, lbh->root) != name) - return (BE_ERR_INVALIDNAME); - - if (name_len >= BE_MAXPATHLEN) - return (BE_ERR_PATHLEN); - - strlcpy(result, name, BE_MAXPATHLEN); - return (BE_ERR_SUCCESS); - } else if (name_len + root_len + 1 < BE_MAXPATHLEN) { - snprintf(result, BE_MAXPATHLEN, "%s/%s", lbh->root, - name); - return (BE_ERR_SUCCESS); - } - - return (BE_ERR_PATHLEN); -} - - -/* - * Verifies the validity of a boot environment name (A-Za-z0-9-_.). Returns - * BE_ERR_SUCCESS (0) if name is valid, otherwise returns BE_ERR_INVALIDNAME - * or BE_ERR_PATHLEN. - * Does not set internal library error state. - */ -int -be_validate_name(libbe_handle_t *lbh, const char *name) -{ - for (int i = 0; *name; i++) { - char c = *(name++); - if (isalnum(c) || (c == '-') || (c == '_') || (c == '.')) - continue; - return (BE_ERR_INVALIDNAME); - } - - /* - * Impose the additional restriction that the entire dataset name must - * not exceed the maximum length of a dataset, i.e. MAXNAMELEN. - */ - if (strlen(lbh->root) + 1 + strlen(name) > MAXNAMELEN) - return (BE_ERR_PATHLEN); - return (BE_ERR_SUCCESS); -} - - -/* - * usage - */ -int -be_rename(libbe_handle_t *lbh, const char *old, const char *new) -{ - char full_old[BE_MAXPATHLEN]; - char full_new[BE_MAXPATHLEN]; - zfs_handle_t *zfs_hdl; - int err; - - /* - * be_validate_name is documented not to set error state, so we should - * do so here. - */ - if ((err = be_validate_name(lbh, new)) != 0) - return (set_error(lbh, err)); - if ((err = be_root_concat(lbh, old, full_old)) != 0) - return (set_error(lbh, err)); - if ((err = be_root_concat(lbh, new, full_new)) != 0) - return (set_error(lbh, err)); - - if (!zfs_dataset_exists(lbh->lzh, full_old, ZFS_TYPE_DATASET)) - return (set_error(lbh, BE_ERR_NOENT)); - - if (zfs_dataset_exists(lbh->lzh, full_new, ZFS_TYPE_DATASET)) - return (set_error(lbh, BE_ERR_EXISTS)); - - if ((zfs_hdl = zfs_open(lbh->lzh, full_old, - ZFS_TYPE_FILESYSTEM)) == NULL) - return (set_error(lbh, BE_ERR_ZFSOPEN)); - - /* recurse, nounmount, forceunmount */ - struct renameflags flags = { - .nounmount = 1, - }; - - err = zfs_rename(zfs_hdl, NULL, full_new, flags); - - zfs_close(zfs_hdl); - if (err != 0) - return (set_error(lbh, BE_ERR_UNKNOWN)); - return (0); -} - - -int -be_export(libbe_handle_t *lbh, const char *bootenv, int fd) -{ - char snap_name[BE_MAXPATHLEN]; - char buf[BE_MAXPATHLEN]; - zfs_handle_t *zfs; - int err; - - if ((err = be_snapshot(lbh, bootenv, NULL, true, snap_name)) != 0) - /* Use the error set by be_snapshot */ - return (err); - - be_root_concat(lbh, snap_name, buf); - - if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL) - return (set_error(lbh, BE_ERR_ZFSOPEN)); - - err = zfs_send_one(zfs, NULL, fd, 0); - zfs_close(zfs); - - return (err); -} - - -int -be_import(libbe_handle_t *lbh, const char *bootenv, int fd) -{ - char buf[BE_MAXPATHLEN]; - time_t rawtime; - nvlist_t *props; - zfs_handle_t *zfs; - int err, len; - char nbuf[24]; - - /* - * We don't need this to be incredibly random, just unique enough that - * it won't conflict with an existing dataset name. Chopping time - * down to 32 bits is probably good enough for this. - */ - snprintf(nbuf, 24, "tmp%u", - (uint32_t)(time(NULL) & 0xFFFFFFFF)); - if ((err = be_root_concat(lbh, nbuf, buf)) != 0) - /* - * Technically this is our problem, but we try to use short - * enough names that we won't run into problems except in - * worst-case BE root approaching MAXPATHLEN. - */ - return (set_error(lbh, BE_ERR_PATHLEN)); - - time(&rawtime); - len = strlen(buf); - strftime(buf + len, sizeof(buf) - len, "@%F-%T", localtime(&rawtime)); - - if ((err = lzc_receive(buf, NULL, NULL, false, fd)) != 0) { - switch (err) { - case EINVAL: - return (set_error(lbh, BE_ERR_NOORIGIN)); - case ENOENT: - return (set_error(lbh, BE_ERR_NOENT)); - case EIO: - return (set_error(lbh, BE_ERR_IO)); - default: - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - } - - if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) == NULL) - return (set_error(lbh, BE_ERR_ZFSOPEN)); - - nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); - nvlist_add_string(props, "canmount", "noauto"); - nvlist_add_string(props, "mountpoint", "/"); - - be_root_concat(lbh, bootenv, buf); - - err = zfs_clone(zfs, buf, props); - zfs_close(zfs); - nvlist_free(props); - - if (err != 0) - return (set_error(lbh, BE_ERR_UNKNOWN)); - - /* - * Finally, we open up the dataset we just cloned the snapshot so that - * we may promote it. This is necessary in order to clean up the ghost - * snapshot that doesn't need to be seen after the operation is - * complete. - */ - if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL) - return (set_error(lbh, BE_ERR_ZFSOPEN)); - - err = zfs_promote(zfs); - zfs_close(zfs); - - if (err != 0) - return (set_error(lbh, BE_ERR_UNKNOWN)); - - /* Clean up the temporary snapshot */ - return (be_destroy(lbh, nbuf, 0)); -} - -#if SOON -static int -be_create_child_noent(libbe_handle_t *lbh, const char *active, - const char *child_path) -{ - nvlist_t *props; - zfs_handle_t *zfs; - int err; - - nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); - nvlist_add_string(props, "canmount", "noauto"); - nvlist_add_string(props, "mountpoint", child_path); - - /* Create */ - if ((err = zfs_create(lbh->lzh, active, ZFS_TYPE_DATASET, - props)) != 0) { - switch (err) { - case EZFS_EXISTS: - return (set_error(lbh, BE_ERR_EXISTS)); - case EZFS_NOENT: - return (set_error(lbh, BE_ERR_NOENT)); - case EZFS_BADTYPE: - case EZFS_BADVERSION: - return (set_error(lbh, BE_ERR_NOPOOL)); - case EZFS_BADPROP: - default: - /* We set something up wrong, probably... */ - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - } - nvlist_free(props); - - if ((zfs = zfs_open(lbh->lzh, active, ZFS_TYPE_DATASET)) == NULL) - return (set_error(lbh, BE_ERR_ZFSOPEN)); - - /* Set props */ - if ((err = zfs_prop_set(zfs, "canmount", "noauto")) != 0) { - zfs_close(zfs); - /* - * Similar to other cases, this shouldn't fail unless we've - * done something wrong. This is a new dataset that shouldn't - * have been mounted anywhere between creation and now. - */ - if (err == EZFS_NOMEM) - return (set_error(lbh, BE_ERR_NOMEM)); - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - zfs_close(zfs); - return (BE_ERR_SUCCESS); -} - -static int -be_create_child_cloned(libbe_handle_t *lbh, const char *active) -{ - char buf[BE_MAXPATHLEN], tmp[BE_MAXPATHLEN];; - zfs_handle_t *zfs; - int err; - - /* XXX TODO ? */ - - /* - * Establish if the existing path is a zfs dataset or just - * the subdirectory of one - */ - strlcpy(tmp, "tmp/be_snap.XXXXX", sizeof(tmp)); - if (mktemp(tmp) == NULL) - return (set_error(lbh, BE_ERR_UNKNOWN)); - - be_root_concat(lbh, tmp, buf); - printf("Here %s?\n", buf); - if ((err = zfs_snapshot(lbh->lzh, buf, false, NULL)) != 0) { - switch (err) { - case EZFS_INVALIDNAME: - return (set_error(lbh, BE_ERR_INVALIDNAME)); - - default: - /* - * The other errors that zfs_ioc_snapshot might return - * shouldn't happen if we've set things up properly, so - * we'll gloss over them and call it UNKNOWN as it will - * require further triage. - */ - if (errno == ENOTSUP) - return (set_error(lbh, BE_ERR_NOPOOL)); - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - } - - /* Clone */ - if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) == NULL) - return (BE_ERR_ZFSOPEN); - - if ((err = zfs_clone(zfs, active, NULL)) != 0) - /* XXX TODO correct error */ - return (set_error(lbh, BE_ERR_UNKNOWN)); - - /* set props */ - zfs_close(zfs); - return (BE_ERR_SUCCESS); -} - -int -be_add_child(libbe_handle_t *lbh, const char *child_path, bool cp_if_exists) -{ - struct stat sb; - char active[BE_MAXPATHLEN], buf[BE_MAXPATHLEN]; - nvlist_t *props; - const char *s; - - /* Require absolute paths */ - if (*child_path != '/') - return (set_error(lbh, BE_ERR_BADPATH)); - - strlcpy(active, be_active_path(lbh), BE_MAXPATHLEN); - strcpy(buf, active); - - /* Create non-mountable parent dataset(s) */ - s = child_path; - for (char *p; (p = strchr(s+1, '/')) != NULL; s = p) { - size_t len = p - s; - strncat(buf, s, len); - - nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); - nvlist_add_string(props, "canmount", "off"); - nvlist_add_string(props, "mountpoint", "none"); - zfs_create(lbh->lzh, buf, ZFS_TYPE_DATASET, props); - nvlist_free(props); - } - - /* Path does not exist as a descendent of / yet */ - if (strlcat(active, child_path, BE_MAXPATHLEN) >= BE_MAXPATHLEN) - return (set_error(lbh, BE_ERR_PATHLEN)); - - if (stat(child_path, &sb) != 0) { - /* Verify that error is ENOENT */ - if (errno != ENOENT) - return (set_error(lbh, BE_ERR_UNKNOWN)); - return (be_create_child_noent(lbh, active, child_path)); - } else if (cp_if_exists) - /* Path is already a descendent of / and should be copied */ - return (be_create_child_cloned(lbh, active)); - return (set_error(lbh, BE_ERR_EXISTS)); -} -#endif /* SOON */ - -static int -be_set_nextboot(libbe_handle_t *lbh, nvlist_t *config, uint64_t pool_guid, - const char *zfsdev) -{ - nvlist_t **child; - uint64_t vdev_guid; - int c, children; - - if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN, &child, - &children) == 0) { - for (c = 0; c < children; ++c) - if (be_set_nextboot(lbh, child[c], pool_guid, zfsdev) != 0) - return (1); - return (0); - } - - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID, - &vdev_guid) != 0) { - return (1); - } - - if (zpool_nextboot(lbh->lzh, pool_guid, vdev_guid, zfsdev) != 0) { - perror("ZFS_IOC_NEXTBOOT failed"); - return (1); - } - - return (0); -} - -/* - * Deactivate old BE dataset; currently just sets canmount=noauto - */ -static int -be_deactivate(libbe_handle_t *lbh, const char *ds) -{ - zfs_handle_t *zfs; - - if ((zfs = zfs_open(lbh->lzh, ds, ZFS_TYPE_DATASET)) == NULL) - return (1); - if (zfs_prop_set(zfs, "canmount", "noauto") != 0) - return (1); - zfs_close(zfs); - return (0); -} - -int -be_activate(libbe_handle_t *lbh, const char *bootenv, bool temporary) -{ - char be_path[BE_MAXPATHLEN]; - char buf[BE_MAXPATHLEN]; - nvlist_t *config, *dsprops, *vdevs; - char *origin; - uint64_t pool_guid; - zfs_handle_t *zhp; - int err; - - be_root_concat(lbh, bootenv, be_path); - - /* Note: be_exists fails if mountpoint is not / */ - if ((err = be_exists(lbh, be_path)) != 0) - return (set_error(lbh, err)); - - if (temporary) { - config = zpool_get_config(lbh->active_phandle, NULL); - if (config == NULL) - /* config should be fetchable... */ - return (set_error(lbh, BE_ERR_UNKNOWN)); - - if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, - &pool_guid) != 0) - /* Similarly, it shouldn't be possible */ - return (set_error(lbh, BE_ERR_UNKNOWN)); - - /* Expected format according to zfsbootcfg(8) man */ - snprintf(buf, sizeof(buf), "zfs:%s:", be_path); - - /* We have no config tree */ - if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, - &vdevs) != 0) - return (set_error(lbh, BE_ERR_NOPOOL)); - - return (be_set_nextboot(lbh, vdevs, pool_guid, buf)); - } else { - if (be_deactivate(lbh, lbh->bootfs) != 0) - return (-1); - - /* Obtain bootenv zpool */ - err = zpool_set_prop(lbh->active_phandle, "bootfs", be_path); - if (err) - return (-1); - - zhp = zfs_open(lbh->lzh, be_path, ZFS_TYPE_FILESYSTEM); - if (zhp == NULL) - return (-1); - - if (be_prop_list_alloc(&dsprops) != 0) - return (-1); - - if (be_get_dataset_props(lbh, be_path, dsprops) != 0) { - nvlist_free(dsprops); - return (-1); - } - - if (nvlist_lookup_string(dsprops, "origin", &origin) == 0) - err = zfs_promote(zhp); - nvlist_free(dsprops); - - zfs_close(zhp); - - if (err) - return (-1); - } - - return (BE_ERR_SUCCESS); -} diff --git a/lib/libbe/be.h b/lib/libbe/be.h deleted file mode 100644 index ab43e9ba564..00000000000 --- a/lib/libbe/be.h +++ /dev/null @@ -1,131 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2017 Kyle J. Kneitinger - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _LIBBE_H -#define _LIBBE_H - -#include -#include - -#define BE_MAXPATHLEN 512 - -typedef struct libbe_handle libbe_handle_t; - -typedef enum be_error { - BE_ERR_SUCCESS = 0, /* No error */ - BE_ERR_INVALIDNAME, /* invalid boot env name */ - BE_ERR_EXISTS, /* boot env name already taken */ - BE_ERR_NOENT, /* boot env doesn't exist */ - BE_ERR_PERMS, /* insufficient permissions */ - BE_ERR_DESTROYACT, /* cannot destroy active boot env */ - BE_ERR_DESTROYMNT, /* destroying a mounted be requires force */ - BE_ERR_BADPATH, /* path not suitable for operation */ - BE_ERR_PATHBUSY, /* requested path is busy */ - BE_ERR_PATHLEN, /* provided name exceeds maximum length limit */ - BE_ERR_BADMOUNT, /* mountpoint is not '/' */ - BE_ERR_NOORIGIN, /* could not open snapshot's origin */ - BE_ERR_MOUNTED, /* boot environment is already mounted */ - BE_ERR_NOMOUNT, /* boot environment is not mounted */ - BE_ERR_ZFSOPEN, /* calling zfs_open() failed */ - BE_ERR_ZFSCLONE, /* error when calling zfs_clone to create be */ - BE_ERR_IO, /* error when doing some I/O operation */ - BE_ERR_NOPOOL, /* operation not supported on this pool */ - BE_ERR_NOMEM, /* insufficient memory */ - BE_ERR_UNKNOWN, /* unknown error */ -} be_error_t; - - -/* Library handling functions: be.c */ -libbe_handle_t *libbe_init(void); -void libbe_close(libbe_handle_t *); - -/* Bootenv information functions: be_info.c */ -const char *be_active_name(libbe_handle_t *); -const char *be_active_path(libbe_handle_t *); -const char *be_nextboot_name(libbe_handle_t *); -const char *be_nextboot_path(libbe_handle_t *); -const char *be_root_path(libbe_handle_t *); - -int be_get_bootenv_props(libbe_handle_t *, nvlist_t *); -int be_get_dataset_props(libbe_handle_t *, const char *, nvlist_t *); -int be_get_dataset_snapshots(libbe_handle_t *, const char *, nvlist_t *); -int be_prop_list_alloc(nvlist_t **be_list); -void be_prop_list_free(nvlist_t *be_list); - -int be_activate(libbe_handle_t *, const char *, bool); - -/* Bootenv creation functions */ -int be_create(libbe_handle_t *, const char *); -int be_create_from_existing(libbe_handle_t *, const char *, const char *); -int be_create_from_existing_snap(libbe_handle_t *, const char *, const char *); -int be_snapshot(libbe_handle_t *, const char *, const char *, bool, char *); - -/* Bootenv manipulation functions */ -int be_rename(libbe_handle_t *, const char *, const char *); - -/* Bootenv removal functions */ - -typedef enum { - BE_DESTROY_FORCE = 1 << 0, -} be_destroy_opt_t; - -int be_destroy(libbe_handle_t *, const char *, int); - -/* Bootenv mounting functions: be_access.c */ - -typedef enum { - BE_MNT_FORCE = 1 << 0, - BE_MNT_DEEP = 1 << 1, -} be_mount_opt_t; - -int be_mount(libbe_handle_t *, char *, char *, int, char *); -int be_unmount(libbe_handle_t *, char *, int); -int be_mounted_at(libbe_handle_t *, const char *path, nvlist_t *); - -/* Error related functions: be_error.c */ -int libbe_errno(libbe_handle_t *); -const char *libbe_error_description(libbe_handle_t *); -void libbe_print_on_error(libbe_handle_t *, bool); - -/* Utility Functions */ -int be_root_concat(libbe_handle_t *, const char *, char *); -int be_validate_name(libbe_handle_t * __unused, const char *); -int be_validate_snap(libbe_handle_t *, const char *); -int be_exists(libbe_handle_t *, char *); - -int be_export(libbe_handle_t *, const char *, int fd); -int be_import(libbe_handle_t *, const char *, int fd); - -#if SOON -int be_add_child(libbe_handle_t *, const char *, bool); -#endif -void be_nicenum(uint64_t num, char *buf, size_t buflen); - -#endif /* _LIBBE_H */ diff --git a/lib/libbe/be_access.c b/lib/libbe/be_access.c deleted file mode 100644 index 328326f7147..00000000000 --- a/lib/libbe/be_access.c +++ /dev/null @@ -1,215 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2017 Kyle J. Kneitinger - * Copyright (c) 2018 Kyle Evans - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "be.h" -#include "be_impl.h" - -struct be_mountcheck_info { - const char *path; - char *name; -}; - -static int -be_mountcheck_cb(zfs_handle_t *zfs_hdl, void *data) -{ - struct be_mountcheck_info *info; - char *mountpoint; - - if (data == NULL) - return (1); - info = (struct be_mountcheck_info *)data; - if (!zfs_is_mounted(zfs_hdl, &mountpoint)) - return (0); - if (strcmp(mountpoint, info->path) == 0) { - info->name = strdup(zfs_get_name(zfs_hdl)); - free(mountpoint); - return (1); - } - free(mountpoint); - return (0); -} - -/* - * usage - */ -int -be_mounted_at(libbe_handle_t *lbh, const char *path, nvlist_t *details) -{ - char be[BE_MAXPATHLEN]; - zfs_handle_t *root_hdl; - struct be_mountcheck_info info; - prop_data_t propinfo; - - bzero(&be, BE_MAXPATHLEN); - if ((root_hdl = zfs_open(lbh->lzh, lbh->root, - ZFS_TYPE_FILESYSTEM)) == NULL) - return (BE_ERR_ZFSOPEN); - - info.path = path; - info.name = NULL; - zfs_iter_filesystems(root_hdl, be_mountcheck_cb, &info); - zfs_close(root_hdl); - - if (info.name != NULL) { - if (details != NULL) { - if ((root_hdl = zfs_open(lbh->lzh, lbh->root, - ZFS_TYPE_FILESYSTEM)) == NULL) { - free(info.name); - return (BE_ERR_ZFSOPEN); - } - - propinfo.lbh = lbh; - propinfo.list = details; - propinfo.single_object = false; - prop_list_builder_cb(root_hdl, &propinfo); - zfs_close(root_hdl); - } - free(info.name); - return (0); - } - return (1); -} - -/* - * usage - */ -int -be_mount(libbe_handle_t *lbh, char *bootenv, char *mountpoint, int flags, - char *result_loc) -{ - char be[BE_MAXPATHLEN]; - char mnt_temp[BE_MAXPATHLEN]; - int mntflags; - int err; - - if ((err = be_root_concat(lbh, bootenv, be)) != 0) - return (set_error(lbh, err)); - - if ((err = be_exists(lbh, bootenv)) != 0) - return (set_error(lbh, err)); - - if (is_mounted(lbh->lzh, be, NULL)) - return (set_error(lbh, BE_ERR_MOUNTED)); - - mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0; - - /* Create mountpoint if it is not specified */ - if (mountpoint == NULL) { - strlcpy(mnt_temp, "/tmp/be_mount.XXXX", sizeof(mnt_temp)); - if (mkdtemp(mnt_temp) == NULL) - return (set_error(lbh, BE_ERR_IO)); - } - - char opt = '\0'; - if ((err = zmount(be, (mountpoint == NULL) ? mnt_temp : mountpoint, - mntflags, __DECONST(char *, MNTTYPE_ZFS), NULL, 0, &opt, 1)) != 0) { - switch (errno) { - case ENAMETOOLONG: - return (set_error(lbh, BE_ERR_PATHLEN)); - case ELOOP: - case ENOENT: - case ENOTDIR: - return (set_error(lbh, BE_ERR_BADPATH)); - case EPERM: - return (set_error(lbh, BE_ERR_PERMS)); - case EBUSY: - return (set_error(lbh, BE_ERR_PATHBUSY)); - default: - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - } - - if (result_loc != NULL) - strlcpy(result_loc, mountpoint == NULL ? mnt_temp : mountpoint, - BE_MAXPATHLEN); - - return (BE_ERR_SUCCESS); -} - - -/* - * usage - */ -int -be_unmount(libbe_handle_t *lbh, char *bootenv, int flags) -{ - int err, mntflags; - char be[BE_MAXPATHLEN]; - struct statfs *mntbuf; - int mntsize; - char *mntpath; - - if ((err = be_root_concat(lbh, bootenv, be)) != 0) - return (set_error(lbh, err)); - - if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { - if (errno == EIO) - return (set_error(lbh, BE_ERR_IO)); - return (set_error(lbh, BE_ERR_NOMOUNT)); - } - - mntpath = NULL; - for (int i = 0; i < mntsize; ++i) { - /* 0x000000de is the type number of zfs */ - if (mntbuf[i].f_type != 0x000000de) - continue; - - if (strcmp(mntbuf[i].f_mntfromname, be) == 0) { - mntpath = mntbuf[i].f_mntonname; - break; - } - } - - if (mntpath == NULL) - return (set_error(lbh, BE_ERR_NOMOUNT)); - - mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0; - - if ((err = unmount(mntpath, mntflags)) != 0) { - switch (errno) { - case ENAMETOOLONG: - return (set_error(lbh, BE_ERR_PATHLEN)); - case ELOOP: - case ENOENT: - case ENOTDIR: - return (set_error(lbh, BE_ERR_BADPATH)); - case EPERM: - return (set_error(lbh, BE_ERR_PERMS)); - case EBUSY: - return (set_error(lbh, BE_ERR_PATHBUSY)); - default: - return (set_error(lbh, BE_ERR_UNKNOWN)); - } - } - - return (set_error(lbh, BE_ERR_SUCCESS)); -} diff --git a/lib/libbe/be_error.c b/lib/libbe/be_error.c deleted file mode 100644 index 746d873f8a3..00000000000 --- a/lib/libbe/be_error.c +++ /dev/null @@ -1,133 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2017 Kyle J. Kneitinger - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "be.h" -#include "be_impl.h" - -/* - * Usage - */ -int -libbe_errno(libbe_handle_t *lbh) -{ - - return (lbh->error); -} - - -const char * -libbe_error_description(libbe_handle_t *lbh) -{ - - switch (lbh->error) { - case BE_ERR_INVALIDNAME: - return ("invalid boot environment name"); - - case BE_ERR_EXISTS: - return ("boot environment name already taken"); - - case BE_ERR_NOENT: - return ("specified boot environment does not exist"); - - case BE_ERR_PERMS: - return ("insufficient permissions"); - - case BE_ERR_DESTROYACT: - return ("cannot destroy active boot environment"); - - case BE_ERR_DESTROYMNT: - return ("cannot destroy mounted boot env unless forced"); - - case BE_ERR_BADPATH: - return ("path not suitable for operation"); - - case BE_ERR_PATHBUSY: - return ("specified path is busy"); - - case BE_ERR_PATHLEN: - return ("provided path name exceeds maximum length limit"); - - case BE_ERR_BADMOUNT: - return ("mountpoint is not \"/\""); - - case BE_ERR_NOORIGIN: - return ("could not open snapshot's origin"); - - case BE_ERR_MOUNTED: - return ("boot environment is already mounted"); - - case BE_ERR_NOMOUNT: - return ("boot environment is not mounted"); - - case BE_ERR_ZFSOPEN: - return ("calling zfs_open() failed"); - - case BE_ERR_ZFSCLONE: - return ("error when calling zfs_clone() to create boot env"); - - case BE_ERR_IO: - return ("input/output error"); - - case BE_ERR_NOPOOL: - return ("operation not supported on this pool"); - - case BE_ERR_NOMEM: - return ("insufficient memory"); - - case BE_ERR_UNKNOWN: - return ("unknown error"); - - default: - assert(lbh->error == BE_ERR_SUCCESS); - return ("no error"); - } -} - - -void -libbe_print_on_error(libbe_handle_t *lbh, bool val) -{ - - lbh->print_on_err = val; - libzfs_print_on_error(lbh->lzh, val); -} - - -int -set_error(libbe_handle_t *lbh, be_error_t err) -{ - - lbh->error = err; - if (lbh->print_on_err && (err != BE_ERR_SUCCESS)) - fprintf(stderr, "%s\n", libbe_error_description(lbh)); - - return (err); -} diff --git a/lib/libbe/be_impl.h b/lib/libbe/be_impl.h deleted file mode 100644 index 99c783a1a64..00000000000 --- a/lib/libbe/be_impl.h +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2017 Kyle J. Kneitinger - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#ifndef _LIBBE_IMPL_H -#define _LIBBE_IMPL_H - -#include - -#include "be.h" - -struct libbe_handle { - libzfs_handle_t *lzh; - zpool_handle_t *active_phandle; - char root[BE_MAXPATHLEN]; - char rootfs[BE_MAXPATHLEN]; - char bootfs[BE_MAXPATHLEN]; - be_error_t error; - bool print_on_err; -}; - -struct libbe_deep_clone { - libbe_handle_t *lbh; - const char *bename; - const char *snapname; - const char *be_root; -}; - -struct libbe_dccb { - zfs_handle_t *zhp; - nvlist_t *props; -}; - -typedef struct prop_data { - nvlist_t *list; - libbe_handle_t *lbh; - bool single_object; /* list will contain props directly */ -} prop_data_t; - -int prop_list_builder_cb(zfs_handle_t *, void *); -int be_proplist_update(prop_data_t *); - -/* Clobbers any previous errors */ -int set_error(libbe_handle_t *, be_error_t); - -#endif /* _LIBBE_IMPL_H */ diff --git a/lib/libbe/be_info.c b/lib/libbe/be_info.c deleted file mode 100644 index dba718cbac8..00000000000 --- a/lib/libbe/be_info.c +++ /dev/null @@ -1,318 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2017 Kyle J. Kneitinger - * Copyright (c) 2018 Kyle Evans - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "be.h" -#include "be_impl.h" - -static int snapshot_proplist_update(zfs_handle_t *hdl, prop_data_t *data); - -/* - * Returns the name of the active boot environment - */ -const char * -be_active_name(libbe_handle_t *lbh) -{ - - return (strrchr(lbh->rootfs, '/') + sizeof(char)); -} - - -/* - * Returns full path of the active boot environment - */ -const char * -be_active_path(libbe_handle_t *lbh) -{ - - return (lbh->rootfs); -} - -/* - * Returns the name of the next active boot environment - */ -const char * -be_nextboot_name(libbe_handle_t *lbh) -{ - - return (strrchr(lbh->bootfs, '/') + sizeof(char)); -} - - -/* - * Returns full path of the active boot environment - */ -const char * -be_nextboot_path(libbe_handle_t *lbh) -{ - - return (lbh->bootfs); -} - - -/* - * Returns the path of the boot environment root dataset - */ -const char * -be_root_path(libbe_handle_t *lbh) -{ - - return (lbh->root); -} - - -/* - * Populates dsnvl with one nvlist per bootenv dataset describing the properties - * of that dataset that we've declared ourselves to care about. - */ -int -be_get_bootenv_props(libbe_handle_t *lbh, nvlist_t *dsnvl) -{ - prop_data_t data; - - data.lbh = lbh; - data.list = dsnvl; - data.single_object = false; - return (be_proplist_update(&data)); -} - -int -be_get_dataset_props(libbe_handle_t *lbh, const char *name, nvlist_t *props) -{ - zfs_handle_t *snap_hdl; - prop_data_t data; - int ret; - - data.lbh = lbh; - data.list = props; - data.single_object = true; - if ((snap_hdl = zfs_open(lbh->lzh, name, - ZFS_TYPE_FILESYSTEM | ZFS_TYPE_SNAPSHOT)) == NULL) - return (BE_ERR_ZFSOPEN); - - ret = prop_list_builder_cb(snap_hdl, &data); - zfs_close(snap_hdl); - return (ret); -} - -int -be_get_dataset_snapshots(libbe_handle_t *lbh, const char *name, nvlist_t *props) -{ - zfs_handle_t *ds_hdl; - prop_data_t data; - int ret; - - data.lbh = lbh; - data.list = props; - data.single_object = false; - if ((ds_hdl = zfs_open(lbh->lzh, name, - ZFS_TYPE_FILESYSTEM)) == NULL) - return (BE_ERR_ZFSOPEN); - - ret = snapshot_proplist_update(ds_hdl, &data); - zfs_close(ds_hdl); - return (ret); -} - -/* - * Internal callback function used by zfs_iter_filesystems. For each dataset in - * the bootenv root, populate an nvlist_t of its relevant properties. - */ -int -prop_list_builder_cb(zfs_handle_t *zfs_hdl, void *data_p) -{ - char buf[512], *mountpoint; - prop_data_t *data; - libbe_handle_t *lbh; - nvlist_t *props; - const char *dataset, *name; - boolean_t mounted; - - /* - * XXX TODO: - * some system for defining constants for the nvlist keys - * error checking - */ - data = (prop_data_t *)data_p; - lbh = data->lbh; - - if (data->single_object) - props = data->list; - else - nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); - - dataset = zfs_get_name(zfs_hdl); - nvlist_add_string(props, "dataset", dataset); - - name = strrchr(dataset, '/') + 1; - nvlist_add_string(props, "name", name); - - mounted = zfs_is_mounted(zfs_hdl, &mountpoint); - - if (mounted) - nvlist_add_string(props, "mounted", mountpoint); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "mountpoint", buf); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "origin", buf); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "creation", buf); - - nvlist_add_boolean_value(props, "active", - (strcmp(be_active_path(lbh), dataset) == 0)); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "used", buf); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "usedds", buf); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "usedsnap", buf); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "usedrefreserv", buf); - - if (zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512, - NULL, NULL, 0, 1) == 0) - nvlist_add_string(props, "referenced", buf); - - nvlist_add_boolean_value(props, "nextboot", - (strcmp(be_nextboot_path(lbh), dataset) == 0)); - - if (!data->single_object) - nvlist_add_nvlist(data->list, name, props); - - return (0); -} - - -/* - * Updates the properties of each bootenv in the libbe handle - * XXX TODO: ensure that this is always consistent (run after adds, deletes, - * renames,etc - */ -int -be_proplist_update(prop_data_t *data) -{ - zfs_handle_t *root_hdl; - - if ((root_hdl = zfs_open(data->lbh->lzh, data->lbh->root, - ZFS_TYPE_FILESYSTEM)) == NULL) - return (BE_ERR_ZFSOPEN); - - /* XXX TODO: some error checking here */ - zfs_iter_filesystems(root_hdl, prop_list_builder_cb, data); - - zfs_close(root_hdl); - - return (0); -} - -static int -snapshot_proplist_update(zfs_handle_t *hdl, prop_data_t *data) -{ - - return (zfs_iter_snapshots_sorted(hdl, prop_list_builder_cb, data)); -} - - -int -be_prop_list_alloc(nvlist_t **be_list) -{ - - return (nvlist_alloc(be_list, NV_UNIQUE_NAME, KM_SLEEP)); -} - -/* - * frees property list and its children - */ -void -be_prop_list_free(nvlist_t *be_list) -{ - nvlist_t *prop_list; - nvpair_t *be_pair; - - be_pair = nvlist_next_nvpair(be_list, NULL); - if (nvpair_value_nvlist(be_pair, &prop_list) == 0) - nvlist_free(prop_list); - - while ((be_pair = nvlist_next_nvpair(be_list, be_pair)) != NULL) { - if (nvpair_value_nvlist(be_pair, &prop_list) == 0) - nvlist_free(prop_list); - } -} - - -/* - * Usage - */ -int -be_exists(libbe_handle_t *lbh, char *be) -{ - char buf[BE_MAXPATHLEN]; - nvlist_t *dsprops; - char *mntpoint; - bool valid; - - be_root_concat(lbh, be, buf); - - if (!zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_DATASET)) - return (BE_ERR_NOENT); - - /* Also check if it's mounted at / */ - if (be_prop_list_alloc(&dsprops) != 0) - return (BE_ERR_UNKNOWN); - - if (be_get_dataset_props(lbh, buf, dsprops) != 0) { - nvlist_free(dsprops); - return (BE_ERR_UNKNOWN); - } - - if (nvlist_lookup_string(dsprops, "mountpoint", &mntpoint) == 0) { - valid = (strcmp(mntpoint, "/") == 0); - nvlist_free(dsprops); - return (valid ? BE_ERR_SUCCESS : BE_ERR_BADMOUNT); - } - - nvlist_free(dsprops); - return (BE_ERR_BADMOUNT); -} diff --git a/lib/libbe/libbe.3 b/lib/libbe/libbe.3 deleted file mode 100644 index 9e3dbef23df..00000000000 --- a/lib/libbe/libbe.3 +++ /dev/null @@ -1,469 +0,0 @@ -.\" -.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD -.\" -.\" Copyright (c) 2017 Kyle Kneitinger -.\" All rights reserved. -.\" Copyright (c) 2018 Kyle Evans -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd August 31, 2018 -.Dt LIBBE 3 -.Os -.Sh NAME -.Nm libbe -.Nd library for creating, destroying and modifying ZFS boot environments -.Sh LIBRARY -.Lb libbe -.Sh SYNOPSIS -.In be.h -.Ft "libbe_handle_t *hdl" Ns -.Fn libbe_init void -.Pp -.Ft void -.Fn libbe_close "libbe_handle_t *hdl" -.Pp -.Ft const char * Ns -.Fn be_active_name "libbe_handle_t *hdl" -.Pp -.Ft const char * Ns -.Fn be_active_path "libbe_handle_t *hdl" -.Pp -.Ft const char * Ns -.Fn be_nextboot_name "libbe_handle_t *hdl" -.Pp -.Ft const char * Ns -.Fn be_nextboot_path "libbe_handle_t *hdl" -.Pp -.Ft const char * Ns -.Fn be_root_path "libbe_handle_t *hdl" -.Pp -.Ft int -.Fn be_create "libbe_handle_t *hdl" "const char *be_name" -.Pp -.Ft int -.Fn be_create_from_existing "libbe_handle_t *hdl" "const char *be_name" "const char *be_origin" -.Pp -.Ft int -.Fn be_create_from_existing_snap "libbe_handle_t *hdl" "const char *be_name" "const char *snap" -.Pp -.Ft int -.Fn be_rename "libbe_handle_t *hdl" "const char *be_old" "const char *be_new" -.Pp -.Ft int -.Fn be_activate "libbe_handle_t *hdl" "const char *be_name" "bool temporary" -.Ft int -.Fn be_destroy "libbe_handle_t *hdl" "const char *be_name" "int options" -.Pp -.Ft void -.Fn be_nicenum "uint64_t num" "char *buf" "size_t bufsz" -.Pp -.\" TODO: Write up of mount options -.\" typedef enum { -.\" BE_MNT_FORCE = 1 << 0, -.\" BE_MNT_DEEP = 1 << 1, -.\" } be_mount_opt_t -.Ft int -.Fn be_mount "libbe_handle_t *hdl" "char *be_name" "char *mntpoint" "int flags" "char *result" -.Pp -.Ft int -.Fn be_mounted_at "libbe_handle_t *hdl" "const char *path" "nvlist_t *details" -.Pp -.Ft int -.Fn be_unmount "libbe_handle_t *hdl" "char *be_name" "int flags" -.Pp -.Ft int -.Fn libbe_errno "libbe_handle_t *hdl" -.Pp -.Ft const char * Ns -.Fn libbe_error_description "libbe_handle_t *hdl" -.Pp -.Ft void -.Fn libbe_print_on_error "libbe_handle_t *hdl" "bool doprint" -.Pp -.Ft int -.Fn be_root_concat "libbe_handle_t *hdl" "const char *be_name" "char *result" -.Pp -.Ft int -.Fn be_validate_name "libbe_handle_t *hdl" "const char *be_name" -.Pp -.Ft int -.Fn be_validate_snap "libbe_handle_t *hdl" "const char *snap" -.Pp -.Ft int -.Fn be_exists "libbe_handle_t *hdl" "char *be_name" -.Pp -.Ft int -.Fn be_export "libbe_handle_t *hdl" "const char *be_name" "int fd" -.Pp -.Ft int -.Fn be_import "libbe_handle_t *hdl" "const char *be_name" "int fd" -.Pp -.Ft int -.Fn be_prop_list_alloc "nvlist_t **prop_list" -.Pp -.Ft int -.Fn be_get_bootenv_props "libbe_handle_t *hdl" "nvlist_t *be_list" -.Pp -.Ft int -.Fn be_get_dataset_props "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *props" -.Pp -.Ft int -.Fn be_get_dataset_snapshots "libbe_handle_t *hdl" "const char *ds_name" "nvlist_t *snap_list" -.Pp -.Ft void -.Fn be_prop_list_free "nvlist_t *prop_list" -.Sh DESCRIPTION -.Nm -interfaces with libzfs to provide a set of functions for various operations -regarding ZFS boot environments including "deep" boot environments in which -a boot environments has child datasets. -.Pp -A context structure is passed to each function, allowing for a small amount -of state to be retained, such as errors from previous operations. -.Nm -may be configured to print the corresponding error message to -.Dv stderr -when an error is encountered with -.Fn libbe_print_on_error . -.Pp -All functions returning an -.Vt int -return 0 on success, or a -.Nm -errno otherwise as described in -.Sx DIAGNOSTICS . -.Pp -The -.Fn libbe_init -function initializes -.Nm , -returning a -.Vt "libbe_handle_t *" -on success, or -.Dv NULL -on error. -An error may occur if: -.Bl -column -.It /boot and / are not on the same filesystem and device, -.It libzfs fails to initialize, -.It The system has not been properly booted with a ZFS boot -environment, -.It Nm -fails to open the zpool the active boot environment resides on, or -.It Nm -fails to locate the boot environment that is currently mounted. -.El -.Pp -The -.Fn libbe_close -function frees all resources previously acquired in -.Fn libbe_init , -invalidating the handle in the process. -.Pp -The -.Fn be_active_name -function returns the name of the currently booted boot environment, -.Pp -The -.Fn be_active_path -function returns the full path of the currently booted boot environment. -.Pp -The -.Fn be_nextboot_name -function returns the name of the boot environment that will be active on reboot. -.Pp -The -.Fn be_nextboot_path -function returns the full path of the boot environment that will be -active on reboot. -.Pp -The -.Fn be_root_path -function returns the boot environment root path. -.Pp -The -.Fn be_create -function creates a boot environment with the given name. -It will be created from a snapshot of the currently booted boot environment. -.Pp -The -.Fn be_create_from_existing -function creates a boot environment with the given name from the name of an -existing boot environment. -A snapshot will be made of the base boot environment, and the new boot -environment will be created from that. -.Pp -The -.Fn be_create_from_existing_snap -function creates a boot environment with the given name from an existing -snapshot. -.Pp -The -.Fn be_rename -function renames a boot environment without unmounting it, as if renamed with -the -.Fl u -argument were passed to -.Nm zfs -.Cm rename -.Pp -The -.Fn be_activate -function makes a boot environment active on the next boot. -If the -.Fa temporary -flag is set, then it will be active for the next boot only, as done by -.Xr zfsbootcfg 8 . -Next boot functionality is currently only available when booting in x86 BIOS -mode. -.Pp -The -.Fn be_destroy -function will recursively destroy the given boot environment. -It will not destroy a mounted boot environment unless the -.Dv BE_DESTROY_FORCE -option is set in -.Fa options . -.Pp -The -.Fn be_nicenum -function will format -.Fa name -in a traditional ZFS humanized format, similar to -.Xr humanize_number 3 . -This function effectively proxies -.Fn zfs_nicenum -from libzfs. -.Pp -The -.Fn be_mount -function will mount the given boot environment. -If -.Fa mountpoint -is -.Dv NULL , -a mount point will be generated in -.Pa /tmp -using -.Xr mkdtemp 3 . -If -.Fa result -is not -.Dv NULL , -it should be large enough to accommodate -.Dv BE_MAXPATHLEN -including the null terminator. -the final mount point will be copied into it. -Setting the -.Dv BE_MNT_FORCE -flag will pass -.Dv MNT_FORCE -to the underlying -.Xr mount 2 -call. -.Pp -The -.Fn be_mounted_at -function will check if there is a boot environment mounted at the given -.Fa path . -If -.Fa details -is not -.Dv NULL , -it will be populated with a list of the mounted dataset's properties. -This list of properties matches the properties collected by -.Fn be_get_bootenv_props . -.Pp -The -.Fn be_unmount -function will unmount the given boot environment. -Setting the -.Dv BE_MNT_FORCE -flag will pass -.Dv MNT_FORCE -to the underlying -.Xr mount 2 -call. -.Pp -The -.Fn libbe_errno -function returns the -.Nm -errno. -.Pp -The -.Fn libbe_error_description -function returns a string description of the currently set -.Nm -errno. -.Pp -The -.Fn libbe_print_on_error -function will change whether or not -.Nm -prints the description of any encountered error to -.Dv stderr , -based on -.Fa doprint . -.Pp -The -.Fn be_root_concat -function will concatenate the boot environment root and the given boot -environment name into -.Fa result . -.Pp -The -.Fn be_validate_name -function will validate the given boot environment name for both length -restrictions as well as valid character restrictions. -This function does not set the internal library error state. -.Pp -The -.Fn be_validate_snap -function will validate the given snapshot name. -The snapshot must have a valid name, exist, and have a mountpoint of -.Pa / . -This function does not set the internal library error state. -.Pp -The -.Fn be_exists -function will check whether the given boot environment exists and has a -mountpoint of -.Pa / . -This function does not set the internal library error state, but will return -the appropriate error. -.Pp -The -.Fn be_export -function will export the given boot environment to the file specified by -.Fa fd . -A snapshot will be created of the boot environment prior to export. -.Pp -The -.Fn be_import -function will import the boot environment in the file specified by -.Fa fd , -and give it the name -.Fa be_name . -.Pp -The -.Fn be_prop_list_alloc -function allocates a property list suitable for passing to -.Fn be_get_bootenv_props , -.Fn be_get_dataset_props , -or -.Fn be_get_dataset_snapshots . -It should be freed later by -.Fa be_prop_list_free . -.Pp -The -.Fn be_get_bootenv_props -function will populate -.Fa be_list -with -.Vt nvpair_t -of boot environment names paired with an -.Vt nvlist_t -of their properties. -The following properties are currently collected as appropriate: -.Bl -column "Returned name" -.It Sy Returned name Ta Sy Description -.It dataset Ta - -.It name Ta Boot environment name -.It mounted Ta Current mount point -.It mountpoint Ta Do mountpoint Dc property -.It origin Ta Do origin Dc property -.It creation Ta Do creation Dc property -.It active Ta Currently booted environment -.It used Ta Literal Do used Dc property -.It usedds Ta Literal Do usedds Dc property -.It usedsnap Ta Literal Do usedrefreserv Dc property -.It referenced Ta Literal Do referenced Dc property -.It nextboot Ta Active on next boot -.El -.Pp -Only the -.Dq dataset , -.Dq name , -.Dq active , -and -.Dq nextboot -returned values will always be present. -All other properties may be omitted if not available. -.Pp -The -.Fn be_get_dataset_props -function will get properties of the specified dataset. -.Fa props -is populated directly with a list of the properties as returned by -.Fn be_get_bootenv_props . -.Pp -The -.Fn be_get_dataset_snapshots -function will retrieve all snapshots of the given dataset. -.Fa snap_list -will be populated with a list of -.Vt nvpair_t -exactly as specified by -.Fn be_get_bootenv_props . -.Pp -The -.Fn be_prop_list_free -function will free the property list. -.Sh DIAGNOSTICS -Upon error, one of the following values will be returned. -.\" TODO: make each entry on its own line. -.Bd -ragged -offset indent -BE_ERR_SUCCESS, -BE_ERR_INVALIDNAME, -BE_ERR_EXISTS, -BE_ERR_NOENT, -BE_ERR_PERMS, -BE_ERR_DESTROYACT, -BE_ERR_DESTROYMNT, -BE_ERR_BADPATH, -BE_ERR_PATHBUSY, -BE_ERR_PATHLEN, -BE_ERR_BADMOUNT, -BE_ERR_NOORIGIN, -BE_ERR_MOUNTED, -BE_ERR_NOMOUNT, -BE_ERR_ZFSOPEN, -BE_ERR_ZFSCLONE, -BE_ERR_IO, -BE_ERR_NOPOOL, -BE_ERR_NOMEM, -BE_ERR_UNKNOWN -.Ed -.Sh SEE ALSO -.Xr be 1 -.Sh HISTORY -.Nm -and its corresponding command, -.Xr bectl 8 , -were written as a 2017 Google Summer of Code project with Allan Jude serving -as a mentor. -Later work was done by -.An Kyle Evans Aq Mt kevans@FreeBSD.org . diff --git a/sbin/Makefile b/sbin/Makefile index 8033867e361..d75da5e8427 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -87,7 +87,6 @@ SUBDIR.${MK_PF}+= pfctl SUBDIR.${MK_PF}+= pflogd SUBDIR.${MK_QUOTAS}+= quotacheck SUBDIR.${MK_ROUTED}+= routed -SUBDIR.${MK_ZFS}+= bectl SUBDIR.${MK_ZFS}+= zfsbootcfg SUBDIR.${MK_TESTS}+= tests diff --git a/sbin/bectl/Makefile b/sbin/bectl/Makefile deleted file mode 100644 index 0014f964261..00000000000 --- a/sbin/bectl/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ - -PROG= bectl -MAN= bectl.8 - -SRCS= bectl.c bectl_jail.c bectl_list.c - -LIBADD+= be -LIBADD+= jail -LIBADD+= nvpair -LIBADD+= util - -CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common -CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris -CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common - -CFLAGS+= -DNEED_SOLARIS_BOOLEAN - -.include diff --git a/sbin/bectl/bectl.8 b/sbin/bectl/bectl.8 deleted file mode 100644 index 56ff28c71e1..00000000000 --- a/sbin/bectl/bectl.8 +++ /dev/null @@ -1,287 +0,0 @@ -.\" -.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD -.\" -.\" Copyright (c) 2017 Kyle J. Kneitinger -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" -.\" @(#)be.1 -.\" -.\" $FreeBSD$ -.\" -.Dd August 24, 2018 -.Dt BECTL 8 -.Os -.Sh NAME -.Nm bectl -.Nd Utility to manage Boot Environments on ZFS -.Sh SYNOPSIS -.Nm -.Cm activate -.Op Fl t -.Ar beName -.Nm -.Cm create -.Op Fl r -.Op Fl e Brq Ar nonActiveBe | beName@snapshot -.Ar beName -.Nm -.Cm create -.Op Fl r -.Ar beName@snapshot -.Nm -.Cm destroy -.Op Fl F -.Brq Ar beName | beName@snapshot -.Nm -.Cm export -.Ar sourceBe -.Nm -.Cm import -.Ar targetBe -.Nm -.Cm jail -.Brq Fl b | Fl U -.Oo Bro Fl o Ar key Ns = Ns Ar value | Fl u Ar key Brc Oc Ns ... -.Brq Ar jailID | jailName -.Ar bootenv -.Op Ar utility Op Ar argument ... -.Nm -.Cm list -.Op Fl DHas -.Nm -.Cm mount -.Ar beName -.Op mountpoint -.Nm -.Cm rename -.Ar origBeName -.Ar newBeName -.Nm -.Brq Cm ujail | unjail -.Brq Ar jailID | jailName -.Ar bootenv -.Nm -.Brq Cm umount | unmount -.Op Fl f -.Ar beName -.Sh DESCRIPTION -The -.Nm -command is used to setup and interact with ZFS boot environments, which are -bootable clones of datasets. -.Pp -.Em Boot Environments -allows the system to be upgraded, while preserving the old system environment in -a separate ZFS dataset. -.Sh COMMANDS -The following commands are supported by -.Nm : -.Bl -tag -width activate -.It Xo -.Cm activate -.Op Fl t -.Ar beName -.Xc -Activate the given -.Ar beName -as the default boot filesystem. -If the -.Op Fl t -flag is given, this takes effect only for the next boot. -.It Xo -.Cm create -.Op Fl r -.Op Fl e Brq Ar nonActiveBe | beName@snapshot -.Ar beName -.Xc -Creates a new boot environment named -.Ar beName . -If the -.Fl e -argument is specified, the new environment will be cloned from the given -.Brq Ar nonActiveBe | Ar beName@snapshot . -If the -.Fl r -flag is given, a recursive boot environment will be made. -.It Xo -.Cm create -.Op Fl r -.Ar beName@snapshot -.Xc -Creates a snapshot of the existing boot environment named -.Ar beName . -If the -.Fl r -flag is given, a recursive boot environment will be made. -.It Xo -.Cm destroy -.Op Fl F -.Brq Ar beName | beName@snapshot -.Xc -Destroys the given -.Ar beName -boot environment or -.Ar beName@snapshot -snapshot without confirmation, unlike in -.Nm beadm . -Specifying -.Fl F -will automatically unmount without confirmation. -.It Cm export Ar sourceBe -Export -.Ar sourceBe -to -.Dv stdout . -.Dv stdout -must be piped or redirected to a file. -.It Cm import Ar targetBe -Import -.Ar targetBe -from -.Dv stdin . -.It Xo -.Cm jail -.Brq Fl b | Fl U -.Oo Bro Fl o Ar key Ns = Ns Ar value | Fl u Ar key Brc Oc Ns ... -.Brq Ar jailID | jailName -.Ao Ar bootenv Ac -.Op Ar utility Op Ar argument ... -.Xc -Creates a jail of the given boot environment. -Multiple -.Fl o -and -.Fl u -arguments may be specified. -.Fl o -will set a jail parameter, and -.Fl u -will unset a jail parameter. -.Pp -By default, jails are created in interactive mode and -.Pa /bin/sh -is -executed within the jail. -If -.Ar utility -is specified, it will be executed instead of -.Pa /bin/sh . -The jail will be destroyed and the boot environment unmounted when the command -finishes executing, unless the -.Fl U -argument is specified. -.Pp -The -.Fl b -argument enables batch mode, thereby disabling interactive mode. -The -.Fl U -argument will be ignored in batch mode. -.Pp -The -.Va name , -.Va host.hostname , -and -.Va path -may not actually be unset. -Attempts to unset any of these will revert them to the default values specified -below, if they have been overwritten by -.Fl o . -.Pp -All -.Ar key Ns = Ns Ar value -pairs are interpreted as jail parameters as described in -.Xr jail 8 . -The following default parameters are provided: -.Bl -column "allow.mount.devfs" "" -.It Va allow.mount Ta Cm true -.It Va allow.mount.devfs Ta Cm true -.It Va enforce_statfs Ta Cm 1 -.It Va name Ta Va bootenv -.It Va host.hostname Ta Va bootenv -.It Va path Ta Set to a path in /tmp generated by -.Xr libbe 3 . -.El -.Pp -All default parameters may be overwritten. -.It Cm list Op Fl DHas -Displays all boot environments. -The Active field indicates whether the boot environment is active now (N); -active on reboot (R); or both (NR). -.Pp -If -.Fl a -is used, display all datasets. -If -.Fl D -is used, display the full space usage for each boot environment, assuming all -other boot environments were destroyed. -The -.Fl H -option is used for scripting. -It does not print headers and separate fields by a single tab instead of -arbitrary white space. -If -.Fl s -is used, display all snapshots as well. -.It Cm mount Ar beName Op Ar mountpoint -Temporarily mount the boot environment. -Mount at the specified -.Ar mountpoint -if provided. -.It Cm rename Ar origBeName newBeName -Renames the given -.Ar origBeName -to the given -.Ar newBeName . -The boot environment will not be unmounted in order for this rename to occur. -.It Cm unjail Brq Ar jailID | jailName | beName -Destroys the jail created from the given boot environment. -.It Xo -.Cm unmount -.Op Fl f -.Ar beName -.Xc -Unmount the given boot environment, if it is mounted. -Specifying -.Fl f -will force the unmount if busy. -.El -.Sh EXAMPLES -.Bl -bullet -.It -To fill in with jail upgrade example when behavior is firm. -.El -.Sh SEE ALSO -.Xr jail 8 , -.Xr zfs 8 , -.Xr zpool 8 -.Sh HISTORY -.Nm -is based on -.Nm beadm -and was implemented as a project for the 2017 Summer of Code, along with -.Xr libbe 3 . -.Sh AUTHORS -.Nm -was written by -.An Kyle Kneitinger (kneitinger) Aq Mt kyle@kneit.in . -.Pp -.Nm beadm -was written and is maintained by -.An Slawomir Wojciech Wojtczak (vermaden) Aq Mt vermaden@interia.pl . -.Pp -.An Bryan Drewery (bdrewery) Aq Mt bryan@shatow.net -wrote the original -.Nm beadm -manual page that this one is derived from. diff --git a/sbin/bectl/bectl.c b/sbin/bectl/bectl.c deleted file mode 100644 index 89a90e4af02..00000000000 --- a/sbin/bectl/bectl.c +++ /dev/null @@ -1,525 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2017 Kyle J. Kneitinger - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "bectl.h" - -static int bectl_cmd_activate(int argc, char *argv[]); -static int bectl_cmd_create(int argc, char *argv[]); -static int bectl_cmd_destroy(int argc, char *argv[]); -static int bectl_cmd_export(int argc, char *argv[]); -static int bectl_cmd_import(int argc, char *argv[]); -#if SOON -static int bectl_cmd_add(int argc, char *argv[]); -#endif -static int bectl_cmd_mount(int argc, char *argv[]); -static int bectl_cmd_rename(int argc, char *argv[]); -static int bectl_cmd_unmount(int argc, char *argv[]); - -libbe_handle_t *be; - -int -usage(bool explicit) -{ - FILE *fp; - - fp = explicit ? stdout : stderr; - fprintf(fp, - "usage:\tbectl {-h | -? | subcommand [args...]}\n" - "\tbectl activate [-t] beName\n" - "\tbectl create [-e {nonActiveBe | -e beName@snapshot}] beName\n" - "\tbectl create beName@snapshot\n" - "\tbectl destroy [-F] {beName | beName@snapshot}\n" - "\tbectl export sourceBe\n" - "\tbectl import targetBe\n" -#if SOON - "\tbectl add (path)*\n" -#endif - "\tbectl jail [{-b | -U}] [{-o key=value | -u key}]... bootenv [utility [argument ...]]\n" - "\tbectl list [-a] [-D] [-H] [-s]\n" - "\tbectl mount beName [mountpoint]\n" - "\tbectl rename origBeName newBeName\n" - "\tbectl {ujail | unjail} ⟨jailID | jailName | bootenv)\n" - "\tbectl {umount | unmount} [-f] beName\n"); - - return (explicit ? 0 : EX_USAGE); -} - - -/* - * Represents a relationship between the command name and the parser action - * that handles it. - */ -struct command_map_entry { - const char *command; - int (*fn)(int argc, char *argv[]); -}; - -static struct command_map_entry command_map[] = -{ - { "activate", bectl_cmd_activate }, - { "create", bectl_cmd_create }, - { "destroy", bectl_cmd_destroy }, - { "export", bectl_cmd_export }, - { "import", bectl_cmd_import }, -#if SOON - { "add", bectl_cmd_add }, -#endif - { "jail", bectl_cmd_jail }, - { "list", bectl_cmd_list }, - { "mount", bectl_cmd_mount }, - { "rename", bectl_cmd_rename }, - { "unjail", bectl_cmd_unjail }, - { "unmount", bectl_cmd_unmount }, -}; - -static int -get_cmd_index(const char *cmd, int *idx) -{ - int map_size; - - map_size = nitems(command_map); - for (int i = 0; i < map_size; ++i) { - if (strcmp(cmd, command_map[i].command) == 0) { - *idx = i; - return (0); - } - } - - return (1); -} - - -static int -bectl_cmd_activate(int argc, char *argv[]) -{ - int err, opt; - bool temp; - - temp = false; - while ((opt = getopt(argc, argv, "t")) != -1) { - switch (opt) { - case 't': - temp = true; - break; - default: - fprintf(stderr, "bectl activate: unknown option '-%c'\n", - optopt); - return (usage(false)); - } - } - - argc -= optind; - argv += optind; - - if (argc != 1) { - fprintf(stderr, "bectl activate: wrong number of arguments\n"); - return (usage(false)); - } - - - /* activate logic goes here */ - if ((err = be_activate(be, argv[0], temp)) != 0) - /* XXX TODO: more specific error msg based on err */ - printf("did not successfully activate boot environment %s\n", - argv[0]); - else - printf("successfully activated boot environment %s\n", argv[0]); - - if (temp) - printf("for next boot\n"); - - return (err); -} - - -/* - * TODO: when only one arg is given, and it contains an "@" the this should - * create that snapshot - */ -static int -bectl_cmd_create(int argc, char *argv[]) -{ - char *atpos, *bootenv, *snapname, *source; - int err, opt; - bool recursive; - - snapname = NULL; - recursive = false; - while ((opt = getopt(argc, argv, "e:r")) != -1) { - switch (opt) { - case 'e': - snapname = optarg; - break; - case 'r': - recursive = true; - break; - default: - fprintf(stderr, "bectl create: unknown option '-%c'\n", - optopt); - return (usage(false)); - } - } - - argc -= optind; - argv += optind; - - if (argc != 1) { - fprintf(stderr, "bectl create: wrong number of arguments\n"); - return (usage(false)); - } - - bootenv = *argv; - if ((atpos = strchr(bootenv, '@')) != NULL) { - /* - * This is the "create a snapshot variant". No new boot - * environment is to be created here. - */ - *atpos++ = '\0'; - err = be_snapshot(be, bootenv, atpos, recursive, NULL); - } else if (snapname != NULL) { - if (strchr(snapname, '@') != NULL) - err = be_create_from_existing_snap(be, bootenv, - snapname); - else - err = be_create_from_existing(be, bootenv, snapname); - } else { - if ((snapname = strchr(bootenv, '@')) != NULL) { - *(snapname++) = '\0'; - if ((err = be_snapshot(be, be_active_path(be), - snapname, true, NULL)) != BE_ERR_SUCCESS) - fprintf(stderr, "failed to create snapshot\n"); - asprintf(&source, "%s@%s", be_active_path(be), snapname); - err = be_create_from_existing_snap(be, bootenv, - source); - return (err); - } else - err = be_create(be, bootenv); - } - - switch (err) { - case BE_ERR_SUCCESS: - break; - default: - if (atpos != NULL) - fprintf(stderr, - "failed to create a snapshot '%s' of '%s'\n", - atpos, bootenv); - else if (snapname == NULL) - fprintf(stderr, - "failed to create bootenv %s\n", bootenv); - else - fprintf(stderr, - "failed to create bootenv %s from snapshot %s\n", - bootenv, snapname); - } - - return (err); -} - - -static int -bectl_cmd_export(int argc, char *argv[]) -{ - char *bootenv; - - if (argc == 1) { - fprintf(stderr, "bectl export: missing boot environment name\n"); - return (usage(false)); - } - - if (argc > 2) { - fprintf(stderr, "bectl export: extra arguments provided\n"); - return (usage(false)); - } - - bootenv = argv[1]; - - if (isatty(STDOUT_FILENO)) { - fprintf(stderr, "bectl export: must redirect output\n"); - return (EX_USAGE); - } - - be_export(be, bootenv, STDOUT_FILENO); - - return (0); -} - - -static int -bectl_cmd_import(int argc, char *argv[]) -{ - char *bootenv; - int err; - - if (argc == 1) { - fprintf(stderr, "bectl import: missing boot environment name\n"); - return (usage(false)); - } - - if (argc > 2) { - fprintf(stderr, "bectl import: extra arguments provided\n"); - return (usage(false)); - } - - bootenv = argv[1]; - - if (isatty(STDIN_FILENO)) { - fprintf(stderr, "bectl import: input can not be from terminal\n"); - return (EX_USAGE); - } - - err = be_import(be, bootenv, STDIN_FILENO); - - return (err); -} - -#if SOON -static int -bectl_cmd_add(int argc, char *argv[]) -{ - - if (argc < 2) { - fprintf(stderr, "bectl add: must provide at least one path\n"); - return (usage(false)); - } - - for (int i = 1; i < argc; ++i) { - printf("arg %d: %s\n", i, argv[i]); - /* XXX TODO catch err */ - be_add_child(be, argv[i], true); - } - - return (0); -} -#endif - -static int -bectl_cmd_destroy(int argc, char *argv[]) -{ - char *target; - int opt, err; - bool force; - - force = false; - while ((opt = getopt(argc, argv, "F")) != -1) { - switch (opt) { - case 'F': - force = true; - break; - default: - fprintf(stderr, "bectl destroy: unknown option '-%c'\n", - optopt); - return (usage(false)); - } - } - - argc -= optind; - argv += optind; - - if (argc != 1) { - fprintf(stderr, "bectl destroy: wrong number of arguments\n"); - return (usage(false)); - } - - target = argv[0]; - - err = be_destroy(be, target, force); - - return (err); -} - -static int -bectl_cmd_mount(int argc, char *argv[]) -{ - char result_loc[BE_MAXPATHLEN]; - char *bootenv, *mountpoint; - int err; - - if (argc < 2) { - fprintf(stderr, "bectl mount: missing argument(s)\n"); - return (usage(false)); - } - - if (argc > 3) { - fprintf(stderr, "bectl mount: too many arguments\n"); - return (usage(false)); - } - - bootenv = argv[1]; - mountpoint = ((argc == 3) ? argv[2] : NULL); - - err = be_mount(be, bootenv, mountpoint, 0, result_loc); - - switch (err) { - case BE_ERR_SUCCESS: - printf("successfully mounted %s at %s\n", bootenv, result_loc); - break; - default: - fprintf(stderr, - (argc == 3) ? "failed to mount bootenv %s at %s\n" : - "failed to mount bootenv %s at temporary path %s\n", - bootenv, mountpoint); - } - - return (err); -} - - -static int -bectl_cmd_rename(int argc, char *argv[]) -{ - char *dest, *src; - int err; - - if (argc < 3) { - fprintf(stderr, "bectl rename: missing argument\n"); - return (usage(false)); - } - - if (argc > 3) { - fprintf(stderr, "bectl rename: too many arguments\n"); - return (usage(false)); - } - - src = argv[1]; - dest = argv[2]; - - err = be_rename(be, src, dest); - - switch (err) { - case BE_ERR_SUCCESS: - break; - default: - fprintf(stderr, "failed to rename bootenv %s to %s\n", - src, dest); - } - - return (0); -} - -static int -bectl_cmd_unmount(int argc, char *argv[]) -{ - char *bootenv, *cmd; - int err, flags, opt; - - /* Store alias used */ - cmd = argv[0]; - - flags = 0; - while ((opt = getopt(argc, argv, "f")) != -1) { - switch (opt) { - case 'f': - flags |= BE_MNT_FORCE; - break; - default: - fprintf(stderr, "bectl %s: unknown option '-%c'\n", - cmd, optopt); - return (usage(false)); - } - } - - argc -= optind; - argv += optind; - - if (argc != 1) { - fprintf(stderr, "bectl %s: wrong number of arguments\n", cmd); - return (usage(false)); - } - - bootenv = argv[0]; - - err = be_unmount(be, bootenv, flags); - - switch (err) { - case BE_ERR_SUCCESS: - break; - default: - fprintf(stderr, "failed to unmount bootenv %s\n", bootenv); - } - - return (err); -} - - -int -main(int argc, char *argv[]) -{ - const char *command; - int command_index, rc; - - if (argc < 2) - return (usage(false)); - - command = argv[1]; - - /* Handle command aliases */ - if (strcmp(command, "umount") == 0) - command = "unmount"; - - if (strcmp(command, "ujail") == 0) - command = "unjail"; - - if ((strcmp(command, "-?") == 0) || (strcmp(command, "-h") == 0)) - return (usage(true)); - - if (get_cmd_index(command, &command_index)) { - fprintf(stderr, "unknown command: %s\n", command); - return (usage(false)); - } - - - if ((be = libbe_init()) == NULL) - return (-1); - - libbe_print_on_error(be, true); - - /* XXX TODO: can be simplified if offset by 2 instead of one */ - rc = command_map[command_index].fn(argc-1, argv+1); - - libbe_close(be); - return (rc); -} diff --git a/sbin/bectl/bectl.h b/sbin/bectl/bectl.h deleted file mode 100644 index 878af24f0cb..00000000000 --- a/sbin/bectl/bectl.h +++ /dev/null @@ -1,37 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2018 Kyle Evans - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -int usage(bool explicit); - -int bectl_cmd_jail(int argc, char *argv[]); -int bectl_cmd_unjail(int argc, char *argv[]); - -int bectl_cmd_list(int argc, char *argv[]); - -extern libbe_handle_t *be; diff --git a/sbin/bectl/bectl_jail.c b/sbin/bectl/bectl_jail.c deleted file mode 100644 index c60cec5fa68..00000000000 --- a/sbin/bectl/bectl_jail.c +++ /dev/null @@ -1,416 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2018 Kyle Evans - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "bectl.h" - -static void jailparam_grow(void); -static void jailparam_add(const char *name, const char *val); -static int jailparam_del(const char *name); -static bool jailparam_addarg(char *arg); -static int jailparam_delarg(char *arg); - -static int bectl_search_jail_paths(const char *mnt); -static int bectl_locate_jail(const char *ident); - -/* We'll start with 8 parameters initially and grow as needed. */ -#define INIT_PARAMCOUNT 8 - -static struct jailparam *jp; -static int jpcnt; -static int jpused; -static char mnt_loc[BE_MAXPATHLEN]; - -static void -jailparam_grow(void) -{ - - jpcnt *= 2; - jp = realloc(jp, jpcnt * sizeof(*jp)); - if (jp == NULL) - err(2, "realloc"); -} - -static void -jailparam_add(const char *name, const char *val) -{ - int i; - - for (i = 0; i < jpused; ++i) { - if (strcmp(name, jp[i].jp_name) == 0) - break; - } - - if (i < jpused) - jailparam_free(&jp[i], 1); - else if (jpused == jpcnt) - /* The next slot isn't allocated yet */ - jailparam_grow(); - - if (jailparam_init(&jp[i], name) != 0) - return; - if (jailparam_import(&jp[i], val) != 0) - return; - ++jpused; -} - -static int -jailparam_del(const char *name) -{ - int i; - char *val; - - for (i = 0; i < jpused; ++i) { - if (strcmp(name, jp[i].jp_name) == 0) - break; - } - - if (i == jpused) - return (ENOENT); - - for (; i < jpused - 1; ++i) { - val = jailparam_export(&jp[i + 1]); - - jailparam_free(&jp[i], 1); - /* - * Given the context, the following will really only fail if - * they can't allocate the copy of the name or value. - */ - if (jailparam_init(&jp[i], jp[i + 1].jp_name) != 0) { - free(val); - return (ENOMEM); - } - if (jailparam_import(&jp[i], val) != 0) { - jailparam_free(&jp[i], 1); - free(val); - return (ENOMEM); - } - free(val); - } - - jailparam_free(&jp[i], 1); - --jpused; - return (0); -} - -static bool -jailparam_addarg(char *arg) -{ - char *name, *val; - - if (arg == NULL) - return (false); - name = arg; - if ((val = strchr(arg, '=')) == NULL) { - fprintf(stderr, "bectl jail: malformed jail option '%s'\n", - arg); - return (false); - } - - *val++ = '\0'; - if (strcmp(name, "path") == 0) { - if (strlen(val) >= BE_MAXPATHLEN) { - fprintf(stderr, - "bectl jail: skipping too long path assignment '%s' (max length = %d)\n", - val, BE_MAXPATHLEN); - return (false); - } - strlcpy(mnt_loc, val, sizeof(mnt_loc)); - } - jailparam_add(name, val); - return (true); -} - -static int -jailparam_delarg(char *arg) -{ - char *name, *val; - - if (arg == NULL) - return (EINVAL); - name = arg; - if ((val = strchr(name, '=')) != NULL) - *val++ = '\0'; - - if (strcmp(name, "path") == 0) - *mnt_loc = '\0'; - return (jailparam_del(name)); -} - -int -bectl_cmd_jail(int argc, char *argv[]) -{ - char *bootenv, *mountpoint; - int jid, opt, ret; - bool default_hostname, default_name, interactive, unjail; - pid_t pid; - - default_hostname = default_name = interactive = unjail = true; - jpcnt = INIT_PARAMCOUNT; - jp = malloc(jpcnt * sizeof(*jp)); - if (jp == NULL) - err(2, "malloc"); - - jailparam_add("persist", "true"); - jailparam_add("allow.mount", "true"); - jailparam_add("allow.mount.devfs", "true"); - jailparam_add("enforce_statfs", "1"); - - while ((opt = getopt(argc, argv, "bo:Uu:")) != -1) { - switch (opt) { - case 'b': - interactive = false; - break; - case 'o': - if (jailparam_addarg(optarg)) { - /* - * optarg has been modified to null terminate - * at the assignment operator. - */ - if (strcmp(optarg, "name") == 0) - default_name = false; - if (strcmp(optarg, "host.hostname") == 0) - default_hostname = false; - } - break; - case 'U': - unjail = false; - break; - case 'u': - if ((ret = jailparam_delarg(optarg)) == 0) { - if (strcmp(optarg, "name") == 0) - default_name = true; - if (strcmp(optarg, "host.hostname") == 0) - default_hostname = true; - } else if (ret != ENOENT) { - fprintf(stderr, - "bectl jail: error unsetting \"%s\"\n", - optarg); - return (ret); - } - break; - default: - fprintf(stderr, "bectl jail: unknown option '-%c'\n", - optopt); - return (usage(false)); - } - } - - argc -= optind; - argv += optind; - - /* struct jail be_jail = { 0 }; */ - if (argc < 1) { - fprintf(stderr, "bectl jail: missing boot environment name\n"); - return (usage(false)); - } - - bootenv = argv[0]; - - /* - * XXX TODO: if its already mounted, perhaps there should be a flag to - * indicate its okay to proceed?? - */ - if (*mnt_loc == '\0') - mountpoint = NULL; - else - mountpoint = mnt_loc; - if (be_mount(be, bootenv, mountpoint, 0, mnt_loc) != BE_ERR_SUCCESS) { - fprintf(stderr, "could not mount bootenv\n"); - return (1); - } - - if (default_name) - jailparam_add("name", bootenv); - if (default_hostname) - jailparam_add("host.hostname", bootenv); - - /* - * This is our indicator that path was not set by the user, so we'll use - * the path that libbe generated for us. - */ - if (mountpoint == NULL) - jailparam_add("path", mnt_loc); - /* Create the jail for now, attach later as-needed */ - jid = jailparam_set(jp, jpused, JAIL_CREATE); - if (jid == -1) { - fprintf(stderr, "unable to create jail. error: %d\n", errno); - return (1); - } - - jailparam_free(jp, jpused); - free(jp); - - /* We're not interactive, nothing more to do here. */ - if (!interactive) - return (0); - - pid = fork(); - switch(pid) { - case -1: - perror("fork"); - return (1); - case 0: - jail_attach(jid); - /* We're attached within the jail... good bye! */ - chdir("/"); - if (argc > 1) - execve(argv[1], &argv[1], NULL); - else - execl("/bin/sh", "/bin/sh", NULL); - fprintf(stderr, "bectl jail: failed to execute %s\n", - (argc > 1 ? argv[1] : "/bin/sh")); - _exit(1); - default: - /* Wait for the child to get back, see if we need to unjail */ - waitpid(pid, NULL, 0); - } - - if (unjail) { - jail_remove(jid); - unmount(mnt_loc, 0); - } - - return (0); -} - -static int -bectl_search_jail_paths(const char *mnt) -{ - char jailpath[MAXPATHLEN]; - int jid; - - jid = 0; - (void)mnt; - while ((jid = jail_getv(0, "lastjid", &jid, "path", &jailpath, - NULL)) != -1) { - if (strcmp(jailpath, mnt) == 0) - return (jid); - } - - return (-1); -} - -/* - * Locate a jail based on an arbitrary identifier. This may be either a name, - * a jid, or a BE name. Returns the jid or -1 on failure. - */ -static int -bectl_locate_jail(const char *ident) -{ - nvlist_t *belist, *props; - char *mnt; - int jid; - - /* Try the easy-match first */ - jid = jail_getid(ident); - if (jid != -1) - return (jid); - - /* Attempt to try it as a BE name, first */ - if (be_prop_list_alloc(&belist) != 0) - return (-1); - - if (be_get_bootenv_props(be, belist) != 0) - return (-1); - - if (nvlist_lookup_nvlist(belist, ident, &props) == 0) { - /* We'll attempt to resolve the jid by way of mountpoint */ - if (nvlist_lookup_string(props, "mountpoint", &mnt) == 0) { - jid = bectl_search_jail_paths(mnt); - be_prop_list_free(belist); - return (jid); - } - - be_prop_list_free(belist); - } - - return (-1); -} - -int -bectl_cmd_unjail(int argc, char *argv[]) -{ - char path[MAXPATHLEN]; - char *cmd, *name, *target; - int jid; - - /* Store alias used */ - cmd = argv[0]; - - if (argc != 2) { - fprintf(stderr, "bectl %s: wrong number of arguments\n", cmd); - return (usage(false)); - } - - target = argv[1]; - - /* Locate the jail */ - if ((jid = bectl_locate_jail(target)) == -1) { - fprintf(stderr, "bectl %s: failed to locate BE by '%s'\n", cmd, - target); - return (1); - } - - bzero(&path, MAXPATHLEN); - name = jail_getname(jid); - if (jail_getv(0, "name", name, "path", path, NULL) != jid) { - free(name); - fprintf(stderr, - "bectl %s: failed to get path for jail requested by '%s'\n", - cmd, target); - return (1); - } - - free(name); - - if (be_mounted_at(be, path, NULL) != 0) { - fprintf(stderr, "bectl %s: jail requested by '%s' not a BE\n", - cmd, target); - return (1); - } - - jail_remove(jid); - unmount(path, 0); - - return (0); -} diff --git a/sbin/bectl/bectl_list.c b/sbin/bectl/bectl_list.c deleted file mode 100644 index 2276ac8a21a..00000000000 --- a/sbin/bectl/bectl_list.c +++ /dev/null @@ -1,419 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2018 Kyle Evans - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include - -#include "bectl.h" - -struct printc { - int active_colsz_def; - int be_colsz; - int current_indent; - int mount_colsz; - int space_colsz; - bool script_fmt; - bool show_all_datasets; - bool show_snaps; - bool show_space; -}; - -static const char *get_origin_props(nvlist_t *dsprops, nvlist_t **originprops); -static void print_padding(const char *fval, int colsz, struct printc *pc); -static int print_snapshots(const char *dsname, struct printc *pc); -static void print_info(const char *name, nvlist_t *dsprops, struct printc *pc); -static void print_headers(nvlist_t *props, struct printc *pc); -static unsigned long long dataset_space(const char *oname); - -#define HEADER_BE "BE" -#define HEADER_BEPLUS "BE/Dataset/Snapshot" -#define HEADER_ACTIVE "Active" -#define HEADER_MOUNT "Mountpoint" -#define HEADER_SPACE "Space" -#define HEADER_CREATED "Created" - -/* Spaces */ -#define INDENT_INCREMENT 2 - -/* - * Given a set of dataset properties (for a BE dataset), populate originprops - * with the origin's properties. - */ -static const char * -get_origin_props(nvlist_t *dsprops, nvlist_t **originprops) -{ - char *propstr; - - if (nvlist_lookup_string(dsprops, "origin", &propstr) == 0) { - if (be_prop_list_alloc(originprops) != 0) { - fprintf(stderr, - "bectl list: failed to allocate origin prop nvlist\n"); - return (NULL); - } - if (be_get_dataset_props(be, propstr, *originprops) != 0) { - /* XXX TODO: Real errors */ - fprintf(stderr, - "bectl list: failed to fetch origin properties\n"); - return (NULL); - } - - return (propstr); - } - return (NULL); -} - -static void -print_padding(const char *fval, int colsz, struct printc *pc) -{ - - /* -H flag handling; all delimiters/padding are a single tab */ - if (pc->script_fmt) { - printf("\t"); - return; - } - - if (fval != NULL) - colsz -= strlen(fval); - printf("%*s ", colsz, ""); -} - -static unsigned long long -dataset_space(const char *oname) -{ - unsigned long long space; - char *dsname, *propstr, *sep; - nvlist_t *dsprops; - - space = 0; - dsname = strdup(oname); - if (dsname == NULL) - return (0); - - /* Truncate snapshot to dataset name, as needed */ - if ((sep = strchr(dsname, '@')) != NULL) - *sep = '\0'; - - if (be_prop_list_alloc(&dsprops) != 0) { - free(dsname); - return (0); - } - - if (be_get_dataset_props(be, dsname, dsprops) != 0) { - nvlist_free(dsprops); - free(dsname); - return (0); - } - - if (nvlist_lookup_string(dsprops, "used", &propstr) == 0) - space = strtoull(propstr, NULL, 10); - - nvlist_free(dsprops); - free(dsname); - return (space); -} - -static int -print_snapshots(const char *dsname, struct printc *pc) -{ - nvpair_t *cur; - nvlist_t *props, *sprops; - - if (be_prop_list_alloc(&props) != 0) { - fprintf(stderr, "bectl list: failed to allocate snapshot nvlist\n"); - return (1); - } - if (be_get_dataset_snapshots(be, dsname, props) != 0) { - fprintf(stderr, "bectl list: failed to fetch boot ds snapshots\n"); - return (1); - } - for (cur = nvlist_next_nvpair(props, NULL); cur != NULL; - cur = nvlist_next_nvpair(props, cur)) { - nvpair_value_nvlist(cur, &sprops); - print_info(nvpair_name(cur), sprops, pc); - } - return (0); -} - -static void -print_info(const char *name, nvlist_t *dsprops, struct printc *pc) -{ -#define BUFSZ 64 - char buf[BUFSZ]; - unsigned long long ctimenum, space; - nvlist_t *originprops; - const char *oname; - char *dsname, *propstr; - int active_colsz; - boolean_t active_now, active_reboot; - - dsname = NULL; - originprops = NULL; - printf("%*s%s", pc->current_indent, "", name); - nvlist_lookup_string(dsprops, "dataset", &dsname); - - /* Recurse at the base level if we're breaking info down */ - if (pc->current_indent == 0 && (pc->show_all_datasets || - pc->show_snaps)) { - printf("\n"); - if (dsname == NULL) - /* XXX TODO: Error? */ - return; - /* - * Whether we're dealing with -a or -s, we'll always print the - * dataset name/information followed by its origin. For -s, we - * additionally iterate through all snapshots of this boot - * environment and also print their information. - */ - pc->current_indent += INDENT_INCREMENT; - print_info(dsname, dsprops, pc); - pc->current_indent += INDENT_INCREMENT; - if ((oname = get_origin_props(dsprops, &originprops)) != NULL) { - print_info(oname, originprops, pc); - nvlist_free(originprops); - } - - /* Back up a level; snapshots at the same level as dataset */ - pc->current_indent -= INDENT_INCREMENT; - if (pc->show_snaps) - print_snapshots(dsname, pc); - pc->current_indent = 0; - return; - } else - print_padding(name, pc->be_colsz - pc->current_indent, pc); - - active_colsz = pc->active_colsz_def; - if (nvlist_lookup_boolean_value(dsprops, "active", - &active_now) == 0 && active_now) { - printf("N"); - active_colsz--; - } - if (nvlist_lookup_boolean_value(dsprops, "nextboot", - &active_reboot) == 0 && active_reboot) { - printf("R"); - active_colsz--; - } - if (active_colsz == pc->active_colsz_def) { - printf("-"); - active_colsz--; - } - print_padding(NULL, active_colsz, pc); - if (nvlist_lookup_string(dsprops, "mounted", &propstr) == 0) { - printf("%s", propstr); - print_padding(propstr, pc->mount_colsz, pc); - } else { - printf("%s", "-"); - print_padding("-", pc->mount_colsz, pc); - } - - oname = get_origin_props(dsprops, &originprops); - if (nvlist_lookup_string(dsprops, "used", &propstr) == 0) { - /* - * The space used column is some composition of: - * - The "used" property of the dataset - * - The "used" property of the origin snapshot (not -a or -s) - * - The "used" property of the origin dataset (-D flag only) - * - * The -D flag is ignored if -a or -s are specified. - */ - space = strtoull(propstr, NULL, 10); - - if (!pc->show_all_datasets && !pc->show_snaps && - originprops != NULL && - nvlist_lookup_string(originprops, "used", &propstr) == 0) - space += strtoull(propstr, NULL, 10); - - if (pc->show_space && oname != NULL) - space += dataset_space(oname); - - /* Alas, there's more to it,. */ - be_nicenum(space, buf, 6); - printf("%s", buf); - print_padding(buf, pc->space_colsz, pc); - } else { - printf("-"); - print_padding("-", pc->space_colsz, pc); - } - - if (nvlist_lookup_string(dsprops, "creation", &propstr) == 0) { - ctimenum = strtoull(propstr, NULL, 10); - strftime(buf, BUFSZ, "%Y-%m-%d %H:%M", - localtime((time_t *)&ctimenum)); - printf("%s", buf); - } - - printf("\n"); - if (originprops != NULL) - be_prop_list_free(originprops); -#undef BUFSZ -} - -static void -print_headers(nvlist_t *props, struct printc *pc) -{ - const char *chosen_be_header; - nvpair_t *cur; - nvlist_t *dsprops; - char *propstr; - size_t be_maxcol; - - if (pc->show_all_datasets || pc->show_snaps) - chosen_be_header = HEADER_BEPLUS; - else - chosen_be_header = HEADER_BE; - be_maxcol = strlen(chosen_be_header); - for (cur = nvlist_next_nvpair(props, NULL); cur != NULL; - cur = nvlist_next_nvpair(props, cur)) { - be_maxcol = MAX(be_maxcol, strlen(nvpair_name(cur))); - if (!pc->show_all_datasets && !pc->show_snaps) - continue; - nvpair_value_nvlist(cur, &dsprops); - if (nvlist_lookup_string(dsprops, "dataset", &propstr) != 0) - continue; - be_maxcol = MAX(be_maxcol, strlen(propstr) + INDENT_INCREMENT); - if (nvlist_lookup_string(dsprops, "origin", &propstr) != 0) - continue; - be_maxcol = MAX(be_maxcol, - strlen(propstr) + INDENT_INCREMENT * 2); - } - - pc->be_colsz = be_maxcol; - pc->active_colsz_def = strlen(HEADER_ACTIVE); - pc->mount_colsz = strlen(HEADER_MOUNT); - pc->space_colsz = strlen(HEADER_SPACE); - printf("%*s %s %s %s %s\n", -pc->be_colsz, chosen_be_header, - HEADER_ACTIVE, HEADER_MOUNT, HEADER_SPACE, HEADER_CREATED); - - /* - * All other invocations in which we aren't using the default header - * will produce quite a bit of input. Throw an extra blank line after - * the header to make it look nicer. - */ - if (strcmp(chosen_be_header, HEADER_BE) != 0) - printf("\n"); -} - -int -bectl_cmd_list(int argc, char *argv[]) -{ - struct printc pc; - nvpair_t *cur; - nvlist_t *dsprops, *props; - int opt, printed; - boolean_t active_now, active_reboot; - - props = NULL; - printed = 0; - bzero(&pc, sizeof(pc)); - while ((opt = getopt(argc, argv, "aDHs")) != -1) { - switch (opt) { - case 'a': - pc.show_all_datasets = true; - break; - case 'D': - pc.show_space = true; - break; - case 'H': - pc.script_fmt = true; - break; - case 's': - pc.show_snaps = true; - break; - default: - fprintf(stderr, "bectl list: unknown option '-%c'\n", - optopt); - return (usage(false)); - } - } - - argc -= optind; - - if (argc != 0) { - fprintf(stderr, "bectl list: extra argument provided\n"); - return (usage(false)); - } - - if (be_prop_list_alloc(&props) != 0) { - fprintf(stderr, "bectl list: failed to allocate prop nvlist\n"); - return (1); - } - if (be_get_bootenv_props(be, props) != 0) { - /* XXX TODO: Real errors */ - fprintf(stderr, "bectl list: failed to fetch boot environments\n"); - return (1); - } - - /* Force -D off if either -a or -s are specified */ - if (pc.show_all_datasets || pc.show_snaps) - pc.show_space = false; - if (!pc.script_fmt) - print_headers(props, &pc); - /* Do a first pass to print active and next active first */ - for (cur = nvlist_next_nvpair(props, NULL); cur != NULL; - cur = nvlist_next_nvpair(props, cur)) { - nvpair_value_nvlist(cur, &dsprops); - active_now = active_reboot = false; - - nvlist_lookup_boolean_value(dsprops, "active", &active_now); - nvlist_lookup_boolean_value(dsprops, "nextboot", - &active_reboot); - if (!active_now && !active_reboot) - continue; - if (printed > 0 && (pc.show_all_datasets || pc.show_snaps)) - printf("\n"); - print_info(nvpair_name(cur), dsprops, &pc); - printed++; - } - - /* Now pull everything else */ - for (cur = nvlist_next_nvpair(props, NULL); cur != NULL; - cur = nvlist_next_nvpair(props, cur)) { - nvpair_value_nvlist(cur, &dsprops); - active_now = active_reboot = false; - - nvlist_lookup_boolean_value(dsprops, "active", &active_now); - nvlist_lookup_boolean_value(dsprops, "nextboot", - &active_reboot); - if (active_now || active_reboot) - continue; - if (printed > 0 && (pc.show_all_datasets || pc.show_snaps)) - printf("\n"); - print_info(nvpair_name(cur), dsprops, &pc); - printed++; - } - be_prop_list_free(props); - - return (0); -} - diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index a0d394b576b..e09b2a6214f 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -21,7 +21,6 @@ LIBASN1?= ${DESTDIR}${LIBDIR_BASE}/libasn1.a LIBATM?= ${DESTDIR}${LIBDIR_BASE}/libatm.a LIBAUDITD?= ${DESTDIR}${LIBDIR_BASE}/libauditd.a LIBAVL?= ${DESTDIR}${LIBDIR_BASE}/libavl.a -LIBBE?= ${DESTDIR}${LIBDIR_BASE}/libbe.a LIBBEGEMOT?= ${DESTDIR}${LIBDIR_BASE}/libbegemot.a LIBBLACKLIST?= ${DESTDIR}${LIBDIR_BASE}/libblacklist.a LIBBLUETOOTH?= ${DESTDIR}${LIBDIR_BASE}/libbluetooth.a diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk index c6b6aa7dbae..f227353372b 100644 --- a/share/mk/src.libnames.mk +++ b/share/mk/src.libnames.mk @@ -59,7 +59,6 @@ _LIBRARIES= \ asn1 \ auditd \ avl \ - be \ begemot \ bluetooth \ bsdxml \ @@ -327,7 +326,6 @@ _DP_zfs= md pthread umem util uutil m nvpair avl bsdxml geom nvpair z \ zfs_core _DP_zfs_core= nvpair _DP_zpool= md pthread z nvpair avl umem -_DP_be= zfs nvpair # OFED support .if ${MK_OFED} != "no" @@ -468,8 +466,6 @@ LIBBSNMPTOOLS?= ${LIBBSNMPTOOLSDIR}/libbsnmptools.a LIBAMUDIR= ${OBJTOP}/usr.sbin/amd/libamu LIBAMU?= ${LIBAMUDIR}/libamu.a -LIBBE?= ${LIBBEDIR}/libbe.a - # Define a directory for each library. This is useful for adding -L in when # not using a --sysroot or for meta mode bootstrapping when there is no # Makefile.depend. These are sorted by directory. diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 8ba1e4848b3..ea1652ff45b 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -21,47 +21,6 @@ cpu HAMMER ident GENERIC -envvar static_env_included=1 -envvar boot_serial=1 -envvar console=userboot -envvar currdev=disk0s2a: -envvar vfs.root.mountfrom=ufs:vtbd0s2a -envvar loader_env.disabled=0 -envvar vfs.mountroot.timeout=3 -envvar hint.acpi_throttle.0.disabled=1 -envvar hint.atkbd.0.at=atkbdc -envvar hint.atkbd.0.irq=1 -envvar hint.atkbdc.0.at=isa -envvar hint.atkbdc.0.port=0x060 -envvar hint.atrtc.0.at=isa -envvar hint.atrtc.0.irq=8 -envvar hint.atrtc.0.port=0x70 -envvar hint.attimer.0.at=isa -envvar hint.attimer.0.irq=0 -envvar hint.attimer.0.port=0x40 -envvar hint.fd.0.at=fdc0 -envvar hint.fd.0.drive=0 -envvar hint.fd.1.at=fdc0 -envvar hint.fd.1.drive=1 -envvar hint.fdc.0.at=isa -envvar hint.fdc.0.drq=2 -envvar hint.fdc.0.irq=6 -envvar hint.fdc.0.port=0x3F0 -envvar hint.p4tcc.0.disabled=1 -envvar hint.ppc.0.at=isa -envvar hint.ppc.0.irq=7 -envvar hint.psm.0.at=atkbdc -envvar hint.psm.0.irq=12 -envvar hint.sc.0.at=isa -envvar hint.sc.0.flags=0x100 -envvar hint.uart.0.at=isa -envvar hint.uart.0.flags=0x10 -envvar hint.uart.0.irq=4 -envvar hint.uart.0.port=0x3F8 - -hints "hints.kyle" - - makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support diff --git a/sys/amd64/conf/MINIMAL b/sys/amd64/conf/MINIMAL index 676c712920b..7e7b0377cd7 100644 --- a/sys/amd64/conf/MINIMAL +++ b/sys/amd64/conf/MINIMAL @@ -35,9 +35,6 @@ cpu HAMMER ident MINIMAL -envvar static_env_included=1 -hints "hints.kyle" - makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols makeoptions WITH_CTF=1 # Run ctfconvert(1) for DTrace support diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 2ed4bf1c182..6de579e7489 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -1330,7 +1330,7 @@ OLD_FILES+=usr/bin/ztest OLD_FILES+=usr/lib/libbe.a OLD_FILES+=usr/lib/libbe_p.a OLD_FILES+=usr/lib/libbe.so -OLD_LIBS+=lib/libbe.so.1 +OLD_LIBS+=usr/lib/libbe.so.1 OLD_FILES+=usr/lib/libzfs.a OLD_LIBS+=usr/lib/libzfs.so OLD_FILES+=usr/lib/libzfs_core.a diff --git a/usr.sbin/config/config.y b/usr.sbin/config/config.y index 26bf4c160c9..e5296a27156 100644 --- a/usr.sbin/config/config.y +++ b/usr.sbin/config/config.y @@ -97,7 +97,7 @@ static void newdev(char *name); static void newfile(char *name); static void newenvvar(char *name, bool is_file); static void rmdev_schedule(struct device_head *dh, char *name); -static void newopt(struct opt_head *list, char *name, char *value, int append, int dupe); +static void newopt(struct opt_head *list, char *name, char *value, int append); static void rmopt_schedule(struct opt_head *list, char *name); static char * @@ -210,7 +210,7 @@ System_spec: ; System_id: - Save_id { newopt(&mkopt, ns("KERNEL"), $1, 0, 0); }; + Save_id { newopt(&mkopt, ns("KERNEL"), $1, 0); }; System_parameter_list: System_parameter_list ID @@ -230,13 +230,13 @@ NoOpt_list: ; Option: Save_id { - newopt(&opt, $1, NULL, 0, 1); + newopt(&opt, $1, NULL, 0); if (strchr($1, '=') != NULL) errx(1, "%s:%d: The `=' in options should not be " "quoted", yyfile, yyline); } | Save_id EQUALS Opt_value { - newopt(&opt, $1, $3, 0, 1); + newopt(&opt, $1, $3, 0); } ; NoOption: @@ -264,10 +264,10 @@ Mkopt_list: ; Mkoption: - Save_id { newopt(&mkopt, $1, ns(""), 0, 0); } | - Save_id EQUALS { newopt(&mkopt, $1, ns(""), 0, 0); } | - Save_id EQUALS Opt_value { newopt(&mkopt, $1, $3, 0, 0); } | - Save_id PLUSEQUALS Opt_value { newopt(&mkopt, $1, $3, 1, 0); } ; + Save_id { newopt(&mkopt, $1, ns(""), 0); } | + Save_id EQUALS { newopt(&mkopt, $1, ns(""), 0); } | + Save_id EQUALS Opt_value { newopt(&mkopt, $1, $3, 0); } | + Save_id PLUSEQUALS Opt_value { newopt(&mkopt, $1, $3, 1); } ; Dev: ID { $$ = $1; } @@ -293,7 +293,7 @@ NoDev_list: Device: Dev { - newopt(&opt, devopt($1), ns("1"), 0, 0); + newopt(&opt, devopt($1), ns("1"), 0); /* and the device part */ newdev($1); } @@ -430,7 +430,7 @@ findopt(struct opt_head *list, char *name) * Add an option to the list of options. */ static void -newopt(struct opt_head *list, char *name, char *value, int append, int dupe) +newopt(struct opt_head *list, char *name, char *value, int append) { struct opt *op, *op2; @@ -443,7 +443,7 @@ newopt(struct opt_head *list, char *name, char *value, int append, int dupe) } op2 = findopt(list, name); - if (op2 != NULL && !append && !dupe) { + if (op2 != NULL && !append) { fprintf(stderr, "WARNING: duplicate option `%s' encountered.\n", name); return; @@ -456,15 +456,9 @@ newopt(struct opt_head *list, char *name, char *value, int append, int dupe) op->op_ownfile = 0; op->op_value = value; if (op2 != NULL) { - if (append) { - while (SLIST_NEXT(op2, op_append) != NULL) - op2 = SLIST_NEXT(op2, op_append); - SLIST_NEXT(op2, op_append) = op; - } else { - while (SLIST_NEXT(op2, op_next) != NULL) - op2 = SLIST_NEXT(op2, op_next); - SLIST_NEXT(op2, op_next) = op; - } + while (SLIST_NEXT(op2, op_append) != NULL) + op2 = SLIST_NEXT(op2, op_append); + SLIST_NEXT(op2, op_append) = op; } else SLIST_INSERT_HEAD(list, op, op_next); } @@ -477,7 +471,8 @@ rmopt_schedule(struct opt_head *list, char *name) { struct opt *op; - while ((op = findopt(list, name)) != NULL) { + op = findopt(list, name); + if (op != NULL) { SLIST_REMOVE(list, op, opt, op_next); free(op->op_name); free(op); -- 2.45.0