+int snapshot_create(Manager *m, const char *name, bool cleanup, Snapshot **_s) {
+ Iterator i;
+ Unit *other, *u = NULL;
+ char *n = NULL;
+ int r;
+ const char *k;
+
+ assert(m);
+ assert(_s);
+
+ if (name) {
+ if (!unit_name_is_valid(name))
+ return -EINVAL;
+
+ if (unit_name_to_type(name) != UNIT_SNAPSHOT)
+ return -EINVAL;
+
+ if (manager_get_unit(m, name))
+ return -EEXIST;
+
+ } else {
+
+ for (;;) {
+ if (asprintf(&n, "snapshot-%u.snapshot", ++ m->n_snapshots) < 0)
+ return -ENOMEM;
+
+ if (!manager_get_unit(m, n))
+ break;
+
+ free(n);
+ }
+
+ name = n;
+ }
+
+ r = manager_load_unit(m, name, NULL, &u);
+ free(n);
+
+ if (r < 0)
+ goto fail;
+
+ HASHMAP_FOREACH_KEY(other, k, m->units, i) {
+
+ if (UNIT_VTABLE(other)->no_snapshots)
+ continue;
+
+ if (k != other->meta.id)
+ continue;
+
+ if (UNIT_VTABLE(other)->check_snapshot)
+ if (!UNIT_VTABLE(other)->check_snapshot(other))
+ continue;
+
+ if (!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
+ continue;
+
+ if ((r = unit_add_dependency(u, UNIT_REQUIRES, other, true)) < 0)
+ goto fail;
+
+ if ((r = unit_add_dependency(u, UNIT_AFTER, other, true)) < 0)
+ goto fail;
+ }
+
+ SNAPSHOT(u)->cleanup = cleanup;
+ *_s = SNAPSHOT(u);
+
+ return 0;
+
+fail:
+ if (u)
+ unit_add_to_cleanup_queue(u);
+
+ return r;
+}
+
+void snapshot_remove(Snapshot *s) {
+ assert(s);
+
+ unit_add_to_cleanup_queue(UNIT(s));
+}
+
+static const char* const snapshot_state_table[_SNAPSHOT_STATE_MAX] = {
+ [SNAPSHOT_DEAD] = "dead",
+ [SNAPSHOT_ACTIVE] = "active"
+};
+
+DEFINE_STRING_TABLE_LOOKUP(snapshot_state, SnapshotState);
+