#include "smbd/smbd.h"
#include "lib/util/tevent_ntstatus.h"
-#define SHADOW_COPY_PREFIX "@GMT-" /* vfs_shadow_copy format */
-#define SHADOW_COPY_PATH_FORMAT "@GMT-%Y.%m.%d-%H.%M.%S"
+/* include common @GMT token filter code */
+#include "vfs_gmt_tok_common.c"
+
#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"
return NT_STATUS_OK;
}
+static NTSTATUS snapper_list_snaps_at_time_pack(const char *snapper_conf,
+ time_t time_lower,
+ time_t time_upper,
+ DBusMessage **req_msg_out)
+{
+ DBusMessage *msg;
+ DBusMessageIter args;
+
+ msg = dbus_message_new_method_call("org.opensuse.Snapper",
+ "/org/opensuse/Snapper",
+ "org.opensuse.Snapper",
+ "ListSnapshotsAtTime");
+ if (msg == NULL) {
+ DEBUG(0, ("failed to create list snaps message\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ dbus_message_iter_init_append(msg, &args);
+ if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING,
+ &snapper_conf)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT64,
+ &time_lower)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT64,
+ &time_upper)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ *req_msg_out = msg;
+
+ return NT_STATUS_OK;
+}
+/* no snapper_list_snaps_at_time_unpack, use snapper_list_snaps_unpack */
+
/*
* Determine the snapper snapshot id given a path.
* Ideally this should be determined via a lookup.
return -1;
}
+static NTSTATUS snapper_get_snap_at_time_call(TALLOC_CTX *mem_ctx,
+ DBusConnection *dconn,
+ const char *conf_name,
+ const char *base_path,
+ time_t snaptime,
+ char **snap_path_out)
+{
+ NTSTATUS status;
+ DBusMessage *req_msg;
+ DBusMessage *rsp_msg;
+ uint32_t num_snaps;
+ struct snapper_snap *snaps;
+ char *snap_path;
+
+ status = snapper_list_snaps_at_time_pack(conf_name,
+ snaptime,
+ snaptime,
+ &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_list_snaps_unpack(mem_ctx, rsp_msg,
+ &num_snaps, &snaps);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_rsp_free;
+ }
+
+ if (num_snaps == 0) {
+ DEBUG(2, ("no snapshots found with time: %lu\n", snaptime));
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto err_snap_array_free;
+ } else if (num_snaps > 0) {
+ DEBUG(2, ("got %u snapshots for single time %lu, using top\n",
+ num_snaps, snaptime));
+ }
+
+ status = snapper_snap_id_to_path(mem_ctx, base_path, snaps[0].id,
+ &snap_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_snap_array_free;
+ }
+
+ snapper_snap_array_free(num_snaps, snaps);
+ dbus_message_unref(rsp_msg);
+ dbus_message_unref(req_msg);
+
+ *snap_path_out = snap_path;
+
+ return NT_STATUS_OK;
+
+err_snap_array_free:
+ snapper_snap_array_free(num_snaps, snaps);
+err_rsp_free:
+ dbus_message_unref(rsp_msg);
+err_req_free:
+ dbus_message_unref(req_msg);
+err_out:
+ return status;
+}
+
+/* callout for vfs_gmt_tok_common.c */
+static char *gmt_tok_insert_string(TALLOC_CTX *mem_ctx,
+ struct vfs_handle_struct *handle,
+ time_t snap_time)
+{
+ DBusConnection *dconn;
+ NTSTATUS status;
+ char *conf_name;
+ char *base_path;
+ char *snap_path;
+ char *snap_path_nobase;
+
+ dconn = snapper_dbus_conn();
+ if (dconn == NULL) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto err_out;
+ }
+
+ if (handle->conn->connectpath == NULL) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto err_conn_free;
+ }
+
+ status = snapper_get_conf_call(mem_ctx, dconn,
+ handle->conn->connectpath,
+ &conf_name,
+ &base_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_conn_free;
+ }
+
+ status = snapper_get_snap_at_time_call(mem_ctx, dconn,
+ conf_name, base_path, snap_time,
+ &snap_path);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err_conf_name_free;
+ }
+
+ /* strip the base path from the snap path for return */
+ if (strncmp(snap_path, base_path, strlen(base_path)) != 0) {
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto err_snap_path_free;
+ }
+
+ snap_path_nobase = talloc_strdup(mem_ctx, snap_path + strlen(base_path));
+ if (snap_path_nobase == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto err_snap_path_free;
+ }
+
+ talloc_free(snap_path);
+ talloc_free(conf_name);
+ talloc_free(base_path);
+ dbus_connection_unref(dconn);
+
+ return snap_path_nobase;
+
+err_snap_path_free:
+ talloc_free(snap_path);
+err_conf_name_free:
+ talloc_free(conf_name);
+ talloc_free(base_path);
+err_conn_free:
+ dbus_connection_unref(dconn);
+err_out:
+ return NULL;
+}
+
static struct vfs_fn_pointers snapper_fns = {
.snap_check_path_fn = snapper_snap_check_path,
.snap_create_send_fn = snapper_snap_create_send,
.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,
+ /* use common @GMT token wrapper fns */
+ .opendir_fn = gmt_tok_opendir,
+ .rename_fn = gmt_tok_rename,
+ .link_fn = gmt_tok_link,
+ .symlink_fn = gmt_tok_symlink,
+ .stat_fn = gmt_tok_stat,
+ .lstat_fn = gmt_tok_lstat,
+ .fstat_fn = gmt_tok_fstat,
+ .open_fn = gmt_tok_open,
+ .unlink_fn = gmt_tok_unlink,
+ .chmod_fn = gmt_tok_chmod,
+ .chown_fn = gmt_tok_chown,
+ .chdir_fn = gmt_tok_chdir,
+ .ntimes_fn = gmt_tok_ntimes,
+ .readlink_fn = gmt_tok_readlink,
+ .mknod_fn = gmt_tok_mknod,
+ .realpath_fn = gmt_tok_realpath,
+ .get_nt_acl_fn = gmt_tok_get_nt_acl,
+ .fget_nt_acl_fn = gmt_tok_fget_nt_acl,
+ .mkdir_fn = gmt_tok_mkdir,
+ .rmdir_fn = gmt_tok_rmdir,
+ .getxattr_fn = gmt_tok_getxattr,
+ .listxattr_fn = gmt_tok_listxattr,
+ .removexattr_fn = gmt_tok_removexattr,
+ .setxattr_fn = gmt_tok_setxattr,
+ .chmod_acl_fn = gmt_tok_chmod_acl,
+ .chflags_fn = gmt_tok_chflags,
+ .get_real_filename_fn = gmt_tok_get_real_filename,
};
NTSTATUS vfs_snapper_init(void);