/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* Copyright (c) 2013 Martin Matuska. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
- * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
*/
#include <ctype.h>
#include <fcntl.h>
#include <sys/mntent.h>
#include <sys/mount.h>
-#include <priv.h>
#include <pwd.h>
#include <grp.h>
#include <stddef.h>
return (dgettext(TEXT_DOMAIN, "snapshot"));
case ZFS_TYPE_VOLUME:
return (dgettext(TEXT_DOMAIN, "volume"));
+ case ZFS_TYPE_POOL:
+ return (dgettext(TEXT_DOMAIN, "pool"));
+ case ZFS_TYPE_BOOKMARK:
+ return (dgettext(TEXT_DOMAIN, "bookmark"));
default:
- break;
+ assert(!"unhandled zfs_type_t");
}
return (NULL);
char what;
(void) zfs_prop_get_table();
- if (dataset_namecheck(path, &why, &what) != 0) {
+ if (entity_namecheck(path, &why, &what) != 0) {
if (hdl != NULL) {
switch (why) {
case NAME_ERR_TOOLONG:
"'%c' in name"), what);
break;
- case NAME_ERR_MULTIPLE_AT:
+ case NAME_ERR_MULTIPLE_DELIMITERS:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "multiple '@' delimiters in name"));
+ "multiple '@' and/or '#' delimiters in "
+ "name"));
break;
case NAME_ERR_NOLETTER:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"reserved disk name"));
break;
+
default:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "(%d) not defined"), why);
break;
}
}
if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
if (hdl != NULL)
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "snapshot delimiter '@' in filesystem name"));
+ "snapshot delimiter '@' is not expected here"));
return (0);
}
return (0);
}
+ if (!(type & ZFS_TYPE_BOOKMARK) && strchr(path, '#') != NULL) {
+ if (hdl != NULL)
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "bookmark delimiter '#' is not expected here"));
+ return (0);
+ }
+
+ if (type == ZFS_TYPE_BOOKMARK && strchr(path, '#') == NULL) {
+ if (hdl != NULL)
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "missing '#' delimiter in bookmark name"));
+ return (0);
+ }
+
if (modifying && strchr(path, '%') != NULL) {
if (hdl != NULL)
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
{
nvlist_t *bmarks;
nvlist_t *props;
- char fsname[ZFS_MAXNAMELEN];
+ char fsname[ZFS_MAX_DATASET_NAME_LEN];
char *bmark_name;
char *pound;
int err;
return (zhp);
}
+struct zfs_open_bookmarks_cb_data {
+ const char *path;
+ zfs_handle_t *zhp;
+};
+
+static int
+zfs_open_bookmarks_cb(zfs_handle_t *zhp, void *data)
+{
+ struct zfs_open_bookmarks_cb_data *dp = data;
+
+ /*
+ * Is it the one we are looking for?
+ */
+ if (strcmp(dp->path, zfs_get_name(zhp)) == 0) {
+ /*
+ * We found it. Save it and let the caller know we are done.
+ */
+ dp->zhp = zhp;
+ return (EEXIST);
+ }
+
+ /*
+ * Not found. Close the handle and ask for another one.
+ */
+ zfs_close(zhp);
+ return (0);
+}
+
/*
- * Opens the given snapshot, filesystem, or volume. The 'types'
+ * Opens the given snapshot, bookmark, filesystem, or volume. The 'types'
* argument is a mask of acceptable types. The function will print an
* appropriate error message and return NULL if it can't be opened.
*/
{
zfs_handle_t *zhp;
char errbuf[1024];
+ char *bookp;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
/*
* Validate the name before we even try to open it.
*/
- if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "invalid dataset name"));
+ if (!zfs_validate_name(hdl, path, types, B_FALSE)) {
(void) zfs_error(hdl, EZFS_INVALIDNAME, errbuf);
return (NULL);
}
/*
- * Try to get stats for the dataset, which will tell us if it exists.
+ * Bookmarks needs to be handled separately.
*/
- errno = 0;
- if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
- (void) zfs_standard_error(hdl, errno, errbuf);
- return (NULL);
+ bookp = strchr(path, '#');
+ if (bookp == NULL) {
+ /*
+ * Try to get stats for the dataset, which will tell us if it
+ * exists.
+ */
+ errno = 0;
+ if ((zhp = make_dataset_handle(hdl, path)) == NULL) {
+ (void) zfs_standard_error(hdl, errno, errbuf);
+ return (NULL);
+ }
+ } else {
+ char dsname[ZFS_MAX_DATASET_NAME_LEN];
+ zfs_handle_t *pzhp;
+ struct zfs_open_bookmarks_cb_data cb_data = {path, NULL};
+
+ /*
+ * We need to cut out '#' and everything after '#'
+ * to get the parent dataset name only.
+ */
+ assert(bookp - path < sizeof (dsname));
+ (void) strncpy(dsname, path, bookp - path);
+ dsname[bookp - path] = '\0';
+
+ /*
+ * Create handle for the parent dataset.
+ */
+ errno = 0;
+ if ((pzhp = make_dataset_handle(hdl, dsname)) == NULL) {
+ (void) zfs_standard_error(hdl, errno, errbuf);
+ return (NULL);
+ }
+
+ /*
+ * Iterate bookmarks to find the right one.
+ */
+ errno = 0;
+ if ((zfs_iter_bookmarks(pzhp, zfs_open_bookmarks_cb,
+ &cb_data) == 0) && (cb_data.zhp == NULL)) {
+ (void) zfs_error(hdl, EZFS_NOENT, errbuf);
+ zfs_close(pzhp);
+ return (NULL);
+ }
+ if (cb_data.zhp == NULL) {
+ (void) zfs_standard_error(hdl, errno, errbuf);
+ zfs_close(pzhp);
+ return (NULL);
+ }
+ zhp = cb_data.zhp;
+
+ /*
+ * Cleanup.
+ */
+ zfs_close(pzhp);
}
if (!(types & zhp->zfs_type)) {
static int
libzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
{
- const mnttab_node_t *mtn1 = arg1;
- const mnttab_node_t *mtn2 = arg2;
+ const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;
+ const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;
int rv;
rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
- if (rv == 0)
- return (0);
- return (rv > 0 ? 1 : -1);
+ return (AVL_ISIGN(rv));
}
void
void *cookie = NULL;
mnttab_node_t *mtn;
- while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie))) {
+ while ((mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie))
+ != NULL) {
free(mtn->mtn_mt.mnt_special);
free(mtn->mtn_mt.mnt_mountp);
free(mtn->mtn_mt.mnt_fstype);
mnttab_node_t *ret;
find.mtn_mt.mnt_special = (char *)fsname;
- if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))) {
+ if ((ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL))
+ != NULL) {
avl_remove(&hdl->libzfs_mnttab_cache, ret);
free(ret->mtn_mt.mnt_special);
free(ret->mtn_mt.mnt_mountp);
}
if (uqtype != ZFS_PROP_USERQUOTA &&
- uqtype != ZFS_PROP_GROUPQUOTA) {
+ uqtype != ZFS_PROP_GROUPQUOTA &&
+ uqtype != ZFS_PROP_USEROBJQUOTA &&
+ uqtype != ZFS_PROP_GROUPOBJQUOTA) {
zfs_error_aux(hdl,
dgettext(TEXT_DOMAIN, "'%s' is readonly"),
propname);
*/
if (intval < SPA_MINBLOCKSIZE ||
intval > maxbs || !ISP2(intval)) {
- zfs_nicenum(maxbs, buf, sizeof (buf));
+ zfs_nicebytes(maxbs, buf, sizeof (buf));
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' must be power of 2 from 512B "
"to %s"), propname, buf);
"component of '%s' is too long"),
propname);
break;
+
default:
+ zfs_error_aux(hdl,
+ dgettext(TEXT_DOMAIN,
+ "(%d) not defined"),
+ why);
break;
}
(void) zfs_error(hdl, EZFS_BADPROP, errbuf);
}
break;
+
case ZFS_PROP_UTF8ONLY:
chosen_utf = (int)intval;
break;
+
case ZFS_PROP_NORMALIZE:
chosen_normal = (int)intval;
break;
+
default:
break;
}
case ZFS_PROP_VOLSIZE:
if (intval % blocksize != 0) {
- zfs_nicenum(blocksize, buf,
+ zfs_nicebytes(blocksize, buf,
sizeof (buf));
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' must be a multiple of "
goto error;
}
break;
+
default:
break;
}
case ERANGE:
if (prop == ZFS_PROP_COMPRESSION ||
+ prop == ZFS_PROP_DNODESIZE ||
prop == ZFS_PROP_RECORDSIZE) {
(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"property setting is not allowed on "
"bootable datasets"));
(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
+ } else if (prop == ZFS_PROP_CHECKSUM ||
+ prop == ZFS_PROP_DEDUP) {
+ (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "property setting is not allowed on "
+ "root pools"));
+ (void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
} else {
(void) zfs_standard_error(hdl, err, errbuf);
}
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
nvlist_t *nvl;
- int nvl_len;
+ int nvl_len = 0;
int added_resv = 0;
zfs_prop_t prop = 0;
nvpair_t *elem;
* Check how many properties we're setting and allocate an array to
* store changelist pointers for postfix().
*/
- nvl_len = 0;
for (elem = nvlist_next_nvpair(nvl, NULL);
elem != NULL;
elem = nvlist_next_nvpair(nvl, elem))
* its canmount property to 'on' or 'noauto'. We only use
* the changelist logic to unmount when setting canmount=off.
*/
- if (!(prop == ZFS_PROP_CANMOUNT &&
- fnvpair_value_uint64(elem) != ZFS_CANMOUNT_OFF)) {
+ if (prop != ZFS_PROP_CANMOUNT ||
+ (fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF &&
+ zfs_is_mounted(zhp, NULL))) {
cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
if (cls[cl_idx] == NULL)
goto error;
return (value);
}
-static char *
+static const char *
getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
{
nvlist_t *nv;
- char *value;
+ const char *value;
*source = NULL;
if (nvlist_lookup_nvlist(zhp->zfs_props,
zfs_prop_to_name(prop), &nv) == 0) {
- verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
+ value = fnvlist_lookup_string(nv, ZPROP_VALUE);
(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
} else {
verify(!zhp->zfs_props_table ||
zhp->zfs_props_table[prop] == B_TRUE);
- if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
- value = "";
+ value = zfs_prop_default_string(prop);
*source = "";
}
* zfs_prop_get_int() are built using this interface.
*
* Certain properties can be overridden using 'mount -o'. In this case, scan
- * the contents of the /etc/mtab entry, searching for the appropriate options.
- * If they differ from the on-disk values, report the current values and mark
- * the source "temporary".
+ * the contents of the /proc/self/mounts entry, searching for the
+ * appropriate options. If they differ from the on-disk values, report the
+ * current values and mark the source "temporary".
*/
static int
get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src,
* the property is valid for the snapshot's head dataset type.
*/
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT &&
- !zfs_prop_valid_for_type(prop, zhp->zfs_head_type, B_TRUE)) {
- *val = zfs_prop_default_numeric(prop);
- return (-1);
+ !zfs_prop_valid_for_type(prop, zhp->zfs_head_type, B_TRUE)) {
+ *val = zfs_prop_default_numeric(prop);
+ return (-1);
}
switch (prop) {
mntopt_on = MNTOPT_NBMAND;
mntopt_off = MNTOPT_NONBMAND;
break;
+
default:
break;
}
/*
* Because looking up the mount options is potentially expensive
- * (iterating over all of /etc/mtab), we defer its calculation until
- * we're looking up a property which requires its presence.
+ * (iterating over all of /proc/self/mounts), we defer its
+ * calculation until we're looking up a property which requires
+ * its presence.
*/
if (!zhp->zfs_mntcheck &&
(mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) {
/*
* If we tried to use a default value for a
* readonly property, it means that it was not
- * present.
+ * present. Note this only applies to "truly"
+ * readonly properties, not set-once properties
+ * like volblocksize.
*/
if (zfs_prop_readonly(prop) &&
+ !zfs_prop_setonce(prop) &&
*source != NULL && (*source)[0] == '\0') {
*source = NULL;
+ return (-1);
}
break;
uint64_t numclones;
nvlist_t *value;
const char *origin;
- char buf[ZFS_MAXNAMELEN];
+ char buf[ZFS_MAX_DATASET_NAME_LEN];
};
int
if (gca.numclones != 0) {
zfs_handle_t *root;
- char pool[ZFS_MAXNAMELEN];
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
char *cp = pool;
/* get the pool name */
(void) strsep(&cp, "/@");
root = zfs_open(zhp->zfs_hdl, pool,
ZFS_TYPE_FILESYSTEM);
+ if (root == NULL) {
+ nvlist_free(nv);
+ nvlist_free(value);
+ return (NULL);
+ }
(void) get_clones_cb(root, &gca);
}
{
char *source = NULL;
uint64_t val;
- char *str;
+ const char *str;
const char *strval;
boolean_t received = zfs_is_recvd_props_mode(zhp);
strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
&t) == 0)
(void) snprintf(propbuf, proplen, "%llu",
- (u_longlong_t) val);
+ (u_longlong_t)val);
}
break;
}
if ((zpool_get_prop(zhp->zpool_hdl,
- ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) ||
- (strcmp(root, "-") == 0))
+ ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL,
+ B_FALSE)) || (strcmp(root, "-") == 0))
root[0] = '\0';
/*
* Special case an alternate root of '/'. This will
break;
case ZFS_PROP_ORIGIN:
- (void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
- proplen);
- /*
- * If there is no parent at all, return failure to indicate that
- * it doesn't apply to this dataset.
- */
- if (propbuf[0] == '\0')
+ str = getprop_string(zhp, prop, &source);
+ if (str == NULL)
return (-1);
+ (void) strlcpy(propbuf, str, proplen);
break;
case ZFS_PROP_CLONES:
(void) snprintf(propbuf, proplen, "%llu",
(u_longlong_t)val);
else
- zfs_nicenum(val, propbuf, proplen);
+ zfs_nicebytes(val, propbuf, proplen);
}
break;
break;
case ZFS_PROP_GUID:
+ case ZFS_PROP_CREATETXG:
/*
* GUIDs are stored as numbers, but they are identifiers.
* We don't want them to be pretty printed, because pretty
(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
break;
+ case ZFS_PROP_REFERENCED:
+ case ZFS_PROP_AVAILABLE:
+ case ZFS_PROP_USED:
+ case ZFS_PROP_USEDSNAP:
+ case ZFS_PROP_USEDDS:
+ case ZFS_PROP_USEDREFRESERV:
+ case ZFS_PROP_USEDCHILD:
+ if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
+ return (-1);
+ if (literal)
+ (void) snprintf(propbuf, proplen, "%llu",
+ (u_longlong_t)val);
+ else
+ zfs_nicebytes(val, propbuf, proplen);
+ break;
+
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
break;
case PROP_TYPE_STRING:
- (void) strlcpy(propbuf,
- getprop_string(zhp, prop, &source), proplen);
+ str = getprop_string(zhp, prop, &source);
+ if (str == NULL)
+ return (-1);
+ (void) strlcpy(propbuf, str, proplen);
break;
case PROP_TYPE_INDEX:
zfs_prop_get_int(zfs_handle_t *zhp, zfs_prop_t prop)
{
char *source;
- uint64_t val;
+ uint64_t val = 0;
(void) get_numeric_property(zhp, prop, NULL, &source, &val);
return (EINVAL);
*typep = type;
- isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED);
- isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED);
+ isuser = (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_USERUSED ||
+ type == ZFS_PROP_USEROBJQUOTA ||
+ type == ZFS_PROP_USEROBJUSED);
+ isgroup = (type == ZFS_PROP_GROUPQUOTA || type == ZFS_PROP_GROUPUSED ||
+ type == ZFS_PROP_GROUPOBJQUOTA ||
+ type == ZFS_PROP_GROUPOBJUSED);
cp = strchr(propname, '@') + 1;
(void) snprintf(propbuf, proplen, "%llu",
(u_longlong_t)propvalue);
} else if (propvalue == 0 &&
- (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA)) {
+ (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA ||
+ type == ZFS_PROP_USEROBJQUOTA || type == ZFS_PROP_GROUPOBJQUOTA)) {
(void) strlcpy(propbuf, "none", proplen);
+ } else if (type == ZFS_PROP_USERQUOTA || type == ZFS_PROP_GROUPQUOTA ||
+ type == ZFS_PROP_USERUSED || type == ZFS_PROP_GROUPUSED) {
+ zfs_nicebytes(propvalue, propbuf, proplen);
} else {
zfs_nicenum(propvalue, propbuf, proplen);
}
(void) snprintf(propbuf, proplen, "%llu",
(u_longlong_t)propvalue);
} else {
- zfs_nicenum(propvalue, propbuf, proplen);
+ zfs_nicebytes(propvalue, propbuf, proplen);
}
return (0);
return (zhp->zfs_name);
}
+/*
+ * Returns the name of the parent pool for the given zfs handle.
+ */
+const char *
+zfs_get_pool_name(const zfs_handle_t *zhp)
+{
+ return (zhp->zpool_hdl->zpool_name);
+}
+
/*
* Returns the type of the given zfs handle.
*/
boolean_t accept_ancestor, int *prefixlen)
{
zfs_cmd_t zc = {"\0"};
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
char *slash;
zfs_handle_t *zhp;
char errbuf[1024];
* up to the prefixlen-long one.
*/
for (cp = target + prefixlen + 1;
- (cp = strchr(cp, '/')); *cp = '/', cp++) {
+ (cp = strchr(cp, '/')) != NULL; *cp = '/', cp++) {
*cp = '\0';
uint64_t blocksize = zfs_prop_default_numeric(ZFS_PROP_VOLBLOCKSIZE);
char errbuf[1024];
uint64_t zoned;
- dmu_objset_type_t ost;
+ enum lzc_dataset_type ost;
+ zpool_handle_t *zpool_handle;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot create '%s'"), path);
}
if (type == ZFS_TYPE_VOLUME)
- ost = DMU_OST_ZVOL;
+ ost = LZC_DATSET_TYPE_ZVOL;
else
- ost = DMU_OST_ZFS;
+ ost = LZC_DATSET_TYPE_ZFS;
/* open zpool handle for prop validation */
- char pool_path[MAXNAMELEN];
+ char pool_path[ZFS_MAX_DATASET_NAME_LEN];
(void) strlcpy(pool_path, path, sizeof (pool_path));
/* truncate pool_path at first slash */
if (p != NULL)
*p = '\0';
- zpool_handle_t *zpool_handle = zpool_open(hdl, pool_path);
+ if ((zpool_handle = zpool_open(hdl, pool_path)) == NULL)
+ return (-1);
if (props && (props = zfs_valid_proplist(hdl, type, props,
zoned, NULL, zpool_handle, errbuf)) == 0) {
/* check for failure */
if (ret != 0) {
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
(void) parent_name(path, parent, sizeof (parent));
switch (errno) {
zfs_check_snap_cb(zfs_handle_t *zhp, void *arg)
{
struct destroydata *dd = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
(void) snprintf(name, sizeof (name),
int
zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
{
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
int ret;
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
{
snapdata_t *sd = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) == 0) {
char errbuf[1024];
nvpair_t *elem;
nvlist_t *errors;
+ zpool_handle_t *zpool_hdl;
+ char pool[ZFS_MAX_DATASET_NAME_LEN];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot create snapshots "));
* get pool handle for prop validation. assumes all snaps are in the
* same pool, as does lzc_snapshot (below).
*/
- char pool[MAXNAMELEN];
elem = nvlist_next_nvpair(snaps, NULL);
(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
pool[strcspn(pool, "/@")] = '\0';
- zpool_handle_t *zpool_hdl = zpool_open(hdl, pool);
+ zpool_hdl = zpool_open(hdl, pool);
+ if (zpool_hdl == NULL)
+ return (-1);
if (props != NULL &&
(props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
{
int ret;
snapdata_t sd = { 0 };
- char fsname[ZFS_MAXNAMELEN];
+ char fsname[ZFS_MAX_DATASET_NAME_LEN];
char *cp;
zfs_handle_t *zhp;
char errbuf[1024];
zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive,
boolean_t force_unmount)
{
- int ret;
+ int ret = 0;
zfs_cmd_t zc = {"\0"};
char *delim;
prop_changelist_t *cl = NULL;
zfs_handle_t *zhrp = NULL;
char *parentname = NULL;
- char parent[ZFS_MAXNAMELEN];
+ char parent[ZFS_MAX_DATASET_NAME_LEN];
libzfs_handle_t *hdl = zhp->zfs_hdl;
char errbuf[1024];
zc.zc_nvlist_dst_size = sizeof (buf);
if (zfs_ioctl(hdl, ZFS_IOC_USERSPACE_MANY, &zc) != 0) {
- char errbuf[ZFS_MAXNAMELEN + 32];
+ char errbuf[1024];
+
+ if ((errno == ENOTSUP &&
+ (type == ZFS_PROP_USEROBJUSED ||
+ type == ZFS_PROP_GROUPOBJUSED ||
+ type == ZFS_PROP_USEROBJQUOTA ||
+ type == ZFS_PROP_GROUPOBJQUOTA)))
+ break;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN,
zfs_hold_one(zfs_handle_t *zhp, void *arg)
{
struct holdarg *ha = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
(void) snprintf(name, sizeof (name),
zfs_release_one(zfs_handle_t *zhp, void *arg)
{
struct holdarg *ha = arg;
- char name[ZFS_MAXNAMELEN];
+ char name[ZFS_MAX_DATASET_NAME_LEN];
int rv = 0;
nvlist_t *existing_holds;
zc.zc_nvlist_dst_size = nvsz;
zc.zc_nvlist_dst = (uintptr_t)nvbuf;
- (void) strlcpy(zc.zc_name, zhp->zfs_name, ZFS_MAXNAMELEN);
+ (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (ioctl(hdl->libzfs_fd, ZFS_IOC_GET_FSACL, &zc) != 0) {
(void) snprintf(errbuf, sizeof (errbuf),