DF-3026 / df3026.c
/* 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; } |