socsvn commit: r326784 - in soc2017/kneitinger/libbe-head: lib/libbe sbin/be
kneitinger at FreeBSD.org
kneitinger at FreeBSD.org
Mon Sep 4 13:22:26 UTC 2017
Author: kneitinger
Date: Mon Sep 4 13:22:23 2017
New Revision: 326784
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=326784
Log:
Mass August commit.
Modified:
soc2017/kneitinger/libbe-head/lib/libbe/be.c
soc2017/kneitinger/libbe-head/lib/libbe/be.h
soc2017/kneitinger/libbe-head/lib/libbe/be_access.c
soc2017/kneitinger/libbe-head/lib/libbe/be_info.c
soc2017/kneitinger/libbe-head/lib/libbe/libbe.3
soc2017/kneitinger/libbe-head/sbin/be/be.c
Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.c
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be.c Mon Sep 4 10:08:42 2017 (r326783)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be.c Mon Sep 4 13:22:23 2017 (r326784)
@@ -34,6 +34,7 @@
#include <libgen.h>
#include <libzfs_core.h>
#include <stdio.h>
+#include <stdlib.h>
#include <time.h>
#include <unistd.h>
@@ -49,7 +50,7 @@
{
char buf[BE_MAXPATHLEN];
struct stat sb;
- dev_t root_dev;
+ dev_t root_dev, boot_dev;
libbe_handle_t *lbh;
char *pos;
@@ -59,13 +60,17 @@
if (stat("/", &sb) != 0) {
return (NULL);
}
+
root_dev = sb.st_dev;
if (stat("/boot", &sb) != 0) {
return (NULL);
}
- if (root_dev != sb.st_dev) {
+ boot_dev = sb.st_dev;
+
+ if (root_dev != boot_dev) {
+ fprintf(stderr, "/ and /boot not on same device, quitting\n");
return (NULL);
}
@@ -134,28 +139,82 @@
int err = BE_ERR_SUCCESS;
- snprintf(path, BE_MAXPATHLEN, "%s/%s", lbh->root, name);
+ be_root_concat(lbh, name, path);
+ printf("path: %s\n", path);
if (!zfs_dataset_exists(lbh->lzh, path, ZFS_TYPE_DATASET)) {
return (set_error(lbh, BE_ERR_NOENT));
}
- fs = zfs_open(lbh->lzh, p, ZFS_TYPE_DATASET);
-
- if (strcmp(path, lbh->active) != 0) {
+ if (strcmp(path, lbh->active) == 0) {
return (set_error(lbh, BE_ERR_DESTROYACT));
}
+ fs = zfs_open(lbh->lzh, p, ZFS_TYPE_DATASET);
+
if ((mounted = zfs_is_mounted(fs, &p)) && !(force)) {
return (set_error(lbh, BE_ERR_DESTROYMNT));
}
- // TODO: check dependants
+ // TODO: account for "force" option by unmounting
+
+ // TODO: convert this to use zfs_iter_children first for deep bes
+ if ((err = zfs_destroy(fs, false)) != 0) {
+ fprintf(stderr, "delete failed\n");
+ }
+
+ return (err);
+}
+
+
+int
+be_snapshot(libbe_handle_t *lbh, char *source, char *snap_name, char *result)
+{
+ char buf[BE_MAXPATHLEN];
+ time_t rawtime;
+ int len, err;
+
+ if (!be_exists(lbh, source)) {
+ return (BE_ERR_NOENT);
+ }
+
+ be_root_concat(lbh, source, buf);
+
+ if (snap_name != NULL) {
+ strcat(buf, "@");
+ strcat(buf, snap_name);
+ if (result != NULL) {
+ snprintf(result, BE_MAXPATHLEN, "%s@%s", source,
+ snap_name);
+ }
+ } else {
+ time(&rawtime);
+ len = strlen(buf);
+ strftime(buf + len, BE_MAXPATHLEN - len,
+ "@%F-%T", localtime(&rawtime));
+ if (result != NULL) {
+ strcpy(result, strrchr(buf, '/') + 1);
+ }
+ }
+
+ if (err = zfs_snapshot(lbh->lzh, buf, false, NULL) != 0) {
+ switch (err) {
+ case EZFS_INVALIDNAME:
+ return (set_error(lbh, BE_ERR_INVALIDNAME));
+
+ default:
+ // TODO: elaborate return codes
+ return (set_error(lbh, BE_ERR_UNKNOWN));
+ }
+ }
- return (0);
+ return (BE_ERR_SUCCESS);
}
+// TODO: should be rewritten to just call be_create_from_existing() with
+// the current bootenv!
+
/*
* Create the boot environment specified by the name parameter
*/
@@ -167,6 +226,7 @@
char snap_name[BE_MAXPATHLEN];
time_t rawtime;
zfs_handle_t *snap_hdl;
+ nvlist_t *props;
if (be_validate_name(lbh, name)) {
return (set_error(lbh, BE_ERR_INVALIDNAME));
@@ -176,13 +236,6 @@
return (set_error(lbh, err));
}
- pos =
- snprintf(be_path, BE_MAXPATHLEN, "%s/%s", be_root_path(lbh), name);
-
- if ((pos < 0) || (pos >= BE_MAXPATHLEN)) {
- err = set_error(lbh, BE_ERR_PATHLEN);
- }
-
if (zfs_dataset_exists(lbh->lzh, be_path, ZFS_TYPE_DATASET)) {
err = set_error(lbh, BE_ERR_EXISTS);
return (err);
@@ -190,6 +243,7 @@
time(&rawtime);
+ // TODO: strcat!
pos = snprintf(snap_name, BE_MAXPATHLEN, "%s", be_active_path(lbh));
strftime(snap_name + pos, BE_MAXPATHLEN - pos,
"@%F-%T", localtime(&rawtime));
@@ -212,6 +266,11 @@
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", "/");
+
+
if (err = zfs_clone(snap_hdl, be_path, NULL)) {
switch (err) {
case EZFS_SUCCESS:
@@ -223,6 +282,8 @@
}
}
+ nvlist_free(props);
+
zfs_close(snap_hdl);
return (set_error(lbh, err));
@@ -233,19 +294,23 @@
* Create the boot environment from pre-existing snapshot
*/
int
-be_create_from_existing(libbe_handle_t *lbh, char *name, char *snap)
+be_create_from_existing_snap(libbe_handle_t *lbh, char *name, char *snap)
{
- int err, pos;
+ int err;
char be_path[BE_MAXPATHLEN];
- char snap_name[BE_MAXPATHLEN];
- time_t rawtime;
+ char snap_path[BE_MAXPATHLEN];
zfs_handle_t *snap_hdl;
+ nvlist_t *props;
if (err = be_validate_name(lbh, name)) {
return (set_error(lbh, err));
}
- if (err = be_validate_snap(lbh, snap)) {
+ if (err = be_root_concat(lbh, snap, snap_path)) {
+ return (set_error(lbh, err));
+ }
+
+ if (err = be_validate_snap(lbh, snap_path)) {
return (set_error(lbh, err));
}
@@ -257,10 +322,16 @@
return (set_error(lbh, BE_ERR_EXISTS));
}
+ if ((snap_hdl =
+ zfs_open(lbh->lzh, snap_path, ZFS_TYPE_SNAPSHOT)) == NULL) {
+ return (set_error(lbh, BE_ERR_ZFSOPEN));
+ }
- snap_hdl = zfs_open(lbh->lzh, snap, ZFS_TYPE_SNAPSHOT);
+ nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
+ nvlist_add_string(props, "canmount", "noauto");
+ nvlist_add_string(props, "mountpoint", "/");
- if (err = zfs_clone(snap_hdl, be_path, NULL)) {
+ if (err = zfs_clone(snap_hdl, be_path, props)) {
switch (err) {
case EZFS_SUCCESS:
err = BE_ERR_SUCCESS;
@@ -271,6 +342,7 @@
}
}
+ nvlist_free(props);
zfs_close(snap_hdl);
return (set_error(lbh, err));
@@ -278,6 +350,36 @@
/*
+ * Create a copy of an existing boot environment
+ */
+int
+be_create_from_existing(libbe_handle_t *lbh, char *name, char *old)
+{
+ int err;
+ char buf[BE_MAXPATHLEN];
+
+
+ long int snap_num = random();
+
+ be_root_concat(lbh, old, buf);
+ snprintf(buf + strlen(buf), BE_MAXPATHLEN, "@%ld", snap_num);
+
+ if (err = zfs_snapshot(lbh->lzh, buf, true, NULL)) {
+ // TODO correct error
+ return (-1);
+ }
+
+ snprintf(buf, BE_MAXPATHLEN, "%s@%ld", old, snap_num);
+
+ err = be_create_from_existing_snap(lbh, name, buf);
+
+ // TODO: delete snap
+
+ return (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.
@@ -289,7 +391,7 @@
char buf[BE_MAXPATHLEN];
char *delim_pos;
char *mountpoint;
- int err = 0;
+ int err = BE_ERR_SUCCESS;
if (strlen(snap_name) >= BE_MAXPATHLEN) {
return (BE_ERR_PATHLEN);
@@ -326,7 +428,7 @@
zfs_close(zfs_hdl);
- return (BE_ERR_SUCCESS);
+ return (err);
}
@@ -455,11 +557,17 @@
int
be_export(libbe_handle_t *lbh, char *bootenv, int fd)
{
+ char snap_name[BE_MAXPATHLEN];
char buf[BE_MAXPATHLEN];
zfs_handle_t *zfs;
int err;
- be_root_concat(lbh, bootenv, buf);
+ if (err = be_snapshot(lbh, bootenv, NULL, snap_name)) {
+ // TODO error handle
+ return (-1);
+ }
+
+ be_root_concat(lbh, snap_name, buf);
if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL) {
return (BE_ERR_ZFSOPEN);
@@ -474,19 +582,245 @@
be_import(libbe_handle_t *lbh, char *bootenv, int fd)
{
char buf[BE_MAXPATHLEN];
- int err;
+ time_t rawtime;
+ nvlist_t *props;
+ zfs_handle_t *zfs;
+ int err, len;
- if (err = be_root_concat(lbh, bootenv, buf)) {
+ // TODO: this is a very likely name for someone to already have used
+ if (err = be_root_concat(lbh, "be_import_temp", buf)) {
// TODO error handle
return (-1);
}
+ time(&rawtime);
+ len = strlen(buf);
+ strftime(buf + len, BE_MAXPATHLEN - len,
+ "@%F-%T", localtime(&rawtime));
+
+
// lzc_receive(SNAPNAME, PROPS, ORIGIN, FORCE, fd)) {
if (err = lzc_receive(buf, NULL, NULL, false, fd)) {
/* TODO: go through libzfs_core's recv_impl and find returned
- * errors and set appropriate BE_ERR */
+ * errors and set appropriate BE_ERR
+ * edit: errors are not in libzfs_core, my assumption is
+ * that they use libzfs errors
+ * note: 17 is err for dataset already existing */
+ return (err);
+ }
+
+ if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) == NULL) {
+ // TODO correct error
+ return (-1);
+ }
+
+ 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);
+
+ // TODO: recursively delete be_import_temp dataset
+
+ return (err);
+}
+
+
+int
+be_add_child(libbe_handle_t *lbh, char *child_path, bool cp_if_exists)
+{
+ char active[BE_MAXPATHLEN];
+ char buf[BE_MAXPATHLEN];
+ nvlist_t *props;
+ zfs_handle_t *zfs;
+ struct stat sb;
+ int err;
+
+ /* Require absolute paths */
+ if (*child_path != '/') {
+ /* TODO: create appropriate error */
+ return (-1);
+ }
+
+ strncpy(active, be_active_path(lbh), BE_MAXPATHLEN);
+ strcpy(buf, active);
+
+ /* Create non-mountable parent dataset(s) */
+ char *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 */
+ int pos = strlen(active);
+
+ /* TODO: Verify that resulting str is less than BE_MAXPATHLEN */
+ strncpy(&active[pos], child_path, BE_MAXPATHLEN-pos);
+
+
+ if (stat(child_path, &sb) != 0) {
+ /* Verify that error is ENOENT */
+ if (errno != 2) {
+ /* TODO: create appropriate error */
+ return (-1);
+ }
+
+ 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)) {
+ /* TODO handle error */
+ return (-1);
+ }
+ nvlist_free(props);
+
+ if ((zfs =
+ zfs_open(lbh->lzh, active, ZFS_TYPE_DATASET)) == NULL) {
+ /* TODO handle error */
+ return (-1);
+ }
+
+ // set props
+ if (err = zfs_prop_set(zfs, "canmount", "noauto")) {
+ /* TODO handle error */
+ return (-1);
+ }
+ } else if (cp_if_exists) {
+ /* Path is already a descendent of / and should be copied */
+
+
+
+ // TODO
+ /*
+ * Establish if the existing path is a zfs dataset or just
+ * the subdirectory of one
+ */
+
+
+ // TODO: use mktemp
+ long int snap_name = random();
+
+ snprintf(buf, BE_MAXPATHLEN, "%s@%ld", child_path, snap_name);
+
+ if (err = zfs_snapshot(lbh->lzh, buf, false, NULL)) {
+ // TODO correct error
+ return (-1);
+ }
+
+ // clone
+ if ((zfs =
+ zfs_open(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) == NULL) {
+ // TODO correct error
+ return (-1);
+ }
+
+ if (err = zfs_clone(zfs, active, NULL)) {
+ // TODO correct error
+ return (-1);
+ }
+
+
+ // set props
+ } else {
+ /* TODO: error code for exists, but not cp? */
return (-1);
}
+
return (BE_ERR_SUCCESS);
}
+
+
+int
+be_activate(libbe_handle_t *lbh, char *bootenv, bool temporary)
+{
+ char be_path[BE_MAXPATHLEN];
+ char buf[BE_MAXPATHLEN];
+ zpool_handle_t *zph;
+ uint64_t pool_guid;
+ uint64_t vdev_guid;
+ int zfs_fd;
+ int len;
+ int err;
+
+ be_root_concat(lbh, bootenv, be_path);
+
+
+ /* Note: be_exists fails if mountpoint is not / */
+ if (!be_exists(lbh, be_path)) {
+ return (BE_ERR_NOENT);
+ }
+
+ if (temporary) {
+ // TODO: give proper attribution to author(s) of zfsbootcfg
+ // for this snippet
+
+ if (kenv(KENV_GET, "vfs.zfs.boot.primary_pool", buf,
+ sizeof(buf)) <= 0) {
+ return (1);
+ }
+ pool_guid = strtoumax(buf, NULL, 10);
+ if (pool_guid == 0) {
+ return (1);
+ }
+
+ if (kenv(KENV_GET, "vfs.zfs.boot.primary_vdev", buf,
+ sizeof(buf)) <= 0) {
+ return (1);
+ }
+ vdev_guid = strtoumax(buf, NULL, 10);
+ if (vdev_guid == 0) {
+ return (1);
+ }
+
+ /* Expected format according to zfsbootcfg(8) man */
+ strcpy(buf, "zfs:");
+ strcat(buf, be_path);
+ strcat(buf, ":");
+
+ if (zpool_nextboot(lbh->lzh, pool_guid, vdev_guid, buf) != 0) {
+ perror("ZFS_IOC_NEXTBOOT failed");
+ return (1);
+ }
+
+ return (BE_ERR_SUCCESS);
+ } else {
+ /* Obtain bootenv zpool */
+ strncpy(buf, be_path, BE_MAXPATHLEN);
+ *(strchr(buf, '/')) = '\0';
+
+ if ((zph = zpool_open(lbh->lzh, buf)) == NULL) {
+ // TODO: create error for this
+ return (-1);
+ }
+ printf("asdf\n");
+
+ err = zpool_set_prop(zph, "bootfs", be_path);
+ zpool_close(zph);
+
+ switch (err) {
+ case 0:
+ return (BE_ERR_SUCCESS);
+
+ default:
+ // TODO correct errors
+ return (-1);
+ }
+ }
+}
Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.h
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be.h Mon Sep 4 10:08:42 2017 (r326783)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be.h Mon Sep 4 13:22:23 2017 (r326784)
@@ -31,7 +31,7 @@
#include <stdbool.h>
-#define BE_MAXPATHLEN ZFS_MAX_DATASET_NAME_LEN
+#define BE_MAXPATHLEN 512
typedef struct libbe_handle libbe_handle_t;
@@ -65,9 +65,13 @@
/* nvlist_t *be_get_bootenv_props(libbe_handle_t *); */
+int be_activate(libbe_handle_t *, char *, bool);
+
/* Bootenv creation functions */
int be_create(libbe_handle_t *, char *);
int be_create_from_existing(libbe_handle_t *, char *, char *);
+int be_create_from_existing_snap(libbe_handle_t *, char *, char *);
+int be_snapshot(libbe_handle_t *, char *, char *, char *);
/* Bootenv manipulation functions */
int be_rename(libbe_handle_t *, char *, char *);
@@ -87,7 +91,7 @@
BE_MNT_DEEP = 1 << 1,
} be_mount_opt_t;
-int be_mount(libbe_handle_t *, char *, char *, int);
+int be_mount(libbe_handle_t *, char *, char *, int, char *);
int be_unmount(libbe_handle_t *, char *, int);
/* Error related functions: be_error.c */
@@ -104,4 +108,6 @@
int be_export(libbe_handle_t *, char *, int fd);
int be_import(libbe_handle_t *, char *, int fd);
+int be_add_child(libbe_handle_t *, char *, bool);
+
#endif /* _LIBBE_H */
Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_access.c
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be_access.c Mon Sep 4 10:08:42 2017 (r326783)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be_access.c Mon Sep 4 13:22:23 2017 (r326784)
@@ -33,21 +33,24 @@
* usage
*/
int
-be_mount(libbe_handle_t *lbh, char *bootenv, char *mountpoint, int flags)
+be_mount(libbe_handle_t *lbh, char *bootenv, char *mountpoint, int flags,
+ char *result_loc)
{
char be[BE_MAXPATHLEN];
+ char mnt_temp[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 (!be_exists(lbh, bootenv)) {
+ return (set_error(lbh, BE_ERR_NOENT));
+ }
if (is_mounted(lbh->lzh, be, &path)) {
return (set_error(lbh, BE_ERR_MOUNTED));
@@ -56,15 +59,27 @@
mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0;
+ if (mountpoint == NULL) {
+ strcpy(mnt_temp, "/tmp/be_mount.XXXX");
+ if (mkdtemp(mnt_temp) == NULL) {
+ // TODO: create error for this
+ return (set_error(lbh, BE_ERR_UNKNOWN));
+ }
+ }
+
char opt = '\0';
- if (err = zmount(be, mountpoint, mntflags, MNTTYPE_ZFS,
- NULL, 0, &opt, 1)) {
+ if (err = zmount(be, (mountpoint == NULL) ? mnt_temp : 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));
+ if (result_loc != NULL) {
+ strcpy(result_loc, mountpoint == NULL ? mnt_temp : mountpoint);
+ }
+
+ return (BE_ERR_SUCCESS);
}
Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_info.c
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be_info.c Mon Sep 4 10:08:42 2017 (r326783)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be_info.c Mon Sep 4 13:22:23 2017 (r326784)
@@ -235,6 +235,11 @@
bool
be_exists(libbe_handle_t *lbh, char *be)
{
- // TODO
- return (true);
+ char buf[BE_MAXPATHLEN];
+
+ be_root_concat(lbh, be, buf);
+
+ // TODO: check mountpoint prop and see if its /, AND that result with below
+ // expression
+ return (zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_DATASET));
}
Modified: soc2017/kneitinger/libbe-head/lib/libbe/libbe.3
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/libbe.3 Mon Sep 4 10:08:42 2017 (r326783)
+++ soc2017/kneitinger/libbe-head/lib/libbe/libbe.3 Mon Sep 4 13:22:23 2017 (r326784)
@@ -0,0 +1,192 @@
+.\"
+.\" Copyright (c) 2017 Kyle 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 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.
+.\"
+.\" This manual page is based on the mp(3X) manual page from Sun Release
+.\" 4.1, dated 7 September 1989. It's an old, crufty, and relatively ugly
+.\" manual page, but it does document what appears to be the "traditional"
+.\" libmp interface.
+.\"
+.\" $FreeBSD: soc2017/kneitinger/libbe-head/lib/libmp/libmp.3 189135 2009-02-26 21:43:15Z ed $
+.\"
+.Dd August 28, 2017
+.Dt LIBBE 3
+.Os
+.Sh NAME
+.Nm libbe
+.Nd library for creating, destroying and modifying ZFS boot environments.
+.Sh SYNOPSIS
+.In be.h
+.Pp
+Function prototypes are given in the main body of the text.
+.Pp
+Applications using this interface must be linked with
+.Fl l Ns Ar be
+.Sh DESCRIPTION
+.Pp
+.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.
+.\" TODO: describe break on err functionality
+.Pp
+.Ft "libbe_handle_t *" Ns
+.Fn libbe_init "void" ;
+.Pp
+.Ft void
+.Fn libbe_close "libbe_handle_t *" ;
+.Pp
+.Ft "const char *" Ns
+.Fn be_active_name "libbe_handle_t *" ;
+.Pp
+.Ft "const char *" Ns
+.Fn be_active_path "libbe_handle_t *" ;
+.Pp
+.Ft "const char *" Ns
+.Fn be_root_path "libbe_handle_t *" ;
+.Pp
+.Ft "nvlist_t *" Ns
+.Fn libbe_handle_t "libbe_handle_t " ;
+.Pp
+.Ft int
+.Fn be_create "libbe_handle_t *, char *" ;
+.Pp
+.Ft int
+.Fn be_create_from_existing "libbe_handle_t *, char *, char *" ;
+.Pp
+.Ft int
+.Fn be_rename "libbe_handle_t *, char *, char *" ;
+.Pp
+.\" TODO: Write up of destroy options
+.\" typedef enum {
+.\" BE_DESTROY_FORCE = 1 << 0,
+.\" } be_destroy_opt_t;
+.Ft int
+.Fn be_destroy "libbe_handle_t *, char *, int" ;
+.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 *, char *, char *, int" ;
+.Pp
+.Ft int
+.Fn be_unmount "libbe_handle_t *, char *, int" ;
+.Pp
+.Ft int
+.Fn libbe_errno "libbe_handle_t *" ;
+.Pp
+.Ft "const char *" Ns
+.Fn libbe_error_description "libbe_handle_t *" ;
+.Pp
+.Ft void
+.Fn libbe_print_on_error "libbe_handle_t *, bool" ;
+.Pp
+.Ft int
+.Fn be_root_concat "libbe_handle_t *, char *, char *" ;
+.Pp
+.Ft int
+.Fn be_validate_name "libbe_handle_t *, char *" ;
+.Pp
+.Ft int
+.Fn be_validate_snap "libbe_handle_t *, char *" ;
+.Pp
+.Ft bool
+.Fn be_exists "libbe_handle_t *, char *" ;
+.Pp
+.Ft int
+.Fn be_export "libbe_handle_t *, char *, int fd" ;
+.Pp
+.Ft int
+.Fn be_import "libbe_handle_t *, char *, int fd" ;
+.Pp
+.Ft int
+.Fn be_add_child "libbe_handle_t *, char *, bool" ;
+.Pp
+.\" .Ft void
+.\" .Fn mp_mfree "MINT *mp" ;
+.\" .Bd -ragged -offset indent
+.\" .Fn mp_itom
+.\" returns an
+.\" .Vt MINT
+.\" with the value of
+.\" .Fa n .
+.\" .Fn mp_xtom
+.\" returns an
+.\" .Vt MINT
+.\" with the value of
+.\" .Fa s ,
+.\" which is treated to be in hexadecimal.
+.\" The return values from
+.\" .Fn mp_itom
+.\" and
+.\" .Fn mp_xtom
+.\" must be released with
+.\" .Fn mp_mfree
+.\" when they are no longer needed.
+.\" .Fn mp_mtox
+.\" returns a null-terminated hexadecimal string having the value of
+.\" .Fa mp ;
+.\" its return value must be released with
+.\" .Fn free
+.\" .Pq Xr free 3
+.\" when it is no longer needed.
+.\" .Ed
+.\" .Pp
+.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_PATHLEN,
+BE_ERR_INVORIGIN,
+BE_ERR_NOORIGIN,
+BE_ERR_MOUNTED,
+BE_ERR_NOMOUNT,
+BE_ERR_ZFSOPEN,
+BE_ERR_ZFSCLONE,
+BE_ERR_UNKNOWN
+.Ed
+.Sh SEE ALSO
+.Xr be 1 ,
+.Sh HISTORY
+.Nm
+and it's corresponding command,
+.Xr be 3 ,
+were written as a 2017 Google Summer of Code project with Allan Jude serving
+as a mentor.
+.\" TODO: update when implementation complete.
+.\" .Sh BUGS
+
Modified: soc2017/kneitinger/libbe-head/sbin/be/be.c
==============================================================================
--- soc2017/kneitinger/libbe-head/sbin/be/be.c Mon Sep 4 10:08:42 2017 (r326783)
+++ soc2017/kneitinger/libbe-head/sbin/be/be.c Mon Sep 4 13:22:23 2017 (r326784)
@@ -26,6 +26,10 @@
* SUCH DAMAGE.
*/
+#include <sys/param.h>
+#include <sys/jail.h>
+#include <sys/mount.h>
+#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -40,6 +44,7 @@
static int be_cmd_destroy(int argc, char *argv[]);
static int be_cmd_export(int argc, char *argv[]);
static int be_cmd_import(int argc, char *argv[]);
+static int be_cmd_init(int argc, char *argv[]);
static int be_cmd_jail(int argc, char *argv[]);
static int be_cmd_list(int argc, char *argv[]);
static int be_cmd_mount(int argc, char *argv[]);
@@ -57,12 +62,13 @@
fprintf(fp,
"usage:\tbe ( -h | -? | subcommand [args...] )\n"
"\tbe activate [-t] beName\n"
- "\tbe create [-r] [-e nonActiveBe | -e beName at snapshot] beName\n"
- "\tbe create [-r] beName at snapshot\n"
+ "\tbe create [-e nonActiveBe | -e beName at snapshot] beName\n"
+ "\tbe create beName at snapshot\n"
"\tbe destroy [-F] beName | beName at snapshot⟩\n"
"\tbe export sourceBe\n"
"\tbe import targetBe\n"
- "\tbe jail ⟨jailID | jailName⟩ bootenv\n"
+ "\tbe init (path)*\n"
+ "\tbe jail bootenv\n"
"\tbe list [-a] [-D] [-H] [-s]\n"
"\tbe mount beName [mountpoint]\n"
"\tbe rename origBeName newBeName\n"
@@ -84,17 +90,18 @@
static struct command_map_entry command_map[] =
{
- { "activate", be_cmd_activate },
- { "create", be_cmd_create },
- { "destroy", be_cmd_destroy },
- { "export", be_cmd_export },
- { "import", be_cmd_import },
- { "jail", be_cmd_jail },
- { "list", be_cmd_list },
- { "mount", be_cmd_mount },
- { "rename", be_cmd_rename },
- { "unjail", be_cmd_unjail },
- { "unmount", be_cmd_unmount },
+ { "activate", be_cmd_activate },
+ { "create", be_cmd_create },
+ { "destroy", be_cmd_destroy },
+ { "export", be_cmd_export },
+ { "import", be_cmd_import },
+ { "init", be_cmd_init },
+ { "jail", be_cmd_jail },
+ { "list", be_cmd_list },
+ { "mount", be_cmd_mount },
+ { "rename", be_cmd_rename },
+ { "unjail", be_cmd_unjail },
+ { "unmount", be_cmd_unmount },
};
static int
@@ -116,7 +123,7 @@
static int
be_cmd_activate(int argc, char *argv[])
{
- int opt;
+ int err, opt;
bool temp;
char *bootenv;
@@ -141,14 +148,26 @@
return (usage(false));
}
- bootenv = argv[0];
/* activate logic goes here */
+ if ((err = be_activate(be, argv[0], temp)) != 0) {
+ // 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]);
+ }
- return (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
be_cmd_create(int argc, char *argv[])
{
@@ -159,14 +178,11 @@
existing = NULL;
recursive = false;
- while ((opt = getopt(argc, argv, "re:")) != -1) {
+ while ((opt = getopt(argc, argv, "e:")) != -1) {
switch (opt) {
case 'e':
existing = optarg;
break;
- case 'r':
- recursive = true;
- break;
default:
fprintf(stderr, "be create: unknown option '-%c'\n",
optopt);
@@ -186,8 +202,12 @@
if (existing != NULL) {
- err = be_create_from_existing(be, bootenv, existing);
- // TODO: look at err and print useful message
+ if (strchr(existing, '@') != NULL) {
+ err =
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-soc-all
mailing list