summaryrefslogtreecommitdiff
path: root/usr/src/lib/libscf/common/lowlevel.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libscf/common/lowlevel.c')
-rw-r--r--usr/src/lib/libscf/common/lowlevel.c132
1 files changed, 77 insertions, 55 deletions
diff --git a/usr/src/lib/libscf/common/lowlevel.c b/usr/src/lib/libscf/common/lowlevel.c
index eb0d29b236..536fab236e 100644
--- a/usr/src/lib/libscf/common/lowlevel.c
+++ b/usr/src/lib/libscf/common/lowlevel.c
@@ -24,6 +24,7 @@
* Copyright 2013, Joyent, Inc. All rights reserved.
* Copyright 2016 RackTop Systems.
* Copyright (c) 2016 by Delphix. All rights reserved.
+ * Copyright 2017 OmniOS Community Edition (OmniOSce) Association.
*/
/*
@@ -6274,6 +6275,42 @@ scf_pattern_match(scf_matchkey_t **htable, char *fmri, const char *legacy,
}
/*
+ * Construct an error message from a provided format string and include all
+ * of the matched FMRIs.
+ */
+static char *
+scf_multiple_match_error(scf_pattern_t *pattern, const char *format)
+{
+ scf_match_t *match;
+ size_t len, off;
+ char *msg;
+
+ /*
+ * Note that strlen(format) includes the length of '%s', which
+ * accounts for the terminating null byte.
+ */
+ assert(strstr(format, "%s") != NULL);
+ len = strlen(format) + strlen(pattern->sp_arg);
+ for (match = pattern->sp_matches; match != NULL;
+ match = match->sm_next)
+ len += strlen(match->sm_key->sk_fmri) + 2;
+
+ if ((msg = malloc(len)) == NULL)
+ return (NULL);
+
+ (void) snprintf(msg, len, format, pattern->sp_arg);
+ off = strlen(msg);
+ for (match = pattern->sp_matches; match != NULL;
+ match = match->sm_next) {
+ assert(off < len);
+ off += snprintf(msg + off, len - off, "\t%s\n",
+ match->sm_key->sk_fmri);
+ }
+
+ return (msg);
+}
+
+/*
* Fails with _INVALID_ARGUMENT, _HANDLE_DESTROYED, _INTERNAL (bad server
* response or id in use), _NO_MEMORY, _HANDLE_MISMATCH, _CONSTRAINT_VIOLATED,
* _NOT_FOUND, _NOT_BOUND, _CONNECTION_BROKEN, _NOT_SET, _DELETED,
@@ -6301,8 +6338,6 @@ scf_walk_fmri(scf_handle_t *h, int argc, char **argv, int flags,
ssize_t max_name_length;
char *pgname = NULL;
scf_walkinfo_t info;
- boolean_t partial_fmri = B_FALSE;
- boolean_t wildcard_fmri = B_FALSE;
#ifndef NDEBUG
if (flags & SCF_WALK_EXPLICIT)
@@ -6510,7 +6545,6 @@ scf_walk_fmri(scf_handle_t *h, int argc, char **argv, int flags,
goto error;
}
pattern[i].sp_type = PATTERN_EXACT;
- partial_fmri = B_TRUE; /* we just iterated all instances */
continue;
@@ -6535,7 +6569,6 @@ badfmri:
* Prepend svc:/ to patterns which don't begin with * or
* svc: or lrc:.
*/
- wildcard_fmri = B_TRUE;
pattern[i].sp_type = PATTERN_GLOB;
if (argv[i][0] == '*' ||
(strlen(argv[i]) >= 4 && argv[i][3] == ':'))
@@ -6548,7 +6581,6 @@ badfmri:
argv[i]);
}
} else {
- partial_fmri = B_TRUE;
pattern[i].sp_type = PATTERN_PARTIAL;
pattern[i].sp_arg = strdup(argv[i]);
}
@@ -6789,44 +6821,55 @@ nolegacy:
*err = UU_EXIT_FATAL;
} else if (!(flags & SCF_WALK_MULTIPLE) &&
pattern[i].sp_matchcount > 1) {
- size_t len, off;
char *msg;
- /*
- * Construct a message with all possible FMRIs before
- * passing off to error handling function.
- *
- * Note that strlen(scf_get_msg(...)) includes the
- * length of '%s', which accounts for the terminating
- * null byte.
- */
- len = strlen(scf_get_msg(SCF_MSG_PATTERN_MULTIMATCH)) +
- strlen(pattern[i].sp_arg);
- for (match = pattern[i].sp_matches; match != NULL;
- match = match->sm_next) {
- len += strlen(match->sm_key->sk_fmri) + 2;
- }
- if ((msg = malloc(len)) == NULL) {
+ msg = scf_multiple_match_error(&pattern[i],
+ scf_get_msg(SCF_MSG_PATTERN_MULTIMATCH));
+
+ if (msg == NULL) {
ret = SCF_ERROR_NO_MEMORY;
goto error;
}
- /* LINTED - format argument */
- (void) snprintf(msg, len,
- scf_get_msg(SCF_MSG_PATTERN_MULTIMATCH),
- pattern[i].sp_arg);
- off = strlen(msg);
- for (match = pattern[i].sp_matches; match != NULL;
- match = match->sm_next) {
- off += snprintf(msg + off, len - off, "\t%s\n",
- match->sm_key->sk_fmri);
+ errfunc(msg);
+
+ if (err != NULL)
+ *err = UU_EXIT_FATAL;
+
+ free(msg);
+
+ /*
+ * Set matchcount to 0 so the callback is not
+ * performed for this pattern.
+ */
+ pattern[i].sp_matchcount = 0;
+
+ } else if ((flags & SCF_WALK_UNIPARTIAL) &&
+ pattern[i].sp_type == PATTERN_PARTIAL &&
+ pattern[i].sp_matchcount > 1) {
+ char *msg;
+
+ msg = scf_multiple_match_error(&pattern[i],
+ scf_get_msg(SCF_MSG_PATTERN_MULTIPARTIAL));
+
+ if (msg == NULL) {
+ ret = SCF_ERROR_NO_MEMORY;
+ goto error;
}
errfunc(msg);
+
if (err != NULL)
*err = UU_EXIT_FATAL;
free(msg);
+
+ /*
+ * Set matchcount to 0 so the callback is not
+ * performed for this pattern.
+ */
+ pattern[i].sp_matchcount = 0;
+
} else {
for (match = pattern[i].sp_matches; match != NULL;
match = match->sm_next) {
@@ -6837,26 +6880,6 @@ nolegacy:
}
}
- if (flags & SCF_WALK_UNIPARTIAL && info.count > 1) {
- /*
- * If the SCF_WALK_UNIPARTIAL flag was passed in and we have
- * more than one fmri, then this is an error if we matched
- * because of a partial fmri parameter, unless we also matched
- * more than one fmri because of wildcards in the parameters.
- * That is, the presence of wildcards indicates that it is ok
- * to match more than one fmri in this case.
- * For example, a parameter of 'foo' that matches more than
- * one fmri is an error, but parameters of 'foo *bar*' that
- * matches more than one is fine.
- */
- if (partial_fmri && !wildcard_fmri) {
- errfunc(scf_get_msg(SCF_MSG_PATTERN_MULTIPARTIAL));
- if (err != NULL)
- *err = UU_EXIT_FATAL;
- goto error;
- }
- }
-
/*
* Clear 'sk_seen' for all keys.
*/
@@ -6875,12 +6898,11 @@ nolegacy:
scf_matchkey_t *key;
/*
- * Ignore patterns which didn't match anything or matched too
- * many FMRIs.
+ * Ignore patterns which didn't match anything or
+ * for which the matchcount has been set to 0 due to an
+ * error detected above.
*/
- if (pattern[i].sp_matchcount == 0 ||
- (!(flags & SCF_WALK_MULTIPLE) &&
- pattern[i].sp_matchcount > 1))
+ if (pattern[i].sp_matchcount == 0)
continue;
for (match = pattern[i].sp_matches; match != NULL;