DragonFlyBSD Kernel Audit
DF-2645 / delsome.c
← back to finding ↓ download raw
/* delsome: delete pct% of the named files under dir, randomized order,
 * in batches with syncs, so the flusher's indirect-maintenance sees
 * sparsified indirect blocks and collapses them. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
	const char *dir = argv[1];
	const char *list = argv[2];
	int pct = argc > 3 ? atoi(argv[3]) : 90;
	char line[512], path[1024];
	char **names;
	int n = 0, i, del = 0;
	FILE *f;
	unsigned long st = 99991;

	if ((f = fopen(list, "r")) == NULL) { perror(list); exit(1); }
	names = calloc(200000, sizeof(char *));
	while (fgets(line, sizeof(line), f)) {
		int len = strlen(line);
		if (len && line[len-1] == '\n') line[--len] = 0;
		if (len == 0) continue;
		asprintf(&names[n], "%s", line);
		++n;
	}
	fclose(f);

	/* Fisher-Yates with cheap LCG */
	for (i = n - 1; i > 0; --i) {
		int j;
		char *t;
		st = st * 6364136223846793005UL + 1442695040888963407UL;
		j = (int)((st >> 33) % (i + 1));
		t = names[i]; names[i] = names[j]; names[j] = t;
	}

	for (i = 0; i < n; ++i) {
		if (i >= (long)n * pct / 100)
			break;
		snprintf(path, sizeof(path), "%s/%s", dir, names[i]);
		if (unlink(path) == 0)
			++del;
		if ((i % 512) == 511)
			sync();
	}
	sync();
	fprintf(stderr, "deleted %d/%d\n", del, n);
	return 0;
}