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