#include "test_utils.h" #include static int expect_errno(const char *what, int exp) { if (errno != exp) { fprintf(stderr, "%s: errno=%d expected=%d\n", what, errno, exp); return -1; } return 0; } static int test_phase2(const char *root) { char dir[PATH_MAX]; char file[PATH_MAX]; char file2[PATH_MAX]; struct stat st; int dfd = -1; int fd = -1; snprintf(dir, sizeof(dir), "%s/p2db", root); snprintf(file, sizeof(file), "%s/p2db/data.log", root); snprintf(file2, sizeof(file2), "%s/p2db/data2.log", root); (void)unlink(file2); (void)unlink(file); (void)rmdir(dir); if (mkdir(dir, 0755) != 0) { perror("mkdir"); return 1; } dfd = open(dir, O_RDONLY | O_DIRECTORY); if (dfd < 0) { perror("open dir"); return 2; } fd = openat(dfd, "data.log", O_CREAT | O_RDWR | O_TRUNC, 0644); if (fd < 0) { perror("openat create"); return 3; } if (write(fd, "ABCD", 4) != 4) { perror("write"); return 4; } if (pwrite(fd, "XYZ", 3, 8) != 3) { perror("pwrite"); return 5; } char buf[16] = {0}; ssize_t n = pread(fd, buf, 11, 0); if (n != 11) { perror("pread"); return 6; } if (memcmp(buf, "ABCD", 4) != 0 || buf[4] || buf[5] || buf[6] || buf[7] || memcmp(buf + 8, "XYZ", 3) != 0) { fprintf(stderr, "pread sparse verify failed\n"); return 7; } if (fsync(fd) != 0) { perror("fsync"); return 8; } if (fdatasync(fd) != 0) { perror("fdatasync"); return 9; } if (fstat(fd, &st) != 0) { perror("fstat"); return 10; } if (st.st_size != 11) { fprintf(stderr, "fstat size=%ld expected=11\n", (long)st.st_size); return 11; } if (ftruncate(fd, 4) != 0) { perror("ftruncate"); return 12; } memset(buf, 0, sizeof(buf)); n = pread(fd, buf, 16, 0); if (n != 4 || memcmp(buf, "ABCD", 4) != 0) { fprintf(stderr, "truncate readback failed n=%zd\n", n); return 13; } if (rename(file, file2) != 0) { perror("rename"); return 14; } if (access(file, F_OK) == 0 || expect_errno("access old", ENOENT) != 0) { return 15; } if (access(file2, F_OK) != 0) { perror("access new"); return 16; } int fd2 = open(file2, O_CREAT | O_EXCL | O_RDWR, 0644); if (fd2 >= 0 || expect_errno("open excl", EEXIST) != 0) { if (fd2 >= 0) close(fd2); return 17; } int rd = open(file2, O_RDONLY); if (rd < 0) { perror("open rdonly"); return 18; } if (write(rd, "Q", 1) >= 0 || expect_errno("write rdonly", EBADF) != 0) { close(rd); return 19; } close(rd); close(fd); close(dfd); if (unlink(file2) != 0) { perror("unlink"); return 20; } if (rmdir(dir) != 0) { perror("rmdir"); return 21; } return 0; } int main(int argc, char **argv) { const char *root = argc >= 2 ? argv[1] : "/zvfs"; int rc = test_phase2(root); return report_result("test_phase2_posix", rc); }