/* DF-3026 - tmpfs APPEND/IMMUTABLE not re-checked per write.
 * usage: df3026 <file> <ctrldir>
 * flow: create file "A"*4096, open O_WRONLY (plain), signal ready,
 * wait for <ctrldir>/go  -> pwrite(fd,"B",1,0)   (middle overwrite)
 * wait for <ctrldir>/go2 -> write(fd,"C",1)      (append at eof offset)
 * report errno for each; exit.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

static void waitfor(const char *p){ struct stat st; while (stat(p,&st)) usleep(20000); }

int main(int argc, char **argv)
{
    char path[512], ctrl[512], buf[4096];
    int fd, r1, r2, e1, e2;
    if (argc != 3) { fprintf(stderr,"usage: df3026 file ctrldir\n"); return 2; }
    snprintf(path,sizeof(path),"%s",argv[1]);
    snprintf(ctrl,sizeof(ctrl),"%s",argv[2]);
    memset(buf,'A',sizeof(buf));
    fd = open(path, O_RDWR|O_CREAT|O_TRUNC, 0644);
    if (fd<0){perror("create");return 1;}
    if (write(fd,buf,sizeof(buf))!=sizeof(buf)){perror("fill");return 1;}
    close(fd);
    fd = open(path, O_WRONLY);           /* plain writable fd, no O_APPEND */
    if (fd<0){perror("open2");return 1;}
    { char rd[600]; snprintf(rd,sizeof(rd),"%s/ready",ctrl);
      if (creat(rd,0644)<0){perror("ready");return 1;} }
    { char g1[600],g2[600];
      snprintf(g1,sizeof(g1),"%s/go",ctrl);   waitfor(g1);
      errno=0; r1=pwrite(fd,"B",1,0); e1=errno;
      snprintf(g2,sizeof(g2),"%s/go2",ctrl);  waitfor(g2);
      errno=0; r2=write(fd,"C",1); e2=errno; }
    printf("PHASE1 pwrite(mid) ret=%d errno=%d (%s)\n", r1, e1, strerror(e1));
    printf("PHASE2 write(eof)  ret=%d errno=%d (%s)\n", r2, e2, strerror(e2));
    { char b[16]; int f=open(path,O_RDONLY); memset(b,0,sizeof b);
      if (f>=0){ read(f,b,8); close(f);} printf("BYTE0=%c FILESIZE_OK\n", b[0]); }
    return 0;
}
