1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <gtest/gtest.h> 18 19 #include <dirent.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <limits.h> 23 #include <sys/stat.h> 24 #include <sys/types.h> 25 #include <unistd.h> 26 27 #include <algorithm> 28 #include <set> 29 #include <string> 30 31 static void CheckProcSelf(std::set<std::string>& names) { 32 // We have a good idea of what should be in /proc/self. 33 ASSERT_TRUE(names.find(".") != names.end()); 34 ASSERT_TRUE(names.find("..") != names.end()); 35 ASSERT_TRUE(names.find("cmdline") != names.end()); 36 ASSERT_TRUE(names.find("fd") != names.end()); 37 ASSERT_TRUE(names.find("stat") != names.end()); 38 } 39 40 template <typename DirEntT> 41 void ScanEntries(DirEntT** entries, int entry_count, 42 std::set<std::string>& name_set, std::vector<std::string>& name_list) { 43 for (size_t i = 0; i < static_cast<size_t>(entry_count); ++i) { 44 name_set.insert(entries[i]->d_name); 45 name_list.push_back(entries[i]->d_name); 46 free(entries[i]); 47 } 48 free(entries); 49 } 50 51 TEST(dirent, scandir_scandir64) { 52 // Get everything from /proc/self... 53 dirent** entries; 54 int entry_count = scandir("/proc/self", &entries, NULL, alphasort); 55 ASSERT_GE(entry_count, 0); 56 57 dirent64** entries64; 58 int entry_count64 = scandir64("/proc/self", &entries64, NULL, alphasort64); 59 ASSERT_EQ(entry_count, entry_count64); 60 61 // Turn the directory entries into a set and vector of the names. 62 std::set<std::string> name_set; 63 std::vector<std::string> unsorted_name_list; 64 ScanEntries(entries, entry_count, name_set, unsorted_name_list); 65 66 // No duplicates. 67 ASSERT_EQ(name_set.size(), unsorted_name_list.size()); 68 69 // All entries sorted. 70 std::vector<std::string> sorted_name_list(unsorted_name_list); 71 std::sort(sorted_name_list.begin(), sorted_name_list.end()); 72 ASSERT_EQ(sorted_name_list, unsorted_name_list); 73 74 // scandir64 returned the same results as scandir. 75 std::set<std::string> name_set64; 76 std::vector<std::string> unsorted_name_list64; 77 ScanEntries(entries64, entry_count64, name_set64, unsorted_name_list64); 78 ASSERT_EQ(name_set, name_set64); 79 ASSERT_EQ(unsorted_name_list, unsorted_name_list64); 80 81 CheckProcSelf(name_set); 82 } 83 84 TEST(dirent, fdopendir_invalid) { 85 ASSERT_TRUE(fdopendir(-1) == NULL); 86 ASSERT_EQ(EBADF, errno); 87 88 int fd = open("/dev/null", O_RDONLY); 89 ASSERT_NE(fd, -1); 90 ASSERT_TRUE(fdopendir(fd) == NULL); 91 ASSERT_EQ(ENOTDIR, errno); 92 close(fd); 93 } 94 95 TEST(dirent, fdopendir) { 96 int fd = open("/proc/self", O_RDONLY); 97 DIR* d = fdopendir(fd); 98 ASSERT_TRUE(d != NULL); 99 dirent* e = readdir(d); 100 ASSERT_STREQ(e->d_name, "."); 101 ASSERT_EQ(closedir(d), 0); 102 103 // fdopendir(3) took ownership, so closedir(3) closed our fd. 104 ASSERT_EQ(close(fd), -1); 105 ASSERT_EQ(EBADF, errno); 106 } 107 108 TEST(dirent, opendir_invalid) { 109 ASSERT_TRUE(opendir("/does/not/exist") == NULL); 110 ASSERT_EQ(ENOENT, errno); 111 112 ASSERT_TRUE(opendir("/dev/null") == NULL); 113 ASSERT_EQ(ENOTDIR, errno); 114 } 115 116 TEST(dirent, opendir) { 117 DIR* d = opendir("/proc/self"); 118 ASSERT_TRUE(d != NULL); 119 dirent* e = readdir(d); 120 ASSERT_STREQ(e->d_name, "."); 121 ASSERT_EQ(closedir(d), 0); 122 } 123 124 TEST(dirent, closedir_invalid) { 125 DIR* d = NULL; 126 ASSERT_EQ(closedir(d), -1); 127 ASSERT_EQ(EINVAL, errno); 128 } 129 130 TEST(dirent, closedir) { 131 DIR* d = opendir("/proc/self"); 132 ASSERT_TRUE(d != NULL); 133 ASSERT_EQ(closedir(d), 0); 134 } 135 136 TEST(dirent, readdir) { 137 DIR* d = opendir("/proc/self"); 138 ASSERT_TRUE(d != NULL); 139 std::set<std::string> name_set; 140 errno = 0; 141 dirent* e; 142 while ((e = readdir(d)) != NULL) { 143 name_set.insert(e->d_name); 144 } 145 // Reading to the end of the directory is not an error. 146 // readdir(3) returns NULL, but leaves errno as 0. 147 ASSERT_EQ(0, errno); 148 ASSERT_EQ(closedir(d), 0); 149 150 CheckProcSelf(name_set); 151 } 152 153 TEST(dirent, readdir64) { 154 DIR* d = opendir("/proc/self"); 155 ASSERT_TRUE(d != NULL); 156 std::set<std::string> name_set; 157 errno = 0; 158 dirent64* e; 159 while ((e = readdir64(d)) != NULL) { 160 name_set.insert(e->d_name); 161 } 162 // Reading to the end of the directory is not an error. 163 // readdir64(3) returns NULL, but leaves errno as 0. 164 ASSERT_EQ(0, errno); 165 ASSERT_EQ(closedir(d), 0); 166 167 CheckProcSelf(name_set); 168 } 169 170 TEST(dirent, readdir_r) { 171 DIR* d = opendir("/proc/self"); 172 ASSERT_TRUE(d != NULL); 173 std::set<std::string> name_set; 174 errno = 0; 175 dirent storage; 176 dirent* e = NULL; 177 while (readdir_r(d, &storage, &e) == 0 && e != NULL) { 178 name_set.insert(e->d_name); 179 } 180 // Reading to the end of the directory is not an error. 181 // readdir_r(3) returns NULL, but leaves errno as 0. 182 ASSERT_EQ(0, errno); 183 ASSERT_EQ(closedir(d), 0); 184 185 CheckProcSelf(name_set); 186 } 187 188 TEST(dirent, readdir64_r) { 189 DIR* d = opendir("/proc/self"); 190 ASSERT_TRUE(d != NULL); 191 std::set<std::string> name_set; 192 errno = 0; 193 dirent64 storage; 194 dirent64* e = NULL; 195 while (readdir64_r(d, &storage, &e) == 0 && e != NULL) { 196 name_set.insert(e->d_name); 197 } 198 // Reading to the end of the directory is not an error. 199 // readdir64_r(3) returns NULL, but leaves errno as 0. 200 ASSERT_EQ(0, errno); 201 ASSERT_EQ(closedir(d), 0); 202 203 CheckProcSelf(name_set); 204 } 205 206 TEST(dirent, rewinddir) { 207 DIR* d = opendir("/proc/self"); 208 ASSERT_TRUE(d != NULL); 209 210 // Get all the names once... 211 std::vector<std::string> pass1; 212 dirent* e; 213 while ((e = readdir(d)) != NULL) { 214 pass1.push_back(e->d_name); 215 } 216 217 // ...rewind... 218 rewinddir(d); 219 220 // ...and get all the names again. 221 std::vector<std::string> pass2; 222 while ((e = readdir(d)) != NULL) { 223 pass2.push_back(e->d_name); 224 } 225 226 ASSERT_EQ(closedir(d), 0); 227 228 // We should have seen the same names in the same order both times. 229 ASSERT_EQ(pass1.size(), pass2.size()); 230 for (size_t i = 0; i < pass1.size(); ++i) { 231 ASSERT_EQ(pass1[i], pass2[i]); 232 } 233 } 234