// host_cuse_swapper.c - synchronized regular-file <-> /dev/cuse swapper.
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
#ifndef RENAME_EXCHANGE
#define RENAME_EXCHANGE (1U<<1)
#endif
int main(int argc,char**argv){if(argc<3)return 2;int d=open(argv[1],O_RDONLY|O_DIRECTORY|O_CLOEXEC),secs=atoi(argv[2]);if(d<0)return 2;
 unlinkat(d,"target",0);unlinkat(d,"swapdev",0);unlinkat(d,"guest-ready",0);unlinkat(d,"host-go",0);int f=openat(d,"target",O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC,0666);if(f<0)return 2;if(write(f,"x",1)!=1)return 2;close(f);
 if(mknodat(d,"swapdev",S_IFCHR|0666,makedev(10,203)))return 2;struct stat st;for(int i=0;fstatat(d,"guest-ready",&st,0)&&i<30000;i++)usleep(1000);f=openat(d,"host-go",O_WRONLY|O_CREAT|O_CLOEXEC,0666);if(f<0)return 2;close(f);
 struct timespec s,n={0};clock_gettime(CLOCK_MONOTONIC,&s);unsigned long c=0;do{if(syscall(SYS_renameat2,d,"target",d,"swapdev",RENAME_EXCHANGE))return 2;c++;if((c&4095)==0)clock_gettime(CLOCK_MONOTONIC,&n);}while(n.tv_sec-s.tv_sec<secs);printf("CUSE_SWAPS=%lu\n",c);return 0;}
