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@xxxxxxxxxx> > --- > 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@xxxxxxxxxx>