snac2

Fork of https://codeberg.org/grunfink/snac2
git clone https://git.inz.fi/snac2
Log | Files | Refs | README | LICENSE

commit 0a87bfdcb83d2dca610ad8f1adcf9a6ab8e64cf6
parent a5fb539ee2ccaf8053ee5503c285a47b8cbb6fe8
Author: Santtu Lakkala <santtu.lakkala@unikie.com>
Date:   Mon, 24 Mar 2025 14:14:01 +0200

Add json helper with binary cache

Diffstat:
Mdata.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
1 file changed, 64 insertions(+), 35 deletions(-)

diff --git a/data.c b/data.c @@ -276,6 +276,58 @@ FILE *user_open_subfile(snac *user, const char *sub, const char *file, int wr) return NULL; } +xs_val *user_parse_json(snac *user, const char *fn, xs_val *(*deflt)(void)) +{ + xs_val *rv; + FILE *f; + FILE *bf; + + struct stat cached; + struct stat current; + + if ((f = user_open_file(user, fn, 0)) == NULL) { + if (!deflt) { + srv_debug(2, xs_fmt("error opening '%s/%s' %d", user->basedir, fn, errno)); + return NULL; + } + else { + return deflt(); + } + } + + if ((bf = user_open_subfile(user, "cache", fn, 0))) { + if (fstat(fileno(bf), &cached) == 0 && + fstat(fileno(f), &current) == 0 && + cached.st_ctime > current.st_ctime) { + rv = xs_realloc(NULL, cached.st_size); + if (fread(rv, 1, cached.st_size, bf) == cached.st_size) { + fclose(bf); + fclose(f); + return rv; + } + } + fclose(bf); + } + + rv = xs_json_load(f); + fclose(f); + + if (!rv) { + srv_log(xs_fmt("error parsing '%s/%s'", user->basedir, fn)); + if (deflt) + rv = deflt(); + } + + if ((bf = user_open_subfile(user, "cache", fn, 1))) { + flock(fileno(bf), LOCK_EX); + ftruncate(fileno(bf), 0); + fwrite(rv, 1, xs_size(rv), bf); + fclose(bf); + } + + return rv; +} + int user_open(snac *user, const char *uid) /* opens a user */ { @@ -313,48 +365,25 @@ int user_open(snac *user, const char *uid) user->basedir = xs_fmt("%s/user/%s", srv_basedir, user->uid); user->basedfd = open(user->basedir, O_DIRECTORY); - if ((f = user_open_file(user, "user.json", 0)) != NULL) { + do { /* read full config file */ - user->config = xs_json_load(f); - fclose(f); - - if (user->config != NULL) { - if ((f = user_open_file(user, "key.json", 0)) != NULL) { - user->key = xs_json_load(f); - fclose(f); - - if (user->key != NULL) { - user->actor = xs_fmt("%s/%s", srv_baseurl, user->uid); - user->md5 = xs_md5_hex(user->actor, strlen(user->actor)); + if ((user->config = user_parse_json(user, "user.json", NULL)) == NULL) + break; - /* everything is ok right now */ - ret = 1; + if ((user->key = user_parse_json(user, "key.json", NULL)) == NULL) + break; - /* does it have a configuration override? */ - if ((f = user_open_file(user, "user_o.json", 0)) != NULL) { - user->config_o = xs_json_load(f); - fclose(f); + user->actor = xs_fmt("%s/%s", srv_baseurl, user->uid); + user->md5 = xs_md5_hex(user->actor, strlen(user->actor)); - if (user->config_o == NULL) - srv_log(xs_fmt("error parsing '%s/user_o.json'", user->basedir)); - } + /* everything is ok right now */ + ret = 1; - if (user->config_o == NULL) - user->config_o = xs_dict_new(); - } - else - srv_log(xs_fmt("error parsing '%s/key.json'", user->basedir)); - } - else - srv_log(xs_fmt("error opening '%s/key.json' %d", user->basedir, errno)); - } - else - srv_log(xs_fmt("error parsing '%s/user.json'", user->basedir)); + /* does it have a configuration override? */ + user->config_o = user_parse_json(user, "user_o.json", xs_dict_new); user->tz = xs_dict_get_def(user->config, "tz", "UTC"); - } - else - srv_debug(2, xs_fmt("error opening '%s/user.json' %d", user->basedir, errno)); + } while (0); /* verified links */ if ((f = user_open_file(user, "links.json", 0)) != NULL) {