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>
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;
}
ERROR:
if (m)
json_object_put(m);
+ if (error)
+ free(error);
return r;
}
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) {
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);
}
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;
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;
}
}
int pakfire_mirrorlist_read(struct pakfire_mirrorlist* list, const char* path) {
+ struct json_object* json = NULL;
+ char* error = NULL;
int r;
if (!path || !*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;
}
ERROR:
if (json)
json_object_put(json);
+ if (error)
+ free(error);
return r;
}
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");
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;
}
}
// Free the parsed JSON object
if (json)
json_object_put(json);
+ if (error)
+ free(error);
return r;
}
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
}
// 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;
}
json_object_put(json);
if (buffer.data)
free(buffer.data);
+ if (error)
+ free(error);
return r;
}
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
// 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;
}
ERROR:
if (o)
json_object_put(o);
+ if (e)
+ free(e);
return r;
}