On Wed, Mar 31, 2021 at 12:40:57PM +0200, Claudio Jeker wrote: > The current code to cleanup the repository after validation did not > cleanup directories and also skipped any repo directory that is no > referenced. > > Adjust the cleanup code to fix these two issues. This uses the fact that > the cache directory now only contains 2 directories rsync & ta. > Thanks to the internal order of the RB tree, the code can use RB_NFIND() > to figure out if a path is used or not. > > With this the cleanup works but is also more aggressiv. > For example if you run > rpki-client -t /etc/rpki/afrinic.tal > then this will clean out all other repositories from arin, apnic, lacnic > and ripe. For regular use this is no isssue since you normally run > rpki-client over and over again with the same flags. >
This version also skips the cleanup run if rpki-client was started with -n -- :wq Claudio Index: extern.h =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v retrieving revision 1.59 diff -u -p -r1.59 extern.h --- extern.h 29 Mar 2021 12:41:34 -0000 1.59 +++ extern.h 31 Mar 2021 08:38:33 -0000 @@ -306,6 +306,7 @@ struct stats { size_t vrps; /* total number of vrps */ size_t uniqs; /* number of unique vrps */ size_t del_files; /* number of files removed in cleanup */ + size_t del_dirs ;/* number of directories removed in cleanup */ char *talnames; struct timeval elapsed_time; struct timeval user_time; Index: main.c =================================================================== RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v retrieving revision 1.126 diff -u -p -r1.126 main.c --- main.c 29 Mar 2021 03:45:35 -0000 1.126 +++ main.c 31 Mar 2021 11:39:56 -0000 @@ -154,6 +154,22 @@ filepath_exists(char *file) return RB_FIND(filepath_tree, &fpt, &needle) != NULL; } +/* + * Return true if a filepath entry exists that starts with path. + */ +static int +filepath_dir_exists(char *path) +{ + struct filepath needle; + struct filepath *res; + + needle.file = path; + res = RB_NFIND(filepath_tree, &fpt, &needle); + if (res != NULL && strstr(res->file, path) == res->file) + return 1; + return 0; +} + RB_GENERATE(filepath_tree, filepath, entry, filepathcmp); void @@ -767,56 +783,56 @@ add_to_del(char **del, size_t *dsz, char return del; } -static size_t +static void repo_cleanup(void) { - size_t i, delsz = 0; - char *argv[2], **del = NULL; - struct repo *rp; + size_t i, delsz = 0, dirsz = 0; + char *argv[3], **del = NULL, **dir = NULL; FTS *fts; FTSENT *e; - SLIST_FOREACH(rp, &repos, entry) { - argv[0] = rp->local; - argv[1] = NULL; - if ((fts = fts_open(argv, FTS_PHYSICAL | FTS_NOSTAT, - NULL)) == NULL) - err(1, "fts_open"); - errno = 0; - while ((e = fts_read(fts)) != NULL) { - switch (e->fts_info) { - case FTS_NSOK: - if (!filepath_exists(e->fts_path)) - del = add_to_del(del, &delsz, - e->fts_path); - break; - case FTS_D: - case FTS_DP: - /* TODO empty directory pruning */ - break; - case FTS_SL: - case FTS_SLNONE: - warnx("symlink %s", e->fts_path); - del = add_to_del(del, &delsz, e->fts_path); - break; - case FTS_NS: - case FTS_ERR: - warnx("fts_read %s: %s", e->fts_path, - strerror(e->fts_errno)); - break; - default: - warnx("unhandled[%x] %s", e->fts_info, + argv[0] = "ta"; + argv[1] = "rsync"; + argv[2] = NULL; + if ((fts = fts_open(argv, FTS_PHYSICAL | FTS_NOSTAT, NULL)) == NULL) + err(1, "fts_open"); + errno = 0; + while ((e = fts_read(fts)) != NULL) { + switch (e->fts_info) { + case FTS_NSOK: + if (!filepath_exists(e->fts_path)) + del = add_to_del(del, &delsz, e->fts_path); - break; - } - - errno = 0; + break; + case FTS_D: + break; + case FTS_DP: + if (!filepath_dir_exists(e->fts_path)) + dir = add_to_del(dir, &dirsz, + e->fts_path); + break; + case FTS_SL: + case FTS_SLNONE: + warnx("symlink %s", e->fts_path); + del = add_to_del(del, &delsz, e->fts_path); + break; + case FTS_NS: + case FTS_ERR: + warnx("fts_read %s: %s", e->fts_path, + strerror(e->fts_errno)); + break; + default: + warnx("unhandled[%x] %s", e->fts_info, + e->fts_path); + break; } - if (errno) - err(1, "fts_read"); - if (fts_close(fts) == -1) - err(1, "fts_close"); + + errno = 0; } + if (errno) + err(1, "fts_read"); + if (fts_close(fts) == -1) + err(1, "fts_close"); for (i = 0; i < delsz; i++) { if (unlink(del[i]) == -1) @@ -826,8 +842,17 @@ repo_cleanup(void) free(del[i]); } free(del); + stats.del_files = delsz; - return delsz; + for (i = 0; i < dirsz; i++) { + if (rmdir(dir[i]) == -1) + warn("rmdir %s", dir[i]); + if (verbose > 1) + logx("deleted dir %s", dir[i]); + free(dir[i]); + } + free(dir); + stats.del_dirs = dirsz; } void @@ -1228,7 +1253,8 @@ main(int argc, char *argv[]) } } - stats.del_files = repo_cleanup(); + if (!noop) + repo_cleanup(); gettimeofday(&now_time, NULL); timersub(&now_time, &start_time, &stats.elapsed_time); @@ -1259,7 +1285,8 @@ main(int argc, char *argv[]) logx("Certificate revocation lists: %zu", stats.crls); logx("Ghostbuster records: %zu", stats.gbrs); logx("Repositories: %zu", stats.repos); - logx("Files removed: %zu", stats.del_files); + logx("Cleanup: removed %zu files, %zu directories", + stats.del_files, stats.del_dirs); logx("VRP Entries: %zu (%zu unique)", stats.vrps, stats.uniqs); /* Memory cleanup. */