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