Loading...
--- /dev/null
+++ Libc/Libc-1583.60.2/tests/dir.c
@@ -0,0 +1,258 @@
+#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();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ 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); // ..
+
+ // we can get any entry -- no ordering
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ // remember position for the second entry
+ long second_pos = telldir(dirp);
+ // read the second entry
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+ char *second_name = strdup(entry->d_name);
+ T_ASSERT_NOTNULL(second_name, NULL);
+ // read the third entry
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ // go back to the second entry and read it
+ seekdir(dirp, second_pos);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ // make sure the name matches the old copy
+ T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
+
+ // return to 2nd once again, reinitializing second_pos and re-reading
+ seekdir(dirp, second_pos);
+ second_pos = telldir(dirp);
+ T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
+
+ // make sure the name matches the old copy
+ T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
+
+ // verify that last pos
+ 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")
+{
+ // http://pubs.opengroup.org/onlinepubs/009695399/functions/telldir.html
+ // If the most recent operation on the directory stream was a seekdir(),
+ // the directory position returned from the telldir() shall be the same as
+ // that supplied as a loc argument for seekdir().
+
+ const char *path = dt_tmpdir();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ {
+ 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();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ {
+ 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")
+{
+ // An older implementation of rewinddir failed to seek the fd which was
+ // passed to fdopendir()
+
+ const char *path = dt_tmpdir();
+ // make sure there are a couple of entries in the dir aside from . and ..
+ 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);
+
+ // prep an fd with a non-zero seek
+ 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);
+
+ // remember the entry name and dup the fd
+ char *third_name = strdup(entry->d_name);
+ int fd2 = dup(fd);
+
+ T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
+
+ dirp = fdopendir(fd2);
+ // rewind back to 0
+ 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);
+}