#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <darwintest.h>
#include <darwintest_utils.h>
T_DECL(seekdir_basic, "seekdir")
{
const char *path = dt_tmpdir();
int fd = open(path, O_RDONLY | O_DIRECTORY);
openat(fd, "a", O_CREAT | O_WRONLY, 0600);
openat(fd, "b", O_CREAT | O_WRONLY, 0600);
openat(fd, "c", O_CREAT | O_WRONLY, 0600);
DIR *dirp = fdopendir(fd);
struct dirent *entry = NULL;
T_ASSERT_NOTNULL(dirp, NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL); T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
long second_pos = telldir(dirp);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
char *second_name = strdup(entry->d_name);
T_ASSERT_NOTNULL(second_name, NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
seekdir(dirp, second_pos);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
seekdir(dirp, second_pos);
second_pos = telldir(dirp);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
seekdir(dirp, second_pos);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
free(second_name);
T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
}
T_DECL(readdir, "readdir")
{
const char *path = dt_tmpdir();
int fd = open(path, O_RDONLY | O_DIRECTORY);
openat(fd, "foobarbaz", O_CREAT | O_WRONLY, 0600);
DIR *dirp = fdopendir(fd);
T_ASSERT_NOTNULL(dirp, NULL);
struct dirent *entry = NULL;
while ((entry = readdir(dirp)) != NULL) {
if (strcmp(entry->d_name, "foobarbaz")) {
break;
}
}
T_ASSERT_NOTNULL(entry, "found the entry");
T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
}
T_DECL(tell_seek_tell, "tell-seek-tell returns the same location")
{
const char *path = dt_tmpdir();
{
int fd = open(path, O_RDONLY | O_DIRECTORY);
openat(fd, "a", O_CREAT | O_WRONLY, 0600);
openat(fd, "b", O_CREAT | O_WRONLY, 0600);
openat(fd, "c", O_CREAT | O_WRONLY, 0600);
close(fd);
}
DIR *dirp = opendir(path);
T_ASSERT_NOTNULL(dirp, NULL);
struct dirent *entry = NULL;
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
long pos1 = telldir(dirp);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
seekdir(dirp, pos1);
long pos2 = telldir(dirp);
T_ASSERT_EQ(pos1, pos2, NULL);
T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
}
T_DECL(rewinddir, "rewinddir")
{
const char *path = dt_tmpdir();
{
int fd = open(path, O_RDONLY | O_DIRECTORY);
openat(fd, "a", O_CREAT | O_WRONLY, 0600);
openat(fd, "b", O_CREAT | O_WRONLY, 0600);
openat(fd, "c", O_CREAT | O_WRONLY, 0600);
close(fd);
}
DIR *dirp = opendir(path);
T_ASSERT_NOTNULL(dirp, NULL);
struct dirent *entry = NULL;
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
char *third_name = strdup(entry->d_name);
rewinddir(dirp);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_EQ_STR(third_name, entry->d_name, NULL);
free(third_name);
T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
}
T_DECL(rewinddir_dup, "rewinddir dup")
{
const char *path = dt_tmpdir();
int fd = open(path, O_RDONLY | O_DIRECTORY);
openat(fd, "a", O_CREAT | O_WRONLY, 0600);
openat(fd, "b", O_CREAT | O_WRONLY, 0600);
openat(fd, "c", O_CREAT | O_WRONLY, 0600);
DIR *dirp = fdopendir(fd);
T_ASSERT_NOTNULL(dirp, NULL);
struct dirent *entry = NULL;
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
char *third_name = strdup(entry->d_name);
int fd2 = dup(fd);
T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
dirp = fdopendir(fd2);
rewinddir(dirp);
T_ASSERT_NOTNULL(dirp, NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
T_ASSERT_EQ_STR(third_name, entry->d_name, NULL);
free(third_name);
T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
}
static int
_select_abc(const struct dirent *entry)
{
return strcmp(entry->d_name, "a") == 0 ||
strcmp(entry->d_name, "b") == 0 ||
strcmp(entry->d_name, "c") == 0;
}
T_DECL(scandir, "scandir")
{
const char *path = dt_tmpdir();
{
int fd = open(path, O_RDONLY | O_DIRECTORY);
openat(fd, "a", O_CREAT | O_WRONLY, 0600);
openat(fd, "b", O_CREAT | O_WRONLY, 0600);
openat(fd, "c", O_CREAT | O_WRONLY, 0600);
close(fd);
}
struct dirent **entries = NULL;
int found = scandir(path, &entries, _select_abc, alphasort);
T_ASSERT_EQ(found, 3, NULL);
T_ASSERT_EQ_STR(entries[0]->d_name, "a", NULL);
T_ASSERT_EQ_STR(entries[1]->d_name, "b", NULL);
T_ASSERT_EQ_STR(entries[2]->d_name, "c", NULL);
free(entries[0]);
free(entries[1]);
free(entries[2]);
free(entries);
}
T_DECL(scandir_b, "scandir_b")
{
const char *path = dt_tmpdir();
{
int fd = open(path, O_RDONLY | O_DIRECTORY);
openat(fd, "a", O_CREAT | O_WRONLY, 0600);
openat(fd, "b", O_CREAT | O_WRONLY, 0600);
openat(fd, "c", O_CREAT | O_WRONLY, 0600);
close(fd);
}
const struct dirent **entries = NULL;
int found = scandir_b(path, &entries,
^(const struct dirent *entry) {
return strcmp(entry->d_name, "a") == 0 ||
strcmp(entry->d_name, "b") == 0 ||
strcmp(entry->d_name, "c") == 0;
},
^(const struct dirent **d1, const struct dirent **d2) {
return strcoll((*d1)->d_name, (*d2)->d_name);
});
T_ASSERT_EQ(found, 3, NULL);
T_ASSERT_EQ_STR(entries[0]->d_name, "a", NULL);
T_ASSERT_EQ_STR(entries[1]->d_name, "b", NULL);
T_ASSERT_EQ_STR(entries[2]->d_name, "c", NULL);
free(entries[0]);
free(entries[1]);
free(entries[2]);
free(entries);
}