aboutsummaryrefslogtreecommitdiff
path: root/lib/libbe/be.c
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2019-10-16 14:43:05 +0000
committerKyle Evans <kevans@FreeBSD.org>2019-10-16 14:43:05 +0000
commit455d8009b468669020eb5dd2a209e9094eeda503 (patch)
treead4f29f660def69020a62779b010ea47c3640636 /lib/libbe/be.c
parente3df342a32debf2cc8bdc20582afd8adeec35775 (diff)
downloadsrc-455d8009b468669020eb5dd2a209e9094eeda503.tar.gz
src-455d8009b468669020eb5dd2a209e9094eeda503.zip
libbe(3): add needed bits for be_destroy to auto-destroy some origins
New BEs can be created from either an existing snapshot or an existing BE. If an existing BE is chosen (either implicitly via 'bectl create' or explicitly via 'bectl create -e foo bar', for instance), then bectl will create a snapshot of the current BE or "foo" with be_snapshot, with a name formatted like: strftime("%F-%T") and a serial added to it. This commit adds the needed bits for libbe or consumers to determine if a snapshot names matches one of these auto-created snapshots (with some light validation of the date/time/serial), and also a be_destroy flag to specify that the origin should be automatically destroyed if possible. A future commit to bectl will specify BE_DESTROY_AUTOORIGIN by default so we clean up the origin in the most common case, non-user-managed snapshots.
Notes
Notes: svn path=/head/; revision=353644
Diffstat (limited to 'lib/libbe/be.c')
-rw-r--r--lib/libbe/be.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/lib/libbe/be.c b/lib/libbe/be.c
index 249fa2f3361c..fb27d7a2855b 100644
--- a/lib/libbe/be.c
+++ b/lib/libbe/be.c
@@ -229,6 +229,7 @@ be_destroy_cb(zfs_handle_t *zfs_hdl, void *data)
return (0);
}
+#define BE_DESTROY_NEEDORIGIN (BE_DESTROY_ORIGIN | BE_DESTROY_AUTOORIGIN)
/*
* Destroy the boot environment or snapshot specified by the name
* parameter. Options are or'd together with the possible values:
@@ -264,11 +265,24 @@ be_destroy(libbe_handle_t *lbh, const char *name, int options)
if (fs == NULL)
return (set_error(lbh, BE_ERR_ZFSOPEN));
- if ((options & BE_DESTROY_ORIGIN) != 0 &&
+ if ((options & BE_DESTROY_NEEDORIGIN) != 0 &&
zfs_prop_get(fs, ZFS_PROP_ORIGIN, origin, sizeof(origin),
NULL, NULL, 0, 1) != 0)
return (set_error(lbh, BE_ERR_NOORIGIN));
+ /*
+ * If the caller wants auto-origin destruction and the origin
+ * name matches one of our automatically created snapshot names
+ * (i.e. strftime("%F-%T") with a serial at the end), then
+ * we'll set the DESTROY_ORIGIN flag and nuke it
+ * be_is_auto_snapshot_name is exported from libbe(3) so that
+ * the caller can determine if it needs to warn about the origin
+ * not being destroyed or not.
+ */
+ if ((options & BE_DESTROY_AUTOORIGIN) != 0 &&
+ be_is_auto_snapshot_name(lbh, origin))
+ options |= BE_DESTROY_ORIGIN;
+
/* Don't destroy a mounted dataset unless force is specified */
if ((mounted = zfs_is_mounted(fs, NULL)) != 0) {
if (force) {
@@ -343,6 +357,25 @@ be_setup_snapshot_name(libbe_handle_t *lbh, char *buf, size_t buflen)
}
}
+bool
+be_is_auto_snapshot_name(libbe_handle_t *lbh, const char *name)
+{
+ const char *snap;
+ int day, hour, minute, month, second, serial, year;
+
+ if ((snap = strchr(name, '@')) == NULL)
+ return (false);
+ ++snap;
+ /* We'll grab the individual components and do some light validation. */
+ if (sscanf(snap, "%d-%d-%d-%d:%d:%d-%d", &year, &month, &day, &hour,
+ &minute, &second, &serial) != 7)
+ return (false);
+ return (year >= 1970) && (month >= 1 && month <= 12) &&
+ (day >= 1 && day <= 31) && (hour >= 0 && hour <= 23) &&
+ (minute >= 0 && minute <= 59) && (second >= 0 && second <= 60) &&
+ serial >= 0;
+}
+
int
be_snapshot(libbe_handle_t *lbh, const char *source, const char *snap_name,
bool recursive, char *result)