X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=cmd%2Fzfs%2Fzfs_main.c;h=b0e6180eac86176715e1ea25890dbd4f83acfb1a;hb=4682b8c14efdeae26808195422a763b896fef037;hp=353fd4fa627db988f138357e8418f6db25fa8199;hpb=428870ff734fdaccc342b33fc53cf94724409a46;p=zfs.git diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 353fd4f..b0e6180 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,7 @@ static int zfs_do_userspace(int argc, char **argv); static int zfs_do_python(int argc, char **argv); static int zfs_do_hold(int argc, char **argv); static int zfs_do_release(int argc, char **argv); +static int zfs_do_diff(int argc, char **argv); /* * Enable a reasonable set of defaults for libumem debugging on DEBUG builds. @@ -128,7 +130,8 @@ typedef enum { HELP_GROUPSPACE, HELP_HOLD, HELP_HOLDS, - HELP_RELEASE + HELP_RELEASE, + HELP_DIFF } zfs_help_t; typedef struct zfs_command { @@ -180,6 +183,7 @@ static zfs_command_t command_table[] = { { "hold", zfs_do_hold, HELP_HOLD }, { "holds", zfs_do_python, HELP_HOLDS }, { "release", zfs_do_release, HELP_RELEASE }, + { "diff", zfs_do_diff, HELP_DIFF }, }; #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) @@ -283,6 +287,9 @@ get_usage(zfs_help_t idx) return (gettext("\tholds [-r] ...\n")); case HELP_RELEASE: return (gettext("\trelease [-r] ...\n")); + case HELP_DIFF: + return (gettext("\tdiff [-FHt] " + "[snapshot|filesystem]\n")); } abort(); @@ -311,6 +318,7 @@ safe_malloc(size_t size) return (data); } +#ifdef HAVE_ZPL static char * safe_strdup(char *str) { @@ -321,6 +329,7 @@ safe_strdup(char *str) return (dupstr); } +#endif /* HAVE_ZPL */ /* * Callback routine that will print out information for each of @@ -488,6 +497,7 @@ parse_depth(char *opt, int *flags) #define PROGRESS_DELAY 2 /* seconds */ +#ifdef HAVE_ZPL 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"; static time_t pt_begin; static char *pt_header = NULL; @@ -539,6 +549,8 @@ finish_progress(char *done) free(pt_header); pt_header = NULL; } +#endif /* HAVE_ZPL */ + /* * zfs clone [-p] [-o prop=value] ... * @@ -619,16 +631,19 @@ zfs_do_clone(int argc, char **argv) ret = zfs_clone(zhp, argv[1], props); /* create the mountpoint if necessary */ +#ifdef HAVE_ZPL if (ret == 0) { zfs_handle_t *clone; clone = zfs_open(g_zfs, argv[1], ZFS_TYPE_DATASET); if (clone != NULL) { - if ((ret = zfs_mount(clone, NULL, 0)) == 0) - ret = zfs_share(clone); + if (zfs_get_type(clone) != ZFS_TYPE_VOLUME) + if ((ret = zfs_mount(clone, NULL, 0)) == 0) + ret = zfs_share(clone); zfs_close(clone); } } +#endif /* HAVE_ZPL */ zfs_close(zhp); nvlist_free(props); @@ -663,7 +678,7 @@ zfs_do_create(int argc, char **argv) { zfs_type_t type = ZFS_TYPE_FILESYSTEM; zfs_handle_t *zhp = NULL; - uint64_t volsize; + uint64_t volsize = 0; int c; boolean_t noreserve = B_FALSE; boolean_t bflag = B_FALSE; @@ -671,7 +686,7 @@ zfs_do_create(int argc, char **argv) int ret = 1; nvlist_t *props; uint64_t intval; - int canmount; + int canmount = ZFS_CANMOUNT_OFF; if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) nomem(); @@ -756,7 +771,7 @@ zfs_do_create(int argc, char **argv) zfs_prop_t resv_prop; char *strval; - if (p = strchr(argv[0], '/')) + if ((p = strchr(argv[0], '/'))) *p = '\0'; zpool_handle = zpool_open(g_zfs, argv[0]); if (p != NULL) @@ -802,19 +817,21 @@ zfs_do_create(int argc, char **argv) if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL) goto error; + + ret = 0; /* * if the user doesn't want the dataset automatically mounted, * then skip the mount/share step */ - - canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); + if (zfs_prop_valid_for_type(ZFS_PROP_CANMOUNT, type)) + canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); /* * Mount and/or share the new filesystem as appropriate. We provide a * verbose error message to let the user know that their filesystem was * in fact created, even if we failed to mount or share it. */ - ret = 0; +#ifdef HAVE_ZPL if (canmount == ZFS_CANMOUNT_ON) { if (zfs_mount(zhp, NULL, 0) != 0) { (void) fprintf(stderr, gettext("filesystem " @@ -826,6 +843,7 @@ zfs_do_create(int argc, char **argv) ret = 1; } } +#endif /* HAVE_ZPL */ error: if (zhp) @@ -1673,7 +1691,7 @@ upgrade_set_callback(zfs_handle_t *zhp, void *data) if (version < cb->cb_version) { char verstr[16]; (void) snprintf(verstr, sizeof (verstr), - "%llu", cb->cb_version); + "%llu", (u_longlong_t)cb->cb_version); if (cb->cb_lastfs[0] && !same_pool(zhp, cb->cb_lastfs)) { /* * If they did "zfs upgrade -a", then we could @@ -1711,7 +1729,7 @@ zfs_do_upgrade(int argc, char **argv) boolean_t showversions = B_FALSE; int ret; upgrade_cbdata_t cb = { 0 }; - char c; + signed char c; int flags = ZFS_ITER_ARGS_CAN_BE_PATHS; /* check options */ @@ -1780,11 +1798,11 @@ zfs_do_upgrade(int argc, char **argv) ret = zfs_for_each(argc, argv, flags, ZFS_TYPE_FILESYSTEM, NULL, NULL, 0, upgrade_set_callback, &cb); (void) printf(gettext("%llu filesystems upgraded\n"), - cb.cb_numupgraded); + (u_longlong_t)cb.cb_numupgraded); if (cb.cb_numsamegraded) { (void) printf(gettext("%llu filesystems already at " "this version\n"), - cb.cb_numsamegraded); + (u_longlong_t)cb.cb_numsamegraded); } if (cb.cb_numfailed != 0) ret = 1; @@ -1948,9 +1966,9 @@ print_header(zprop_list_t *pl) if (pl->pl_next == NULL && !right_justify) (void) printf("%s", header); else if (right_justify) - (void) printf("%*s", pl->pl_width, header); + (void) printf("%*s", (int)pl->pl_width, header); else - (void) printf("%-*s", pl->pl_width, header); + (void) printf("%-*s", (int)pl->pl_width, header); } (void) printf("\n"); @@ -2541,7 +2559,7 @@ zfs_do_set(int argc, char **argv) usage(B_FALSE); } - ret = zfs_for_each(argc - 2, argv + 2, NULL, + ret = zfs_for_each(argc - 2, argv + 2, 0, ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb); return (ret); @@ -2558,7 +2576,7 @@ zfs_do_snapshot(int argc, char **argv) { boolean_t recursive = B_FALSE; int ret; - char c; + signed char c; nvlist_t *props; if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0) @@ -2888,7 +2906,7 @@ zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding) } if (holding) { if (zfs_hold(zhp, delim+1, tag, recursive, - temphold, B_FALSE) != 0) + temphold, B_FALSE, -1, 0, 0) != 0) ++errors; } else { if (zfs_release(zhp, delim+1, tag, recursive) != 0) @@ -2927,18 +2945,11 @@ zfs_do_release(int argc, char **argv) return (zfs_do_hold_rele_impl(argc, argv, B_FALSE)); } -typedef struct get_all_cbdata { - zfs_handle_t **cb_handles; - size_t cb_alloc; - size_t cb_used; - uint_t cb_types; - boolean_t cb_verbose; -} get_all_cbdata_t; - #define CHECK_SPINNER 30 #define SPINNER_TIME 3 /* seconds */ #define MOUNT_TIME 5 /* seconds */ +#ifdef HAVE_ZPL static int get_one_dataset(zfs_handle_t *zhp, void *data) { @@ -2946,7 +2957,7 @@ get_one_dataset(zfs_handle_t *zhp, void *data) static int spinval = 0; static int spincheck = 0; static time_t last_spin_time = (time_t)0; - get_all_cbdata_t *cbp = data; + get_all_cb_t *cbp = data; zfs_type_t type = zfs_get_type(zhp); if (cbp->cb_verbose) { @@ -2963,8 +2974,7 @@ get_one_dataset(zfs_handle_t *zhp, void *data) /* * Interate over any nested datasets. */ - if (type == ZFS_TYPE_FILESYSTEM && - zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) { + if (zfs_iter_filesystems(zhp, get_one_dataset, data) != 0) { zfs_close(zhp); return (1); } @@ -2972,46 +2982,25 @@ get_one_dataset(zfs_handle_t *zhp, void *data) /* * Skip any datasets whose type does not match. */ - if ((type & cbp->cb_types) == 0) { + if ((type & ZFS_TYPE_FILESYSTEM) == 0) { zfs_close(zhp); return (0); } - - if (cbp->cb_alloc == cbp->cb_used) { - zfs_handle_t **handles; - - if (cbp->cb_alloc == 0) - cbp->cb_alloc = 64; - else - cbp->cb_alloc *= 2; - - handles = safe_malloc(cbp->cb_alloc * sizeof (void *)); - - if (cbp->cb_handles) { - bcopy(cbp->cb_handles, handles, - cbp->cb_used * sizeof (void *)); - free(cbp->cb_handles); - } - - cbp->cb_handles = handles; - } - - cbp->cb_handles[cbp->cb_used++] = zhp; + libzfs_add_handle(cbp, zhp); + assert(cbp->cb_used <= cbp->cb_alloc); return (0); } static void -get_all_datasets(uint_t types, zfs_handle_t ***dslist, size_t *count, - boolean_t verbose) +get_all_datasets(zfs_handle_t ***dslist, size_t *count, boolean_t verbose) { - get_all_cbdata_t cb = { 0 }; - cb.cb_types = types; + get_all_cb_t cb = { 0 }; cb.cb_verbose = verbose; + cb.cb_getone = get_one_dataset; if (verbose) set_progress_header(gettext("Reading ZFS config")); - (void) zfs_iter_root(g_zfs, get_one_dataset, &cb); *dslist = cb.cb_handles; @@ -3021,33 +3010,6 @@ get_all_datasets(uint_t types, zfs_handle_t ***dslist, size_t *count, finish_progress(gettext("done.")); } -static int -dataset_cmp(const void *a, const void *b) -{ - zfs_handle_t **za = (zfs_handle_t **)a; - zfs_handle_t **zb = (zfs_handle_t **)b; - char mounta[MAXPATHLEN]; - char mountb[MAXPATHLEN]; - boolean_t gota, gotb; - - if ((gota = (zfs_get_type(*za) == ZFS_TYPE_FILESYSTEM)) != 0) - verify(zfs_prop_get(*za, ZFS_PROP_MOUNTPOINT, mounta, - sizeof (mounta), NULL, NULL, 0, B_FALSE) == 0); - if ((gotb = (zfs_get_type(*zb) == ZFS_TYPE_FILESYSTEM)) != 0) - verify(zfs_prop_get(*zb, ZFS_PROP_MOUNTPOINT, mountb, - sizeof (mountb), NULL, NULL, 0, B_FALSE) == 0); - - if (gota && gotb) - return (strcmp(mounta, mountb)); - - if (gota) - return (-1); - if (gotb) - return (1); - - return (strcmp(zfs_get_name(a), zfs_get_name(b))); -} - /* * Generic callback for sharing or mounting filesystems. Because the code is so * similar, we have a common function with an extra parameter to determine which @@ -3069,184 +3031,180 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol, const char *cmdname = op == OP_SHARE ? "share" : "mount"; struct mnttab mnt; uint64_t zoned, canmount; - zfs_type_t type = zfs_get_type(zhp); boolean_t shared_nfs, shared_smb; - assert(type & (ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)); + assert(zfs_get_type(zhp) & ZFS_TYPE_FILESYSTEM); - if (type == ZFS_TYPE_FILESYSTEM) { - /* - * Check to make sure we can mount/share this dataset. If we - * are in the global zone and the filesystem is exported to a - * local zone, or if we are in a local zone and the - * filesystem is not exported, then it is an error. - */ - zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); + /* + * Check to make sure we can mount/share this dataset. If we + * are in the global zone and the filesystem is exported to a + * local zone, or if we are in a local zone and the + * filesystem is not exported, then it is an error. + */ + zoned = zfs_prop_get_int(zhp, ZFS_PROP_ZONED); - if (zoned && getzoneid() == GLOBAL_ZONEID) { - if (!explicit) - return (0); + if (zoned && getzoneid() == GLOBAL_ZONEID) { + if (!explicit) + return (0); - (void) fprintf(stderr, gettext("cannot %s '%s': " - "dataset is exported to a local zone\n"), cmdname, - zfs_get_name(zhp)); - return (1); + (void) fprintf(stderr, gettext("cannot %s '%s': " + "dataset is exported to a local zone\n"), cmdname, + zfs_get_name(zhp)); + return (1); - } else if (!zoned && getzoneid() != GLOBAL_ZONEID) { - if (!explicit) - return (0); + } else if (!zoned && getzoneid() != GLOBAL_ZONEID) { + if (!explicit) + return (0); - (void) fprintf(stderr, gettext("cannot %s '%s': " - "permission denied\n"), cmdname, - zfs_get_name(zhp)); - return (1); - } + (void) fprintf(stderr, gettext("cannot %s '%s': " + "permission denied\n"), cmdname, + zfs_get_name(zhp)); + return (1); + } - /* - * Ignore any filesystems which don't apply to us. This - * includes those with a legacy mountpoint, or those with - * legacy share options. - */ - verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, - sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); - verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, - sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); - verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshareopts, - sizeof (smbshareopts), NULL, NULL, 0, B_FALSE) == 0); - - if (op == OP_SHARE && strcmp(shareopts, "off") == 0 && - strcmp(smbshareopts, "off") == 0) { - if (!explicit) - return (0); + /* + * Ignore any filesystems which don't apply to us. This + * includes those with a legacy mountpoint, or those with + * legacy share options. + */ + verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, mountpoint, + sizeof (mountpoint), NULL, NULL, 0, B_FALSE) == 0); + verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, shareopts, + sizeof (shareopts), NULL, NULL, 0, B_FALSE) == 0); + verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, smbshareopts, + sizeof (smbshareopts), NULL, NULL, 0, B_FALSE) == 0); + + if (op == OP_SHARE && strcmp(shareopts, "off") == 0 && + strcmp(smbshareopts, "off") == 0) { + if (!explicit) + return (0); - (void) fprintf(stderr, gettext("cannot share '%s': " - "legacy share\n"), zfs_get_name(zhp)); - (void) fprintf(stderr, gettext("use share(1M) to " - "share this filesystem, or set " - "sharenfs property on\n")); - return (1); - } + (void) fprintf(stderr, gettext("cannot share '%s': " + "legacy share\n"), zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("use share(1M) to " + "share this filesystem, or set " + "sharenfs property on\n")); + return (1); + } - /* - * We cannot share or mount legacy filesystems. If the - * shareopts is non-legacy but the mountpoint is legacy, we - * treat it as a legacy share. - */ - if (strcmp(mountpoint, "legacy") == 0) { - if (!explicit) - return (0); + /* + * We cannot share or mount legacy filesystems. If the + * shareopts is non-legacy but the mountpoint is legacy, we + * treat it as a legacy share. + */ + if (strcmp(mountpoint, "legacy") == 0) { + if (!explicit) + return (0); - (void) fprintf(stderr, gettext("cannot %s '%s': " - "legacy mountpoint\n"), cmdname, zfs_get_name(zhp)); - (void) fprintf(stderr, gettext("use %s(1M) to " - "%s this filesystem\n"), cmdname, cmdname); - return (1); - } + (void) fprintf(stderr, gettext("cannot %s '%s': " + "legacy mountpoint\n"), cmdname, zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("use %s(1M) to " + "%s this filesystem\n"), cmdname, cmdname); + return (1); + } - if (strcmp(mountpoint, "none") == 0) { - if (!explicit) - return (0); + if (strcmp(mountpoint, "none") == 0) { + if (!explicit) + return (0); - (void) fprintf(stderr, gettext("cannot %s '%s': no " - "mountpoint set\n"), cmdname, zfs_get_name(zhp)); - return (1); - } + (void) fprintf(stderr, gettext("cannot %s '%s': no " + "mountpoint set\n"), cmdname, zfs_get_name(zhp)); + return (1); + } - /* - * canmount explicit outcome - * on no pass through - * on yes pass through - * off no return 0 - * off yes display error, return 1 - * noauto no return 0 - * noauto yes pass through - */ - canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); - if (canmount == ZFS_CANMOUNT_OFF) { + /* + * canmount explicit outcome + * on no pass through + * on yes pass through + * off no return 0 + * off yes display error, return 1 + * noauto no return 0 + * noauto yes pass through + */ + canmount = zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT); + if (canmount == ZFS_CANMOUNT_OFF) { + if (!explicit) + return (0); + + (void) fprintf(stderr, gettext("cannot %s '%s': " + "'canmount' property is set to 'off'\n"), cmdname, + zfs_get_name(zhp)); + return (1); + } else if (canmount == ZFS_CANMOUNT_NOAUTO && !explicit) { + return (0); + } + + /* + * At this point, we have verified that the mountpoint and/or + * shareopts are appropriate for auto management. If the + * filesystem is already mounted or shared, return (failing + * for explicit requests); otherwise mount or share the + * filesystem. + */ + switch (op) { + case OP_SHARE: + + shared_nfs = zfs_is_shared_nfs(zhp, NULL); + shared_smb = zfs_is_shared_smb(zhp, NULL); + + if (shared_nfs && shared_smb || + (shared_nfs && strcmp(shareopts, "on") == 0 && + strcmp(smbshareopts, "off") == 0) || + (shared_smb && strcmp(smbshareopts, "on") == 0 && + strcmp(shareopts, "off") == 0)) { if (!explicit) return (0); - (void) fprintf(stderr, gettext("cannot %s '%s': " - "'canmount' property is set to 'off'\n"), cmdname, + (void) fprintf(stderr, gettext("cannot share " + "'%s': filesystem already shared\n"), zfs_get_name(zhp)); return (1); - } else if (canmount == ZFS_CANMOUNT_NOAUTO && !explicit) { - return (0); } - /* - * At this point, we have verified that the mountpoint and/or - * shareopts are appropriate for auto management. If the - * filesystem is already mounted or shared, return (failing - * for explicit requests); otherwise mount or share the - * filesystem. - */ - switch (op) { - case OP_SHARE: - - shared_nfs = zfs_is_shared_nfs(zhp, NULL); - shared_smb = zfs_is_shared_smb(zhp, NULL); - - if (shared_nfs && shared_smb || - (shared_nfs && strcmp(shareopts, "on") == 0 && - strcmp(smbshareopts, "off") == 0) || - (shared_smb && strcmp(smbshareopts, "on") == 0 && - strcmp(shareopts, "off") == 0)) { - if (!explicit) - return (0); + if (!zfs_is_mounted(zhp, NULL) && + zfs_mount(zhp, NULL, 0) != 0) + return (1); - (void) fprintf(stderr, gettext("cannot share " - "'%s': filesystem already shared\n"), - zfs_get_name(zhp)); + if (protocol == NULL) { + if (zfs_shareall(zhp) != 0) return (1); - } - - if (!zfs_is_mounted(zhp, NULL) && - zfs_mount(zhp, NULL, 0) != 0) + } else if (strcmp(protocol, "nfs") == 0) { + if (zfs_share_nfs(zhp)) return (1); - - if (protocol == NULL) { - if (zfs_shareall(zhp) != 0) - return (1); - } else if (strcmp(protocol, "nfs") == 0) { - if (zfs_share_nfs(zhp)) - return (1); - } else if (strcmp(protocol, "smb") == 0) { - if (zfs_share_smb(zhp)) - return (1); - } else { - (void) fprintf(stderr, gettext("cannot share " - "'%s': invalid share type '%s' " - "specified\n"), - zfs_get_name(zhp), protocol); + } else if (strcmp(protocol, "smb") == 0) { + if (zfs_share_smb(zhp)) return (1); - } - - break; + } else { + (void) fprintf(stderr, gettext("cannot share " + "'%s': invalid share type '%s' " + "specified\n"), + zfs_get_name(zhp), protocol); + return (1); + } - case OP_MOUNT: - if (options == NULL) - mnt.mnt_mntopts = ""; - else - mnt.mnt_mntopts = (char *)options; + break; - if (!hasmntopt(&mnt, MNTOPT_REMOUNT) && - zfs_is_mounted(zhp, NULL)) { - if (!explicit) - return (0); + case OP_MOUNT: + if (options == NULL) + mnt.mnt_mntopts = ""; + else + mnt.mnt_mntopts = (char *)options; - (void) fprintf(stderr, gettext("cannot mount " - "'%s': filesystem already mounted\n"), - zfs_get_name(zhp)); - return (1); - } + if (!hasmntopt(&mnt, MNTOPT_REMOUNT) && + zfs_is_mounted(zhp, NULL)) { + if (!explicit) + return (0); - if (zfs_mount(zhp, options, flags) != 0) - return (1); - break; + (void) fprintf(stderr, gettext("cannot mount " + "'%s': filesystem already mounted\n"), + zfs_get_name(zhp)); + return (1); } - } else - assert(op == OP_SHARE); + + if (zfs_mount(zhp, options, flags) != 0) + return (1); + break; + } return (0); } @@ -3290,7 +3248,7 @@ append_options(char *mntopts, char *newopts) /* original length plus new string to append plus 1 for the comma */ if (len + 1 + strlen(newopts) >= MNT_LINE_MAX) { (void) fprintf(stderr, gettext("the opts argument for " - "'%c' option is too long (more than %d chars)\n"), + "'%s' option is too long (more than %d chars)\n"), "-o", MNT_LINE_MAX); usage(B_FALSE); } @@ -3308,7 +3266,7 @@ share_mount(int op, int argc, char **argv) boolean_t verbose = B_FALSE; int c, ret = 0; char *options = NULL; - int types, flags = 0; + int flags = 0; /* check options */ while ((c = getopt(argc, argv, op == OP_MOUNT ? ":avo:O" : "a")) @@ -3358,13 +3316,9 @@ share_mount(int op, int argc, char **argv) size_t i, count = 0; char *protocol = NULL; - if (op == OP_MOUNT) { - types = ZFS_TYPE_FILESYSTEM; - } else if (argc > 0) { - if (strcmp(argv[0], "nfs") == 0 || - strcmp(argv[0], "smb") == 0) { - types = ZFS_TYPE_FILESYSTEM; - } else { + if (op == OP_SHARE && argc > 0) { + if (strcmp(argv[0], "nfs") != 0 && + strcmp(argv[0], "smb") != 0) { (void) fprintf(stderr, gettext("share type " "must be 'nfs' or 'smb'\n")); usage(B_FALSE); @@ -3372,8 +3326,6 @@ share_mount(int op, int argc, char **argv) protocol = argv[0]; argc--; argv++; - } else { - types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME; } if (argc != 0) { @@ -3382,12 +3334,12 @@ share_mount(int op, int argc, char **argv) } start_progress_timer(); - get_all_datasets(types, &dslist, &count, verbose); + get_all_datasets(&dslist, &count, verbose); if (count == 0) return (0); - qsort(dslist, count, sizeof (void *), dataset_cmp); + qsort(dslist, count, sizeof (void *), libzfs_dataset_cmp); for (i = 0; i < count; i++) { if (verbose) @@ -3427,17 +3379,14 @@ share_mount(int op, int argc, char **argv) } else { zfs_handle_t *zhp; - types = ZFS_TYPE_FILESYSTEM; - if (op == OP_SHARE) - types |= ZFS_TYPE_VOLUME; - if (argc > 1) { (void) fprintf(stderr, gettext("too many arguments\n")); usage(B_FALSE); } - if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) { + if ((zhp = zfs_open(g_zfs, argv[0], + ZFS_TYPE_FILESYSTEM)) == NULL) { ret = 1; } else { ret = share_mount_one(zhp, op, flags, NULL, B_TRUE, @@ -3448,6 +3397,7 @@ share_mount(int op, int argc, char **argv) return (ret); } +#endif /* HAVE_ZPL */ /* * zfs mount -a [nfs] @@ -3458,7 +3408,11 @@ share_mount(int op, int argc, char **argv) static int zfs_do_mount(int argc, char **argv) { +#ifdef HAVE_ZPL return (share_mount(OP_MOUNT, argc, argv)); +#else + return ENOSYS; +#endif /* HAVE_ZPL */ } /* @@ -3470,9 +3424,14 @@ zfs_do_mount(int argc, char **argv) static int zfs_do_share(int argc, char **argv) { +#ifdef HAVE_ZPL return (share_mount(OP_SHARE, argc, argv)); +#else + return ENOSYS; +#endif /* HAVE_ZPL */ } +#ifdef HAVE_ZPL typedef struct unshare_unmount_node { zfs_handle_t *un_zhp; char *un_mountp; @@ -3616,7 +3575,7 @@ unshare_unmount(int op, int argc, char **argv) int do_all = 0; int flags = 0; int ret = 0; - int types, c; + int c; zfs_handle_t *zhp; char nfs_mnt_prop[ZFS_MAXPROPLEN]; char sharesmb[ZFS_MAXPROPLEN]; @@ -3792,68 +3751,63 @@ unshare_unmount(int op, int argc, char **argv) return (unshare_unmount_path(op, argv[0], flags, B_FALSE)); - types = ZFS_TYPE_FILESYSTEM; - if (op == OP_SHARE) - types |= ZFS_TYPE_VOLUME; - - if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL) + if ((zhp = zfs_open(g_zfs, argv[0], + ZFS_TYPE_FILESYSTEM)) == NULL) return (1); - if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM) { - verify(zfs_prop_get(zhp, op == OP_SHARE ? - ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, - nfs_mnt_prop, sizeof (nfs_mnt_prop), NULL, - NULL, 0, B_FALSE) == 0); + verify(zfs_prop_get(zhp, op == OP_SHARE ? + ZFS_PROP_SHARENFS : ZFS_PROP_MOUNTPOINT, + nfs_mnt_prop, sizeof (nfs_mnt_prop), NULL, + NULL, 0, B_FALSE) == 0); - switch (op) { - case OP_SHARE: - verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, - nfs_mnt_prop, - sizeof (nfs_mnt_prop), - NULL, NULL, 0, B_FALSE) == 0); - verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, - sharesmb, sizeof (sharesmb), NULL, NULL, - 0, B_FALSE) == 0); - - if (strcmp(nfs_mnt_prop, "off") == 0 && - strcmp(sharesmb, "off") == 0) { - (void) fprintf(stderr, gettext("cannot " - "unshare '%s': legacy share\n"), - zfs_get_name(zhp)); - (void) fprintf(stderr, gettext("use " - "unshare(1M) to unshare this " - "filesystem\n")); - ret = 1; - } else if (!zfs_is_shared(zhp)) { - (void) fprintf(stderr, gettext("cannot " - "unshare '%s': not currently " - "shared\n"), zfs_get_name(zhp)); - ret = 1; - } else if (zfs_unshareall(zhp) != 0) { - ret = 1; - } - break; + switch (op) { + case OP_SHARE: + verify(zfs_prop_get(zhp, ZFS_PROP_SHARENFS, + nfs_mnt_prop, + sizeof (nfs_mnt_prop), + NULL, NULL, 0, B_FALSE) == 0); + verify(zfs_prop_get(zhp, ZFS_PROP_SHARESMB, + sharesmb, sizeof (sharesmb), NULL, NULL, + 0, B_FALSE) == 0); + + if (strcmp(nfs_mnt_prop, "off") == 0 && + strcmp(sharesmb, "off") == 0) { + (void) fprintf(stderr, gettext("cannot " + "unshare '%s': legacy share\n"), + zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("use " + "unshare(1M) to unshare this " + "filesystem\n")); + ret = 1; + } else if (!zfs_is_shared(zhp)) { + (void) fprintf(stderr, gettext("cannot " + "unshare '%s': not currently " + "shared\n"), zfs_get_name(zhp)); + ret = 1; + } else if (zfs_unshareall(zhp) != 0) { + ret = 1; + } + break; - case OP_MOUNT: - if (strcmp(nfs_mnt_prop, "legacy") == 0) { - (void) fprintf(stderr, gettext("cannot " - "unmount '%s': legacy " - "mountpoint\n"), zfs_get_name(zhp)); - (void) fprintf(stderr, gettext("use " - "umount(1M) to unmount this " - "filesystem\n")); - ret = 1; - } else if (!zfs_is_mounted(zhp, NULL)) { - (void) fprintf(stderr, gettext("cannot " - "unmount '%s': not currently " - "mounted\n"), - zfs_get_name(zhp)); - ret = 1; - } else if (zfs_unmountall(zhp, flags) != 0) { - ret = 1; - } - break; + case OP_MOUNT: + if (strcmp(nfs_mnt_prop, "legacy") == 0) { + (void) fprintf(stderr, gettext("cannot " + "unmount '%s': legacy " + "mountpoint\n"), zfs_get_name(zhp)); + (void) fprintf(stderr, gettext("use " + "umount(1M) to unmount this " + "filesystem\n")); + ret = 1; + } else if (!zfs_is_mounted(zhp, NULL)) { + (void) fprintf(stderr, gettext("cannot " + "unmount '%s': not currently " + "mounted\n"), + zfs_get_name(zhp)); + ret = 1; + } else if (zfs_unmountall(zhp, flags) != 0) { + ret = 1; } + break; } zfs_close(zhp); @@ -3861,6 +3815,7 @@ unshare_unmount(int op, int argc, char **argv) return (ret); } +#endif /* HAVE_ZPL */ /* * zfs unmount -a @@ -3871,7 +3826,11 @@ unshare_unmount(int op, int argc, char **argv) static int zfs_do_unmount(int argc, char **argv) { +#ifdef HAVE_ZPL return (unshare_unmount(OP_MOUNT, argc, argv)); +#else + return ENOSYS; +#endif /* HAVE_ZPL */ } /* @@ -3883,7 +3842,11 @@ zfs_do_unmount(int argc, char **argv) static int zfs_do_unshare(int argc, char **argv) { +#ifdef HAVE_ZPL return (unshare_unmount(OP_SHARE, argc, argv)); +#else + return ENOSYS; +#endif /* HAVE_ZPL */ } /* ARGSUSED */ @@ -3899,6 +3862,7 @@ zfs_do_python(int argc, char **argv) * Called when invoked as /etc/fs/zfs/mount. Do the mount if the mountpoint is * 'legacy'. Otherwise, complain that use should be using 'zfs mount'. */ +#ifdef HAVE_ZPL static int manual_mount(int argc, char **argv) { @@ -4029,6 +3993,7 @@ manual_unmount(int argc, char **argv) return (unshare_unmount_path(OP_MOUNT, argv[0], flags, B_TRUE)); } +#endif /* HAVE_ZPL */ static int find_command_idx(char *command, int *idx) @@ -4047,12 +4012,89 @@ find_command_idx(char *command, int *idx) return (1); } +static int +zfs_do_diff(int argc, char **argv) +{ + zfs_handle_t *zhp; + int flags = 0; + char *tosnap = NULL; + char *fromsnap = NULL; + char *atp, *copy; + int err; + int c; + + while ((c = getopt(argc, argv, "FHt")) != -1) { + switch (c) { + case 'F': + flags |= ZFS_DIFF_CLASSIFY; + break; + case 'H': + flags |= ZFS_DIFF_PARSEABLE; + break; + case 't': + flags |= ZFS_DIFF_TIMESTAMP; + break; + default: + (void) fprintf(stderr, + gettext("invalid option '%c'\n"), optopt); + usage(B_FALSE); + } + } + + argc -= optind; + argv += optind; + + if (argc < 1) { + (void) fprintf(stderr, + gettext("must provide at least one snapshot name\n")); + usage(B_FALSE); + } + + if (argc > 2) { + (void) fprintf(stderr, gettext("too many arguments\n")); + usage(B_FALSE); + } + + fromsnap = argv[0]; + tosnap = (argc == 2) ? argv[1] : NULL; + + copy = NULL; + if (*fromsnap != '@') + copy = strdup(fromsnap); + else if (tosnap) + copy = strdup(tosnap); + if (copy == NULL) + usage(B_FALSE); + + if ((atp = strchr(copy, '@'))) + *atp = '\0'; + + if ((zhp = zfs_open(g_zfs, copy, ZFS_TYPE_FILESYSTEM)) == NULL) + return (1); + + free(copy); + + /* + * Ignore SIGPIPE so that the library can give us + * information on any failure + */ + (void) sigignore(SIGPIPE); + + err = zfs_show_diffs(zhp, STDOUT_FILENO, fromsnap, tosnap, flags); + + zfs_close(zhp); + + return (err != 0); +} + int main(int argc, char **argv) { int ret; - int i; + int i = 0; +#ifdef HAVE_ZPL char *progname; +#endif char *cmdname; (void) setlocale(LC_ALL, ""); @@ -4060,23 +4102,13 @@ main(int argc, char **argv) opterr = 0; - if ((g_zfs = libzfs_init()) == NULL) { - (void) fprintf(stderr, gettext("internal error: failed to " - "initialize ZFS library\n")); - return (1); - } - - zpool_set_history_str("zfs", argc, argv, history_str); - verify(zpool_stage_history(g_zfs, history_str) == 0); - - libzfs_print_on_error(g_zfs, B_TRUE); - if ((mnttab_file = fopen(MNTTAB, "r")) == NULL) { (void) fprintf(stderr, gettext("internal error: unable to " "open %s\n"), MNTTAB); return (1); } +#ifdef HAVE_ZPL /* * This command also doubles as the /etc/fs mount and unmount program. * Determine if we should take this behavior based on argv[0]. @@ -4087,6 +4119,9 @@ main(int argc, char **argv) } else if (strcmp(progname, "umount") == 0) { ret = manual_unmount(argc, argv); } else { +#else + { +#endif /* HAVE_ZPL */ /* * Make sure the user has specified some command. */ @@ -4112,9 +4147,18 @@ main(int argc, char **argv) /* * Special case '-?' */ - if (strcmp(cmdname, "-?") == 0) + if ((strcmp(cmdname, "-?") == 0) || + (strcmp(cmdname, "--help") == 0)) usage(B_TRUE); + if ((g_zfs = libzfs_init()) == NULL) + return (1); + + zpool_set_history_str("zfs", argc, argv, history_str); + verify(zpool_stage_history(g_zfs, history_str) == 0); + + libzfs_print_on_error(g_zfs, B_TRUE); + /* * Run the appropriate command. */ @@ -4130,6 +4174,7 @@ main(int argc, char **argv) (void) fprintf(stderr, gettext("unrecognized " "command '%s'\n"), cmdname); usage(B_FALSE); + ret = 1; } libzfs_mnttab_cache(g_zfs, B_FALSE); }