libsmb: Convert cli_NetServerEnum() away from cli_api()
[samba4-gss.git] / source3 / rpcclient / cmd_fss.c
blob1d7883ed4dc294d00936ebb1187893996b3525eb
1 /*
2 * Unix SMB/CIFS implementation.
4 * File Server Remote VSS Protocol (FSRVP) client
6 * Copyright (C) David Disseldorp 2012
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "rpcclient.h"
24 #include "../librpc/gen_ndr/ndr_fsrvp.h"
25 #include "../librpc/gen_ndr/ndr_fsrvp_c.h"
26 #include "../libcli/util/hresult.h"
28 static const struct {
29 uint32_t error_code;
30 const char *error_str;
31 } fss_errors[] = {
33 FSRVP_E_BAD_STATE,
34 "A method call was invalid because of the state of the server."
37 FSRVP_E_SHADOW_COPY_SET_IN_PROGRESS,
38 "A call was made to either \'SetContext\' or \'StartShadowCopySet\' while the creation of another shadow copy set is in progress."
41 FSRVP_E_NOT_SUPPORTED,
42 "The file store which contains the share to be shadow copied is not supported by the server."
45 FSRVP_E_WAIT_TIMEOUT,
46 "The wait for a shadow copy commit or expose operation has timed out."
49 FSRVP_E_WAIT_FAILED,
50 "The wait for a shadow copy commit expose operation has failed."
53 FSRVP_E_OBJECT_NOT_FOUND,
54 "The specified object does not exist."
57 FSRVP_E_UNSUPPORTED_CONTEXT,
58 "The specified context value is invalid."
61 FSRVP_E_SHADOWCOPYSET_ID_MISMATCH,
62 "The provided ShadowCopySetId does not exist."
66 struct fss_context_map {
67 uint32_t ctx_val;
68 const char *ctx_str;
69 const char *ctx_desc;
71 struct fss_context_map ctx_map[] = {
73 .ctx_val = FSRVP_CTX_BACKUP,
74 .ctx_str = "backup",
75 .ctx_desc = "auto-release, non-persistent shadow-copy.",
78 .ctx_val = FSRVP_CTX_FILE_SHARE_BACKUP,
79 .ctx_str = "file_share_backup",
80 .ctx_desc = "auto-release, non-persistent shadow-copy created "
81 "without writer involvement.",
84 .ctx_val = FSRVP_CTX_NAS_ROLLBACK,
85 .ctx_str = "nas_rollback",
86 .ctx_desc = "non-auto-release, persistent shadow-copy created "
87 "without writer involvement.",
90 .ctx_val = FSRVP_CTX_APP_ROLLBACK,
91 .ctx_str = "app_rollback",
92 .ctx_desc = "non-auto-release, persistent shadow-copy.",
94 { 0, NULL, NULL },
97 static const char *get_error_str(uint32_t code)
99 static const char *default_err = "Unknown Error";
100 const char *result = default_err;
101 int i;
102 for (i = 0; i < ARRAY_SIZE(fss_errors); ++i) {
103 if (code == fss_errors[i].error_code) {
104 result = fss_errors[i].error_str;
105 break;
108 /* error isn't specific fsrvp one, check hresult errors */
109 if (result == default_err) {
110 const char *hres_err = hresult_errstr_const(HRES_ERROR(code));
111 if (hres_err) {
112 result = hres_err;
115 return result;
118 static bool map_fss_ctx_str(const char *ctx_str,
119 uint32_t *ctx_val)
121 int i;
123 for (i = 0; ctx_map[i].ctx_str != NULL; i++) {
124 if (!strcmp(ctx_map[i].ctx_str, ctx_str)) {
125 *ctx_val = ctx_map[i].ctx_val;
126 return true;
129 return false;
132 static void cmd_fss_is_path_sup_usage(const char *script_name)
134 printf("usage: %s [share_name]\n", script_name);
137 static NTSTATUS cmd_fss_is_path_sup(struct rpc_pipe_client *cli,
138 TALLOC_CTX *mem_ctx, int argc,
139 const char **argv)
141 NTSTATUS status;
142 struct fss_IsPathSupported r;
143 struct dcerpc_binding_handle *b = cli->binding_handle;
145 if (argc != 2) {
146 cmd_fss_is_path_sup_usage(argv[0]);
147 return NT_STATUS_UNSUCCESSFUL;
150 ZERO_STRUCT(r);
151 r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s\\",
152 cli->srv_name_slash, argv[1]);
153 if (r.in.ShareName == NULL) {
154 return NT_STATUS_NO_MEMORY;
157 status = dcerpc_fss_IsPathSupported_r(b, mem_ctx, &r);
158 if (!NT_STATUS_IS_OK(status)) {
159 DEBUG(0, ("IsPathSupported failed with UNC %s\n",
160 r.in.ShareName));
161 return NT_STATUS_UNSUCCESSFUL;
162 } else if (r.out.result) {
163 DEBUG(0, ("failed IsPathSupported response: 0x%x - \"%s\"\n",
164 r.out.result, get_error_str(r.out.result)));
165 return NT_STATUS_UNSUCCESSFUL;
167 printf("UNC %s %s shadow copy requests\n", r.in.ShareName,
168 *r.out.SupportedByThisProvider ? "supports" : "does not support");
170 return NT_STATUS_OK;
173 static void cmd_fss_get_sup_version_usage(const char *script_name)
175 printf("usage: %s\n", script_name);
178 static NTSTATUS cmd_fss_get_sup_version(struct rpc_pipe_client *cli,
179 TALLOC_CTX *mem_ctx, int argc,
180 const char **argv)
182 NTSTATUS status;
183 struct fss_GetSupportedVersion r;
184 struct dcerpc_binding_handle *b = cli->binding_handle;
186 if (argc != 1) {
187 cmd_fss_get_sup_version_usage(argv[0]);
188 return NT_STATUS_UNSUCCESSFUL;
191 ZERO_STRUCT(r);
192 status = dcerpc_fss_GetSupportedVersion_r(b, mem_ctx, &r);
193 if (!NT_STATUS_IS_OK(status) || (r.out.result != 0)) {
194 DEBUG(0, ("GetSupportedVersion failed: %s result: 0x%x\n",
195 nt_errstr(status), r.out.result));
196 return NT_STATUS_UNSUCCESSFUL;
198 printf("server %s supports FSRVP versions from %u to %u\n",
199 cli->desthost, *r.out.MinVersion, *r.out.MaxVersion);
201 return NT_STATUS_OK;
204 static void cmd_fss_create_expose_usage(const char *script_name)
206 int i;
208 printf("usage: %s [fss_context] [ro|rw] [share1] <share2> ...\n"
209 "[fss_context] values:\n", script_name);
210 for (i = 0; ctx_map[i].ctx_str != NULL; i++) {
211 printf("\t%s: %s\n", ctx_map[i].ctx_str, ctx_map[i].ctx_desc);
215 static NTSTATUS cmd_fss_create_expose_parse(TALLOC_CTX *mem_ctx, int argc,
216 const char **argv,
217 const char *desthost,
218 uint32_t *fss_ctx_val,
219 int *num_maps,
220 struct fssagent_share_mapping_1 **maps)
222 int num_non_share_args = 3;
223 int num_share_args;
224 int i;
225 struct fssagent_share_mapping_1 *map_array;
227 if (argc < 4) {
228 return NT_STATUS_INVALID_PARAMETER;
231 if (!map_fss_ctx_str(argv[1], fss_ctx_val)) {
232 return NT_STATUS_INVALID_PARAMETER;
235 if (!strcmp(argv[2], "rw")) {
236 /* shadow-copy is created as read-write */
237 *fss_ctx_val |= ATTR_AUTO_RECOVERY;
238 } else if (strcmp(argv[2], "ro")) {
239 return NT_STATUS_INVALID_PARAMETER;
242 num_share_args = argc - num_non_share_args;
243 map_array = talloc_array(mem_ctx, struct fssagent_share_mapping_1,
244 num_share_args);
245 if (map_array == NULL) {
246 return NT_STATUS_NO_MEMORY;
249 for (i = 0; i < num_share_args; i++) {
251 * A trailing slash should to be present in the request UNC,
252 * otherwise Windows Server 2012 FSRVP servers don't append
253 * a '$' to exposed hidden share shadow-copies. E.g.
254 * AddToShadowCopySet(UNC=\\server\hidden$)
255 * CommitShadowCopySet()
256 * ExposeShadowCopySet()
257 * -> new share = \\server\hidden$@{ShadowCopy.ShadowCopyId}
258 * But...
259 * AddToShadowCopySet(UNC=\\server\hidden$\)
260 * CommitShadowCopySet()
261 * ExposeShadowCopySet()
262 * -> new share = \\server\hidden$@{ShadowCopy.ShadowCopyId}$
264 map_array[i].ShareNameUNC = talloc_asprintf(mem_ctx,
265 "\\\\%s\\%s\\",
266 desthost,
267 argv[i + num_non_share_args]);
268 if (map_array[i].ShareNameUNC == NULL) {
269 return NT_STATUS_NO_MEMORY;
272 *num_maps = num_share_args;
273 *maps = map_array;
275 return NT_STATUS_OK;
278 static NTSTATUS cmd_fss_abort(TALLOC_CTX *mem_ctx,
279 struct dcerpc_binding_handle *b,
280 struct GUID *sc_set_id)
282 NTSTATUS status;
283 struct fss_AbortShadowCopySet r_scset_abort;
285 ZERO_STRUCT(r_scset_abort);
286 r_scset_abort.in.ShadowCopySetId = *sc_set_id;
287 status = dcerpc_fss_AbortShadowCopySet_r(b, mem_ctx, &r_scset_abort);
288 if (!NT_STATUS_IS_OK(status) || (r_scset_abort.out.result != 0)) {
289 DEBUG(0, ("AbortShadowCopySet failed: %s result: 0x%x\n",
290 nt_errstr(status), r_scset_abort.out.result));
291 return NT_STATUS_UNSUCCESSFUL;
293 return NT_STATUS_OK;
296 static NTSTATUS cmd_fss_create_expose(struct rpc_pipe_client *cli,
297 TALLOC_CTX *mem_ctx, int argc,
298 const char **argv)
300 NTSTATUS status;
301 struct fss_GetSupportedVersion r_version_get;
302 struct fss_SetContext r_context_set;
303 struct fss_StartShadowCopySet r_scset_start;
304 struct fss_PrepareShadowCopySet r_scset_prep;
305 struct fss_CommitShadowCopySet r_scset_commit;
306 struct fss_ExposeShadowCopySet r_scset_expose;
307 struct dcerpc_binding_handle *b = cli->binding_handle;
308 time_t start_time;
309 TALLOC_CTX *tmp_ctx;
310 uint32_t fss_ctx_val;
311 int num_maps;
312 struct fssagent_share_mapping_1 *req_maps;
313 int i;
315 tmp_ctx = talloc_new(mem_ctx);
316 if (tmp_ctx == NULL) {
317 return NT_STATUS_NO_MEMORY;
320 status = cmd_fss_create_expose_parse(tmp_ctx, argc, argv, cli->desthost,
321 &fss_ctx_val, &num_maps, &req_maps);
322 if (!NT_STATUS_IS_OK(status)) {
323 cmd_fss_create_expose_usage(argv[0]);
324 goto err_out;
328 * PrepareShadowCopySet & CommitShadowCopySet often exceed the default
329 * 60 second dcerpc request timeout against Windows Server "8" Beta.
330 * ACHTUNG! dcerpc_binding_handle_set_timeout() value is interpreted as
331 * seconds on a source4 transport and as msecs here.
333 dcerpc_binding_handle_set_timeout(b, 240 * 1000);
335 for (i = 0; i < num_maps; i++) {
336 struct fss_IsPathSupported r_pathsupport_get;
337 r_pathsupport_get.in.ShareName = req_maps[i].ShareNameUNC;
338 status = dcerpc_fss_IsPathSupported_r(b, tmp_ctx, &r_pathsupport_get);
339 if (!NT_STATUS_IS_OK(status) || (r_pathsupport_get.out.result != 0)) {
340 DEBUG(0, ("IsPathSupported failed: %s result: 0x%x\n",
341 nt_errstr(status), r_pathsupport_get.out.result));
342 goto err_out;
344 if (!r_pathsupport_get.out.SupportedByThisProvider) {
345 printf("path %s does not supported shadow-copies\n",
346 req_maps[i].ShareNameUNC);
347 status = NT_STATUS_NOT_SUPPORTED;
348 goto err_out;
352 ZERO_STRUCT(r_version_get);
353 status = dcerpc_fss_GetSupportedVersion_r(b, tmp_ctx, &r_version_get);
354 if (!NT_STATUS_IS_OK(status) || (r_version_get.out.result != 0)) {
355 DEBUG(0, ("GetSupportedVersion failed: %s result: 0x%x\n",
356 nt_errstr(status), r_version_get.out.result));
357 goto err_out;
360 ZERO_STRUCT(r_context_set);
361 r_context_set.in.Context = fss_ctx_val;
362 status = dcerpc_fss_SetContext_r(b, tmp_ctx, &r_context_set);
363 if (!NT_STATUS_IS_OK(status) || (r_context_set.out.result != 0)) {
364 DEBUG(0, ("SetContext failed: %s result: 0x%x\n",
365 nt_errstr(status), r_context_set.out.result));
366 goto err_out;
369 ZERO_STRUCT(r_scset_start);
370 r_scset_start.in.ClientShadowCopySetId = GUID_random();
371 status = dcerpc_fss_StartShadowCopySet_r(b, tmp_ctx, &r_scset_start);
372 if (!NT_STATUS_IS_OK(status) || (r_scset_start.out.result != 0)) {
373 DEBUG(0, ("StartShadowCopySet failed: %s result: 0x%x\n",
374 nt_errstr(status), r_scset_start.out.result));
375 goto err_out;
377 printf("%s: shadow-copy set created\n",
378 GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId));
380 for (i = 0; i < num_maps; i++) {
381 struct fss_AddToShadowCopySet r_scset_add;
382 r_scset_add.in.ClientShadowCopyId = GUID_random();
383 r_scset_add.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
384 r_scset_add.in.ShareName = req_maps[i].ShareNameUNC;
385 status = dcerpc_fss_AddToShadowCopySet_r(b, tmp_ctx, &r_scset_add);
386 if (!NT_STATUS_IS_OK(status) || (r_scset_add.out.result != 0)) {
387 DEBUG(0, ("AddToShadowCopySet failed: %s result: 0x%x\n",
388 nt_errstr(status), r_scset_add.out.result));
389 goto err_sc_set_abort;
391 printf("%s(%s): %s shadow-copy added to set\n",
392 GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
393 GUID_string(tmp_ctx, r_scset_add.out.pShadowCopyId),
394 r_scset_add.in.ShareName);
395 req_maps[i].ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
396 req_maps[i].ShadowCopyId = *r_scset_add.out.pShadowCopyId;
399 start_time = time_mono(NULL);
400 ZERO_STRUCT(r_scset_prep);
401 r_scset_prep.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
402 r_scset_prep.in.TimeOutInMilliseconds = (240 * 1000);
403 status = dcerpc_fss_PrepareShadowCopySet_r(b, tmp_ctx, &r_scset_prep);
404 if (!NT_STATUS_IS_OK(status) || (r_scset_prep.out.result != 0)) {
405 DEBUG(0, ("PrepareShadowCopySet failed: %s result: 0x%x\n",
406 nt_errstr(status), r_scset_prep.out.result));
407 goto err_sc_set_abort;
409 printf("%s: prepare completed in %llu secs\n",
410 GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
411 (long long unsigned int)(time_mono(NULL) - start_time));
413 start_time = time_mono(NULL);
414 ZERO_STRUCT(r_scset_commit);
415 r_scset_commit.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
416 r_scset_commit.in.TimeOutInMilliseconds = (180 * 1000); /* win8 */
417 status = dcerpc_fss_CommitShadowCopySet_r(b, tmp_ctx, &r_scset_commit);
418 if (!NT_STATUS_IS_OK(status) || (r_scset_commit.out.result != 0)) {
419 DEBUG(0, ("CommitShadowCopySet failed: %s result: 0x%x\n",
420 nt_errstr(status), r_scset_commit.out.result));
421 goto err_sc_set_abort;
423 printf("%s: commit completed in %llu secs\n",
424 GUID_string(tmp_ctx, r_scset_start.out.pShadowCopySetId),
425 (long long unsigned int)(time_mono(NULL) - start_time));
427 ZERO_STRUCT(r_scset_expose);
428 r_scset_expose.in.ShadowCopySetId = *r_scset_start.out.pShadowCopySetId;
429 r_scset_expose.in.TimeOutInMilliseconds = (120 * 1000); /* win8 */
430 status = dcerpc_fss_ExposeShadowCopySet_r(b, tmp_ctx, &r_scset_expose);
431 if (!NT_STATUS_IS_OK(status) || (r_scset_expose.out.result != 0)) {
432 DEBUG(0, ("ExposeShadowCopySet failed: %s result: 0x%x\n",
433 nt_errstr(status), r_scset_expose.out.result));
434 goto err_out;
437 for (i = 0; i < num_maps; i++) {
438 struct fss_GetShareMapping r_sharemap_get;
439 struct fssagent_share_mapping_1 *map;
440 r_sharemap_get.in.ShadowCopyId = req_maps[i].ShadowCopyId;
441 r_sharemap_get.in.ShadowCopySetId = req_maps[i].ShadowCopySetId;
442 r_sharemap_get.in.ShareName = req_maps[i].ShareNameUNC;
443 r_sharemap_get.in.Level = 1;
444 status = dcerpc_fss_GetShareMapping_r(b, tmp_ctx, &r_sharemap_get);
445 if (!NT_STATUS_IS_OK(status) || (r_sharemap_get.out.result != 0)) {
446 DEBUG(0, ("GetShareMapping failed: %s result: 0x%x\n",
447 nt_errstr(status), r_sharemap_get.out.result));
448 goto err_out;
450 map = r_sharemap_get.out.ShareMapping->ShareMapping1;
451 printf("%s(%s): share %s exposed as a snapshot of %s\n",
452 GUID_string(tmp_ctx, &map->ShadowCopySetId),
453 GUID_string(tmp_ctx, &map->ShadowCopyId),
454 map->ShadowCopyShareName, map->ShareNameUNC);
457 talloc_free(tmp_ctx);
458 return NT_STATUS_OK;
460 err_sc_set_abort:
461 cmd_fss_abort(tmp_ctx, b, r_scset_start.out.pShadowCopySetId);
462 err_out:
463 talloc_free(tmp_ctx);
464 return status;
467 static void cmd_fss_delete_usage(const char *script_name)
469 printf("usage: %s [base_share] [shadow_copy_set_id] [shadow_copy_id]\n",
470 script_name);
473 static NTSTATUS cmd_fss_delete(struct rpc_pipe_client *cli,
474 TALLOC_CTX *mem_ctx, int argc,
475 const char **argv)
477 struct dcerpc_binding_handle *b = cli->binding_handle;
478 struct fss_DeleteShareMapping r_sharemap_del;
479 const char *sc_set_id;
480 const char *sc_id;
481 NTSTATUS status;
482 TALLOC_CTX *tmp_ctx;
484 if (argc < 4) {
485 cmd_fss_delete_usage(argv[0]);
486 return NT_STATUS_UNSUCCESSFUL;
488 sc_set_id = argv[2];
489 sc_id = argv[3];
491 tmp_ctx = talloc_new(mem_ctx);
492 if (tmp_ctx == NULL) {
493 return NT_STATUS_NO_MEMORY;
496 ZERO_STRUCT(r_sharemap_del);
497 r_sharemap_del.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s\\",
498 cli->desthost, argv[1]);
499 if (r_sharemap_del.in.ShareName == NULL) {
500 status = NT_STATUS_NO_MEMORY;
501 goto err_out;
503 status = GUID_from_string(sc_set_id, &r_sharemap_del.in.ShadowCopySetId);
504 if (!NT_STATUS_IS_OK(status)) {
505 DEBUG(0, ("Invalid shadow_copy_set_id parameter\n"));
506 goto err_out;
508 status = GUID_from_string(sc_id, &r_sharemap_del.in.ShadowCopyId);
509 if (!NT_STATUS_IS_OK(status)) {
510 DEBUG(0, ("Invalid shadow_copy_id parameter\n"));
511 goto err_out;
513 status = dcerpc_fss_DeleteShareMapping_r(b, tmp_ctx, &r_sharemap_del);
514 if (!NT_STATUS_IS_OK(status)) {
515 DEBUG(0, ("DeleteShareMapping failed\n"));
516 goto err_out;
517 } else if (r_sharemap_del.out.result != 0) {
518 DEBUG(0, ("failed DeleteShareMapping response: 0x%x\n",
519 r_sharemap_del.out.result));
520 status = NT_STATUS_UNSUCCESSFUL;
521 goto err_out;
524 printf("%s(%s): %s shadow-copy deleted\n",
525 sc_set_id, sc_id, r_sharemap_del.in.ShareName);
527 err_out:
528 talloc_free(tmp_ctx);
529 return status;
532 static void cmd_fss_is_shadow_copied_usage(const char *script_name)
534 printf("usage: %s [share_name]\n", script_name);
537 static NTSTATUS cmd_fss_is_shadow_copied(struct rpc_pipe_client *cli,
538 TALLOC_CTX *mem_ctx, int argc,
539 const char **argv)
541 NTSTATUS status;
542 struct fss_IsPathShadowCopied r;
543 struct dcerpc_binding_handle *b = cli->binding_handle;
545 if (argc != 2) {
546 cmd_fss_is_shadow_copied_usage(argv[0]);
547 return NT_STATUS_UNSUCCESSFUL;
550 ZERO_STRUCT(r);
551 r.in.ShareName = talloc_asprintf(mem_ctx, "%s\\%s\\",
552 cli->srv_name_slash, argv[1]);
553 if (r.in.ShareName == NULL) {
554 return NT_STATUS_NO_MEMORY;
557 status = dcerpc_fss_IsPathShadowCopied_r(b, mem_ctx, &r);
558 if (!NT_STATUS_IS_OK(status)) {
559 DEBUG(0, ("IsPathShadowCopied failed with UNC %s\n",
560 r.in.ShareName));
561 return NT_STATUS_UNSUCCESSFUL;
562 } else if (r.out.result) {
563 DEBUG(0, ("failed IsPathShadowCopied response: 0x%x\n",
564 r.out.result));
565 return NT_STATUS_UNSUCCESSFUL;
567 printf("UNC %s %s an associated shadow-copy with compatibility 0x%x\n",
568 r.in.ShareName,
569 *r.out.ShadowCopyPresent ? "has" : "does not have",
570 *r.out.ShadowCopyCompatibility);
572 return NT_STATUS_OK;
575 static void cmd_fss_get_mapping_usage(const char *script_name)
577 printf("usage: %s [base_share] [shadow_copy_set_id] [shadow_copy_id]\n",
578 script_name);
581 static NTSTATUS cmd_fss_get_mapping(struct rpc_pipe_client *cli,
582 TALLOC_CTX *mem_ctx, int argc,
583 const char **argv)
585 struct dcerpc_binding_handle *b = cli->binding_handle;
586 struct fss_GetShareMapping r_sharemap_get;
587 const char *sc_set_id;
588 const char *sc_id;
589 struct fssagent_share_mapping_1 *map;
590 NTSTATUS status;
591 TALLOC_CTX *tmp_ctx;
593 if (argc < 4) {
594 cmd_fss_get_mapping_usage(argv[0]);
595 return NT_STATUS_UNSUCCESSFUL;
597 sc_set_id = argv[2];
598 sc_id = argv[3];
600 tmp_ctx = talloc_new(mem_ctx);
601 if (tmp_ctx == NULL) {
602 return NT_STATUS_NO_MEMORY;
605 ZERO_STRUCT(r_sharemap_get);
606 r_sharemap_get.in.ShareName = talloc_asprintf(tmp_ctx, "\\\\%s\\%s\\",
607 cli->desthost, argv[1]);
608 if (r_sharemap_get.in.ShareName == NULL) {
609 status = NT_STATUS_NO_MEMORY;
610 goto err_out;
612 status = GUID_from_string(sc_set_id, &r_sharemap_get.in.ShadowCopySetId);
613 if (!NT_STATUS_IS_OK(status)) {
614 DEBUG(0, ("Invalid shadow_copy_set_id parameter\n"));
615 goto err_out;
617 status = GUID_from_string(sc_id, &r_sharemap_get.in.ShadowCopyId);
618 if (!NT_STATUS_IS_OK(status)) {
619 DEBUG(0, ("Invalid shadow_copy_id parameter\n"));
620 goto err_out;
622 r_sharemap_get.in.Level = 1;
623 status = dcerpc_fss_GetShareMapping_r(b, tmp_ctx, &r_sharemap_get);
624 if (!NT_STATUS_IS_OK(status)) {
625 DEBUG(0, ("GetShareMapping failed\n"));
626 goto err_out;
627 } else if (r_sharemap_get.out.result != 0) {
628 DEBUG(0, ("failed GetShareMapping response: 0x%x\n",
629 r_sharemap_get.out.result));
630 status = NT_STATUS_UNSUCCESSFUL;
631 goto err_out;
634 map = r_sharemap_get.out.ShareMapping->ShareMapping1;
635 printf("%s(%s): share %s is a shadow-copy of %s at %s\n",
636 GUID_string(tmp_ctx, &map->ShadowCopySetId),
637 GUID_string(tmp_ctx, &map->ShadowCopyId),
638 map->ShadowCopyShareName, map->ShareNameUNC,
639 nt_time_string(tmp_ctx, map->tstamp));
641 err_out:
642 talloc_free(tmp_ctx);
643 return status;
646 static void cmd_fss_recov_complete_usage(const char *script_name)
648 printf("usage: %s [shadow_copy_set_id]\n", script_name);
651 static NTSTATUS cmd_fss_recov_complete(struct rpc_pipe_client *cli,
652 TALLOC_CTX *mem_ctx, int argc,
653 const char **argv)
655 NTSTATUS status;
656 struct fss_RecoveryCompleteShadowCopySet r;
657 struct dcerpc_binding_handle *b = cli->binding_handle;
658 const char *sc_set_id;
660 if (argc != 2) {
661 cmd_fss_recov_complete_usage(argv[0]);
662 return NT_STATUS_UNSUCCESSFUL;
664 sc_set_id = argv[1];
666 ZERO_STRUCT(r);
667 status = GUID_from_string(sc_set_id, &r.in.ShadowCopySetId);
668 if (!NT_STATUS_IS_OK(status)) {
669 DEBUG(0, ("Invalid shadow_copy_set_id\n"));
670 return NT_STATUS_INVALID_PARAMETER;
673 status = dcerpc_fss_RecoveryCompleteShadowCopySet_r(b, mem_ctx, &r);
674 if (!NT_STATUS_IS_OK(status) || (r.out.result != 0)) {
675 DEBUG(0, ("RecoveryCompleteShadowCopySet failed: %s "
676 "result: 0x%x\n", nt_errstr(status), r.out.result));
677 return status;
679 printf("%s: shadow-copy set marked recovery complete\n", sc_set_id);
681 return NT_STATUS_OK;
684 /* List of commands exported by this module */
685 struct cmd_set fss_commands[] = {
688 .name = "FSRVP",
692 .name = "fss_is_path_sup",
693 .returntype = RPC_RTYPE_NTSTATUS,
694 .ntfn = cmd_fss_is_path_sup,
695 .table = &ndr_table_FileServerVssAgent,
696 .rpc_pipe = NULL,
697 .description = "Check whether a share supports shadow-copy "
698 "requests",
699 .usage = "",
702 .name = "fss_get_sup_version",
703 .returntype = RPC_RTYPE_NTSTATUS,
704 .ntfn = cmd_fss_get_sup_version,
705 .table = &ndr_table_FileServerVssAgent,
706 .rpc_pipe = NULL,
707 .description = "Get supported FSRVP version from server",
708 .usage = "",
711 .name = "fss_create_expose",
712 .returntype = RPC_RTYPE_NTSTATUS,
713 .ntfn = cmd_fss_create_expose,
714 .table = &ndr_table_FileServerVssAgent,
715 .rpc_pipe = NULL,
716 .description = "Request shadow-copy creation and exposure",
717 .usage = "",
720 .name = "fss_delete",
721 .returntype = RPC_RTYPE_NTSTATUS,
722 .ntfn = cmd_fss_delete,
723 .table = &ndr_table_FileServerVssAgent,
724 .rpc_pipe = NULL,
725 .description = "Request shadow-copy share deletion",
726 .usage = "",
729 .name = "fss_has_shadow_copy",
730 .returntype = RPC_RTYPE_NTSTATUS,
731 .ntfn = cmd_fss_is_shadow_copied,
732 .table = &ndr_table_FileServerVssAgent,
733 .rpc_pipe = NULL,
734 .description = "Check for an associated share shadow-copy",
735 .usage = "",
738 .name = "fss_get_mapping",
739 .returntype = RPC_RTYPE_NTSTATUS,
740 .ntfn = cmd_fss_get_mapping,
741 .table = &ndr_table_FileServerVssAgent,
742 .rpc_pipe = NULL,
743 .description = "Get shadow-copy share mapping information",
744 .usage = "",
747 .name = "fss_recovery_complete",
748 .returntype = RPC_RTYPE_NTSTATUS,
749 .ntfn = cmd_fss_recov_complete,
750 .table = &ndr_table_FileServerVssAgent,
751 .rpc_pipe = NULL,
752 .description = "Flag read-write snapshot as recovery complete, "
753 "allowing further shadow-copy requests",
754 .usage = "",
757 .name = NULL,