Line data Source code
1 : /*
2 : * Module for snapshot management using shell callouts
3 : *
4 : * Copyright (C) David Disseldorp 2013-2015
5 : *
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.
10 : *
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.
15 : *
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/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "include/ntioctl.h"
22 : #include "system/filesys.h"
23 : #include "smbd/smbd.h"
24 : #include "lib/util/util_file.h"
25 :
26 : /*
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.
29 : */
30 68 : static NTSTATUS shell_snap_check_path(struct vfs_handle_struct *handle,
31 : TALLOC_CTX *mem_ctx,
32 : const char *service_path,
33 : char **base_volume)
34 : {
35 : NTSTATUS status;
36 : const char *cmd;
37 : char *cmd_run;
38 : int ret;
39 : TALLOC_CTX *tmp_ctx;
40 :
41 68 : cmd = lp_parm_const_string(handle->conn->params->service,
42 : "shell_snap", "check path command", "");
43 68 : if ((cmd == NULL) || (strlen(cmd) == 0)) {
44 0 : DEBUG(0,
45 : ("\"shell_snap:check path command\" not configured\n"));
46 0 : status = NT_STATUS_NOT_SUPPORTED;
47 0 : goto err_out;
48 : }
49 :
50 68 : tmp_ctx = talloc_new(mem_ctx);
51 68 : if (tmp_ctx == NULL) {
52 0 : status = NT_STATUS_NO_MEMORY;
53 0 : goto err_out;
54 : }
55 :
56 : /* add service path argument */
57 68 : cmd_run = talloc_asprintf(tmp_ctx, "%s %s", cmd, service_path);
58 68 : if (cmd_run == NULL) {
59 0 : status = NT_STATUS_NO_MEMORY;
60 0 : goto err_tmp_free;
61 : }
62 :
63 68 : ret = smbrun(cmd_run, NULL, NULL);
64 68 : if (ret != 0) {
65 0 : DEBUG(0, ("%s failed with %d\n", cmd_run, ret));
66 0 : status = NT_STATUS_NOT_SUPPORTED;
67 0 : goto err_tmp_free;
68 : }
69 :
70 : /* assume the service path is the base volume */
71 68 : *base_volume = talloc_strdup(mem_ctx, service_path);
72 68 : if (*base_volume == NULL) {
73 0 : status = NT_STATUS_NO_MEMORY;
74 0 : goto err_tmp_free;
75 : }
76 68 : status = NT_STATUS_OK;
77 68 : err_tmp_free:
78 68 : talloc_free(tmp_ctx);
79 68 : err_out:
80 68 : return status;
81 : }
82 :
83 16 : static NTSTATUS shell_snap_create(struct vfs_handle_struct *handle,
84 : TALLOC_CTX *mem_ctx,
85 : const char *base_volume,
86 : time_t *tstamp,
87 : bool rw,
88 : char **base_path,
89 : char **snap_path)
90 : {
91 : const char *cmd;
92 : char *cmd_run;
93 : char **qlines;
94 : int numlines, ret;
95 16 : int fd = -1;
96 : TALLOC_CTX *tmp_ctx;
97 : NTSTATUS status;
98 :
99 16 : cmd = lp_parm_const_string(handle->conn->params->service,
100 : "shell_snap", "create command", "");
101 16 : if ((cmd == NULL) || (strlen(cmd) == 0)) {
102 0 : DEBUG(1, ("\"shell_snap:create command\" not configured\n"));
103 0 : status = NT_STATUS_NOT_SUPPORTED;
104 0 : goto err_out;
105 : }
106 :
107 16 : tmp_ctx = talloc_new(mem_ctx);
108 16 : if (tmp_ctx == NULL) {
109 0 : status = NT_STATUS_NO_MEMORY;
110 0 : goto err_out;
111 : }
112 :
113 : /* add base vol argument */
114 16 : cmd_run = talloc_asprintf(tmp_ctx, "%s %s", cmd, base_volume);
115 16 : if (cmd_run == NULL) {
116 0 : status = NT_STATUS_NO_MEMORY;
117 0 : goto err_tmp_free;
118 : }
119 :
120 16 : ret = smbrun(cmd_run, &fd, NULL);
121 16 : talloc_free(cmd_run);
122 16 : if (ret != 0) {
123 0 : if (fd != -1) {
124 0 : close(fd);
125 : }
126 0 : status = NT_STATUS_UNSUCCESSFUL;
127 0 : goto err_tmp_free;
128 : }
129 :
130 16 : numlines = 0;
131 16 : qlines = fd_lines_load(fd, &numlines, PATH_MAX + 1, tmp_ctx);
132 16 : close(fd);
133 :
134 : /* script must return the snapshot path as a single line */
135 16 : if ((numlines == 0) || (qlines == NULL) || (qlines[0] == NULL)) {
136 0 : status = NT_STATUS_UNSUCCESSFUL;
137 0 : goto err_tmp_free;
138 : }
139 :
140 16 : *base_path = talloc_strdup(mem_ctx, base_volume);
141 16 : if (*base_path == NULL) {
142 0 : status = NT_STATUS_NO_MEMORY;
143 0 : goto err_tmp_free;
144 : }
145 16 : *snap_path = talloc_strdup(mem_ctx, qlines[0]);
146 16 : if (*snap_path == NULL) {
147 0 : status = NT_STATUS_NO_MEMORY;
148 0 : talloc_free(*base_path);
149 0 : goto err_tmp_free;
150 : }
151 :
152 16 : status = NT_STATUS_OK;
153 16 : err_tmp_free:
154 16 : talloc_free(tmp_ctx);
155 16 : err_out:
156 16 : return status;
157 : }
158 :
159 10 : static NTSTATUS shell_snap_delete(struct vfs_handle_struct *handle,
160 : TALLOC_CTX *mem_ctx,
161 : char *base_path,
162 : char *snap_path)
163 : {
164 : const char *cmd;
165 : char *cmd_run;
166 : int ret;
167 :
168 10 : cmd = lp_parm_const_string(handle->conn->params->service,
169 : "shell_snap", "delete command", "");
170 10 : if ((cmd == NULL) || (strlen(cmd) == 0)) {
171 0 : DEBUG(1, ("\"shell_snap:delete command\" not configured\n"));
172 0 : return NT_STATUS_NOT_SUPPORTED;
173 : }
174 :
175 : /* add base path and snap path arguments */
176 10 : cmd_run = talloc_asprintf(mem_ctx, "%s %s %s",
177 : cmd, base_path, snap_path);
178 10 : if (cmd_run == NULL) {
179 0 : return NT_STATUS_NO_MEMORY;
180 : }
181 :
182 10 : ret = smbrun(cmd_run, NULL, NULL);
183 10 : talloc_free(cmd_run);
184 10 : if (ret != 0) {
185 0 : return NT_STATUS_UNSUCCESSFUL;
186 : }
187 :
188 10 : return NT_STATUS_OK;
189 : }
190 :
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,
195 : };
196 :
197 : static_decl_vfs;
198 39 : NTSTATUS vfs_shell_snap_init(TALLOC_CTX *ctx)
199 : {
200 39 : return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,
201 : "shell_snap", &shell_snap_fns);
202 : }
|