2 * Module for snapshot management using shell callouts
4 * Copyright (C) David Disseldorp 2013-2015
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "include/ntioctl.h"
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "lib/util/util_file.h"
27 * Check whether a path can be shadow copied. Return the base volume, allowing
28 * the caller to determine if multiple paths lie on the same base volume.
30 static NTSTATUS shell_snap_check_path(struct vfs_handle_struct *handle,
32 const char *service_path,
41 cmd = lp_parm_const_string(handle->conn->params->service,
42 "shell_snap", "check path command", "");
43 if ((cmd == NULL) || (strlen(cmd) == 0)) {
45 ("\"shell_snap:check path command\" not configured\n"));
46 status = NT_STATUS_NOT_SUPPORTED;
50 tmp_ctx = talloc_new(mem_ctx);
51 if (tmp_ctx == NULL) {
52 status = NT_STATUS_NO_MEMORY;
56 /* add service path argument */
57 cmd_run = talloc_asprintf(tmp_ctx, "%s %s", cmd, service_path);
58 if (cmd_run == NULL) {
59 status = NT_STATUS_NO_MEMORY;
63 ret = smbrun(cmd_run, NULL, NULL);
65 DEBUG(0, ("%s failed with %d\n", cmd_run, ret));
66 status = NT_STATUS_NOT_SUPPORTED;
70 /* assume the service path is the base volume */
71 *base_volume = talloc_strdup(mem_ctx, service_path);
72 if (*base_volume == NULL) {
73 status = NT_STATUS_NO_MEMORY;
76 status = NT_STATUS_OK;
83 static NTSTATUS shell_snap_create(struct vfs_handle_struct *handle,
85 const char *base_volume,
99 cmd = lp_parm_const_string(handle->conn->params->service,
100 "shell_snap", "create command", "");
101 if ((cmd == NULL) || (strlen(cmd) == 0)) {
102 DEBUG(1, ("\"shell_snap:create command\" not configured\n"));
103 status = NT_STATUS_NOT_SUPPORTED;
107 tmp_ctx = talloc_new(mem_ctx);
108 if (tmp_ctx == NULL) {
109 status = NT_STATUS_NO_MEMORY;
113 /* add base vol argument */
114 cmd_run = talloc_asprintf(tmp_ctx, "%s %s", cmd, base_volume);
115 if (cmd_run == NULL) {
116 status = NT_STATUS_NO_MEMORY;
120 ret = smbrun(cmd_run, &fd, NULL);
121 talloc_free(cmd_run);
126 status = NT_STATUS_UNSUCCESSFUL;
131 qlines = fd_lines_load(fd, &numlines, PATH_MAX + 1, tmp_ctx);
134 /* script must return the snapshot path as a single line */
135 if ((numlines == 0) || (qlines == NULL) || (qlines[0] == NULL)) {
136 status = NT_STATUS_UNSUCCESSFUL;
140 *base_path = talloc_strdup(mem_ctx, base_volume);
141 if (*base_path == NULL) {
142 status = NT_STATUS_NO_MEMORY;
145 *snap_path = talloc_strdup(mem_ctx, qlines[0]);
146 if (*snap_path == NULL) {
147 status = NT_STATUS_NO_MEMORY;
148 talloc_free(*base_path);
152 status = NT_STATUS_OK;
154 talloc_free(tmp_ctx);
159 static NTSTATUS shell_snap_delete(struct vfs_handle_struct *handle,
168 cmd = lp_parm_const_string(handle->conn->params->service,
169 "shell_snap", "delete command", "");
170 if ((cmd == NULL) || (strlen(cmd) == 0)) {
171 DEBUG(1, ("\"shell_snap:delete command\" not configured\n"));
172 return NT_STATUS_NOT_SUPPORTED;
175 /* add base path and snap path arguments */
176 cmd_run = talloc_asprintf(mem_ctx, "%s %s %s",
177 cmd, base_path, snap_path);
178 if (cmd_run == NULL) {
179 return NT_STATUS_NO_MEMORY;
182 ret = smbrun(cmd_run, NULL, NULL);
183 talloc_free(cmd_run);
185 return NT_STATUS_UNSUCCESSFUL;
191 static struct vfs_fn_pointers shell_snap_fns = {
192 .snap_check_path_fn = shell_snap_check_path,
193 .snap_create_fn = shell_snap_create,
194 .snap_delete_fn = shell_snap_delete,
198 NTSTATUS vfs_shell_snap_init(TALLOC_CTX *ctx)
200 return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
201 "shell_snap", &shell_snap_fns);