/* * 976_stat_run — execute the lib/os stat fixture under the C-side * `ww test` driver and assert exit 0. * * Workflow (mirrors 975_dirs_run's mkdtemp + exact-cleanup shape): * 1. mkdtemp /tmp/wwstat-XXXXXX — fresh per run, no parallel-test * contention. * 2. Populate the scratch tree: * /regfile regular file, 11 bytes "hello world" * /symlink → ./regfile (relative symlink) * /subdir directory, mode 0700 * 3. setenv WW_TEST_STAT_REGFILE / SYMLINK / SUBDIR / NOENT with * the absolute paths; lib/os/stat_test.ww reads them via * os.getenv and exercises stat/lstat/fstat/exists. * 4. exec `ww test lib/os/stat_test.ww`. * 5. Remove the exact children and then the mkdtemp-owned root. * * Same wrapper shape as 970-975; cleanup runs on success and failure. */ #include #include #include #include #include #include #include #include static int runwait(const char *cmd) { int rc = system(cmd); if (rc == -1) return -1; if (WIFEXITED(rc)) return WEXITSTATUS(rc); return 1; } int main(void) { const char *bin = getenv("BIN"); if (!bin) bin = "out/bin"; char absbin[1024]; if (bin[0] != '/') { char cwd[1024]; if (getcwd(cwd, sizeof cwd) == NULL) return 1; snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin); bin = absbin; } char cwd[1024]; if (getcwd(cwd, sizeof cwd) == NULL) return 1; char tmpl[64]; strcpy(tmpl, "/tmp/wwstat-XXXXXX"); if (mkdtemp(tmpl) == NULL) { perror("mkdtemp"); return 1; } char regfile[256], symlink_path[256], subdir[256], noent[256]; snprintf(regfile, sizeof regfile, "%s/regfile", tmpl); snprintf(symlink_path, sizeof symlink_path, "%s/symlink", tmpl); snprintf(subdir, sizeof subdir, "%s/subdir", tmpl); snprintf(noent, sizeof noent, "%s/does-not-exist", tmpl); const char *src = "lib/os/stat_test.ww"; int fail = 0, subdir_owned = 0; /* Populate. */ int fd = open(regfile, O_WRONLY | O_CREAT | O_EXCL, 0644); if (fd < 0) { perror("open regfile"); fail = 1; goto cleanup; } if (write(fd, "hello world", 11) != 11) { perror("write regfile"); close(fd); fail = 1; goto cleanup; } close(fd); if (symlink("./regfile", symlink_path) != 0) { perror("symlink"); fail = 1; goto cleanup; } if (mkdir(subdir, 0700) != 0) { perror("mkdir subdir"); fail = 1; goto cleanup; } subdir_owned = 1; setenv("WW_TEST_STAT_REGFILE", regfile, 1); setenv("WW_TEST_STAT_SYMLINK", symlink_path, 1); setenv("WW_TEST_STAT_SUBDIR", subdir, 1); setenv("WW_TEST_STAT_NOENT", noent, 1); char path[1024], cmd[2048]; snprintf(path, sizeof path, "%s/%s", cwd, src); snprintf(cmd, sizeof cmd, "%s/ww test %s", bin, path); int rc = runwait(cmd); if (rc != 0) { fprintf(stderr, "stat_run FAIL: %s exited %d\n", src, rc); fail = 1; } cleanup: { int cleanbad = 0; if (unlink(symlink_path) != 0 && errno != ENOENT) cleanbad = 1; if (unlink(regfile) != 0 && errno != ENOENT) cleanbad = 1; if (subdir_owned && rmdir(subdir) != 0) cleanbad = 1; if (rmdir(tmpl) != 0) cleanbad = 1; if (cleanbad) { fprintf(stderr, "stat_run FAIL: temporary cleanup failed\n"); fail = 1; } } if (fail) return 1; printf("stat_run: %s ok\n", src); return 0; }