| /* |
| * Copyright 2013 The Emscripten Authors. All rights reserved. |
| * Emscripten is available under two separate licenses, the MIT license and the |
| * University of Illinois/NCSA Open Source License. Both these licenses can be |
| * found in the LICENSE file. |
| */ |
| |
| #include <assert.h> |
| #include <dirent.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <signal.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/stat.h> |
| |
| static void create_file(const char *path, const char *buffer, int mode) { |
| int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode); |
| assert(fd >= 0); |
| |
| int err = write(fd, buffer, sizeof(char) * strlen(buffer)); |
| assert(err == (sizeof(char) * strlen(buffer))); |
| |
| close(fd); |
| } |
| |
| void setup() { |
| int err; |
| err = mkdir("nocanread", 0111); |
| assert(!err); |
| err = mkdir("foobar", 0777); |
| assert(!err); |
| create_file("foobar/file.txt", "ride into the danger zone", 0666); |
| } |
| |
| void cleanup() { |
| rmdir("nocanread"); |
| unlink("foobar/file.txt"); |
| rmdir("foobar"); |
| } |
| |
| void test() { |
| int err; |
| long loc, loc2; |
| DIR *dir; |
| struct dirent *ent; |
| struct dirent ent_r; |
| struct dirent *result; |
| int i; |
| |
| // check bad opendir input |
| dir = opendir("noexist"); |
| assert(!dir); |
| assert(errno == ENOENT); |
| dir = opendir("nocanread"); |
| assert(!dir); |
| assert(errno == EACCES); |
| dir = opendir("foobar/file.txt"); |
| assert(!dir); |
| assert(errno == ENOTDIR); |
| |
| // check bad readdir input |
| //dir = opendir("foobar"); |
| //closedir(dir); |
| //ent = readdir(dir); |
| //assert(!ent); |
| // XXX musl doesn't have enough error handling for this: assert(errno == EBADF); |
| |
| // check bad readdir_r input |
| //dir = opendir("foobar"); |
| //closedir(dir); |
| //err = readdir_r(dir, NULL, &result); |
| // XXX musl doesn't have enough error handling for this: assert(err == EBADF); |
| |
| // |
| // do a normal read with readdir |
| // |
| dir = opendir("foobar"); |
| assert(dir); |
| int seen[3] = { 0, 0, 0 }; |
| for (i = 0; i < 3; i++) { |
| errno = 0; |
| ent = readdir(dir); |
| //printf("ent, errno: %p, %d\n", ent, errno); |
| assert(ent); |
| //printf("%d file: %s (%d : %d)\n", i, ent->d_name, ent->d_reclen, sizeof(*ent)); |
| assert(ent->d_reclen == sizeof(*ent)); |
| if (!seen[0] && !strcmp(ent->d_name, ".")) { |
| assert(ent->d_type & DT_DIR); |
| seen[0] = 1; |
| continue; |
| } |
| if (!seen[1] && !strcmp(ent->d_name, "..")) { |
| assert(ent->d_type & DT_DIR); |
| seen[1] = 1; |
| continue; |
| } |
| if (!seen[2] && !strcmp(ent->d_name, "file.txt")) { |
| assert(ent->d_type & DT_REG); |
| seen[2] = 1; |
| continue; |
| } |
| assert(0 && "odd filename"); |
| } |
| ent = readdir(dir); |
| if (ent) printf("surprising ent: %p : %s\n", ent, ent->d_name); |
| assert(!ent); |
| |
| // test rewinddir |
| rewinddir(dir); |
| ent = readdir(dir); |
| assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt")); |
| |
| // test seek / tell |
| rewinddir(dir); |
| ent = readdir(dir); |
| assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt")); |
| loc = telldir(dir); |
| assert(loc >= 0); |
| //printf("loc=%d\n", loc); |
| loc2 = ent->d_off; |
| ent = readdir(dir); |
| char name_at_loc[1024]; |
| strcpy(name_at_loc, ent->d_name); |
| //printf("name_at_loc: %s\n", name_at_loc); |
| assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt")); |
| ent = readdir(dir); |
| assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt")); |
| seekdir(dir, loc); |
| ent = readdir(dir); |
| assert(ent); |
| //printf("check: %s / %s\n", ent->d_name, name_at_loc); |
| assert(!strcmp(ent->d_name, name_at_loc)); |
| |
| seekdir(dir, loc2); |
| ent = readdir(dir); |
| assert(ent); |
| //printf("check: %s / %s\n", ent->d_name, name_at_loc); |
| assert(!strcmp(ent->d_name, name_at_loc)); |
| |
| // |
| // do a normal read with readdir_r |
| // |
| rewinddir(dir); |
| err = readdir_r(dir, &ent_r, &result); |
| assert(!err); |
| assert(&ent_r == result); |
| assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt")); |
| err = readdir_r(dir, &ent_r, &result); |
| assert(!err); |
| assert(&ent_r == result); |
| assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt")); |
| err = readdir_r(dir, &ent_r, &result); |
| assert(!err); |
| assert(&ent_r == result); |
| assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt")); |
| err = readdir_r(dir, &ent_r, &result); |
| assert(!err); |
| assert(!result); |
| |
| err = closedir(dir); |
| assert(!err); |
| |
| puts("success"); |
| } |
| |
| void test_scandir() { |
| struct dirent **namelist; |
| int n; |
| |
| n = scandir(".", &namelist, NULL, alphasort); |
| printf("n: %d\n", n); |
| if (n < 0) |
| return; |
| else { |
| while (n--) { |
| printf("name: %s\n", namelist[n]->d_name); |
| free(namelist[n]); |
| } |
| free(namelist); |
| } |
| } |
| |
| int main() { |
| atexit(cleanup); |
| signal(SIGABRT, cleanup); |
| setup(); |
| test(); |
| test_scandir(); |
| |
| #ifdef REPORT_RESULT |
| REPORT_RESULT(0); |
| #endif |
| return EXIT_SUCCESS; |
| } |