diff options
Diffstat (limited to '')
| -rw-r--r-- | data.c | 58 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rw-r--r-- | snac.h | 2 |
3 files changed, 66 insertions, 0 deletions
| @@ -4362,3 +4362,61 @@ const char *lang_str(const char *str, const snac *user) | |||
| 4362 | 4362 | ||
| 4363 | return n_str; | 4363 | return n_str; |
| 4364 | } | 4364 | } |
| 4365 | |||
| 4366 | |||
| 4367 | /** integrity checks **/ | ||
| 4368 | |||
| 4369 | void data_fsck(void) | ||
| 4370 | { | ||
| 4371 | xs *list = user_list(); | ||
| 4372 | const char *uid; | ||
| 4373 | |||
| 4374 | xs_list_foreach(list, uid) { | ||
| 4375 | snac user; | ||
| 4376 | |||
| 4377 | if (!user_open(&user, uid)) | ||
| 4378 | continue; | ||
| 4379 | |||
| 4380 | { | ||
| 4381 | /* iterate all private posts and check that non-public posts | ||
| 4382 | from this user are also linked into the public directory, | ||
| 4383 | to avoid the don't-fucking-delete-my-own-private-posts purge bug */ | ||
| 4384 | |||
| 4385 | xs *priv_spec = xs_fmt("%s/private/""*.json", user.basedir); | ||
| 4386 | xs *posts = xs_glob(priv_spec, 0, 0); | ||
| 4387 | const char *priv_fn; | ||
| 4388 | |||
| 4389 | xs_list_foreach(posts, priv_fn) { | ||
| 4390 | xs *pub_fn = xs_replace(priv_fn, "/private/", "/public/"); | ||
| 4391 | |||
| 4392 | /* already there? look no more */ | ||
| 4393 | if (mtime(pub_fn)) | ||
| 4394 | continue; | ||
| 4395 | |||
| 4396 | /* read the post */ | ||
| 4397 | FILE *f; | ||
| 4398 | if ((f = fopen(priv_fn, "r")) == NULL) | ||
| 4399 | continue; | ||
| 4400 | |||
| 4401 | xs *post = xs_json_load(f); | ||
| 4402 | fclose(f); | ||
| 4403 | |||
| 4404 | if (!xs_is_dict(post)) | ||
| 4405 | continue; | ||
| 4406 | |||
| 4407 | const char *attr_to = get_atto(post); | ||
| 4408 | |||
| 4409 | if (!xs_is_string(attr_to) || strcmp(attr_to, user.actor) != 0) { | ||
| 4410 | /* not from this user */ | ||
| 4411 | continue; | ||
| 4412 | } | ||
| 4413 | |||
| 4414 | /* link */ | ||
| 4415 | snac_log(&user, xs_fmt("fsck: fixed missing link %s", xs_dict_get(post, "id"))); | ||
| 4416 | link(priv_fn, pub_fn); | ||
| 4417 | } | ||
| 4418 | } | ||
| 4419 | |||
| 4420 | user_free(&user); | ||
| 4421 | } | ||
| 4422 | } | ||
| @@ -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 | ||
| @@ -477,3 +477,5 @@ xs_str *rss_from_timeline(snac *user, const xs_list *timeline, | |||
| 477 | const char *title, const char *link, const char *desc); | 477 | const char *title, const char *link, const char *desc); |
| 478 | void rss_to_timeline(snac *user, const char *url); | 478 | void rss_to_timeline(snac *user, const char *url); |
| 479 | void rss_poll_hashtags(void); | 479 | void rss_poll_hashtags(void); |
| 480 | |||
| 481 | void data_fsck(void); | ||