]> git.saurik.com Git - apple/libc.git/blob - tests/dir.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / tests / dir.c
1 #include <dirent.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <unistd.h>
5
6 #include <darwintest.h>
7 #include <darwintest_utils.h>
8
9 T_DECL(seekdir_basic, "seekdir")
10 {
11 const char *path = dt_tmpdir();
12 // make sure there are a couple of entries in the dir aside from . and ..
13 int fd = open(path, O_RDONLY | O_DIRECTORY);
14 openat(fd, "a", O_CREAT | O_WRONLY, 0600);
15 openat(fd, "b", O_CREAT | O_WRONLY, 0600);
16 openat(fd, "c", O_CREAT | O_WRONLY, 0600);
17
18 DIR *dirp = fdopendir(fd);
19 struct dirent *entry = NULL;
20
21 T_ASSERT_NOTNULL(dirp, NULL);
22
23 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL); // .
24 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL); // ..
25
26 // we can get any entry -- no ordering
27 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
28 // remember position for the second entry
29 long second_pos = telldir(dirp);
30 // read the second entry
31 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
32 char *second_name = strdup(entry->d_name);
33 T_ASSERT_NOTNULL(second_name, NULL);
34 // read the third entry
35 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
36
37 // go back to the second entry and read it
38 seekdir(dirp, second_pos);
39 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
40
41 // make sure the name matches the old copy
42 T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
43
44 // return to 2nd once again, reinitializing second_pos and re-reading
45 seekdir(dirp, second_pos);
46 second_pos = telldir(dirp);
47 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
48
49 // make sure the name matches the old copy
50 T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
51
52 // verify that last pos
53 seekdir(dirp, second_pos);
54 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
55 T_ASSERT_EQ_STR(second_name, entry->d_name, NULL);
56
57 free(second_name);
58 T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
59 }
60
61 T_DECL(readdir, "readdir")
62 {
63 const char *path = dt_tmpdir();
64 int fd = open(path, O_RDONLY | O_DIRECTORY);
65 openat(fd, "foobarbaz", O_CREAT | O_WRONLY, 0600);
66
67 DIR *dirp = fdopendir(fd);
68 T_ASSERT_NOTNULL(dirp, NULL);
69
70 struct dirent *entry = NULL;
71 while ((entry = readdir(dirp)) != NULL) {
72 if (strcmp(entry->d_name, "foobarbaz")) {
73 break;
74 }
75 }
76
77 T_ASSERT_NOTNULL(entry, "found the entry");
78
79 T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
80 }
81
82 T_DECL(tell_seek_tell, "tell-seek-tell returns the same location")
83 {
84 // http://pubs.opengroup.org/onlinepubs/009695399/functions/telldir.html
85 // If the most recent operation on the directory stream was a seekdir(),
86 // the directory position returned from the telldir() shall be the same as
87 // that supplied as a loc argument for seekdir().
88
89 const char *path = dt_tmpdir();
90 // make sure there are a couple of entries in the dir aside from . and ..
91 {
92 int fd = open(path, O_RDONLY | O_DIRECTORY);
93 openat(fd, "a", O_CREAT | O_WRONLY, 0600);
94 openat(fd, "b", O_CREAT | O_WRONLY, 0600);
95 openat(fd, "c", O_CREAT | O_WRONLY, 0600);
96 close(fd);
97 }
98
99 DIR *dirp = opendir(path);
100 T_ASSERT_NOTNULL(dirp, NULL);
101 struct dirent *entry = NULL;
102
103 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
104 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
105 long pos1 = telldir(dirp);
106 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
107 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
108 seekdir(dirp, pos1);
109 long pos2 = telldir(dirp);
110
111 T_ASSERT_EQ(pos1, pos2, NULL);
112
113 T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
114 }
115
116 T_DECL(rewinddir, "rewinddir")
117 {
118 const char *path = dt_tmpdir();
119 // make sure there are a couple of entries in the dir aside from . and ..
120 {
121 int fd = open(path, O_RDONLY | O_DIRECTORY);
122 openat(fd, "a", O_CREAT | O_WRONLY, 0600);
123 openat(fd, "b", O_CREAT | O_WRONLY, 0600);
124 openat(fd, "c", O_CREAT | O_WRONLY, 0600);
125 close(fd);
126 }
127
128 DIR *dirp = opendir(path);
129 T_ASSERT_NOTNULL(dirp, NULL);
130 struct dirent *entry = NULL;
131
132 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
133 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
134 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
135 char *third_name = strdup(entry->d_name);
136
137 rewinddir(dirp);
138
139 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
140 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
141 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
142
143 T_ASSERT_EQ_STR(third_name, entry->d_name, NULL);
144
145 free(third_name);
146 T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
147 }
148
149
150 T_DECL(rewinddir_dup, "rewinddir dup")
151 {
152 // An older implementation of rewinddir failed to seek the fd which was
153 // passed to fdopendir()
154
155 const char *path = dt_tmpdir();
156 // make sure there are a couple of entries in the dir aside from . and ..
157 int fd = open(path, O_RDONLY | O_DIRECTORY);
158 openat(fd, "a", O_CREAT | O_WRONLY, 0600);
159 openat(fd, "b", O_CREAT | O_WRONLY, 0600);
160 openat(fd, "c", O_CREAT | O_WRONLY, 0600);
161
162 // prep an fd with a non-zero seek
163 DIR *dirp = fdopendir(fd);
164 T_ASSERT_NOTNULL(dirp, NULL);
165 struct dirent *entry = NULL;
166
167 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
168 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
169 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
170
171 // remember the entry name and dup the fd
172 char *third_name = strdup(entry->d_name);
173 int fd2 = dup(fd);
174
175 T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
176
177 dirp = fdopendir(fd2);
178 // rewind back to 0
179 rewinddir(dirp);
180
181 T_ASSERT_NOTNULL(dirp, NULL);
182 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
183 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
184 T_ASSERT_NOTNULL(entry = readdir(dirp), NULL);
185
186 T_ASSERT_EQ_STR(third_name, entry->d_name, NULL);
187
188 free(third_name);
189 T_ASSERT_POSIX_ZERO(closedir(dirp), NULL);
190 }
191
192 static int
193 _select_abc(const struct dirent *entry)
194 {
195 return strcmp(entry->d_name, "a") == 0 ||
196 strcmp(entry->d_name, "b") == 0 ||
197 strcmp(entry->d_name, "c") == 0;
198 }
199
200 T_DECL(scandir, "scandir")
201 {
202 const char *path = dt_tmpdir();
203 {
204 int fd = open(path, O_RDONLY | O_DIRECTORY);
205 openat(fd, "a", O_CREAT | O_WRONLY, 0600);
206 openat(fd, "b", O_CREAT | O_WRONLY, 0600);
207 openat(fd, "c", O_CREAT | O_WRONLY, 0600);
208 close(fd);
209 }
210
211 struct dirent **entries = NULL;
212 int found = scandir(path, &entries, _select_abc, alphasort);
213
214 T_ASSERT_EQ(found, 3, NULL);
215
216 T_ASSERT_EQ_STR(entries[0]->d_name, "a", NULL);
217 T_ASSERT_EQ_STR(entries[1]->d_name, "b", NULL);
218 T_ASSERT_EQ_STR(entries[2]->d_name, "c", NULL);
219
220 free(entries[0]);
221 free(entries[1]);
222 free(entries[2]);
223 free(entries);
224 }
225
226 T_DECL(scandir_b, "scandir_b")
227 {
228 const char *path = dt_tmpdir();
229 {
230 int fd = open(path, O_RDONLY | O_DIRECTORY);
231 openat(fd, "a", O_CREAT | O_WRONLY, 0600);
232 openat(fd, "b", O_CREAT | O_WRONLY, 0600);
233 openat(fd, "c", O_CREAT | O_WRONLY, 0600);
234 close(fd);
235 }
236
237 const struct dirent **entries = NULL;
238 int found = scandir_b(path, &entries,
239 ^(const struct dirent *entry) {
240 return strcmp(entry->d_name, "a") == 0 ||
241 strcmp(entry->d_name, "b") == 0 ||
242 strcmp(entry->d_name, "c") == 0;
243 },
244 ^(const struct dirent **d1, const struct dirent **d2) {
245 return strcoll((*d1)->d_name, (*d2)->d_name);
246 });
247
248 T_ASSERT_EQ(found, 3, NULL);
249
250 T_ASSERT_EQ_STR(entries[0]->d_name, "a", NULL);
251 T_ASSERT_EQ_STR(entries[1]->d_name, "b", NULL);
252 T_ASSERT_EQ_STR(entries[2]->d_name, "c", NULL);
253
254 free(entries[0]);
255 free(entries[1]);
256 free(entries[2]);
257 free(entries);
258 }