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