1063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes/*
2063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * Copyright (C) 2012 The Android Open Source Project
3063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *
4063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * you may not use this file except in compliance with the License.
6063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * You may obtain a copy of the License at
7063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *
8063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes *
10063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * See the License for the specific language governing permissions and
14063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes * limitations under the License.
15063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes */
16063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
17063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <gtest/gtest.h>
18063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
19063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <dirent.h>
20063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <errno.h>
21063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <fcntl.h>
22063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <limits.h>
23063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <sys/stat.h>
24063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <sys/types.h>
25063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <unistd.h>
26063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
27063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <algorithm>
28063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <set>
29063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes#include <string>
30063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
31063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughesstatic void CheckProcSelf(std::set<std::string>& names) {
32063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // We have a good idea of what should be in /proc/self.
33063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find(".") != names.end());
34063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("..") != names.end());
35063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("cmdline") != names.end());
36063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("fd") != names.end());
37063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(names.find("stat") != names.end());
38063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
39063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
40db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughestemplate <typename DirEntT>
41db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughesvoid ScanEntries(DirEntT** entries, int entry_count,
42db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes                 std::set<std::string>& name_set, std::vector<std::string>& name_list) {
43db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  for (size_t i = 0; i < static_cast<size_t>(entry_count); ++i) {
44db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes    name_set.insert(entries[i]->d_name);
45db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes    name_list.push_back(entries[i]->d_name);
46db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes    free(entries[i]);
47db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  }
48db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  free(entries);
49db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes}
50db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes
51db1ea3474899ebbd783aba872d3005f95a816d0fElliott HughesTEST(dirent, scandir_scandir64) {
52063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Get everything from /proc/self...
53063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent** entries;
54063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  int entry_count = scandir("/proc/self", &entries, NULL, alphasort);
55063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_GE(entry_count, 0);
56063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
57db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  dirent64** entries64;
58db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  int entry_count64 = scandir64("/proc/self", &entries64, NULL, alphasort64);
59db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_EQ(entry_count, entry_count64);
60db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes
61063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Turn the directory entries into a set and vector of the names.
62063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::set<std::string> name_set;
63063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> unsorted_name_list;
64db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ScanEntries(entries, entry_count, name_set, unsorted_name_list);
65063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
66063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // No duplicates.
67063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(name_set.size(), unsorted_name_list.size());
68063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
69063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // All entries sorted.
70063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> sorted_name_list(unsorted_name_list);
71063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::sort(sorted_name_list.begin(), sorted_name_list.end());
72063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(sorted_name_list, unsorted_name_list);
73063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
74db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  // scandir64 returned the same results as scandir.
75db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  std::set<std::string> name_set64;
76db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  std::vector<std::string> unsorted_name_list64;
77db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ScanEntries(entries64, entry_count64, name_set64, unsorted_name_list64);
78db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_EQ(name_set, name_set64);
79db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_EQ(unsorted_name_list, unsorted_name_list64);
80db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes
81063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  CheckProcSelf(name_set);
82063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
83063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
846331e806de41d98083f1bfa3661addfae4682c37Elliott HughesTEST(dirent, scandirat_scandirat64) {
856331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  // Get everything from /proc/self...
866331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  dirent** entries;
876331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  int entry_count = scandir("/proc/self", &entries, NULL, alphasort);
886331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_GE(entry_count, 0);
896331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
906331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  int proc_fd = open("/proc", O_DIRECTORY);
916331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_NE(-1, proc_fd);
926331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
936331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  dirent** entries_at;
946331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  int entry_count_at = scandirat(proc_fd, "self", &entries_at, NULL, alphasort);
956331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(entry_count, entry_count_at);
966331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
976331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  dirent64** entries_at64;
986331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  int entry_count_at64 = scandirat64(proc_fd, "self", &entries_at64, NULL, alphasort64);
996331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(entry_count, entry_count_at64);
1006331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
1016331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  close(proc_fd);
1026331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
1036331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  // scandirat and scandirat64 should return the same results as scandir.
1046331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  std::set<std::string> name_set, name_set_at, name_set_at64;
1056331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  std::vector<std::string> unsorted_name_list, unsorted_name_list_at, unsorted_name_list_at64;
1066331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ScanEntries(entries, entry_count, name_set, unsorted_name_list);
1076331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ScanEntries(entries_at, entry_count_at, name_set_at, unsorted_name_list_at);
1086331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ScanEntries(entries_at64, entry_count_at64, name_set_at64, unsorted_name_list_at64);
1096331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
1106331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(name_set, name_set_at);
1116331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(name_set, name_set_at64);
1126331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(unsorted_name_list, unsorted_name_list_at);
1136331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(unsorted_name_list, unsorted_name_list_at64);
1146331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes}
1156331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
1166331e806de41d98083f1bfa3661addfae4682c37Elliott HughesTEST(dirent, scandir_ENOENT) {
1176331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  dirent** entries;
1186331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  errno = 0;
1196331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(-1, scandir("/does-not-exist", &entries, nullptr, nullptr));
1206331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(ENOENT, errno);
1216331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes}
1226331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
1236331e806de41d98083f1bfa3661addfae4682c37Elliott HughesTEST(dirent, scandir64_ENOENT) {
1246331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  dirent64** entries;
1256331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  errno = 0;
1266331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(-1, scandir64("/does-not-exist", &entries, nullptr, nullptr));
1276331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(ENOENT, errno);
1286331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes}
1296331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
1306331e806de41d98083f1bfa3661addfae4682c37Elliott HughesTEST(dirent, scandirat_ENOENT) {
1316331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  int root_fd = open("/", O_DIRECTORY | O_RDONLY);
1326331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_NE(-1, root_fd);
1336331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  dirent** entries;
1346331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  errno = 0;
1356331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(-1, scandirat(root_fd, "does-not-exist", &entries, nullptr, nullptr));
1366331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(ENOENT, errno);
1376331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  close(root_fd);
1386331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes}
1396331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
1406331e806de41d98083f1bfa3661addfae4682c37Elliott HughesTEST(dirent, scandirat64_ENOENT) {
1416331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  int root_fd = open("/", O_DIRECTORY | O_RDONLY);
1426331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_NE(-1, root_fd);
1436331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  dirent64** entries;
1446331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  errno = 0;
1456331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(-1, scandirat64(root_fd, "does-not-exist", &entries, nullptr, nullptr));
1466331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  ASSERT_EQ(ENOENT, errno);
1476331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes  close(root_fd);
1486331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes}
1496331e806de41d98083f1bfa3661addfae4682c37Elliott Hughes
150063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, fdopendir_invalid) {
151063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(fdopendir(-1) == NULL);
1525e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(EBADF, errno);
153063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
154063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  int fd = open("/dev/null", O_RDONLY);
155063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_NE(fd, -1);
156063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(fdopendir(fd) == NULL);
1575e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(ENOTDIR, errno);
158063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  close(fd);
159063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
160063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
161063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, fdopendir) {
162063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  int fd = open("/proc/self", O_RDONLY);
163063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = fdopendir(fd);
164063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
165063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e = readdir(d);
166063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_STREQ(e->d_name, ".");
167063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
168063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
169063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // fdopendir(3) took ownership, so closedir(3) closed our fd.
170063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(close(fd), -1);
1715e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(EBADF, errno);
172063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
173063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
174063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, opendir_invalid) {
175063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(opendir("/does/not/exist") == NULL);
1765e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(ENOENT, errno);
177063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
178063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(opendir("/dev/null") == NULL);
1795e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(ENOTDIR, errno);
180063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
181063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
182063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, opendir) {
183063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
184063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
185063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e = readdir(d);
186063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_STREQ(e->d_name, ".");
187063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
188063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
189063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
190063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, closedir_invalid) {
191063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = NULL;
192063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), -1);
1935e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(EINVAL, errno);
194063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
195063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
196063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, closedir) {
197063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
198063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
199063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
200063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
201063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
202063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, readdir) {
203063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
204063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
205063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::set<std::string> name_set;
206063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  errno = 0;
207063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e;
208063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while ((e = readdir(d)) != NULL) {
209063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    name_set.insert(e->d_name);
210063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
211063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Reading to the end of the directory is not an error.
212063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // readdir(3) returns NULL, but leaves errno as 0.
2135e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(0, errno);
214063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
215063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
216063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  CheckProcSelf(name_set);
217063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
218063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
219db1ea3474899ebbd783aba872d3005f95a816d0fElliott HughesTEST(dirent, readdir64) {
220db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  DIR* d = opendir("/proc/self");
221db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_TRUE(d != NULL);
222db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  std::set<std::string> name_set;
223db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  errno = 0;
224db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  dirent64* e;
225db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  while ((e = readdir64(d)) != NULL) {
226db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes    name_set.insert(e->d_name);
227db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  }
228db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  // Reading to the end of the directory is not an error.
229db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  // readdir64(3) returns NULL, but leaves errno as 0.
230db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_EQ(0, errno);
231db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_EQ(closedir(d), 0);
232db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes
233db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  CheckProcSelf(name_set);
234db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes}
235db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes
236063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, readdir_r) {
237063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
238063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
239063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::set<std::string> name_set;
240063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  errno = 0;
241063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent storage;
242063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e = NULL;
243063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while (readdir_r(d, &storage, &e) == 0 && e != NULL) {
244063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    name_set.insert(e->d_name);
245063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
246063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Reading to the end of the directory is not an error.
247063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // readdir_r(3) returns NULL, but leaves errno as 0.
2485e3fc43ddeada547a155c6f561a12ff0b16e02d3Elliott Hughes  ASSERT_EQ(0, errno);
249063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
250063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
251063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  CheckProcSelf(name_set);
252063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
253063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
254db1ea3474899ebbd783aba872d3005f95a816d0fElliott HughesTEST(dirent, readdir64_r) {
255db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  DIR* d = opendir("/proc/self");
256db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_TRUE(d != NULL);
257db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  std::set<std::string> name_set;
258db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  errno = 0;
259db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  dirent64 storage;
260db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  dirent64* e = NULL;
261db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  while (readdir64_r(d, &storage, &e) == 0 && e != NULL) {
262db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes    name_set.insert(e->d_name);
263db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  }
264db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  // Reading to the end of the directory is not an error.
265db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  // readdir64_r(3) returns NULL, but leaves errno as 0.
266db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_EQ(0, errno);
267db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  ASSERT_EQ(closedir(d), 0);
268db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes
269db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes  CheckProcSelf(name_set);
270db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes}
271db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes
272063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott HughesTEST(dirent, rewinddir) {
273063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  DIR* d = opendir("/proc/self");
274063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_TRUE(d != NULL);
275063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
276063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // Get all the names once...
277063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> pass1;
278063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  dirent* e;
279063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while ((e = readdir(d)) != NULL) {
280063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    pass1.push_back(e->d_name);
281063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
282063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
283063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // ...rewind...
284063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  rewinddir(d);
285063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
286063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // ...and get all the names again.
287063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  std::vector<std::string> pass2;
288063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  while ((e = readdir(d)) != NULL) {
289063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    pass2.push_back(e->d_name);
290063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
291063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
292063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(closedir(d), 0);
293063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes
294063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  // We should have seen the same names in the same order both times.
295063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  ASSERT_EQ(pass1.size(), pass2.size());
296063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  for (size_t i = 0; i < pass1.size(); ++i) {
297063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes    ASSERT_EQ(pass1[i], pass2[i]);
298063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes  }
299063cfb2084ea4b12d3c85b2d2c44e888f0857eb4Elliott Hughes}
3005ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui
3015ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin CuiTEST(dirent, seekdir_telldir) {
3025ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  DIR* d = opendir("/proc/self");
3035ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  ASSERT_TRUE(d != NULL);
3045ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  std::vector<long> offset_list;
3055ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  std::vector<std::string> name_list;
3065ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  dirent* e = NULL;
3075ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui
3085ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  offset_list.push_back(telldir(d));
3095ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  ASSERT_EQ(0L, offset_list.back());
3105ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui
3115ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  while ((e = readdir(d)) != NULL) {
3125ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    name_list.push_back(e->d_name);
3135ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    offset_list.push_back(telldir(d));
3145ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    // Make sure telldir() point to the next entry.
3155ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    ASSERT_EQ(e->d_off, offset_list.back());
3165ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  }
3175ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui
3185ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  long end_offset = telldir(d);
3195ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  // telldir() should not pass the end of the file.
3205ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  ASSERT_EQ(offset_list.back(), end_offset);
3215ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  offset_list.pop_back();
3225ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui
3235ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  for (size_t i = 0; i < offset_list.size(); ++i) {
3245ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    seekdir(d, offset_list[i]);
3255ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    ASSERT_EQ(offset_list[i], telldir(d));
3265ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    e = readdir(d);
3275ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    ASSERT_TRUE(e != NULL);
3285ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    ASSERT_STREQ(name_list[i].c_str(), e->d_name);
3295ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  }
3305ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  for (int i = static_cast<int>(offset_list.size()) - 1; i >= 0; --i) {
3315ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    seekdir(d, offset_list[i]);
3325ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    ASSERT_EQ(offset_list[i], telldir(d));
3335ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    e = readdir(d);
3345ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    ASSERT_TRUE(e != NULL);
3355ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui    ASSERT_STREQ(name_list[i].c_str(), e->d_name);
3365ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  }
3375ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui
3385ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  // Seek to the end, read NULL.
3395ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  seekdir(d, end_offset);
3405ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  ASSERT_EQ(end_offset, telldir(d));
3415ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  errno = 0;
3425ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  ASSERT_EQ(NULL, readdir(d));
3435ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  ASSERT_EQ(0, errno);
3445ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui
3455ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui  ASSERT_EQ(0, closedir(d));
3465ca4a9e2da46db30ad6d8556b61679d138aaf88dYabin Cui}
347