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