#include #include #include #include #include #include #include #include #include #include #include #include #include #include static uint64_t parse_u64(const char *text) { char *end; uintmax_t value; errno = 0; value = strtoumax(text, &end, 0); if (errno != 0 || *text == '\0' || *end != '\0' || value > UINT64_MAX) errx(2, "invalid integer: %s", text); return ((uint64_t)value); } static void stat_blocks(const char *path, const char *expected_text) { fhandle_t handle; struct stat direct, by_handle; uint64_t expected; expected = parse_u64(expected_text); if (stat(path, &direct) != 0) err(1, "stat %s", path); if (getfh(path, &handle) != 0) err(1, "getfh %s", path); if (fhstat(&handle, &by_handle) != 0) err(1, "fhstat %s", path); if ((uint64_t)direct.st_blocks != expected || (uint64_t)by_handle.st_blocks != expected) errx(1, "st_blocks direct=%jd handle=%jd expected=%" PRIu64, (intmax_t)direct.st_blocks, (intmax_t)by_handle.st_blocks, expected); printf("direct_blocks=%jd handle_blocks=%jd size=%jd expected=%" PRIu64 "\n", (intmax_t)direct.st_blocks, (intmax_t)by_handle.st_blocks, (intmax_t)direct.st_size, expected); } static void expect_stat_error(const char *path, const char *expected_text) { struct stat status; int expected; expected = (int)parse_u64(expected_text); errno = 0; if (stat(path, &status) != -1) errx(1, "stat unexpectedly succeeded: %s", path); if (errno != expected) errx(1, "stat errno=%d expected=%d", errno, expected); printf("stat_errno=%d path=%s\n", errno, path); } static void readdir_offmax(const char *path, const char *expected_text) { char buffer[512]; off_t base, current; ssize_t bytes; int descriptor, expected; expected = (int)parse_u64(expected_text); descriptor = open(path, O_RDONLY | O_DIRECTORY); if (descriptor < 0) err(1, "open %s", path); if (lseek(descriptor, OFF_MAX, SEEK_SET) != OFF_MAX) err(1, "lseek OFF_MAX"); base = 0; errno = 0; bytes = getdirentries(descriptor, buffer, sizeof(buffer), &base); if (bytes != -1 || errno != expected) errx(1, "OFF_MAX getdirentries bytes=%zd errno=%d expected=%d", bytes, errno, expected); current = lseek(descriptor, 0, SEEK_CUR); if (current < 0 || current != OFF_MAX) errx(1, "negative or changed post-error offset: %jd", (intmax_t)current); if (lseek(descriptor, 0, SEEK_SET) != 0) err(1, "lseek zero"); base = 0; errno = 0; bytes = getdirentries(descriptor, buffer, sizeof(buffer), &base); if (bytes != -1 || errno != expected) errx(1, "zero-offset getdirentries bytes=%zd errno=%d expected=%d", bytes, errno, expected); current = lseek(descriptor, 0, SEEK_CUR); if (current < 0 || current != 0) errx(1, "negative or changed zero offset: %jd", (intmax_t)current); if (close(descriptor) != 0) err(1, "close %s", path); printf("offmax_errno=%d offmax_offset=%jd zero_errno=%d zero_offset=%jd\n", expected, (intmax_t)OFF_MAX, expected, (intmax_t)current); } int main(int argc, char **argv) { if (argc == 4 && strcmp(argv[1], "stat-blocks") == 0) { stat_blocks(argv[2], argv[3]); return (0); } if (argc == 4 && strcmp(argv[1], "expect-stat-error") == 0) { expect_stat_error(argv[2], argv[3]); return (0); } if (argc == 4 && strcmp(argv[1], "readdir-offmax") == 0) { readdir_offmax(argv[2], argv[3]); return (0); } errx(2, "usage: %s stat-blocks PATH EXPECTED | " "expect-stat-error PATH ERRNO | readdir-offmax PATH ERRNO", argv[0]); }