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 <[email protected]>
> ---
> 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 <[email protected]>