/*
 * DF-3159 trigger: grow the file through ftruncate in steps so the kernel
 * zero-fill drains between steps, then one final ftruncate past
 * MSDOSFS_FILESIZE_MAX (0xFFFFFFFF).  The final size 0x100010000
 * (4 GiB + 64 KiB) truncates to 0x10000 in the 32-bit dirent field.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

int main(int argc, char **argv)
{
	const char *path = argv[1];
	unsigned long long target = 0x100010000ULL, cur = 0, step = 64ULL<<20;
	int fd = open(path, O_RDWR);

	if (fd < 0) { perror("open"); return 2; }
	while (cur + step < target) {
		cur += step;
		if (ftruncate(fd, cur) < 0) {
			printf("ftruncate(%llu) FAILED %s\n", cur, strerror(errno));
			return 1;
		}
	}
	printf("stepped to %llu; final ftruncate(0x%llx):\n", cur, target);
	fflush(stdout);
	if (ftruncate(fd, (off_t)target) < 0) {
		printf("final ftruncate FAILED errno=%d (%s)\n", errno, strerror(errno));
		return 1;
	}
	struct stat st;
	fstat(fd, &st);
	printf("OK: in-memory size %jd (0x%jx) -- dirent field will store 0x%llx\n",
	       (intmax_t)st.st_size, (uintmax_t)st.st_size,
	       (unsigned long long)(target & 0xFFFFFFFFULL));
	return 0;
}
