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