#define SNAPPER_SIG_LIST_SNAPS_RSP "a(uqutussa{ss})"
#define SNAPPER_SIG_LIST_CONFS_RSP "a(ssa{ss})"
#define SNAPPER_SIG_CREATE_SNAP_RSP "u"
+#define SNAPPER_SIG_DEL_SNAPS_RSP ""
#define SNAPPER_SIG_STRING_DICT "{ss}"
struct snapper_dict {
return NT_STATUS_OK;
}
+static NTSTATUS snapper_del_snap_pack(const char *snapper_conf,
+ uint32_t snap_id,
+ DBusMessage **req_msg_out)
+{
+ DBusMessage *msg;
+ DBusMessageIter args;
+ DBusMessageIter array_iter;
+ bool ok;
+
+ msg = dbus_message_new_method_call("org.opensuse.Snapper",
+ "/org/opensuse/Snapper",
+ "org.opensuse.Snapper",
+ "DeleteSnapshots");
+ if (msg == NULL) {
+ DEBUG(0, ("failed to create req msg\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* append arguments */
+ dbus_message_iter_init_append(msg, &args);
+ ok = dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,
+ &snapper_conf);
+ if (!ok) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok = dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_UINT32_AS_STRING,
+ &array_iter);
+ if (!ok) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok = dbus_message_iter_append_basic(&array_iter,
+ DBUS_TYPE_UINT32,
+ &snap_id);
+ if (!ok) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dbus_message_iter_close_container(&args, &array_iter);
+ *req_msg_out = msg;
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS snapper_del_snap_unpack(DBusConnection *conn,
+ DBusMessage *rsp_msg)
+{
+ int msg_type;
+ const char *sig;
+
+ msg_type = dbus_message_get_type(rsp_msg);
+ if (msg_type == DBUS_MESSAGE_TYPE_ERROR) {
+ DEBUG(0, ("del snap error response: %s\n",
+ dbus_message_get_error_name(rsp_msg)));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (msg_type != DBUS_MESSAGE_TYPE_METHOD_RETURN) {
+ DEBUG(0, ("unexpected del snap ret type: %d\n",
+ msg_type));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ sig = dbus_message_get_signature(rsp_msg);
+ if ((sig == NULL)
+ || (strcmp(sig, SNAPPER_SIG_DEL_SNAPS_RSP) != 0)) {
+ DEBUG(0, ("bad create snap response sig: %s, expected: %s\n",
+ (sig ? sig : "NULL"), SNAPPER_SIG_DEL_SNAPS_RSP));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* no parameters in response */
+
+ return NT_STATUS_OK;
+}
+
static NTSTATUS snapper_get_conf_call(TALLOC_CTX *mem_ctx,
DBusConnection *dconn,
const char *path,
* Assume snapshot exists in the .snapshots subdir of the base.
* TODO lookup via GetSnapshot
*/
- snap_path = talloc_asprintf(mem_ctx, "%s/%u", base_path, snap_id);
+ snap_path = talloc_asprintf(mem_ctx, "%s/.snapshots/%u", base_path, snap_id);
if (snap_path == NULL) {
status = NT_STATUS_NO_MEMORY;
goto err_rsp_free;
return NT_STATUS_OK;
}
+static NTSTATUS snapper_delete_snap_call(TALLOC_CTX *mem_ctx,
+ DBusConnection *dconn,
+ const char *conf_name,
+ uint32_t snap_id)
+{
+ NTSTATUS status;
+ DBusMessage *req_msg;
+ DBusMessage *rsp_msg;
+
+ status = snapper_del_snap_pack(conf_name, snap_id, &req_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_out;
+ }
+
+ status = snapper_dbus_msg_xchng(dconn, req_msg, &rsp_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_req_free;
+ }
+
+ status = snapper_del_snap_unpack(dconn, rsp_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_rsp_free;
+ }
+
+ dbus_message_unref(rsp_msg);
+ dbus_message_unref(req_msg);
+
+ DEBUG(6, ("deleted snapshot %u\n", snap_id));
+
+ return NT_STATUS_OK;
+
+err_rsp_free:
+ dbus_message_unref(rsp_msg);
+err_req_free:
+ dbus_message_unref(req_msg);
+err_out:
+ return status;
+}
+
+struct snapper_snap_delete_state {
+ char *conf_name;
+ char *base_path;
+ char *snap_path;
+ uint32_t snap_id;
+};
+
static struct tevent_req *snapper_snap_delete_send(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+ char *base_path,
char *snap_path)
{
struct tevent_req *req;
+ DBusConnection *dconn;
+ struct snapper_snap_delete_state *delete_state;
+ NTSTATUS status;
+ char *snap_id_str;
+ char *str_end;
- /* no state retained over delete, only the ntstatus in req */
- req = tevent_req_create(mem_ctx, NULL, NULL);
+ req = tevent_req_create(mem_ctx, &delete_state,
+ struct snapper_snap_delete_state);
if (req == NULL) {
return NULL;
}
- /* always fail for now */
- if (req) {
+ dconn = snapper_dbus_conn();
+ if (dconn == NULL) {
tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
return tevent_req_post(req, ev);
}
+ status = snapper_get_conf_call(delete_state, dconn, base_path,
+ &delete_state->conf_name,
+ &delete_state->base_path);
+ if (tevent_req_nterror(req, status)) {
+ dbus_connection_unref(dconn);
+ return tevent_req_post(req, ev);
+ }
+
+ /* TODO we should look this up by doing a list_snapshots */
+ snap_id_str = strrchr(snap_path, '/');
+ if (snap_id_str == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ dbus_connection_unref(dconn);
+ return tevent_req_post(req, ev);
+ }
+ snap_id_str++;
+ delete_state->snap_id = strtoul(snap_id_str, &str_end, 10);
+ if (snap_id_str == str_end) {
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ dbus_connection_unref(dconn);
+ return tevent_req_post(req, ev);
+ }
+
+ status = snapper_delete_snap_call(delete_state, dconn,
+ delete_state->conf_name,
+ delete_state->snap_id);
+ if (tevent_req_nterror(req, status)) {
+ dbus_connection_unref(dconn);
+ return tevent_req_post(req, ev);
+ }
+
+ dbus_connection_unref(dconn);
+
tevent_req_done(req);
return tevent_req_post(req, ev);
}