/* * Returns true if the given dataset is mountable, false otherwise. Returns the * mountpoint in 'buf'. */ static boolean_t zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, zprop_source_t *source) { char sourceloc[ZFS_MAXNAMELEN]; zprop_source_t sourcetype; if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type)) return (B_FALSE); verify(zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, buf, buflen, &sourcetype, sourceloc, sizeof (sourceloc), B_FALSE) == 0); if (strcmp(buf, ZFS_MOUNTPOINT_NONE) == 0 || strcmp(buf, ZFS_MOUNTPOINT_LEGACY) == 0) return (B_FALSE); if (zfs_prop_get_int(zhp, ZFS_PROP_CANMOUNT) == ZFS_CANMOUNT_OFF) return (B_FALSE); if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) && getzoneid() == GLOBAL_ZONEID) return (B_FALSE); if (zfs_prop_get_int(zhp, ZFS_PROP_KEYSTATUS) == ZFS_CRYPT_KEY_UNAVAILABLE) return (B_FALSE); if (source) *source = sourcetype; return (B_TRUE); }
int zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, size_t proplen, zfs_source_t *srctype) { uint64_t value; char msg[1024], *strvalue; nvlist_t *nvp; zfs_source_t src = ZFS_SRC_NONE; (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, "cannot get property '%s'"), zpool_prop_to_name(prop)); if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, "pool must be " "upgraded to support pool properties")); return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, msg)); } if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, msg)); /* * the "name" property is special cased */ if (!zfs_prop_valid_for_type(prop, ZFS_TYPE_POOL) && prop != ZFS_PROP_NAME) return (-1); switch (prop) { case ZFS_PROP_NAME: (void) strlcpy(propbuf, zhp->zpool_name, proplen); break; case ZFS_PROP_BOOTFS: if (nvlist_lookup_nvlist(zhp->zpool_props, zpool_prop_to_name(prop), &nvp) != 0) { strvalue = (char *)zfs_prop_default_string(prop); if (strvalue == NULL) strvalue = "-"; src = ZFS_SRC_DEFAULT; } else { VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_SOURCE, &value) == 0); src = value; VERIFY(nvlist_lookup_string(nvp, ZFS_PROP_VALUE, &strvalue) == 0); if (strlen(strvalue) >= proplen) return (-1); } (void) strcpy(propbuf, strvalue); break; default: return (-1); } if (srctype) *srctype = src; return (0); }
/* * Iterate over all properties, calling back into the specified function * for each property. We will continue to iterate until we either * reach the end or the callback function something other than * ZFS_PROP_CONT. */ zfs_prop_t zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type, boolean_t show_all, boolean_t ordered) { int i,j; zfs_prop_t order[ZFS_NUM_PROPS]; for (j = 0; j < ZFS_NUM_PROPS; j++) order[j] = j; if (ordered) { qsort((void *)order, ZFS_NUM_PROPS, sizeof (zfs_prop_t), zfs_prop_compare); } for (i = 0; i < ZFS_NUM_PROPS; i++) { if (zfs_prop_valid_for_type(order[i], type) && (zfs_prop_is_visible(order[i]) || show_all)) { if (func(order[i], cb) != ZFS_PROP_CONT) return (order[i]); } } return (ZFS_PROP_CONT); }
/* * Iterate over all properties, calling back into the specified function * for each property. We will continue to iterate until we either * reach the end or the callback function something other than * ZFS_PROP_CONT. */ zfs_prop_t zfs_prop_iter_common(zfs_prop_f func, void *cb, zfs_type_t type, boolean_t show_all) { int i; for (i = 0; i < ZFS_PROP_COUNT; i++) { if (zfs_prop_valid_for_type(i, type) && (zfs_prop_is_visible(i) || show_all)) { if (func(i, cb) != ZFS_PROP_CONT) return (i); } } return (ZFS_PROP_CONT); }
/* * Sort datasets by specified columns. * * o Numeric types sort in ascending order. * o String types sort in alphabetical order. * o Types inappropriate for a row sort that row to the literal * bottom, regardless of the specified ordering. * * If no sort columns are specified, or two datasets compare equally * across all specified columns, they are sorted alphabetically by name * with snapshots grouped under their parents. */ static int zfs_sort(const void *larg, const void *rarg, void *data) { zfs_handle_t *l = ((zfs_node_t *)larg)->zn_handle; zfs_handle_t *r = ((zfs_node_t *)rarg)->zn_handle; zfs_sort_column_t *sc = (zfs_sort_column_t *)data; zfs_sort_column_t *psc; for (psc = sc; psc != NULL; psc = psc->sc_next) { char lbuf[ZFS_MAXPROPLEN], rbuf[ZFS_MAXPROPLEN]; char *lstr, *rstr; uint64_t lnum, rnum; boolean_t lvalid, rvalid; int ret = 0; /* * We group the checks below the generic code. If 'lstr' and * 'rstr' are non-NULL, then we do a string based comparison. * Otherwise, we compare 'lnum' and 'rnum'. */ lstr = rstr = NULL; if (psc->sc_prop == ZPROP_INVAL) { nvlist_t *luser, *ruser; nvlist_t *lval, *rval; luser = zfs_get_user_props(l); ruser = zfs_get_user_props(r); lvalid = (nvlist_lookup_nvlist(luser, psc->sc_user_prop, &lval) == 0); rvalid = (nvlist_lookup_nvlist(ruser, psc->sc_user_prop, &rval) == 0); if (lvalid) verify(nvlist_lookup_string(lval, ZPROP_VALUE, &lstr) == 0); if (rvalid) verify(nvlist_lookup_string(rval, ZPROP_VALUE, &rstr) == 0); } else if (psc->sc_prop == ZFS_PROP_NAME) { lvalid = rvalid = B_TRUE; (void) strlcpy(lbuf, zfs_get_name(l), sizeof(lbuf)); (void) strlcpy(rbuf, zfs_get_name(r), sizeof(rbuf)); lstr = lbuf; rstr = rbuf; } else if (zfs_prop_is_string(psc->sc_prop)) { lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf, sizeof (lbuf), NULL, NULL, 0, B_TRUE) == 0); rvalid = (zfs_prop_get(r, psc->sc_prop, rbuf, sizeof (rbuf), NULL, NULL, 0, B_TRUE) == 0); lstr = lbuf; rstr = rbuf; } else { lvalid = zfs_prop_valid_for_type(psc->sc_prop, zfs_get_type(l)); rvalid = zfs_prop_valid_for_type(psc->sc_prop, zfs_get_type(r)); if (lvalid) (void) zfs_prop_get_numeric(l, psc->sc_prop, &lnum, NULL, NULL, 0); if (rvalid) (void) zfs_prop_get_numeric(r, psc->sc_prop, &rnum, NULL, NULL, 0); } if (!lvalid && !rvalid) continue; else if (!lvalid) return (1); else if (!rvalid) return (-1); if (lstr) ret = strcmp(lstr, rstr); else if (lnum < rnum) ret = -1; else if (lnum > rnum) ret = 1; if (ret != 0) { if (psc->sc_reverse == B_TRUE) ret = (ret < 0) ? 1 : -1; return (ret); } } return (zfs_compare(larg, rarg, NULL)); }