diff options
Diffstat (limited to 'service/cleaner/main.c')
| -rw-r--r-- | service/cleaner/main.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/service/cleaner/main.c b/service/cleaner/main.c new file mode 100644 index 0000000..ef48dfa --- /dev/null +++ b/service/cleaner/main.c @@ -0,0 +1,155 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#include <unistd.h> +#include <dirent.h> +#include <time.h> +#include <sys/file.h> +#include <sys/stat.h> + +void +die(const char *fmtstr, ...) +{ + va_list ap; + + fprintf(stderr, "CLEANER: "); + va_start(ap, fmtstr); + vfprintf(stderr, fmtstr, ap); + va_end(ap); + + exit(EXIT_FAILURE); +} + +int +creation_time(const char *path) +{ + struct stat attrib; + + stat(path, &attrib); + return attrib.st_ctim.tv_sec; +} + +char* +aprintf(const char *fmtstr, ...) +{ + va_list ap, cpy; + size_t nb; + char *str; + + va_copy(cpy, ap); + + va_start(cpy, fmtstr); + nb = vsnprintf(NULL, 0, fmtstr, cpy); + va_end(cpy); + + if (nb <= 0) die("Invalid fmtstr!\n"); + str = malloc(nb+1); + if (!str) die("Alloc of fmtstr failed\n"); + + va_start(ap, fmtstr); + nb = vsnprintf(str, nb+1, fmtstr, ap); + va_end(ap); + + return str; +} + +void +recdel(const char *path) +{ + struct stat attrib; + struct dirent *de; + char *subpath; + DIR *d; + + stat(path, &attrib); + if (S_ISDIR(attrib.st_mode)) { + d = opendir(path); + while ((de = readdir(d))) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + subpath = aprintf("%s/%s", path, de->d_name); + recdel(subpath); + free(subpath); + } + closedir(d); + rmdir(path); + } else { + remove(path); + } +} + +int +main(int argc, const char **argv) +{ + char buf[256], *end, *path, + **paths, *oldpath, *newpath; + unsigned long reftime; + int i, pathc, pathcap, nread; + const char *dirpath; + FILE *f, *fn; + + if (argc != 3) die("USAGE: cleaner DIR REFTIME\n"); + + dirpath = argv[1]; + + reftime = strtoul(argv[2], &end, 10); + if (end && *end) die("Invalid unix time reference\n"); + + oldpath = aprintf("%s/.index", dirpath); + if (!(f = fopen(oldpath, "r+"))) + die("Missing index file: %s\n", oldpath); + flock(fileno(f), LOCK_EX); + + newpath = aprintf("%s/.index.next", dirpath); + if (!(fn = fopen(newpath, "w+"))) + die("Failed to create index file: %s\n", newpath); + + pathc = 0; + pathcap = 1024; + paths = malloc(pathcap * sizeof(char*)); + if (!paths) die("OOM - allocating initial path array\n"); + + while (fgets(buf, sizeof(buf), f)) { + if (*buf && buf[strlen(buf)-1] == '\n') + buf[strlen(buf)-1] = '\0'; + + path = aprintf("%s/%s", dirpath, buf); + if (creation_time(path) < reftime) { + paths[pathc] = strdup(path); + if (!paths[pathc++]) die("OOM - during path str alloc\n"); + if (pathc == pathcap) { + pathcap *= 2; + paths = realloc(paths, pathcap * sizeof(char*)); + if (!paths) die("OOM - too many paths to alloc\n"); + } + } else { + fwrite(buf, 1, strlen(buf), fn); + putc('\n', fn); + } + free(path); + } + + fseek(f, 0, SEEK_SET); + fseek(fn, 0, SEEK_SET); + while ((nread = fread(buf, 1, sizeof(buf), fn)) > 0) + fwrite(buf, 1, nread, f); + ftruncate(fileno(f), ftell(f)); + + nread = ftell(f); + + flock(fileno(f), LOCK_UN); + fclose(f); + fclose(fn); + + if (!nread && getenv("DELROOT")) { + remove(oldpath); + remove(newpath); + } + + for (i = 0; i < pathc; i++) { + printf("CLEANER: REMOVED %s\n", paths[i]); + recdel(paths[i]); + } +} |
