changeset 526:e50ea2fd4b66

common.subr: Implement check_zfs_naming() to check for valid ZFS names
author Franz Glasner <fzglas.hg@dom66.de>
date Wed, 04 Sep 2024 11:15:29 +0200
parents 2c31b1d4bd66
children b7d60802b25f
files share/local-bsdtools/common.subr
diffstat 1 files changed, 51 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/share/local-bsdtools/common.subr	Wed Sep 04 10:36:24 2024 +0200
+++ b/share/local-bsdtools/common.subr	Wed Sep 04 11:15:29 2024 +0200
@@ -350,3 +350,54 @@
     _fstab="$(mount -p | awk -v pa1="^${_directory}\$" -v pa2="^${_directory}/" '($2 ~ pa1) || ($2 ~ pa2 ) { print; }' | sort -k3)"
     echo "${_fstab}"
 }
+
+
+#:
+#: Check the validity of ZFS dataset names.
+#:
+#: See: ZFS Component Naming Requirements
+#: - https://docs.oracle.com/cd/E26505_01/html/E37384/gbcpt.html
+#: - https://illumos.org/books/zfs-admin/zfsover-1.html#gbcpt
+#:
+#: But it seems that in OpenZFS a space character is also allowed in
+#: name components; see https://github.com/openzfs/zfs/issues/439:
+#: It is in zfs_namecheck.c:valid_char() line #55; its the last
+#: character comparison.
+#:
+#: In OpenZFS pool names allow also the colon.
+#:
+#: Also there is no difference between "starting with" and other
+#: "containing" (with the exception of pools starting with a alpha
+#: character.
+#:
+#: Source code: https://iris.cs.tu-dortmund.de/freebsd-lockdoc/lockdoc-v13.0-0.1/source/sys/contrib/openzfs/module/zcommon/zfs_namecheck.c
+#:
+#: Args:
+#:   $1 (str): The name of the dataset.
+#:   $2 (bool, optional): If this evals to yes/on/1 then strict checking is
+#:                        done, otherwise the OpenZFS implementation is
+#:                        followed.
+#:
+#: Returns:
+#:   int
+#:     0 (truish) if it is a valid name,
+#:     1 (falsy) if not.
+#:
+#: We never check for special pool names (such as ``mirror``, ``raidz``,
+#: ``c0`` to ``c9`` et al.) because we do not create any pools.
+#:
+#: That also means that proper quoting with double quotes is enough to
+#: handle all sorts of ZFS names.
+#:
+check_zfs_naming() {
+    local _strict
+
+    _strict="${2-}"
+    if checkyes _strict; then
+        # Oracle docs
+        printf "%s" "$1" | LC_ALL=C GREP_OPTIONS="" /usr/bin/egrep -q '^[A-Za-z][-A-Za-z0-9_.]*(/[A-Za-z0-9][-A-Za-z0-9:_.]*)*(@[A-Za-z0-9][-A-Za-z0-9:_.]*)?$'
+    else
+        # OpenZFS
+        printf "%s" "$1" | LC_ALL=C GREP_OPTIONS="" /usr/bin/egrep -q '^[A-Za-z][-A-Za-z0-9:_. ]*(/[-A-Za-z0-9:_. ]+)*(@[-A-Za-z0-9:_. ]+)?$'
+    fi
+}