From aeacdefedc31b498cfccc0026b83be0bab197a3b Mon Sep 17 00:00:00 2001 From: George Melikov Date: Fri, 27 Jan 2017 01:42:15 +0300 Subject: OpenZFS 7386 - zfs get does not work properly with bookmarks Authored by: Marcel Telka Reviewed by: Simon Klinkert Reviewed by: Paul Dagnelie Approved by: Matthew Ahrens Reviewed-by: Brian Behlendorf Ported-by: George Melikov OpenZFS-issue: https://www.illumos.org/issues/7386 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/edb901a Closes #5666 --- module/zcommon/zfs_namecheck.c | 93 ++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 44 deletions(-) (limited to 'module/zcommon') diff --git a/module/zcommon/zfs_namecheck.c b/module/zcommon/zfs_namecheck.c index b58071bed..f9c20896d 100644 --- a/module/zcommon/zfs_namecheck.c +++ b/module/zcommon/zfs_namecheck.c @@ -120,9 +120,9 @@ permset_namecheck(const char *path, namecheck_err_t *why, char *what) } /* - * Dataset names must be of the following form: + * Entity names must be of the following form: * - * [component][/]*[component][@component] + * [component/]*[component][(@|#)component]? * * Where each component is made up of alphanumeric characters plus the following * characters: @@ -133,10 +133,10 @@ permset_namecheck(const char *path, namecheck_err_t *why, char *what) * names for temporary clones (for online recv). */ int -dataset_namecheck(const char *path, namecheck_err_t *why, char *what) +entity_namecheck(const char *path, namecheck_err_t *why, char *what) { - const char *loc, *end; - int found_snapshot; + const char *start, *end, *loc; + int found_delim; /* * Make sure the name is not too long. @@ -160,12 +160,13 @@ dataset_namecheck(const char *path, namecheck_err_t *why, char *what) return (-1); } - loc = path; - found_snapshot = 0; + start = path; + found_delim = 0; for (;;) { /* Find the end of this component */ - end = loc; - while (*end != '/' && *end != '@' && *end != '\0') + end = start; + while (*end != '/' && *end != '@' && *end != '#' && + *end != '\0') end++; if (*end == '\0' && end[-1] == '/') { @@ -175,25 +176,8 @@ dataset_namecheck(const char *path, namecheck_err_t *why, char *what) return (-1); } - /* Zero-length components are not allowed */ - if (loc == end) { - if (why) { - /* - * Make sure this is really a zero-length - * component and not a '@@'. - */ - if (*end == '@' && found_snapshot) { - *why = NAME_ERR_MULTIPLE_AT; - } else { - *why = NAME_ERR_EMPTY_COMPONENT; - } - } - - return (-1); - } - /* Validate the contents of this component */ - while (loc != end) { + for (loc = start; loc != end; loc++) { if (!valid_char(*loc) && *loc != '%') { if (why) { *why = NAME_ERR_INVALCHAR; @@ -201,43 +185,64 @@ dataset_namecheck(const char *path, namecheck_err_t *why, char *what) } return (-1); } - loc++; } - /* If we've reached the end of the string, we're OK */ - if (*end == '\0') - return (0); - - if (*end == '@') { - /* - * If we've found an @ symbol, indicate that we're in - * the snapshot component, and report a second '@' - * character as an error. - */ - if (found_snapshot) { + /* Snapshot or bookmark delimiter found */ + if (*end == '@' || *end == '#') { + /* Multiple delimiters are not allowed */ + if (found_delim != 0) { if (why) - *why = NAME_ERR_MULTIPLE_AT; + *why = NAME_ERR_MULTIPLE_DELIMITERS; return (-1); } - found_snapshot = 1; + found_delim = 1; } + /* Zero-length components are not allowed */ + if (start == end) { + if (why) + *why = NAME_ERR_EMPTY_COMPONENT; + return (-1); + } + + /* If we've reached the end of the string, we're OK */ + if (*end == '\0') + return (0); + /* - * If there is a '/' in a snapshot name + * If there is a '/' in a snapshot or bookmark name * then report an error */ - if (*end == '/' && found_snapshot) { + if (*end == '/' && found_delim != 0) { if (why) *why = NAME_ERR_TRAILING_SLASH; return (-1); } /* Update to the next component */ - loc = end + 1; + start = end + 1; } } +/* + * Dataset is any entity, except bookmark + */ +int +dataset_namecheck(const char *path, namecheck_err_t *why, char *what) +{ + int ret = entity_namecheck(path, why, what); + + if (ret == 0 && strchr(path, '#') != NULL) { + if (why != NULL) { + *why = NAME_ERR_INVALCHAR; + *what = '#'; + } + return (-1); + } + + return (ret); +} /* * mountpoint names must be of the following form: -- cgit v1.2.3