enowars5-service-stldoctor

STL-Analyzing A/D Service for ENOWARS5 in 2021
git clone https://git.sinitax.com/sinitax/enowars5-service-stldoctor
Log | Files | Refs | README | LICENSE | sfeed.txt

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}