OSDN Git Service

Merge "Add kryo support."
[android-x86/bionic.git] / libc / bionic / scandir.cpp
index dd22b22..e55be42 100644 (file)
 
 #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"
 
 // 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() {
@@ -40,7 +44,7 @@ class ScandirResult {
 
   dirent** release() {
     dirent** result = names_;
-    names_ = NULL;
+    names_ = nullptr;
     size_ = capacity_ = 0;
     return result;
   }
@@ -48,8 +52,9 @@ class ScandirResult {
   bool Add(dirent* entry) {
     if (size_ >= capacity_) {
       size_t new_capacity = capacity_ + 32;
-      dirent** new_names = (dirent**) realloc(names_, new_capacity * sizeof(dirent*));
-      if (new_names == NULL) {
+      dirent** new_names =
+          reinterpret_cast<dirent**>(realloc(names_, new_capacity * sizeof(dirent*)));
+      if (new_names == nullptr) {
         return false;
       }
       names_ = new_names;
@@ -57,7 +62,7 @@ class ScandirResult {
     }
 
     dirent* copy = CopyDirent(entry);
-    if (copy == NULL) {
+    if (copy == nullptr) {
       return false;
     }
     names_[size_++] = copy;
@@ -66,8 +71,9 @@ class ScandirResult {
 
   void Sort(int (*comparator)(const dirent**, const dirent**)) {
     // If we have entries and a comparator, sort them.
-    if (size_ > 0 && comparator != NULL) {
-      qsort(names_, size_, sizeof(dirent*), (int (*)(const void*, const void*)) comparator);
+    if (size_ > 0 && comparator != nullptr) {
+      qsort(names_, size_, sizeof(dirent*),
+            reinterpret_cast<int (*)(const void*, const void*)>(comparator));
     }
   }
 
@@ -79,29 +85,37 @@ class ScandirResult {
   static dirent* CopyDirent(dirent* original) {
     // Allocate the minimum number of bytes necessary, rounded up to a 4-byte boundary.
     size_t size = ((original->d_reclen + 3) & ~3);
-    dirent* copy = (dirent*) malloc(size);
+    dirent* copy = reinterpret_cast<dirent*>(malloc(size));
     memcpy(copy, original, original->d_reclen);
     return copy;
   }
 
-  // Disallow copy and assignment.
-  ScandirResult(const ScandirResult&);
-  void operator=(const ScandirResult&);
+  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);
@@ -113,3 +127,11 @@ int scandir(const char* dirname, dirent*** name_list,
   *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);