Files
erofs-freebsd-out-tree/tests/results/manual/2026-08-08T1800Z-namei/readdir_probe.c
T
2026-08-18 09:20:44 +02:00

72 lines
1.8 KiB
C

#include <sys/types.h>
#include <sys/dirent.h>
#include <dirent.h>
#include <err.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
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);
}