commit c541296
grunfink
·
2025-09-07 06:03:38 +0000 UTC
parent fdcd7b9
New command-line option 'fsck'.
M
data.c
+58,
-0
1@@ -4362,3 +4362,61 @@ const char *lang_str(const char *str, const snac *user)
2
3 return n_str;
4 }
5+
6+
7+/** integrity checks **/
8+
9+void data_fsck(void)
10+{
11+ xs *list = user_list();
12+ const char *uid;
13+
14+ xs_list_foreach(list, uid) {
15+ snac user;
16+
17+ if (!user_open(&user, uid))
18+ continue;
19+
20+ {
21+ /* iterate all private posts and check that non-public posts
22+ from this user are also linked into the public directory,
23+ to avoid the don't-fucking-delete-my-own-private-posts purge bug */
24+
25+ xs *priv_spec = xs_fmt("%s/private/""*.json", user.basedir);
26+ xs *posts = xs_glob(priv_spec, 0, 0);
27+ const char *priv_fn;
28+
29+ xs_list_foreach(posts, priv_fn) {
30+ xs *pub_fn = xs_replace(priv_fn, "/private/", "/public/");
31+
32+ /* already there? look no more */
33+ if (mtime(pub_fn))
34+ continue;
35+
36+ /* read the post */
37+ FILE *f;
38+ if ((f = fopen(priv_fn, "r")) == NULL)
39+ continue;
40+
41+ xs *post = xs_json_load(f);
42+ fclose(f);
43+
44+ if (!xs_is_dict(post))
45+ continue;
46+
47+ const char *attr_to = get_atto(post);
48+
49+ if (!xs_is_string(attr_to) || strcmp(attr_to, user.actor) != 0) {
50+ /* not from this user */
51+ continue;
52+ }
53+
54+ /* link */
55+ snac_log(&user, xs_fmt("fsck: fixed missing link %s", xs_dict_get(post, "id")));
56+ link(priv_fn, pub_fn);
57+ }
58+ }
59+
60+ user_free(&user);
61+ }
62+}
M
main.c
+6,
-0
1@@ -34,6 +34,7 @@ int usage(const char *cmd)
2 "httpd {basedir} Starts the HTTPD daemon\n"
3 "purge {basedir} Purges old data\n"
4 "state {basedir} Prints server state\n"
5+ "fsck {basedir} Performs a non-destructive data integrity check\n"
6 "webfinger {basedir} {account} Queries about an account (@user@host or actor url)\n"
7 "queue {basedir} {uid} Processes a user queue\n"
8 "follow {basedir} {uid} {actor} Follows an actor\n"
9@@ -200,6 +201,11 @@ int main(int argc, char *argv[])
10 return 0;
11 }
12
13+ if (strcmp(cmd, "fsck") == 0) { /** **/
14+ data_fsck();
15+ return 0;
16+ }
17+
18 if ((user = GET_ARGV()) == NULL)
19 return usage(cmd);
20
M
snac.h
+2,
-0
1@@ -477,3 +477,5 @@ xs_str *rss_from_timeline(snac *user, const xs_list *timeline,
2 const char *title, const char *link, const char *desc);
3 void rss_to_timeline(snac *user, const char *url);
4 void rss_poll_hashtags(void);
5+
6+void data_fsck(void);