From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source3/modules/vfs_shell_snap.c | 201 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 source3/modules/vfs_shell_snap.c (limited to 'source3/modules/vfs_shell_snap.c') diff --git a/source3/modules/vfs_shell_snap.c b/source3/modules/vfs_shell_snap.c new file mode 100644 index 0000000..d1b7b8c --- /dev/null +++ b/source3/modules/vfs_shell_snap.c @@ -0,0 +1,201 @@ +/* + * Module for snapshot management using shell callouts + * + * Copyright (C) David Disseldorp 2013-2015 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "include/ntioctl.h" +#include "system/filesys.h" +#include "smbd/smbd.h" + +/* + * Check whether a path can be shadow copied. Return the base volume, allowing + * the caller to determine if multiple paths lie on the same base volume. + */ +static NTSTATUS shell_snap_check_path(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + const char *service_path, + char **base_volume) +{ + NTSTATUS status; + const char *cmd; + char *cmd_run; + int ret; + TALLOC_CTX *tmp_ctx; + + cmd = lp_parm_const_string(handle->conn->params->service, + "shell_snap", "check path command", ""); + if ((cmd == NULL) || (strlen(cmd) == 0)) { + DEBUG(0, + ("\"shell_snap:check path command\" not configured\n")); + status = NT_STATUS_NOT_SUPPORTED; + goto err_out; + } + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err_out; + } + + /* add service path argument */ + cmd_run = talloc_asprintf(tmp_ctx, "%s %s", cmd, service_path); + if (cmd_run == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err_tmp_free; + } + + ret = smbrun(cmd_run, NULL, NULL); + if (ret != 0) { + DEBUG(0, ("%s failed with %d\n", cmd_run, ret)); + status = NT_STATUS_NOT_SUPPORTED; + goto err_tmp_free; + } + + /* assume the service path is the base volume */ + *base_volume = talloc_strdup(mem_ctx, service_path); + if (*base_volume == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err_tmp_free; + } + status = NT_STATUS_OK; +err_tmp_free: + talloc_free(tmp_ctx); +err_out: + return status; +} + +static NTSTATUS shell_snap_create(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + const char *base_volume, + time_t *tstamp, + bool rw, + char **base_path, + char **snap_path) +{ + const char *cmd; + char *cmd_run; + char **qlines; + int numlines, ret; + int fd = -1; + TALLOC_CTX *tmp_ctx; + NTSTATUS status; + + cmd = lp_parm_const_string(handle->conn->params->service, + "shell_snap", "create command", ""); + if ((cmd == NULL) || (strlen(cmd) == 0)) { + DEBUG(1, ("\"shell_snap:create command\" not configured\n")); + status = NT_STATUS_NOT_SUPPORTED; + goto err_out; + } + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err_out; + } + + /* add base vol argument */ + cmd_run = talloc_asprintf(tmp_ctx, "%s %s", cmd, base_volume); + if (cmd_run == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err_tmp_free; + } + + ret = smbrun(cmd_run, &fd, NULL); + talloc_free(cmd_run); + if (ret != 0) { + if (fd != -1) { + close(fd); + } + status = NT_STATUS_UNSUCCESSFUL; + goto err_tmp_free; + } + + numlines = 0; + qlines = fd_lines_load(fd, &numlines, PATH_MAX + 1, tmp_ctx); + close(fd); + + /* script must return the snapshot path as a single line */ + if ((numlines == 0) || (qlines == NULL) || (qlines[0] == NULL)) { + status = NT_STATUS_UNSUCCESSFUL; + goto err_tmp_free; + } + + *base_path = talloc_strdup(mem_ctx, base_volume); + if (*base_path == NULL) { + status = NT_STATUS_NO_MEMORY; + goto err_tmp_free; + } + *snap_path = talloc_strdup(mem_ctx, qlines[0]); + if (*snap_path == NULL) { + status = NT_STATUS_NO_MEMORY; + talloc_free(*base_path); + goto err_tmp_free; + } + + status = NT_STATUS_OK; +err_tmp_free: + talloc_free(tmp_ctx); +err_out: + return status; +} + +static NTSTATUS shell_snap_delete(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + char *base_path, + char *snap_path) +{ + const char *cmd; + char *cmd_run; + int ret; + + cmd = lp_parm_const_string(handle->conn->params->service, + "shell_snap", "delete command", ""); + if ((cmd == NULL) || (strlen(cmd) == 0)) { + DEBUG(1, ("\"shell_snap:delete command\" not configured\n")); + return NT_STATUS_NOT_SUPPORTED; + } + + /* add base path and snap path arguments */ + cmd_run = talloc_asprintf(mem_ctx, "%s %s %s", + cmd, base_path, snap_path); + if (cmd_run == NULL) { + return NT_STATUS_NO_MEMORY; + } + + ret = smbrun(cmd_run, NULL, NULL); + talloc_free(cmd_run); + if (ret != 0) { + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} + +static struct vfs_fn_pointers shell_snap_fns = { + .snap_check_path_fn = shell_snap_check_path, + .snap_create_fn = shell_snap_create, + .snap_delete_fn = shell_snap_delete, +}; + +static_decl_vfs; +NTSTATUS vfs_shell_snap_init(TALLOC_CTX *ctx) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, + "shell_snap", &shell_snap_fns); +} -- cgit v1.2.3