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 return (1); 1641 1642 ret = 0; 1643 error: 1644 return (ret); 1645 } 1646 1647 static int 1648 zfs_do_set(int argc, char **argv) 1649 { 1650 set_cbdata_t cb; 1651 1652 /* check for options */ 1653 if (argc > 1 && argv[1][0] == '-') { 1654 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1655 argv[1][1]); 1656 usage(B_FALSE); 1657 } 1658 1659 /* check number of arguments */ 1660 if (argc < 2) { 1661 (void) fprintf(stderr, gettext("missing property=value " 1662 "argument\n")); 1663 usage(B_FALSE); 1664 } 1665 if (argc < 3) { 1666 (void) fprintf(stderr, gettext("missing dataset name\n")); 1667 usage(B_FALSE); 1668 } 1669 1670 /* validate property=value argument */ 1671 cb.cb_propname = argv[1]; 1672 if ((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) { 1673 (void) fprintf(stderr, gettext("missing value in " 1674 "property=value argument\n")); 1675 usage(B_FALSE); 1676 } 1677 1678 *cb.cb_value = '\0'; 1679 cb.cb_value++; 1680 1681 if (*cb.cb_propname == '\0') { 1682 (void) fprintf(stderr, 1683 gettext("missing property in property=value argument\n")); 1684 usage(B_FALSE); 1685 } 1686 if (*cb.cb_value == '\0') { 1687 (void) fprintf(stderr, 1688 gettext("missing value in property=value argument\n")); 1689 usage(B_FALSE); 1690 } 1691 1692 /* get the property type */ 1693 if ((cb.cb_prop = zfs_name_to_prop(cb.cb_propname)) == 1694 ZFS_PROP_INVAL) { 1695 (void) fprintf(stderr, 1696 gettext("invalid property '%s'\n"), cb.cb_propname); 1697 usage(B_FALSE); 1698 } 1699 1700 /* 1701 * Validate that the value is appropriate for this property. We do this 1702 * once now so we don't generate multiple errors each time we try to 1703 * apply it to a dataset. 1704 */ 1705 if (zfs_prop_validate(g_zfs, cb.cb_prop, cb.cb_value, NULL) != 0) 1706 return (1); 1707 1708 return (zfs_for_each(argc - 2, argv + 2, B_FALSE, 1709 ZFS_TYPE_ANY, set_callback, &cb)); 1710 } 1711 1712 /* 1713 * zfs snapshot <fs@snap> 1714 * 1715 * Creates a snapshot with the given name. While functionally equivalent to 1716 * 'zfs create', it is a separate command to diffferentiate intent. 1717 */ 1718 static int 1719 zfs_do_snapshot(int argc, char **argv) 1720 { 1721 /* check options */ 1722 if (argc > 1 && argv[1][0] == '-') { 1723 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1724 argv[1][1]); 1725 usage(B_FALSE); 1726 } 1727 1728 /* check number of arguments */ 1729 if (argc < 2) { 1730 (void) fprintf(stderr, gettext("missing snapshot argument\n")); 1731 usage(B_FALSE); 1732 } 1733 if (argc > 2) { 1734 (void) fprintf(stderr, gettext("too many arguments\n")); 1735 usage(B_FALSE); 1736 } 1737 1738 return (zfs_snapshot(g_zfs, argv[1]) != 0); 1739 } 1740 1741 /* 1742 * zfs send [-i <fs@snap>] <fs@snap> 1743 * 1744 * Send a backup stream to stdout. 1745 */ 1746 static int 1747 zfs_do_send(int argc, char **argv) 1748 { 1749 char *fromname = NULL; 1750 zfs_handle_t *zhp_from = NULL, *zhp_to; 1751 int c, err; 1752 1753 /* check options */ 1754 while ((c = getopt(argc, argv, ":i:")) != -1) { 1755 switch (c) { 1756 case 'i': 1757 fromname = optarg; 1758 break; 1759 case ':': 1760 (void) fprintf(stderr, gettext("missing argument for " 1761 "'%c' option\n"), optopt); 1762 usage(B_FALSE); 1763 break; 1764 case '?': 1765 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1766 optopt); 1767 usage(B_FALSE); 1768 } 1769 } 1770 1771 argc -= optind; 1772 argv += optind; 1773 1774 /* check number of arguments */ 1775 if (argc < 1) { 1776 (void) fprintf(stderr, gettext("missing snapshot argument\n")); 1777 usage(B_FALSE); 1778 } 1779 if (argc > 1) { 1780 (void) fprintf(stderr, gettext("too many arguments\n")); 1781 usage(B_FALSE); 1782 } 1783 1784 if (isatty(STDOUT_FILENO)) { 1785 (void) fprintf(stderr, 1786 gettext("Error: Stream can not be written " 1787 "to a terminal.\n" 1788 "You must redirect standard output.\n")); 1789 return (1); 1790 } 1791 1792 if (fromname) { 1793 if ((zhp_from = zfs_open(g_zfs, fromname, 1794 ZFS_TYPE_SNAPSHOT)) == NULL) 1795 return (1); 1796 } 1797 if ((zhp_to = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) 1798 return (1); 1799 1800 err = zfs_send(zhp_to, zhp_from); 1801 1802 if (zhp_from) 1803 zfs_close(zhp_from); 1804 zfs_close(zhp_to); 1805 1806 return (err != 0); 1807 } 1808 1809 /* 1810 * zfs receive <fs@snap> 1811 * 1812 * Restore a backup stream from stdin. 1813 */ 1814 static int 1815 zfs_do_receive(int argc, char **argv) 1816 { 1817 int c, err; 1818 boolean_t isprefix = B_FALSE; 1819 boolean_t dryrun = B_FALSE; 1820 boolean_t verbose = B_FALSE; 1821 1822 /* check options */ 1823 while ((c = getopt(argc, argv, ":dnv")) != -1) { 1824 switch (c) { 1825 case 'd': 1826 isprefix = B_TRUE; 1827 break; 1828 case 'n': 1829 dryrun = B_TRUE; 1830 break; 1831 case 'v': 1832 verbose = B_TRUE; 1833 break; 1834 case ':': 1835 (void) fprintf(stderr, gettext("missing argument for " 1836 "'%c' option\n"), optopt); 1837 usage(B_FALSE); 1838 break; 1839 case '?': 1840 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 1841 optopt); 1842 usage(B_FALSE); 1843 } 1844 } 1845 1846 argc -= optind; 1847 argv += optind; 1848 1849 /* check number of arguments */ 1850 if (argc < 1) { 1851 (void) fprintf(stderr, gettext("missing snapshot argument\n")); 1852 usage(B_FALSE); 1853 } 1854 if (argc > 1) { 1855 (void) fprintf(stderr, gettext("too many arguments\n")); 1856 usage(B_FALSE); 1857 } 1858 1859 if (isatty(STDIN_FILENO)) { 1860 (void) fprintf(stderr, 1861 gettext("Error: Backup stream can not be read " 1862 "from a terminal.\n" 1863 "You must redirect standard input.\n")); 1864 return (1); 1865 } 1866 1867 err = zfs_receive(g_zfs, argv[0], isprefix, verbose, dryrun); 1868 return (err != 0); 1869 } 1870 1871 typedef struct get_all_cbdata { 1872 zfs_handle_t **cb_handles; 1873 size_t cb_alloc; 1874 size_t cb_used; 1875 } get_all_cbdata_t; 1876 1877 static int 1878 get_one_filesystem(zfs_handle_t *zhp, void *data) 1879 { 1880 get_all_cbdata_t *cbp = data; 1881 1882 /* 1883 * Skip any zvols 1884 */ 1885 if (zfs_get_type(zhp) != ZFS_TYPE_FILESYSTEM) { 1886 zfs_close(zhp); 1887 return (0); 1888 } 1889 1890 if (cbp->cb_alloc == cbp->cb_used) { 1891 zfs_handle_t **handles; 1892 1893 if (cbp->cb_alloc == 0) 1894 cbp->cb_alloc = 64; 1895 else 1896 cbp->cb_alloc *= 2; 1897 1898 handles = safe_malloc(cbp->cb_alloc * sizeof (void *)); 1899 1900 if (cbp->cb_handles) { 1901 bcopy(cbp->cb_handles, handles, 1902 cbp->cb_used * sizeof (void *)); 1903 free(cbp->cb_handles); 1904 } 1905 1906 cbp->cb_handles = handles; 1907 } 1908 1909 cbp->cb_handles[cbp->cb_used++] = zhp; 1910 1911 return (zfs_iter_filesystems(zhp, get_one_filesystem, data)); 1912 } 1913 1914 static void 1915 get_all_filesystems(zfs_handle_t ***fslist, size_t *count) 1916 { 1917 get_all_cbdata_t cb = { 0 }; 1918 1919 (void) zfs_iter_root(g_zfs, get_one_filesystem, &cb); 1920 1921 *fslist = cb.cb_handles; 1922 *count = cb.cb_used; 1923 } 1924 1925 static int 1926 mountpoint_compare(const void *a, const void *b) 1927 { 1928 zfs_handle_t **za = (zfs_handle_t **)a; 1929 zfs_handle_t **zb = (zfs_handle_t **)b; 1930 char mounta[MAXPATHLEN]; 1931 char mountb[MAXPATHLEN]; 1932 1933 verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, 1934 sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); 1935 verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, 1936 sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); 1937 1938 return (strcmp(mounta, mountb)); 1939 } 1940 1941 /* 1942 * Generic callback for sharing or mounting filesystems. Because the code is so 1943 * similar, we have a common function with an extra parameter to determine which 1944 * mode we are using. 1945 */ 1946 #define OP_SHARE 0x1 1947 #define OP_MOUNT 0x2 1948 1949 typedef struct share_mount_cbdata { 1950 int cb_type; 1951 int cb_explicit; 1952 int cb_flags; 1953 const char *cb_options; 1954 } share_mount_cbdata_t; 1955 1956 /* 1957 * Share or mount the filesystem. 1958 */ 1959 static int 1960 share_mount_callback(zfs_handle_t *zhp, void *data) 1961 { 1962 char mountpoint[ZFS_MAXPROPLEN]; 1963 char shareopts[ZFS_MAXPROPLEN]; 1964 share_mount_cbdata_t *cbp = data; 1965 const char *cmdname = cbp->cb_type == OP_SHARE ? "share" : "mount"; 1966 struct mnttab mnt; 1967 uint64_t zoned; 1968 1969 if (cbp->cb_options == NULL) 1970 mnt.mnt_mntopts = ""; 1971 else 1972 mnt.mnt_mntopts = (char *)cbp->cb_options; 1973 1974 /* 1975 * Check to make sure we can mount/share this dataset. If we are in the 1976 * global zone and the filesystem is exported to a local zone, or if we 1977 * are in a local zone and the filesystem is not exported, then it is an 1978 * error. 1979 */ 1980 zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); 1981 1982 if (zoned && getzoneid() == GLOBAL_ZONEID) { 1983 if (!cbp->cb_explicit) 1984 return (0); 1985 1986 (void) fprintf(stderr, gettext("cannot %s '%s': dataset is " 1987 "exported to a local zone\n"), cmdname, zfs_get_name(zhp)); 1988 return (1); 1989 1990 } else if (!zoned && getzoneid() != GLOBAL_ZONEID) { 1991 if (!cbp->cb_explicit) 1992 return (0); 1993 1994 (void) fprintf(stderr, gettext("cannot %s '%s': permission " 1995 "denied\n"), cmdname, zfs_get_name(zhp)); 1996 return (1); 1997 } 1998 1999 /* 2000 * Inore any filesystems which don't apply to us. This includes those 2001 * with a legacy mountpoint, or those with legacy share options. 2002 */ 2003 verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, 2004 sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); 2005 verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, 2006 sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); 2007 2008 if (cbp->cb_type == OP_SHARE) { 2009 if (strcmp(shareopts, "off") == 0) { 2010 if (!cbp->cb_explicit) 2011 return (0); 2012 2013 (void) fprintf(stderr, gettext("cannot share '%s': " 2014 "legacy share\n"), zfs_get_name(zhp)); 2015 (void) fprintf(stderr, gettext("use share(1M) to " 2016 "share this filesystem\n")); 2017 return (1); 2018 } 2019 } 2020 2021 /* 2022 * We cannot share or mount legacy filesystems. If the shareopts is 2023 * non-legacy but the mountpoint is legacy, we treat it as a legacy 2024 * share. 2025 */ 2026 if (strcmp(mountpoint, "legacy") == 0) { 2027 if (!cbp->cb_explicit) 2028 return (0); 2029 2030 (void) fprintf(stderr, gettext("cannot %s '%s': " 2031 "legacy mountpoint\n"), cmdname, zfs_get_name(zhp)); 2032 (void) fprintf(stderr, gettext("use %s to " 2033 "%s this filesystem\n"), cbp->cb_type == OP_SHARE ? 2034 "share(1M)" : "mount(1M)", cmdname); 2035 return (1); 2036 } 2037 2038 if (strcmp(mountpoint, "none") == 0) { 2039 if (!cbp->cb_explicit) 2040 return (0); 2041 2042 (void) fprintf(stderr, gettext("cannot %s '%s': no " 2043 "mountpoint set\n"), cmdname, zfs_get_name(zhp)); 2044 return (1); 2045 } 2046 2047 /* 2048 * At this point, we have verified that the mountpoint and/or shareopts 2049 * are appropriate for auto management. Determine if the filesystem is 2050 * currently mounted or shared, and abort if this is an explicit 2051 * request. 2052 */ 2053 switch (cbp->cb_type) { 2054 case OP_SHARE: 2055 if (zfs_is_shared(zhp, NULL)) { 2056 if (cbp->cb_explicit) { 2057 (void) fprintf(stderr, gettext("cannot share " 2058 "'%s': filesystem already shared\n"), 2059 zfs_get_name(zhp)); 2060 return (1); 2061 } else { 2062 return (0); 2063 } 2064 } 2065 break; 2066 2067 case OP_MOUNT: 2068 if (!hasmntopt(&mnt, MNTOPT_REMOUNT) && 2069 zfs_is_mounted(zhp, NULL)) { 2070 if (cbp->cb_explicit) { 2071 (void) fprintf(stderr, gettext("cannot mount " 2072 "'%s': filesystem already mounted\n"), 2073 zfs_get_name(zhp)); 2074 return (1); 2075 } else { 2076 return (0); 2077 } 2078 } 2079 break; 2080 } 2081 2082 /* 2083 * Mount and optionally share the filesystem. 2084 */ 2085 switch (cbp->cb_type) { 2086 case OP_SHARE: 2087 { 2088 if (!zfs_is_mounted(zhp, NULL) && 2089 zfs_mount(zhp, NULL, 0) != 0) 2090 return (1); 2091 2092 if (zfs_share(zhp) != 0) 2093 return (1); 2094 } 2095 break; 2096 2097 case OP_MOUNT: 2098 if (zfs_mount(zhp, cbp->cb_options, cbp->cb_flags) != 0) 2099 return (1); 2100 break; 2101 } 2102 2103 return (0); 2104 } 2105 2106 static int 2107 share_or_mount(int type, int argc, char **argv) 2108 { 2109 int do_all = 0; 2110 int c, ret; 2111 share_mount_cbdata_t cb = { 0 }; 2112 2113 cb.cb_type = type; 2114 2115 /* check options */ 2116 while ((c = getopt(argc, argv, type == OP_MOUNT ? ":ao:O" : "a")) 2117 != -1) { 2118 switch (c) { 2119 case 'a': 2120 do_all = 1; 2121 break; 2122 case 'o': 2123 cb.cb_options = optarg; 2124 break; 2125 case 'O': 2126 cb.cb_flags |= MS_OVERLAY; 2127 break; 2128 case ':': 2129 (void) fprintf(stderr, gettext("missing argument for " 2130 "'%c' option\n"), optopt); 2131 usage(B_FALSE); 2132 break; 2133 case '?': 2134 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2135 optopt); 2136 usage(B_FALSE); 2137 } 2138 } 2139 2140 argc -= optind; 2141 argv += optind; 2142 2143 /* check number of arguments */ 2144 if (do_all) { 2145 zfs_handle_t **fslist = NULL; 2146 size_t i, count = 0; 2147 2148 if (argc != 0) { 2149 (void) fprintf(stderr, gettext("too many arguments\n")); 2150 usage(B_FALSE); 2151 } 2152 2153 get_all_filesystems(&fslist, &count); 2154 2155 if (count == 0) 2156 return (0); 2157 2158 qsort(fslist, count, sizeof (void *), mountpoint_compare); 2159 2160 for (i = 0; i < count; i++) { 2161 if ((ret = share_mount_callback(fslist[i], &cb)) != 0) 2162 break; 2163 } 2164 2165 for (i = 0; i < count; i++) 2166 zfs_close(fslist[i]); 2167 2168 free(fslist); 2169 } else if (argc == 0) { 2170 struct mnttab entry; 2171 2172 if (type == OP_SHARE) { 2173 (void) fprintf(stderr, gettext("missing filesystem " 2174 "argument\n")); 2175 usage(B_FALSE); 2176 } 2177 2178 /* 2179 * When mount is given no arguments, go through /etc/mnttab and 2180 * display any active ZFS mounts. We hide any snapshots, since 2181 * they are controlled automatically. 2182 */ 2183 rewind(mnttab_file); 2184 while (getmntent(mnttab_file, &entry) == 0) { 2185 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0 || 2186 strchr(entry.mnt_special, '@') != NULL) 2187 continue; 2188 2189 (void) printf("%-30s %s\n", entry.mnt_special, 2190 entry.mnt_mountp); 2191 } 2192 2193 ret = 0; 2194 } else { 2195 zfs_handle_t *zhp; 2196 2197 if (argc > 1) { 2198 (void) fprintf(stderr, 2199 gettext("too many arguments\n")); 2200 usage(B_FALSE); 2201 } 2202 2203 if ((zhp = zfs_open(g_zfs, argv[0], 2204 ZFS_TYPE_FILESYSTEM)) == NULL) 2205 ret = 1; 2206 else { 2207 cb.cb_explicit = B_TRUE; 2208 ret = share_mount_callback(zhp, &cb); 2209 zfs_close(zhp); 2210 } 2211 } 2212 2213 return (ret); 2214 } 2215 2216 /* 2217 * zfs mount -a 2218 * zfs mount filesystem 2219 * 2220 * Mount all filesystems, or mount the given filesystem. 2221 */ 2222 static int 2223 zfs_do_mount(int argc, char **argv) 2224 { 2225 return (share_or_mount(OP_MOUNT, argc, argv)); 2226 } 2227 2228 /* 2229 * zfs share -a 2230 * zfs share filesystem 2231 * 2232 * Share all filesystems, or share the given filesystem. 2233 */ 2234 static int 2235 zfs_do_share(int argc, char **argv) 2236 { 2237 return (share_or_mount(OP_SHARE, argc, argv)); 2238 } 2239 2240 typedef struct unshare_unmount_node { 2241 zfs_handle_t *un_zhp; 2242 char *un_mountp; 2243 uu_avl_node_t un_avlnode; 2244 } unshare_unmount_node_t; 2245 2246 /* ARGSUSED */ 2247 static int 2248 unshare_unmount_compare(const void *larg, const void *rarg, void *unused) 2249 { 2250 const unshare_unmount_node_t *l = larg; 2251 const unshare_unmount_node_t *r = rarg; 2252 2253 return (strcmp(l->un_mountp, r->un_mountp)); 2254 } 2255 2256 /* 2257 * Convenience routine used by zfs_do_umount() and manual_unmount(). Given an 2258 * absolute path, find the entry /etc/mnttab, verify that its a ZFS filesystem, 2259 * and unmount it appropriately. 2260 */ 2261 static int 2262 unshare_unmount_path(int type, char *path, int flags, boolean_t is_manual) 2263 { 2264 zfs_handle_t *zhp; 2265 int ret; 2266 struct stat64 statbuf; 2267 struct extmnttab entry; 2268 const char *cmdname = (type == OP_SHARE) ? "unshare" : "unmount"; 2269 char property[ZFS_MAXPROPLEN]; 2270 2271 /* 2272 * Search for the path in /etc/mnttab. Rather than looking for the 2273 * specific path, which can be fooled by non-standard paths (i.e. ".." 2274 * or "//"), we stat() the path and search for the corresponding 2275 * (major,minor) device pair. 2276 */ 2277 if (stat64(path, &statbuf) != 0) { 2278 (void) fprintf(stderr, gettext("cannot %s '%s': %s\n"), 2279 cmdname, path, strerror(errno)); 2280 return (1); 2281 } 2282 2283 /* 2284 * Search for the given (major,minor) pair in the mount table. 2285 */ 2286 rewind(mnttab_file); 2287 while ((ret = getextmntent(mnttab_file, &entry, 0)) == 0) { 2288 if (entry.mnt_major == major(statbuf.st_dev) && 2289 entry.mnt_minor == minor(statbuf.st_dev)) 2290 break; 2291 } 2292 if (ret != 0) { 2293 (void) fprintf(stderr, gettext("cannot %s '%s': not " 2294 "currently mounted\n"), cmdname, path); 2295 return (1); 2296 } 2297 2298 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) { 2299 (void) fprintf(stderr, gettext("cannot %s '%s': not a ZFS " 2300 "filesystem\n"), cmdname, path); 2301 return (1); 2302 } 2303 2304 if ((zhp = zfs_open(g_zfs, entry.mnt_special, 2305 ZFS_TYPE_FILESYSTEM)) == NULL) 2306 return (1); 2307 2308 verify(zfs_prop_get(zhp, type == OP_SHARE ? 2309 ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, 2310 sizeof (property), NULL, NULL, 0, B_FALSE) == 0); 2311 2312 if (type == OP_SHARE) { 2313 if (strcmp(property, "off") == 0) { 2314 (void) fprintf(stderr, gettext("cannot unshare " 2315 "'%s': legacy share\n"), path); 2316 (void) fprintf(stderr, gettext("use " 2317 "unshare(1M) to unshare this filesystem\n")); 2318 ret = 1; 2319 } else if (!zfs_is_shared(zhp, NULL)) { 2320 (void) fprintf(stderr, gettext("cannot unshare '%s': " 2321 "not currently shared\n"), path); 2322 ret = 1; 2323 } else { 2324 ret = zfs_unshareall(zhp); 2325 } 2326 } else { 2327 if (is_manual) { 2328 ret = zfs_unmount(zhp, NULL, flags); 2329 } else if (strcmp(property, "legacy") == 0) { 2330 (void) fprintf(stderr, gettext("cannot unmount " 2331 "'%s': legacy mountpoint\n"), 2332 zfs_get_name(zhp)); 2333 (void) fprintf(stderr, gettext("use umount(1M) " 2334 "to unmount this filesystem\n")); 2335 ret = 1; 2336 } else { 2337 ret = zfs_unmountall(zhp, flags); 2338 } 2339 } 2340 2341 zfs_close(zhp); 2342 2343 return (ret != 0); 2344 } 2345 2346 /* 2347 * Generic callback for unsharing or unmounting a filesystem. 2348 */ 2349 static int 2350 unshare_unmount(int type, int argc, char **argv) 2351 { 2352 int do_all = 0; 2353 int flags = 0; 2354 int ret = 0; 2355 int c; 2356 zfs_handle_t *zhp; 2357 char property[ZFS_MAXPROPLEN]; 2358 2359 /* check options */ 2360 while ((c = getopt(argc, argv, type == OP_SHARE ? "a" : "af")) != -1) { 2361 switch (c) { 2362 case 'a': 2363 do_all = 1; 2364 break; 2365 case 'f': 2366 flags = MS_FORCE; 2367 break; 2368 case '?': 2369 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2370 optopt); 2371 usage(B_FALSE); 2372 } 2373 } 2374 2375 argc -= optind; 2376 argv += optind; 2377 2378 /* ensure correct number of arguments */ 2379 if (do_all) { 2380 if (argc != 0) { 2381 (void) fprintf(stderr, gettext("too many arguments\n")); 2382 usage(B_FALSE); 2383 } 2384 } else if (argc != 1) { 2385 if (argc == 0) 2386 (void) fprintf(stderr, 2387 gettext("missing filesystem argument\n")); 2388 else 2389 (void) fprintf(stderr, 2390 gettext("too many arguments\n")); 2391 usage(B_FALSE); 2392 } 2393 2394 if (do_all) { 2395 /* 2396 * We could make use of zfs_for_each() to walk all datasets in 2397 * the system, but this would be very inefficient, especially 2398 * since we would have to linearly search /etc/mnttab for each 2399 * one. Instead, do one pass through /etc/mnttab looking for 2400 * zfs entries and call zfs_unmount() for each one. 2401 * 2402 * Things get a little tricky if the administrator has created 2403 * mountpoints beneath other ZFS filesystems. In this case, we 2404 * have to unmount the deepest filesystems first. To accomplish 2405 * this, we place all the mountpoints in an AVL tree sorted by 2406 * the special type (dataset name), and walk the result in 2407 * reverse to make sure to get any snapshots first. 2408 */ 2409 struct mnttab entry; 2410 uu_avl_pool_t *pool; 2411 uu_avl_t *tree; 2412 unshare_unmount_node_t *node; 2413 uu_avl_index_t idx; 2414 uu_avl_walk_t *walk; 2415 2416 if ((pool = uu_avl_pool_create("unmount_pool", 2417 sizeof (unshare_unmount_node_t), 2418 offsetof(unshare_unmount_node_t, un_avlnode), 2419 unshare_unmount_compare, 2420 UU_DEFAULT)) == NULL) { 2421 (void) fprintf(stderr, gettext("internal error: " 2422 "out of memory\n")); 2423 exit(1); 2424 } 2425 2426 if ((tree = uu_avl_create(pool, NULL, UU_DEFAULT)) == NULL) { 2427 (void) fprintf(stderr, gettext("internal error: " 2428 "out of memory\n")); 2429 exit(1); 2430 } 2431 2432 rewind(mnttab_file); 2433 while (getmntent(mnttab_file, &entry) == 0) { 2434 2435 /* ignore non-ZFS entries */ 2436 if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) 2437 continue; 2438 2439 /* ignore snapshots */ 2440 if (strchr(entry.mnt_special, '@') != NULL) 2441 continue; 2442 2443 if ((zhp = zfs_open(g_zfs, entry.mnt_special, 2444 ZFS_TYPE_FILESYSTEM)) == NULL) { 2445 ret = 1; 2446 continue; 2447 } 2448 2449 verify(zfs_prop_get(zhp, type == OP_SHARE ? 2450 ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, 2451 property, sizeof (property), NULL, NULL, 2452 0, B_FALSE) == 0); 2453 2454 /* Ignore legacy mounts and shares */ 2455 if ((type == OP_SHARE && 2456 strcmp(property, "off") == 0) || 2457 (type == OP_MOUNT && 2458 strcmp(property, "legacy") == 0)) { 2459 zfs_close(zhp); 2460 continue; 2461 } 2462 2463 node = safe_malloc(sizeof (unshare_unmount_node_t)); 2464 node->un_zhp = zhp; 2465 2466 if ((node->un_mountp = strdup(entry.mnt_mountp)) == 2467 NULL) { 2468 (void) fprintf(stderr, gettext("internal error:" 2469 " out of memory\n")); 2470 exit(1); 2471 } 2472 2473 uu_avl_node_init(node, &node->un_avlnode, pool); 2474 2475 if (uu_avl_find(tree, node, NULL, &idx) == NULL) { 2476 uu_avl_insert(tree, node, idx); 2477 } else { 2478 zfs_close(node->un_zhp); 2479 free(node->un_mountp); 2480 free(node); 2481 } 2482 } 2483 2484 /* 2485 * Walk the AVL tree in reverse, unmounting each filesystem and 2486 * removing it from the AVL tree in the process. 2487 */ 2488 if ((walk = uu_avl_walk_start(tree, 2489 UU_WALK_REVERSE | UU_WALK_ROBUST)) == NULL) { 2490 (void) fprintf(stderr, 2491 gettext("internal error: out of memory")); 2492 exit(1); 2493 } 2494 2495 while ((node = uu_avl_walk_next(walk)) != NULL) { 2496 uu_avl_remove(tree, node); 2497 2498 switch (type) { 2499 case OP_SHARE: 2500 if (zfs_unshare(node->un_zhp, 2501 node->un_mountp) != 0) 2502 ret = 1; 2503 break; 2504 2505 case OP_MOUNT: 2506 if (zfs_unmount(node->un_zhp, 2507 node->un_mountp, flags) != 0) 2508 ret = 1; 2509 break; 2510 } 2511 2512 zfs_close(node->un_zhp); 2513 free(node->un_mountp); 2514 free(node); 2515 } 2516 2517 uu_avl_walk_end(walk); 2518 uu_avl_destroy(tree); 2519 uu_avl_pool_destroy(pool); 2520 } else { 2521 /* 2522 * We have an argument, but it may be a full path or a ZFS 2523 * filesystem. Pass full paths off to unmount_path() (shared by 2524 * manual_unmount), otherwise open the filesystem and pass to 2525 * zfs_unmount(). 2526 */ 2527 if (argv[0][0] == '/') 2528 return (unshare_unmount_path(type, argv[0], 2529 flags, B_FALSE)); 2530 2531 if ((zhp = zfs_open(g_zfs, argv[0], 2532 ZFS_TYPE_FILESYSTEM)) == NULL) 2533 return (1); 2534 2535 verify(zfs_prop_get(zhp, type == OP_SHARE ? 2536 ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, property, 2537 sizeof (property), NULL, NULL, 0, B_FALSE) == 0); 2538 2539 switch (type) { 2540 case OP_SHARE: 2541 if (strcmp(property, "off") == 0) { 2542 (void) fprintf(stderr, gettext("cannot unshare " 2543 "'%s': legacy share\n"), zfs_get_name(zhp)); 2544 (void) fprintf(stderr, gettext("use unshare(1M)" 2545 " to unshare this filesystem\n")); 2546 ret = 1; 2547 } else if (!zfs_is_shared(zhp, NULL)) { 2548 (void) fprintf(stderr, gettext("cannot unshare " 2549 "'%s': not currently shared\n"), 2550 zfs_get_name(zhp)); 2551 ret = 1; 2552 } else if (zfs_unshareall(zhp) != 0) { 2553 ret = 1; 2554 } 2555 break; 2556 2557 case OP_MOUNT: 2558 if (strcmp(property, "legacy") == 0) { 2559 (void) fprintf(stderr, gettext("cannot unmount " 2560 "'%s': legacy mountpoint\n"), 2561 zfs_get_name(zhp)); 2562 (void) fprintf(stderr, gettext("use umount(1M) " 2563 "to unmount this filesystem\n")); 2564 ret = 1; 2565 } else if (!zfs_is_mounted(zhp, NULL)) { 2566 (void) fprintf(stderr, gettext("cannot unmount " 2567 "'%s': not currently mounted\n"), 2568 zfs_get_name(zhp)); 2569 ret = 1; 2570 } else if (zfs_unmountall(zhp, flags) != 0) { 2571 ret = 1; 2572 } 2573 } 2574 2575 zfs_close(zhp); 2576 } 2577 2578 return (ret); 2579 } 2580 2581 /* 2582 * zfs unmount -a 2583 * zfs unmount filesystem 2584 * 2585 * Unmount all filesystems, or a specific ZFS filesystem. 2586 */ 2587 static int 2588 zfs_do_unmount(int argc, char **argv) 2589 { 2590 return (unshare_unmount(OP_MOUNT, argc, argv)); 2591 } 2592 2593 /* 2594 * zfs unshare -a 2595 * zfs unshare filesystem 2596 * 2597 * Unshare all filesystems, or a specific ZFS filesystem. 2598 */ 2599 static int 2600 zfs_do_unshare(int argc, char **argv) 2601 { 2602 return (unshare_unmount(OP_SHARE, argc, argv)); 2603 } 2604 2605 /* 2606 * Called when invoked as /etc/fs/zfs/mount. Do the mount if the mountpoint is 2607 * 'legacy'. Otherwise, complain that use should be using 'zfs mount'. 2608 */ 2609 static int 2610 manual_mount(int argc, char **argv) 2611 { 2612 zfs_handle_t *zhp; 2613 char mountpoint[ZFS_MAXPROPLEN]; 2614 char mntopts[MNT_LINE_MAX] = { '\0' }; 2615 int ret; 2616 int c; 2617 int flags = 0; 2618 char *dataset, *path; 2619 2620 /* check options */ 2621 while ((c = getopt(argc, argv, ":mo:O")) != -1) { 2622 switch (c) { 2623 case 'o': 2624 (void) strlcpy(mntopts, optarg, sizeof (mntopts)); 2625 break; 2626 case 'O': 2627 flags |= MS_OVERLAY; 2628 break; 2629 case 'm': 2630 flags |= MS_NOMNTTAB; 2631 break; 2632 case ':': 2633 (void) fprintf(stderr, gettext("missing argument for " 2634 "'%c' option\n"), optopt); 2635 usage(B_FALSE); 2636 break; 2637 case '?': 2638 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2639 optopt); 2640 (void) fprintf(stderr, gettext("usage: mount [-o opts] " 2641 "<path>\n")); 2642 return (2); 2643 } 2644 } 2645 2646 argc -= optind; 2647 argv += optind; 2648 2649 /* check that we only have two arguments */ 2650 if (argc != 2) { 2651 if (argc == 0) 2652 (void) fprintf(stderr, gettext("missing dataset " 2653 "argument\n")); 2654 else if (argc == 1) 2655 (void) fprintf(stderr, 2656 gettext("missing mountpoint argument\n")); 2657 else 2658 (void) fprintf(stderr, gettext("too many arguments\n")); 2659 (void) fprintf(stderr, "usage: mount <dataset> <mountpoint>\n"); 2660 return (2); 2661 } 2662 2663 dataset = argv[0]; 2664 path = argv[1]; 2665 2666 /* try to open the dataset */ 2667 if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_FILESYSTEM)) == NULL) 2668 return (1); 2669 2670 (void) zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, 2671 sizeof (mountpoint), NULL, NULL, 0, B_FALSE); 2672 2673 /* check for legacy mountpoint and complain appropriately */ 2674 ret = 0; 2675 if (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) == 0) { 2676 if (mount(dataset, path, MS_OPTIONSTR | flags, MNTTYPE_ZFS, 2677 NULL, 0, mntopts, sizeof (mntopts)) != 0) { 2678 (void) fprintf(stderr, gettext("mount failed: %s\n"), 2679 strerror(errno)); 2680 ret = 1; 2681 } 2682 } else { 2683 (void) fprintf(stderr, gettext("filesystem '%s' cannot be " 2684 "mounted using 'mount -F zfs'\n"), dataset); 2685 (void) fprintf(stderr, gettext("Use 'zfs set mountpoint=%s' " 2686 "instead.\n"), path); 2687 (void) fprintf(stderr, gettext("If you must use 'mount -F zfs' " 2688 "or /etc/vfstab, use 'zfs set mountpoint=legacy'.\n")); 2689 (void) fprintf(stderr, gettext("See zfs(1M) for more " 2690 "information.\n")); 2691 ret = 1; 2692 } 2693 2694 return (ret); 2695 } 2696 2697 /* 2698 * Called when invoked as /etc/fs/zfs/umount. Unlike a manual mount, we allow 2699 * unmounts of non-legacy filesystems, as this is the dominant administrative 2700 * interface. 2701 */ 2702 static int 2703 manual_unmount(int argc, char **argv) 2704 { 2705 int flags = 0; 2706 int c; 2707 2708 /* check options */ 2709 while ((c = getopt(argc, argv, "f")) != -1) { 2710 switch (c) { 2711 case 'f': 2712 flags = MS_FORCE; 2713 break; 2714 case '?': 2715 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 2716 optopt); 2717 (void) fprintf(stderr, gettext("usage: unmount [-f] " 2718 "<path>\n")); 2719 return (2); 2720 } 2721 } 2722 2723 argc -= optind; 2724 argv += optind; 2725 2726 /* check arguments */ 2727 if (argc != 1) { 2728 if (argc == 0) 2729 (void) fprintf(stderr, gettext("missing path " 2730 "argument\n")); 2731 else 2732 (void) fprintf(stderr, gettext("too many arguments\n")); 2733 (void) fprintf(stderr, gettext("usage: unmount [-f] <path>\n")); 2734 return (2); 2735 } 2736 2737 return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE)); 2738 } 2739 2740 static int 2741 volcheck(zpool_handle_t *zhp, void *data) 2742 { 2743 int isinit = (int)data; 2744 2745 if (isinit) 2746 return (zpool_create_zvol_links(zhp)); 2747 else 2748 return (zpool_remove_zvol_links(zhp)); 2749 } 2750 2751 /* 2752 * Iterate over all pools in the system and either create or destroy /dev/zvol 2753 * links, depending on the value of 'isinit'. 2754 */ 2755 static int 2756 do_volcheck(boolean_t isinit) 2757 { 2758 return (zpool_iter(g_zfs, volcheck, (void *)isinit) ? 1 : 0); 2759 } 2760 2761 int 2762 main(int argc, char **argv) 2763 { 2764 int ret; 2765 int i; 2766 char *progname; 2767 char *cmdname; 2768 2769 (void) setlocale(LC_ALL, ""); 2770 (void) textdomain(TEXT_DOMAIN); 2771 2772 opterr = 0; 2773 2774 if ((g_zfs = libzfs_init()) == NULL) { 2775 (void) fprintf(stderr, gettext("internal error: failed to " 2776 "initialize ZFS library\n")); 2777 return (1); 2778 } 2779 2780 libzfs_print_on_error(g_zfs, B_TRUE); 2781 2782 if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) { 2783 (void) fprintf(stderr, gettext("internal error: unable to " 2784 "open %s\n"), MNTTAB); 2785 return (1); 2786 } 2787 2788 /* 2789 * This command also doubles as the /etc/fs mount and unmount program. 2790 * Determine if we should take this behavior based on argv[0]. 2791 */ 2792 progname = basename(argv[0]); 2793 if (strcmp(progname, "mount") == 0) { 2794 ret = manual_mount(argc, argv); 2795 } else if (strcmp(progname, "umount") == 0) { 2796 ret = manual_unmount(argc, argv); 2797 } else { 2798 /* 2799 * Make sure the user has specified some command. 2800 */ 2801 if (argc < 2) { 2802 (void) fprintf(stderr, gettext("missing command\n")); 2803 usage(B_FALSE); 2804 } 2805 2806 cmdname = argv[1]; 2807 2808 /* 2809 * The 'umount' command is an alias for 'unmount' 2810 */ 2811 if (strcmp(cmdname, "umount") == 0) 2812 cmdname = "unmount"; 2813 2814 /* 2815 * The 'recv' command is an alias for 'receive' 2816 */ 2817 if (strcmp(cmdname, "recv") == 0) 2818 cmdname = "receive"; 2819 2820 /* 2821 * Special case '-?' 2822 */ 2823 if (strcmp(cmdname, "-?") == 0) 2824 usage(B_TRUE); 2825 2826 /* 2827 * 'volinit' and 'volfini' do not appear in the usage message, 2828 * so we have to special case them here. 2829 */ 2830 if (strcmp(cmdname, "volinit") == 0) 2831 return (do_volcheck(B_TRUE)); 2832 else if (strcmp(cmdname, "volfini") == 0) 2833 return (do_volcheck(B_FALSE)); 2834 2835 /* 2836 * Run the appropriate command. 2837 */ 2838 for (i = 0; i < NCOMMAND; i++) { 2839 if (command_table[i].name == NULL) 2840 continue; 2841 2842 if (strcmp(cmdname, command_table[i].name) == 0) { 2843 current_command = &command_table[i]; 2844 ret = command_table[i].func(argc - 1, argv + 1); 2845 break; 2846 } 2847 } 2848 2849 if (i == NCOMMAND) { 2850 (void) fprintf(stderr, gettext("unrecognized " 2851 "command '%s'\n"), cmdname); 2852 usage(B_FALSE); 2853 } 2854 } 2855 2856 (void) fclose(mnttab_file); 2857 2858 libzfs_fini(g_zfs); 2859 2860 /* 2861 * The 'ZFS_ABORT' environment variable causes us to dump core on exit 2862 * for the purposes of running ::findleaks. 2863 */ 2864 if (getenv("ZFS_ABORT") != NULL) { 2865 (void) printf("dumping core by request\n"); 2866 abort(); 2867 } 2868 2869 return (ret); 2870 } 2871