#include <dirent.h>
#include <libgen.h>
#include "includes.h"
+#include "include/ntioctl.h"
#include "system/filesys.h"
#include "smbd/smbd.h"
#include "lib/util/tevent_ntstatus.h"
}
static NTSTATUS snapper_list_snaps_unpack(TALLOC_CTX *mem_ctx,
- DBusConnection *dconn,
DBusMessage *rsp_msg,
uint32_t *num_snaps_out,
struct snapper_snap **snaps_out)
return NULL;
}
- /* become root for snapper dbus exchange */
- become_root();
dconn = snapper_dbus_conn();
if (dconn == NULL) {
- unbecome_root();
tevent_req_nterror(req, NT_STATUS_UNSUCCESSFUL);
return tevent_req_post(req, ev);
}
&create_state->base_path);
if (tevent_req_nterror(req, status)) {
dbus_connection_unref(dconn);
- unbecome_root();
return tevent_req_post(req, ev);
}
&create_state->snap_path);
if (tevent_req_nterror(req, status)) {
dbus_connection_unref(dconn);
- unbecome_root();
return tevent_req_post(req, ev);
}
dbus_connection_unref(dconn);
- unbecome_root();
tevent_req_done(req);
return tevent_req_post(req, ev);
return NT_STATUS_OK;
}
+/* sc_data used as parent talloc context for all labels */
+static int snapper_get_shadow_copy_data(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ struct shadow_copy_data *sc_data,
+ bool labels)
+{
+ DBusConnection *dconn;
+ TALLOC_CTX *tmp_ctx;
+ NTSTATUS status;
+ char *conf_name;
+ char *base_path;
+ DBusMessage *req_msg;
+ DBusMessage *rsp_msg;
+ uint32_t num_snaps;
+ struct snapper_snap *snaps;
+ uint32_t i;
+
+ tmp_ctx = talloc_new(sc_data);
+ if (tmp_ctx == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto err_out;
+ }
+
+ dconn = snapper_dbus_conn();
+ if (dconn == NULL) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto err_mem_ctx_free;
+ }
+
+ if (fsp->conn->connectpath == NULL) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto err_conn_free;
+ }
+
+ status = snapper_get_conf_call(tmp_ctx, dconn,
+ fsp->conn->connectpath,
+ &conf_name,
+ &base_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_conn_free;
+ }
+
+ status = snapper_list_snaps_pack(conf_name, &req_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_req_free;
+ }
+
+ status = snapper_dbus_msg_xchng(dconn, req_msg, &rsp_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_req_free;
+ }
+
+ status = snapper_list_snaps_unpack(tmp_ctx, rsp_msg,
+ &num_snaps, &snaps);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_rsp_free;
+ }
+ /* we should always get at least one snapshot (current) */
+ if (num_snaps == 0) {
+ DEBUG(0, ("zero snapshots in snap list response\n"));
+ goto err_rsp_free;
+ }
+
+ snapper_snap_array_print(num_snaps, snaps);
+
+ /* subtract 1, (current) snapshot is not returned */
+ sc_data->num_volumes = num_snaps - 1;
+ sc_data->labels = NULL;
+
+ if ((labels == false) || (sc_data->num_volumes == 0)) {
+ /* tokens need not be added to the labels array */
+ goto done;
+ }
+
+ sc_data->labels = talloc_array(sc_data, SHADOW_COPY_LABEL, num_snaps - 1);
+ if (sc_data->labels == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto err_rsp_free;
+ }
+
+ /* start at offset 1, skipping (current) */
+ for (i = 1; i < num_snaps; i++) {
+ char *lbl = sc_data->labels[i - 1];
+ struct tm gmt_snap_time;
+ struct tm *tm_ret;
+ size_t str_sz;
+
+ tm_ret = gmtime_r((time_t *)&snaps[i].time, &gmt_snap_time);
+ if (tm_ret == NULL) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto err_labels_free;
+ }
+ str_sz = strftime(lbl, sizeof(SHADOW_COPY_LABEL),
+ "@GMT-%Y.%m.%d-%H.%M.%S", &gmt_snap_time);
+ if (str_sz == 0) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto err_labels_free;
+ }
+ }
+
+done:
+ talloc_free(tmp_ctx);
+ dbus_message_unref(rsp_msg);
+ dbus_message_unref(req_msg);
+ dbus_connection_unref(dconn);
+
+ return 0;
+
+err_labels_free:
+ TALLOC_FREE(sc_data->labels);
+err_rsp_free:
+ dbus_message_unref(rsp_msg);
+err_req_free:
+ dbus_message_unref(req_msg);
+err_conn_free:
+ dbus_connection_unref(dconn);
+err_mem_ctx_free:
+ talloc_free(tmp_ctx);
+err_out:
+ /* all errors are collapsed to a -1 return code */
+ return -1;
+}
+
static struct vfs_fn_pointers snapper_fns = {
.snap_check_path_fn = snapper_snap_check_path,
.snap_create_send_fn = snapper_snap_create_send,
.snap_create_recv_fn = snapper_snap_create_recv,
.snap_delete_send_fn = snapper_snap_delete_send,
.snap_delete_recv_fn = snapper_snap_delete_recv,
+ .get_shadow_copy_data_fn = snapper_get_shadow_copy_data,
};
NTSTATUS vfs_snapper_init(void);