snac2/upgrade.c

351 lines
9.9 KiB
C
Raw Normal View History

2022-11-23 14:05:55 +00:00
/* snac - A simple, minimalistic ActivityPub instance */
2024-01-04 08:22:03 +00:00
/* copyright (c) 2022 - 2024 grunfink et al. / MIT license */
2022-11-23 14:05:55 +00:00
#include "xs.h"
#include "xs_io.h"
#include "xs_json.h"
#include "xs_glob.h"
#include "snac.h"
#include <sys/stat.h>
2023-01-31 17:33:45 +00:00
int snac_upgrade(xs_str **error)
2022-11-23 14:05:55 +00:00
{
int ret = 1;
int changed = 0;
double f = 0.0;
for (;;) {
2024-05-21 12:12:15 +00:00
const char *layout = xs_dict_get(srv_config, "layout");
2022-11-23 14:05:55 +00:00
double nf;
f = nf = xs_number_get(layout);
2023-01-31 17:33:45 +00:00
if (!(f < disk_layout))
2022-11-23 14:05:55 +00:00
break;
2023-01-31 17:33:45 +00:00
srv_log(xs_fmt("disk layout upgrade needed (%1.1lf < %1.1lf)", f, disk_layout));
2022-11-23 14:05:55 +00:00
if (f < 2.0) {
*error = xs_fmt("ERROR: unsupported old disk layout %1.1lf\n", f);
ret = 0;
break;
}
else
if (f < 2.1) {
xs *dir = xs_fmt("%s/object", srv_basedir);
2023-02-07 08:25:01 +00:00
mkdirx(dir);
2022-11-23 14:05:55 +00:00
nf = 2.1;
}
2022-11-23 15:46:18 +00:00
else
if (f < 2.2) {
xs *users = user_list();
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-11-23 15:46:18 +00:00
p = users;
while (xs_list_iter(&p, &v)) {
snac snac;
if (user_open(&snac, v)) {
xs *spec = xs_fmt("%s/actors/" "*.json", snac.basedir);
xs *list = xs_glob(spec, 0, 0);
2024-05-23 08:01:37 +00:00
char *g;
const char *fn;
2022-11-23 15:46:18 +00:00
g = list;
while (xs_list_iter(&g, &fn)) {
2024-05-21 12:12:15 +00:00
xs *l = xs_split(fn, "/");
const char *b = xs_list_get(l, -1);
2022-11-23 15:46:18 +00:00
xs *dir = xs_fmt("%s/object/%c%c", srv_basedir, b[0], b[1]);
xs *nfn = xs_fmt("%s/%s", dir, b);
2023-02-07 08:25:01 +00:00
mkdirx(dir);
2022-11-23 15:46:18 +00:00
rename(fn, nfn);
}
xs *odir = xs_fmt("%s/actors", snac.basedir);
rmdir(odir);
user_free(&snac);
}
}
nf = 2.2;
}
2022-11-24 08:49:54 +00:00
else
if (f < 2.3) {
xs *users = user_list();
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-11-24 08:49:54 +00:00
p = users;
while (xs_list_iter(&p, &v)) {
snac snac;
if (user_open(&snac, v)) {
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-11-24 08:49:54 +00:00
xs *dir = xs_fmt("%s/hidden", snac.basedir);
2022-11-24 09:06:24 +00:00
/* create the hidden directory */
2023-02-07 08:25:01 +00:00
mkdirx(dir);
2022-11-24 09:06:24 +00:00
/* rename all muted files incorrectly named .json */
xs *spec = xs_fmt("%s/muted/" "*.json", snac.basedir);
xs *fns = xs_glob(spec, 0, 0);
p = fns;
while (xs_list_iter(&p, &v)) {
xs *nfn = xs_replace(v, ".json", "");
rename(v, nfn);
}
2022-11-24 08:49:54 +00:00
user_free(&snac);
}
}
nf = 2.3;
}
else
if (f < 2.4) {
xs *users = user_list();
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
p = users;
while (xs_list_iter(&p, &v)) {
snac snac;
if (user_open(&snac, v)) {
xs *dir = xs_fmt("%s/public", snac.basedir);
2023-02-07 08:25:01 +00:00
mkdirx(dir);
dir = xs_replace_i(dir, "public", "private");
2023-02-07 08:25:01 +00:00
mkdirx(dir);
user_free(&snac);
}
}
nf = 2.4;
}
2022-11-28 09:46:42 +00:00
else
if (f < 2.5) {
/* upgrade followers */
xs *users = user_list();
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-11-28 09:46:42 +00:00
p = users;
while (xs_list_iter(&p, &v)) {
snac snac;
if (user_open(&snac, v)) {
xs *spec = xs_fmt("%s/followers/" "*.json", snac.basedir);
xs *dir = xs_glob(spec, 0, 0);
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-11-28 09:46:42 +00:00
p = dir;
while (xs_list_iter(&p, &v)) {
FILE *f;
if ((f = fopen(v, "r")) != NULL) {
xs *s = xs_readall(f);
xs *o = xs_json_loads(s);
fclose(f);
2024-05-21 12:12:15 +00:00
const char *type = xs_dict_get(o, "type");
2022-11-28 09:46:42 +00:00
if (!xs_is_null(type) && strcmp(type, "Follow") == 0) {
unlink(v);
2024-05-21 12:12:15 +00:00
const char *actor = xs_dict_get(o, "actor");
2022-11-28 09:46:42 +00:00
if (!xs_is_null(actor))
follower_add(&snac, actor);
}
}
}
user_free(&snac);
}
}
nf = 2.5;
}
2022-12-03 16:58:49 +00:00
else
if (f < 2.6) {
/* upgrade local/ to public/ */
xs *users = user_list();
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-12-03 16:58:49 +00:00
p = users;
while (xs_list_iter(&p, &v)) {
snac snac;
if (user_open(&snac, v)) {
xs *spec = xs_fmt("%s/local/" "*.json", snac.basedir);
xs *dir = xs_glob(spec, 0, 0);
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-12-03 16:58:49 +00:00
p = dir;
while (xs_list_iter(&p, &v)) {
FILE *f;
if ((f = fopen(v, "r")) != NULL) {
xs *s = xs_readall(f);
xs *o = xs_json_loads(s);
fclose(f);
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
o = xs_dict_del(o, "_snac");
2024-05-21 12:12:15 +00:00
const char *id = xs_dict_get(o, "id");
2022-12-03 16:58:49 +00:00
/* store object */
object_add_ow(id, o);
/* if it's from us, add to public */
if (xs_startswith(id, snac.actor)) {
2024-05-21 12:12:15 +00:00
const xs_list *p;
2024-05-23 08:01:37 +00:00
const char *v;
2024-05-21 12:12:15 +00:00
int c;
2022-12-03 16:58:49 +00:00
object_user_cache_add(&snac, id, "public");
p = xs_dict_get(meta, "announced_by");
2024-05-21 12:12:15 +00:00
c = 0;
while (xs_list_next(p, &v, &c))
2022-12-03 16:58:49 +00:00
object_admire(id, v, 0);
2024-05-21 12:12:15 +00:00
2022-12-03 16:58:49 +00:00
p = xs_dict_get(meta, "liked_by");
2024-05-21 12:12:15 +00:00
c = 0;
while (xs_list_next(p, &v, &c))
2022-12-03 16:58:49 +00:00
object_admire(id, v, 1);
}
unlink(v);
}
}
xs *od = xs_fmt("%s/local", snac.basedir);
rmdir(od);
user_free(&snac);
}
}
nf = 2.6;
}
2022-12-03 17:41:44 +00:00
else
if (f < 2.7) {
/* upgrade timeline/ to private/ */
xs *users = user_list();
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-12-03 17:41:44 +00:00
p = users;
while (xs_list_iter(&p, &v)) {
snac snac;
if (user_open(&snac, v)) {
xs *spec = xs_fmt("%s/timeline/" "*.json", snac.basedir);
xs *dir = xs_glob(spec, 0, 0);
2024-05-23 08:01:37 +00:00
char *p;
const char *v;
2022-12-03 17:41:44 +00:00
p = dir;
while (xs_list_iter(&p, &v)) {
FILE *f;
if ((f = fopen(v, "r")) != NULL) {
xs *s = xs_readall(f);
xs *o = xs_json_loads(s);
fclose(f);
xs *meta = xs_dup(xs_dict_get(o, "_snac"));
o = xs_dict_del(o, "_snac");
2024-05-21 12:12:15 +00:00
const char *id = xs_dict_get(o, "id");
2022-12-03 17:41:44 +00:00
/* store object */
object_add_ow(id, o);
{
2024-05-21 12:12:15 +00:00
const xs_list *p;
2024-05-23 08:01:37 +00:00
const char *v;
2024-05-21 12:12:15 +00:00
int c = 0;
2022-12-03 17:41:44 +00:00
object_user_cache_add(&snac, id, "private");
p = xs_dict_get(meta, "announced_by");
2024-05-21 12:12:15 +00:00
c = 0;
while (xs_list_next(p, &v, &c))
2022-12-03 17:41:44 +00:00
object_admire(id, v, 0);
2024-05-21 12:12:15 +00:00
2022-12-03 17:41:44 +00:00
p = xs_dict_get(meta, "liked_by");
2024-05-21 12:12:15 +00:00
c = 0;
while (xs_list_next(p, &v, &c))
2022-12-03 17:41:44 +00:00
object_admire(id, v, 1);
}
unlink(v);
}
}
xs *od = xs_fmt("%s/timeline", snac.basedir);
rmdir(od);
user_free(&snac);
}
}
nf = 2.7;
}
2022-11-23 14:05:55 +00:00
if (f < nf) {
f = nf;
xs *nv = xs_number_new(f);
srv_config = xs_dict_set(srv_config, "layout", nv);
2023-01-31 17:33:45 +00:00
srv_log(xs_fmt("disk layout upgraded to version %1.1lf", f));
2022-11-23 14:05:55 +00:00
changed++;
}
else
break;
}
2023-01-31 17:33:45 +00:00
if (f > disk_layout) {
2022-11-23 14:05:55 +00:00
*error = xs_fmt("ERROR: unknown future version %lf\n", f);
ret = 0;
}
if (changed) {
/* upgrade the configuration file */
xs *fn = xs_fmt("%s/server.json", srv_basedir);
FILE *f;
if ((f = fopen(fn, "w")) != NULL) {
xs_json_dump(srv_config, 4, f);
2022-11-23 14:05:55 +00:00
fclose(f);
2023-01-31 17:33:45 +00:00
srv_log(xs_fmt("disk layout upgraded %s after %d changes", fn, changed));
2022-11-23 14:05:55 +00:00
}
else
ret = 0;
}
return ret;
}