/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
case HELP_HOLD:
return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
case HELP_HOLDS:
- return (gettext("\tholds [-r] <snapshot> ...\n"));
+ return (gettext("\tholds [-rH] <snapshot> ...\n"));
case HELP_RELEASE:
return (gettext("\trelease [-r] <tag> <snapshot> ...\n"));
case HELP_DIFF:
zfs_unmount(zhp, NULL, cb->cb_force ? MS_FORCE : 0) != 0 ||
zfs_destroy(zhp, cb->cb_defer_destroy) != 0) {
zfs_close(zhp);
+ /*
+ * When performing a recursive destroy we ignore errors
+ * so that the recursive destroy could continue
+ * destroying past problem datasets
+ */
+ if (cb->cb_recurse) {
+ cb->cb_error = B_TRUE;
+ return (0);
+ }
return (-1);
}
}
err = zfs_destroy_snaps_nvl(g_zfs,
cb.cb_batchedsnaps, cb.cb_defer_destroy);
}
- if (err != 0)
+ if (err != 0 || cb.cb_error == B_TRUE)
rv = 1;
}
}
/*
- * zfs holds [-r] <snap> ...
+ * zfs holds [-rH] <snap> ...
*
- * -r Recursively hold
+ * -r Lists holds that are set on the named snapshots recursively.
+ * -H Scripted mode; elide headers and separate columns by tabs.
*/
static int
zfs_do_holds(int argc, char **argv)
}
if (c == 't') {
- if (arg > ZCP_MAX_INSTRLIMIT || arg == 0) {
- (void) fprintf(stderr, gettext(
- "Invalid instruction limit: "
- "%s\n"), optarg);
- return (1);
- } else {
- instrlimit = arg;
- }
+ instrlimit = arg;
} else {
ASSERT3U(c, ==, 'm');
- if (arg > ZCP_MAX_MEMLIMIT || arg == 0) {
- (void) fprintf(stderr, gettext(
- "Invalid memory limit: "
- "%s\n"), optarg);
- return (1);
- } else {
- memlimit = arg;
- }
+ memlimit = arg;
}
break;
}
int ret = 0;
int i = 0;
char *cmdname;
+ char **newargv;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
libzfs_print_on_error(g_zfs, B_TRUE);
+ /*
+ * Many commands modify input strings for string parsing reasons.
+ * We create a copy to protect the original argv.
+ */
+ newargv = malloc((argc + 1) * sizeof (newargv[0]));
+ for (i = 0; i < argc; i++)
+ newargv[i] = strdup(argv[i]);
+ newargv[argc] = NULL;
+
/*
* Run the appropriate command.
*/
libzfs_mnttab_cache(g_zfs, B_TRUE);
if (find_command_idx(cmdname, &i) == 0) {
current_command = &command_table[i];
- ret = command_table[i].func(argc - 1, argv + 1);
+ ret = command_table[i].func(argc - 1, newargv + 1);
} else if (strchr(cmdname, '=') != NULL) {
verify(find_command_idx("set", &i) == 0);
current_command = &command_table[i];
- ret = command_table[i].func(argc, argv);
+ ret = command_table[i].func(argc, newargv);
} else {
(void) fprintf(stderr, gettext("unrecognized "
"command '%s'\n"), cmdname);
ret = 1;
}
+ for (i = 0; i < argc; i++)
+ free(newargv[i]);
+ free(newargv);
+
if (ret == 0 && log_history)
(void) zpool_log_history(g_zfs, history_str);