1*a7ee947fSAlexander Stetsenko /* 2*a7ee947fSAlexander Stetsenko * CDDL HEADER START 3*a7ee947fSAlexander Stetsenko * 4*a7ee947fSAlexander Stetsenko * The contents of this file are subject to the terms of the 5*a7ee947fSAlexander Stetsenko * Common Development and Distribution License (the "License"). 6*a7ee947fSAlexander Stetsenko * You may not use this file except in compliance with the License. 7*a7ee947fSAlexander Stetsenko * 8*a7ee947fSAlexander Stetsenko * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*a7ee947fSAlexander Stetsenko * or http://www.opensolaris.org/os/licensing. 10*a7ee947fSAlexander Stetsenko * See the License for the specific language governing permissions 11*a7ee947fSAlexander Stetsenko * and limitations under the License. 12*a7ee947fSAlexander Stetsenko * 13*a7ee947fSAlexander Stetsenko * When distributing Covered Code, include this CDDL HEADER in each 14*a7ee947fSAlexander Stetsenko * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*a7ee947fSAlexander Stetsenko * If applicable, add the following below this CDDL HEADER, with the 16*a7ee947fSAlexander Stetsenko * fields enclosed by brackets "[]" replaced with your own identifying 17*a7ee947fSAlexander Stetsenko * information: Portions Copyright [yyyy] [name of copyright owner] 18*a7ee947fSAlexander Stetsenko * 19*a7ee947fSAlexander Stetsenko * CDDL HEADER END 20*a7ee947fSAlexander Stetsenko */ 21*a7ee947fSAlexander Stetsenko 22*a7ee947fSAlexander Stetsenko /* 23*a7ee947fSAlexander Stetsenko * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24*a7ee947fSAlexander Stetsenko */ 25*a7ee947fSAlexander Stetsenko 26*a7ee947fSAlexander Stetsenko /* 27*a7ee947fSAlexander Stetsenko * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 28*a7ee947fSAlexander Stetsenko */ 29*a7ee947fSAlexander Stetsenko 30*a7ee947fSAlexander Stetsenko /* 31*a7ee947fSAlexander Stetsenko * System includes 32*a7ee947fSAlexander Stetsenko */ 33*a7ee947fSAlexander Stetsenko 34*a7ee947fSAlexander Stetsenko #include <assert.h> 35*a7ee947fSAlexander Stetsenko #include <stdio.h> 36*a7ee947fSAlexander Stetsenko #include <strings.h> 37*a7ee947fSAlexander Stetsenko #include <libzfs.h> 38*a7ee947fSAlexander Stetsenko #include <locale.h> 39*a7ee947fSAlexander Stetsenko #include <langinfo.h> 40*a7ee947fSAlexander Stetsenko #include <stdlib.h> 41*a7ee947fSAlexander Stetsenko #include <wchar.h> 42*a7ee947fSAlexander Stetsenko #include <sys/types.h> 43*a7ee947fSAlexander Stetsenko 44*a7ee947fSAlexander Stetsenko #include "libbe.h" 45*a7ee947fSAlexander Stetsenko 46*a7ee947fSAlexander Stetsenko #ifndef lint 47*a7ee947fSAlexander Stetsenko #define _(x) gettext(x) 48*a7ee947fSAlexander Stetsenko #else 49*a7ee947fSAlexander Stetsenko #define _(x) (x) 50*a7ee947fSAlexander Stetsenko #endif 51*a7ee947fSAlexander Stetsenko 52*a7ee947fSAlexander Stetsenko #ifndef TEXT_DOMAIN 53*a7ee947fSAlexander Stetsenko #define TEXT_DOMAIN "SYS_TEST" 54*a7ee947fSAlexander Stetsenko #endif 55*a7ee947fSAlexander Stetsenko 56*a7ee947fSAlexander Stetsenko #define DT_BUF_LEN (128) 57*a7ee947fSAlexander Stetsenko #define NUM_COLS (6) 58*a7ee947fSAlexander Stetsenko 59*a7ee947fSAlexander Stetsenko static int be_do_activate(int argc, char **argv); 60*a7ee947fSAlexander Stetsenko static int be_do_create(int argc, char **argv); 61*a7ee947fSAlexander Stetsenko static int be_do_create_snapshot(int argc, char **argv); 62*a7ee947fSAlexander Stetsenko static int be_do_destroy(int argc, char **argv); 63*a7ee947fSAlexander Stetsenko static int be_do_destroy_snapshot(int argc, char **argv); 64*a7ee947fSAlexander Stetsenko static int be_do_list(int argc, char **argv); 65*a7ee947fSAlexander Stetsenko static int be_do_mount(int argc, char **argv); 66*a7ee947fSAlexander Stetsenko static int be_do_unmount(int argc, char **argv); 67*a7ee947fSAlexander Stetsenko static int be_do_rename(int argc, char **argv); 68*a7ee947fSAlexander Stetsenko static int be_do_rollback(int argc, char **argv); 69*a7ee947fSAlexander Stetsenko static void usage(void); 70*a7ee947fSAlexander Stetsenko 71*a7ee947fSAlexander Stetsenko /* 72*a7ee947fSAlexander Stetsenko * single column name/width output format description 73*a7ee947fSAlexander Stetsenko */ 74*a7ee947fSAlexander Stetsenko struct col_info { 75*a7ee947fSAlexander Stetsenko const char *col_name; 76*a7ee947fSAlexander Stetsenko size_t width; 77*a7ee947fSAlexander Stetsenko }; 78*a7ee947fSAlexander Stetsenko 79*a7ee947fSAlexander Stetsenko /* 80*a7ee947fSAlexander Stetsenko * all columns output format 81*a7ee947fSAlexander Stetsenko */ 82*a7ee947fSAlexander Stetsenko struct hdr_info { 83*a7ee947fSAlexander Stetsenko struct col_info cols[NUM_COLS]; 84*a7ee947fSAlexander Stetsenko }; 85*a7ee947fSAlexander Stetsenko 86*a7ee947fSAlexander Stetsenko /* 87*a7ee947fSAlexander Stetsenko * type of possible output formats 88*a7ee947fSAlexander Stetsenko */ 89*a7ee947fSAlexander Stetsenko enum be_fmt { 90*a7ee947fSAlexander Stetsenko BE_FMT_DEFAULT, 91*a7ee947fSAlexander Stetsenko BE_FMT_DATASET, 92*a7ee947fSAlexander Stetsenko BE_FMT_SNAPSHOT, 93*a7ee947fSAlexander Stetsenko BE_FMT_ALL, 94*a7ee947fSAlexander Stetsenko BE_NUM_FMTS 95*a7ee947fSAlexander Stetsenko }; 96*a7ee947fSAlexander Stetsenko 97*a7ee947fSAlexander Stetsenko /* 98*a7ee947fSAlexander Stetsenko * command id 99*a7ee947fSAlexander Stetsenko */ 100*a7ee947fSAlexander Stetsenko enum be_cmd { 101*a7ee947fSAlexander Stetsenko BE_CMD_ACTIVATE, 102*a7ee947fSAlexander Stetsenko BE_CMD_CREATE, 103*a7ee947fSAlexander Stetsenko BE_CMD_CREATE_SNAP, 104*a7ee947fSAlexander Stetsenko BE_CMD_DESTROY, 105*a7ee947fSAlexander Stetsenko BE_CMD_DESTROY_SNAP, 106*a7ee947fSAlexander Stetsenko BE_CMD_LIST, 107*a7ee947fSAlexander Stetsenko BE_CMD_MOUNT, 108*a7ee947fSAlexander Stetsenko BE_CMD_UNMOUNT, 109*a7ee947fSAlexander Stetsenko BE_CMD_RENAME, 110*a7ee947fSAlexander Stetsenko BE_CMD_ROLLBACK, 111*a7ee947fSAlexander Stetsenko 112*a7ee947fSAlexander Stetsenko BE_NUM_COMMANDS 113*a7ee947fSAlexander Stetsenko }; 114*a7ee947fSAlexander Stetsenko 115*a7ee947fSAlexander Stetsenko /* 116*a7ee947fSAlexander Stetsenko * command handler description 117*a7ee947fSAlexander Stetsenko */ 118*a7ee947fSAlexander Stetsenko typedef struct be_command { 119*a7ee947fSAlexander Stetsenko const char *name; 120*a7ee947fSAlexander Stetsenko int (*func)(int argc, char **argv); 121*a7ee947fSAlexander Stetsenko } be_command_t; 122*a7ee947fSAlexander Stetsenko 123*a7ee947fSAlexander Stetsenko /* 124*a7ee947fSAlexander Stetsenko * sorted list of be commands 125*a7ee947fSAlexander Stetsenko */ 126*a7ee947fSAlexander Stetsenko static const be_command_t be_command_tbl[BE_NUM_COMMANDS] = { 127*a7ee947fSAlexander Stetsenko { "activate", be_do_activate }, 128*a7ee947fSAlexander Stetsenko { "create", be_do_create }, 129*a7ee947fSAlexander Stetsenko { "create_snap", be_do_create_snapshot }, 130*a7ee947fSAlexander Stetsenko { "destroy", be_do_destroy }, 131*a7ee947fSAlexander Stetsenko { "destroy_snap", be_do_destroy_snapshot }, 132*a7ee947fSAlexander Stetsenko { "list", be_do_list }, 133*a7ee947fSAlexander Stetsenko { "mount", be_do_mount }, 134*a7ee947fSAlexander Stetsenko { "unmount", be_do_unmount }, 135*a7ee947fSAlexander Stetsenko { "rename", be_do_rename }, 136*a7ee947fSAlexander Stetsenko { "rollback", be_do_rollback }, 137*a7ee947fSAlexander Stetsenko }; 138*a7ee947fSAlexander Stetsenko 139*a7ee947fSAlexander Stetsenko static struct hdr_info hdrs[BE_NUM_FMTS] = { 0 }; 140*a7ee947fSAlexander Stetsenko 141*a7ee947fSAlexander Stetsenko static void 142*a7ee947fSAlexander Stetsenko usage(void) 143*a7ee947fSAlexander Stetsenko { 144*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("usage:\n" 145*a7ee947fSAlexander Stetsenko "\tbeadm subcommand cmd_options\n" 146*a7ee947fSAlexander Stetsenko "\n" 147*a7ee947fSAlexander Stetsenko "\tsubcommands:\n" 148*a7ee947fSAlexander Stetsenko "\n" 149*a7ee947fSAlexander Stetsenko "\tbeadm create [-d BE_desc]\n" 150*a7ee947fSAlexander Stetsenko "\t\t[-o property=value] ... [-p zpool] \n" 151*a7ee947fSAlexander Stetsenko "\t\t[-e nonActiveBe | beName@snapshot] beName\n" 152*a7ee947fSAlexander Stetsenko "\tbeadm create [-d BE_desc]\n" 153*a7ee947fSAlexander Stetsenko "\t\t[-o property=value] ... [-p zpool] beName@snapshot\n" 154*a7ee947fSAlexander Stetsenko "\tbeadm create_snap [-p policy] beName [snapshot]\n" 155*a7ee947fSAlexander Stetsenko "\tbeadm destroy [-Ffs] beName \n" 156*a7ee947fSAlexander Stetsenko "\tbeadm destroy [-F] beName@snapshot \n" 157*a7ee947fSAlexander Stetsenko "\tbeadm destroy_snap beName snapshot\n" 158*a7ee947fSAlexander Stetsenko "\tbeadm list [[-a] | [-d] [-s]] [-H] [beName]\n" 159*a7ee947fSAlexander Stetsenko "\tbeadm mount [-s ro|rw] beName [mountpoint]\n" 160*a7ee947fSAlexander Stetsenko "\tbeadm unmount [-f] beName\n" 161*a7ee947fSAlexander Stetsenko "\tbeadm rename origBeName newBeName\n" 162*a7ee947fSAlexander Stetsenko "\tbeadm rollback beName snapshot\n" 163*a7ee947fSAlexander Stetsenko "\tbeadm rollback beName@snapshot\n")); 164*a7ee947fSAlexander Stetsenko } 165*a7ee947fSAlexander Stetsenko 166*a7ee947fSAlexander Stetsenko static int 167*a7ee947fSAlexander Stetsenko run_be_cmd(const char *cmdname, int argc, char **argv) 168*a7ee947fSAlexander Stetsenko { 169*a7ee947fSAlexander Stetsenko int cmd; 170*a7ee947fSAlexander Stetsenko for (cmd = 0; cmd < BE_NUM_COMMANDS; cmd++) { 171*a7ee947fSAlexander Stetsenko const be_command_t *command = &be_command_tbl[cmd]; 172*a7ee947fSAlexander Stetsenko if (strcmp(command->name, cmdname) == 0) 173*a7ee947fSAlexander Stetsenko return (command->func(argc, argv)); 174*a7ee947fSAlexander Stetsenko } 175*a7ee947fSAlexander Stetsenko 176*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Invalid command: %s\n"), cmdname); 177*a7ee947fSAlexander Stetsenko usage(); 178*a7ee947fSAlexander Stetsenko return (1); 179*a7ee947fSAlexander Stetsenko } 180*a7ee947fSAlexander Stetsenko 181*a7ee947fSAlexander Stetsenko int 182*a7ee947fSAlexander Stetsenko main(int argc, char **argv) 183*a7ee947fSAlexander Stetsenko { 184*a7ee947fSAlexander Stetsenko const char *cmdname; 185*a7ee947fSAlexander Stetsenko 186*a7ee947fSAlexander Stetsenko (void) setlocale(LC_ALL, ""); 187*a7ee947fSAlexander Stetsenko (void) textdomain(TEXT_DOMAIN); 188*a7ee947fSAlexander Stetsenko 189*a7ee947fSAlexander Stetsenko if (argc < 2) { 190*a7ee947fSAlexander Stetsenko usage(); 191*a7ee947fSAlexander Stetsenko return (1); 192*a7ee947fSAlexander Stetsenko } 193*a7ee947fSAlexander Stetsenko 194*a7ee947fSAlexander Stetsenko cmdname = argv[1]; 195*a7ee947fSAlexander Stetsenko 196*a7ee947fSAlexander Stetsenko /* Turn error printing off */ 197*a7ee947fSAlexander Stetsenko libbe_print_errors(B_FALSE); 198*a7ee947fSAlexander Stetsenko 199*a7ee947fSAlexander Stetsenko return (run_be_cmd(cmdname, --argc, ++argv)); 200*a7ee947fSAlexander Stetsenko } 201*a7ee947fSAlexander Stetsenko 202*a7ee947fSAlexander Stetsenko static void 203*a7ee947fSAlexander Stetsenko print_hdr(struct hdr_info *hdr_info) 204*a7ee947fSAlexander Stetsenko { 205*a7ee947fSAlexander Stetsenko boolean_t first = B_TRUE; 206*a7ee947fSAlexander Stetsenko size_t i; 207*a7ee947fSAlexander Stetsenko for (i = 0; i < NUM_COLS; i++) { 208*a7ee947fSAlexander Stetsenko struct col_info *col_info = &hdr_info->cols[i]; 209*a7ee947fSAlexander Stetsenko const char *name = col_info->col_name; 210*a7ee947fSAlexander Stetsenko size_t width = col_info->width; 211*a7ee947fSAlexander Stetsenko if (name == NULL) 212*a7ee947fSAlexander Stetsenko continue; 213*a7ee947fSAlexander Stetsenko 214*a7ee947fSAlexander Stetsenko if (first) { 215*a7ee947fSAlexander Stetsenko (void) printf("%-*s", width, name); 216*a7ee947fSAlexander Stetsenko first = B_FALSE; 217*a7ee947fSAlexander Stetsenko } else 218*a7ee947fSAlexander Stetsenko (void) printf(" %-*s", width, name); 219*a7ee947fSAlexander Stetsenko } 220*a7ee947fSAlexander Stetsenko (void) putchar('\n'); 221*a7ee947fSAlexander Stetsenko } 222*a7ee947fSAlexander Stetsenko 223*a7ee947fSAlexander Stetsenko static void 224*a7ee947fSAlexander Stetsenko init_hdr_cols(enum be_fmt be_fmt, struct hdr_info *hdr) 225*a7ee947fSAlexander Stetsenko { 226*a7ee947fSAlexander Stetsenko struct col_info *col = hdr->cols; 227*a7ee947fSAlexander Stetsenko size_t i; 228*a7ee947fSAlexander Stetsenko 229*a7ee947fSAlexander Stetsenko col[1].col_name = _("Active"); 230*a7ee947fSAlexander Stetsenko col[2].col_name = _("Mountpoint"); 231*a7ee947fSAlexander Stetsenko col[3].col_name = _("Space"); 232*a7ee947fSAlexander Stetsenko col[4].col_name = _("Policy"); 233*a7ee947fSAlexander Stetsenko col[5].col_name = _("Created"); 234*a7ee947fSAlexander Stetsenko col[6].col_name = NULL; 235*a7ee947fSAlexander Stetsenko 236*a7ee947fSAlexander Stetsenko switch (be_fmt) { 237*a7ee947fSAlexander Stetsenko case BE_FMT_ALL: 238*a7ee947fSAlexander Stetsenko col[0].col_name = _("BE/Dataset/Snapshot"); 239*a7ee947fSAlexander Stetsenko break; 240*a7ee947fSAlexander Stetsenko case BE_FMT_DATASET: 241*a7ee947fSAlexander Stetsenko col[0].col_name = _("BE/Dataset"); 242*a7ee947fSAlexander Stetsenko break; 243*a7ee947fSAlexander Stetsenko case BE_FMT_SNAPSHOT: 244*a7ee947fSAlexander Stetsenko col[0].col_name = _("BE/Snapshot"); 245*a7ee947fSAlexander Stetsenko col[1].col_name = NULL; 246*a7ee947fSAlexander Stetsenko col[2].col_name = NULL; 247*a7ee947fSAlexander Stetsenko break; 248*a7ee947fSAlexander Stetsenko case BE_FMT_DEFAULT: 249*a7ee947fSAlexander Stetsenko default: 250*a7ee947fSAlexander Stetsenko col[0].col_name = _("BE"); 251*a7ee947fSAlexander Stetsenko } 252*a7ee947fSAlexander Stetsenko 253*a7ee947fSAlexander Stetsenko for (i = 0; i < NUM_COLS; i++) { 254*a7ee947fSAlexander Stetsenko const char *name = col[i].col_name; 255*a7ee947fSAlexander Stetsenko col[i].width = 0; 256*a7ee947fSAlexander Stetsenko 257*a7ee947fSAlexander Stetsenko if (name != NULL) { 258*a7ee947fSAlexander Stetsenko wchar_t wname[128]; 259*a7ee947fSAlexander Stetsenko size_t sz = mbstowcs(wname, name, sizeof (wname) / 260*a7ee947fSAlexander Stetsenko sizeof (wchar_t)); 261*a7ee947fSAlexander Stetsenko if (sz > 0) 262*a7ee947fSAlexander Stetsenko col[i].width = wcswidth(wname, sz); 263*a7ee947fSAlexander Stetsenko } 264*a7ee947fSAlexander Stetsenko } 265*a7ee947fSAlexander Stetsenko } 266*a7ee947fSAlexander Stetsenko 267*a7ee947fSAlexander Stetsenko static void 268*a7ee947fSAlexander Stetsenko nicenum(uint64_t num, char *buf, size_t buflen) 269*a7ee947fSAlexander Stetsenko { 270*a7ee947fSAlexander Stetsenko uint64_t n = num; 271*a7ee947fSAlexander Stetsenko int index = 0; 272*a7ee947fSAlexander Stetsenko char u; 273*a7ee947fSAlexander Stetsenko 274*a7ee947fSAlexander Stetsenko while (n >= 1024) { 275*a7ee947fSAlexander Stetsenko n /= 1024; 276*a7ee947fSAlexander Stetsenko index++; 277*a7ee947fSAlexander Stetsenko } 278*a7ee947fSAlexander Stetsenko 279*a7ee947fSAlexander Stetsenko u = " KMGTPE"[index]; 280*a7ee947fSAlexander Stetsenko 281*a7ee947fSAlexander Stetsenko if (index == 0) { 282*a7ee947fSAlexander Stetsenko (void) snprintf(buf, buflen, "%llu", n); 283*a7ee947fSAlexander Stetsenko } else { 284*a7ee947fSAlexander Stetsenko int i; 285*a7ee947fSAlexander Stetsenko for (i = 2; i >= 0; i--) { 286*a7ee947fSAlexander Stetsenko if (snprintf(buf, buflen, "%.*f%c", i, 287*a7ee947fSAlexander Stetsenko (double)num / (1ULL << 10 * index), u) <= 5) 288*a7ee947fSAlexander Stetsenko break; 289*a7ee947fSAlexander Stetsenko } 290*a7ee947fSAlexander Stetsenko } 291*a7ee947fSAlexander Stetsenko } 292*a7ee947fSAlexander Stetsenko 293*a7ee947fSAlexander Stetsenko static void 294*a7ee947fSAlexander Stetsenko count_widths(enum be_fmt be_fmt, struct hdr_info *hdr, be_node_list_t *be_nodes) 295*a7ee947fSAlexander Stetsenko { 296*a7ee947fSAlexander Stetsenko size_t len[NUM_COLS]; 297*a7ee947fSAlexander Stetsenko char buf[DT_BUF_LEN]; 298*a7ee947fSAlexander Stetsenko int i; 299*a7ee947fSAlexander Stetsenko be_node_list_t *cur_be; 300*a7ee947fSAlexander Stetsenko 301*a7ee947fSAlexander Stetsenko for (i = 0; i < NUM_COLS; i++) 302*a7ee947fSAlexander Stetsenko len[i] = hdr->cols[i].width; 303*a7ee947fSAlexander Stetsenko 304*a7ee947fSAlexander Stetsenko for (cur_be = be_nodes; cur_be != NULL; cur_be = cur_be->be_next_node) { 305*a7ee947fSAlexander Stetsenko char name[ZFS_MAXNAMELEN+1]; 306*a7ee947fSAlexander Stetsenko const char *be_name = cur_be->be_node_name; 307*a7ee947fSAlexander Stetsenko const char *root_ds = cur_be->be_root_ds; 308*a7ee947fSAlexander Stetsenko char *pos; 309*a7ee947fSAlexander Stetsenko size_t node_name_len = strlen(cur_be->be_node_name); 310*a7ee947fSAlexander Stetsenko size_t root_ds_len = strlen(cur_be->be_root_ds); 311*a7ee947fSAlexander Stetsenko size_t mntpt_len = strlen(cur_be->be_mntpt); 312*a7ee947fSAlexander Stetsenko size_t policy_len = strlen(cur_be->be_policy_type); 313*a7ee947fSAlexander Stetsenko size_t used_len; 314*a7ee947fSAlexander Stetsenko 315*a7ee947fSAlexander Stetsenko uint64_t used = cur_be->be_space_used; 316*a7ee947fSAlexander Stetsenko be_snapshot_list_t *snap = NULL; 317*a7ee947fSAlexander Stetsenko 318*a7ee947fSAlexander Stetsenko (void) strncpy(name, root_ds, sizeof (name)); 319*a7ee947fSAlexander Stetsenko pos = strstr(name, be_name); 320*a7ee947fSAlexander Stetsenko 321*a7ee947fSAlexander Stetsenko if (be_fmt == BE_FMT_DEFAULT) { 322*a7ee947fSAlexander Stetsenko if (node_name_len > len[0]) 323*a7ee947fSAlexander Stetsenko len[0] = node_name_len; 324*a7ee947fSAlexander Stetsenko } else { 325*a7ee947fSAlexander Stetsenko if (root_ds_len + 3 > len[0]) 326*a7ee947fSAlexander Stetsenko len[0] = root_ds_len + 3; 327*a7ee947fSAlexander Stetsenko } 328*a7ee947fSAlexander Stetsenko 329*a7ee947fSAlexander Stetsenko if (mntpt_len > len[2]) 330*a7ee947fSAlexander Stetsenko len[2] = mntpt_len; 331*a7ee947fSAlexander Stetsenko if (policy_len > len[4]) 332*a7ee947fSAlexander Stetsenko len[4] = policy_len; 333*a7ee947fSAlexander Stetsenko 334*a7ee947fSAlexander Stetsenko for (snap = cur_be->be_node_snapshots; snap != NULL; 335*a7ee947fSAlexander Stetsenko snap = snap->be_next_snapshot) { 336*a7ee947fSAlexander Stetsenko uint64_t snap_used = snap->be_snapshot_space_used; 337*a7ee947fSAlexander Stetsenko const char *snap_name = snap->be_snapshot_name; 338*a7ee947fSAlexander Stetsenko (void) strcpy(pos, snap_name); 339*a7ee947fSAlexander Stetsenko 340*a7ee947fSAlexander Stetsenko if (be_fmt == BE_FMT_DEFAULT) 341*a7ee947fSAlexander Stetsenko used += snap_used; 342*a7ee947fSAlexander Stetsenko else if (be_fmt & BE_FMT_SNAPSHOT) { 343*a7ee947fSAlexander Stetsenko int snap_len = strlen(name) + 3; 344*a7ee947fSAlexander Stetsenko if (be_fmt == BE_FMT_SNAPSHOT) 345*a7ee947fSAlexander Stetsenko snap_len -= pos - name; 346*a7ee947fSAlexander Stetsenko if (snap_len > len[0]) 347*a7ee947fSAlexander Stetsenko len[0] = snap_len; 348*a7ee947fSAlexander Stetsenko nicenum(snap_used, buf, sizeof (buf)); 349*a7ee947fSAlexander Stetsenko used_len = strlen(buf); 350*a7ee947fSAlexander Stetsenko if (used_len > len[3]) 351*a7ee947fSAlexander Stetsenko len[3] = used_len; 352*a7ee947fSAlexander Stetsenko } 353*a7ee947fSAlexander Stetsenko } 354*a7ee947fSAlexander Stetsenko 355*a7ee947fSAlexander Stetsenko if (be_fmt == BE_FMT_DEFAULT) { 356*a7ee947fSAlexander Stetsenko int used_len; 357*a7ee947fSAlexander Stetsenko nicenum(used, buf, sizeof (buf)); 358*a7ee947fSAlexander Stetsenko used_len = strlen(buf); 359*a7ee947fSAlexander Stetsenko if (used_len > len[3]) 360*a7ee947fSAlexander Stetsenko len[3] = used_len; 361*a7ee947fSAlexander Stetsenko } 362*a7ee947fSAlexander Stetsenko 363*a7ee947fSAlexander Stetsenko nicenum(used, buf, sizeof (buf)); 364*a7ee947fSAlexander Stetsenko } 365*a7ee947fSAlexander Stetsenko 366*a7ee947fSAlexander Stetsenko for (i = 0; i < NUM_COLS; i++) 367*a7ee947fSAlexander Stetsenko hdr->cols[i].width = len[i]; 368*a7ee947fSAlexander Stetsenko } 369*a7ee947fSAlexander Stetsenko 370*a7ee947fSAlexander Stetsenko static void 371*a7ee947fSAlexander Stetsenko print_be_nodes(const char *be_name, boolean_t parsable, be_node_list_t *nodes) 372*a7ee947fSAlexander Stetsenko { 373*a7ee947fSAlexander Stetsenko char buf[64]; 374*a7ee947fSAlexander Stetsenko char datetime[DT_BUF_LEN]; 375*a7ee947fSAlexander Stetsenko struct hdr_info *hdr = NULL; 376*a7ee947fSAlexander Stetsenko enum be_fmt be_fmt = BE_FMT_DEFAULT; 377*a7ee947fSAlexander Stetsenko be_node_list_t *cur_be; 378*a7ee947fSAlexander Stetsenko 379*a7ee947fSAlexander Stetsenko if (!parsable) { 380*a7ee947fSAlexander Stetsenko hdr = hdrs; 381*a7ee947fSAlexander Stetsenko init_hdr_cols(be_fmt, hdr); 382*a7ee947fSAlexander Stetsenko count_widths(be_fmt, hdr, nodes); 383*a7ee947fSAlexander Stetsenko print_hdr(hdr); 384*a7ee947fSAlexander Stetsenko } 385*a7ee947fSAlexander Stetsenko 386*a7ee947fSAlexander Stetsenko for (cur_be = nodes; cur_be != NULL; cur_be = cur_be->be_next_node) { 387*a7ee947fSAlexander Stetsenko char active[3] = "-\0"; 388*a7ee947fSAlexander Stetsenko int ai = 0; 389*a7ee947fSAlexander Stetsenko const char *datetime_fmt = "%F %R"; 390*a7ee947fSAlexander Stetsenko const char *name = cur_be->be_node_name; 391*a7ee947fSAlexander Stetsenko const char *mntpt = cur_be->be_mntpt; 392*a7ee947fSAlexander Stetsenko be_snapshot_list_t *snap = NULL; 393*a7ee947fSAlexander Stetsenko uint64_t used = cur_be->be_space_used; 394*a7ee947fSAlexander Stetsenko time_t creation = cur_be->be_node_creation; 395*a7ee947fSAlexander Stetsenko struct tm *tm; 396*a7ee947fSAlexander Stetsenko 397*a7ee947fSAlexander Stetsenko if (be_name != NULL && strcmp(be_name, name) != 0) 398*a7ee947fSAlexander Stetsenko continue; 399*a7ee947fSAlexander Stetsenko 400*a7ee947fSAlexander Stetsenko if (parsable) 401*a7ee947fSAlexander Stetsenko active[0] = '\0'; 402*a7ee947fSAlexander Stetsenko 403*a7ee947fSAlexander Stetsenko tm = localtime(&creation); 404*a7ee947fSAlexander Stetsenko (void) strftime(datetime, DT_BUF_LEN, datetime_fmt, tm); 405*a7ee947fSAlexander Stetsenko 406*a7ee947fSAlexander Stetsenko for (snap = cur_be->be_node_snapshots; snap != NULL; 407*a7ee947fSAlexander Stetsenko snap = snap->be_next_snapshot) 408*a7ee947fSAlexander Stetsenko used += snap->be_snapshot_space_used; 409*a7ee947fSAlexander Stetsenko 410*a7ee947fSAlexander Stetsenko if (cur_be->be_active) 411*a7ee947fSAlexander Stetsenko active[ai++] = 'N'; 412*a7ee947fSAlexander Stetsenko if (cur_be->be_active_on_boot) 413*a7ee947fSAlexander Stetsenko active[ai] = 'R'; 414*a7ee947fSAlexander Stetsenko 415*a7ee947fSAlexander Stetsenko nicenum(used, buf, sizeof (buf)); 416*a7ee947fSAlexander Stetsenko if (parsable) 417*a7ee947fSAlexander Stetsenko (void) printf("%s;%s;%s;%s;%llu;%s;%ld\n", 418*a7ee947fSAlexander Stetsenko name, 419*a7ee947fSAlexander Stetsenko cur_be->be_uuid_str, 420*a7ee947fSAlexander Stetsenko active, 421*a7ee947fSAlexander Stetsenko (cur_be->be_mounted ? mntpt: ""), 422*a7ee947fSAlexander Stetsenko used, 423*a7ee947fSAlexander Stetsenko cur_be->be_policy_type, 424*a7ee947fSAlexander Stetsenko creation); 425*a7ee947fSAlexander Stetsenko else 426*a7ee947fSAlexander Stetsenko (void) printf("%-*s %-*s %-*s %-*s %-*s %-*s\n", 427*a7ee947fSAlexander Stetsenko hdr->cols[0].width, name, 428*a7ee947fSAlexander Stetsenko hdr->cols[1].width, active, 429*a7ee947fSAlexander Stetsenko hdr->cols[2].width, (cur_be->be_mounted ? mntpt: 430*a7ee947fSAlexander Stetsenko "-"), 431*a7ee947fSAlexander Stetsenko hdr->cols[3].width, buf, 432*a7ee947fSAlexander Stetsenko hdr->cols[4].width, cur_be->be_policy_type, 433*a7ee947fSAlexander Stetsenko hdr->cols[5].width, datetime); 434*a7ee947fSAlexander Stetsenko } 435*a7ee947fSAlexander Stetsenko } 436*a7ee947fSAlexander Stetsenko 437*a7ee947fSAlexander Stetsenko static void 438*a7ee947fSAlexander Stetsenko print_be_snapshots(be_node_list_t *be, struct hdr_info *hdr, boolean_t parsable) 439*a7ee947fSAlexander Stetsenko { 440*a7ee947fSAlexander Stetsenko char buf[64]; 441*a7ee947fSAlexander Stetsenko char datetime[DT_BUF_LEN]; 442*a7ee947fSAlexander Stetsenko be_snapshot_list_t *snap = NULL; 443*a7ee947fSAlexander Stetsenko 444*a7ee947fSAlexander Stetsenko for (snap = be->be_node_snapshots; snap != NULL; 445*a7ee947fSAlexander Stetsenko snap = snap->be_next_snapshot) { 446*a7ee947fSAlexander Stetsenko char name[ZFS_MAXNAMELEN+1]; 447*a7ee947fSAlexander Stetsenko const char *datetime_fmt = "%F %R"; 448*a7ee947fSAlexander Stetsenko const char *be_name = be->be_node_name; 449*a7ee947fSAlexander Stetsenko const char *root_ds = be->be_root_ds; 450*a7ee947fSAlexander Stetsenko const char *snap_name = snap->be_snapshot_name; 451*a7ee947fSAlexander Stetsenko char *pos; 452*a7ee947fSAlexander Stetsenko uint64_t used = snap->be_snapshot_space_used; 453*a7ee947fSAlexander Stetsenko time_t creation = snap->be_snapshot_creation; 454*a7ee947fSAlexander Stetsenko struct tm *tm = localtime(&creation); 455*a7ee947fSAlexander Stetsenko 456*a7ee947fSAlexander Stetsenko (void) strncpy(name, root_ds, sizeof (name)); 457*a7ee947fSAlexander Stetsenko pos = strstr(name, be_name); 458*a7ee947fSAlexander Stetsenko (void) strcpy(pos, snap_name); 459*a7ee947fSAlexander Stetsenko 460*a7ee947fSAlexander Stetsenko (void) strftime(datetime, DT_BUF_LEN, datetime_fmt, tm); 461*a7ee947fSAlexander Stetsenko nicenum(used, buf, sizeof (buf)); 462*a7ee947fSAlexander Stetsenko 463*a7ee947fSAlexander Stetsenko if (parsable) 464*a7ee947fSAlexander Stetsenko if (hdr->cols[1].width != 0) 465*a7ee947fSAlexander Stetsenko (void) printf("%s;%s;%s;%s;%llu;%s;%ld\n", 466*a7ee947fSAlexander Stetsenko be_name, 467*a7ee947fSAlexander Stetsenko snap_name, 468*a7ee947fSAlexander Stetsenko "", 469*a7ee947fSAlexander Stetsenko "", 470*a7ee947fSAlexander Stetsenko used, 471*a7ee947fSAlexander Stetsenko be->be_policy_type, 472*a7ee947fSAlexander Stetsenko creation); 473*a7ee947fSAlexander Stetsenko else 474*a7ee947fSAlexander Stetsenko (void) printf("%s;%s;%llu;%s;%ld\n", 475*a7ee947fSAlexander Stetsenko be_name, 476*a7ee947fSAlexander Stetsenko snap_name, 477*a7ee947fSAlexander Stetsenko used, 478*a7ee947fSAlexander Stetsenko be->be_policy_type, 479*a7ee947fSAlexander Stetsenko creation); 480*a7ee947fSAlexander Stetsenko else 481*a7ee947fSAlexander Stetsenko if (hdr->cols[1].width != 0) 482*a7ee947fSAlexander Stetsenko (void) printf(" %-*s %-*s %-*s %-*s %-*s " 483*a7ee947fSAlexander Stetsenko "%-*s\n", 484*a7ee947fSAlexander Stetsenko hdr->cols[0].width-3, name, 485*a7ee947fSAlexander Stetsenko hdr->cols[1].width, "-", 486*a7ee947fSAlexander Stetsenko hdr->cols[2].width, "-", 487*a7ee947fSAlexander Stetsenko hdr->cols[3].width, buf, 488*a7ee947fSAlexander Stetsenko hdr->cols[4].width, be->be_policy_type, 489*a7ee947fSAlexander Stetsenko hdr->cols[5].width, datetime); 490*a7ee947fSAlexander Stetsenko else 491*a7ee947fSAlexander Stetsenko (void) printf(" %-*s %-*s %-*s %-*s\n", 492*a7ee947fSAlexander Stetsenko hdr->cols[0].width-3, snap_name, 493*a7ee947fSAlexander Stetsenko hdr->cols[3].width, buf, 494*a7ee947fSAlexander Stetsenko hdr->cols[4].width, be->be_policy_type, 495*a7ee947fSAlexander Stetsenko hdr->cols[5].width, datetime); 496*a7ee947fSAlexander Stetsenko } 497*a7ee947fSAlexander Stetsenko } 498*a7ee947fSAlexander Stetsenko 499*a7ee947fSAlexander Stetsenko static void 500*a7ee947fSAlexander Stetsenko print_fmt_nodes(const char *be_name, enum be_fmt be_fmt, boolean_t parsable, 501*a7ee947fSAlexander Stetsenko be_node_list_t *nodes) 502*a7ee947fSAlexander Stetsenko { 503*a7ee947fSAlexander Stetsenko char buf[64]; 504*a7ee947fSAlexander Stetsenko char datetime[DT_BUF_LEN]; 505*a7ee947fSAlexander Stetsenko struct hdr_info *hdr = NULL; 506*a7ee947fSAlexander Stetsenko be_node_list_t *cur_be; 507*a7ee947fSAlexander Stetsenko 508*a7ee947fSAlexander Stetsenko if (!parsable) { 509*a7ee947fSAlexander Stetsenko hdr = hdrs + be_fmt; 510*a7ee947fSAlexander Stetsenko init_hdr_cols(be_fmt, hdr); 511*a7ee947fSAlexander Stetsenko count_widths(be_fmt, hdr, nodes); 512*a7ee947fSAlexander Stetsenko print_hdr(hdr); 513*a7ee947fSAlexander Stetsenko } 514*a7ee947fSAlexander Stetsenko 515*a7ee947fSAlexander Stetsenko for (cur_be = nodes; cur_be != NULL; cur_be = cur_be->be_next_node) { 516*a7ee947fSAlexander Stetsenko char active[3] = "-\0"; 517*a7ee947fSAlexander Stetsenko int ai = 0; 518*a7ee947fSAlexander Stetsenko const char *datetime_fmt = "%F %R"; 519*a7ee947fSAlexander Stetsenko const char *name = cur_be->be_node_name; 520*a7ee947fSAlexander Stetsenko const char *mntpt = cur_be->be_mntpt; 521*a7ee947fSAlexander Stetsenko uint64_t used = cur_be->be_space_used; 522*a7ee947fSAlexander Stetsenko time_t creation = cur_be->be_node_creation; 523*a7ee947fSAlexander Stetsenko struct tm *tm; 524*a7ee947fSAlexander Stetsenko 525*a7ee947fSAlexander Stetsenko if (be_name != NULL && strcmp(be_name, name) != 0) 526*a7ee947fSAlexander Stetsenko continue; 527*a7ee947fSAlexander Stetsenko 528*a7ee947fSAlexander Stetsenko if (!parsable) 529*a7ee947fSAlexander Stetsenko (void) printf("%-s\n", name); 530*a7ee947fSAlexander Stetsenko else 531*a7ee947fSAlexander Stetsenko active[0] = '\0'; 532*a7ee947fSAlexander Stetsenko 533*a7ee947fSAlexander Stetsenko tm = localtime(&creation); 534*a7ee947fSAlexander Stetsenko (void) strftime(datetime, DT_BUF_LEN, datetime_fmt, tm); 535*a7ee947fSAlexander Stetsenko 536*a7ee947fSAlexander Stetsenko if (cur_be->be_active) 537*a7ee947fSAlexander Stetsenko active[ai++] = 'N'; 538*a7ee947fSAlexander Stetsenko if (cur_be->be_active_on_boot) 539*a7ee947fSAlexander Stetsenko active[ai] = 'R'; 540*a7ee947fSAlexander Stetsenko 541*a7ee947fSAlexander Stetsenko nicenum(used, buf, sizeof (buf)); 542*a7ee947fSAlexander Stetsenko if (be_fmt & BE_FMT_DATASET) 543*a7ee947fSAlexander Stetsenko if (parsable) 544*a7ee947fSAlexander Stetsenko (void) printf("%s;%s;%s;%s;%llu;%s;%ld\n", 545*a7ee947fSAlexander Stetsenko cur_be->be_node_name, 546*a7ee947fSAlexander Stetsenko cur_be->be_root_ds, 547*a7ee947fSAlexander Stetsenko active, 548*a7ee947fSAlexander Stetsenko (cur_be->be_mounted ? mntpt: ""), 549*a7ee947fSAlexander Stetsenko used, 550*a7ee947fSAlexander Stetsenko cur_be->be_policy_type, 551*a7ee947fSAlexander Stetsenko creation); 552*a7ee947fSAlexander Stetsenko else 553*a7ee947fSAlexander Stetsenko (void) printf(" %-*s %-*s %-*s %-*s %-*s " 554*a7ee947fSAlexander Stetsenko "%-*s\n", 555*a7ee947fSAlexander Stetsenko hdr->cols[0].width-3, cur_be->be_root_ds, 556*a7ee947fSAlexander Stetsenko hdr->cols[1].width, active, 557*a7ee947fSAlexander Stetsenko hdr->cols[2].width, (cur_be->be_mounted ? 558*a7ee947fSAlexander Stetsenko mntpt: "-"), 559*a7ee947fSAlexander Stetsenko hdr->cols[3].width, buf, 560*a7ee947fSAlexander Stetsenko hdr->cols[4].width, cur_be->be_policy_type, 561*a7ee947fSAlexander Stetsenko hdr->cols[5].width, datetime); 562*a7ee947fSAlexander Stetsenko 563*a7ee947fSAlexander Stetsenko if (be_fmt & BE_FMT_SNAPSHOT) 564*a7ee947fSAlexander Stetsenko print_be_snapshots(cur_be, hdr, parsable); 565*a7ee947fSAlexander Stetsenko } 566*a7ee947fSAlexander Stetsenko } 567*a7ee947fSAlexander Stetsenko 568*a7ee947fSAlexander Stetsenko static void 569*a7ee947fSAlexander Stetsenko print_nodes(const char *be_name, boolean_t dsets, boolean_t snaps, 570*a7ee947fSAlexander Stetsenko boolean_t parsable, be_node_list_t *be_nodes) 571*a7ee947fSAlexander Stetsenko { 572*a7ee947fSAlexander Stetsenko enum be_fmt be_fmt = BE_FMT_DEFAULT; 573*a7ee947fSAlexander Stetsenko 574*a7ee947fSAlexander Stetsenko if (dsets) 575*a7ee947fSAlexander Stetsenko be_fmt |= BE_FMT_DATASET; 576*a7ee947fSAlexander Stetsenko if (snaps) 577*a7ee947fSAlexander Stetsenko be_fmt |= BE_FMT_SNAPSHOT; 578*a7ee947fSAlexander Stetsenko 579*a7ee947fSAlexander Stetsenko if (be_fmt == BE_FMT_DEFAULT) 580*a7ee947fSAlexander Stetsenko print_be_nodes(be_name, parsable, be_nodes); 581*a7ee947fSAlexander Stetsenko else 582*a7ee947fSAlexander Stetsenko print_fmt_nodes(be_name, be_fmt, parsable, be_nodes); 583*a7ee947fSAlexander Stetsenko } 584*a7ee947fSAlexander Stetsenko 585*a7ee947fSAlexander Stetsenko static boolean_t 586*a7ee947fSAlexander Stetsenko confirm_destroy(const char *name) 587*a7ee947fSAlexander Stetsenko { 588*a7ee947fSAlexander Stetsenko boolean_t res = B_FALSE; 589*a7ee947fSAlexander Stetsenko const char *yesre = nl_langinfo(YESEXPR); 590*a7ee947fSAlexander Stetsenko const char *nore = nl_langinfo(NOEXPR); 591*a7ee947fSAlexander Stetsenko regex_t yes_re; 592*a7ee947fSAlexander Stetsenko regex_t no_re; 593*a7ee947fSAlexander Stetsenko char buf[128]; 594*a7ee947fSAlexander Stetsenko char *answer; 595*a7ee947fSAlexander Stetsenko int cflags = REG_EXTENDED; 596*a7ee947fSAlexander Stetsenko 597*a7ee947fSAlexander Stetsenko if (regcomp(&yes_re, yesre, cflags) != 0) { 598*a7ee947fSAlexander Stetsenko /* should not happen */ 599*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Failed to compile 'yes' regexp\n")); 600*a7ee947fSAlexander Stetsenko return (res); 601*a7ee947fSAlexander Stetsenko } 602*a7ee947fSAlexander Stetsenko if (regcomp(&no_re, nore, cflags) != 0) { 603*a7ee947fSAlexander Stetsenko /* should not happen */ 604*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Failed to compile 'no' regexp\n")); 605*a7ee947fSAlexander Stetsenko regfree(&yes_re); 606*a7ee947fSAlexander Stetsenko return (res); 607*a7ee947fSAlexander Stetsenko } 608*a7ee947fSAlexander Stetsenko 609*a7ee947fSAlexander Stetsenko (void) printf(_("Are you sure you want to destroy %s?\n" 610*a7ee947fSAlexander Stetsenko "This action cannot be undone (y/[n]): "), name); 611*a7ee947fSAlexander Stetsenko 612*a7ee947fSAlexander Stetsenko answer = fgets(buf, sizeof (buf), stdin); 613*a7ee947fSAlexander Stetsenko if (answer == NULL || *answer == '\0' || *answer == 10) 614*a7ee947fSAlexander Stetsenko goto out; 615*a7ee947fSAlexander Stetsenko 616*a7ee947fSAlexander Stetsenko if (regexec(&yes_re, answer, 0, NULL, 0) == 0) { 617*a7ee947fSAlexander Stetsenko res = B_TRUE; 618*a7ee947fSAlexander Stetsenko } else if (regexec(&no_re, answer, 0, NULL, 0) != 0) { 619*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Invalid response. " 620*a7ee947fSAlexander Stetsenko "Please enter 'y' or 'n'.\n")); 621*a7ee947fSAlexander Stetsenko } 622*a7ee947fSAlexander Stetsenko 623*a7ee947fSAlexander Stetsenko out: 624*a7ee947fSAlexander Stetsenko regfree(&yes_re); 625*a7ee947fSAlexander Stetsenko regfree(&no_re); 626*a7ee947fSAlexander Stetsenko return (res); 627*a7ee947fSAlexander Stetsenko } 628*a7ee947fSAlexander Stetsenko 629*a7ee947fSAlexander Stetsenko static int 630*a7ee947fSAlexander Stetsenko be_nvl_alloc(nvlist_t **nvlp) 631*a7ee947fSAlexander Stetsenko { 632*a7ee947fSAlexander Stetsenko assert(nvlp != NULL); 633*a7ee947fSAlexander Stetsenko 634*a7ee947fSAlexander Stetsenko if (nvlist_alloc(nvlp, NV_UNIQUE_NAME, 0) != 0) { 635*a7ee947fSAlexander Stetsenko (void) perror(_("nvlist_alloc failed.\n")); 636*a7ee947fSAlexander Stetsenko return (1); 637*a7ee947fSAlexander Stetsenko } 638*a7ee947fSAlexander Stetsenko 639*a7ee947fSAlexander Stetsenko return (0); 640*a7ee947fSAlexander Stetsenko } 641*a7ee947fSAlexander Stetsenko 642*a7ee947fSAlexander Stetsenko static int 643*a7ee947fSAlexander Stetsenko be_nvl_add_string(nvlist_t *nvl, const char *name, const char *val) 644*a7ee947fSAlexander Stetsenko { 645*a7ee947fSAlexander Stetsenko assert(nvl != NULL); 646*a7ee947fSAlexander Stetsenko 647*a7ee947fSAlexander Stetsenko if (nvlist_add_string(nvl, name, val) != 0) { 648*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("nvlist_add_string failed for " 649*a7ee947fSAlexander Stetsenko "%s (%s).\n"), name, val); 650*a7ee947fSAlexander Stetsenko return (1); 651*a7ee947fSAlexander Stetsenko } 652*a7ee947fSAlexander Stetsenko 653*a7ee947fSAlexander Stetsenko return (0); 654*a7ee947fSAlexander Stetsenko } 655*a7ee947fSAlexander Stetsenko 656*a7ee947fSAlexander Stetsenko static int 657*a7ee947fSAlexander Stetsenko be_nvl_add_nvlist(nvlist_t *nvl, const char *name, nvlist_t *val) 658*a7ee947fSAlexander Stetsenko { 659*a7ee947fSAlexander Stetsenko assert(nvl != NULL); 660*a7ee947fSAlexander Stetsenko 661*a7ee947fSAlexander Stetsenko if (nvlist_add_nvlist(nvl, name, val) != 0) { 662*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("nvlist_add_nvlist failed for %s.\n"), 663*a7ee947fSAlexander Stetsenko name); 664*a7ee947fSAlexander Stetsenko return (1); 665*a7ee947fSAlexander Stetsenko } 666*a7ee947fSAlexander Stetsenko 667*a7ee947fSAlexander Stetsenko return (0); 668*a7ee947fSAlexander Stetsenko } 669*a7ee947fSAlexander Stetsenko 670*a7ee947fSAlexander Stetsenko static int 671*a7ee947fSAlexander Stetsenko be_nvl_add_uint16(nvlist_t *nvl, const char *name, uint16_t val) 672*a7ee947fSAlexander Stetsenko { 673*a7ee947fSAlexander Stetsenko assert(nvl != NULL); 674*a7ee947fSAlexander Stetsenko 675*a7ee947fSAlexander Stetsenko if (nvlist_add_uint16(nvl, name, val) != 0) { 676*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("nvlist_add_uint16 failed for " 677*a7ee947fSAlexander Stetsenko "%s (%hu).\n"), name, val); 678*a7ee947fSAlexander Stetsenko return (1); 679*a7ee947fSAlexander Stetsenko } 680*a7ee947fSAlexander Stetsenko 681*a7ee947fSAlexander Stetsenko return (0); 682*a7ee947fSAlexander Stetsenko } 683*a7ee947fSAlexander Stetsenko 684*a7ee947fSAlexander Stetsenko static int 685*a7ee947fSAlexander Stetsenko be_do_activate(int argc, char **argv) 686*a7ee947fSAlexander Stetsenko { 687*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 688*a7ee947fSAlexander Stetsenko int err = 1; 689*a7ee947fSAlexander Stetsenko char *obe_name; 690*a7ee947fSAlexander Stetsenko 691*a7ee947fSAlexander Stetsenko argc -= optind; 692*a7ee947fSAlexander Stetsenko argv += optind; 693*a7ee947fSAlexander Stetsenko 694*a7ee947fSAlexander Stetsenko if (argc != 1) { 695*a7ee947fSAlexander Stetsenko usage(); 696*a7ee947fSAlexander Stetsenko return (1); 697*a7ee947fSAlexander Stetsenko } 698*a7ee947fSAlexander Stetsenko 699*a7ee947fSAlexander Stetsenko obe_name = argv[0]; 700*a7ee947fSAlexander Stetsenko 701*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 702*a7ee947fSAlexander Stetsenko return (1); 703*a7ee947fSAlexander Stetsenko 704*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 705*a7ee947fSAlexander Stetsenko goto out; 706*a7ee947fSAlexander Stetsenko 707*a7ee947fSAlexander Stetsenko err = be_activate(be_attrs); 708*a7ee947fSAlexander Stetsenko 709*a7ee947fSAlexander Stetsenko switch (err) { 710*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 711*a7ee947fSAlexander Stetsenko (void) printf(_("Activated successfully\n")); 712*a7ee947fSAlexander Stetsenko break; 713*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 714*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 715*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 716*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), obe_name); 717*a7ee947fSAlexander Stetsenko break; 718*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 719*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 720*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to activate %s.\n"), obe_name); 721*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 722*a7ee947fSAlexander Stetsenko "execute this command.\n")); 723*a7ee947fSAlexander Stetsenko break; 724*a7ee947fSAlexander Stetsenko case BE_ERR_ACTIVATE_CURR: 725*a7ee947fSAlexander Stetsenko default: 726*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to activate %s.\n"), obe_name); 727*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 728*a7ee947fSAlexander Stetsenko } 729*a7ee947fSAlexander Stetsenko 730*a7ee947fSAlexander Stetsenko out: 731*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 732*a7ee947fSAlexander Stetsenko return (err); 733*a7ee947fSAlexander Stetsenko } 734*a7ee947fSAlexander Stetsenko 735*a7ee947fSAlexander Stetsenko static int 736*a7ee947fSAlexander Stetsenko be_do_create(int argc, char **argv) 737*a7ee947fSAlexander Stetsenko { 738*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 739*a7ee947fSAlexander Stetsenko nvlist_t *zfs_props = NULL; 740*a7ee947fSAlexander Stetsenko boolean_t activate = B_FALSE; 741*a7ee947fSAlexander Stetsenko boolean_t is_snap = B_FALSE; 742*a7ee947fSAlexander Stetsenko int c; 743*a7ee947fSAlexander Stetsenko int err = 1; 744*a7ee947fSAlexander Stetsenko char *obe_name = NULL; 745*a7ee947fSAlexander Stetsenko char *snap_name = NULL; 746*a7ee947fSAlexander Stetsenko char *nbe_zpool = NULL; 747*a7ee947fSAlexander Stetsenko char *nbe_name = NULL; 748*a7ee947fSAlexander Stetsenko char *nbe_desc = NULL; 749*a7ee947fSAlexander Stetsenko char *propname = NULL; 750*a7ee947fSAlexander Stetsenko char *propval = NULL; 751*a7ee947fSAlexander Stetsenko char *strval = NULL; 752*a7ee947fSAlexander Stetsenko 753*a7ee947fSAlexander Stetsenko while ((c = getopt(argc, argv, "ad:e:io:p:")) != -1) { 754*a7ee947fSAlexander Stetsenko switch (c) { 755*a7ee947fSAlexander Stetsenko case 'a': 756*a7ee947fSAlexander Stetsenko activate = B_TRUE; 757*a7ee947fSAlexander Stetsenko break; 758*a7ee947fSAlexander Stetsenko case 'd': 759*a7ee947fSAlexander Stetsenko nbe_desc = optarg; 760*a7ee947fSAlexander Stetsenko break; 761*a7ee947fSAlexander Stetsenko case 'e': 762*a7ee947fSAlexander Stetsenko obe_name = optarg; 763*a7ee947fSAlexander Stetsenko break; 764*a7ee947fSAlexander Stetsenko case 'o': 765*a7ee947fSAlexander Stetsenko if (zfs_props == NULL && be_nvl_alloc(&zfs_props) != 0) 766*a7ee947fSAlexander Stetsenko return (1); 767*a7ee947fSAlexander Stetsenko 768*a7ee947fSAlexander Stetsenko propname = optarg; 769*a7ee947fSAlexander Stetsenko if ((propval = strchr(propname, '=')) == NULL) { 770*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("missing " 771*a7ee947fSAlexander Stetsenko "'=' for -o option\n")); 772*a7ee947fSAlexander Stetsenko goto out2; 773*a7ee947fSAlexander Stetsenko } 774*a7ee947fSAlexander Stetsenko *propval = '\0'; 775*a7ee947fSAlexander Stetsenko propval++; 776*a7ee947fSAlexander Stetsenko if (nvlist_lookup_string(zfs_props, propname, 777*a7ee947fSAlexander Stetsenko &strval) == 0) { 778*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("property '%s' " 779*a7ee947fSAlexander Stetsenko "specified multiple times\n"), propname); 780*a7ee947fSAlexander Stetsenko goto out2; 781*a7ee947fSAlexander Stetsenko 782*a7ee947fSAlexander Stetsenko } 783*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(zfs_props, propname, propval) 784*a7ee947fSAlexander Stetsenko != 0) 785*a7ee947fSAlexander Stetsenko goto out2; 786*a7ee947fSAlexander Stetsenko 787*a7ee947fSAlexander Stetsenko break; 788*a7ee947fSAlexander Stetsenko case 'p': 789*a7ee947fSAlexander Stetsenko nbe_zpool = optarg; 790*a7ee947fSAlexander Stetsenko break; 791*a7ee947fSAlexander Stetsenko default: 792*a7ee947fSAlexander Stetsenko usage(); 793*a7ee947fSAlexander Stetsenko goto out2; 794*a7ee947fSAlexander Stetsenko } 795*a7ee947fSAlexander Stetsenko } 796*a7ee947fSAlexander Stetsenko 797*a7ee947fSAlexander Stetsenko argc -= optind; 798*a7ee947fSAlexander Stetsenko argv += optind; 799*a7ee947fSAlexander Stetsenko 800*a7ee947fSAlexander Stetsenko if (argc != 1) { 801*a7ee947fSAlexander Stetsenko usage(); 802*a7ee947fSAlexander Stetsenko goto out2; 803*a7ee947fSAlexander Stetsenko } 804*a7ee947fSAlexander Stetsenko 805*a7ee947fSAlexander Stetsenko nbe_name = argv[0]; 806*a7ee947fSAlexander Stetsenko 807*a7ee947fSAlexander Stetsenko if ((snap_name = strrchr(nbe_name, '@')) != NULL) { 808*a7ee947fSAlexander Stetsenko if (snap_name[1] == '\0') { 809*a7ee947fSAlexander Stetsenko usage(); 810*a7ee947fSAlexander Stetsenko goto out2; 811*a7ee947fSAlexander Stetsenko } 812*a7ee947fSAlexander Stetsenko 813*a7ee947fSAlexander Stetsenko snap_name[0] = '\0'; 814*a7ee947fSAlexander Stetsenko snap_name++; 815*a7ee947fSAlexander Stetsenko is_snap = B_TRUE; 816*a7ee947fSAlexander Stetsenko } 817*a7ee947fSAlexander Stetsenko 818*a7ee947fSAlexander Stetsenko if (obe_name) { 819*a7ee947fSAlexander Stetsenko if (is_snap) { 820*a7ee947fSAlexander Stetsenko usage(); 821*a7ee947fSAlexander Stetsenko goto out2; 822*a7ee947fSAlexander Stetsenko } 823*a7ee947fSAlexander Stetsenko 824*a7ee947fSAlexander Stetsenko /* 825*a7ee947fSAlexander Stetsenko * Check if obe_name is really a snapshot name. 826*a7ee947fSAlexander Stetsenko * If so, split it out. 827*a7ee947fSAlexander Stetsenko */ 828*a7ee947fSAlexander Stetsenko if ((snap_name = strrchr(obe_name, '@')) != NULL) { 829*a7ee947fSAlexander Stetsenko if (snap_name[1] == '\0') { 830*a7ee947fSAlexander Stetsenko usage(); 831*a7ee947fSAlexander Stetsenko goto out2; 832*a7ee947fSAlexander Stetsenko } 833*a7ee947fSAlexander Stetsenko 834*a7ee947fSAlexander Stetsenko snap_name[0] = '\0'; 835*a7ee947fSAlexander Stetsenko snap_name++; 836*a7ee947fSAlexander Stetsenko } 837*a7ee947fSAlexander Stetsenko } else if (is_snap) { 838*a7ee947fSAlexander Stetsenko obe_name = nbe_name; 839*a7ee947fSAlexander Stetsenko nbe_name = NULL; 840*a7ee947fSAlexander Stetsenko } 841*a7ee947fSAlexander Stetsenko 842*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 843*a7ee947fSAlexander Stetsenko goto out2; 844*a7ee947fSAlexander Stetsenko 845*a7ee947fSAlexander Stetsenko 846*a7ee947fSAlexander Stetsenko if (zfs_props != NULL && be_nvl_add_nvlist(be_attrs, 847*a7ee947fSAlexander Stetsenko BE_ATTR_ORIG_BE_NAME, zfs_props) != 0) 848*a7ee947fSAlexander Stetsenko goto out; 849*a7ee947fSAlexander Stetsenko 850*a7ee947fSAlexander Stetsenko if (obe_name != NULL && be_nvl_add_string(be_attrs, 851*a7ee947fSAlexander Stetsenko BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 852*a7ee947fSAlexander Stetsenko goto out; 853*a7ee947fSAlexander Stetsenko 854*a7ee947fSAlexander Stetsenko if (snap_name != NULL && be_nvl_add_string(be_attrs, 855*a7ee947fSAlexander Stetsenko BE_ATTR_SNAP_NAME, snap_name) != 0) 856*a7ee947fSAlexander Stetsenko goto out; 857*a7ee947fSAlexander Stetsenko 858*a7ee947fSAlexander Stetsenko if (nbe_zpool != NULL && be_nvl_add_string(be_attrs, 859*a7ee947fSAlexander Stetsenko BE_ATTR_NEW_BE_POOL, nbe_zpool) != 0) 860*a7ee947fSAlexander Stetsenko goto out; 861*a7ee947fSAlexander Stetsenko 862*a7ee947fSAlexander Stetsenko if (nbe_name != NULL && be_nvl_add_string(be_attrs, 863*a7ee947fSAlexander Stetsenko BE_ATTR_NEW_BE_NAME, nbe_name) != 0) 864*a7ee947fSAlexander Stetsenko goto out; 865*a7ee947fSAlexander Stetsenko 866*a7ee947fSAlexander Stetsenko if (nbe_desc != NULL && be_nvl_add_string(be_attrs, 867*a7ee947fSAlexander Stetsenko BE_ATTR_NEW_BE_DESC, nbe_desc) != 0) 868*a7ee947fSAlexander Stetsenko goto out; 869*a7ee947fSAlexander Stetsenko 870*a7ee947fSAlexander Stetsenko if (is_snap) 871*a7ee947fSAlexander Stetsenko err = be_create_snapshot(be_attrs); 872*a7ee947fSAlexander Stetsenko else 873*a7ee947fSAlexander Stetsenko err = be_copy(be_attrs); 874*a7ee947fSAlexander Stetsenko 875*a7ee947fSAlexander Stetsenko switch (err) { 876*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 877*a7ee947fSAlexander Stetsenko if (!is_snap && !nbe_name) { 878*a7ee947fSAlexander Stetsenko /* 879*a7ee947fSAlexander Stetsenko * We requested an auto named BE; find out the 880*a7ee947fSAlexander Stetsenko * name of the BE that was created for us and 881*a7ee947fSAlexander Stetsenko * the auto snapshot created from the original BE. 882*a7ee947fSAlexander Stetsenko */ 883*a7ee947fSAlexander Stetsenko if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME, 884*a7ee947fSAlexander Stetsenko &nbe_name) != 0) { 885*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("failed to get %s " 886*a7ee947fSAlexander Stetsenko "attribute\n"), BE_ATTR_NEW_BE_NAME); 887*a7ee947fSAlexander Stetsenko break; 888*a7ee947fSAlexander Stetsenko } else 889*a7ee947fSAlexander Stetsenko (void) printf(_("Auto named BE: %s\n"), 890*a7ee947fSAlexander Stetsenko nbe_name); 891*a7ee947fSAlexander Stetsenko 892*a7ee947fSAlexander Stetsenko if (nvlist_lookup_string(be_attrs, BE_ATTR_SNAP_NAME, 893*a7ee947fSAlexander Stetsenko &snap_name) != 0) { 894*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("failed to get %s " 895*a7ee947fSAlexander Stetsenko "attribute\n"), BE_ATTR_SNAP_NAME); 896*a7ee947fSAlexander Stetsenko break; 897*a7ee947fSAlexander Stetsenko } else 898*a7ee947fSAlexander Stetsenko (void) printf(_("Auto named snapshot: %s\n"), 899*a7ee947fSAlexander Stetsenko snap_name); 900*a7ee947fSAlexander Stetsenko } 901*a7ee947fSAlexander Stetsenko 902*a7ee947fSAlexander Stetsenko if (!is_snap && activate) { 903*a7ee947fSAlexander Stetsenko char *args[] = { "activate", "", NULL }; 904*a7ee947fSAlexander Stetsenko args[1] = nbe_name; 905*a7ee947fSAlexander Stetsenko optind = 1; 906*a7ee947fSAlexander Stetsenko 907*a7ee947fSAlexander Stetsenko err = be_do_activate(2, args); 908*a7ee947fSAlexander Stetsenko goto out; 909*a7ee947fSAlexander Stetsenko } 910*a7ee947fSAlexander Stetsenko 911*a7ee947fSAlexander Stetsenko (void) printf(_("Created successfully\n")); 912*a7ee947fSAlexander Stetsenko break; 913*a7ee947fSAlexander Stetsenko case BE_ERR_BE_EXISTS: 914*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("BE %s already exists\n." 915*a7ee947fSAlexander Stetsenko "Please choose a different BE name.\n"), nbe_name); 916*a7ee947fSAlexander Stetsenko break; 917*a7ee947fSAlexander Stetsenko case BE_ERR_SS_EXISTS: 918*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("BE %s snapshot %s already exists.\n" 919*a7ee947fSAlexander Stetsenko "Please choose a different snapshot name.\n"), obe_name, 920*a7ee947fSAlexander Stetsenko snap_name); 921*a7ee947fSAlexander Stetsenko break; 922*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 923*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 924*a7ee947fSAlexander Stetsenko if (is_snap) 925*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to create snapshot " 926*a7ee947fSAlexander Stetsenko "%s.\n"), snap_name); 927*a7ee947fSAlexander Stetsenko else 928*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to create %s.\n"), 929*a7ee947fSAlexander Stetsenko nbe_name); 930*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 931*a7ee947fSAlexander Stetsenko "execute this command.\n")); 932*a7ee947fSAlexander Stetsenko break; 933*a7ee947fSAlexander Stetsenko default: 934*a7ee947fSAlexander Stetsenko if (is_snap) 935*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to create snapshot " 936*a7ee947fSAlexander Stetsenko "%s.\n"), snap_name); 937*a7ee947fSAlexander Stetsenko else 938*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to create %s.\n"), 939*a7ee947fSAlexander Stetsenko nbe_name); 940*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 941*a7ee947fSAlexander Stetsenko } 942*a7ee947fSAlexander Stetsenko 943*a7ee947fSAlexander Stetsenko out: 944*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 945*a7ee947fSAlexander Stetsenko out2: 946*a7ee947fSAlexander Stetsenko if (zfs_props != NULL) 947*a7ee947fSAlexander Stetsenko nvlist_free(zfs_props); 948*a7ee947fSAlexander Stetsenko 949*a7ee947fSAlexander Stetsenko return (err); 950*a7ee947fSAlexander Stetsenko } 951*a7ee947fSAlexander Stetsenko 952*a7ee947fSAlexander Stetsenko static int 953*a7ee947fSAlexander Stetsenko be_do_create_snapshot(int argc, char **argv) 954*a7ee947fSAlexander Stetsenko { 955*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 956*a7ee947fSAlexander Stetsenko int err = 1; 957*a7ee947fSAlexander Stetsenko int c; 958*a7ee947fSAlexander Stetsenko char *obe_name = NULL; 959*a7ee947fSAlexander Stetsenko char *snap_name = NULL; 960*a7ee947fSAlexander Stetsenko char *policy = NULL; 961*a7ee947fSAlexander Stetsenko 962*a7ee947fSAlexander Stetsenko while ((c = getopt(argc, argv, "p:")) != -1) { 963*a7ee947fSAlexander Stetsenko switch (c) { 964*a7ee947fSAlexander Stetsenko case 'p': 965*a7ee947fSAlexander Stetsenko policy = optarg; 966*a7ee947fSAlexander Stetsenko break; 967*a7ee947fSAlexander Stetsenko default: 968*a7ee947fSAlexander Stetsenko usage(); 969*a7ee947fSAlexander Stetsenko return (1); 970*a7ee947fSAlexander Stetsenko } 971*a7ee947fSAlexander Stetsenko } 972*a7ee947fSAlexander Stetsenko 973*a7ee947fSAlexander Stetsenko argc -= optind; 974*a7ee947fSAlexander Stetsenko argv += optind; 975*a7ee947fSAlexander Stetsenko 976*a7ee947fSAlexander Stetsenko if (argc < 1 || argc > 2) { 977*a7ee947fSAlexander Stetsenko usage(); 978*a7ee947fSAlexander Stetsenko return (1); 979*a7ee947fSAlexander Stetsenko } 980*a7ee947fSAlexander Stetsenko 981*a7ee947fSAlexander Stetsenko obe_name = argv[0]; 982*a7ee947fSAlexander Stetsenko 983*a7ee947fSAlexander Stetsenko if (argc > 1) { 984*a7ee947fSAlexander Stetsenko /* Snapshot name provided */ 985*a7ee947fSAlexander Stetsenko snap_name = argv[1]; 986*a7ee947fSAlexander Stetsenko } 987*a7ee947fSAlexander Stetsenko 988*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 989*a7ee947fSAlexander Stetsenko return (1); 990*a7ee947fSAlexander Stetsenko 991*a7ee947fSAlexander Stetsenko 992*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 993*a7ee947fSAlexander Stetsenko goto out; 994*a7ee947fSAlexander Stetsenko 995*a7ee947fSAlexander Stetsenko if (policy != NULL && be_nvl_add_string(be_attrs, 996*a7ee947fSAlexander Stetsenko BE_ATTR_POLICY, policy) != 0) 997*a7ee947fSAlexander Stetsenko goto out; 998*a7ee947fSAlexander Stetsenko 999*a7ee947fSAlexander Stetsenko if (snap_name != NULL && be_nvl_add_string(be_attrs, 1000*a7ee947fSAlexander Stetsenko BE_ATTR_SNAP_NAME, snap_name) != 0) 1001*a7ee947fSAlexander Stetsenko goto out; 1002*a7ee947fSAlexander Stetsenko 1003*a7ee947fSAlexander Stetsenko err = be_create_snapshot(be_attrs); 1004*a7ee947fSAlexander Stetsenko 1005*a7ee947fSAlexander Stetsenko switch (err) { 1006*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1007*a7ee947fSAlexander Stetsenko if (!snap_name) { 1008*a7ee947fSAlexander Stetsenko /* 1009*a7ee947fSAlexander Stetsenko * We requested an auto named snapshot; find out 1010*a7ee947fSAlexander Stetsenko * the snapshot name that was created for us. 1011*a7ee947fSAlexander Stetsenko */ 1012*a7ee947fSAlexander Stetsenko if (nvlist_lookup_string(be_attrs, BE_ATTR_SNAP_NAME, 1013*a7ee947fSAlexander Stetsenko &snap_name) != 0) { 1014*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("failed to get %s " 1015*a7ee947fSAlexander Stetsenko "attribute\n"), BE_ATTR_SNAP_NAME); 1016*a7ee947fSAlexander Stetsenko err = 1; 1017*a7ee947fSAlexander Stetsenko break; 1018*a7ee947fSAlexander Stetsenko } 1019*a7ee947fSAlexander Stetsenko 1020*a7ee947fSAlexander Stetsenko (void) printf(_("Auto named snapshot: %s\n"), 1021*a7ee947fSAlexander Stetsenko snap_name); 1022*a7ee947fSAlexander Stetsenko } 1023*a7ee947fSAlexander Stetsenko (void) printf(_("Created successfully\n")); 1024*a7ee947fSAlexander Stetsenko break; 1025*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 1026*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1027*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 1028*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), obe_name); 1029*a7ee947fSAlexander Stetsenko break; 1030*a7ee947fSAlexander Stetsenko case BE_ERR_SS_EXISTS: 1031*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("BE %s snapshot %s already exists.\n" 1032*a7ee947fSAlexander Stetsenko "Please choose a different snapshot name.\n"), obe_name, 1033*a7ee947fSAlexander Stetsenko snap_name); 1034*a7ee947fSAlexander Stetsenko break; 1035*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 1036*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 1037*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to create snapshot %s.\n"), 1038*a7ee947fSAlexander Stetsenko snap_name); 1039*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 1040*a7ee947fSAlexander Stetsenko "execute this command.\n")); 1041*a7ee947fSAlexander Stetsenko break; 1042*a7ee947fSAlexander Stetsenko default: 1043*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to create snapshot %s.\n"), 1044*a7ee947fSAlexander Stetsenko snap_name); 1045*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1046*a7ee947fSAlexander Stetsenko } 1047*a7ee947fSAlexander Stetsenko 1048*a7ee947fSAlexander Stetsenko out: 1049*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 1050*a7ee947fSAlexander Stetsenko return (err); 1051*a7ee947fSAlexander Stetsenko } 1052*a7ee947fSAlexander Stetsenko 1053*a7ee947fSAlexander Stetsenko static int 1054*a7ee947fSAlexander Stetsenko be_do_destroy(int argc, char **argv) 1055*a7ee947fSAlexander Stetsenko { 1056*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 1057*a7ee947fSAlexander Stetsenko boolean_t is_snap = B_FALSE; 1058*a7ee947fSAlexander Stetsenko boolean_t suppress_prompt = B_FALSE; 1059*a7ee947fSAlexander Stetsenko int err = 1; 1060*a7ee947fSAlexander Stetsenko int c; 1061*a7ee947fSAlexander Stetsenko int destroy_flags = 0; 1062*a7ee947fSAlexander Stetsenko char *snap_name; 1063*a7ee947fSAlexander Stetsenko char *be_name; 1064*a7ee947fSAlexander Stetsenko 1065*a7ee947fSAlexander Stetsenko while ((c = getopt(argc, argv, "fFs")) != -1) { 1066*a7ee947fSAlexander Stetsenko switch (c) { 1067*a7ee947fSAlexander Stetsenko case 'f': 1068*a7ee947fSAlexander Stetsenko destroy_flags |= BE_DESTROY_FLAG_FORCE_UNMOUNT; 1069*a7ee947fSAlexander Stetsenko break; 1070*a7ee947fSAlexander Stetsenko case 's': 1071*a7ee947fSAlexander Stetsenko destroy_flags |= BE_DESTROY_FLAG_SNAPSHOTS; 1072*a7ee947fSAlexander Stetsenko break; 1073*a7ee947fSAlexander Stetsenko case 'F': 1074*a7ee947fSAlexander Stetsenko suppress_prompt = B_TRUE; 1075*a7ee947fSAlexander Stetsenko break; 1076*a7ee947fSAlexander Stetsenko default: 1077*a7ee947fSAlexander Stetsenko usage(); 1078*a7ee947fSAlexander Stetsenko return (1); 1079*a7ee947fSAlexander Stetsenko } 1080*a7ee947fSAlexander Stetsenko } 1081*a7ee947fSAlexander Stetsenko 1082*a7ee947fSAlexander Stetsenko argc -= optind; 1083*a7ee947fSAlexander Stetsenko argv += optind; 1084*a7ee947fSAlexander Stetsenko 1085*a7ee947fSAlexander Stetsenko if (argc != 1) { 1086*a7ee947fSAlexander Stetsenko usage(); 1087*a7ee947fSAlexander Stetsenko return (1); 1088*a7ee947fSAlexander Stetsenko } 1089*a7ee947fSAlexander Stetsenko 1090*a7ee947fSAlexander Stetsenko be_name = argv[0]; 1091*a7ee947fSAlexander Stetsenko if (!suppress_prompt && !confirm_destroy(be_name)) { 1092*a7ee947fSAlexander Stetsenko (void) printf(_("%s has not been destroyed.\n"), be_name); 1093*a7ee947fSAlexander Stetsenko return (0); 1094*a7ee947fSAlexander Stetsenko } 1095*a7ee947fSAlexander Stetsenko 1096*a7ee947fSAlexander Stetsenko if ((snap_name = strrchr(be_name, '@')) != NULL) { 1097*a7ee947fSAlexander Stetsenko if (snap_name[1] == '\0') { 1098*a7ee947fSAlexander Stetsenko usage(); 1099*a7ee947fSAlexander Stetsenko return (1); 1100*a7ee947fSAlexander Stetsenko } 1101*a7ee947fSAlexander Stetsenko 1102*a7ee947fSAlexander Stetsenko is_snap = B_TRUE; 1103*a7ee947fSAlexander Stetsenko *snap_name = '\0'; 1104*a7ee947fSAlexander Stetsenko snap_name++; 1105*a7ee947fSAlexander Stetsenko } 1106*a7ee947fSAlexander Stetsenko 1107*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 1108*a7ee947fSAlexander Stetsenko return (1); 1109*a7ee947fSAlexander Stetsenko 1110*a7ee947fSAlexander Stetsenko 1111*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, be_name) != 0) 1112*a7ee947fSAlexander Stetsenko goto out; 1113*a7ee947fSAlexander Stetsenko 1114*a7ee947fSAlexander Stetsenko if (is_snap) { 1115*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_SNAP_NAME, 1116*a7ee947fSAlexander Stetsenko snap_name) != 0) 1117*a7ee947fSAlexander Stetsenko goto out; 1118*a7ee947fSAlexander Stetsenko 1119*a7ee947fSAlexander Stetsenko err = be_destroy_snapshot(be_attrs); 1120*a7ee947fSAlexander Stetsenko } else { 1121*a7ee947fSAlexander Stetsenko if (be_nvl_add_uint16(be_attrs, BE_ATTR_DESTROY_FLAGS, 1122*a7ee947fSAlexander Stetsenko destroy_flags) != 0) 1123*a7ee947fSAlexander Stetsenko goto out; 1124*a7ee947fSAlexander Stetsenko 1125*a7ee947fSAlexander Stetsenko err = be_destroy(be_attrs); 1126*a7ee947fSAlexander Stetsenko } 1127*a7ee947fSAlexander Stetsenko 1128*a7ee947fSAlexander Stetsenko switch (err) { 1129*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1130*a7ee947fSAlexander Stetsenko (void) printf(_("Destroyed successfully\n")); 1131*a7ee947fSAlexander Stetsenko break; 1132*a7ee947fSAlexander Stetsenko case BE_ERR_MOUNTED: 1133*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to destroy %s.\n"), be_name); 1134*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("It is currently mounted and must be " 1135*a7ee947fSAlexander Stetsenko "unmounted before it can be destroyed.\n" "Use 'beadm " 1136*a7ee947fSAlexander Stetsenko "unmount %s' to unmount the BE before destroying\nit or " 1137*a7ee947fSAlexander Stetsenko "'beadm destroy -f %s'.\n"), be_name, be_name); 1138*a7ee947fSAlexander Stetsenko break; 1139*a7ee947fSAlexander Stetsenko case BE_ERR_DESTROY_CURR_BE: 1140*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s is the currently active BE and " 1141*a7ee947fSAlexander Stetsenko "cannot be destroyed.\nYou must boot from another BE in " 1142*a7ee947fSAlexander Stetsenko "order to destroy %s.\n"), be_name, be_name); 1143*a7ee947fSAlexander Stetsenko break; 1144*a7ee947fSAlexander Stetsenko case BE_ERR_ZONES_UNMOUNT: 1145*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to destroy one of " "%s's " 1146*a7ee947fSAlexander Stetsenko "zone BE's.\nUse 'beadm destroy -f %s' or " 1147*a7ee947fSAlexander Stetsenko "'zfs -f destroy <dataset>'.\n"), be_name, be_name); 1148*a7ee947fSAlexander Stetsenko break; 1149*a7ee947fSAlexander Stetsenko case BE_ERR_SS_NOENT: 1150*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1151*a7ee947fSAlexander Stetsenko "to be a valid snapshot.\nPlease check that the name of " 1152*a7ee947fSAlexander Stetsenko "the snapshot provided is correct.\n"), snap_name); 1153*a7ee947fSAlexander Stetsenko break; 1154*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 1155*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 1156*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to destroy %s.\n"), be_name); 1157*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 1158*a7ee947fSAlexander Stetsenko "execute this command.\n")); 1159*a7ee947fSAlexander Stetsenko break; 1160*a7ee947fSAlexander Stetsenko default: 1161*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to destroy %s.\n"), be_name); 1162*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1163*a7ee947fSAlexander Stetsenko } 1164*a7ee947fSAlexander Stetsenko 1165*a7ee947fSAlexander Stetsenko out: 1166*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 1167*a7ee947fSAlexander Stetsenko return (err); 1168*a7ee947fSAlexander Stetsenko } 1169*a7ee947fSAlexander Stetsenko 1170*a7ee947fSAlexander Stetsenko static int 1171*a7ee947fSAlexander Stetsenko be_do_destroy_snapshot(int argc, char **argv) 1172*a7ee947fSAlexander Stetsenko { 1173*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 1174*a7ee947fSAlexander Stetsenko boolean_t suppress_prompt = B_FALSE; 1175*a7ee947fSAlexander Stetsenko int err = 1; 1176*a7ee947fSAlexander Stetsenko char c; 1177*a7ee947fSAlexander Stetsenko char *obe_name; 1178*a7ee947fSAlexander Stetsenko char *snap_name; 1179*a7ee947fSAlexander Stetsenko char *sn; 1180*a7ee947fSAlexander Stetsenko int sz; 1181*a7ee947fSAlexander Stetsenko 1182*a7ee947fSAlexander Stetsenko while ((c = getopt(argc, argv, "F")) != -1) { 1183*a7ee947fSAlexander Stetsenko switch (c) { 1184*a7ee947fSAlexander Stetsenko case 'F': 1185*a7ee947fSAlexander Stetsenko suppress_prompt = B_TRUE; 1186*a7ee947fSAlexander Stetsenko break; 1187*a7ee947fSAlexander Stetsenko default: 1188*a7ee947fSAlexander Stetsenko usage(); 1189*a7ee947fSAlexander Stetsenko return (1); 1190*a7ee947fSAlexander Stetsenko } 1191*a7ee947fSAlexander Stetsenko } 1192*a7ee947fSAlexander Stetsenko 1193*a7ee947fSAlexander Stetsenko argc -= optind; 1194*a7ee947fSAlexander Stetsenko argv += optind; 1195*a7ee947fSAlexander Stetsenko 1196*a7ee947fSAlexander Stetsenko if (argc != 2) { 1197*a7ee947fSAlexander Stetsenko usage(); 1198*a7ee947fSAlexander Stetsenko return (1); 1199*a7ee947fSAlexander Stetsenko } 1200*a7ee947fSAlexander Stetsenko 1201*a7ee947fSAlexander Stetsenko obe_name = argv[0]; 1202*a7ee947fSAlexander Stetsenko snap_name = argv[1]; 1203*a7ee947fSAlexander Stetsenko 1204*a7ee947fSAlexander Stetsenko sz = asprintf(&sn, "%s@%s", obe_name, snap_name); 1205*a7ee947fSAlexander Stetsenko if (sz < 0) { 1206*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("internal error: " 1207*a7ee947fSAlexander Stetsenko "out of memory\n")); 1208*a7ee947fSAlexander Stetsenko return (1); 1209*a7ee947fSAlexander Stetsenko } 1210*a7ee947fSAlexander Stetsenko 1211*a7ee947fSAlexander Stetsenko if (!suppress_prompt && !confirm_destroy(sn)) { 1212*a7ee947fSAlexander Stetsenko (void) printf(_("%s has not been destroyed.\n"), sn); 1213*a7ee947fSAlexander Stetsenko free(sn); 1214*a7ee947fSAlexander Stetsenko return (0); 1215*a7ee947fSAlexander Stetsenko } 1216*a7ee947fSAlexander Stetsenko 1217*a7ee947fSAlexander Stetsenko free(sn); 1218*a7ee947fSAlexander Stetsenko 1219*a7ee947fSAlexander Stetsenko 1220*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 1221*a7ee947fSAlexander Stetsenko return (1); 1222*a7ee947fSAlexander Stetsenko 1223*a7ee947fSAlexander Stetsenko 1224*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 1225*a7ee947fSAlexander Stetsenko goto out; 1226*a7ee947fSAlexander Stetsenko 1227*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name) != 0) 1228*a7ee947fSAlexander Stetsenko goto out; 1229*a7ee947fSAlexander Stetsenko 1230*a7ee947fSAlexander Stetsenko err = be_destroy_snapshot(be_attrs); 1231*a7ee947fSAlexander Stetsenko 1232*a7ee947fSAlexander Stetsenko switch (err) { 1233*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1234*a7ee947fSAlexander Stetsenko (void) printf(_("Destroyed successfully\n")); 1235*a7ee947fSAlexander Stetsenko break; 1236*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 1237*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1238*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 1239*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), obe_name); 1240*a7ee947fSAlexander Stetsenko break; 1241*a7ee947fSAlexander Stetsenko case BE_ERR_SS_NOENT: 1242*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1243*a7ee947fSAlexander Stetsenko "to be a valid snapshot.\nPlease check that the name of " 1244*a7ee947fSAlexander Stetsenko "the snapshot provided is correct.\n"), snap_name); 1245*a7ee947fSAlexander Stetsenko break; 1246*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 1247*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 1248*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to destroy snapshot %s.\n"), 1249*a7ee947fSAlexander Stetsenko snap_name); 1250*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 1251*a7ee947fSAlexander Stetsenko "execute this command.\n")); 1252*a7ee947fSAlexander Stetsenko break; 1253*a7ee947fSAlexander Stetsenko default: 1254*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to destroy snapshot %s.\n"), 1255*a7ee947fSAlexander Stetsenko snap_name); 1256*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1257*a7ee947fSAlexander Stetsenko } 1258*a7ee947fSAlexander Stetsenko 1259*a7ee947fSAlexander Stetsenko out: 1260*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 1261*a7ee947fSAlexander Stetsenko return (err); 1262*a7ee947fSAlexander Stetsenko } 1263*a7ee947fSAlexander Stetsenko 1264*a7ee947fSAlexander Stetsenko static int 1265*a7ee947fSAlexander Stetsenko be_do_list(int argc, char **argv) 1266*a7ee947fSAlexander Stetsenko { 1267*a7ee947fSAlexander Stetsenko be_node_list_t *be_nodes = NULL; 1268*a7ee947fSAlexander Stetsenko boolean_t all = B_FALSE; 1269*a7ee947fSAlexander Stetsenko boolean_t dsets = B_FALSE; 1270*a7ee947fSAlexander Stetsenko boolean_t snaps = B_FALSE; 1271*a7ee947fSAlexander Stetsenko boolean_t parsable = B_FALSE; 1272*a7ee947fSAlexander Stetsenko int err = 1; 1273*a7ee947fSAlexander Stetsenko int c = 0; 1274*a7ee947fSAlexander Stetsenko char *be_name = NULL; 1275*a7ee947fSAlexander Stetsenko 1276*a7ee947fSAlexander Stetsenko while ((c = getopt(argc, argv, "nadsH")) != -1) { 1277*a7ee947fSAlexander Stetsenko switch (c) { 1278*a7ee947fSAlexander Stetsenko case 'a': 1279*a7ee947fSAlexander Stetsenko all = B_TRUE; 1280*a7ee947fSAlexander Stetsenko break; 1281*a7ee947fSAlexander Stetsenko case 'd': 1282*a7ee947fSAlexander Stetsenko dsets = B_TRUE; 1283*a7ee947fSAlexander Stetsenko break; 1284*a7ee947fSAlexander Stetsenko case 's': 1285*a7ee947fSAlexander Stetsenko snaps = B_TRUE; 1286*a7ee947fSAlexander Stetsenko break; 1287*a7ee947fSAlexander Stetsenko case 'H': 1288*a7ee947fSAlexander Stetsenko parsable = B_TRUE; 1289*a7ee947fSAlexander Stetsenko break; 1290*a7ee947fSAlexander Stetsenko default: 1291*a7ee947fSAlexander Stetsenko usage(); 1292*a7ee947fSAlexander Stetsenko return (1); 1293*a7ee947fSAlexander Stetsenko } 1294*a7ee947fSAlexander Stetsenko } 1295*a7ee947fSAlexander Stetsenko 1296*a7ee947fSAlexander Stetsenko if (all) { 1297*a7ee947fSAlexander Stetsenko if (dsets) { 1298*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Invalid options: -a and %s " 1299*a7ee947fSAlexander Stetsenko "are mutually exclusive.\n"), "-d"); 1300*a7ee947fSAlexander Stetsenko usage(); 1301*a7ee947fSAlexander Stetsenko return (1); 1302*a7ee947fSAlexander Stetsenko } 1303*a7ee947fSAlexander Stetsenko if (snaps) { 1304*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Invalid options: -a and %s " 1305*a7ee947fSAlexander Stetsenko "are mutually exclusive.\n"), "-s"); 1306*a7ee947fSAlexander Stetsenko usage(); 1307*a7ee947fSAlexander Stetsenko return (1); 1308*a7ee947fSAlexander Stetsenko } 1309*a7ee947fSAlexander Stetsenko 1310*a7ee947fSAlexander Stetsenko dsets = B_TRUE; 1311*a7ee947fSAlexander Stetsenko snaps = B_TRUE; 1312*a7ee947fSAlexander Stetsenko } 1313*a7ee947fSAlexander Stetsenko 1314*a7ee947fSAlexander Stetsenko argc -= optind; 1315*a7ee947fSAlexander Stetsenko argv += optind; 1316*a7ee947fSAlexander Stetsenko 1317*a7ee947fSAlexander Stetsenko 1318*a7ee947fSAlexander Stetsenko if (argc == 1) 1319*a7ee947fSAlexander Stetsenko be_name = argv[0]; 1320*a7ee947fSAlexander Stetsenko 1321*a7ee947fSAlexander Stetsenko err = be_list(be_name, &be_nodes); 1322*a7ee947fSAlexander Stetsenko 1323*a7ee947fSAlexander Stetsenko switch (err) { 1324*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1325*a7ee947fSAlexander Stetsenko print_nodes(be_name, dsets, snaps, parsable, be_nodes); 1326*a7ee947fSAlexander Stetsenko break; 1327*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 1328*a7ee947fSAlexander Stetsenko if (be_name == NULL) 1329*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("No boot environments found " 1330*a7ee947fSAlexander Stetsenko "on this system.\n")); 1331*a7ee947fSAlexander Stetsenko else { 1332*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1333*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 1334*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), be_name); 1335*a7ee947fSAlexander Stetsenko } 1336*a7ee947fSAlexander Stetsenko break; 1337*a7ee947fSAlexander Stetsenko default: 1338*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to display Boot " 1339*a7ee947fSAlexander Stetsenko "Environment\n")); 1340*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1341*a7ee947fSAlexander Stetsenko } 1342*a7ee947fSAlexander Stetsenko 1343*a7ee947fSAlexander Stetsenko if (be_nodes != NULL) 1344*a7ee947fSAlexander Stetsenko be_free_list(be_nodes); 1345*a7ee947fSAlexander Stetsenko return (err); 1346*a7ee947fSAlexander Stetsenko } 1347*a7ee947fSAlexander Stetsenko 1348*a7ee947fSAlexander Stetsenko static int 1349*a7ee947fSAlexander Stetsenko be_do_mount(int argc, char **argv) 1350*a7ee947fSAlexander Stetsenko { 1351*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 1352*a7ee947fSAlexander Stetsenko boolean_t shared_fs = B_FALSE; 1353*a7ee947fSAlexander Stetsenko int err = 1; 1354*a7ee947fSAlexander Stetsenko int c; 1355*a7ee947fSAlexander Stetsenko int mount_flags = 0; 1356*a7ee947fSAlexander Stetsenko char *obe_name; 1357*a7ee947fSAlexander Stetsenko char *mountpoint; 1358*a7ee947fSAlexander Stetsenko char *tmp_mp = NULL; 1359*a7ee947fSAlexander Stetsenko 1360*a7ee947fSAlexander Stetsenko while ((c = getopt(argc, argv, "s:")) != -1) { 1361*a7ee947fSAlexander Stetsenko switch (c) { 1362*a7ee947fSAlexander Stetsenko case 's': 1363*a7ee947fSAlexander Stetsenko shared_fs = B_TRUE; 1364*a7ee947fSAlexander Stetsenko 1365*a7ee947fSAlexander Stetsenko mount_flags |= BE_MOUNT_FLAG_SHARED_FS; 1366*a7ee947fSAlexander Stetsenko 1367*a7ee947fSAlexander Stetsenko if (strcmp(optarg, "rw") == 0) { 1368*a7ee947fSAlexander Stetsenko mount_flags |= BE_MOUNT_FLAG_SHARED_RW; 1369*a7ee947fSAlexander Stetsenko } else if (strcmp(optarg, "ro") != 0) { 1370*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("The -s flag " 1371*a7ee947fSAlexander Stetsenko "requires an argument [ rw | ro ]\n")); 1372*a7ee947fSAlexander Stetsenko usage(); 1373*a7ee947fSAlexander Stetsenko return (1); 1374*a7ee947fSAlexander Stetsenko } 1375*a7ee947fSAlexander Stetsenko 1376*a7ee947fSAlexander Stetsenko break; 1377*a7ee947fSAlexander Stetsenko default: 1378*a7ee947fSAlexander Stetsenko usage(); 1379*a7ee947fSAlexander Stetsenko return (1); 1380*a7ee947fSAlexander Stetsenko } 1381*a7ee947fSAlexander Stetsenko } 1382*a7ee947fSAlexander Stetsenko 1383*a7ee947fSAlexander Stetsenko argc -= optind; 1384*a7ee947fSAlexander Stetsenko argv += optind; 1385*a7ee947fSAlexander Stetsenko 1386*a7ee947fSAlexander Stetsenko if (argc < 1 || argc > 2) { 1387*a7ee947fSAlexander Stetsenko usage(); 1388*a7ee947fSAlexander Stetsenko return (1); 1389*a7ee947fSAlexander Stetsenko } 1390*a7ee947fSAlexander Stetsenko 1391*a7ee947fSAlexander Stetsenko obe_name = argv[0]; 1392*a7ee947fSAlexander Stetsenko 1393*a7ee947fSAlexander Stetsenko if (argc == 2) { 1394*a7ee947fSAlexander Stetsenko mountpoint = argv[1]; 1395*a7ee947fSAlexander Stetsenko if (mountpoint[0] != '/') { 1396*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Invalid mount point %s. " 1397*a7ee947fSAlexander Stetsenko "Mount point must start with a /.\n"), mountpoint); 1398*a7ee947fSAlexander Stetsenko return (1); 1399*a7ee947fSAlexander Stetsenko } 1400*a7ee947fSAlexander Stetsenko } else { 1401*a7ee947fSAlexander Stetsenko const char *tmpdir = getenv("TMPDIR"); 1402*a7ee947fSAlexander Stetsenko const char *tmpname = "tmp.XXXXXX"; 1403*a7ee947fSAlexander Stetsenko int sz; 1404*a7ee947fSAlexander Stetsenko 1405*a7ee947fSAlexander Stetsenko if (tmpdir == NULL) 1406*a7ee947fSAlexander Stetsenko tmpdir = "/tmp"; 1407*a7ee947fSAlexander Stetsenko 1408*a7ee947fSAlexander Stetsenko sz = asprintf(&tmp_mp, "%s/%s", tmpdir, tmpname); 1409*a7ee947fSAlexander Stetsenko if (sz < 0) { 1410*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("internal error: " 1411*a7ee947fSAlexander Stetsenko "out of memory\n")); 1412*a7ee947fSAlexander Stetsenko return (1); 1413*a7ee947fSAlexander Stetsenko } 1414*a7ee947fSAlexander Stetsenko 1415*a7ee947fSAlexander Stetsenko mountpoint = mkdtemp(tmp_mp); 1416*a7ee947fSAlexander Stetsenko } 1417*a7ee947fSAlexander Stetsenko 1418*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 1419*a7ee947fSAlexander Stetsenko return (1); 1420*a7ee947fSAlexander Stetsenko 1421*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 1422*a7ee947fSAlexander Stetsenko goto out; 1423*a7ee947fSAlexander Stetsenko 1424*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_MOUNTPOINT, mountpoint) != 0) 1425*a7ee947fSAlexander Stetsenko goto out; 1426*a7ee947fSAlexander Stetsenko 1427*a7ee947fSAlexander Stetsenko if (shared_fs && be_nvl_add_uint16(be_attrs, BE_ATTR_MOUNT_FLAGS, 1428*a7ee947fSAlexander Stetsenko mount_flags) != 0) 1429*a7ee947fSAlexander Stetsenko goto out; 1430*a7ee947fSAlexander Stetsenko 1431*a7ee947fSAlexander Stetsenko err = be_mount(be_attrs); 1432*a7ee947fSAlexander Stetsenko 1433*a7ee947fSAlexander Stetsenko switch (err) { 1434*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1435*a7ee947fSAlexander Stetsenko (void) printf(_("Mounted successfully on: '%s'\n"), mountpoint); 1436*a7ee947fSAlexander Stetsenko break; 1437*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 1438*a7ee947fSAlexander Stetsenko err = 1; 1439*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1440*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 1441*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), obe_name); 1442*a7ee947fSAlexander Stetsenko break; 1443*a7ee947fSAlexander Stetsenko case BE_ERR_MOUNTED: 1444*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s is already mounted.\n" 1445*a7ee947fSAlexander Stetsenko "Please unmount the BE before mounting it again.\n"), 1446*a7ee947fSAlexander Stetsenko obe_name); 1447*a7ee947fSAlexander Stetsenko break; 1448*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 1449*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 1450*a7ee947fSAlexander Stetsenko err = 1; 1451*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to mount %s.\n"), obe_name); 1452*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 1453*a7ee947fSAlexander Stetsenko "execute this command.\n")); 1454*a7ee947fSAlexander Stetsenko break; 1455*a7ee947fSAlexander Stetsenko default: 1456*a7ee947fSAlexander Stetsenko err = 1; 1457*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to mount %s.\n"), obe_name); 1458*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1459*a7ee947fSAlexander Stetsenko } 1460*a7ee947fSAlexander Stetsenko 1461*a7ee947fSAlexander Stetsenko out: 1462*a7ee947fSAlexander Stetsenko if (tmp_mp != NULL) 1463*a7ee947fSAlexander Stetsenko free(tmp_mp); 1464*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 1465*a7ee947fSAlexander Stetsenko return (err); 1466*a7ee947fSAlexander Stetsenko } 1467*a7ee947fSAlexander Stetsenko 1468*a7ee947fSAlexander Stetsenko static int 1469*a7ee947fSAlexander Stetsenko be_do_unmount(int argc, char **argv) 1470*a7ee947fSAlexander Stetsenko { 1471*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 1472*a7ee947fSAlexander Stetsenko char *obe_name; 1473*a7ee947fSAlexander Stetsenko int err = 1; 1474*a7ee947fSAlexander Stetsenko int c; 1475*a7ee947fSAlexander Stetsenko int unmount_flags = 0; 1476*a7ee947fSAlexander Stetsenko 1477*a7ee947fSAlexander Stetsenko while ((c = getopt(argc, argv, "f")) != -1) { 1478*a7ee947fSAlexander Stetsenko switch (c) { 1479*a7ee947fSAlexander Stetsenko case 'f': 1480*a7ee947fSAlexander Stetsenko unmount_flags |= BE_UNMOUNT_FLAG_FORCE; 1481*a7ee947fSAlexander Stetsenko break; 1482*a7ee947fSAlexander Stetsenko default: 1483*a7ee947fSAlexander Stetsenko usage(); 1484*a7ee947fSAlexander Stetsenko return (1); 1485*a7ee947fSAlexander Stetsenko } 1486*a7ee947fSAlexander Stetsenko } 1487*a7ee947fSAlexander Stetsenko 1488*a7ee947fSAlexander Stetsenko argc -= optind; 1489*a7ee947fSAlexander Stetsenko argv += optind; 1490*a7ee947fSAlexander Stetsenko 1491*a7ee947fSAlexander Stetsenko if (argc != 1) { 1492*a7ee947fSAlexander Stetsenko usage(); 1493*a7ee947fSAlexander Stetsenko return (1); 1494*a7ee947fSAlexander Stetsenko } 1495*a7ee947fSAlexander Stetsenko 1496*a7ee947fSAlexander Stetsenko obe_name = argv[0]; 1497*a7ee947fSAlexander Stetsenko 1498*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 1499*a7ee947fSAlexander Stetsenko return (1); 1500*a7ee947fSAlexander Stetsenko 1501*a7ee947fSAlexander Stetsenko 1502*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 1503*a7ee947fSAlexander Stetsenko goto out; 1504*a7ee947fSAlexander Stetsenko 1505*a7ee947fSAlexander Stetsenko if (be_nvl_add_uint16(be_attrs, BE_ATTR_UNMOUNT_FLAGS, 1506*a7ee947fSAlexander Stetsenko unmount_flags) != 0) 1507*a7ee947fSAlexander Stetsenko goto out; 1508*a7ee947fSAlexander Stetsenko 1509*a7ee947fSAlexander Stetsenko err = be_unmount(be_attrs); 1510*a7ee947fSAlexander Stetsenko 1511*a7ee947fSAlexander Stetsenko switch (err) { 1512*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1513*a7ee947fSAlexander Stetsenko (void) printf(_("Unmounted successfully\n")); 1514*a7ee947fSAlexander Stetsenko break; 1515*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 1516*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1517*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 1518*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), obe_name); 1519*a7ee947fSAlexander Stetsenko break; 1520*a7ee947fSAlexander Stetsenko case BE_ERR_UMOUNT_CURR_BE: 1521*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s is the currently active BE.\n" 1522*a7ee947fSAlexander Stetsenko "It cannot be unmounted unless another BE is the " 1523*a7ee947fSAlexander Stetsenko "currently active BE.\n"), obe_name); 1524*a7ee947fSAlexander Stetsenko break; 1525*a7ee947fSAlexander Stetsenko case BE_ERR_UMOUNT_SHARED: 1526*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s is a shared file system and it " 1527*a7ee947fSAlexander Stetsenko "cannot be unmounted.\n"), obe_name); 1528*a7ee947fSAlexander Stetsenko break; 1529*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 1530*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 1531*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to unmount %s.\n"), obe_name); 1532*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 1533*a7ee947fSAlexander Stetsenko "execute this command.\n")); 1534*a7ee947fSAlexander Stetsenko break; 1535*a7ee947fSAlexander Stetsenko default: 1536*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Unable to unmount %s.\n"), obe_name); 1537*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1538*a7ee947fSAlexander Stetsenko } 1539*a7ee947fSAlexander Stetsenko 1540*a7ee947fSAlexander Stetsenko out: 1541*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 1542*a7ee947fSAlexander Stetsenko return (err); 1543*a7ee947fSAlexander Stetsenko } 1544*a7ee947fSAlexander Stetsenko 1545*a7ee947fSAlexander Stetsenko static int 1546*a7ee947fSAlexander Stetsenko be_do_rename(int argc, char **argv) 1547*a7ee947fSAlexander Stetsenko { 1548*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 1549*a7ee947fSAlexander Stetsenko char *obe_name; 1550*a7ee947fSAlexander Stetsenko char *nbe_name; 1551*a7ee947fSAlexander Stetsenko int err = 1; 1552*a7ee947fSAlexander Stetsenko 1553*a7ee947fSAlexander Stetsenko argc -= optind; 1554*a7ee947fSAlexander Stetsenko argv += optind; 1555*a7ee947fSAlexander Stetsenko 1556*a7ee947fSAlexander Stetsenko if (argc != 2) { 1557*a7ee947fSAlexander Stetsenko usage(); 1558*a7ee947fSAlexander Stetsenko return (1); 1559*a7ee947fSAlexander Stetsenko } 1560*a7ee947fSAlexander Stetsenko 1561*a7ee947fSAlexander Stetsenko obe_name = argv[0]; 1562*a7ee947fSAlexander Stetsenko nbe_name = argv[1]; 1563*a7ee947fSAlexander Stetsenko 1564*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 1565*a7ee947fSAlexander Stetsenko return (1); 1566*a7ee947fSAlexander Stetsenko 1567*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 1568*a7ee947fSAlexander Stetsenko goto out; 1569*a7ee947fSAlexander Stetsenko 1570*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_NEW_BE_NAME, nbe_name) != 0) 1571*a7ee947fSAlexander Stetsenko goto out; 1572*a7ee947fSAlexander Stetsenko 1573*a7ee947fSAlexander Stetsenko err = be_rename(be_attrs); 1574*a7ee947fSAlexander Stetsenko 1575*a7ee947fSAlexander Stetsenko switch (err) { 1576*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1577*a7ee947fSAlexander Stetsenko (void) printf(_("Renamed successfully\n")); 1578*a7ee947fSAlexander Stetsenko break; 1579*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 1580*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1581*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 1582*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), obe_name); 1583*a7ee947fSAlexander Stetsenko break; 1584*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 1585*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 1586*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Rename of BE %s failed.\n"), 1587*a7ee947fSAlexander Stetsenko obe_name); 1588*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 1589*a7ee947fSAlexander Stetsenko "execute this command.\n")); 1590*a7ee947fSAlexander Stetsenko break; 1591*a7ee947fSAlexander Stetsenko default: 1592*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Rename of BE %s failed.\n"), 1593*a7ee947fSAlexander Stetsenko obe_name); 1594*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1595*a7ee947fSAlexander Stetsenko } 1596*a7ee947fSAlexander Stetsenko 1597*a7ee947fSAlexander Stetsenko out: 1598*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 1599*a7ee947fSAlexander Stetsenko return (err); 1600*a7ee947fSAlexander Stetsenko } 1601*a7ee947fSAlexander Stetsenko 1602*a7ee947fSAlexander Stetsenko static int 1603*a7ee947fSAlexander Stetsenko be_do_rollback(int argc, char **argv) 1604*a7ee947fSAlexander Stetsenko { 1605*a7ee947fSAlexander Stetsenko nvlist_t *be_attrs; 1606*a7ee947fSAlexander Stetsenko char *obe_name; 1607*a7ee947fSAlexander Stetsenko char *snap_name; 1608*a7ee947fSAlexander Stetsenko int err = 1; 1609*a7ee947fSAlexander Stetsenko 1610*a7ee947fSAlexander Stetsenko argc -= optind; 1611*a7ee947fSAlexander Stetsenko argv += optind; 1612*a7ee947fSAlexander Stetsenko 1613*a7ee947fSAlexander Stetsenko if (argc < 1 || argc > 2) { 1614*a7ee947fSAlexander Stetsenko usage(); 1615*a7ee947fSAlexander Stetsenko return (1); 1616*a7ee947fSAlexander Stetsenko } 1617*a7ee947fSAlexander Stetsenko 1618*a7ee947fSAlexander Stetsenko obe_name = argv[0]; 1619*a7ee947fSAlexander Stetsenko if (argc == 2) 1620*a7ee947fSAlexander Stetsenko snap_name = argv[1]; 1621*a7ee947fSAlexander Stetsenko else { /* argc == 1 */ 1622*a7ee947fSAlexander Stetsenko if ((snap_name = strrchr(obe_name, '@')) != NULL) { 1623*a7ee947fSAlexander Stetsenko if (snap_name[1] == '\0') { 1624*a7ee947fSAlexander Stetsenko usage(); 1625*a7ee947fSAlexander Stetsenko return (1); 1626*a7ee947fSAlexander Stetsenko } 1627*a7ee947fSAlexander Stetsenko 1628*a7ee947fSAlexander Stetsenko snap_name[0] = '\0'; 1629*a7ee947fSAlexander Stetsenko snap_name++; 1630*a7ee947fSAlexander Stetsenko } else { 1631*a7ee947fSAlexander Stetsenko usage(); 1632*a7ee947fSAlexander Stetsenko return (1); 1633*a7ee947fSAlexander Stetsenko } 1634*a7ee947fSAlexander Stetsenko } 1635*a7ee947fSAlexander Stetsenko 1636*a7ee947fSAlexander Stetsenko if (be_nvl_alloc(&be_attrs) != 0) 1637*a7ee947fSAlexander Stetsenko return (1); 1638*a7ee947fSAlexander Stetsenko 1639*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) 1640*a7ee947fSAlexander Stetsenko goto out; 1641*a7ee947fSAlexander Stetsenko 1642*a7ee947fSAlexander Stetsenko if (be_nvl_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name) != 0) 1643*a7ee947fSAlexander Stetsenko goto out; 1644*a7ee947fSAlexander Stetsenko 1645*a7ee947fSAlexander Stetsenko err = be_rollback(be_attrs); 1646*a7ee947fSAlexander Stetsenko 1647*a7ee947fSAlexander Stetsenko switch (err) { 1648*a7ee947fSAlexander Stetsenko case BE_SUCCESS: 1649*a7ee947fSAlexander Stetsenko (void) printf(_("Rolled back successfully\n")); 1650*a7ee947fSAlexander Stetsenko break; 1651*a7ee947fSAlexander Stetsenko case BE_ERR_BE_NOENT: 1652*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1653*a7ee947fSAlexander Stetsenko "to be a valid BE.\nPlease check that the name of " 1654*a7ee947fSAlexander Stetsenko "the BE provided is correct.\n"), obe_name); 1655*a7ee947fSAlexander Stetsenko break; 1656*a7ee947fSAlexander Stetsenko case BE_ERR_SS_NOENT: 1657*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("%s does not exist or appear " 1658*a7ee947fSAlexander Stetsenko "to be a valid snapshot.\nPlease check that the name of " 1659*a7ee947fSAlexander Stetsenko "the snapshot provided is correct.\n"), snap_name); 1660*a7ee947fSAlexander Stetsenko break; 1661*a7ee947fSAlexander Stetsenko case BE_ERR_PERM: 1662*a7ee947fSAlexander Stetsenko case BE_ERR_ACCESS: 1663*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Rollback of BE %s snapshot %s " 1664*a7ee947fSAlexander Stetsenko "failed.\n"), obe_name, snap_name); 1665*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("You have insufficient privileges to " 1666*a7ee947fSAlexander Stetsenko "execute this command.\n")); 1667*a7ee947fSAlexander Stetsenko break; 1668*a7ee947fSAlexander Stetsenko default: 1669*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, _("Rollback of BE %s snapshot %s " 1670*a7ee947fSAlexander Stetsenko "failed.\n"), obe_name, snap_name); 1671*a7ee947fSAlexander Stetsenko (void) fprintf(stderr, "%s\n", be_err_to_str(err)); 1672*a7ee947fSAlexander Stetsenko } 1673*a7ee947fSAlexander Stetsenko 1674*a7ee947fSAlexander Stetsenko out: 1675*a7ee947fSAlexander Stetsenko nvlist_free(be_attrs); 1676*a7ee947fSAlexander Stetsenko return (err); 1677*a7ee947fSAlexander Stetsenko } 1678