diff --git a/include/libzfs.h b/include/libzfs.h index fa05b7921b..ee1830dd2e 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -887,6 +887,7 @@ _LIBZFS_H int zfs_name_valid(const char *, zfs_type_t); _LIBZFS_H zfs_handle_t *zfs_path_to_zhandle(libzfs_handle_t *, const char *, zfs_type_t); _LIBZFS_H int zfs_parent_name(zfs_handle_t *, char *, size_t); +_LIBZFS_H boolean_t zfs_dataset_related(zfs_handle_t *, const char *); _LIBZFS_H boolean_t zfs_dataset_exists(libzfs_handle_t *, const char *, zfs_type_t); _LIBZFS_H int zfs_spa_version(zfs_handle_t *, int *); diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 11d3eb6a3c..c037811933 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -3446,6 +3446,35 @@ is_descendant(const char *ds1, const char *ds2) return (ds2[d1len] == '/' && (strncmp(ds1, ds2, d1len) == 0)); } +/* + * Is one dataset is related to another, including self-relation? + * + * Needs to handle these cases: + * Dataset 1 "a/foo" "a/foo" "a/foo" "a/foo" + * Dataset 2 "a/foo" "a/fo" "a/foobar" "a/foo/bar" + * Related? Yes. No. No. Yes. + */ +static boolean_t +dataset_related(const char *ds1, const char *ds2) +{ + /* ds1 and ds2 are identical */ + if (strcmp(ds1, ds2) == 0) + return (B_TRUE); + + /* ds2 is a descendant of ds1 */ + if (is_descendant(ds1, ds2)) + return (B_TRUE); + + /* dataset are not related. */ + return (B_FALSE); +} + +boolean_t +zfs_dataset_related(zfs_handle_t *zhp, const char *parent) +{ + return (dataset_related(parent, zfs_get_name(zhp))); +} + /* * Given a complete name, return just the portion that refers to the parent. * Will return -1 if there is no parent (path is just the name of the