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.

-- 
: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 10:12:40 -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,7 @@ main(int argc, char *argv[])
                }
        }
 
-       stats.del_files = repo_cleanup();
+       repo_cleanup();
 
        gettimeofday(&now_time, NULL);
        timersub(&now_time, &start_time, &stats.elapsed_time);
@@ -1259,7 +1284,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. */

Reply via email to