#include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { struct dirent *entry; off_t base, before, start; char *buffer; char *end; size_t buffer_size; ssize_t bytes; int calls, fd; if (argc < 2 || argc > 5) errx(2, "usage: %s directory [offset [buffer-size [calls]]]", argv[0]); start = argc >= 3 ? strtoll(argv[2], NULL, 0) : 0; buffer_size = argc >= 4 ? strtoul(argv[3], NULL, 0) : 128; calls = argc >= 5 ? strtol(argv[4], NULL, 0) : 32; if (buffer_size < 32 || calls < 1) errx(2, "invalid buffer size or call count"); fd = open(argv[1], O_RDONLY | O_DIRECTORY); if (fd < 0) err(1, "open %s", argv[1]); if (lseek(fd, start, SEEK_SET) < 0) err(1, "lseek %jd", (intmax_t)start); buffer = malloc(buffer_size); if (buffer == NULL) err(1, "malloc"); for (int call = 0; call < calls; call++) { before = lseek(fd, 0, SEEK_CUR); if (before < 0) err(1, "lseek current"); base = -1; bytes = getdirentries(fd, buffer, buffer_size, &base); if (bytes < 0) err(1, "getdirentries"); printf("call=%d before=%jd after=%jd base=%jd bytes=%zd\n", call, (intmax_t)before, (intmax_t)lseek(fd, 0, SEEK_CUR), (intmax_t)base, bytes); if (bytes == 0) break; end = buffer + bytes; for (entry = (struct dirent *)buffer; (char *)entry < end; entry = (struct dirent *)((char *)entry + entry->d_reclen)) { if (entry->d_reclen == 0 || (char *)entry + entry->d_reclen > end) errx(1, "invalid dirent record"); printf(" off=%jd ino=%ju reclen=%u type=%u name=%.*s\n", (intmax_t)entry->d_off, (uintmax_t)entry->d_fileno, entry->d_reclen, entry->d_type, entry->d_namlen, entry->d_name); } } free(buffer); close(fd); return (0); }