Implement scandirat and scandirat64.
Bug: http://b/12612339
Change-Id: Id3b249a884fe08964b26a017ae9574961f0cb441
diff --git a/libc/bionic/scandir.cpp b/libc/bionic/scandir.cpp
index ee62fee..e55be42 100644
--- a/libc/bionic/scandir.cpp
+++ b/libc/bionic/scandir.cpp
@@ -16,9 +16,11 @@
#include <dirent.h>
+#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "private/bionic_macros.h"
#include "private/ScopedReaddir.h"
@@ -26,7 +28,7 @@
// A smart pointer to the scandir dirent**.
class ScandirResult {
public:
- ScandirResult() : names_(NULL), size_(0), capacity_(0) {
+ ScandirResult() : names_(nullptr), size_(0), capacity_(0) {
}
~ScandirResult() {
@@ -42,7 +44,7 @@
dirent** release() {
dirent** result = names_;
- names_ = NULL;
+ names_ = nullptr;
size_ = capacity_ = 0;
return result;
}
@@ -52,7 +54,7 @@
size_t new_capacity = capacity_ + 32;
dirent** new_names =
reinterpret_cast<dirent**>(realloc(names_, new_capacity * sizeof(dirent*)));
- if (new_names == NULL) {
+ if (new_names == nullptr) {
return false;
}
names_ = new_names;
@@ -60,7 +62,7 @@
}
dirent* copy = CopyDirent(entry);
- if (copy == NULL) {
+ if (copy == nullptr) {
return false;
}
names_[size_++] = copy;
@@ -69,7 +71,7 @@
void Sort(int (*comparator)(const dirent**, const dirent**)) {
// If we have entries and a comparator, sort them.
- if (size_ > 0 && comparator != NULL) {
+ if (size_ > 0 && comparator != nullptr) {
qsort(names_, size_, sizeof(dirent*),
reinterpret_cast<int (*)(const void*, const void*)>(comparator));
}
@@ -91,19 +93,29 @@
DISALLOW_COPY_AND_ASSIGN(ScandirResult);
};
-int scandir(const char* dirname, dirent*** name_list,
- int (*filter)(const dirent*),
- int (*comparator)(const dirent**, const dirent**)) {
- ScopedReaddir reader(dirname);
+int scandirat(int parent_fd, const char* dir_name, dirent*** name_list,
+ int (*filter)(const dirent*),
+ int (*comparator)(const dirent**, const dirent**)) {
+ DIR* dir = nullptr;
+ if (parent_fd == AT_FDCWD) {
+ dir = opendir(dir_name);
+ } else {
+ int dir_fd = openat(parent_fd, dir_name, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
+ if (dir_fd != -1) {
+ dir = fdopendir(dir_fd);
+ }
+ }
+
+ ScopedReaddir reader(dir);
if (reader.IsBad()) {
return -1;
}
ScandirResult names;
dirent* entry;
- while ((entry = reader.ReadEntry()) != NULL) {
+ while ((entry = reader.ReadEntry()) != nullptr) {
// If we have a filter, skip names that don't match.
- if (filter != NULL && !(*filter)(entry)) {
+ if (filter != nullptr && !(*filter)(entry)) {
continue;
}
names.Add(entry);
@@ -115,4 +127,11 @@
*name_list = names.release();
return size;
}
+__strong_alias(scandirat64, scandirat);
+
+int scandir(const char* dir_path, dirent*** name_list,
+ int (*filter)(const dirent*),
+ int (*comparator)(const dirent**, const dirent**)) {
+ return scandirat(AT_FDCWD, dir_path, name_list, filter, comparator);
+}
__strong_alias(scandir64, scandir);