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