From owner-svn-soc-all@freebsd.org Wed Jul 12 08:03:25 2017 Return-Path: Delivered-To: svn-soc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 102CEDB5998 for ; Wed, 12 Jul 2017 08:03:25 +0000 (UTC) (envelope-from kneitinger@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 01BC57E0D0 for ; Wed, 12 Jul 2017 08:03:25 +0000 (UTC) (envelope-from kneitinger@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.15.2/8.15.2) with ESMTP id v6C83OIp085053 for ; Wed, 12 Jul 2017 08:03:24 GMT (envelope-from kneitinger@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.15.2/8.15.2/Submit) id v6C83LkX084984 for svn-soc-all@FreeBSD.org; Wed, 12 Jul 2017 08:03:21 GMT (envelope-from kneitinger@FreeBSD.org) Date: Wed, 12 Jul 2017 08:03:21 GMT Message-Id: <201707120803.v6C83LkX084984@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to kneitinger@FreeBSD.org using -f From: kneitinger@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r324530 - in soc2017/kneitinger/libbe-head: lib/libbe sbin/be MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Jul 2017 08:03:25 -0000 Author: kneitinger Date: Wed Jul 12 08:03:21 2017 New Revision: 324530 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=324530 Log: libbe(3): add mount/unmount functions Added: soc2017/kneitinger/libbe-head/lib/libbe/be_access.c Modified: soc2017/kneitinger/libbe-head/lib/libbe/Makefile soc2017/kneitinger/libbe-head/lib/libbe/be.c soc2017/kneitinger/libbe-head/lib/libbe/be.h soc2017/kneitinger/libbe-head/lib/libbe/be_error.c soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h soc2017/kneitinger/libbe-head/lib/libbe/be_info.c soc2017/kneitinger/libbe-head/sbin/be/be.c Modified: soc2017/kneitinger/libbe-head/lib/libbe/Makefile ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/Makefile Wed Jul 12 07:31:28 2017 (r324529) +++ soc2017/kneitinger/libbe-head/lib/libbe/Makefile Wed Jul 12 08:03:21 2017 (r324530) @@ -28,7 +28,7 @@ LIB= be SHLIB_MAJOR= 1 SHLIB_MINOR= 0 -SRCS= be.c be_error.c be_info.c +SRCS= be.c be_access.c be_error.c be_info.c INCS= be.h MAN= libbe.3 Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.c ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be.c Wed Jul 12 07:31:28 2017 (r324529) +++ soc2017/kneitinger/libbe-head/lib/libbe/be.c Wed Jul 12 08:03:21 2017 (r324530) @@ -26,11 +26,12 @@ * SUCH DAMAGE. */ +#include + #include #include #include #include -#include #include #include "be.h" @@ -135,20 +136,17 @@ snprintf(path, MAXPATHLEN, "%s/%s", zfs_get_name(lbh->be_root), name); if (!zfs_dataset_exists(lbh->lzh, path, ZFS_TYPE_DATASET)) { - err = set_error(lbh, BE_ERR_NOENT); - return (err); + return (set_error(lbh, BE_ERR_NOENT)); } fs = zfs_open(lbh->lzh, p, ZFS_TYPE_DATASET); if (strcmp(path, zfs_get_name(lbh->be_active)) != 0) { - err = set_error(lbh, BE_ERR_DESTROYACT); - return (err); + return (set_error(lbh, BE_ERR_DESTROYACT)); } if ((mounted = zfs_is_mounted(fs, &p)) && !(force)) { - err = set_error(lbh, BE_ERR_DESTROYMNT); - return (err); + return (set_error(lbh, BE_ERR_DESTROYMNT)); } // TODO: check dependants @@ -327,6 +325,9 @@ int be_root_concat(libbe_handle_t *lbh, char *name, char *result) { + // TODO: make idempotent. As in: if it already is of the form: + // pool/beroot/be, return that + const char *root = be_root_path(lbh); int n = snprintf(result, MAXPATHLEN, "%s/%s", root, name); Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.h ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be.h Wed Jul 12 07:31:28 2017 (r324529) +++ soc2017/kneitinger/libbe-head/lib/libbe/be.h Wed Jul 12 08:03:21 2017 (r324530) @@ -45,6 +45,9 @@ BE_ERR_PATHLEN, /* provided name exceeds maximum length limit */ BE_ERR_INVORIGIN, /* snapshot origin's 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_UNKNOWN, /* unknown error */ } be_error_t; @@ -58,6 +61,7 @@ const char *be_active_path(libbe_handle_t *); const char *be_root_path(libbe_handle_t *); nvlist_t *be_get_bootenv_props(libbe_handle_t *); +bool be_exists(libbe_handle_t, char *); /* Bootenv creation functions */ int be_create(libbe_handle_t *, char *); @@ -68,15 +72,23 @@ /* Bootenv removal functions */ -#define BE_DESTROY_FORCE 1 +typedef enum { + BE_DESTROY_FORCE = 1 << 0, +} be_destroy_opt_t; int be_destroy(libbe_handle_t *, char *, int); -/* Bootenv mounting functions */ -int be_mount(libbe_handle_t *, char *, char *); +/* 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); int be_unmount(libbe_handle_t *, char *, int); -/* Bootenv jail functions */ +/* Bootenv jail functions: be_access.c */ int be_jail(libbe_handle_t *, char *); /* Error related functions: be_error.c */ @@ -88,5 +100,6 @@ int be_root_concat(libbe_handle_t *, char *, char *); int be_validate_name(libbe_handle_t *, char *); int be_validate_snap(libbe_handle_t *, char *); +bool be_exists(libbe_handle_t *, char *); #endif /* _LIBBE_H */ Added: soc2017/kneitinger/libbe-head/lib/libbe/be_access.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ soc2017/kneitinger/libbe-head/lib/libbe/be_access.c Wed Jul 12 08:03:21 2017 (r324530) @@ -0,0 +1,127 @@ +/* + * be_access.c + * + * 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 "be.h" +#include "be_impl.h" + +/* + * usage + */ +int +be_mount(libbe_handle_t *lbh, char *bootenv, char *mountpoint, int flags) +{ + char be[MAXPATHLEN]; + zfs_handle_t *zfs_hdl; + char *path; + int mntflags; + int err; + + // TODO: handle deep bes + + if (err = be_root_concat(lbh, bootenv, be)) { + return (set_error(lbh, err)); + } + + // TODO: make sure it exists (in a be_exists fn)! + + if (is_mounted(lbh->lzh, be, &path)) { + return (set_error(lbh, BE_ERR_MOUNTED)); + } + + + mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0; + + char opt = '\0'; + if (err = zmount(be, mountpoint, mntflags, MNTTYPE_ZFS, + NULL, 0, &opt, 1)) { + // TODO: zmount returns the nmount error, look into what kind of + // errors we can report from that + return (set_error(lbh, BE_ERR_UNKNOWN)); + } + + return (set_error(lbh, BE_ERR_SUCCESS)); +} + + +/* + * usage + */ +int +be_unmount(libbe_handle_t *lbh, char *bootenv, int flags) +{ + int err, mntflags; + char be[MAXPATHLEN]; + struct statfs *mntbuf; + int mntsize; + char *mntpath; + + if (err = be_root_concat(lbh, bootenv, be)) { + return (set_error(lbh, err)); + } + + if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { + // TODO correct error + 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)) { + // TODO correct error + return (set_error(lbh, BE_ERR_NOMOUNT)); + } + + return (set_error(lbh, BE_ERR_SUCCESS)); +} + + +/* + * usage + */ +int +be_jail(libbe_handle_t *lbh, char *bootenv) +{ + return (BE_ERR_SUCCESS); +} Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_error.c ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be_error.c Wed Jul 12 07:31:28 2017 (r324529) +++ soc2017/kneitinger/libbe-head/lib/libbe/be_error.c Wed Jul 12 08:03:21 2017 (r324530) @@ -35,69 +35,78 @@ int libbe_errno(libbe_handle_t *lbh) { - return (lbh->error); + return (lbh->error); } const char * libbe_error_description(libbe_handle_t *lbh) { - switch (lbh->error) { - case BE_ERR_INVALIDNAME: - return ("invalid boot environment name"); + 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_EXISTS: + return ("boot environment name already taken"); - case BE_ERR_NOENT: - return ("specified boot environment does not exist"); + case BE_ERR_NOENT: + return ("specified boot environment does not exist"); - case BE_ERR_PERMS: - return ("insufficient permissions"); + case BE_ERR_PERMS: + return ("insufficient permissions"); - case BE_ERR_DESTROYACT: - return ("cannot destroy active boot environment"); + 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_DESTROYMNT: + return ("cannot destroy mounted boot env unless forced"); - case BE_ERR_PATHLEN: - return ("provided path name exceeds maximum length limit"); + case BE_ERR_PATHLEN: + return ("provided path name exceeds maximum length limit"); - case BE_ERR_INVORIGIN: - return ("snapshot origin's mountpoint is not \"/\""); + case BE_ERR_INVORIGIN: + return ("snapshot origin's mountpoint is not \"/\""); - case BE_ERR_NOORIGIN: - return ("could not open snapshot's origin"); + case BE_ERR_NOORIGIN: + return ("could not open snapshot's origin"); - case BE_ERR_UNKNOWN: - return ("unknown error"); + case BE_ERR_MOUNTED: + return ("boot environment is already mounted"); - default: - assert(lbh->error == BE_ERR_SUCCESS); - return ("no error"); - } + case BE_ERR_NOMOUNT: + return ("boot environment is not mounted"); + + case BE_ERR_ZFSOPEN: + return ("calling zfs_open() failed"); + + 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); + lbh->print_on_err = val; + libzfs_print_on_error(lbh->lzh, val); } int set_error(libbe_handle_t *lbh, be_error_t err) { - // TODO: should the old error be overwritten or no? + // TODO: should the old error be overwritten or no? - lbh->error = err; + lbh->error = err; - if (lbh->print_on_err) { - fprintf(stderr, "%s\n", libbe_error_description(lbh)); - } + if (lbh->print_on_err) { + fprintf(stderr, "%s\n", libbe_error_description(lbh)); + } - return (err); + return (err); } Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h Wed Jul 12 07:31:28 2017 (r324529) +++ soc2017/kneitinger/libbe-head/lib/libbe/be_impl.h Wed Jul 12 08:03:21 2017 (r324530) @@ -30,16 +30,17 @@ #define _LIBBE_IMPL_H #include + #include "be.h" struct libbe_handle { - libzfs_handle_t *lzh; - zfs_handle_t *be_root; - zfs_handle_t *be_active; - be_error_t error; - nvlist_t *list; - bool print_on_err; + libzfs_handle_t *lzh; + zfs_handle_t *be_root; + zfs_handle_t *be_active; + be_error_t error; + nvlist_t *list; + bool print_on_err; }; int prop_list_builder(libbe_handle_t *); Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_info.c ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be_info.c Wed Jul 12 07:31:28 2017 (r324529) +++ soc2017/kneitinger/libbe-head/lib/libbe/be_info.c Wed Jul 12 08:03:21 2017 (r324530) @@ -37,9 +37,9 @@ const char * be_active_name(libbe_handle_t *lbh) { - const char *full_path = zfs_get_name(lbh->be_active); + const char *full_path = zfs_get_name(lbh->be_active); - return (strrchr(full_path, '/') + 1); + return (strrchr(full_path, '/') + 1); } @@ -49,7 +49,7 @@ const char * be_active_path(libbe_handle_t *lbh) { - return (zfs_get_name(lbh->be_active)); + return (zfs_get_name(lbh->be_active)); } @@ -59,7 +59,7 @@ const char * be_root_path(libbe_handle_t *lbh) { - return (zfs_get_name(lbh->be_root)); + return (zfs_get_name(lbh->be_root)); } @@ -70,9 +70,9 @@ nvlist_t * be_get_bootenv_props(libbe_handle_t *lbh) { - // TODO: Should there be a dirty flag that re-calcs the list if an op - // has changed it? - return (lbh->list); + // TODO: Should there be a dirty flag that re-calcs the list if an op + // has changed it? + return (lbh->list); } @@ -84,82 +84,83 @@ static int prop_list_builder_cb(zfs_handle_t *zfs_hdl, void *data) { - /* - * TODO: - * some system for defining constants for the nvlist keys - * error checking - */ + /* + * TODO: + * some system for defining constants for the nvlist keys + * error checking + */ - boolean_t mounted, active, nextboot; + boolean_t mounted, active, nextboot; - char buf[512]; + char buf[512]; - nvlist_t *props; + nvlist_t *props; - libbe_handle_t *lbh = (libbe_handle_t *)data; + libbe_handle_t *lbh = (libbe_handle_t *)data; - nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); + nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP); - const char *dataset = zfs_get_name(zfs_hdl); - nvlist_add_string(props, "dataset", dataset); + const char *dataset = zfs_get_name(zfs_hdl); + nvlist_add_string(props, "dataset", dataset); - const char *name = strrchr(dataset, '/') + 1; - nvlist_add_string(props, "name", name); + const char *name = strrchr(dataset, '/') + 1; + nvlist_add_string(props, "name", name); - mounted = zfs_prop_get_int(zfs_hdl, ZFS_PROP_MOUNTED); - nvlist_add_boolean_value(props, "mounted", mounted); + mounted = zfs_prop_get_int(zfs_hdl, ZFS_PROP_MOUNTED); + nvlist_add_boolean_value(props, "mounted", mounted); - if (mounted) { - zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, 512, - NULL, NULL, 0, 1); - nvlist_add_string(props, "mountpoint", buf); - } + // TODO: NOT CORRECT! Must use is_mounted + if (mounted) { + zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, 512, + NULL, NULL, 0, 1); + nvlist_add_string(props, "mountpoint", buf); + } - if (zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512, - NULL, NULL, 0, 1)) { - nvlist_add_string(props, "origin", buf); - } + if (zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512, + NULL, NULL, 0, 1)) { + nvlist_add_string(props, "origin", buf); + } - if (zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512, - NULL, NULL, 0, 1)) { - nvlist_add_string(props, "creation", buf); - } + if (zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512, + NULL, NULL, 0, 1)) { + nvlist_add_string(props, "creation", buf); + } - nvlist_add_boolean_value(props, "active", - (strcmp(be_active_path(lbh), dataset) == 0)); + 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)) { - nvlist_add_string(props, "used", buf); - } + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512, + NULL, NULL, 0, 1)) { + nvlist_add_string(props, "used", buf); + } - if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512, - NULL, NULL, 0, 1)) { - nvlist_add_string(props, "usedds", buf); - } + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512, + NULL, NULL, 0, 1)) { + nvlist_add_string(props, "usedds", buf); + } - if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512, - NULL, NULL, 0, 1)) { - nvlist_add_string(props, "usedsnap", buf); - } + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512, + NULL, NULL, 0, 1)) { + nvlist_add_string(props, "usedsnap", buf); + } - if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512, - NULL, NULL, 0, 1)) { - nvlist_add_string(props, "usedrefreserv", buf); - } + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512, + NULL, NULL, 0, 1)) { + nvlist_add_string(props, "usedrefreserv", buf); + } - if (zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512, - NULL, NULL, 0, 1)) { - nvlist_add_string(props, "referenced", buf); - } + if (zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512, + NULL, NULL, 0, 1)) { + nvlist_add_string(props, "referenced", buf); + } - /* TODO figure out how to read nextboot (set in libzfs_pool.c) */ + /* TODO figure out how to read nextboot (set in libzfs_pool.c) */ - nvlist_add_nvlist(lbh->list, name, props); + nvlist_add_nvlist(lbh->list, name, props); - return (0); + return (0); } @@ -172,45 +173,56 @@ int prop_list_builder(libbe_handle_t *lbh) { - if (lbh->list != NULL) { - /* TODO: should actually call prop_list_free */ - nvlist_free(lbh->list); - return (1); - } + if (lbh->list != NULL) { + /* TODO: should actually call prop_list_free */ + nvlist_free(lbh->list); + return (1); + } - if (nvlist_alloc(&lbh->list, NV_UNIQUE_NAME, KM_SLEEP) != 0) { - /* TODO: actually handle error */ - return (1); - } + if (nvlist_alloc(&lbh->list, NV_UNIQUE_NAME, KM_SLEEP) != 0) { + /* TODO: actually handle error */ + return (1); + } - zfs_iter_filesystems(lbh->be_root, prop_list_builder_cb, lbh); + zfs_iter_filesystems(lbh->be_root, prop_list_builder_cb, lbh); - return (0); + return (0); } /* - * Frees property list and its children + * frees property list and its children */ void prop_list_free(libbe_handle_t *lbh) { - nvlist_t *be_list; - nvlist_t *prop_list; + nvlist_t *be_list; + nvlist_t *prop_list; - if ((be_list = lbh->list) == 0) { - return; - } - - nvpair_t *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); - } - } + if ((be_list = lbh->list) == 0) { + return; + } + + nvpair_t *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 + */ +bool +be_exists(libbe_handle_t lbh, char *be) +{ + // TODO + return (true); } Modified: soc2017/kneitinger/libbe-head/sbin/be/be.c ============================================================================== --- soc2017/kneitinger/libbe-head/sbin/be/be.c Wed Jul 12 07:31:28 2017 (r324529) +++ soc2017/kneitinger/libbe-head/sbin/be/be.c Wed Jul 12 08:03:21 2017 (r324530) @@ -148,11 +148,10 @@ static int be_cmd_create(int argc, char *argv[]) { - int opt; + int err, opt; bool recursive; char *existing; char *bootenv; - char *snapshot; existing = NULL; recursive = false; @@ -179,25 +178,17 @@ return (usage(false)); } - /* Determine bootenv name, and snapshot if provided */ - char *buffer = malloc((strlen(argv[0])+1) * sizeof(char)); - strcpy(buffer, argv[0]); - char *delimiter; - if ((delimiter = strchr(buffer, '@')) != NULL) { - *delimiter = '\0'; - snapshot = delimiter + sizeof(char); - if (strchr(snapshot, '@') != NULL) { - fprintf(stderr, "be destroy: invalid snapshot name\n"); - free(buffer); - return (usage(false)); - } - } - bootenv = buffer; + bootenv = *argv; - /* create logic goes here */ - free(buffer); - return (0); + if (existing != NULL) { + err = be_create_from_existing(be, bootenv, existing); + // TODO: look at err and print useful message + } else { + err = be_create(be, bootenv); + } + + return (err); }