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