2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
25 #include "private/bionic_macros.h"
26 #include "private/ScopedReaddir.h"
28 // A smart pointer to the scandir dirent**.
31 ScandirResult() : names_(nullptr), size_(0), capacity_(0) {
36 free(names_[--size_]);
46 dirent** result = names_;
48 size_ = capacity_ = 0;
52 bool Add(dirent* entry) {
53 if (size_ >= capacity_) {
54 size_t new_capacity = capacity_ + 32;
56 reinterpret_cast<dirent**>(realloc(names_, new_capacity * sizeof(dirent*)));
57 if (new_names == nullptr) {
61 capacity_ = new_capacity;
64 dirent* copy = CopyDirent(entry);
65 if (copy == nullptr) {
68 names_[size_++] = copy;
72 void Sort(int (*comparator)(const dirent**, const dirent**)) {
73 // If we have entries and a comparator, sort them.
74 if (size_ > 0 && comparator != nullptr) {
75 qsort(names_, size_, sizeof(dirent*),
76 reinterpret_cast<int (*)(const void*, const void*)>(comparator));
85 static dirent* CopyDirent(dirent* original) {
86 // Allocate the minimum number of bytes necessary, rounded up to a 4-byte boundary.
87 size_t size = ((original->d_reclen + 3) & ~3);
88 dirent* copy = reinterpret_cast<dirent*>(malloc(size));
89 memcpy(copy, original, original->d_reclen);
93 DISALLOW_COPY_AND_ASSIGN(ScandirResult);
96 int scandirat(int parent_fd, const char* dir_name, dirent*** name_list,
97 int (*filter)(const dirent*),
98 int (*comparator)(const dirent**, const dirent**)) {
100 if (parent_fd == AT_FDCWD) {
101 dir = opendir(dir_name);
103 int dir_fd = openat(parent_fd, dir_name, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
105 dir = fdopendir(dir_fd);
109 ScopedReaddir reader(dir);
110 if (reader.IsBad()) {
116 while ((entry = reader.ReadEntry()) != nullptr) {
117 // If we have a filter, skip names that don't match.
118 if (filter != nullptr && !(*filter)(entry)) {
124 names.Sort(comparator);
126 size_t size = names.size();
127 *name_list = names.release();
130 __strong_alias(scandirat64, scandirat);
132 int scandir(const char* dir_path, dirent*** name_list,
133 int (*filter)(const dirent*),
134 int (*comparator)(const dirent**, const dirent**)) {
135 return scandirat(AT_FDCWD, dir_path, name_list, filter, comparator);
137 __strong_alias(scandir64, scandir);