]> git.ipfire.org Git - pakfire.git/commitdiff
json: Cleanup the JSON parsing interfaces
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 21 Jun 2025 16:16:55 +0000 (16:16 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 21 Jun 2025 16:16:55 +0000 (16:16 +0000)
We should not always require the context to have some basic logging.
Instead we can return the error as a string.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/daemon.c
src/pakfire/json.c
src/pakfire/json.h
src/pakfire/jwt.c
src/pakfire/mirrorlist.c
src/pakfire/repo.c
src/pakfire/xfer.c

index 2b562d5a3ef385bd11f48cc62f1b3ffe9bbb04cd..567ab3ab84e4efeebd46a3dd9b350c54f6c5ecf5 100644 (file)
@@ -533,14 +533,15 @@ static int pakfire_daemon_recv(struct pakfire_xfer* xfer,
        struct pakfire_daemon* daemon = data;
        struct json_object* type = NULL;
        struct json_object* m = NULL;
+       char* error = NULL;
        int r;
 
        const char* job_id = NULL;
 
        // Parse the JSON message
-       m = pakfire_json_parse(daemon->ctx, message, size);
-       if (!m) {
-               r = -errno;
+       r = pakfire_json_parse(&m, &error, message, size);
+       if (r < 0) {
+               ERROR(daemon->ctx, "Failed to parse JSON message: %s\n", error);
                goto ERROR;
        }
 
@@ -592,6 +593,8 @@ static int pakfire_daemon_recv(struct pakfire_xfer* xfer,
 ERROR:
        if (m)
                json_object_put(m);
+       if (error)
+               free(error);
 
        return r;
 }
index 0eee8228d4e49e2a4b9f93520c453493fc261f74..116e79105283758929324e11f6479053d06d4e77 100644 (file)
@@ -32,67 +32,87 @@ const char* pakfire_json_to_string(struct json_object* json) {
        return json_object_to_json_string_ext(json, flags);
 }
 
-struct json_object* pakfire_json_parse(
-               struct pakfire_ctx* ctx, const char* buffer, const size_t length) {
+int pakfire_json_parse(struct json_object** json, char** error,
+               const char* buffer, const size_t length) {
        struct json_tokener* tokener = NULL;
-       struct json_object* json = NULL;
+       struct json_object* object = NULL;
+       enum json_tokener_error e;
+       int r;
 
        // Create tokener
        tokener = json_tokener_new();
-       if (!tokener) {
-               ERROR(ctx, "Could not allocate JSON tokener: %m\n");
-               goto ERROR;
-       }
+       if (!tokener)
+               return -ENOMEM;
 
        // Parse JSON from buffer
-       json = json_tokener_parse_ex(tokener, buffer, length);
-       if (!json) {
-               enum json_tokener_error error = json_tokener_get_error(tokener);
-
-               ERROR(ctx, "JSON parsing error: %s\n", json_tokener_error_desc(error));
-               goto ERROR;
+       object = json_tokener_parse_ex(tokener, buffer, length);
+       if (!object) {
+               // Fetch the error code
+               e = json_tokener_get_error(tokener);
+
+               // Format the error string
+               if (error) {
+                       r = asprintf(error, "JSON parsing error: %s\n", json_tokener_error_desc(e));
+                       if (r < 0)
+                               goto ERROR;
+               }
+
+               // Assume that the input was invalid
+               r = -EBADMSG;
        }
 
-       // Log what we have parsed
-       DEBUG(ctx, "Parsed JSON:\n%s\n", pakfire_json_to_string(json));
+       // Return the object
+       *json = object;
+       r = 0;
 
 ERROR:
        if (tokener)
                json_tokener_free(tokener);
 
-       return json;
+       return r;
 }
 
-static struct json_object* pakfire_json_parse_file(struct pakfire_ctx* ctx, FILE* f) {
-       struct json_object* json = NULL;
+static int pakfire_json_parse_file(struct json_object** json, char** error, FILE* f) {
        char* buffer = NULL;
        size_t length = 0;
        int r;
 
        // Map everything into memory
        r = pakfire_mmap(fileno(f), &buffer, &length);
-       if (r)
+       if (r < 0)
                goto ERROR;
 
        // Parse
-       json = pakfire_json_parse(ctx, buffer, length);
+       r = pakfire_json_parse(json, error, buffer, length);
 
 ERROR:
        if (buffer)
                munmap(buffer, length);
 
-       return json;
+       return r;
 }
 
-struct json_object* pakfire_json_parse_from_file(struct pakfire_ctx* ctx, const char* path) {
-       FILE* f = fopen(path, "r");
-       if (!f)
-               return NULL;
+int pakfire_json_parse_from_file(struct json_object** json, char** error, const char* path) {
+       FILE* f = NULL;
+       int r;
+
+       // Open the file
+       f = fopen(path, "r");
+       if (!f) {
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Parse the payload
+       r = pakfire_json_parse_file(json, error, f);
+       if (r < 0)
+               goto ERROR;
 
-       struct json_object* json = pakfire_json_parse_file(ctx, f);
-       fclose(f);
+ERROR:
+       if (f)
+               fclose(f);
 
-       return json;
+       return r;
 }
 
 struct json_object* pakfire_json_new_object(void) {
index 2023ccd1fdbf2d304d6738e772bb8242c3f44205..b6a2d3ef510b2725c6c6300538475faf0037a32a 100644 (file)
 const char* pakfire_json_to_string(struct json_object* json);
 
 // Parse
-struct json_object* pakfire_json_parse(struct pakfire_ctx* ctx,
+int pakfire_json_parse(struct json_object** json, char** error,
        const char* buffer, const size_t length);
 
 // Parse from file
-struct json_object* pakfire_json_parse_from_file(struct pakfire_ctx* ctx, const char* path);
+int pakfire_json_parse_from_file(struct json_object** json, char** error, const char* path);
 
 struct json_object* pakfire_json_new_object(void);
 
index 4474104e2e704ddfff8029200b98e4eb97572554..0682650d7c819a727f4f89832cc932b439613593 100644 (file)
@@ -89,6 +89,7 @@ ERROR:
 }
 
 int pakfire_jwt_payload(struct pakfire_ctx* ctx, const char* token, struct json_object** payload) {
+       char* error = NULL;
        char* p = NULL;
        size_t l = 0;
        int r;
@@ -97,13 +98,19 @@ int pakfire_jwt_payload(struct pakfire_ctx* ctx, const char* token, struct json_
        r = pakfire_jwt_decode_payload(&p, &l, token);
        if (r < 0) {
                ERROR(ctx, "Failed to decode the JWT payload: %s\n", strerror(-r));
-               return r;
+               goto ERROR;
        }
 
        // Parse the JSON
-       *payload = pakfire_json_parse(ctx, p, l);
-       if (!*payload)
-               return -EINVAL;
+       r = pakfire_json_parse(payload, &error, p, l);
+       if (r < 0) {
+               ERROR(ctx, "Failed to parse JSON payload: %s\n", error);
+               goto ERROR;
+       }
+
+ERROR:
+       if (error)
+               free(error);
 
        return 0;
 }
index 801061c5a8c39260eb6509dcc6a7532e505d75db..10016b39a630d286d3a799c8d4630de64c23ac21 100644 (file)
@@ -140,6 +140,8 @@ ERROR:
 }
 
 int pakfire_mirrorlist_read(struct pakfire_mirrorlist* list, const char* path) {
+       struct json_object* json = NULL;
+       char* error = NULL;
        int r;
 
        if (!path || !*path) {
@@ -149,13 +151,14 @@ int pakfire_mirrorlist_read(struct pakfire_mirrorlist* list, const char* path) {
 
        DEBUG(list->ctx, "Reading mirrorlist from %s\n", path);
 
-       struct json_object* json = pakfire_json_parse_from_file(list->ctx, path);
-       if (!json) {
+       // Parse the file
+       r = pakfire_json_parse_from_file(&json, &error, path);
+       if (r < 0) {
                // Ignore if path does not exist
                if (errno == ENOENT)
                        return 0;
 
-               ERROR(list->ctx, "Could not parse mirrorlist from %s: %m\n", path);
+               ERROR(list->ctx, "Could not parse mirrorlist from %s: %s\n", path, error);
                return 1;
        }
 
@@ -206,6 +209,8 @@ int pakfire_mirrorlist_read(struct pakfire_mirrorlist* list, const char* path) {
 ERROR:
        if (json)
                json_object_put(json);
+       if (error)
+               free(error);
 
        return r;
 }
index c0b18fb21e0ca664dba0ad49767ab610f2605991..ac627e0632f09fed26c4bf561e1ff957baecdad8 100644 (file)
@@ -1055,14 +1055,15 @@ ERROR:
 
 static int pakfire_repo_read_metadata(struct pakfire_repo* repo, const char* path) {
        struct json_object* json = NULL;
+       char* error = NULL;
        int r;
 
        DEBUG(repo->ctx, "Reading repository metadata from %s...\n", path);
 
        // Parse the existing metadata
-       json = pakfire_json_parse_from_file(repo->ctx, path);
-       if (!json) {
-               switch (errno) {
+       r = pakfire_json_parse_from_file(&json, &error, path);
+       if (r < 0) {
+               switch (-r) {
                        case ENOENT:
                                // Log some message
                                DEBUG(repo->ctx, "Repository metadata is not available\n");
@@ -1071,8 +1072,7 @@ static int pakfire_repo_read_metadata(struct pakfire_repo* repo, const char* pat
                                return 0;
 
                        default:
-                               ERROR(repo->ctx, "Could not parse metadata from %s: %m\n", path);
-                               r = -errno;
+                               ERROR(repo->ctx, "Could not parse metadata from %s: %s\n", path, error);
                                goto ERROR;
                }
        }
@@ -1098,6 +1098,8 @@ ERROR:
        // Free the parsed JSON object
        if (json)
                json_object_put(json);
+       if (error)
+               free(error);
 
        return r;
 }
@@ -1262,6 +1264,7 @@ static int pakfire_repo_download_metadata(struct pakfire_repo* repo, const char*
        struct pakfire_buffer buffer = {};
        struct pakfire_xfer* xfer = NULL;
        struct json_object* json = NULL;
+       char* error = NULL;
        int r;
 
        // Local repositories don't need to download metadata
@@ -1320,9 +1323,9 @@ static int pakfire_repo_download_metadata(struct pakfire_repo* repo, const char*
        }
 
        // Parse JSON from buffer
-       json = pakfire_json_parse(repo->ctx, buffer.data, buffer.length);
-       if (!json) {
-               r = -EBADMSG;
+       r = pakfire_json_parse(&json, &error, buffer.data, buffer.length);
+       if (r < 0) {
+               ERROR(repo->ctx, "Failed to parse JSON data: %s\n", error);
                goto ERROR;
        }
 
@@ -1361,6 +1364,8 @@ ERROR:
                json_object_put(json);
        if (buffer.data)
                free(buffer.data);
+       if (error)
+               free(error);
 
        return r;
 }
index 583cab2920f0262a9e1a95d1f07b085829459f2d..21d9c10cdcae4430b4b4c015e894792c4f99b886 100644 (file)
@@ -1875,6 +1875,7 @@ static int pakfire_xfer_parse_api_response(struct pakfire_xfer* xfer,
                const char* buffer, const size_t length, struct json_object** object) {
        struct json_object* error = NULL;
        struct json_object* o = NULL;
+       char* e = NULL;
        int r;
 
        // Check if we received any data
@@ -1891,10 +1892,9 @@ static int pakfire_xfer_parse_api_response(struct pakfire_xfer* xfer,
        // XXX Maybe fetch the parser's error message here?!
 
        // Parse the buffer
-       o = pakfire_json_parse(xfer->ctx, buffer, length);
-       if (!o) {
-               ERROR(xfer->ctx, "Could not parse the response\n");
-               r = -EBADMSG;
+       r = pakfire_json_parse(&o, &e, buffer, length);
+       if (r < 0) {
+               ERROR(xfer->ctx, "Could not parse the response: %s\n", e);
                goto ERROR;
        }
 
@@ -1919,6 +1919,8 @@ static int pakfire_xfer_parse_api_response(struct pakfire_xfer* xfer,
 ERROR:
        if (o)
                json_object_put(o);
+       if (e)
+               free(e);
 
        return r;
 }