summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--activitypub.c6
-rw-r--r--data.c69
-rw-r--r--httpd.c2
-rw-r--r--main.c6
-rw-r--r--snac.h3
5 files changed, 86 insertions, 0 deletions
diff --git a/activitypub.c b/activitypub.c
index d699fee..5fb60ba 100644
--- a/activitypub.c
+++ b/activitypub.c
@@ -3377,6 +3377,12 @@ void process_queue_item(xs_dict *q_item)
3377 rss_poll_hashtags(); 3377 rss_poll_hashtags();
3378 } 3378 }
3379 else 3379 else
3380 if (strcmp(type, "fsck") == 0) {
3381 srv_log(xs_fmt("started deferred data integrity check"));
3382 data_fsck();
3383 srv_log(xs_fmt("finished deferred data integrity check"));
3384 }
3385 else
3380 srv_log(xs_fmt("unexpected q_item type '%s'", type)); 3386 srv_log(xs_fmt("unexpected q_item type '%s'", type));
3381} 3387}
3382 3388
diff --git a/data.c b/data.c
index b36e31e..1533305 100644
--- a/data.c
+++ b/data.c
@@ -3605,6 +3605,17 @@ void enqueue_collect_outbox(snac *user, const char *actor_id)
3605} 3605}
3606 3606
3607 3607
3608void enqueue_fsck(void)
3609/* enqueues an fsck */
3610{
3611 xs *qmsg = _new_qmsg("fsck", "", 0);
3612 const char *ntid = xs_dict_get(qmsg, "ntid");
3613 xs *fn = xs_fmt("%s/queue/%s.json", srv_basedir, ntid);
3614
3615 qmsg = _enqueue_put(fn, qmsg);
3616}
3617
3618
3608int was_question_voted(snac *user, const char *id) 3619int was_question_voted(snac *user, const char *id)
3609/* returns true if the user voted in this poll */ 3620/* returns true if the user voted in this poll */
3610{ 3621{
@@ -4362,3 +4373,61 @@ const char *lang_str(const char *str, const snac *user)
4362 4373
4363 return n_str; 4374 return n_str;
4364} 4375}
4376
4377
4378/** integrity checks **/
4379
4380void data_fsck(void)
4381{
4382 xs *list = user_list();
4383 const char *uid;
4384
4385 xs_list_foreach(list, uid) {
4386 snac user;
4387
4388 if (!user_open(&user, uid))
4389 continue;
4390
4391 {
4392 /* iterate all private posts and check that non-public posts
4393 from this user are also linked into the public directory,
4394 to avoid the don't-fucking-delete-my-own-private-posts purge bug */
4395
4396 xs *priv_spec = xs_fmt("%s/private/""*.json", user.basedir);
4397 xs *posts = xs_glob(priv_spec, 0, 0);
4398 const char *priv_fn;
4399
4400 xs_list_foreach(posts, priv_fn) {
4401 xs *pub_fn = xs_replace(priv_fn, "/private/", "/public/");
4402
4403 /* already there? look no more */
4404 if (mtime(pub_fn))
4405 continue;
4406
4407 /* read the post */
4408 FILE *f;
4409 if ((f = fopen(priv_fn, "r")) == NULL)
4410 continue;
4411
4412 xs *post = xs_json_load(f);
4413 fclose(f);
4414
4415 if (!xs_is_dict(post))
4416 continue;
4417
4418 const char *attr_to = get_atto(post);
4419
4420 if (!xs_is_string(attr_to) || strcmp(attr_to, user.actor) != 0) {
4421 /* not from this user */
4422 continue;
4423 }
4424
4425 /* link */
4426 snac_debug(&user, 1, xs_fmt("fsck: fixed missing link %s", xs_dict_get(post, "id")));
4427 link(priv_fn, pub_fn);
4428 }
4429 }
4430
4431 user_free(&user);
4432 }
4433}
diff --git a/httpd.c b/httpd.c
index 9707f9c..50f56f2 100644
--- a/httpd.c
+++ b/httpd.c
@@ -805,6 +805,8 @@ static void *background_thread(void *arg)
805 805
806 srv_log(xs_fmt("background thread started")); 806 srv_log(xs_fmt("background thread started"));
807 807
808 enqueue_fsck();
809
808 while (p_state->srv_running) { 810 while (p_state->srv_running) {
809 int cnt = 0; 811 int cnt = 0;
810 812
diff --git a/main.c b/main.c
index f767355..19cfe1a 100644
--- a/main.c
+++ b/main.c
@@ -34,6 +34,7 @@ int usage(const char *cmd)
34 "httpd {basedir} Starts the HTTPD daemon\n" 34 "httpd {basedir} Starts the HTTPD daemon\n"
35 "purge {basedir} Purges old data\n" 35 "purge {basedir} Purges old data\n"
36 "state {basedir} Prints server state\n" 36 "state {basedir} Prints server state\n"
37 "fsck {basedir} Performs a non-destructive data integrity check\n"
37 "webfinger {basedir} {account} Queries about an account (@user@host or actor url)\n" 38 "webfinger {basedir} {account} Queries about an account (@user@host or actor url)\n"
38 "queue {basedir} {uid} Processes a user queue\n" 39 "queue {basedir} {uid} Processes a user queue\n"
39 "follow {basedir} {uid} {actor} Follows an actor\n" 40 "follow {basedir} {uid} {actor} Follows an actor\n"
@@ -200,6 +201,11 @@ int main(int argc, char *argv[])
200 return 0; 201 return 0;
201 } 202 }
202 203
204 if (strcmp(cmd, "fsck") == 0) { /** **/
205 data_fsck();
206 return 0;
207 }
208
203 if ((user = GET_ARGV()) == NULL) 209 if ((user = GET_ARGV()) == NULL)
204 return usage(cmd); 210 return usage(cmd);
205 211
diff --git a/snac.h b/snac.h
index e4f5262..e344f46 100644
--- a/snac.h
+++ b/snac.h
@@ -299,6 +299,7 @@ void enqueue_webmention(const xs_dict *msg);
299void enqueue_notify_webhook(snac *user, const xs_dict *noti, int retries); 299void enqueue_notify_webhook(snac *user, const xs_dict *noti, int retries);
300void enqueue_collect_replies(snac *user, const char *post); 300void enqueue_collect_replies(snac *user, const char *post);
301void enqueue_collect_outbox(snac *user, const char *actor_id); 301void enqueue_collect_outbox(snac *user, const char *actor_id);
302void enqueue_fsck(void);
302 303
303int was_question_voted(snac *user, const char *id); 304int was_question_voted(snac *user, const char *id);
304 305
@@ -477,3 +478,5 @@ xs_str *rss_from_timeline(snac *user, const xs_list *timeline,
477 const char *title, const char *link, const char *desc); 478 const char *title, const char *link, const char *desc);
478void rss_to_timeline(snac *user, const char *url); 479void rss_to_timeline(snac *user, const char *url);
479void rss_poll_hashtags(void); 480void rss_poll_hashtags(void);
481
482void data_fsck(void);