💾 Archived View for thrig.me › tech › openbsd › parse-restic-find.c captured on 2024-08-18 at 22:12:19.

View Raw

More Information

⬅️ Previous capture (2023-09-08)

-=-=-=-=-=-=-

// parse restic-find JSON output for some desired metadata
//   doas pkg_add jansson
//   CFLAGS=`pkg-config --cflags --libs jansson` make parse-restic-find
#include <err.h>
#include <search.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <jansson.h>

// array of objects containing file "path" and "mtime" that need to be
// shown for review of what to restore
void
each_match(json_t *root, const char *snapname)
{
	int header = 0;
	size_t len = json_array_size(root);
	for (size_t i = 0; i < len; i++) {
		json_t *obj = json_array_get(root, i);
		if (!obj) errx(1, "json_array_get match ??");

		json_t *path = json_object_get(obj, "path");
		if (!path) errx(1, "json_object_get path??");

		json_t *mtime = json_object_get(obj, "mtime");
		if (!mtime) errx(1, "json_object_get mtime??");

		const char *pathstr = json_string_value(path);
		if (!pathstr) errx(1, "json_string_value path??");
		const char *mtimestr = json_string_value(mtime);
		if (!mtimestr) errx(1, "json_string_value mtime??");
		char *key;
		asprintf(&key, "%s%s", mtimestr, pathstr);
		ENTRY item;
		item.key = key;
		if (hsearch(item, FIND)) {
			free(key);
			continue;
		}
		hsearch(item, ENTER);

		if (!header) {
			printf("%s\n", snapname);
			header = 1;
		}
		printf("  %s\n  %s\n", pathstr, mtimestr);
	}
	if (header) putchar('\n');
}

// array of objects containing "snapshot" and presumably at least
// one "matches"
void
result_list(json_t *root)
{
	size_t len = json_array_size(root);
	for (size_t i = 0; i < len; i++) {
		json_t *obj = json_array_get(root, i);
		if (!obj) errx(1, "json_array_get ??");

		json_t *matches = json_object_get(obj, "matches");
		if (!matches) errx(1, "json_object_get matches??");

		json_t *snap = json_object_get(obj, "snapshot");
		if (!snap) errx(1, "json_object_get snap??");
		const char *s = json_string_value(snap);
		if (!s) errx(1, "json_string_value snap??");

		each_match(matches, s);
	}
}

int
main(void)
{
	char *line      = NULL;
	size_t linesize = 0;
	ssize_t linelen;

#ifdef __OpenBSD__
	if (pledge("stdio", NULL) == -1) err(1, "pledge failed");
#endif

	if (!hcreate(16)) err(1, "hcreate");

	while ((linelen = getline(&line, &linesize, stdin)) != -1) {
		json_t *root;
		json_error_t error;
		root = json_loads(line, 0, &error);
		if (!root) errx(1, "json err -:%d: %s", error.line, error.text);
		result_list(root);
		json_decref(root);
	}
	free(line);
}