From f476a37b3714c6c0e218814693eb623f4d77d549 Mon Sep 17 00:00:00 2001 From: QORTEC Date: Tue, 10 Oct 2023 17:07:16 -0400 Subject: [PATCH] This commit adds functions to libzfs to check if one dataset is related to another. The `related_dataset()` function checks if the second provided dataset is the same as or a child dataset of the first provided dataset. The function returns a `boolean_t` value (`B_TRUE` if related). The `zfs_related_dataset()` helper function takes a `zfs_handle_t` and checks if the provided handle is related to the provided dataset. The function returns a `boolean_t` value (`B_TRUE` if related). libzfs_dataset.c: - `related_dataset()` - `zfs_related_dataset()` libzfs.h: - `zfs_related_dataset()` Signed-off-by: QORTEC --- include/libzfs.h | 1 + lib/libzfs/libzfs_dataset.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) 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