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 2008 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 <sys/mkdev.h> 43 #include <sys/mntent.h> 44 #include <sys/mnttab.h> 45 #include <sys/mount.h> 46 #include <sys/stat.h> 47 #include <sys/avl.h> 48 49 #include <libzfs.h> 50 #include <libuutil.h> 51 52 #include "zfs_iter.h" 53 #include "zfs_util.h" 54 55 libzfs_handle_t *g_zfs; 56 57 static FILE *mnttab_file; 58 static char history_str[HIS_MAX_RECORD_LEN]; 59 60 static int zfs_do_clone(int argc, char **argv); 61 static int zfs_do_create(int argc, char **argv); 62 static int zfs_do_destroy(int argc, char **argv); 63 static int zfs_do_get(int argc, char **argv); 64 static int zfs_do_inherit(int argc, char **argv); 65 static int zfs_do_list(int argc, char **argv); 66 static int zfs_do_mount(int argc, char **argv); 67 static int zfs_do_rename(int argc, char **argv); 68 static int zfs_do_rollback(int argc, char **argv); 69 static int zfs_do_set(int argc, char **argv); 70 static int zfs_do_upgrade(int argc, char **argv); 71 static int zfs_do_snapshot(int argc, char **argv); 72 static int zfs_do_unmount(int argc, char **argv); 73 static int zfs_do_share(int argc, char **argv); 74 static int zfs_do_unshare(int argc, char **argv); 75 static int zfs_do_send(int argc, char **argv); 76 static int zfs_do_receive(int argc, char **argv); 77 static int zfs_do_promote(int argc, char **argv); 78 static int zfs_do_allow(int argc, char **argv); 79 static int zfs_do_unallow(int argc, char **argv); 80 81 /* 82 * Enable a reasonable set of defaults for libumem debugging on DEBUG builds. 83 */ 84 85 #ifdef DEBUG 86 const char * 87 _umem_debug_init(void) 88 { 89 return ("default,verbose"); /* $UMEM_DEBUG setting */ 90 } 91 92 const char * 93 _umem_logging_init(void) 94 { 95 return ("fail,contents"); /* $UMEM_LOGGING setting */ 96 } 97 #endif 98 99 typedef enum { 100 HELP_CLONE, 101 HELP_CREATE, 102 HELP_DESTROY, 103 HELP_GET, 104 HELP_INHERIT, 105 HELP_UPGRADE, 106 HELP_LIST, 107 HELP_MOUNT, 108 HELP_PROMOTE, 109 HELP_RECEIVE, 110 HELP_RENAME, 111 HELP_ROLLBACK, 112 HELP_SEND, 113 HELP_SET, 114 HELP_SHARE, 115 HELP_SNAPSHOT, 116 HELP_UNMOUNT, 117 HELP_UNSHARE, 118 HELP_ALLOW, 119 HELP_UNALLOW 120 } zfs_help_t; 121 122 typedef struct zfs_command { 123 const char *name; 124 int (*func)(int argc, char **argv); 125 zfs_help_t usage; 126 } zfs_command_t; 127 128 /* 129 * Master command table. Each ZFS command has a name, associated function, and 130 * usage message. The usage messages need to be internationalized, so we have 131 * to have a function to return the usage message based on a command index. 132 * 133 * These commands are organized according to how they are displayed in the usage 134 * message. An empty command (one with a NULL name) indicates an empty line in 135 * the generic usage message. 136 */ 137 static zfs_command_t command_table[] = { 138 { "create", zfs_do_create, HELP_CREATE }, 139 { "destroy", zfs_do_destroy, HELP_DESTROY }, 140 { NULL }, 141 { "snapshot", zfs_do_snapshot, HELP_SNAPSHOT }, 142 { "rollback", zfs_do_rollback, HELP_ROLLBACK }, 143 { "clone", zfs_do_clone, HELP_CLONE }, 144 { "promote", zfs_do_promote, HELP_PROMOTE }, 145 { "rename", zfs_do_rename, HELP_RENAME }, 146 { NULL }, 147 { "list", zfs_do_list, HELP_LIST }, 148 { NULL }, 149 { "set", zfs_do_set, HELP_SET }, 150 { "get", zfs_do_get, HELP_GET }, 151 { "inherit", zfs_do_inherit, HELP_INHERIT }, 152 { "upgrade", zfs_do_upgrade, HELP_UPGRADE }, 153 { NULL }, 154 { "mount", zfs_do_mount, HELP_MOUNT }, 155 { "unmount", zfs_do_unmount, HELP_UNMOUNT }, 156 { "share", zfs_do_share, HELP_SHARE }, 157 { "unshare", zfs_do_unshare, HELP_UNSHARE }, 158 { NULL }, 159 { "send", zfs_do_send, HELP_SEND }, 160 { "receive", zfs_do_receive, HELP_RECEIVE }, 161 { NULL }, 162 { "allow", zfs_do_allow, HELP_ALLOW }, 163 { NULL }, 164 { "unallow", zfs_do_unallow, HELP_UNALLOW }, 165 }; 166 167 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) 168 169 zfs_command_t *current_command; 170 171 static const char * 172 get_usage(zfs_help_t idx) 173 { 174 switch (idx) { 175 case HELP_CLONE: 176 return (gettext("\tclone [-p] [-o property=value] ... " 177 "<snapshot> <filesystem|volume>\n")); 178 case HELP_CREATE: 179 return (gettext("\tcreate [-p] [-o property=value] ... " 180 "<filesystem>\n" 181 "\tcreate [-ps] [-b blocksize] [-o property=value] ... " 182 "-V <size> <volume>\n")); 183 case HELP_DESTROY: 184 return (gettext("\tdestroy [-rRf] " 185 "<filesystem|volume|snapshot>\n")); 186 case HELP_GET: 187 return (gettext("\tget [-rHp] [-o field[,...]] " 188 "[-s source[,...]]\n" 189 "\t <\"all\" | property[,...]> " 190 "[filesystem|volume|snapshot] ...\n")); 191 case HELP_INHERIT: 192 return (gettext("\tinherit [-r] <property> " 193 "<filesystem|volume|snapshot> ...\n")); 194 case HELP_UPGRADE: 195 return (gettext("\tupgrade [-v]\n" 196 "\tupgrade [-r] [-V version] <-a | filesystem ...>\n")); 197 case HELP_LIST: 198 return (gettext("\tlist [-rH] [-o property[,...]] " 199 "[-t type[,...]] [-s property] ...\n" 200 "\t [-S property] ... " 201 "[filesystem|volume|snapshot] ...\n")); 202 case HELP_MOUNT: 203 return (gettext("\tmount\n" 204 "\tmount [-vO] [-o opts] <-a | filesystem>\n")); 205 case HELP_PROMOTE: 206 return (gettext("\tpromote <clone-filesystem>\n")); 207 case HELP_RECEIVE: 208 return (gettext("\treceive [-vnF] <filesystem|volume|" 209 "snapshot>\n" 210 "\treceive [-vnF] -d <filesystem>\n")); 211 case HELP_RENAME: 212 return (gettext("\trename <filesystem|volume|snapshot> " 213 "<filesystem|volume|snapshot>\n" 214 "\trename -p <filesystem|volume> <filesystem|volume>\n" 215 "\trename -r <snapshot> <snapshot>")); 216 case HELP_ROLLBACK: 217 return (gettext("\trollback [-rRf] <snapshot>\n")); 218 case HELP_SEND: 219 return (gettext("\tsend [-R] [-[iI] snapshot] <snapshot>\n")); 220 case HELP_SET: 221 return (gettext("\tset <property=value> " 222 "<filesystem|volume|snapshot> ...\n")); 223 case HELP_SHARE: 224 return (gettext("\tshare <-a | filesystem>\n")); 225 case HELP_SNAPSHOT: 226 return (gettext("\tsnapshot [-r] [-o property=value] ... " 227 "<filesystem@snapname|volume@snapname>\n")); 228 case HELP_UNMOUNT: 229 return (gettext("\tunmount [-f] " 230 "<-a | filesystem|mountpoint>\n")); 231 case HELP_UNSHARE: 232 return (gettext("\tunshare [-f] " 233 "<-a | filesystem|mountpoint>\n")); 234 case HELP_ALLOW: 235 return (gettext("\tallow [-ldug] " 236 "<\"everyone\"|user|group>[,...] <perm|@setname>[,...]\n" 237 "\t <filesystem|volume>\n" 238 "\tallow [-ld] -e <perm|@setname>[,...] " 239 "<filesystem|volume>\n" 240 "\tallow -c <perm|@setname>[,...] <filesystem|volume>\n" 241 "\tallow -s @setname <perm|@setname>[,...] " 242 "<filesystem|volume>\n")); 243 case HELP_UNALLOW: 244 return (gettext("\tunallow [-rldug] " 245 "<\"everyone\"|user|group>[,...]\n" 246 "\t [<perm|@setname>[,...]] <filesystem|volume>\n" 247 "\tunallow [-rld] -e [<perm|@setname>[,...]] " 248 "<filesystem|volume>\n" 249 "\tunallow [-r] -c [<perm|@setname>[,...]] " 250 "<filesystem|volume>\n" 251 "\tunallow [-r] -s @setname [<perm|@setname>[,...]] " 252 "<filesystem|volume>\n")); 253 } 254 255 abort(); 256 /* NOTREACHED */ 257 } 258 259 /* 260 * Utility function to guarantee malloc() success. 261 */ 262 void * 263 safe_malloc(size_t size) 264 { 265 void *data; 266 267 if ((data = calloc(1, size)) == NULL) { 268 (void) fprintf(stderr, "internal error: out of memory\n"); 269 exit(1); 270 } 271 272 return (data); 273 } 274 275 /* 276 * Callback routine that will print out information for each of 277 * the properties. 278 */ 279 static int 280 usage_prop_cb(int prop, void *cb) 281 { 282 FILE *fp = cb; 283 284 (void) fprintf(fp, "\t%-15s ", zfs_prop_to_name(prop)); 285 286 if (zfs_prop_readonly(prop)) 287 (void) fprintf(fp, " NO "); 288 else 289 (void) fprintf(fp, "YES "); 290 291 if (zfs_prop_inheritable(prop)) 292 (void) fprintf(fp, " YES "); 293 else 294 (void) fprintf(fp, " NO "); 295 296 if (zfs_prop_values(prop) == NULL) 297 (void) fprintf(fp, "-\n"); 298 else 299 (void) fprintf(fp, "%s\n", zfs_prop_values(prop)); 300 301 return (ZPROP_CONT); 302 } 303 304 /* 305 * Display usage message. If we're inside a command, display only the usage for 306 * that command. Otherwise, iterate over the entire command table and display 307 * a complete usage message. 308 */ 309 static void 310 usage(boolean_t requested) 311 { 312 int i; 313 boolean_t show_properties = B_FALSE; 314 boolean_t show_permissions = B_FALSE; 315 FILE *fp = requested ? stdout : stderr; 316 317 if (current_command == NULL) { 318 319 (void) fprintf(fp, gettext("usage: zfs command args ...\n")); 320 (void) fprintf(fp, 321 gettext("where 'command' is one of the following:\n\n")); 322 323 for (i = 0; i < NCOMMAND; i++) { 324 if (command_table[i].name == NULL) 325 (void) fprintf(fp, "\n"); 326 else 327 (void) fprintf(fp, "%s", 328 get_usage(command_table[i].usage)); 329 } 330 331 (void) fprintf(fp, gettext("\nEach dataset is of the form: " 332 "pool/[dataset/]*dataset[@name]\n")); 333 } else { 334 (void) fprintf(fp, gettext("usage:\n")); 335 (void) fprintf(fp, "%s", get_usage(current_command->usage)); 336 } 337 338 if (current_command != NULL && 339 (strcmp(current_command->name, "set") == 0 || 340 strcmp(current_command->name, "get") == 0 || 341 strcmp(current_command->name, "inherit") == 0 || 342 strcmp(current_command->name, "list") == 0)) 343 show_properties = B_TRUE; 344 345 if (current_command != NULL && 346 (strcmp(current_command->name, "allow") == 0 || 347 strcmp(current_command->name, "unallow") == 0)) 348 show_permissions = B_TRUE; 349 350 if (show_properties) { 351 352 (void) fprintf(fp, 353 gettext("\nThe following properties are supported:\n")); 354 355 (void) fprintf(fp, "\n\t%-14s %s %s %s\n\n", 356 "PROPERTY", "EDIT", "INHERIT", "VALUES"); 357 358 /* Iterate over all properties */ 359 (void) zprop_iter(usage_prop_cb, fp, B_FALSE, B_TRUE, 360 ZFS_TYPE_DATASET); 361 362 (void) fprintf(fp, gettext("\nSizes are specified in bytes " 363 "with standard units such as K, M, G, etc.\n")); 364 (void) fprintf(fp, gettext("\n\nUser-defined properties can " 365 "be specified by using a name containing a colon (:).\n")); 366 367 } else if (show_permissions) { 368 (void) fprintf(fp, 369 gettext("\nThe following permissions are supported:\n")); 370 371 zfs_deleg_permissions(); 372 } else { 373 /* 374 * TRANSLATION NOTE: 375 * "zfs set|get" must not be localised this is the 376 * command name and arguments. 377 */ 378 379 (void) fprintf(fp, 380 gettext("\nFor the property list, run: zfs set|get\n")); 381 382 (void) fprintf(fp, 383 gettext("\nFor the delegated permission list, run:" 384 " zfs allow|unallow\n")); 385 } 386 387 /* 388 * See comments at end of main(). 389 */ 390 if (getenv("ZFS_ABORT") != NULL) { 391 (void) printf("dumping core by request\n"); 392 abort(); 393 } 394 395 exit(requested ? 0 : 2); 396 } 397 398 static int 399 parseprop(nvlist_t *props) 400 { 401 char *propname = optarg; 402 char *propval, *strval; 403 404 if ((propval = strchr(propname, '=')) == NULL) { 405 (void) fprintf(stderr, gettext("missing " 406 "'=' for -o option\n")); 407 return (-1); 408 } 409 *propval = '\0'; 410 propval++; 411 if (nvlist_lookup_string(props, propname, &strval) == 0) { 412 (void) fprintf(stderr, gettext("property '%s' " 413 "specified multiple times\n"), propname); 414 return (-1); 415 } 416 if (nvlist_add_string(props, propname, propval) != 0) { 417 (void) fprintf(stderr, gettext("internal " 418 "error: out of memory\n")); 419 return (-1); 420 } 421 return (0); 422 423 } 424 425 /* 426 * zfs clone [-p] [-o prop=value] ... <snap> <fs | vol> 427 * 428 * Given an existing dataset, create a writable copy whose initial contents 429 * are the same as the source. The newly created dataset maintains a 430 * dependency on the original; the original cannot be destroyed so long as 431 * the clone exists. 432 * 433 * The '-p' flag creates all the non-existing ancestors of the target first. 434 */ 435 static int 436 zfs_do_clone(int argc, char **argv) 437 { 438 zfs_handle_t *zhp = NULL; 439 boolean_t parents = B_FALSE; 440 nvlist_t *props; 441 int ret; 442 int c; 443 444 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 445 (void) fprintf(stderr, gettext("internal error: " 446 "out of memory\n")); 447 return (1); 448 } 449 450 /* check options */ 451 while ((c = getopt(argc, argv, "o:p")) != -1) { 452 switch (c) { 453 case 'o': 454 if (parseprop(props)) 455 return (1); 456 break; 457 case 'p': 458 parents = B_TRUE; 459 break; 460 case '?': 461 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 462 optopt); 463 goto usage; 464 } 465 } 466 467 argc -= optind; 468 argv += optind; 469 470 /* check number of arguments */ 471 if (argc < 1) { 472 (void) fprintf(stderr, gettext("missing source dataset " 473 "argument\n")); 474 goto usage; 475 } 476 if (argc < 2) { 477 (void) fprintf(stderr, gettext("missing target dataset " 478 "argument\n")); 479 goto usage; 480 } 481 if (argc > 2) { 482 (void) fprintf(stderr, gettext("too many arguments\n")); 483 goto usage; 484 } 485 486 /* open the source dataset */ 487 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_SNAPSHOT)) == NULL) 488 return (1); 489 490 if (parents && zfs_name_valid(argv[1], ZFS_TYPE_FILESYSTEM | 491 ZFS_TYPE_VOLUME)) { 492 /* 493 * Now create the ancestors of the target dataset. If the 494 * target already exists and '-p' option was used we should not 495 * complain. 496 */ 497 if (zfs_dataset_exists(g_zfs, argv[1], ZFS_TYPE_FILESYSTEM | 498 ZFS_TYPE_VOLUME)) 499 return (0); 500 if (zfs_create_ancestors(g_zfs, argv[1]) != 0) 501 return (1); 502 } 503 504 /* pass to libzfs */ 505 ret = zfs_clone(zhp, argv[1], props); 506 507 /* create the mountpoint if necessary */ 508 if (ret == 0) { 509 zfs_handle_t *clone; 510 511 clone = zfs_open(g_zfs, argv[1], ZFS_TYPE_DATASET); 512 if (clone != NULL) { 513 if ((ret = zfs_mount(clone, NULL, 0)) == 0) 514 ret = zfs_share(clone); 515 zfs_close(clone); 516 } 517 } 518 519 zfs_close(zhp); 520 nvlist_free(props); 521 522 return (!!ret); 523 524 usage: 525 if (zhp) 526 zfs_close(zhp); 527 nvlist_free(props); 528 usage(B_FALSE); 529 return (-1); 530 } 531 532 /* 533 * zfs create [-p] [-o prop=value] ... fs 534 * zfs create [-ps] [-b blocksize] [-o prop=value] ... -V vol size 535 * 536 * Create a new dataset. This command can be used to create filesystems 537 * and volumes. Snapshot creation is handled by 'zfs snapshot'. 538 * For volumes, the user must specify a size to be used. 539 * 540 * The '-s' flag applies only to volumes, and indicates that we should not try 541 * to set the reservation for this volume. By default we set a reservation 542 * equal to the size for any volume. For pools with SPA_VERSION >= 543 * SPA_VERSION_REFRESERVATION, we set a refreservation instead. 544 * 545 * The '-p' flag creates all the non-existing ancestors of the target first. 546 */ 547 static int 548 zfs_do_create(int argc, char **argv) 549 { 550 zfs_type_t type = ZFS_TYPE_FILESYSTEM; 551 zfs_handle_t *zhp = NULL; 552 uint64_t volsize; 553 int c; 554 boolean_t noreserve = B_FALSE; 555 boolean_t bflag = B_FALSE; 556 boolean_t parents = B_FALSE; 557 int ret = 1; 558 nvlist_t *props; 559 uint64_t intval; 560 int canmount; 561 562 if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) { 563 (void) fprintf(stderr, gettext("internal error: " 564 "out of memory\n")); 565 return (1); 566 } 567 568 /* check options */ 569 while ((c = getopt(argc, argv, ":V:b:so:p")) != -1) { 570 switch (c) { 571 case 'V': 572 type = ZFS_TYPE_VOLUME; 573 if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { 574 (void) fprintf(stderr, gettext("bad volume " 575 "size '%s': %s\n"), optarg, 576 libzfs_error_description(g_zfs)); 577 goto error; 578 } 579 580 if (nvlist_add_uint64(props, 581 zfs_prop_to_name(ZFS_PROP_VOLSIZE), 582 intval) != 0) { 583 (void) fprintf(stderr, gettext("internal " 584 "error: out of memory\n")); 585 goto error; 586 } 587 volsize = intval; 588 break; 589 case 'p': 590 parents = B_TRUE; 591 break; 592 case 'b': 593 bflag = B_TRUE; 594 if (zfs_nicestrtonum(g_zfs, optarg, &intval) != 0) { 595 (void) fprintf(stderr, gettext("bad volume " 596 "block size '%s': %s\n"), optarg, 597 libzfs_error_description(g_zfs)); 598 goto error; 599 } 600 601 if (nvlist_add_uint64(props, 602 zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE), 603 intval) != 0) { 604 (void) fprintf(stderr, gettext("internal " 605 "error: out of memory\n")); 606 goto error; 607 } 608 break; 609 case 'o': 610 if (parseprop(props)) 611 goto error; 612 break; 613 case 's': 614 noreserve = B_TRUE; 615 break; 616 case ':': 617 (void) fprintf(stderr, gettext("missing size " 618 "argument\n")); 619 goto badusage; 620 break; 621 case '?': 622 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 623 optopt); 624 goto badusage; 625 } 626 } 627 628 if ((bflag || noreserve) && type != ZFS_TYPE_VOLUME) { 629 (void) fprintf(stderr, gettext("'-s' and '-b' can only be " 630 "used when creating a volume\n")); 631 goto badusage; 632 } 633 634 argc -= optind; 635 argv += optind; 636 637 /* check number of arguments */ 638 if (argc == 0) { 639 (void) fprintf(stderr, gettext("missing %s argument\n"), 640 zfs_type_to_name(type)); 641 goto badusage; 642 } 643 if (argc > 1) { 644 (void) fprintf(stderr, gettext("too many arguments\n")); 645 goto badusage; 646 } 647 648 if (type == ZFS_TYPE_VOLUME && !noreserve) { 649 zpool_handle_t *zpool_handle; 650 uint64_t spa_version; 651 char *p; 652 zfs_prop_t resv_prop; 653 char *strval; 654 655 if (p = strchr(argv[0], '/')) 656 *p = '\0'; 657 zpool_handle = zpool_open(g_zfs, argv[0]); 658 if (p != NULL) 659 *p = '/'; 660 if (zpool_handle == NULL) 661 goto error; 662 spa_version = zpool_get_prop_int(zpool_handle, 663 ZPOOL_PROP_VERSION, NULL); 664 zpool_close(zpool_handle); 665 if (spa_version >= SPA_VERSION_REFRESERVATION) 666 resv_prop = ZFS_PROP_REFRESERVATION; 667 else 668 resv_prop = ZFS_PROP_RESERVATION; 669 670 if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop), 671 &strval) != 0) { 672 if (nvlist_add_uint64(props, 673 zfs_prop_to_name(resv_prop), volsize) != 0) { 674 (void) fprintf(stderr, gettext("internal " 675 "error: out of memory\n")); 676 nvlist_free(props); 677 return (1); 678 } 679 } 680 } 681 682 if (parents && zfs_name_valid(argv[0], type)) { 683 /* 684 * Now create the ancestors of target dataset. If the target 685 * already exists and '-p' option was used we should not 686 * complain. 687 */ 688 if (zfs_dataset_exists(g_zfs, argv[0], type)) { 689 ret = 0; 690 goto error; 691 } 692 if (zfs_create_ancestors(g_zfs, argv[0]) != 0) 693 goto error; 694 } 695 696 /* pass to libzfs */ 697 if (zfs_create(g_zfs, argv[0], type, props) != 0) 698 goto error; 699 700 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL) 701 goto error; 702 /* 703 * if the user doesn't want the dataset automatically mounted, 704 * then skip the mount/share step 705 */ 706 707 canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); 708 709 /* 710 * Mount and/or share the new filesystem as appropriate. We provide a 711 * verbose error message to let the user know that their filesystem was 712 * in fact created, even if we failed to mount or share it. 713 */ 714 ret = 0; 715 if (canmount == ZFS_CANMOUNT_ON) { 716 if (zfs_mount(zhp, NULL, 0) != 0) { 717 (void) fprintf(stderr, gettext("filesystem " 718 "successfully created, but not mounted\n")); 719 ret = 1; 720 } else if (zfs_share(zhp) != 0) { 721 (void) fprintf(stderr, gettext("filesystem " 722 "successfully created, but not shared\n")); 723 ret = 1; 724 } 725 } 726 727 error: 728 if (zhp) 729 zfs_close(zhp); 730 nvlist_free(props); 731 return (ret); 732 badusage: 733 nvlist_free(props); 734 usage(B_FALSE); 735 return (2); 736 } 737 738 /* 739 * zfs destroy [-rf] <fs, snap, vol> 740 * 741 * -r Recursively destroy all children 742 * -R Recursively destroy all dependents, including clones 743 * -f Force unmounting of any dependents 744 * 745 * Destroys the given dataset. By default, it will unmount any filesystems, 746 * and refuse to destroy a dataset that has any dependents. A dependent can 747 * either be a child, or a clone of a child. 748 */ 749 typedef struct destroy_cbdata { 750 boolean_t cb_first; 751 int cb_force; 752 int cb_recurse; 753 int cb_error; 754 int cb_needforce; 755 int cb_doclones; 756 boolean_t cb_closezhp; 757 zfs_handle_t *cb_target; 758 char *cb_snapname; 759 } destroy_cbdata_t; 760 761 /* 762 * Check for any dependents based on the '-r' or '-R' flags. 763 */ 764 static int 765 destroy_check_dependent(zfs_handle_t *zhp, void *data) 766 { 767 destroy_cbdata_t *cbp = data; 768 const char *tname = zfs_get_name(cbp->cb_target); 769 const char *name = zfs_get_name(zhp); 770 771 if (strncmp(tname, name, strlen(tname)) == 0 && 772 (name[strlen(tname)] == '/' || name[strlen(tname)] == '@')) { 773 /* 774 * This is a direct descendant, not a clone somewhere else in 775 * the hierarchy. 776 */ 777 if (cbp->cb_recurse) 778 goto out; 779 780 if (cbp->cb_first) { 781 (void) fprintf(stderr, gettext("cannot destroy '%s': " 782 "%s has children\n"), 783 zfs_get_name(cbp->cb_target), 784 zfs_type_to_name(zfs_get_type(cbp->cb_target))); 785 (void) fprintf(stderr, gettext("use '-r' to destroy " 786 "the following datasets:\n")); 787 cbp->cb_first = B_FALSE; 788 cbp->cb_error = 1; 789 } 790 791 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 792 } else { 793 /* 794 * This is a clone. We only want to report this if the '-r' 795 * wasn't specified, or the target is a snapshot. 796 */ 797 if (!cbp->cb_recurse && 798 zfs_get_type(cbp->cb_target) != ZFS_TYPE_SNAPSHOT) 799 goto out; 800 801 if (cbp->cb_first) { 802 (void) fprintf(stderr, gettext("cannot destroy '%s': " 803 "%s has dependent clones\n"), 804 zfs_get_name(cbp->cb_target), 805 zfs_type_to_name(zfs_get_type(cbp->cb_target))); 806 (void) fprintf(stderr, gettext("use '-R' to destroy " 807 "the following datasets:\n")); 808 cbp->cb_first = B_FALSE; 809 cbp->cb_error = 1; 810 } 811 812 (void) fprintf(stderr, "%s\n", zfs_get_name(zhp)); 813 } 814 815 out: 816 zfs_close(zhp); 817 return (0); 818 } 819 820 static int 821 destroy_callback(zfs_handle_t *zhp, void *data) 822 { 823 destroy_cbdata_t *cbp = data; 824 825 /* 826 * Ignore pools (which we've already flagged as an error before getting 827 * here. 828 */ 829 if (strchr(zfs_get_name(zhp), '/') == NULL && 830 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { 831 zfs_close(zhp); 832 return (0); 833 } 834 835 /* 836 * Bail out on the first error. 837 */ 838 if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 || 839 zfs_destroy(zhp) != 0) { 840 zfs_close(zhp); 841 return (-1); 842 } 843 844 zfs_close(zhp); 845 return (0); 846 } 847 848 static int 849 destroy_snap_clones(zfs_handle_t *zhp, void *arg) 850 { 851 destroy_cbdata_t *cbp = arg; 852 char thissnap[MAXPATHLEN]; 853 zfs_handle_t *szhp; 854 boolean_t closezhp = cbp->cb_closezhp; 855 int rv; 856 857 (void) snprintf(thissnap, sizeof (thissnap), 858 "%s@%s", zfs_get_name(zhp), cbp->cb_snapname); 859 860 libzfs_print_on_error(g_zfs, B_FALSE); 861 szhp = zfs_open(g_zfs, thissnap, ZFS_TYPE_SNAPSHOT); 862 libzfs_print_on_error(g_zfs, B_TRUE); 863 if (szhp) { 864 /* 865 * Destroy any clones of this snapshot 866 */ 867 if (zfs_iter_dependents(szhp, B_FALSE, destroy_callback, 868 cbp) != 0) { 869 zfs_close(szhp); 870 if (closezhp) 871 zfs_close(zhp); 872 return (-1); 873 } 874 zfs_close(szhp); 875 } 876 877 cbp->cb_closezhp = B_TRUE; 878 rv = zfs_iter_filesystems(zhp, destroy_snap_clones, arg); 879 if (closezhp) 880 zfs_close(zhp); 881 return (rv); 882 } 883 884 static int 885 zfs_do_destroy(int argc, char **argv) 886 { 887 destroy_cbdata_t cb = { 0 }; 888 int c; 889 zfs_handle_t *zhp; 890 char *cp; 891 892 /* check options */ 893 while ((c = getopt(argc, argv, "frR")) != -1) { 894 switch (c) { 895 case 'f': 896 cb.cb_force = 1; 897 break; 898 case 'r': 899 cb.cb_recurse = 1; 900 break; 901 case 'R': 902 cb.cb_recurse = 1; 903 cb.cb_doclones = 1; 904 break; 905 case '?': 906 default: 907 (void) fprintf(stderr, gettext("invalid option '%c'\n"), 908 optopt); 909 usage(B_FALSE); 910 } 911 } 912 913 argc -= optind; 914 argv += optind; 915 916 /* check number of arguments */ 917 if (argc == 0) { 918 (void) fprintf(stderr, gettext("missing path argument\n")); 919 usage(B_FALSE); 920 } 921 if (argc > 1) { 922 (void) fprintf(stderr, gettext("too many arguments\n")); 923 usage(B_FALSE); 924 } 925 926 /* 927 * If we are doing recursive destroy of a snapshot, then the 928 * named snapshot may not exist. Go straight to libzfs. 929 */ 930 if (cb.cb_recurse && (cp = strchr(argv[0], '@'))) { 931 int ret; 932 933 *cp = '\0'; 934 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL) 935 return (1); 936 *cp = '@'; 937 cp++; 938 939 if (cb.cb_doclones) { 940 cb.cb_snapname = cp; 941 if (destroy_snap_clones(zhp, &cb) != 0) { 942 zfs_close(zhp); 943 return (1); 944 } 945 } 946 947 ret = zfs_destroy_snaps(zhp, cp); 948 zfs_close(zhp); 949 if (ret) { 950 (void) fprintf(stderr, 951 gettext("no snapshots destroyed\n")); 952 } 953 return (ret != 0); 954 } 955 956 957 /* Open the given dataset */ 958 if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL) 959 return (1); 960 961 cb.cb_target = zhp; 962 963 /* 964 * Perform an explicit check for pools before going any further. 965 */ 966 if (!cb.cb_recurse && strchr(zfs_get_name(zhp), '/') == NULL && 967 zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { 968 (void) fprintf(stderr, gettext("cannot destroy '%s': " 969 "operation does not apply to pools\n"), 970 zfs_get_name(zhp)); 971 (void) fprintf(stderr, gettext("use 'zfs destroy -r " 972 "%s' to destroy all datasets in the pool\n"), 973 zfs_get_name(zhp)); 974 (void) fprintf(stderr, gettext("use 'zpool destroy %s' " 975 "to destroy the pool itself\n"), zfs_get_name(zhp)); 976 zfs_close(zhp); 977 return (1); 978 } 979 980 /* 981 * Check for any dependents and/or clones. 982 */ 983 cb.cb_first = B_TRUE; 984 if (!cb.cb_doclones && 985 zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent, 986 &cb) != 0) { 987 zfs_close(zhp); 988 return (1); 989 } 990 991 if (cb.cb_error || 992 zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0) { 993 zfs_close(zhp); 994 return (1); 995 } 996 997 /* 998 * Do the real thing. The callback will close the handle regardless of 999 * whether it succeeds or not. 1000 */ 1001 1002 if (destroy_callback(zhp, &cb) != 0) 1003 return (1); 1004 1005 1006 return (0); 1007 } 1008 1009 /* 1010 * zfs get [-rHp] [-o field[,field]...] [-s source[,source]...] 1011 * < all | property[,property]... > < fs | snap | vol > ... 1012 * 1013 * -r recurse over any child datasets 1014 * -H scripted mode. Headers are stripped, and fields are separated 1015 * by tabs instead of spaces. 1016 * -o Set of fields to display. One of "name,property,value,source". 1017 * Default is all four. 1018 * -s Set of sources to allow. One of 1019 * "local,default,inherited,temporary,none". Default is all 1020 * five. 1021 * -p Display values in parsable (literal) format. 1022 * 1023 * Prints properties for the given datasets. The user can control which 1024 * columns to display as well as which property types to allow. 1025 */ 1026 1027 /* 1028 * Invoked to display the properties for a single dataset. 1029 */ 1030 static int 1031 get_callback(zfs_handle_t *zhp, void *data) 1032 { 1033 char buf[ZFS_MAXPROPLEN]; 1034 zprop_source_t sourcetype; 1035 char source[ZFS_MAXNAMELEN]; 1036 zprop_get_cbdata_t *cbp = data; 1037 nvlist_t *userprop = zfs_get_user_props(zhp); 1038 zprop_list_t *pl = cbp->cb_proplist; 1039 nvlist_t *propval; 1040 char *strval; 1041 char *sourceval; 1042 1043 for (; pl != NULL; pl = pl->pl_next) { 1044 /* 1045 * Skip the special fake placeholder. This will also skip over 1046 * the name property when 'all' is specified. 1047 */ 1048 if (pl->pl_prop == ZFS_PROP_NAME && 1049 pl == cbp->cb_proplist) 1050 continue; 1051 1052 if (pl->pl_prop != ZPROP_INVAL) { 1053 if (zfs_prop_get(zhp, pl->pl_prop, buf, 1054 sizeof (buf), &sourcetype, source, 1055 sizeof (source), 1056 cbp->cb_literal) != 0) { 1057 if (pl->pl_all) 1058 continue; 1059 if (!zfs_prop_valid_for_type(pl->pl_prop, 1060 ZFS_TYPE_DATASET)) { 1061 (void) fprintf(stderr, 1062 gettext("No such property '%s'\n"), 1063 zfs_prop_to_name(pl->pl_prop)); 1064 continue; 1065 } 1066 sourcetype = ZPROP_SRC_NONE; 1067 (void) strlcpy(buf, "-", sizeof (buf)); 1068 } 1069 1070 zprop_print_one_property(zfs_get_name(zhp), cbp, 1071 zfs_prop_to_name(pl->pl_prop), 1072 buf, sourcetype, source); 1073 } else { 1074 if (nvlist_lookup_nvlist(userprop, 1075 pl->pl_user_prop, &propval) != 0) { 1076 if (pl->pl_all) 1077 continue; 1078 sourcetype = ZPROP_SRC_NONE; 1079 strval = "-"; 1080 } else { 1081 verify(nvlist_lookup_string(propval, 1082 ZPROP_VALUE, &strval) == 0); 1083 verify(nvlist_lookup_string(propval, 1084 ZPROP_SOURCE, &sourceval) == 0); 1085 1086 if (strcmp(sourceval, 1087 zfs_get_name(zhp)) == 0) { 1088 sourcetype = ZPROP_SRC_LOCAL; 1089 } else { 1090 sourcetype = ZPROP_SRC_INHERITED; 1091 (void) strlcpy(source, 1092 sourceval, sizeof (source)); 1093 } 1094 } 1095 1096 zprop_print_one_property(zfs_get_name(zhp), cbp, 1097 pl->pl_user_prop, strval, sourcetype, 1098 source); 1099 } 1100 } 1101 1102 return (0); 1103 } 1104 1105 static int 1106 zfs_do_get(int argc, char **argv) 1107 { 1108 zprop_get_cbdata_t cb = { 0 }; 1109 boolean_t recurse =