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