1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <assert.h> 30 #include <ctype.h> 31 #include <errno.h> 32 #include <libgen.h> 33 #include <libintl.h> 34 #include <libuutil.h> 35 #include <locale.h> 36 #include <stddef.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <strings.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <zone.h> 43 #include <sys/mkdev.h> 44 #include <sys/mntent.h> 45 #include <sys/mnttab.h> 46 #include <sys/mount.h> 47 #include <sys/stat.h> 48 49 #include <libzfs.h> 50 51 #include "zfs_iter.h" 52 #include "zfs_util.h" 53 54 libzfs_handle_t *g_zfs; 55 56 static FILE *mnttab_file; 57 58 static int zfs_do_clone(int argc, char **argv); 59 static int zfs_do_create(int argc, char **argv); 60 static int zfs_do_destroy(int argc, char **argv); 61 static int zfs_do_get(int argc, char **argv); 62 static int zfs_do_inherit(int argc, char **argv); 63 static int zfs_do_list(int argc, char **argv); 64 static int zfs_do_mount(int argc, char **argv); 65 static int zfs_do_rename(int argc, char **argv); 66 static int zfs_do_rollback(int argc, char **argv); 67 static int zfs_do_set(int argc, char **argv); 68 static int zfs_do_snapshot(int argc, char **argv); 69 static int zfs_do_unmount(int argc, char **argv); 70 static int zfs_do_share(int argc, char **argv); 71 static int zfs_do_unshare(int argc, char **argv); 72 static int zfs_do_send(int argc, char **argv); 73 static int zfs_do_receive(int argc, char **argv); 74 static int zfs_do_promote(int argc, char **argv); 75 76 /* 77 * These libumem hooks provide a reasonable set of defaults for the allocator's 78 * debugging facilities. 79 */ 80 const char * 81 _umem_debug_init(void) 82 { 83 return ("default,verbose"); /* $UMEM_DEBUG setting */ 84 } 85 86 const char * 87 _umem_logging_init(void) 88 { 89 return ("fail,contents"); /* $UMEM_LOGGING setting */ 90 } 91 92 typedef enum { 93 HELP_CLONE, 94 HELP_CREATE, 95 HELP_DESTROY, 96 HELP_GET, 97 HELP_INHERIT, 98 HELP_LIST, 99 HELP_MOUNT, 100 HELP_PROMOTE, 101 HELP_RECEIVE, 102 HELP_RENAME, 103 HELP_ROLLBACK, 104 HELP_SEND, 105 HELP_SET, 106 HELP_SHARE, 107 HELP_SNAPSHOT, 108 HELP_UNMOUNT, 109 HELP_UNSHARE 110 } zfs_help_t; 111 112 typedef struct zfs_command { 113 const char *name; 114 int (*func)(int argc, char **argv); 115 zfs_help_t usage; 116 } zfs_command_t; 117 118 /* 119 * Master command table. Each ZFS command has a name, associated function, and 120 * usage message. The usage messages need to be internationalized, so we have 121 * to have a function to return the usage message based on a command index. 122 * 123 * These commands are organized according to how they are displayed in the usage 124 * message. An empty command (one with a NULL name) indicates an empty line in 125 * the generic usage message. 126 */ 127 static zfs_command_t command_table[] = { 128 { "create", zfs_do_create, HELP_CREATE }, 129 { "destroy", zfs_do_destroy, HELP_DESTROY }, 130 { NULL }, 131 { "snapshot", zfs_do_snapshot, HELP_SNAPSHOT }, 132 { "rollback", zfs_do_rollback, HELP_ROLLBACK }, 133 { "clone", zfs_do_clone, HELP_CLONE }, 134 { "promote", zfs_do_promote, HELP_PROMOTE }, 135 { "rename", zfs_do_rename, HELP_RENAME }, 136 { NULL }, 137 { "list", zfs_do_list, HELP_LIST }, 138 { NULL }, 139 { "set", zfs_do_set, HELP_SET }, 140 { "get", zfs_do_get, HELP_GET }, 141 { "inherit", zfs_do_inherit, HELP_INHERIT }, 142 { NULL }, 143 { "mount", zfs_do_mount, HELP_MOUNT }, 144 { NULL }, 145 { "unmount", zfs_do_unmount, HELP_UNMOUNT }, 146 { NULL }, 147 { "share", zfs_do_share, HELP_SHARE }, 148 { NULL }, 149 { "unshare", zfs_do_unshare, HELP_UNSHARE }, 150 { NULL }, 151 { "send", zfs_do_send, HELP_SEND }, 152 { "receive", zfs_do_receive, HELP_RECEIVE }, 153 }; 154 155 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 156 157 zfs_command_t *current_command; 158 159 static const char * 160 get_usage(zfs_help_t idx) 161 { 162 switch (idx) { 163 case HELP_CLONE: 164 return (gettext("\tclone <snapshot> <filesystem|volume>\n")); 165 case HELP_CREATE: 166 return (gettext("\tcreate [[-o property=value] ... ] " 167 "<filesystem>\n" 168 "\tcreate [-s] [-b blocksize] [[-o property=value] ...]\n" 169 "\t -V <size> <volume>\n")); 170 case HELP_DESTROY: 171 return (gettext("\tdestroy [-rRf] " 172 "<filesystem|volume|snapshot>\n")); 173 case HELP_GET: 174 return (gettext("\tget [-rHp] [-o field[,field]...] " 175 "[-s source[,source]...]\n" 176 "\t <all | property[,property]...> " 177 "[filesystem|volume|snapshot] ...\n")); 178 case HELP_INHERIT: 179 return (gettext("\tinherit [-r] <property> " 180 "<filesystem|volume> ...\n")); 181 case HELP_LIST: 182 return (gettext("\tlist [-rH] [-o property[,property]...] " 183 "[-t type[,type]...]\n" 184 "\t [-s property [-s property]...]" 185 " [-S property [-S property]...]\n" 186 "\t [filesystem|volume|snapshot] ...\n")); 187 case HELP_MOUNT: 188 return (gettext("\tmount\n" 189 "\tmount [-o opts] [-O] -a\n" 190 "\tmount [-o opts] [-O] <filesystem>\n")); 191 case HELP_PROMOTE: 192 return (gettext("\tpromote <clone filesystem>\n")); 193 case HELP_RECEIVE: 194 return (gettext("\treceive [-vnF] <filesystem|volume|" 195 "snapshot>\n" 196 "\treceive [-vnF] -d <filesystem>\n")); 197 case HELP_RENAME: 198 return (gettext("\trename <filesystem|volume|snapshot> " 199 "<filesystem|volume|snapshot>\n")); 200 case HELP_ROLLBACK: 201 return (gettext("\trollback [-rRf] <snapshot>\n")); 202 case HELP_SEND: 203 return (gettext("\tsend [-i <snapshot>] <snapshot>\n")); 204 case HELP_SET: 205 return (gettext("\tset <property=value> " 206 "<filesystem|volume> ...\n")); 207 case HELP_SHARE: 208 return (gettext("\tshare -a\n" 209 "\tshare <filesystem>\n")); 210 case HELP_SNAPSHOT: 211 return (gettext("\tsnapshot [-r] " 212 "<filesystem@name|volume@name>\n")); 213 case HELP_UNMOUNT: 214 return (gettext("\tunmount [-f] -a\n" 215 "\tunmount [-f] <filesystem|mountpoint>\n")); 216 case HELP_UNSHARE: 217 return (gettext("\tunshare [-f] -a\n" 218 "\tunshare [-f] <filesystem|mountpoint>\n")); 219 } 220 221 abort(); 222 /* NOTREACHED */ 223 } 224 225 /* 226 * Utility function to guarantee malloc() success. 227 */ 228 void * 229 safe_malloc(size_t size) 230 { 231 void *data; 232 233 if ((data = calloc(1, size)) == NULL) { 234 (void) fprintf(stderr, "internal error: out of memory\n"); 235 exit(1); 236 } 237 238 return (data); 239 } 240 241 /* 242 * Callback routinue that will print out information for each of the 243 * the properties. 244 */ 245 static zfs_prop_t 246 usage_prop_cb(zfs_prop_t prop, void *cb) 247 { 248 FILE *fp = cb; 249 250 (void) fprintf(fp, "\t%-13s ", zfs_prop_to_name(prop)); 251 252 if (zfs_prop_readonly(prop)) 253 (void) fprintf(fp, " NO "); 254 else 255 (void) fprintf(fp, " YES "); 256 257 if (zfs_prop_inheritable(prop)) 258 (void) fprintf(fp, " YES "); 259 else 260 (void) fprintf(fp, " NO "); 261 262 if (zfs_prop_values(prop) == NULL) 263 (void) fprintf(fp, "-\n"); 264 else 265 (void) fprintf(fp, "%s\n", zfs_prop_values(prop)); 266 267 return (ZFS_PROP_CONT); 268 } 269 270 /* 271 * Display usage message. If we're inside a command, display only the usage for 272 * that command. Otherwise, iterate over the entire command table and display 273 * a complete usage message. 274 */ 275 static void 276 usage(boolean_t requested) 277 { 278 int i; 279 boolean_t show_properties = B_FALSE; 280 FILE *fp = requested ? stdout : stderr; 281 282 if (current_command == NULL) { 283 284 (void) fprintf(fp, gettext("usage: zfs command args ...\n")); 285 (void) fprintf(fp, 286 gettext("where 'command' is one of the following:\n\n")); 287 288 for (i = 0; i < NCOMMAND; i++) { 289 if (command_table[i].name == NULL) 290 (void) fprintf(fp, "\n"); 291 else 292 (void) fprintf(fp, "%s", 293 get_usage(command_table[i].usage)); 294 } 295 296 (void) fprintf(fp, gettext("\nEach dataset is of the form: " 297 "pool/[dataset/]*dataset[@name]\n")); 298 } else { 299 (void) fprintf(fp, gettext("usage:\n")); 300 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 301 } 302 303 if (current_command != NULL && 304 (strcmp(current_command->name, "set") == 0 || 305 strcmp(current_command->name, "get") == 0 || 306 strcmp(current_command->name, "inherit") == 0 || 307 strcmp(current_command->name, "list") == 0)) 308 show_properties = B_TRUE; 309 310 if (show_properties) { 311 312 (void) fprintf(fp, 313 gettext("\nThe following properties are supported:\n")); 314 315 (void) fprintf(fp, "\n\t%-13s %s %s %s\n\n", 316 "PROPERTY", "EDIT", "INHERIT", "VALUES"); 317 318 /* Iterate over all properties */ 319 (void) zfs_prop_iter(usage_prop_cb, fp, B_FALSE); 320 321 (void) fprintf(fp, gettext("\nSizes are specified in bytes " 322 "with standard units such as K, M, G, etc.\n")); 323 (void) fprintf(fp, gettext("\n\nUser-defined properties can " 324 "be specified by using a name containing a colon (:).\n")); 325 } else { 326 /* 327 * TRANSLATION NOTE: 328 * "zfs set|get" must not be localised this is the 329 * command name and arguments. 330 */ 331 (void) fprintf(fp, 332 gettext("\nFor the property list, run: zfs set|get\n")); 333 } 334 335 /* 336 * See comments at end of main(). 337 */ 338 if (getenv("ZFS_ABORT") != NULL) { 339 (void) printf("dumping core by request\n"); 340 abort(); 341 } 342 343 exit(requested ? 0 : 2); 344 } 345 346 /* 347 * zfs clone <fs, snap, vol> fs 348 * 349 * Given an existing dataset, create a writable copy whose initial contents 350 * are the same as the source. The newly created dataset maintains a 351 * dependency on the original; the original cannot be destroyed so long as 352 * the clone exists. 353 */ 354 static int 355 zfs_do_clone(int argc, char **argv) 356 { 357 zfs_handle_t *zhp; 358 int ret; 359 360 /* check options */ 361 if (argc > 1 && argv[1][0] == '-') { 362 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 363 argv[1][1]); 364 usage(B_FALSE); 365 } 366 367 /* check number of arguments */ 368 if (argc < 2) { 369 (void) fprintf(stderr, gettext("missing source dataset " 370 "argument\n")); 371 usage(B_FALSE); 372 } 373 if (argc < 3) { 374 (void) fprintf(stderr, gettext("missing target dataset " 375 "argument\n")); 376 usage(B_FALSE); 377 } 378 if (argc > 3) { 379 (void) fprintf(stderr, gettext("too many arguments\n")); 380 usage(B_FALSE); 381 } 382 383 /* open the source dataset */ 384 if ((zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_SNAPSHOT)) == NULL) 385 return (1); 386 387 /* pass to libzfs */ 388 ret = zfs_clone(zhp, argv[2], NULL); 389 390 /* create the mountpoint if necessary */ 391 if (ret == 0) { 392 zfs_handle_t *clone = zfs_open(g_zfs, argv[2], ZFS_TYPE_ANY); 393 if (clone != NULL) { 394 if ((ret = zfs_mount(clone, NULL, 0)) == 0) 395 ret = zfs_share(clone); 396 zfs_close(clone); 397 } 398 zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE); 399 } 400 401 zfs_close(zhp); 402 403 return (ret == 0 ? 0 : 1); 404 } 405 406 /* 407 * zfs create [-o prop=value] ... fs 408 * zfs create [-s] [-b blocksize] [-o prop=value] ... -V vol size 409 * 410 * Create a new dataset. This command can be used to create filesystems 411 * and volumes. Snapshot creation is handled by 'zfs snapshot'. 412 * For volumes, the user must specify a size to be used. 413 * 414 * The '-s' flag applies only to volumes, and indicates that we should not try 415 * to set the reservation for this volume. By default we set a reservation 416 * equal to the size for any volume. 417 */ 418 static int 419 zfs_do_create(int argc, char **argv) 420 { 421 zfs_type_t type = ZFS_TYPE_FILESYSTEM; 422 zfs_handle_t *zhp = NULL; 423 uint64_t volsize; 424 int c; 425 boolean_t noreserve = B_FALSE; 426 int ret = 1; 427 nvlist_t *props = NULL; 428 uint64_t intval; 429 char *propname; 430 char *propval = NULL; 431 char *strval; 432 433 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 434 (void) fprintf(stderr, gettext("internal error: " 435 "out of memory\n")); 436 return (1); 437 } 438 439 /* check options */ 440 while ((c = getopt(argc, argv, ":V:b:so:")) != -1) { 441 switch (c) { 442 case 'V': 443 type = ZFS_TYPE_VOLUME; 444 if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { 445 (void) fprintf(stderr, gettext("bad volume " 446 "size '%s': %s\n"), optarg, 447 libzfs_error_description(g_zfs)); 448 goto error; 449 } 450 451 if (nvlist_add_uint64(props, 452 zfs_prop_to_name(ZFS_PROP_VOLSIZE), 453 intval) != 0) { 454 (void) fprintf(stderr, gettext("internal " 455 "error: out of memory\n")); 456 goto error; 457 } 458 volsize = intval; 459 break; 460 case 'b': 461 if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { 462 (void) fprintf(stderr, gettext("bad volume " 463 "block size '%s': %s\n"), optarg, 464 libzfs_error_description(g_zfs)); 465 goto error; 466 } 467 468 if (nvlist_add_uint64(props, 469 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 470 intval) != 0) { 471 (void) fprintf(stderr, gettext("internal " 472 "error: out of memory\n")); 473 goto error; 474 } 475 break; 476 case 'o': 477 propname = optarg; 478 if ((propval = strchr(propname, '=')) == NULL) { 479 (void) fprintf(stderr, gettext("missing " 480 "'=' for -o option\n")); 481 goto error; 482 } 483 *propval = '\0'; 484 propval++; 485 if (nvlist_lookup_string(props, propname, 486 &strval) == 0) { 487 (void) fprintf(stderr, gettext("property '%s' " 488 "specified multiple times\n"), propname); 489 goto error; 490 } 491 if (nvlist_add_string(props, propname, propval) != 0) { 492 (void) fprintf(stderr, gettext("internal " 493 "error: out of memory\n")); 494 goto error; 495 } 496 break; 497 case 's': 498 noreserve = B_TRUE; 499 break; 500 case ':': 501 (void) fprintf(stderr, gettext("missing size " 502 "argument\n")); 503 goto badusage; 504 break; 505 case '?': 506 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 507 optopt); 508 goto badusage; 509 } 510 } 511 512 if (noreserve && type != ZFS_TYPE_VOLUME) { 513 (void) fprintf(stderr, gettext("'-s' can only be used when " 514 "creating a volume\n")); 515 goto badusage; 516 } 517 518 argc -= optind; 519 argv += optind; 520 521 /* check number of arguments */ 522 if (argc == 0) { 523 (void) fprintf(stderr, gettext("missing %s argument\n"), 524 zfs_type_to_name(type)); 525 goto badusage; 526 } 527 if (argc > 1) { 528 (void) fprintf(stderr, gettext("too many arguments\n")); 529 goto badusage; 530 } 531 532 if (type == ZFS_TYPE_VOLUME && !noreserve && 533 nvlist_lookup_string(props, zfs_prop_to_name(ZFS_PROP_RESERVATION), 534 &strval) != 0) { 535 if (nvlist_add_uint64(props, 536 zfs_prop_to_name(ZFS_PROP_RESERVATION), 537 volsize) != 0) { 538 (void) fprintf(stderr, gettext("internal " 539 "error: out of memory\n")); 540 nvlist_free(props); 541 return (1); 542 } 543 } 544 545 /* pass to libzfs */ 546 if (zfs_create(g_zfs, argv[0], type, props) != 0) 547 goto error; 548 549 if (propval != NULL) 550 *(propval - 1) = '='; 551 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], 552 B_FALSE, B_FALSE); 553 554 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL) 555 goto error; 556 557 /* 558 * Mount and/or share the new filesystem as appropriate. We provide a 559 * verbose error message to let the user know that their filesystem was 560 * in fact created, even if we failed to mount or share it. 561 */ 562 if (zfs_mount(zhp, NULL, 0) != 0) { 563 (void) fprintf(stderr, gettext("filesystem successfully " 564 "created, but not mounted\n")); 565 ret = 1; 566 } else if (zfs_share(zhp) != 0) { 567 (void) fprintf(stderr, gettext("filesystem successfully " 568 "created, but not shared\n")); 569 ret = 1; 570 } else { 571 ret = 0; 572 } 573 574 error: 575 if (zhp) 576 zfs_close(zhp); 577 nvlist_free(props); 578 return (ret); 579 badusage: 580 nvlist_free(props); 581 usage(B_FALSE); 582 return (2); 583 } 584 585 /* 586 * zfs destroy [-rf] <fs, snap, vol> 587 * 588 * -r Recursively destroy all children 589 * -R Recursively destroy all dependents, including clones 590 * -f Force unmounting of any dependents 591 * 592 * Destroys the given dataset. By default, it will unmount any filesystems, 593 * and refuse to destroy a dataset that has any dependents. A dependent can 594 * either be a child, or a clone of a child. 595 */ 596 typedef struct destroy_cbdata { 597 boolean_t cb_first; 598 int cb_force; 599 int cb_recurse; 600 int cb_error; 601 int cb_needforce; 602 int cb_doclones; 603 boolean_t cb_closezhp; 604 zfs_handle_t *cb_target; 605 char *cb_snapname; 606 } destroy_cbdata_t; 607 608 /* 609 * Check for any dependents based on the '-r' or '-R' flags. 610 */ 611 static int 612 destroy_check_dependent(zfs_handle_t *zhp, void *data) 613 { 614 destroy_cbdata_t *cbp = data; 615 const char *tname = zfs_get_name(cbp->cb_target); 616 const char *name = zfs_get_name(zhp); 617 618 if (strncmp(tname, name, strlen(tname)) == 0 && 619 (name[strlen(tname)] == '/' || name[strlen(tname)] == '@')) { 620 /* 621 * This is a direct descendant, not a clone somewhere else in 622 * the hierarchy. 623 */ 624 if (cbp->cb_recurse) 625 goto out; 626 627 if (cbp->cb_first) { 628 (void) fprintf(stderr, gettext("cannot destroy '%s': " 629 "%s has children\n"), 630 zfs_get_name(cbp->cb_target), 631 zfs_type_to_name(zfs_get_type(cbp->cb_target))); 632 (void) fprintf(stderr, gettext("use '-r' to destroy " 633 "the following datasets:\n")); 634 cbp->cb_first = B_FALSE; 635 cbp->cb_error = 1; 636 } 637 638 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 639 } else { 640 /* 641 * This is a clone. We only want to report this if the '-r' 642 * wasn't specified, or the target is a snapshot. 643 */ 644 if (!cbp->cb_recurse && 645 zfs_get_type(cbp->cb_target) != ZFS_TYPE_SNAPSHOT) 646 goto out; 647 648 if (cbp->cb_first) { 649 (void) fprintf(stderr, gettext("cannot destroy '%s': " 650 "%s has dependent clones\n"), 651 zfs_get_name(cbp->cb_target), 652 zfs_type_to_name(zfs_get_type(cbp->cb_target))); 653 (void) fprintf(stderr, gettext("use '-R' to destroy " 654 "the following datasets:\n")); 655 cbp->cb_first = B_FALSE; 656 cbp->cb_error = 1; 657 } 658 659 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 660 } 661 662 out: 663 zfs_close(zhp); 664 return (0); 665 } 666 667 static int 668 destroy_callback(zfs_handle_t *zhp, void *data) 669 { 670 destroy_cbdata_t *cbp = data; 671 672 /* 673 * Ignore pools (which we've already flagged as an error before getting 674 * here. 675 */ 676 if (strchr(zfs_get_name(zhp), '/') == NULL && 677 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { 678 zfs_close(zhp); 679 return (0); 680 } 681 682 /* 683 * Bail out on the first error. 684 */ 685 if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 || 686 zfs_destroy(zhp) != 0) { 687 zfs_close(zhp); 688 return (-1); 689 } 690 691 zfs_close(zhp); 692 return (0); 693 } 694 695 static int 696 destroy_snap_clones(zfs_handle_t *zhp, void *arg) 697 { 698 destroy_cbdata_t *cbp = arg; 699 char thissnap[MAXPATHLEN]; 700 zfs_handle_t *szhp; 701 boolean_t closezhp = cbp->cb_closezhp; 702 int rv; 703 704 (void) snprintf(thissnap, sizeof (thissnap), 705 "%s@%s", zfs_get_name(zhp), cbp->cb_snapname); 706 707 libzfs_print_on_error(g_zfs, B_FALSE); 708 szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT); 709 libzfs_print_on_error(g_zfs, B_TRUE); 710 if (szhp) { 711 /* 712 * Destroy any clones of this snapshot 713 */ 714 if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback, 715 cbp) != 0) { 716 zfs_close(szhp); 717 if (closezhp) 718 zfs_close(zhp); 719 return (-1); 720 } 721 zfs_close(szhp); 722 } 723 724 cbp->cb_closezhp = B_TRUE; 725 rv = zfs_iter_filesystems(zhp, destroy_snap_clones, arg); 726 if (closezhp) 727 zfs_close(zhp); 728 return (rv); 729 } 730 731 static int 732 zfs_do_destroy(int argc, char **argv) 733 { 734 destroy_cbdata_t cb = { 0 }; 735 int c; 736 zfs_handle_t *zhp; 737 char *cp; 738 739 /* check options */ 740 while ((c = getopt(argc, argv, "frR")) != -1) { 741 switch (c) { 742 case 'f': 743 cb.cb_force = 1; 744 break; 745 case 'r': 746 cb.cb_recurse = 1; 747 break; 748 case 'R': 749 cb.cb_recurse = 1; 750 cb.cb_doclones = 1; 751 break; 752 case '?': 753 default: 754 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 755 optopt); 756 usage(B_FALSE); 757 } 758 } 759 760 argc -= optind; 761 argv += optind; 762 763 /* check number of arguments */ 764 if (argc == 0) { 765 (void) fprintf(stderr, gettext("missing path argument\n")); 766 usage(B_FALSE); 767 } 768 if (argc > 1) { 769 (void) fprintf(stderr, gettext("too many arguments\n")); 770 usage(B_FALSE); 771 } 772 773 /* 774 * If we are doing recursive destroy of a snapshot, then the 775 * named snapshot may not exist. Go straight to libzfs. 776 */ 777 if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) { 778 int ret; 779 780 *cp = '\0'; 781 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL) 782 return (1); 783 *cp = '@'; 784 cp++; 785 786 if (cb.cb_doclones) { 787 cb.cb_snapname = cp; 788 if (destroy_snap_clones(zhp, &cb) != 0) { 789 zfs_close(zhp); 790 return (1); 791 } 792 } 793 794 ret = zfs_destroy_snaps(zhp, cp); 795 zfs_close(zhp); 796 if (ret) { 797 (void) fprintf(stderr, 798 gettext("no snapshots destroyed\n")); 799 } else { 800 zpool_log_history(g_zfs, argc + optind, argv - optind, 801 argv[0], B_FALSE, B_FALSE); 802 } 803 return (ret != 0); 804 } 805 806 807 /* Open the given dataset */ 808 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_ANY)) == NULL) 809 return (1); 810 811 cb.cb_target = zhp; 812 813 /* 814 * Perform an explicit check for pools before going any further. 815 */ 816 if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL && 817 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { 818 (void) fprintf(stderr, gettext("cannot destroy '%s': " 819 "operation does not apply to pools\n"), 820 zfs_get_name(zhp)); 821 (void) fprintf(stderr, gettext("use 'zfs destroy -r " 822 "%s' to destroy all datasets in the pool\n"), 823 zfs_get_name(zhp)); 824 (void) fprintf(stderr, gettext("use 'zpool destroy %s' " 825 "to destroy the pool itself\n"), zfs_get_name(zhp)); 826 zfs_close(zhp); 827 return (1); 828 } 829 830 /* 831 * Check for any dependents and/or clones. 832 */ 833 cb.cb_first = B_TRUE; 834 if (!cb.cb_doclones && 835 zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent, 836 &cb) != 0) { 837 zfs_close(zhp); 838 return (1); 839 } 840 841 842 if (cb.cb_error || 843 zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0) { 844 zfs_close(zhp); 845 return (1); 846 } 847 848 /* 849 * Do the real thing. The callback will close the handle regardless of 850 * whether it succeeds or not. 851 */ 852 if (destroy_callback(zhp, &cb) != 0) 853 return (1); 854 855 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], 856 B_FALSE, B_FALSE); 857 858 return (0); 859 } 860 861 /* 862 * zfs get [-rHp] [-o field[,field]...] [-s source[,source]...] 863 * < all | property[,property]... > < fs | snap | vol > ... 864 * 865 * -r recurse over any child datasets 866 * -H scripted mode. Headers are stripped, and fields are separated 867 * by tabs instead of spaces. 868 * -o Set of fields to display. One of "name,property,value,source". 869 * Default is all four. 870 * -s Set of sources to allow. One of 871 * "local,default,inherited,temporary,none". Default is all 872 * five. 873 * -p Display values in parsable (literal) format. 874 * 875 * Prints properties for the given datasets. The user can control which 876 * columns to display as well as which property types to allow. 877 */ 878 typedef struct get_cbdata { 879 int cb_sources; 880 int cb_columns[4]; 881 int cb_colwidths[5]; 882 boolean_t cb_scripted; 883 boolean_t cb_literal; 884 boolean_t cb_first; 885 zfs_proplist_t *cb_proplist; 886 } get_cbdata_t; 887 888 #define GET_COL_NAME 1 889 #define GET_COL_PROPERTY 2 890 #define GET_COL_VALUE 3 891 #define GET_COL_SOURCE 4 892 893 /* 894 * Print the column headers for 'zfs get'. 895 */ 896 static void 897 print_get_headers(get_cbdata_t *cbp) 898 { 899 zfs_proplist_t *pl = cbp->cb_proplist; 900 int i; 901 char *title; 902 size_t len; 903 904 cbp->cb_first = B_FALSE; 905 if (cbp->cb_scripted) 906 return; 907 908 /* 909 * Start with the length of the column headers. 910 */ 911 cbp->cb_colwidths[GET_COL_NAME] = strlen(gettext("NAME")); 912 cbp->cb_colwidths[GET_COL_PROPERTY] = strlen(gettext("PROPERTY")); 913 cbp->cb_colwidths[GET_COL_VALUE] = strlen(gettext("VALUE")); 914 cbp->cb_colwidths[GET_COL_SOURCE] = strlen(gettext("SOURCE")); 915 916 /* 917 * Go through and calculate the widths for each column. For the 918 * 'source' column, we kludge it up by taking the worst-case scenario of 919 * inheriting from the longest name. This is acceptable because in the 920 * majority of cases 'SOURCE' is the last column displayed, and we don't 921 * use the width anyway. Note that the 'VALUE' column can be oversized, 922 * if the name of the property is much longer the any values we find. 923 */ 924 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) { 925 /* 926 * 'PROPERTY' column 927 */ 928 if (pl->pl_prop != ZFS_PROP_INVAL) { 929 len = strlen(zfs_prop_to_name(pl->pl_prop)); 930 if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 931 cbp->cb_colwidths[GET_COL_PROPERTY] = len; 932 } else { 933 len = strlen(pl->pl_user_prop); 934 if (len > cbp->cb_colwidths[GET_COL_PROPERTY]) 935 cbp->cb_colwidths[GET_COL_PROPERTY] = len; 936 } 937 938 /* 939 * 'VALUE' column 940 */ 941 if ((pl->pl_prop != ZFS_PROP_NAME || !pl->pl_all) && 942 pl->pl_width > cbp->cb_colwidths[GET_COL_VALUE]) 943 cbp->cb_colwidths[GET_COL_VALUE] = pl->pl_width; 944 945 /* 946 * 'NAME' and 'SOURCE' columns 947 */ 948 if (pl->pl_prop == ZFS_PROP_NAME && 949 pl->pl_width > cbp->cb_colwidths[GET_COL_NAME]) { 950 cbp->cb_colwidths[GET_COL_NAME] = pl->pl_width; 951 cbp->cb_colwidths[GET_COL_SOURCE] = pl->pl_width + 952 strlen(gettext("inherited from")); 953 } 954 } 955 956 /* 957 * Now go through and print the headers. 958 */ 959 for (i = 0; i < 4; i++) { 960 switch (cbp->cb_columns[i]) { 961 case GET_COL_NAME: 962 title = gettext("NAME"); 963 break; 964 case GET_COL_PROPERTY: 965 title = gettext("PROPERTY"); 966 break; 967 case GET_COL_VALUE: 968 title = gettext("VALUE"); 969 break; 970 case GET_COL_SOURCE: 971 title = gettext("SOURCE"); 972 break; 973 default: 974 title = NULL; 975 } 976 977 if (title != NULL) { 978 if (i == 3 || cbp->cb_columns[i + 1] == 0) 979 (void) printf("%s", title); 980 else 981 (void) printf("%-*s ", 982 cbp->cb_colwidths[cbp->cb_columns[i]], 983 title); 984 } 985 } 986 (void) printf("\n"); 987 } 988 989 /* 990 * Display a single line of output, according to the settings in the callback 991 * structure. 992 */ 993 static void 994 print_one_property(zfs_handle_t *zhp, get_cbdata_t *cbp, const char *propname, 995 const char *value, zfs_source_t sourcetype, const char *source) 996 { 997 int i; 998 const char *str; 999 char buf[128]; 1000 1001 /* 1002 * Ignore those source types that the user has chosen to ignore. 1003 */ 1004 if ((sourcetype & cbp->cb_sources) == 0) 1005 return; 1006 1007 if (cbp->cb_first) 1008 print_get_headers(cbp); 1009 1010 for (i = 0; i < 4; i++) { 1011 switch (cbp->cb_columns[i]) { 1012 case GET_COL_NAME: 1013 str = zfs_get_name(zhp); 1014 break; 1015 1016 case GET_COL_PROPERTY: 1017 str = propname; 1018 break; 1019 1020 case GET_COL_VALUE: 1021 str = value; 1022 break; 1023 1024 case GET_COL_SOURCE: 1025 switch (sourcetype) { 1026 case ZFS_SRC_NONE: 1027 str = "-"; 1028 break; 1029 1030 case ZFS_SRC_DEFAULT: 1031 str = "default"; 1032 break; 1033 1034 case ZFS_SRC_LOCAL: 1035 str = "local"; 1036 break; 1037 1038 case ZFS_SRC_TEMPORARY: 1039 str = "temporary"; 1040 break; 1041 1042 case ZFS_SRC_INHERITED: 1043 (void) snprintf(buf, sizeof (buf), 1044 "inherited from %s", source); 1045 str = buf; 1046 break; 1047 } 1048 break; 1049 1050 default: 1051 continue; 1052 } 1053 1054 if (cbp->cb_columns[i + 1] == 0) 1055 (void) printf("%s", str); 1056 else if (cbp->cb_scripted) 1057 (void) printf("%s\t", str); 1058 else 1059 (void) printf("%-*s ", 1060 cbp->cb_colwidths[cbp->cb_columns[i]], 1061 str); 1062 1063 } 1064 1065 (void) printf("\n"); 1066 } 1067 1068 /* 1069 * Invoked to display the properties for a single dataset. 1070 */ 1071 static int 1072 get_callback(zfs_handle_t *zhp, void *data) 1073 { 1074 char buf[ZFS_MAXPROPLEN]; 1075 zfs_source_t sourcetype; 1076 char source[ZFS_MAXNAMELEN]; 1077 get_cbdata_t *cbp = data; 1078 nvlist_t *userprop = zfs_get_user_props(zhp); 1079 zfs_proplist_t *pl = cbp->cb_proplist; 1080 nvlist_t *propval; 1081 char *strval; 1082 char *sourceval; 1083 1084 for (; pl != NULL; pl = pl->pl_next) { 1085 /* 1086 * Skip the special fake placeholder. This will also skip over 1087 * the name property when 'all' is specified. 1088 */ 1089 if (pl->pl_prop == ZFS_PROP_NAME && 1090 pl == cbp->cb_proplist) 1091 continue; 1092 1093 if (pl->pl_prop != ZFS_PROP_INVAL) { 1094 if (zfs_prop_get(zhp, pl->pl_prop, buf, 1095 sizeof (buf), &sourcetype, source, 1096 sizeof (source), 1097 cbp->cb_literal) != 0) { 1098 if (pl->pl_all) 1099 continue; 1100 sourcetype = ZFS_SRC_NONE; 1101 (void) strlcpy(buf, "-", sizeof (buf)); 1102 } 1103 1104 print_one_property(zhp, cbp, 1105 zfs_prop_to_name(pl->pl_prop), 1106 buf, sourcetype, source); 1107 } else { 1108 if (nvlist_lookup_nvlist(userprop, 1109 pl->pl_user_prop, &propval) != 0) { 1110 if (pl->pl_all) 1111 continue; 1112 sourcetype = ZFS_SRC_NONE; 1113 strval = "-"; 1114 } else { 1115 verify(nvlist_lookup_string(propval, 1116 ZFS_PROP_VALUE, &strval) == 0); 1117 verify(nvlist_lookup_string(propval, 1118 ZFS_PROP_SOURCE, &sourceval) == 0); 1119 1120 if (strcmp(sourceval, 1121 zfs_get_name(zhp)) == 0) { 1122 sourcetype = ZFS_SRC_LOCAL; 1123 } else { 1124 sourcetype = ZFS_SRC_INHERITED; 1125 (void) strlcpy(source, 1126 sourceval, sizeof (source)); 1127 } 1128 } 1129 1130 print_one_property(zhp, cbp, 1131 pl->pl_user_prop, strval, sourcetype, 1132 source); 1133 } 1134 } 1135 1136 return (0); 1137 } 1138 1139 static int 1140 zfs_do_get(int argc, char **argv) 1141 { 1142 get_cbdata_t cb = { 0 }; 1143 boolean_t recurse = B_FALSE; 1144 int i, c; 1145 char *value, *fields; 1146 int ret; 1147 zfs_proplist_t fake_name = { 0 }; 1148 1149 /* 1150 * Set up default columns and sources. 1151 */ 1152 cb.cb_sources = ZFS_SRC_ALL; 1153 cb.cb_columns[0] = GET_COL_NAME; 1154 cb.cb_columns[1] = GET_COL_PROPERTY; 1155 cb.cb_columns[2] = GET_COL_VALUE; 1156 cb.cb_columns[3] = GET_COL_SOURCE; 1157 1158 /* check options */ 1159 while ((c = getopt(argc, argv, ":o:s:rHp")) != -1) { 1160 switch (c) { 1161 case 'p': 1162 cb.cb_literal = B_TRUE; 1163 break; 1164 case 'r': 1165 recurse = B_TRUE; 1166 break; 1167 case 'H': 1168 cb.cb_scripted = B_TRUE; 1169 break; 1170 case ':': 1171 (void) fprintf(stderr, gettext("missing argument for " 1172 "'%c' option\n"), optopt); 1173 usage(B_FALSE); 1174 break; 1175 case 'o': 1176 /* 1177 * Process the set of columns to display. We zero out 1178 * the structure to give us a blank slate. 1179 */ 1180 bzero(&cb.cb_columns, sizeof (cb.cb_columns)); 1181 i = 0; 1182 while (*optarg != '\0') { 1183 static char *col_subopts[] = 1184 { "name", "property", "value", "source", 1185 NULL }; 1186 1187 if (i == 4) { 1188 (void) fprintf(stderr, gettext("too " 1189 "many fields given to -o " 1190 "option\n")); 1191 usage(B_FALSE); 1192 } 1193 1194 switch (getsubopt(&optarg, col_subopts, 1195 &value)) { 1196 case 0: 1197 cb.cb_columns[i++] = GET_COL_NAME; 1198 break; 1199 case 1: 1200 cb.cb_columns[i++] = GET_COL_PROPERTY; 1201 break; 1202 case 2: 1203 cb.cb_columns[i++] = GET_COL_VALUE; 1204 break; 1205 case 3: 1206 cb.cb_columns[i++] = GET_COL_SOURCE; 1207 break; 1208 default: 1209 (void) fprintf(stderr, 1210 gettext("invalid column name " 1211 "'%s'\n"), value); 1212 usage(B_FALSE); 1213 } 1214 } 1215 break; 1216 1217 case 's': 1218 cb.cb_sources = 0; 1219 while (*optarg != '\0') { 1220 static char *source_subopts[] = { 1221 "local", "default", "inherited", 1222 "temporary", "none", NULL }; 1223 1224 switch (getsubopt(&optarg, source_subopts, 1225 &value)) { 1226 case 0: 1227 cb.cb_sources |= ZFS_SRC_LOCAL; 1228 break; 1229 case 1: 1230 cb.cb_sources |= ZFS_SRC_DEFAULT; 1231 break; 1232 case 2: 1233 cb.cb_sources |= ZFS_SRC_INHERITED; 1234 break; 1235 case 3: 1236 cb.cb_sources |= ZFS_SRC_TEMPORARY; 1237 break; 1238 case 4: 1239 cb.cb_sources |= ZFS_SRC_NONE; 1240 break; 1241 default: 1242 (void) fprintf(stderr, 1243 gettext("invalid source " 1244 "'%s'\n"), value); 1245 usage(B_FALSE); 1246 } 1247 } 1248 break; 1249 1250 case '?': 1251 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1252 optopt); 1253 usage(B_FALSE); 1254 } 1255 } 1256 1257 argc -= optind; 1258 argv += optind; 1259 1260 if (argc < 1) { 1261 (void) fprintf(stderr, gettext("missing property " 1262 "argument\n")); 1263 usage(B_FALSE); 1264 } 1265 1266 fields = argv[0]; 1267 1268 if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0) 1269 usage(B_FALSE); 1270 1271 argc--; 1272 argv++; 1273 1274 /* 1275 * As part of zfs_expand_proplist(), we keep track of the maximum column 1276 * width for each property. For the 'NAME' (and 'SOURCE') columns, we 1277 * need to know the maximum name length. However, the user likely did 1278 * not specify 'name' as one of the properties to fetch, so we need to 1279 * make sure we always include at least this property for 1280 * print_get_headers() to work properly. 1281 */ 1282 if (cb.cb_proplist != NULL) { 1283 fake_name.pl_prop = ZFS_PROP_NAME; 1284 fake_name.pl_width = strlen(gettext("NAME")); 1285 fake_name.pl_next = cb.cb_proplist; 1286 cb.cb_proplist = &fake_name; 1287 } 1288 1289 cb.cb_first = B_TRUE; 1290 1291 /* run for each object */ 1292 ret = zfs_for_each(argc, argv, recurse, ZFS_TYPE_ANY, NULL, 1293 &cb.cb_proplist, get_callback, &cb, B_FALSE); 1294 1295 if (cb.cb_proplist == &fake_name) 1296 zfs_free_proplist(fake_name.pl_next); 1297 else 1298 zfs_free_proplist(cb.cb_proplist); 1299 1300 return (ret); 1301 } 1302 1303 /* 1304 * inherit [-r] <property> <fs|vol> ... 1305 * 1306 * -r Recurse over all children 1307 * 1308 * For each dataset specified on the command line, inherit the given property 1309 * from its parent. Inheriting a property at the pool level will cause it to 1310 * use the default value. The '-r' flag will recurse over all children, and is 1311 * useful for setting a property on a hierarchy-wide basis, regardless of any 1312 * local modifications for each dataset. 1313 */ 1314 typedef struct inherit_cbdata { 1315 char *cb_propname; 1316 boolean_t cb_any_successful; 1317 } inherit_cbdata_t; 1318 1319 static int 1320 inherit_callback(zfs_handle_t *zhp, void *data) 1321 { 1322 inherit_cbdata_t *cbp = data; 1323 int ret; 1324 1325 ret = zfs_prop_inherit(zhp, cbp->cb_propname); 1326 if (ret == 0) 1327 cbp->cb_any_successful = B_TRUE; 1328 return (ret != 0); 1329 } 1330 1331 static int 1332 zfs_do_inherit(int argc, char **argv) 1333 { 1334 boolean_t recurse = B_FALSE; 1335 int c; 1336 zfs_prop_t prop; 1337 inherit_cbdata_t cb; 1338 int ret; 1339 1340 /* check options */ 1341 while ((c = getopt(argc, argv, "r")) != -1) { 1342 switch (c) { 1343 case 'r': 1344 recurse = B_TRUE; 1345 break; 1346 case '?': 1347 default: 1348 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1349 optopt); 1350 usage(B_FALSE); 1351 } 1352 } 1353 1354 argc -= optind; 1355 argv += optind; 1356 1357 /* check number of arguments */ 1358 if (argc < 1) { 1359 (void) fprintf(stderr, gettext("missing property argument\n")); 1360 usage(B_FALSE); 1361 } 1362 if (argc < 2) { 1363 (void) fprintf(stderr, gettext("missing dataset argument\n")); 1364 usage(B_FALSE); 1365 } 1366 1367 cb.cb_propname = argv[0]; 1368 argc--; 1369 argv++; 1370 1371 if ((prop = zfs_name_to_prop(cb.cb_propname)) != ZFS_PROP_INVAL) { 1372 if (zfs_prop_readonly(prop)) { 1373 (void) fprintf(stderr, gettext( 1374 "%s property is read-only\n"), 1375 cb.cb_propname); 1376 return (1); 1377 } 1378 if (!zfs_prop_inheritable(prop)) { 1379 (void) fprintf(stderr, gettext("'%s' property cannot " 1380 "be inherited\n"), cb.cb_propname); 1381 if (prop == ZFS_PROP_QUOTA || 1382 prop == ZFS_PROP_RESERVATION) 1383 (void) fprintf(stderr, gettext("use 'zfs set " 1384 "%s=none' to clear\n"), cb.cb_propname); 1385 return (1); 1386 } 1387 } else if (!zfs_prop_user(cb.cb_propname)) { 1388 (void) fprintf(stderr, gettext( 1389 "invalid property '%s'\n"), 1390 cb.cb_propname); 1391 usage(B_FALSE); 1392 } 1393 1394 cb.cb_any_successful = B_FALSE; 1395 1396 ret = zfs_for_each(argc, argv, recurse, 1397 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, NULL, NULL, 1398 inherit_callback, &cb, B_FALSE); 1399 1400 if (cb.cb_any_successful) { 1401 zpool_log_history(g_zfs, argc + optind + 1, argv - optind - 1, 1402 argv[0], B_FALSE, B_FALSE); 1403 } 1404 1405 return (ret); 1406 } 1407 1408 /* 1409 * list [-rH] [-o property[,property]...] [-t type[,type]...] 1410 * [-s property [-s property]...] [-S property [-S property]...] 1411 * <dataset> ... 1412 * 1413 * -r Recurse over all children 1414 * -H Scripted mode; elide headers and separate colums by tabs 1415 * -o Control which fields to display. 1416 * -t Control which object types to display. 1417 * -s Specify sort columns, descending order. 1418 * -S Specify sort columns, ascending order. 1419 * 1420 * When given no arguments, lists all filesystems in the system. 1421 * Otherwise, list the specified datasets, optionally recursing down them if 1422 * '-r' is specified. 1423 */ 1424 typedef struct list_cbdata { 1425 boolean_t cb_first; 1426 boolean_t cb_scripted; 1427 zfs_proplist_t *cb_proplist; 1428 } list_cbdata_t; 1429 1430 /* 1431 * Given a list of columns to display, output appropriate headers for each one. 1432 */ 1433 static void 1434 print_header(zfs_proplist_t *pl) 1435 { 1436 char headerbuf[ZFS_MAXPROPLEN]; 1437 const char *header; 1438 int i; 1439 boolean_t first = B_TRUE; 1440 boolean_t right_justify; 1441 1442 for (; pl != NULL; pl = pl->pl_next) { 1443 if (!first) { 1444 (void) printf(" "); 1445 } else { 1446 first = B_FALSE; 1447 } 1448 1449 right_justify = B_FALSE; 1450 if (pl->pl_prop != ZFS_PROP_INVAL) { 1451 header = zfs_prop_column_name(pl->pl_prop); 1452 right_justify = zfs_prop_align_right(pl->pl_prop); 1453 } else { 1454 for (i = 0; pl->pl_user_prop[i] != '\0'; i++) 1455 headerbuf[i] = toupper(pl->pl_user_prop[i]); 1456 headerbuf[i] = '\0'; 1457 header = headerbuf; 1458 } 1459 1460 if (pl->pl_next == NULL && !right_justify) 1461 (void) printf("%s", header); 1462 else if (right_justify) 1463 (void) printf("%*s", pl->pl_width, header); 1464 else 1465 (void) printf("%-*s", pl->pl_width, header); 1466 } 1467 1468 (void) printf("\n"); 1469 } 1470 1471 /* 1472 * Given a dataset and a list of fields, print out all the properties according 1473 * to the described layout. 1474 */ 1475 static void 1476 print_dataset(zfs_handle_t *zhp, zfs_proplist_t *pl, int scripted) 1477 { 1478 boolean_t first = B_TRUE; 1479 char property[ZFS_MAXPROPLEN]; 1480 nvlist_t *userprops = zfs_get_user_props(zhp); 1481 nvlist_t *propval; 1482 char *propstr; 1483 boolean_t right_justify; 1484 int width; 1485 1486 for (; pl != NULL; pl = pl->pl_next) { 1487 if (!first) { 1488 if (scripted) 1489 (void) printf("\t"); 1490 else 1491 (void) printf(" "); 1492 } else { 1493 first = B_FALSE; 1494 } 1495 1496 right_justify = B_FALSE; 1497 if (pl->pl_prop != ZFS_PROP_INVAL) { 1498 if (zfs_prop_get(zhp, pl->pl_prop, property, 1499 sizeof (property), NULL, NULL, 0, B_FALSE) != 0) 1500 propstr = "-"; 1501 else 1502 propstr = property; 1503 1504 right_justify = zfs_prop_align_right(pl->pl_prop); 1505 } else { 1506 if (nvlist_lookup_nvlist(userprops, 1507 pl->pl_user_prop, &propval) != 0) 1508 propstr = "-"; 1509 else 1510 verify(nvlist_lookup_string(propval, 1511 ZFS_PROP_VALUE, &propstr) == 0); 1512 } 1513 1514 width = pl->pl_width; 1515 1516 /* 1517 * If this is being called in scripted mode, or if this is the 1518 * last column and it is left-justified, don't include a width 1519 * format specifier. 1520 */ 1521 if (scripted || (pl->pl_next == NULL && !right_justify)) 1522 (void) printf("%s", propstr); 1523 else if (right_justify) 1524 (void) printf("%*s", width, propstr); 1525 else 1526 (void) printf("%-*s", width, propstr); 1527 } 1528 1529 (void) printf("\n"); 1530 } 1531 1532 /* 1533 * Generic callback function to list a dataset or snapshot. 1534 */ 1535 static int 1536 list_callback(zfs_handle_t *zhp, void *data) 1537 { 1538 list_cbdata_t *cbp = data; 1539 1540 if (cbp->cb_first) { 1541 if (!cbp->cb_scripted) 1542 print_header(cbp->cb_proplist); 1543 cbp->cb_first = B_FALSE; 1544 } 1545 1546 print_dataset(zhp, cbp->cb_proplist, cbp->cb_scripted); 1547 1548 return (0); 1549 } 1550 1551 static int 1552 zfs_do_list(int argc, char **argv) 1553 { 1554 int c; 1555 boolean_t recurse = B_FALSE; 1556 boolean_t scripted = B_FALSE; 1557 static char default_fields[] = 1558 "name,used,available,referenced,mountpoint"; 1559 int types = ZFS_TYPE_ANY; 1560 char *fields = NULL; 1561 char *basic_fields = default_fields; 1562 list_cbdata_t cb = { 0 }; 1563 char *value; 1564 int ret; 1565 char *type_subopts[] = { "filesystem", "volume", "snapshot", NULL }; 1566 zfs_sort_column_t *sortcol = NULL; 1567 1568 /* check options */ 1569 while ((c = getopt(argc, argv, ":o:rt:Hs:S:")) != -1) { 1570 switch (c) { 1571 case 'o': 1572 fields = optarg; 1573 break; 1574 case 'r': 1575 recurse = B_TRUE; 1576 break; 1577 case 'H': 1578 scripted = B_TRUE; 1579 break; 1580 case 's': 1581 if (zfs_add_sort_column(&sortcol, optarg, 1582 B_FALSE) != 0) { 1583 (void) fprintf(stderr, 1584 gettext("invalid property '%s'\n"), optarg); 1585 usage(B_FALSE); 1586 } 1587 break; 1588 case 'S': 1589 if (zfs_add_sort_column(&sortcol, optarg, 1590 B_TRUE) != 0) { 1591 (void) fprintf(stderr, 1592 gettext("invalid property '%s'\n"), optarg); 1593 usage(B_FALSE); 1594 } 1595 break; 1596 case 't': 1597 types = 0; 1598 while (*optarg != '\0') { 1599 switch (getsubopt(&optarg, type_subopts, 1600 &value)) { 1601 case 0: 1602 types |= ZFS_TYPE_FILESYSTEM; 1603 break; 1604 case 1: 1605 types |= ZFS_TYPE_VOLUME; 1606 break; 1607 case 2: 1608 types |= ZFS_TYPE_SNAPSHOT; 1609 break; 1610 default: 1611 (void) fprintf(stderr, 1612 gettext("invalid type '%s'\n"), 1613 value); 1614 usage(B_FALSE); 1615 } 1616 } 1617 break; 1618 case ':': 1619 (void) fprintf(stderr, gettext("missing argument for " 1620 "'%c' option\n"), optopt); 1621 usage(B_FALSE); 1622 break; 1623 case '?': 1624 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1625 optopt); 1626 usage(B_FALSE); 1627 } 1628 } 1629 1630 argc -= optind; 1631 argv += optind; 1632 1633 if (fields == NULL) 1634 fields = basic_fields; 1635 1636 /* 1637 * If the user specifies '-o all', the zfs_get_proplist() doesn't 1638 * normally include the name of the dataset. For 'zfs list', we always 1639 * want this property to be first. 1640 */ 1641 if (zfs_get_proplist(g_zfs, fields, &cb.cb_proplist) != 0) 1642 usage(B_FALSE); 1643 1644 cb.cb_scripted = scripted; 1645 cb.cb_first = B_TRUE; 1646 1647 ret = zfs_for_each(argc, argv, recurse, types, sortcol, &cb.cb_proplist, 1648 list_callback, &cb, B_TRUE); 1649 1650 zfs_free_proplist(cb.cb_proplist); 1651 zfs_free_sort_columns(sortcol); 1652 1653 if (ret == 0 && cb.cb_first) 1654 (void) printf(gettext("no datasets available\n")); 1655 1656 return (ret); 1657 } 1658 1659 /* 1660 * zfs rename <fs | snap | vol> <fs | snap | vol> 1661 * 1662 * Renames the given dataset to another of the same type. 1663 */ 1664 /* ARGSUSED */ 1665 static int 1666 zfs_do_rename(int argc, char **argv) 1667 { 1668 zfs_handle_t *zhp; 1669 int ret; 1670 1671 /* check options */ 1672 if (argc > 1 && argv[1][0] == '-') { 1673 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1674 argv[1][1]); 1675 usage(B_FALSE); 1676 } 1677 1678 /* check number of arguments */ 1679 if (argc < 2) { 1680 (void) fprintf(stderr, gettext("missing source dataset " 1681 "argument\n")); 1682 usage(B_FALSE); 1683 } 1684 if (argc < 3) { 1685 (void) fprintf(stderr, gettext("missing target dataset " 1686 "argument\n")); 1687 usage(B_FALSE); 1688 } 1689 if (argc > 3) { 1690 (void) fprintf(stderr, gettext("too many arguments\n")); 1691 usage(B_FALSE); 1692 } 1693 1694 if ((zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_ANY)) == NULL) 1695 return (1); 1696 1697 ret = (zfs_rename(zhp, argv[2]) != 0); 1698 1699 if (!ret) 1700 zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE); 1701 1702 zfs_close(zhp); 1703 return (ret); 1704 } 1705 1706 /* 1707 * zfs promote <fs> 1708 * 1709 * Promotes the given clone fs to be the parent 1710 */ 1711 /* ARGSUSED */ 1712 static int 1713 zfs_do_promote(int argc, char **argv) 1714 { 1715 zfs_handle_t *zhp; 1716 int ret; 1717 1718 /* check options */ 1719 if (argc > 1 && argv[1][0] == '-') { 1720 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1721 argv[1][1]); 1722 usage(B_FALSE); 1723 } 1724 1725 /* check number of arguments */ 1726 if (argc < 2) { 1727 (void) fprintf(stderr, gettext("missing clone filesystem" 1728 " argument\n")); 1729 usage(B_FALSE); 1730 } 1731 if (argc > 2) { 1732 (void) fprintf(stderr, gettext("too many arguments\n")); 1733 usage(B_FALSE); 1734 } 1735 1736 zhp = zfs_open(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); 1737 if (zhp == NULL) 1738 return (1); 1739 1740 ret = (zfs_promote(zhp) != 0); 1741 1742 if (!ret) 1743 zpool_log_history(g_zfs, argc, argv, argv[1], B_FALSE, B_FALSE); 1744 1745 zfs_close(zhp); 1746 return (ret); 1747 } 1748 1749 /* 1750 * zfs rollback [-rfR] <snapshot> 1751 * 1752 * -r Delete any intervening snapshots before doing rollback 1753 * -R Delete any snapshots and their clones 1754 * -f Force unmount filesystems, even if they are in use. 1755 * 1756 * Given a filesystem, rollback to a specific snapshot, discarding any changes 1757 * since then and making it the active dataset. If more recent snapshots exist, 1758 * the command will complain unless the '-r' flag is given. 1759 */ 1760 typedef struct rollback_cbdata { 1761 uint64_t cb_create; 1762 boolean_t cb_first; 1763 int cb_doclones; 1764 char *cb_target; 1765 int cb_error; 1766 boolean_t cb_recurse; 1767 boolean_t cb_dependent; 1768 } rollback_cbdata_t; 1769 1770 /* 1771 * Report any snapshots more recent than the one specified. Used when '-r' is 1772 * not specified. We reuse this same callback for the snapshot dependents - if 1773 * 'cb_dependent' is set, then this is a dependent and we should report it 1774 * without checking the transaction group. 1775 */ 1776 static int 1777 rollback_check(zfs_handle_t *zhp, void *data) 1778 { 1779 rollback_cbdata_t *cbp = data; 1780 1781 if (cbp->cb_doclones) { 1782 zfs_close(zhp); 1783 return (0); 1784 } 1785 1786 if (!cbp->cb_dependent) { 1787 if (strcmp(zfs_get_name(zhp), cbp->cb_target) != 0 && 1788 zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && 1789 zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > 1790 cbp->cb_create) { 1791 1792 if (cbp->cb_first && !cbp->cb_recurse) { 1793 (void) fprintf(stderr, gettext("cannot " 1794 "rollback to '%s': more recent snapshots " 1795 "exist\n"), 1796 cbp->cb_target); 1797 (void) fprintf(stderr, gettext("use '-r' to " 1798 "force deletion of the following " 1799 "snapshots:\n")); 1800 cbp->cb_first = 0; 1801 cbp->cb_error = 1; 1802 } 1803 1804 if (cbp->cb_recurse) { 1805 cbp->cb_dependent = B_TRUE; 1806 if (zfs_iter_dependents(zhp, B_TRUE, 1807 rollback_check, cbp) != 0) { 1808 zfs_close(zhp); 1809 return (-1); 1810 } 1811 cbp->cb_dependent = B_FALSE; 1812 } else { 1813 (void) fprintf(stderr, "%s\n", 1814 zfs_get_name(zhp)); 1815 } 1816 } 1817 } else { 1818 if (cbp->cb_first && cbp->cb_recurse) { 1819 (void) fprintf(stderr, gettext("cannot rollback to " 1820 "'%s': clones of previous snapshots exist\n"), 1821 cbp->cb_target); 1822 (void) fprintf(stderr, gettext("use '-R' to " 1823 "force deletion of the following clones and " 1824 "dependents:\n")); 1825 cbp->cb_first = 0; 1826 cbp->cb_error = 1; 1827 } 1828 1829 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 1830 } 1831 1832 zfs_close(zhp); 1833 return (0); 1834 } 1835 1836 static int 1837 zfs_do_rollback(int argc, char **argv) 1838 { 1839 int ret; 1840 int c; 1841 rollback_cbdata_t cb = { 0 }; 1842 zfs_handle_t *zhp, *snap; 1843 char parentname[ZFS_MAXNAMELEN]; 1844 char *delim; 1845 int force = 0; 1846 1847 /* check options */ 1848 while ((c = getopt(argc, argv, "rfR")) != -1) { 1849 switch (c) { 1850 case 'f': 1851 force = 1; 1852 break; 1853 case 'r': 1854 cb.cb_recurse = 1; 1855 break; 1856 case 'R': 1857 cb.cb_recurse = 1; 1858 cb.cb_doclones = 1; 1859 break; 1860 case '?': 1861 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1862 optopt); 1863 usage(B_FALSE); 1864 } 1865 } 1866 1867 argc -= optind; 1868 argv += optind; 1869 1870 /* check number of arguments */ 1871 if (argc < 1) { 1872 (void) fprintf(stderr, gettext("missing dataset argument\n")); 1873 usage(B_FALSE); 1874 } 1875 if (argc > 1) { 1876 (void) fprintf(stderr, gettext("too many arguments\n")); 1877 usage(B_FALSE); 1878 } 1879 1880 /* open the snapshot */ 1881 if ((snap = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) 1882 return (1); 1883 1884 /* open the parent dataset */ 1885 (void) strlcpy(parentname, argv[0], sizeof (parentname)); 1886 verify((delim = strrchr(parentname, '@')) != NULL); 1887 *delim = '\0'; 1888 if ((zhp = zfs_open(g_zfs, parentname, ZFS_TYPE_ANY)) == NULL) { 1889 zfs_close(snap); 1890 return (1); 1891 } 1892 1893 /* 1894 * Check for more recent snapshots and/or clones based on the presence 1895 * of '-r' and '-R'. 1896 */ 1897 cb.cb_target = argv[0]; 1898 cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG); 1899 cb.cb_first = B_TRUE; 1900 cb.cb_error = 0; 1901 if ((ret = zfs_iter_children(zhp, rollback_check, &cb)) != 0) 1902 goto out; 1903 1904 if ((ret = cb.cb_error) != 0) 1905 goto out; 1906 1907 /* 1908 * Rollback parent to the given snapshot. 1909 */ 1910 ret = zfs_rollback(zhp, snap, force); 1911 1912 if (!ret) { 1913 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], 1914 B_FALSE, B_FALSE); 1915 } 1916 1917 out: 1918 zfs_close(snap); 1919 zfs_close(zhp); 1920 1921 if (ret == 0) 1922 return (0); 1923 else 1924 return (1); 1925 } 1926 1927 /* 1928 * zfs set property=value { fs | snap | vol } ... 1929 * 1930 * Sets the given property for all datasets specified on the command line. 1931 */ 1932 typedef struct set_cbdata { 1933 char *cb_propname; 1934 char *cb_value; 1935 boolean_t cb_any_successful; 1936 } set_cbdata_t; 1937 1938 static int 1939 set_callback(zfs_handle_t *zhp, void *data) 1940 { 1941 set_cbdata_t *cbp = data; 1942 1943 if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) { 1944 switch (libzfs_errno(g_zfs)) { 1945 case EZFS_MOUNTFAILED: 1946 (void) fprintf(stderr, gettext("property may be set " 1947 "but unable to remount filesystem\n")); 1948 break; 1949 case EZFS_SHARENFSFAILED: 1950 (void) fprintf(stderr, gettext("property may be set " 1951 "but unable to reshare filesystem\n")); 1952 break; 1953 } 1954 return (1); 1955 } 1956 cbp->cb_any_successful = B_TRUE; 1957 return (0); 1958 } 1959 1960 static int 1961 zfs_do_set(int argc, char **argv) 1962 { 1963 set_cbdata_t cb; 1964 int ret; 1965 1966 /* check for options */ 1967 if (argc > 1 && argv[1][0] == '-') { 1968 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1969 argv[1][1]); 1970 usage(B_FALSE); 1971 } 1972 1973 /* check number of arguments */ 1974 if (argc < 2) { 1975 (void) fprintf(stderr, gettext("missing property=value " 1976 "argument\n")); 1977 usage(B_FALSE); 1978 } 1979 if (argc < 3) { 1980 (void) fprintf(stderr, gettext("missing dataset name\n")); 1981 usage(B_FALSE); 1982 } 1983 1984 /* validate property=value argument */ 1985 cb.cb_propname = argv[1]; 1986 if ((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) { 1987 (void) fprintf(stderr, gettext("missing value in " 1988 "property=value argument\n")); 1989 usage(B_FALSE); 1990 } 1991 1992 *cb.cb_value = '\0'; 1993 cb.cb_value++; 1994 cb.cb_any_successful = B_FALSE; 1995 1996 if (*cb.cb_propname == '\0') { 1997 (void) fprintf(stderr, 1998 gettext("missing property in property=value argument\n")); 1999 usage(B_FALSE); 2000 } 2001 2002 ret = zfs_for_each(argc - 2, argv + 2, B_FALSE, 2003 ZFS_TYPE_ANY, NULL, NULL, set_callback, &cb, B_FALSE); 2004 2005 if (cb.cb_any_successful) { 2006 *(cb.cb_value - 1) = '='; 2007 zpool_log_history(g_zfs, argc, argv, argv[2], B_FALSE, B_FALSE); 2008 } 2009 2010 return (ret); 2011 } 2012 2013 /* 2014 * zfs snapshot [-r] <fs@snap> 2015 * 2016 * Creates a snapshot with the given name. While functionally equivalent to 2017 * 'zfs create', it is a separate command to diffferentiate intent. 2018 */ 2019 static int 2020 zfs_do_snapshot(int argc, char **argv) 2021 { 2022 int recursive = B_FALSE; 2023 int ret; 2024 char c; 2025 2026 /* check options */ 2027 while ((c = getopt(argc, argv, ":r")) != -1) { 2028 switch (c) { 2029 case 'r': 2030 recursive = B_TRUE; 2031 break; 2032 case '?': 2033 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2034 optopt); 2035 usage(B_FALSE); 2036 } 2037 } 2038 2039 argc -= optind; 2040 argv += optind; 2041 2042 /* check number of arguments */ 2043 if (argc < 1) { 2044 (void) fprintf(stderr, gettext("missing snapshot argument\n")); 2045 usage(B_FALSE); 2046 } 2047 if (argc > 1) { 2048 (void) fprintf(stderr, gettext("too many arguments\n")); 2049 usage(B_FALSE); 2050 } 2051 2052 ret = zfs_snapshot(g_zfs, argv[0], recursive); 2053 if (ret && recursive) 2054 (void) fprintf(stderr, gettext("no snapshots were created\n")); 2055 if (!ret) { 2056 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], 2057 B_FALSE, B_FALSE); 2058 } 2059 return (ret != 0); 2060 } 2061 2062 /* 2063 * zfs send [-i <@snap>] <fs@snap> 2064 * 2065 * Send a backup stream to stdout. 2066 */ 2067 static int 2068 zfs_do_send(int argc, char **argv) 2069 { 2070 char *fromname = NULL; 2071 char *cp; 2072 zfs_handle_t *zhp; 2073 int c, err; 2074 2075 /* check options */ 2076 while ((c = getopt(argc, argv, ":i:")) != -1) { 2077 switch (c) { 2078 case 'i': 2079 if (fromname) 2080 usage(B_FALSE); 2081 fromname = optarg; 2082 break; 2083 case ':': 2084 (void) fprintf(stderr, gettext("missing argument for " 2085 "'%c' option\n"), optopt); 2086 usage(B_FALSE); 2087 break; 2088 case '?': 2089 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2090 optopt); 2091 usage(B_FALSE); 2092 } 2093 } 2094 2095 argc -= optind; 2096 argv += optind; 2097 2098 /* check number of arguments */ 2099 if (argc < 1) { 2100 (void) fprintf(stderr, gettext("missing snapshot argument\n")); 2101 usage(B_FALSE); 2102 } 2103 if (argc > 1) { 2104 (void) fprintf(stderr, gettext("too many arguments\n")); 2105 usage(B_FALSE); 2106 } 2107 2108 if (isatty(STDOUT_FILENO)) { 2109 (void) fprintf(stderr, 2110 gettext("Error: Stream can not be written to a terminal.\n" 2111 "You must redirect standard output.\n")); 2112 return (1); 2113 } 2114 2115 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) 2116 return (1); 2117 2118 /* 2119 * If they specified the full path to the snapshot, chop off 2120 * everything except the short name of the snapshot. 2121 */ 2122 if (fromname && (cp = strchr(fromname, '@')) != NULL) { 2123 if (cp != fromname && 2124 strncmp(argv[0], fromname, cp - fromname + 1)) { 2125 (void) fprintf(stderr, 2126 gettext("incremental source must be " 2127 "in same filesystem\n")); 2128 usage(B_FALSE); 2129 } 2130 fromname = cp + 1; 2131 if (strchr(fromname, '@') || strchr(fromname, '/')) { 2132 (void) fprintf(stderr, 2133 gettext("invalid incremental source\n")); 2134 usage(B_FALSE); 2135 } 2136 } 2137 2138 err = zfs_send(zhp, fromname, STDOUT_FILENO); 2139 zfs_close(zhp); 2140 2141 return (err != 0); 2142 } 2143 2144 /* 2145 * zfs receive <fs@snap> 2146 * 2147 * Restore a backup stream from stdin. 2148 */ 2149 static int 2150 zfs_do_receive(int argc, char **argv) 2151 { 2152 int c, err; 2153 boolean_t isprefix = B_FALSE; 2154 boolean_t dryrun = B_FALSE; 2155 boolean_t verbose = B_FALSE; 2156 boolean_t force = B_FALSE; 2157 2158 /* check options */ 2159 while ((c = getopt(argc, argv, ":dnvF")) != -1) { 2160 switch (c) { 2161 case 'd': 2162 isprefix = B_TRUE; 2163 break; 2164 case 'n': 2165 dryrun = B_TRUE; 2166 break; 2167 case 'v': 2168 verbose = B_TRUE; 2169 break; 2170 case 'F': 2171 force = B_TRUE; 2172 break; 2173 case ':': 2174 (void) fprintf(stderr, gettext("missing argument for " 2175 "'%c' option\n"), optopt); 2176 usage(B_FALSE); 2177 break; 2178 case '?': 2179 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2180 optopt); 2181 usage(B_FALSE); 2182 } 2183 } 2184 2185 argc -= optind; 2186 argv += optind; 2187 2188 /* check number of arguments */ 2189 if (argc < 1) { 2190 (void) fprintf(stderr, gettext("missing snapshot argument\n")); 2191 usage(B_FALSE); 2192 } 2193 if (argc > 1) { 2194 (void) fprintf(stderr, gettext("too many arguments\n")); 2195 usage(B_FALSE); 2196 } 2197 2198 if (isatty(STDIN_FILENO)) { 2199 (void) fprintf(stderr, 2200 gettext("Error: Backup stream can not be read " 2201 "from a terminal.\n" 2202 "You must redirect standard input.\n")); 2203 return (1); 2204 } 2205 2206 err = zfs_receive(g_zfs, argv[0], isprefix, verbose, dryrun, force, 2207 STDIN_FILENO); 2208 2209 if (!err) { 2210 zpool_log_history(g_zfs, argc + optind, argv - optind, argv[0], 2211 B_FALSE, B_FALSE); 2212 } 2213 2214 return (err != 0); 2215 } 2216 2217 typedef struct get_all_cbdata { 2218 zfs_handle_t **cb_handles; 2219 size_t cb_alloc; 2220 size_t cb_used; 2221 uint_t cb_types; 2222 } get_all_cbdata_t; 2223 2224 static int 2225 get_one_dataset(zfs_handle_t *zhp, void *data) 2226 { 2227 get_all_cbdata_t *cbp = data; 2228 zfs_type_t type = zfs_get_type(zhp); 2229 2230 /* 2231 * Interate over any nested datasets. 2232 */ 2233 if (type == ZFS_TYPE_FILESYSTEM && 2234 zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) { 2235 zfs_close(zhp); 2236 return (1); 2237 } 2238 2239 /* 2240 * Skip any datasets whose type does not match. 2241 */ 2242 if ((type & cbp->cb_types) == 0) { 2243 zfs_close(zhp); 2244 return (0); 2245 } 2246 2247 if (cbp->cb_alloc == cbp->cb_used) { 2248 zfs_handle_t **handles; 2249 2250 if (cbp->cb_alloc == 0) 2251 cbp->cb_alloc = 64; 2252 else 2253 cbp->cb_alloc *= 2; 2254 2255 handles = safe_malloc(cbp->cb_alloc * sizeof (void *)); 2256 2257 if (cbp->cb_handles) { 2258 bcopy(cbp->cb_handles, handles, 2259 cbp->cb_used * sizeof (void *)); 2260 free(cbp->cb_handles); 2261 } 2262 2263 cbp->cb_handles = handles; 2264 } 2265 2266 cbp->cb_handles[cbp->cb_used++] = zhp; 2267 2268 return (0); 2269 } 2270 2271 static void 2272 get_all_datasets(uint_t types, zfs_handle_t ***dslist, size_t *count) 2273 { 2274 get_all_cbdata_t cb = { 0 }; 2275 cb.cb_types = types; 2276 2277 (void) zfs_iter_root(g_zfs, get_one_dataset, &cb); 2278 2279 *dslist = cb.cb_handles; 2280 *count = cb.cb_used; 2281 } 2282 2283 static int 2284 dataset_cmp(const void *a, const void *b) 2285 { 2286 zfs_handle_t **za = (zfs_handle_t **)a; 2287 zfs_handle_t **zb = (zfs_handle_t **)b; 2288 char mounta[MAXPATHLEN]; 2289 char mountb[MAXPATHLEN]; 2290 boolean_t gota, gotb; 2291 2292 if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0) 2293 verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, 2294 sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); 2295 if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0) 2296 verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, 2297 sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); 2298 2299 if (gota && gotb) 2300 return (strcmp(mounta, mountb)); 2301 2302 if (gota) 2303 return (-1); 2304 if (gotb) 2305 return (1); 2306 2307 return (strcmp(zfs_get_name(a), zfs_get_name(b))); 2308 } 2309 2310 /* 2311 * Generic callback for sharing or mounting filesystems. Because the code is so 2312 * similar, we have a common function with an extra parameter to determine which 2313 * mode we are using. 2314 */ 2315 #define OP_SHARE 0x1 2316 #define OP_MOUNT 0x2 2317 2318 /* 2319 * Share or mount a dataset. 2320 */ 2321 static int 2322 share_mount_one(zfs_handle_t *zhp, int op, int flags, boolean_t explicit, 2323 const char *options) 2324 { 2325 char mountpoint[ZFS_MAXPROPLEN]; 2326 char shareopts[ZFS_MAXPROPLEN]; 2327 const char *cmdname = op == OP_SHARE ? "share" : "mount"; 2328 struct mnttab mnt; 2329 uint64_t zoned, canmount; 2330 zfs_type_t type = zfs_get_type(zhp); 2331 2332 assert(type & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)); 2333 2334 if (type == ZFS_TYPE_FILESYSTEM) { 2335 /* 2336 * Check to make sure we can mount/share this dataset. If we 2337 * are in the global zone and the filesystem is exported to a 2338 * local zone, or if we are in a local zone and the 2339 * filesystem is not exported, then it is an error. 2340 */ 2341 zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 2342 2343 if (zoned && getzoneid() == GLOBAL_ZONEID) { 2344 if (!explicit) 2345 return (0); 2346 2347 (void) fprintf(stderr, gettext("cannot %s '%s': " 2348 "dataset is exported to a local zone\n"), cmdname, 2349 zfs_get_name(zhp)); 2350 return (1); 2351 2352 } else if (!zoned && getzoneid() != GLOBAL_ZONEID) { 2353 if (!explicit) 2354 return (0); 2355 2356 (void) fprintf(stderr, gettext("cannot %s '%s': " 2357 "permission denied\n"), cmdname, 2358 zfs_get_name(zhp)); 2359 return (1); 2360 } 2361 2362 /* 2363 * Ignore any filesystems which don't apply to us. This 2364 * includes those with a legacy mountpoint, or those with 2365 * legacy share options. 2366 */ 2367 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, 2368 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); 2369 verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, 2370 sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); 2371 canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); 2372 2373 if (op == OP_SHARE && strcmp(shareopts, "off") == 0) { 2374 if (!explicit) 2375 return (0); 2376 2377 (void) fprintf(stderr, gettext("cannot share '%s': " 2378 "legacy share\n"), zfs_get_name(zhp)); 2379 (void) fprintf(stderr, gettext("use share(1M) to " 2380 "share this filesystem\n")); 2381 return (1); 2382 } 2383 2384 /* 2385 * We cannot share or mount legacy filesystems. If the 2386 * shareopts is non-legacy but the mountpoint is legacy, we 2387 * treat it as a legacy share. 2388 */ 2389 if (strcmp(mountpoint, "legacy") == 0) { 2390 if (!explicit) 2391 return (0); 2392 2393 (void) fprintf(stderr, gettext("cannot %s '%s': " 2394 "legacy mountpoint\n"), cmdname, zfs_get_name(zhp)); 2395 (void) fprintf(stderr, gettext("use %s to " 2396 "%s this filesystem\n"), op == OP_SHARE ? 2397 "share(1M)" : "mount(1M)", cmdname); 2398 return (1); 2399 } 2400 2401 if (strcmp(mountpoint, "none") == 0) { 2402 if (!explicit) 2403 return (0); 2404 2405 (void) fprintf(stderr, gettext("cannot %s '%s': no " 2406 "mountpoint set\n"), cmdname, zfs_get_name(zhp)); 2407 return (1); 2408 } 2409 2410 if (!canmount) { 2411 if (!explicit) 2412 return (0); 2413 2414 (void) fprintf(stderr, gettext("cannot %s '%s': " 2415 "'canmount' property is set to 'off'\n"), cmdname, 2416 zfs_get_name(zhp)); 2417 return (1); 2418 } 2419 2420 /* 2421 * At this point, we have verified that the mountpoint and/or 2422 * shareopts are appropriate for auto management. If the 2423 * filesystem is already mounted or shared, return (failing 2424 * for explicit requests); otherwise mount or share the 2425 * filesystem. 2426 */ 2427 switch (op) { 2428 case OP_SHARE: 2429 if (zfs_is_shared_nfs(zhp, NULL)) { 2430 if (!explicit) 2431 return (0); 2432 2433 (void) fprintf(stderr, gettext("cannot share " 2434 "'%s': filesystem already shared\n"), 2435 zfs_get_name(zhp)); 2436 return (1); 2437 } 2438 2439 if (!zfs_is_mounted(zhp, NULL) && 2440 zfs_mount(zhp, NULL, 0) != 0) 2441 return (1); 2442 2443 if (zfs_share_nfs(zhp) != 0) 2444 return (1); 2445 break; 2446 2447 case OP_MOUNT: 2448 if (options == NULL) 2449 mnt.mnt_mntopts = ""; 2450 else 2451 mnt.mnt_mntopts = (char *)options; 2452 2453 if (!hasmntopt(&mnt, MNTOPT_REMOUNT) && 2454 zfs_is_mounted(zhp, NULL)) { 2455 if (!explicit) 2456 return (0); 2457 2458 (void) fprintf(stderr, gettext("cannot mount " 2459 "'%s': filesystem already mounted\n"), 2460 zfs_get_name(zhp)); 2461 return (1); 2462 } 2463 2464 if (zfs_mount(zhp, options, flags) != 0) 2465 return (1); 2466 break; 2467 } 2468 } else { 2469 assert(op == OP_SHARE); 2470 2471 /* 2472 * Ignore any volumes that aren't shared. 2473 */ 2474 verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, shareopts, 2475 sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); 2476 2477 if (strcmp(shareopts, "off") == 0) { 2478 if (!explicit) 2479 return (0); 2480 2481 (void) fprintf(stderr, gettext("cannot share '%s': " 2482 "'shareiscsi' property not set\n"), 2483 zfs_get_name(zhp)); 2484 (void) fprintf(stderr, gettext("set 'shareiscsi' " 2485 "property or use iscsitadm(1M) to share this " 2486 "volume\n")); 2487 return (1); 2488 } 2489 2490 if (zfs_is_shared_iscsi(zhp)) { 2491 if (!explicit) 2492 return (0); 2493 2494 (void) fprintf(stderr, gettext("cannot share " 2495 "'%s': volume already shared\n"), 2496 zfs_get_name(zhp)); 2497 return (1); 2498 } 2499 2500 if (zfs_share_iscsi(zhp) != 0) 2501 return (1); 2502 } 2503 2504 return (0); 2505 } 2506 2507 static int 2508 share_mount(int op, int argc, char **argv) 2509 { 2510 int do_all = 0; 2511 int c, ret = 0; 2512 const char *options = NULL; 2513 int types, flags = 0; 2514 2515 /* check options */ 2516 while ((c = getopt(argc, argv, op == OP_MOUNT ? ":ao:O" : "a")) 2517 != -1) { 2518 switch (c) { 2519 case 'a': 2520 do_all = 1; 2521 break; 2522 case 'o': 2523 options = optarg; 2524 break; 2525 case 'O': 2526 flags |= MS_OVERLAY; 2527 break; 2528 case ':': 2529 (void) fprintf(stderr, gettext("missing argument for " 2530 "'%c' option\n"), optopt); 2531 usage(B_FALSE); 2532 break; 2533 case '?': 2534 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2535 optopt); 2536 usage(B_FALSE); 2537 } 2538 } 2539 2540 argc -= optind; 2541 argv += optind; 2542 2543 /* check number of arguments */ 2544 if (do_all) { 2545 zfs_handle_t **dslist = NULL; 2546 size_t i, count = 0; 2547 2548 if (op == OP_MOUNT) { 2549 types = ZFS_TYPE_FILESYSTEM; 2550 } else if (argc > 0) { 2551 if (strcmp(argv[0], "nfs") == 0) { 2552 types = ZFS_TYPE_FILESYSTEM; 2553 } else if (strcmp(argv[0], "iscsi") == 0) { 2554 types = ZFS_TYPE_VOLUME; 2555 } else { 2556 (void) fprintf(stderr, gettext("share type " 2557 "must be 'nfs' or 'iscsi'\n")); 2558 usage(B_FALSE); 2559 } 2560 2561 argc--; 2562 argv++; 2563 } else { 2564 types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME; 2565 } 2566 2567 if (argc != 0) { 2568 (void) fprintf(stderr, gettext("too many arguments\n")); 2569 usage(B_FALSE); 2570 } 2571 2572 get_all_datasets(types, &dslist, &count); 2573 2574 if (count == 0) 2575 return (0); 2576 2577 qsort(dslist, count, sizeof (void *), dataset_cmp); 2578 2579 for (i = 0; i < count; i++) { 2580 if (share_mount_one(dslist[i], op, flags, B_FALSE, 2581 options) != 0) 2582 ret = 1; 2583 zfs_close(dslist[i]); 2584 } 2585 2586 free(dslist); 2587 } else if (argc == 0) { 2588 struct mnttab entry; 2589 2590 if (op == OP_SHARE) { 2591 (void) fprintf(stderr, gettext("missing filesystem " 2592 "argument\n")); 2593 usage(B_FALSE); 2594 } 2595 2596 /* 2597 * When mount is given no arguments, go through /etc/mnttab and 2598 * display any active ZFS mounts. We hide any snapshots, since 2599 * they are controlled automatically. 2600 */ 2601 rewind(mnttab_file); 2602 while (getmntent(mnttab_file, &entry) == 0) { 2603 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0 || 2604 strchr(entry.mnt_special, '@') != NULL) 2605 continue; 2606 2607 (void) printf("%-30s %s\n", entry.mnt_special, 2608 entry.mnt_mountp); 2609 } 2610 2611 } else { 2612 zfs_handle_t *zhp; 2613 2614 types = ZFS_TYPE_FILESYSTEM; 2615 if (op == OP_SHARE) 2616 types |= ZFS_TYPE_VOLUME; 2617 2618 if (argc > 1) { 2619 (void) fprintf(stderr, 2620 gettext("too many arguments\n")); 2621 usage(B_FALSE); 2622 } 2623 2624 if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) { 2625 ret = 1; 2626 } else { 2627 ret = share_mount_one(zhp, op, flags, B_TRUE, 2628 options); 2629 zfs_close(zhp); 2630 } 2631 } 2632 2633 return (ret); 2634 } 2635 2636 /* 2637 * zfs mount -a [nfs | iscsi] 2638 * zfs mount filesystem 2639 * 2640 * Mount all filesystems, or mount the given filesystem. 2641 */ 2642 static int 2643 zfs_do_mount(int argc, char **argv) 2644 { 2645 return (share_mount(OP_MOUNT, argc, argv)); 2646 } 2647 2648 /* 2649 * zfs share -a [nfs | iscsi] 2650 * zfs share filesystem 2651 * 2652 * Share all filesystems, or share the given filesystem. 2653 */ 2654 static int 2655 zfs_do_share(int argc, char **argv) 2656 { 2657 return (share_mount(OP_SHARE, argc, argv)); 2658 } 2659 2660 typedef struct unshare_unmount_node { 2661 zfs_handle_t *un_zhp; 2662 char *un_mountp; 2663 uu_avl_node_t un_avlnode; 2664 } unshare_unmount_node_t; 2665 2666 /* ARGSUSED */ 2667 static int 2668 unshare_unmount_compare(const void *larg, const void *rarg, void *unused) 2669 { 2670 const unshare_unmount_node_t *l = larg; 2671 const unshare_unmount_node_t *r = rarg; 2672 2673 return (strcmp(l->un_mountp, r->un_mountp)); 2674 } 2675 2676 /* 2677 * Convenience routine used by zfs_do_umount() and manual_unmount(). Given an 2678 * absolute path, find the entry /etc/mnttab, verify that its a ZFS filesystem, 2679 * and unmount it appropriately. 2680 */ 2681 static int 2682 unshare_unmount_path(int op, char *path, int flags, boolean_t is_manual) 2683 { 2684 zfs_handle_t *zhp; 2685 int ret; 2686 struct stat64 statbuf; 2687 struct extmnttab entry; 2688 const char *cmdname = (op == OP_SHARE) ? "unshare" : "unmount"; 2689 char property[ZFS_MAXPROPLEN]; 2690 2691 /* 2692 * Search for the path in /etc/mnttab. Rather than looking for the 2693 * specific path, which can be fooled by non-standard paths (i.e. ".." 2694 * or "//"), we stat() the path and search for the corresponding 2695 * (major,minor) device pair. 2696 */ 2697 if (stat64(path, &statbuf) != 0) { 2698 (void) fprintf(stderr, gettext("cannot %s '%s': %s\n"), 2699 cmdname, path, strerror(errno)); 2700 return (1); 2701 } 2702 2703 /* 2704 * Search for the given (major,minor) pair in the mount table. 2705 */ 2706 rewind(mnttab_file); 2707 while ((ret = getextmntent(mnttab_file, &entry, 0)) == 0) { 2708 if (entry.mnt_major == major(statbuf.st_dev) && 2709 entry.mnt_minor == minor(statbuf.st_dev)) 2710 break; 2711 } 2712 if (ret != 0) { 2713 (void) fprintf(stderr, gettext("cannot %s '%s': not " 2714 "currently mounted\n"), cmdname, path); 2715 return (1); 2716 } 2717 2718 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { 2719 (void) fprintf(stderr, gettext("cannot %s '%s': not a ZFS " 2720 "filesystem\n"), cmdname, path); 2721 return (1); 2722 } 2723 2724 if ((zhp = zfs_open(g_zfs, entry.mnt_special, 2725 ZFS_TYPE_FILESYSTEM)) == NULL) 2726 return (1); 2727 2728 verify(zfs_prop_get(zhp, op == OP_SHARE ? 2729 ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, 2730 sizeof (property), NULL, NULL, 0, B_FALSE) == 0); 2731 2732 if (op == OP_SHARE) { 2733 if (strcmp(property, "off") == 0) { 2734 (void) fprintf(stderr, gettext("cannot unshare " 2735 "'%s': legacy share\n"), path); 2736 (void) fprintf(stderr, gettext("use " 2737 "unshare(1M) to unshare this filesystem\n")); 2738 ret = 1; 2739 } else if (!zfs_is_shared_nfs(zhp, NULL)) { 2740 (void) fprintf(stderr, gettext("cannot unshare '%s': " 2741 "not currently shared\n"), path); 2742 ret = 1; 2743 } else { 2744 ret = zfs_unshareall_nfs(zhp); 2745 } 2746 } else { 2747 if (is_manual) { 2748 ret = zfs_unmount(zhp, NULL, flags); 2749 } else if (strcmp(property, "legacy") == 0) { 2750 (void) fprintf(stderr, gettext("cannot unmount " 2751 "'%s': legacy mountpoint\n"), 2752 zfs_get_name(zhp)); 2753 (void) fprintf(stderr, gettext("use umount(1M) " 2754 "to unmount this filesystem\n")); 2755 ret = 1; 2756 } else { 2757 ret = zfs_unmountall(zhp, flags); 2758 } 2759 } 2760 2761 zfs_close(zhp); 2762 2763 return (ret != 0); 2764 } 2765 2766 /* 2767 * Generic callback for unsharing or unmounting a filesystem. 2768 */ 2769 static int 2770 unshare_unmount(int op, int argc, char **argv) 2771 { 2772 int do_all = 0; 2773 int flags = 0; 2774 int ret = 0; 2775 int types, c; 2776 zfs_handle_t *zhp; 2777 char property[ZFS_MAXPROPLEN]; 2778 2779 /* check options */ 2780 while ((c = getopt(argc, argv, op == OP_SHARE ? "a" : "af")) != -1) { 2781 switch (c) { 2782 case 'a': 2783 do_all = 1; 2784 break; 2785 case 'f': 2786 flags = MS_FORCE; 2787 break; 2788 case '?': 2789 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2790 optopt); 2791 usage(B_FALSE); 2792 } 2793 } 2794 2795 argc -= optind; 2796 argv += optind; 2797 2798 if (do_all) { 2799 /* 2800 * We could make use of zfs_for_each() to walk all datasets in 2801 * the system, but this would be very inefficient, especially 2802 * since we would have to linearly search /etc/mnttab for each 2803 * one. Instead, do one pass through /etc/mnttab looking for 2804 * zfs entries and call zfs_unmount() for each one. 2805 * 2806 * Things get a little tricky if the administrator has created 2807 * mountpoints beneath other ZFS filesystems. In this case, we 2808 * have to unmount the deepest filesystems first. To accomplish 2809 * this, we place all the mountpoints in an AVL tree sorted by 2810 * the special type (dataset name), and walk the result in 2811 * reverse to make sure to get any snapshots first. 2812 */ 2813 struct mnttab entry; 2814 uu_avl_pool_t *pool; 2815 uu_avl_t *tree; 2816 unshare_unmount_node_t *node; 2817 uu_avl_index_t idx; 2818 uu_avl_walk_t *walk; 2819 2820 if (argc != 0) { 2821 (void) fprintf(stderr, gettext("too many arguments\n")); 2822 usage(B_FALSE); 2823 } 2824 2825 if ((pool = uu_avl_pool_create("unmount_pool", 2826 sizeof (unshare_unmount_node_t), 2827 offsetof(unshare_unmount_node_t, un_avlnode), 2828 unshare_unmount_compare, 2829 UU_DEFAULT)) == NULL) { 2830 (void) fprintf(stderr, gettext("internal error: " 2831 "out of memory\n")); 2832 exit(1); 2833 } 2834 2835 if ((tree = uu_avl_create(pool, NULL, UU_DEFAULT)) == NULL) { 2836 (void) fprintf(stderr, gettext("internal error: " 2837 "out of memory\n")); 2838 exit(1); 2839 } 2840 2841 rewind(mnttab_file); 2842 while (getmntent(mnttab_file, &entry) == 0) { 2843 2844 /* ignore non-ZFS entries */ 2845 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) 2846 continue; 2847 2848 /* ignore snapshots */ 2849 if (strchr(entry.mnt_special, '@') != NULL) 2850 continue; 2851 2852 if ((zhp = zfs_open(g_zfs, entry.mnt_special, 2853 ZFS_TYPE_FILESYSTEM)) == NULL) { 2854 ret = 1; 2855 continue; 2856 } 2857 2858 verify(zfs_prop_get(zhp, op == OP_SHARE ? 2859 ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, 2860 property, sizeof (property), NULL, NULL, 2861 0, B_FALSE) == 0); 2862 2863 /* Ignore legacy mounts and shares */ 2864 if ((op == OP_SHARE && 2865 strcmp(property, "off") == 0) || 2866 (op == OP_MOUNT && 2867 strcmp(property, "legacy") == 0)) { 2868 zfs_close(zhp); 2869 continue; 2870 } 2871 2872 node = safe_malloc(sizeof (unshare_unmount_node_t)); 2873 node->un_zhp = zhp; 2874 2875 if ((node->un_mountp = strdup(entry.mnt_mountp)) == 2876 NULL) { 2877 (void) fprintf(stderr, gettext("internal error:" 2878 " out of memory\n")); 2879 exit(1); 2880 } 2881 2882 uu_avl_node_init(node, &node->un_avlnode, pool); 2883 2884 if (uu_avl_find(tree, node, NULL, &idx) == NULL) { 2885 uu_avl_insert(tree, node, idx); 2886 } else { 2887 zfs_close(node->un_zhp); 2888 free(node->un_mountp); 2889 free(node); 2890 } 2891 } 2892 2893 /* 2894 * Walk the AVL tree in reverse, unmounting each filesystem and 2895 * removing it from the AVL tree in the process. 2896 */ 2897 if ((walk = uu_avl_walk_start(tree, 2898 UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL) { 2899 (void) fprintf(stderr, 2900 gettext("internal error: out of memory")); 2901 exit(1); 2902 } 2903 2904 while ((node = uu_avl_walk_next(walk)) != NULL) { 2905 uu_avl_remove(tree, node); 2906 2907 switch (op) { 2908 case OP_SHARE: 2909 if (zfs_unshare_nfs(node->un_zhp, 2910 node->un_mountp) != 0) 2911 ret = 1; 2912 break; 2913 2914 case OP_MOUNT: 2915 if (zfs_unmount(node->un_zhp, 2916 node->un_mountp, flags) != 0) 2917 ret = 1; 2918 break; 2919 } 2920 2921 zfs_close(node->un_zhp); 2922 free(node->un_mountp); 2923 free(node); 2924 } 2925 2926 uu_avl_walk_end(walk); 2927 uu_avl_destroy(tree); 2928 uu_avl_pool_destroy(pool); 2929 2930 if (op == OP_SHARE) { 2931 /* 2932 * Finally, unshare any volumes shared via iSCSI. 2933 */ 2934 zfs_handle_t **dslist = NULL; 2935 size_t i, count = 0; 2936 2937 get_all_datasets(ZFS_TYPE_VOLUME, &dslist, &count); 2938 2939 if (count != 0) { 2940 qsort(dslist, count, sizeof (void *), 2941 dataset_cmp); 2942 2943 for (i = 0; i < count; i++) { 2944 if (zfs_unshare_iscsi(dslist[i]) != 0) 2945 ret = 1; 2946 zfs_close(dslist[i]); 2947 } 2948 2949 free(dslist); 2950 } 2951 } 2952 } else { 2953 if (argc != 1) { 2954 if (argc == 0) 2955 (void) fprintf(stderr, 2956 gettext("missing filesystem argument\n")); 2957 else 2958 (void) fprintf(stderr, 2959 gettext("too many arguments\n")); 2960 usage(B_FALSE); 2961 } 2962 2963 /* 2964 * We have an argument, but it may be a full path or a ZFS 2965 * filesystem. Pass full paths off to unmount_path() (shared by 2966 * manual_unmount), otherwise open the filesystem and pass to 2967 * zfs_unmount(). 2968 */ 2969 if (argv[0][0] == '/') 2970 return (unshare_unmount_path(op, argv[0], 2971 flags, B_FALSE)); 2972 2973 types = ZFS_TYPE_FILESYSTEM; 2974 if (op == OP_SHARE) 2975 types |= ZFS_TYPE_VOLUME; 2976 2977 if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) 2978 return (1); 2979 2980 if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { 2981 verify(zfs_prop_get(zhp, op == OP_SHARE ? 2982 ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, 2983 sizeof (property), NULL, NULL, 0, B_FALSE) == 0); 2984 2985 switch (op) { 2986 case OP_SHARE: 2987 if (strcmp(property, "off") == 0) { 2988 (void) fprintf(stderr, gettext("cannot " 2989 "unshare '%s': legacy share\n"), 2990 zfs_get_name(zhp)); 2991 (void) fprintf(stderr, gettext("use " 2992 "unshare(1M) to unshare this " 2993 "filesystem\n")); 2994 ret = 1; 2995 } else if (!zfs_is_shared_nfs(zhp, NULL)) { 2996 (void) fprintf(stderr, gettext("cannot " 2997 "unshare '%s': not currently " 2998 "shared\n"), zfs_get_name(zhp)); 2999 ret = 1; 3000 } else if (zfs_unshareall_nfs(zhp) != 0) { 3001 ret = 1; 3002 } 3003 break; 3004 3005 case OP_MOUNT: 3006 if (strcmp(property, "legacy") == 0) { 3007 (void) fprintf(stderr, gettext("cannot " 3008 "unmount '%s': legacy " 3009 "mountpoint\n"), zfs_get_name(zhp)); 3010 (void) fprintf(stderr, gettext("use " 3011 "umount(1M) to unmount this " 3012 "filesystem\n")); 3013 ret = 1; 3014 } else if (!zfs_is_mounted(zhp, NULL)) { 3015 (void) fprintf(stderr, gettext("cannot " 3016 "unmount '%s': not currently " 3017 "mounted\n"), 3018 zfs_get_name(zhp)); 3019 ret = 1; 3020 } else if (zfs_unmountall(zhp, flags) != 0) { 3021 ret = 1; 3022 } 3023 break; 3024 } 3025 } else { 3026 assert(op == OP_SHARE); 3027 3028 verify(zfs_prop_get(zhp, ZFS_PROP_SHAREISCSI, property, 3029 sizeof (property), NULL, NULL, 0, B_FALSE) == 0); 3030 3031 if (strcmp(property, "off") == 0) { 3032 (void) fprintf(stderr, gettext("cannot unshare " 3033 "'%s': 'shareiscsi' property not set\n"), 3034 zfs_get_name(zhp)); 3035 (void) fprintf(stderr, gettext("set " 3036 "'shareiscsi' property or use " 3037 "iscsitadm(1M) to share this volume\n")); 3038 ret = 1; 3039 } else if (!zfs_is_shared_iscsi(zhp)) { 3040 (void) fprintf(stderr, gettext("cannot " 3041 "unshare '%s': not currently shared\n"), 3042 zfs_get_name(zhp)); 3043 ret = 1; 3044 } else if (zfs_unshare_iscsi(zhp) != 0) { 3045 ret = 1; 3046 } 3047 } 3048 3049 zfs_close(zhp); 3050 } 3051 3052 return (ret); 3053 } 3054 3055 /* 3056 * zfs unmount -a 3057 * zfs unmount filesystem 3058 * 3059 * Unmount all filesystems, or a specific ZFS filesystem. 3060 */ 3061 static int 3062 zfs_do_unmount(int argc, char **argv) 3063 { 3064 return (unshare_unmount(OP_MOUNT, argc, argv)); 3065 } 3066 3067 /* 3068 * zfs unshare -a 3069 * zfs unshare filesystem 3070 * 3071 * Unshare all filesystems, or a specific ZFS filesystem. 3072 */ 3073 static int 3074 zfs_do_unshare(int argc, char **argv) 3075 { 3076 return (unshare_unmount(OP_SHARE, argc, argv)); 3077 } 3078 3079 /* 3080 * Called when invoked as /etc/fs/zfs/mount. Do the mount if the mountpoint is 3081 * 'legacy'. Otherwise, complain that use should be using 'zfs mount'. 3082 */ 3083 static int 3084 manual_mount(int argc, char **argv) 3085 { 3086 zfs_handle_t *zhp; 3087 char mountpoint[ZFS_MAXPROPLEN]; 3088 char mntopts[MNT_LINE_MAX] = { '\0' }; 3089 int ret; 3090 int c; 3091 int flags = 0; 3092 char *dataset, *path; 3093 3094 /* check options */ 3095 while ((c = getopt(argc, argv, ":mo:O")) != -1) { 3096 switch (c) { 3097 case 'o': 3098 (void) strlcpy(mntopts, optarg, sizeof (mntopts)); 3099 break; 3100 case 'O': 3101 flags |= MS_OVERLAY; 3102 break; 3103 case 'm': 3104 flags |= MS_NOMNTTAB; 3105 break; 3106 case ':': 3107 (void) fprintf(stderr, gettext("missing argument for " 3108 "'%c' option\n"), optopt); 3109 usage(B_FALSE); 3110 break; 3111 case '?': 3112 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3113 optopt); 3114 (void) fprintf(stderr, gettext("usage: mount [-o opts] " 3115 "<path>\n")); 3116 return (2); 3117 } 3118 } 3119 3120 argc -= optind; 3121 argv += optind; 3122 3123 /* check that we only have two arguments */ 3124 if (argc != 2) { 3125 if (argc == 0) 3126 (void) fprintf(stderr, gettext("missing dataset " 3127 "argument\n")); 3128 else if (argc == 1) 3129 (void) fprintf(stderr, 3130 gettext("missing mountpoint argument\n")); 3131 else 3132 (void) fprintf(stderr, gettext("too many arguments\n")); 3133 (void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n"); 3134 return (2); 3135 } 3136 3137 dataset = argv[0]; 3138 path = argv[1]; 3139 3140 /* try to open the dataset */ 3141 if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) 3142 return (1); 3143 3144 (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, 3145 sizeof (mountpoint), NULL, NULL, 0, B_FALSE); 3146 3147 /* check for legacy mountpoint and complain appropriately */ 3148 ret = 0; 3149 if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) { 3150 if (mount(dataset, path, MS_OPTIONSTR | flags, MNTTYPE_ZFS, 3151 NULL, 0, mntopts, sizeof (mntopts)) != 0) { 3152 (void) fprintf(stderr, gettext("mount failed: %s\n"), 3153 strerror(errno)); 3154 ret = 1; 3155 } 3156 } else { 3157 (void) fprintf(stderr, gettext("filesystem '%s' cannot be " 3158 "mounted using 'mount -F zfs'\n"), dataset); 3159 (void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' " 3160 "instead.\n"), path); 3161 (void) fprintf(stderr, gettext("If you must use 'mount -F zfs' " 3162 "or /etc/vfstab, use 'zfs set mountpoint=legacy'.\n")); 3163 (void) fprintf(stderr, gettext("See zfs(1M) for more " 3164 "information.\n")); 3165 ret = 1; 3166 } 3167 3168 return (ret); 3169 } 3170 3171 /* 3172 * Called when invoked as /etc/fs/zfs/umount. Unlike a manual mount, we allow 3173 * unmounts of non-legacy filesystems, as this is the dominant administrative 3174 * interface. 3175 */ 3176 static int 3177 manual_unmount(int argc, char **argv) 3178 { 3179 int flags = 0; 3180 int c; 3181 3182 /* check options */ 3183 while ((c = getopt(argc, argv, "f")) != -1) { 3184 switch (c) { 3185 case 'f': 3186 flags = MS_FORCE; 3187 break; 3188 case '?': 3189 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 3190 optopt); 3191 (void) fprintf(stderr, gettext("usage: unmount [-f] " 3192 "<path>\n")); 3193 return (2); 3194 } 3195 } 3196 3197 argc -= optind; 3198 argv += optind; 3199 3200 /* check arguments */ 3201 if (argc != 1) { 3202 if (argc == 0) 3203 (void) fprintf(stderr, gettext("missing path " 3204 "argument\n")); 3205 else 3206 (void) fprintf(stderr, gettext("too many arguments\n")); 3207 (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n")); 3208 return (2); 3209 } 3210 3211 return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE)); 3212 } 3213 3214 static int 3215 volcheck(zpool_handle_t *zhp, void *data) 3216 { 3217 boolean_t isinit = *((boolean_t *)data); 3218 3219 if (isinit) 3220 return (zpool_create_zvol_links(zhp)); 3221 else 3222 return (zpool_remove_zvol_links(zhp)); 3223 } 3224 3225 /* 3226 * Iterate over all pools in the system and either create or destroy /dev/zvol 3227 * links, depending on the value of 'isinit'. 3228 */ 3229 static int 3230 do_volcheck(boolean_t isinit) 3231 { 3232 return (zpool_iter(g_zfs, volcheck, &isinit) ? 1 : 0); 3233 } 3234 3235 int 3236 main(int argc, char **argv) 3237 { 3238 int ret; 3239 int i; 3240 char *progname; 3241 char *cmdname; 3242 3243 (void) setlocale(LC_ALL, ""); 3244 (void) textdomain(TEXT_DOMAIN); 3245 3246 opterr = 0; 3247 3248 if ((g_zfs = libzfs_init()) == NULL) { 3249 (void) fprintf(stderr, gettext("internal error: failed to " 3250 "initialize ZFS library\n")); 3251 return (1); 3252 } 3253 3254 libzfs_print_on_error(g_zfs, B_TRUE); 3255 3256 if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) { 3257 (void) fprintf(stderr, gettext("internal error: unable to " 3258 "open %s\n"), MNTTAB); 3259 return (1); 3260 } 3261 3262 /* 3263 * This command also doubles as the /etc/fs mount and unmount program. 3264 * Determine if we should take this behavior based on argv[0]. 3265 */ 3266 progname = basename(argv[0]); 3267 if (strcmp(progname, "mount") == 0) { 3268 ret = manual_mount(argc, argv); 3269 } else if (strcmp(progname, "umount") == 0) { 3270 ret = manual_unmount(argc, argv); 3271 } else { 3272 /* 3273 * Make sure the user has specified some command. 3274 */ 3275 if (argc < 2) { 3276 (void) fprintf(stderr, gettext("missing command\n")); 3277 usage(B_FALSE); 3278 } 3279 3280 cmdname = argv[1]; 3281 3282 /* 3283 * The 'umount' command is an alias for 'unmount' 3284 */ 3285 if (strcmp(cmdname, "umount") == 0) 3286 cmdname = "unmount"; 3287 3288 /* 3289 * The 'recv' command is an alias for 'receive' 3290 */ 3291 if (strcmp(cmdname, "recv") == 0) 3292 cmdname = "receive"; 3293 3294 /* 3295 * Special case '-?' 3296 */ 3297 if (strcmp(cmdname, "-?") == 0) 3298 usage(B_TRUE); 3299 3300 /* 3301 * 'volinit' and 'volfini' do not appear in the usage message, 3302 * so we have to special case them here. 3303 */ 3304 if (strcmp(cmdname, "volinit") == 0) 3305 return (do_volcheck(B_TRUE)); 3306 else if (strcmp(cmdname, "volfini") == 0) 3307 return (do_volcheck(B_FALSE)); 3308 3309 /* 3310 * Run the appropriate command. 3311 */ 3312 for (i = 0; i < NCOMMAND; i++) { 3313 if (command_table[i].name == NULL) 3314 continue; 3315 3316 if (strcmp(cmdname, command_table[i].name) == 0) { 3317 current_command = &command_table[i]; 3318 ret = command_table[i].func(argc - 1, argv + 1); 3319 break; 3320 } 3321 } 3322 3323 if (i == NCOMMAND) { 3324 (void) fprintf(stderr, gettext("unrecognized " 3325 "command '%s'\n"), cmdname); 3326 usage(B_FALSE); 3327 } 3328 } 3329 3330 (void) fclose(mnttab_file); 3331 3332 libzfs_fini(g_zfs); 3333 3334 /* 3335 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 3336 * for the purposes of running ::findleaks. 3337 */ 3338 if (getenv("ZFS_ABORT") != NULL) { 3339 (void) printf("dumping core by request\n"); 3340 abort(); 3341 } 3342 3343 return (ret); 3344 } 3345