xref: /aosp_15_r20/bionic/tests/dirent_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
18*8d67ca89SAndroid Build Coastguard Worker 
19*8d67ca89SAndroid Build Coastguard Worker #include <dirent.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <errno.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <fcntl.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <limits.h>
23*8d67ca89SAndroid Build Coastguard Worker #include <sys/cdefs.h>
24*8d67ca89SAndroid Build Coastguard Worker #include <sys/stat.h>
25*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
26*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
27*8d67ca89SAndroid Build Coastguard Worker 
28*8d67ca89SAndroid Build Coastguard Worker #include <algorithm>
29*8d67ca89SAndroid Build Coastguard Worker #include <set>
30*8d67ca89SAndroid Build Coastguard Worker #include <string>
31*8d67ca89SAndroid Build Coastguard Worker 
32*8d67ca89SAndroid Build Coastguard Worker #include "utils.h"
33*8d67ca89SAndroid Build Coastguard Worker 
CheckProcSelf(std::set<std::string> & names)34*8d67ca89SAndroid Build Coastguard Worker static void CheckProcSelf(std::set<std::string>& names) {
35*8d67ca89SAndroid Build Coastguard Worker   // We have a good idea of what should be in /proc/self.
36*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(names.contains("."));
37*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(names.contains(".."));
38*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(names.contains("cmdline"));
39*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(names.contains("fd"));
40*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(names.contains("stat"));
41*8d67ca89SAndroid Build Coastguard Worker }
42*8d67ca89SAndroid Build Coastguard Worker 
43*8d67ca89SAndroid Build Coastguard Worker template <typename DirEntT>
ScanEntries(DirEntT ** entries,int entry_count,std::set<std::string> & name_set,std::vector<std::string> & name_list)44*8d67ca89SAndroid Build Coastguard Worker void ScanEntries(DirEntT** entries, int entry_count,
45*8d67ca89SAndroid Build Coastguard Worker                  std::set<std::string>& name_set, std::vector<std::string>& name_list) {
46*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < static_cast<size_t>(entry_count); ++i) {
47*8d67ca89SAndroid Build Coastguard Worker     name_set.insert(entries[i]->d_name);
48*8d67ca89SAndroid Build Coastguard Worker     name_list.push_back(entries[i]->d_name);
49*8d67ca89SAndroid Build Coastguard Worker     free(entries[i]);
50*8d67ca89SAndroid Build Coastguard Worker   }
51*8d67ca89SAndroid Build Coastguard Worker   free(entries);
52*8d67ca89SAndroid Build Coastguard Worker }
53*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,scandir_scandir64)54*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, scandir_scandir64) {
55*8d67ca89SAndroid Build Coastguard Worker   // Get everything from /proc/self...
56*8d67ca89SAndroid Build Coastguard Worker   dirent** entries;
57*8d67ca89SAndroid Build Coastguard Worker   int entry_count = scandir("/proc/self", &entries, nullptr, alphasort);
58*8d67ca89SAndroid Build Coastguard Worker   ASSERT_GE(entry_count, 0);
59*8d67ca89SAndroid Build Coastguard Worker 
60*8d67ca89SAndroid Build Coastguard Worker   dirent64** entries64;
61*8d67ca89SAndroid Build Coastguard Worker   int entry_count64 = scandir64("/proc/self", &entries64, nullptr, alphasort64);
62*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(entry_count, entry_count64);
63*8d67ca89SAndroid Build Coastguard Worker 
64*8d67ca89SAndroid Build Coastguard Worker   // Turn the directory entries into a set and vector of the names.
65*8d67ca89SAndroid Build Coastguard Worker   std::set<std::string> name_set;
66*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> unsorted_name_list;
67*8d67ca89SAndroid Build Coastguard Worker   ScanEntries(entries, entry_count, name_set, unsorted_name_list);
68*8d67ca89SAndroid Build Coastguard Worker 
69*8d67ca89SAndroid Build Coastguard Worker   // No duplicates.
70*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(name_set.size(), unsorted_name_list.size());
71*8d67ca89SAndroid Build Coastguard Worker 
72*8d67ca89SAndroid Build Coastguard Worker   // All entries sorted.
73*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> sorted_name_list(unsorted_name_list);
74*8d67ca89SAndroid Build Coastguard Worker   std::sort(sorted_name_list.begin(), sorted_name_list.end());
75*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(sorted_name_list, unsorted_name_list);
76*8d67ca89SAndroid Build Coastguard Worker 
77*8d67ca89SAndroid Build Coastguard Worker   // scandir64 returned the same results as scandir.
78*8d67ca89SAndroid Build Coastguard Worker   std::set<std::string> name_set64;
79*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> unsorted_name_list64;
80*8d67ca89SAndroid Build Coastguard Worker   ScanEntries(entries64, entry_count64, name_set64, unsorted_name_list64);
81*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(name_set, name_set64);
82*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(unsorted_name_list, unsorted_name_list64);
83*8d67ca89SAndroid Build Coastguard Worker 
84*8d67ca89SAndroid Build Coastguard Worker   CheckProcSelf(name_set);
85*8d67ca89SAndroid Build Coastguard Worker }
86*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,scandirat_scandirat64)87*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, scandirat_scandirat64) {
88*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
89*8d67ca89SAndroid Build Coastguard Worker   // Get everything from /proc/self...
90*8d67ca89SAndroid Build Coastguard Worker   dirent** entries;
91*8d67ca89SAndroid Build Coastguard Worker   int entry_count = scandir("/proc/self", &entries, nullptr, alphasort);
92*8d67ca89SAndroid Build Coastguard Worker   ASSERT_GE(entry_count, 0);
93*8d67ca89SAndroid Build Coastguard Worker 
94*8d67ca89SAndroid Build Coastguard Worker   int proc_fd = open("/proc", O_DIRECTORY);
95*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, proc_fd);
96*8d67ca89SAndroid Build Coastguard Worker 
97*8d67ca89SAndroid Build Coastguard Worker   dirent** entries_at;
98*8d67ca89SAndroid Build Coastguard Worker   int entry_count_at = scandirat(proc_fd, "self", &entries_at, nullptr, alphasort);
99*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(entry_count, entry_count_at);
100*8d67ca89SAndroid Build Coastguard Worker 
101*8d67ca89SAndroid Build Coastguard Worker   dirent64** entries_at64;
102*8d67ca89SAndroid Build Coastguard Worker   int entry_count_at64 = scandirat64(proc_fd, "self", &entries_at64, nullptr, alphasort64);
103*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(entry_count, entry_count_at64);
104*8d67ca89SAndroid Build Coastguard Worker 
105*8d67ca89SAndroid Build Coastguard Worker   close(proc_fd);
106*8d67ca89SAndroid Build Coastguard Worker 
107*8d67ca89SAndroid Build Coastguard Worker   // scandirat and scandirat64 should return the same results as scandir.
108*8d67ca89SAndroid Build Coastguard Worker   std::set<std::string> name_set, name_set_at, name_set_at64;
109*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> unsorted_name_list, unsorted_name_list_at, unsorted_name_list_at64;
110*8d67ca89SAndroid Build Coastguard Worker   ScanEntries(entries, entry_count, name_set, unsorted_name_list);
111*8d67ca89SAndroid Build Coastguard Worker   ScanEntries(entries_at, entry_count_at, name_set_at, unsorted_name_list_at);
112*8d67ca89SAndroid Build Coastguard Worker   ScanEntries(entries_at64, entry_count_at64, name_set_at64, unsorted_name_list_at64);
113*8d67ca89SAndroid Build Coastguard Worker 
114*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(name_set, name_set_at);
115*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(name_set, name_set_at64);
116*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(unsorted_name_list, unsorted_name_list_at);
117*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(unsorted_name_list, unsorted_name_list_at64);
118*8d67ca89SAndroid Build Coastguard Worker #else
119*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "musl doesn't have scandirat or scandirat64";
120*8d67ca89SAndroid Build Coastguard Worker #endif
121*8d67ca89SAndroid Build Coastguard Worker }
122*8d67ca89SAndroid Build Coastguard Worker 
is_version_filter(const dirent * de)123*8d67ca89SAndroid Build Coastguard Worker static int is_version_filter(const dirent* de) {
124*8d67ca89SAndroid Build Coastguard Worker   return !strcmp(de->d_name, "version");
125*8d67ca89SAndroid Build Coastguard Worker }
126*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,scandir_filter)127*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, scandir_filter) {
128*8d67ca89SAndroid Build Coastguard Worker   dirent** entries;
129*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(1, scandir("/proc", &entries, is_version_filter, nullptr));
130*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ("version", entries[0]->d_name);
131*8d67ca89SAndroid Build Coastguard Worker   free(entries);
132*8d67ca89SAndroid Build Coastguard Worker }
133*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,scandir_ENOENT)134*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, scandir_ENOENT) {
135*8d67ca89SAndroid Build Coastguard Worker   dirent** entries;
136*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
137*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, scandir("/does-not-exist", &entries, nullptr, nullptr));
138*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
139*8d67ca89SAndroid Build Coastguard Worker }
140*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,scandir64_ENOENT)141*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, scandir64_ENOENT) {
142*8d67ca89SAndroid Build Coastguard Worker   dirent64** entries;
143*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
144*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, scandir64("/does-not-exist", &entries, nullptr, nullptr));
145*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
146*8d67ca89SAndroid Build Coastguard Worker }
147*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,scandirat_ENOENT)148*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, scandirat_ENOENT) {
149*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
150*8d67ca89SAndroid Build Coastguard Worker   int root_fd = open("/", O_DIRECTORY | O_RDONLY);
151*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, root_fd);
152*8d67ca89SAndroid Build Coastguard Worker   dirent** entries;
153*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
154*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, scandirat(root_fd, "does-not-exist", &entries, nullptr, nullptr));
155*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
156*8d67ca89SAndroid Build Coastguard Worker   close(root_fd);
157*8d67ca89SAndroid Build Coastguard Worker #else
158*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "musl doesn't have scandirat or scandirat64";
159*8d67ca89SAndroid Build Coastguard Worker #endif
160*8d67ca89SAndroid Build Coastguard Worker }
161*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,scandirat64_ENOENT)162*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, scandirat64_ENOENT) {
163*8d67ca89SAndroid Build Coastguard Worker #if !defined(ANDROID_HOST_MUSL)
164*8d67ca89SAndroid Build Coastguard Worker   int root_fd = open("/", O_DIRECTORY | O_RDONLY);
165*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(-1, root_fd);
166*8d67ca89SAndroid Build Coastguard Worker   dirent64** entries;
167*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
168*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(-1, scandirat64(root_fd, "does-not-exist", &entries, nullptr, nullptr));
169*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
170*8d67ca89SAndroid Build Coastguard Worker   close(root_fd);
171*8d67ca89SAndroid Build Coastguard Worker #else
172*8d67ca89SAndroid Build Coastguard Worker   GTEST_SKIP() << "musl doesn't have scandirat or scandirat64";
173*8d67ca89SAndroid Build Coastguard Worker #endif
174*8d67ca89SAndroid Build Coastguard Worker }
175*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,fdopendir_invalid)176*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, fdopendir_invalid) {
177*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(fdopendir(-1) == nullptr);
178*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
179*8d67ca89SAndroid Build Coastguard Worker 
180*8d67ca89SAndroid Build Coastguard Worker   int fd = open("/dev/null", O_RDONLY);
181*8d67ca89SAndroid Build Coastguard Worker   ASSERT_NE(fd, -1);
182*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(fdopendir(fd) == nullptr);
183*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOTDIR);
184*8d67ca89SAndroid Build Coastguard Worker   close(fd);
185*8d67ca89SAndroid Build Coastguard Worker }
186*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,fdopendir)187*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, fdopendir) {
188*8d67ca89SAndroid Build Coastguard Worker   int fd = open("/proc/self", O_RDONLY);
189*8d67ca89SAndroid Build Coastguard Worker   DIR* d = fdopendir(fd);
190*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
191*8d67ca89SAndroid Build Coastguard Worker   dirent* e = readdir(d);
192*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ(e->d_name, ".");
193*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
194*8d67ca89SAndroid Build Coastguard Worker 
195*8d67ca89SAndroid Build Coastguard Worker   // fdopendir(3) took ownership, so closedir(3) closed our fd.
196*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(close(fd), -1);
197*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EBADF);
198*8d67ca89SAndroid Build Coastguard Worker }
199*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,opendir_invalid)200*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, opendir_invalid) {
201*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
202*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(opendir("/does/not/exist") == nullptr);
203*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOENT);
204*8d67ca89SAndroid Build Coastguard Worker 
205*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
206*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(opendir("/dev/null") == nullptr);
207*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(ENOTDIR);
208*8d67ca89SAndroid Build Coastguard Worker }
209*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,opendir)210*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, opendir) {
211*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
212*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
213*8d67ca89SAndroid Build Coastguard Worker   dirent* e = readdir(d);
214*8d67ca89SAndroid Build Coastguard Worker   ASSERT_STREQ(e->d_name, ".");
215*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
216*8d67ca89SAndroid Build Coastguard Worker }
217*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,closedir_invalid)218*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, closedir_invalid) {
219*8d67ca89SAndroid Build Coastguard Worker   DIR* d = nullptr;
220*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), -1);
221*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(EINVAL);
222*8d67ca89SAndroid Build Coastguard Worker }
223*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,closedir)224*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, closedir) {
225*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
226*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
227*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
228*8d67ca89SAndroid Build Coastguard Worker }
229*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,readdir)230*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, readdir) {
231*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
232*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
233*8d67ca89SAndroid Build Coastguard Worker   std::set<std::string> name_set;
234*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
235*8d67ca89SAndroid Build Coastguard Worker   dirent* e;
236*8d67ca89SAndroid Build Coastguard Worker   while ((e = readdir(d)) != nullptr) {
237*8d67ca89SAndroid Build Coastguard Worker     name_set.insert(e->d_name);
238*8d67ca89SAndroid Build Coastguard Worker   }
239*8d67ca89SAndroid Build Coastguard Worker   // Reading to the end of the directory is not an error.
240*8d67ca89SAndroid Build Coastguard Worker   // readdir(3) returns NULL, but leaves errno as 0.
241*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(0);
242*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
243*8d67ca89SAndroid Build Coastguard Worker 
244*8d67ca89SAndroid Build Coastguard Worker   CheckProcSelf(name_set);
245*8d67ca89SAndroid Build Coastguard Worker }
246*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,readdir64_smoke)247*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, readdir64_smoke) {
248*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
249*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
250*8d67ca89SAndroid Build Coastguard Worker   std::set<std::string> name_set;
251*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
252*8d67ca89SAndroid Build Coastguard Worker   dirent64* e;
253*8d67ca89SAndroid Build Coastguard Worker   while ((e = readdir64(d)) != nullptr) {
254*8d67ca89SAndroid Build Coastguard Worker     name_set.insert(e->d_name);
255*8d67ca89SAndroid Build Coastguard Worker   }
256*8d67ca89SAndroid Build Coastguard Worker   // Reading to the end of the directory is not an error.
257*8d67ca89SAndroid Build Coastguard Worker   // readdir64(3) returns NULL, but leaves errno as 0.
258*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(0);
259*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
260*8d67ca89SAndroid Build Coastguard Worker 
261*8d67ca89SAndroid Build Coastguard Worker   CheckProcSelf(name_set);
262*8d67ca89SAndroid Build Coastguard Worker }
263*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,readdir_r)264*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, readdir_r) {
265*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
266*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
267*8d67ca89SAndroid Build Coastguard Worker   std::set<std::string> name_set;
268*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
269*8d67ca89SAndroid Build Coastguard Worker   dirent storage;
270*8d67ca89SAndroid Build Coastguard Worker   dirent* e = nullptr;
271*8d67ca89SAndroid Build Coastguard Worker   while (readdir_r(d, &storage, &e) == 0 && e != nullptr) {
272*8d67ca89SAndroid Build Coastguard Worker     name_set.insert(e->d_name);
273*8d67ca89SAndroid Build Coastguard Worker   }
274*8d67ca89SAndroid Build Coastguard Worker   // Reading to the end of the directory is not an error.
275*8d67ca89SAndroid Build Coastguard Worker   // readdir_r(3) returns NULL, but leaves errno as 0.
276*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(0);
277*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
278*8d67ca89SAndroid Build Coastguard Worker 
279*8d67ca89SAndroid Build Coastguard Worker   CheckProcSelf(name_set);
280*8d67ca89SAndroid Build Coastguard Worker }
281*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,readdir64_r_smoke)282*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, readdir64_r_smoke) {
283*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
284*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
285*8d67ca89SAndroid Build Coastguard Worker   std::set<std::string> name_set;
286*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
287*8d67ca89SAndroid Build Coastguard Worker   dirent64 storage;
288*8d67ca89SAndroid Build Coastguard Worker   dirent64* e = nullptr;
289*8d67ca89SAndroid Build Coastguard Worker   while (readdir64_r(d, &storage, &e) == 0 && e != nullptr) {
290*8d67ca89SAndroid Build Coastguard Worker     name_set.insert(e->d_name);
291*8d67ca89SAndroid Build Coastguard Worker   }
292*8d67ca89SAndroid Build Coastguard Worker   // Reading to the end of the directory is not an error.
293*8d67ca89SAndroid Build Coastguard Worker   // readdir64_r(3) returns NULL, but leaves errno as 0.
294*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(0);
295*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
296*8d67ca89SAndroid Build Coastguard Worker 
297*8d67ca89SAndroid Build Coastguard Worker   CheckProcSelf(name_set);
298*8d67ca89SAndroid Build Coastguard Worker }
299*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,rewinddir)300*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, rewinddir) {
301*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
302*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
303*8d67ca89SAndroid Build Coastguard Worker 
304*8d67ca89SAndroid Build Coastguard Worker   // Get all the names once...
305*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> pass1;
306*8d67ca89SAndroid Build Coastguard Worker   dirent* e;
307*8d67ca89SAndroid Build Coastguard Worker   while ((e = readdir(d)) != nullptr) {
308*8d67ca89SAndroid Build Coastguard Worker     pass1.push_back(e->d_name);
309*8d67ca89SAndroid Build Coastguard Worker   }
310*8d67ca89SAndroid Build Coastguard Worker 
311*8d67ca89SAndroid Build Coastguard Worker   // ...rewind...
312*8d67ca89SAndroid Build Coastguard Worker   rewinddir(d);
313*8d67ca89SAndroid Build Coastguard Worker 
314*8d67ca89SAndroid Build Coastguard Worker   // ...and get all the names again.
315*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> pass2;
316*8d67ca89SAndroid Build Coastguard Worker   while ((e = readdir(d)) != nullptr) {
317*8d67ca89SAndroid Build Coastguard Worker     pass2.push_back(e->d_name);
318*8d67ca89SAndroid Build Coastguard Worker   }
319*8d67ca89SAndroid Build Coastguard Worker 
320*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(closedir(d), 0);
321*8d67ca89SAndroid Build Coastguard Worker 
322*8d67ca89SAndroid Build Coastguard Worker   // We should have seen the same names in the same order both times.
323*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(pass1.size(), pass2.size());
324*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < pass1.size(); ++i) {
325*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(pass1[i], pass2[i]);
326*8d67ca89SAndroid Build Coastguard Worker   }
327*8d67ca89SAndroid Build Coastguard Worker }
328*8d67ca89SAndroid Build Coastguard Worker 
TEST(dirent,seekdir_telldir)329*8d67ca89SAndroid Build Coastguard Worker TEST(dirent, seekdir_telldir) {
330*8d67ca89SAndroid Build Coastguard Worker   DIR* d = opendir("/proc/self");
331*8d67ca89SAndroid Build Coastguard Worker   ASSERT_TRUE(d != nullptr);
332*8d67ca89SAndroid Build Coastguard Worker   std::vector<long> offset_list;
333*8d67ca89SAndroid Build Coastguard Worker   std::vector<std::string> name_list;
334*8d67ca89SAndroid Build Coastguard Worker   dirent* e = nullptr;
335*8d67ca89SAndroid Build Coastguard Worker 
336*8d67ca89SAndroid Build Coastguard Worker   offset_list.push_back(telldir(d));
337*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0L, offset_list.back());
338*8d67ca89SAndroid Build Coastguard Worker 
339*8d67ca89SAndroid Build Coastguard Worker   while ((e = readdir(d)) != nullptr) {
340*8d67ca89SAndroid Build Coastguard Worker     name_list.push_back(e->d_name);
341*8d67ca89SAndroid Build Coastguard Worker     offset_list.push_back(telldir(d));
342*8d67ca89SAndroid Build Coastguard Worker     // Make sure telldir() point to the next entry.
343*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(e->d_off, offset_list.back());
344*8d67ca89SAndroid Build Coastguard Worker   }
345*8d67ca89SAndroid Build Coastguard Worker 
346*8d67ca89SAndroid Build Coastguard Worker   long end_offset = telldir(d);
347*8d67ca89SAndroid Build Coastguard Worker   // telldir() should not pass the end of the file.
348*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(offset_list.back(), end_offset);
349*8d67ca89SAndroid Build Coastguard Worker   offset_list.pop_back();
350*8d67ca89SAndroid Build Coastguard Worker 
351*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < offset_list.size(); ++i) {
352*8d67ca89SAndroid Build Coastguard Worker     seekdir(d, offset_list[i]);
353*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(offset_list[i], telldir(d));
354*8d67ca89SAndroid Build Coastguard Worker     e = readdir(d);
355*8d67ca89SAndroid Build Coastguard Worker     ASSERT_TRUE(e != nullptr);
356*8d67ca89SAndroid Build Coastguard Worker     ASSERT_STREQ(name_list[i].c_str(), e->d_name);
357*8d67ca89SAndroid Build Coastguard Worker   }
358*8d67ca89SAndroid Build Coastguard Worker   for (int i = static_cast<int>(offset_list.size()) - 1; i >= 0; --i) {
359*8d67ca89SAndroid Build Coastguard Worker     seekdir(d, offset_list[i]);
360*8d67ca89SAndroid Build Coastguard Worker     ASSERT_EQ(offset_list[i], telldir(d));
361*8d67ca89SAndroid Build Coastguard Worker     e = readdir(d);
362*8d67ca89SAndroid Build Coastguard Worker     ASSERT_TRUE(e != nullptr);
363*8d67ca89SAndroid Build Coastguard Worker     ASSERT_STREQ(name_list[i].c_str(), e->d_name);
364*8d67ca89SAndroid Build Coastguard Worker   }
365*8d67ca89SAndroid Build Coastguard Worker 
366*8d67ca89SAndroid Build Coastguard Worker   // Seek to the end, read NULL.
367*8d67ca89SAndroid Build Coastguard Worker   seekdir(d, end_offset);
368*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(end_offset, telldir(d));
369*8d67ca89SAndroid Build Coastguard Worker   errno = 0;
370*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(nullptr, readdir(d));
371*8d67ca89SAndroid Build Coastguard Worker   ASSERT_ERRNO(0);
372*8d67ca89SAndroid Build Coastguard Worker 
373*8d67ca89SAndroid Build Coastguard Worker   ASSERT_EQ(0, closedir(d));
374*8d67ca89SAndroid Build Coastguard Worker }
375