commit 86ea9d526dc78b71570b5465274eaf04cd6a5b65
parent c3989c1d2a8f334a44a2fd133f527ed0ce039dc0
Author: sin <sin@2f30.org>
Date: Mon, 9 Jun 2014 14:35:11 +0100
Add primitive ref counting to removepkg
Prune empty dirs only if the package refcount for that dir
is 1.
Diffstat:
M | removepkg.c | | | 58 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 58 insertions(+), 0 deletions(-)
diff --git a/removepkg.c b/removepkg.c
@@ -13,6 +13,7 @@
#include <unistd.h>
#include "util.h"
+static int numrefs(const char *);
static int rmemptydir(const char *, const struct stat *, int, struct FTW *);
static int removepkg(const char *);
@@ -104,6 +105,61 @@ main(int argc, char *argv[])
}
static int
+numrefs(const char *f)
+{
+ DIR *dir;
+ struct dirent *dp;
+ FILE *fp;
+ char path[PATH_MAX];
+ char buf[BUFSIZ], *p;
+ int refs = 0;
+
+ dir = opendir("var/pkg");
+ if (!dir) {
+ fprintf(stderr, "opendir %s: %s\n", "var/pkg",
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ while ((dp = readdir(dir))) {
+ if (strcmp(dp->d_name, ".") == 0 ||
+ strcmp(dp->d_name, "..") == 0)
+ continue;
+
+ strlcpy(path, "var/pkg/", sizeof(path));
+ strlcat(path, dp->d_name, sizeof(path));
+
+ fp = fopen(path, "r");
+ if (!fp) {
+ fprintf(stderr, "fopen %s: %s\n", path,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ while (fgets(buf, sizeof(buf), fp)) {
+ p = strrchr(buf, '\n');
+ if (p)
+ *p = '\0';
+ if (buf[0] == '\0')
+ continue;
+ if (strcmp(buf, f) == 0)
+ refs++;
+ }
+ if (ferror(fp)) {
+ fprintf(stderr, "I/O error while processing %s\n", path);
+ fclose(fp);
+ return 1;
+ }
+
+ fclose(fp);
+ }
+
+ closedir(dir);
+
+ return refs;
+}
+
+static int
rmemptydir(const char *f, const struct stat *sb, int typeflag,
struct FTW *ftwbuf)
{
@@ -193,6 +249,8 @@ removepkg(const char *f)
*p = '\0';
if (buf[0] == '\0')
continue;
+ if (numrefs(buf) > 1)
+ continue;
nftw(buf, rmemptydir, 1, FTW_DEPTH);
}
if (ferror(fp)) {