socsvn commit: r324259 - soc2017/kneitinger/libbe-head/lib/libbe

kneitinger at FreeBSD.org kneitinger at FreeBSD.org
Tue Jul 4 10:55:04 UTC 2017


Author: kneitinger
Date: Tue Jul  4 10:55:02 2017
New Revision: 324259
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=324259

Log:
  libbe(3): add be_create function
  

Modified:
  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_info.c

Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.c
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be.c	Tue Jul  4 07:07:08 2017	(r324258)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be.c	Tue Jul  4 10:55:02 2017	(r324259)
@@ -26,11 +26,12 @@
  * SUCH DAMAGE.
  */
 
-#include <errno.h>
+#include <ctype.h>
 #include <kenv.h>
 #include <libgen.h>
 #include <stdio.h>
 #include <sys/types.h>
+#include <time.h>
 
 #include "be.h"
 #include "be_impl.h"
@@ -55,9 +56,6 @@
 		return (NULL);
 	}
 
-	lbh->print_on_err = true;
-
-
 	/* Obtain path to active boot environment */
 	if ((kenv(KENV_GET, "zfs_be_active", buf, MAXPATHLEN)) == -1) {
 		libzfs_fini(lbh->lzh);
@@ -77,7 +75,6 @@
 		return (NULL);
 	}
 
-
 	/* Obtain path to boot environment root */
 	if ((kenv(KENV_GET, "zfs_be_root", buf, MAXPATHLEN)) == -1) {
 		zfs_close(lbh->be_active);
@@ -123,7 +120,6 @@
  * Destroy the boot environment 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, char *name, int options)
@@ -138,26 +134,126 @@
 
 	snprintf(path, MAXPATHLEN, "%s/%s", zfs_get_name(lbh->be_root), name);
 
-	if(!zfs_dataset_exists(lbh->lzh, path, ZFS_TYPE_DATASET)) {
+	if (!zfs_dataset_exists(lbh->lzh, path, ZFS_TYPE_DATASET)) {
 		err = set_error(lbh, BE_ERR_NOENT);
 		return (err);
 	}
 
 	fs = zfs_open(lbh->lzh, p, ZFS_TYPE_DATASET);
 
-	if(strcmp(path, zfs_get_name(lbh->be_active)) != 0) {
+	if (strcmp(path, zfs_get_name(lbh->be_active)) != 0) {
 		err = set_error(lbh, BE_ERR_DESTROYACT);
 		return (err);
 	}
 
-
-	//check mounted
-	if((mounted = zfs_is_mounted(fs, &p)) && !(force)) {
+	if ((mounted = zfs_is_mounted(fs, &p)) && !(force)) {
 		err = set_error(lbh, BE_ERR_DESTROYMNT);
 		return (err);
 	}
 
-	// check dependants
+	// TODO: check dependants
 
 	return (0);
 }
+
+
+/*
+ * Create the boot environment specified by the name parameter
+ */
+int
+be_create(libbe_handle_t *lbh, char *name)
+{
+	int err, pos;
+	char be_path[MAXPATHLEN];
+	char snap_name[MAXPATHLEN];
+	time_t rawtime;
+	zfs_handle_t *snap_hdl;
+
+	if (!(be_valid_name(lbh, name))) {
+		err = set_error(lbh, BE_ERR_INVALIDNAME);
+		return (err);
+	}
+
+	if (err = be_root_concat(lbh, name, be_path)) {
+		return (err);
+	}
+
+	pos = snprintf(be_path, MAXPATHLEN, "%s/%s", be_root_path(lbh), name);
+
+	if ((pos < 0) || (pos >= 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);
+	}
+
+
+	time(&rawtime);
+	pos = snprintf(snap_name, MAXPATHLEN, "%s", be_active_path(lbh));
+	strftime(snap_name + pos, MAXPATHLEN - pos,
+	    "@%F-%T", localtime(&rawtime));
+
+
+	// TODO: should any props be in the last arg (nvlist)?
+	if (err = zfs_snapshot(lbh->lzh, snap_name, true, NULL)) {
+		// TODO: switch on err to determine correct BE_ERR_* to return
+		return (-1);
+	}
+
+	snap_hdl = zfs_open(lbh->lzh, snap_name, ZFS_TYPE_SNAPSHOT);
+
+	// TODO: should any props be in the last arg (nvlist)?
+	if (err = zfs_clone(snap_hdl, be_path, NULL)) {
+		// TODO: switch on err to determine correct BE_ERR_* to return
+		return (-1);
+	}
+
+	return (err);
+}
+
+
+/*
+ * Appends the name argument on the root boot environment path and copies the
+ * resulting string into the result buffer. Returns 0 upon success and
+ * BE_ERR_PATHLEN if the resulting path is longer than MAXPATHLEN
+ */
+int
+be_root_concat(libbe_handle_t *lbh, char *name, char *result)
+{
+	const char *root = be_root_path(lbh);
+	int n = snprintf(result, MAXPATHLEN, "%s/%s", root, name);
+
+	if ((n >= 0) && (n < MAXPATHLEN)) {
+		return (BE_ERR_SUCCESS);
+	}
+
+	// TODO: reconsider if this, or the caller, should set_error.
+	return (set_error(lbh, BE_ERR_PATHLEN));
+}
+
+
+/*
+ * Verifies the validity of a boot environment name (A-Za-z0-9-_.,). Returns 0
+ * if the name is valid, otherwise, returns the position of the first offending
+ * character
+ */
+int
+be_valid_name(libbe_handle_t *lbh, char *name)
+{
+	for (int i = 0; *name; i++) {
+		char c = *(name++);
+		// TODO: beadm allows commas...they seem like a bad idea though
+		if (isalnum(c) || (c == '-') || (c == '_') || (c == '.') ||
+		    (c == ',')) {
+			// if lbh is not null, the offending char could be
+			// logged into some field for helpful error reporting
+			// also, should the set_error happen here, or in the
+			// caller (probably caller)??
+			return (i);
+		}
+	}
+
+	return (BE_ERR_SUCCESS);
+}

Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.h
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be.h	Tue Jul  4 07:07:08 2017	(r324258)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be.h	Tue Jul  4 10:55:02 2017	(r324259)
@@ -35,14 +35,15 @@
 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,      /* cannot destroy active boot env */
-        BE_ERR_UNKNOWN,         /* unknown 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_PATHLEN,         /* provided name exceeds maximum length limit */
+	BE_ERR_UNKNOWN,         /* unknown error */
 } be_error_t;
 
 
@@ -51,9 +52,9 @@
 void libbe_close(libbe_handle_t *);
 
 /* Bootenv information functions: be_info.c */
-const char *be_get_active_name(libbe_handle_t *);
-const char *be_get_active_path(libbe_handle_t *);
-const char *be_get_root_path(libbe_handle_t *);
+const char *be_active_name(libbe_handle_t *);
+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 *);
 
 /* Bootenv creation functions */
