main.c (2946B)
1#include <stdlib.h> 2#include <stdio.h> 3#include <stdarg.h> 4#include <string.h> 5 6#include <unistd.h> 7#include <dirent.h> 8#include <time.h> 9#include <sys/file.h> 10#include <sys/stat.h> 11 12void 13die(const char *fmtstr, ...) 14{ 15 va_list ap; 16 17 fprintf(stderr, "CLEANER: "); 18 va_start(ap, fmtstr); 19 vfprintf(stderr, fmtstr, ap); 20 va_end(ap); 21 22 exit(EXIT_FAILURE); 23} 24 25int 26creation_time(const char *path) 27{ 28 struct stat attrib; 29 30 stat(path, &attrib); 31 return attrib.st_ctim.tv_sec; 32} 33 34char* 35aprintf(const char *fmtstr, ...) 36{ 37 va_list ap, cpy; 38 size_t nb; 39 char *str; 40 41 va_copy(cpy, ap); 42 43 va_start(cpy, fmtstr); 44 nb = vsnprintf(NULL, 0, fmtstr, cpy); 45 va_end(cpy); 46 47 if (nb <= 0) die("Invalid fmtstr!\n"); 48 str = malloc(nb+1); 49 if (!str) die("Alloc of fmtstr failed\n"); 50 51 va_start(ap, fmtstr); 52 nb = vsnprintf(str, nb+1, fmtstr, ap); 53 va_end(ap); 54 55 return str; 56} 57 58void 59recdel(const char *path) 60{ 61 struct stat attrib; 62 struct dirent *de; 63 char *subpath; 64 DIR *d; 65 66 stat(path, &attrib); 67 if (S_ISDIR(attrib.st_mode)) { 68 d = opendir(path); 69 while ((de = readdir(d))) { 70 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 71 continue; 72 subpath = aprintf("%s/%s", path, de->d_name); 73 recdel(subpath); 74 free(subpath); 75 } 76 closedir(d); 77 rmdir(path); 78 } else { 79 remove(path); 80 } 81} 82 83int 84main(int argc, const char **argv) 85{ 86 char buf[256], *end, *path, 87 **paths, *oldpath, *newpath; 88 unsigned long reftime; 89 int i, pathc, pathcap, nread; 90 const char *dirpath; 91 FILE *f, *fn; 92 93 if (argc != 3) die("USAGE: cleaner DIR REFTIME\n"); 94 95 dirpath = argv[1]; 96 97 reftime = strtoul(argv[2], &end, 10); 98 if (end && *end) die("Invalid unix time reference\n"); 99 100 oldpath = aprintf("%s/.index", dirpath); 101 if (!(f = fopen(oldpath, "r+"))) 102 die("Missing index file: %s\n", oldpath); 103 flock(fileno(f), LOCK_EX); 104 fflush(f); 105 106 newpath = aprintf("%s/.index.next", dirpath); 107 if (!(fn = fopen(newpath, "w+"))) 108 die("Failed to create index file: %s\n", newpath); 109 110 pathc = 0; 111 pathcap = 1024; 112 paths = malloc(pathcap * sizeof(char*)); 113 if (!paths) die("OOM - allocating initial path array\n"); 114 115 while (fgets(buf, sizeof(buf), f)) { 116 if (*buf && buf[strlen(buf)-1] == '\n') 117 buf[strlen(buf)-1] = '\0'; 118 119 path = aprintf("%s/%s", dirpath, buf); 120 if (creation_time(path) < reftime) { 121 paths[pathc] = strdup(path); 122 if (!paths[pathc++]) die("OOM - during path str alloc\n"); 123 if (pathc == pathcap) { 124 pathcap *= 2; 125 paths = realloc(paths, pathcap * sizeof(char*)); 126 if (!paths) die("OOM - too many paths to alloc\n"); 127 } 128 } else { 129 fwrite(buf, 1, strlen(buf), fn); 130 putc('\n', fn); 131 } 132 free(path); 133 } 134 135 fseek(f, 0, SEEK_SET); 136 fseek(fn, 0, SEEK_SET); 137 while ((nread = fread(buf, 1, sizeof(buf), fn)) > 0) 138 fwrite(buf, 1, nread, f); 139 ftruncate(fileno(f), ftell(f)); 140 141 fflush(f); 142 flock(fileno(f), LOCK_UN); 143 fclose(f); 144 fclose(fn); 145 146 for (i = 0; i < pathc; i++) { 147 recdel(paths[i]); 148 printf("CLEANER: REMOVED %s\n", paths[i]); 149 } 150}