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:
M | data.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), ¤t) == 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) {