On Thu, Sep 05, 2024 at 15:49:38 +0200, Ján Tomko wrote:
While the parsing is still done by 1K buffers, the results
are no longer filtered during the parsing, but the whole JSON
has to live in memory at once, which was also the case before
the NSS plugin dropped its dependency on libvirt_util.
Also, the new parser might be more forgiving of missing elements.
Signed-off-by: Ján Tomko <jtomko(a)redhat.com>
---
tools/nss/libvirt_nss_macs.c | 278 ++++++++++-------------------------
1 file changed, 80 insertions(+), 198 deletions(-)
diff --git a/tools/nss/libvirt_nss_macs.c b/tools/nss/libvirt_nss_macs.c
index f45d149793..281865a05b 100644
--- a/tools/nss/libvirt_nss_macs.c
+++ b/tools/nss/libvirt_nss_macs.c
As in previous patch I'll trim the deletions to just se the new code:
+/**
+ * findMACsFromJSON
+ *
+ * @jobj: JSON object containing the leases
+ * @name: requested hostname
+ * @macs: returned array of MAC addresses leased to the hostname
+ * @nmacs: size of the returned array
+ */
static int
+findMACsFromJSON(json_object *jobj,
+ const char *name,
+ char ***macs,
+ size_t *nmacs)
{
size_t i;
+ int len;
+ if (!json_object_is_type(jobj, json_type_array)) {
+ ERROR("parsed JSON does not contain the leases array");
+ return -1;
}
+ len = json_object_array_length(jobj);
+ DEBUG("Found an array of length: %zu", len);
+ for (i = 0; i < len; i++) {
+ json_object *entry = NULL;
+ json_object *domain = NULL;
+ const char *domainName;
+ char **tmpMacs = NULL;
+ size_t newmacs = 0;
+ json_object *macsArray = NULL;
+ size_t j;
+
+ entry = json_object_array_get_idx(jobj, i);
+ if (!entry)
+ continue;
+ DEBUG("Processing item %zu", i);
+ domain = json_object_object_get(entry, "domain");
+ if (!domain)
+ continue;
+ domainName = json_object_get_string(domain);
+ if (!domainName)
+ continue;
+ DEBUG("Processing domain %s", domainName);
+ if (strcasecmp(domainName, name))
+ continue;
+ macsArray = json_object_object_get(entry, "macs");
+ if (!macsArray)
+ continue;
+ newmacs = json_object_array_length(macsArray);
+ DEBUG("Found %zu MAC addresses", newmacs);
+ tmpMacs = realloc(*macs, sizeof(char *) * (*nmacs + newmacs + 1));
+ if (!tmpMacs)
+ return -1;
+ *macs = tmpMacs;
+ for (j = 0; j < newmacs; j++) {
+ json_object *macobj = NULL;
+ char *macstr;
+ macobj = json_object_array_get_idx(macsArray, j);
+ macstr = strdup(json_object_get_string(macobj));
+ if (!macstr)
+ return -1;
+ (*macs)[(*nmacs)++] = macstr;
+ }
+ }
+ return 0;
}
@@ -209,66 +119,45 @@ findMACs(const char *file,
{
int fd = -1;
int ret = -1;
char line[1024];
+ json_object *jobj = NULL;
+ json_tokener *tok = NULL;
+ enum json_tokener_error jerr;
+ int jsonflags = JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8;
+ ssize_t nreadTotal = 0;
int rv;
+ size_t i;
if ((fd = open(file, O_RDONLY)) < 0) {
ERROR("Cannot open %s", file);
goto cleanup;
}
+ tok = json_tokener_new();
+ json_tokener_set_flags(tok, jsonflags);
+ do {
+ rv = read(fd, line, sizeof(line) - 1);
-1 unnecessary
if (rv < 0)
goto cleanup;
if (rv == 0)
break;
+ nreadTotal += rv;
+ jobj = json_tokener_parse_ex(tok, line, rv);
+ jerr = json_tokener_get_error(tok);
+ } while (jerr == json_tokener_continue);
+ if (nreadTotal > 0 && jerr != json_tokener_success) {
+ ERROR("Cannot parse %s: %s", file, json_tokener_error_desc(jerr));
Same problem regarding the possibility to reach this with
json_tokener_continue state as in previous patch.
goto cleanup;
}
+ ret = findMACsFromJSON(jobj, name, macs, nmacs);
cleanup:
+ json_object_put(jobj);
+ json_tokener_free(tok);
if (ret != 0) {
for (i = 0; i < *nmacs; i++) {
char *mac = (*macs)[i];
Reviewed-by: Peter Krempa <pkrempa(a)redhat.com>