@@ -65,7 +66,7 @@
 
 /* Bootenv removal functions */
 
-#define BE_DESTROY_FORCE 1
+#define BE_DESTROY_FORCE    1
 
 int be_destroy(libbe_handle_t *, char *, int);
 
@@ -81,4 +82,8 @@
 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 *, char *, char *);
+int be_valid_name(libbe_handle_t *, char *);
+
 #endif  /* _LIBBE_H */

Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_error.c
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be_error.c	Tue Jul  4 07:07:08 2017	(r324258)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be_error.c	Tue Jul  4 10:55:02 2017	(r324259)
@@ -61,6 +61,9 @@
 	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_UNKNOWN:
 		return ("unknown error");
 
@@ -70,6 +73,7 @@
 	}
 }
 
+
 void
 libbe_print_on_error(libbe_handle_t *lbh, bool val)
 {
@@ -77,6 +81,7 @@
 	libzfs_print_on_error(lbh->lzh, val);
 }
 
+
 int
 set_error(libbe_handle_t *lbh, be_error_t err)
 {
@@ -84,7 +89,7 @@
 
 	lbh->error = err;
 
-	if(lbh->print_on_err) {
+	if (lbh->print_on_err) {
 		fprintf(stderr, "%s\n", libbe_error_description(lbh));
 	}
 

Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_info.c
==============================================================================
--- soc2017/kneitinger/libbe-head/lib/libbe/be_info.c	Tue Jul  4 07:07:08 2017	(r324258)
+++ soc2017/kneitinger/libbe-head/lib/libbe/be_info.c	Tue Jul  4 10:55:02 2017	(r324259)
@@ -35,7 +35,7 @@
  * Returns the name of the active boot environment
  */
 const char *
-be_get_active_name(libbe_handle_t *lbh)
+be_active_name(libbe_handle_t *lbh)
 {
 	const char *full_path = zfs_get_name(lbh->be_active);
 
@@ -47,7 +47,7 @@
  * Returns full path of the active boot environment
  */
 const char *
-be_get_active_path(libbe_handle_t *lbh)
+be_active_path(libbe_handle_t *lbh)
 {
 	return (zfs_get_name(lbh->be_active));
 }
@@ -57,7 +57,7 @@
  * Returns the path of the boot environment root dataset
  */
 const char *
-be_get_root_path(libbe_handle_t *lbh)
+be_root_path(libbe_handle_t *lbh)
 {
 	return (zfs_get_name(lbh->be_root));
 }
@@ -86,8 +86,8 @@
 {
 	/*
 	 * TODO:
-	 * 	some system for defining constants for the nvlist keys
-	 * 	error checking
+	 *      some system for defining constants for the nvlist keys
+	 *      error checking
 	 */
 
 	boolean_t mounted, active, nextboot;
@@ -128,7 +128,7 @@
 	}
 
 	nvlist_add_boolean_value(props, "active",
-	    (strcmp(be_get_active_path(lbh), dataset) == 0));
+	    (strcmp(be_active_path(lbh), dataset) == 0));
 
 	if ((zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512,
 	    NULL, NULL, 0, 1)) == 0) {
@@ -167,7 +167,7 @@
  * Updates the properties of each bootenv in the libbe handle
  * TODO: rename to be_proplist_update
  * TODO: ensure that this is always consistent (run after adds, deletes,
- * 	 renames,etc
+ *       renames,etc
  */
 int
 prop_list_builder(libbe_handle_t *lbh)
@@ -188,6 +188,7 @@
 	return (0);
 }
 
+
 /*
  * Frees property list and its children
  */
@@ -197,18 +198,18 @@
 	nvlist_t *be_list;
 	nvlist_t *prop_list;
 
-	if((be_list = lbh->list) == 0) {
+	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) {
+	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) {
+	while ((be_pair = nvlist_next_nvpair(be_list, be_pair)) != NULL) {
+		if (nvpair_value_nvlist(be_pair, &prop_list) == 0) {
 			nvlist_free(prop_list);
 		}
 	}


More information about the svn-soc-all mailing list