1701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes/* 2701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * Copyright (C) 2013 The Android Open Source Project 3701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * 4701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * you may not use this file except in compliance with the License. 6701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * You may obtain a copy of the License at 7701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * 8701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * 10701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * Unless required by applicable law or agreed to in writing, software 11701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * See the License for the specific language governing permissions and 14701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes * limitations under the License. 15701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes */ 16701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 17701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes#include <dirent.h> 18701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 19701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes#include <errno.h> 20701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes#include <stdlib.h> 21701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 228eac9af24ea7e570e0b297bcd6ac8a46ba3ecc39Elliott Hughes#include "private/bionic_macros.h" 23701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes#include "private/ScopedReaddir.h" 24701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 25701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes// A smart pointer to the scandir dirent**. 26701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughesclass ScandirResult { 27701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes public: 28701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes ScandirResult() : names_(NULL), size_(0), capacity_(0) { 29701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 30701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 31701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes ~ScandirResult() { 32701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes while (size_ > 0) { 33701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes free(names_[--size_]); 34701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 35701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes free(names_); 36701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 37701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 38701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes size_t size() { 39701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return size_; 40701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 41701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 42701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes dirent** release() { 43701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes dirent** result = names_; 44701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes names_ = NULL; 45701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes size_ = capacity_ = 0; 46701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return result; 47701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 48701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 49701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes bool Add(dirent* entry) { 50701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes if (size_ >= capacity_) { 51701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes size_t new_capacity = capacity_ + 32; 52701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes dirent** new_names = (dirent**) realloc(names_, new_capacity * sizeof(dirent*)); 53701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes if (new_names == NULL) { 54701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return false; 55701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 56701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes names_ = new_names; 57701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes capacity_ = new_capacity; 58701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 59701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 60701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes dirent* copy = CopyDirent(entry); 61701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes if (copy == NULL) { 62701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return false; 63701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 64701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes names_[size_++] = copy; 65701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return true; 66701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 67701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 68701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes void Sort(int (*comparator)(const dirent**, const dirent**)) { 69701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes // If we have entries and a comparator, sort them. 70701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes if (size_ > 0 && comparator != NULL) { 71701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes qsort(names_, size_, sizeof(dirent*), (int (*)(const void*, const void*)) comparator); 72701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 73701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 74701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 75701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes private: 76701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes dirent** names_; 77701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes size_t size_; 78701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes size_t capacity_; 79701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 80701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes static dirent* CopyDirent(dirent* original) { 81701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes // Allocate the minimum number of bytes necessary, rounded up to a 4-byte boundary. 82701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes size_t size = ((original->d_reclen + 3) & ~3); 83701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes dirent* copy = (dirent*) malloc(size); 84701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes memcpy(copy, original, original->d_reclen); 85701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return copy; 86701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 87701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 888eac9af24ea7e570e0b297bcd6ac8a46ba3ecc39Elliott Hughes DISALLOW_COPY_AND_ASSIGN(ScandirResult); 89701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes}; 90701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 91701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughesint scandir(const char* dirname, dirent*** name_list, 92701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes int (*filter)(const dirent*), 93701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes int (*comparator)(const dirent**, const dirent**)) { 94701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes ScopedReaddir reader(dirname); 95701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes if (reader.IsBad()) { 96701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return -1; 97701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 98701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 99701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes ScandirResult names; 100701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes dirent* entry; 101701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes while ((entry = reader.ReadEntry()) != NULL) { 102701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes // If we have a filter, skip names that don't match. 103701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes if (filter != NULL && !(*filter)(entry)) { 104701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes continue; 105701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 106701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes names.Add(entry); 107701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes } 108701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 109701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes names.Sort(comparator); 110701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes 111701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes size_t size = names.size(); 112701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes *name_list = names.release(); 113701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes return size; 114701bec2af33feaa9dddf12ccf8e4c714441b7f2eElliott Hughes} 115db1ea3474899ebbd783aba872d3005f95a816d0fElliott Hughes__strong_alias(scandir64, scandir); 116