Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/test/dirent/test_readdir.c
4130 views
1
/*
2
* Copyright 2013 The Emscripten Authors. All rights reserved.
3
* Emscripten is available under two separate licenses, the MIT license and the
4
* University of Illinois/NCSA Open Source License. Both these licenses can be
5
* found in the LICENSE file.
6
*/
7
8
#include <assert.h>
9
#include <dirent.h>
10
#include <errno.h>
11
#include <fcntl.h>
12
#include <signal.h>
13
#include <stdio.h>
14
#include <stdlib.h>
15
#include <string.h>
16
#include <unistd.h>
17
#include <sys/stat.h>
18
19
#define CHECK(cond) if (!(cond)) { printf("errno: %s\n", strerror(errno)); assert(cond); }
20
21
static void create_file(const char *path, const char *buffer, int mode) {
22
int fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
23
CHECK(fd >= 0);
24
25
int err = write(fd, buffer, sizeof(char) * strlen(buffer));
26
assert(err == (sizeof(char) * strlen(buffer)));
27
28
close(fd);
29
}
30
31
void setup() {
32
int err;
33
err = mkdir("testtmp", 0777); // can't call it tmp, that already exists
34
CHECK(!err);
35
chdir("testtmp");
36
err = mkdir("nocanread", 0111);
37
CHECK(!err);
38
err = mkdir("foobar", 0777);
39
CHECK(!err);
40
create_file("foobar/file.txt", "ride into the danger zone", 0666);
41
}
42
43
void test() {
44
int err;
45
long loc, loc2;
46
DIR *dir;
47
struct dirent *ent;
48
struct dirent ent_r;
49
struct dirent *result;
50
int i;
51
52
// check bad opendir input
53
dir = opendir("noexist");
54
assert(!dir);
55
assert(errno == ENOENT);
56
// NODERAWFS tests run as root, and the root user can opendir any directory
57
#ifndef NODERAWFS
58
dir = opendir("nocanread");
59
assert(!dir);
60
assert(errno == EACCES);
61
#endif
62
dir = opendir("foobar/file.txt");
63
assert(!dir);
64
assert(errno == ENOTDIR);
65
66
// check bad readdir input
67
//dir = opendir("foobar");
68
//closedir(dir);
69
//ent = readdir(dir);
70
//assert(!ent);
71
// XXX musl doesn't have enough error handling for this: assert(errno == EBADF);
72
73
// check bad readdir_r input
74
//dir = opendir("foobar");
75
//closedir(dir);
76
//err = readdir_r(dir, NULL, &result);
77
// XXX musl doesn't have enough error handling for this: assert(err == EBADF);
78
79
//
80
// do a normal read with readdir
81
//
82
dir = opendir("foobar");
83
assert(dir);
84
int seen[3] = { 0, 0, 0 };
85
for (i = 0; i < 3; i++) {
86
errno = 0;
87
ent = readdir(dir);
88
if (ent) {
89
fprintf(stderr, "%d file: %s (%d : %lu)\n", i, ent->d_name, ent->d_reclen, sizeof(*ent));
90
} else {
91
fprintf(stderr, "ent: %p, errno: %d\n", ent, errno);
92
assert(ent);
93
}
94
assert(ent->d_reclen == sizeof(*ent));
95
if (!seen[0] && !strcmp(ent->d_name, ".")) {
96
assert(ent->d_type & DT_DIR);
97
seen[0] = 1;
98
continue;
99
}
100
if (!seen[1] && !strcmp(ent->d_name, "..")) {
101
assert(ent->d_type & DT_DIR);
102
seen[1] = 1;
103
continue;
104
}
105
if (!seen[2] && !strcmp(ent->d_name, "file.txt")) {
106
assert(ent->d_type & DT_REG);
107
seen[2] = 1;
108
continue;
109
}
110
assert(0 && "odd filename");
111
}
112
ent = readdir(dir);
113
if (ent) printf("surprising ent: %p : %s\n", ent, ent->d_name);
114
assert(!ent);
115
116
// test rewinddir
117
rewinddir(dir);
118
ent = readdir(dir);
119
assert(ent && ent->d_ino);
120
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
121
122
// test seek / tell
123
rewinddir(dir);
124
ent = readdir(dir);
125
assert(ent && ent->d_ino);
126
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
127
loc = telldir(dir);
128
assert(loc >= 0);
129
//printf("loc=%d\n", loc);
130
loc2 = ent->d_off;
131
ent = readdir(dir);
132
assert(ent && ent->d_ino);
133
char name_at_loc[1024];
134
strcpy(name_at_loc, ent->d_name);
135
//printf("name_at_loc: %s\n", name_at_loc);
136
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
137
ent = readdir(dir);
138
#ifndef WASMFS_NODERAWFS
139
// WasmFS + NODERAWFS lacks ino numbers in directory listings, see
140
// https://github.com/emscripten-core/emscripten/issues/19418
141
// This is not an issue for "." and ".." (the other checks before and after
142
// us) since "." and ".." are added by WasmFS code itself; only "file.txt" is
143
// added from the node JS API, and as a result it has inode 0.
144
assert(ent && ent->d_ino);
145
#endif
146
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
147
seekdir(dir, loc);
148
ent = readdir(dir);
149
assert(ent && ent->d_ino);
150
//printf("check: %s / %s\n", ent->d_name, name_at_loc);
151
assert(!strcmp(ent->d_name, name_at_loc));
152
153
seekdir(dir, loc2);
154
ent = readdir(dir);
155
assert(ent && ent->d_ino);
156
//printf("check: %s / %s\n", ent->d_name, name_at_loc);
157
assert(!strcmp(ent->d_name, name_at_loc));
158
159
//
160
// do a normal read with readdir_r
161
//
162
rewinddir(dir);
163
err = readdir_r(dir, &ent_r, &result);
164
assert(!err);
165
assert(&ent_r == result);
166
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
167
err = readdir_r(dir, &ent_r, &result);
168
assert(!err);
169
assert(&ent_r == result);
170
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
171
err = readdir_r(dir, &ent_r, &result);
172
assert(!err);
173
assert(&ent_r == result);
174
assert(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "file.txt"));
175
err = readdir_r(dir, &ent_r, &result);
176
assert(!err);
177
assert(!result);
178
179
err = closedir(dir);
180
assert(!err);
181
182
puts("success");
183
}
184
185
void test_scandir() {
186
struct dirent **namelist;
187
int n;
188
189
n = scandir(".", &namelist, NULL, alphasort);
190
printf("n: %d\n", n);
191
if (n < 0)
192
return;
193
else {
194
while (n--) {
195
printf("name: %s\n", namelist[n]->d_name);
196
free(namelist[n]);
197
}
198
free(namelist);
199
}
200
}
201
202
int main() {
203
setup();
204
test();
205
test_scandir();
206
207
return 0;
208
}
209
210