1*bb722a7dSDimitry Andric //===--- Implementation of a platform independent Dir data structure ------===// 2*bb722a7dSDimitry Andric // 3*bb722a7dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bb722a7dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*bb722a7dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bb722a7dSDimitry Andric // 7*bb722a7dSDimitry Andric //===----------------------------------------------------------------------===// 8*bb722a7dSDimitry Andric 9*bb722a7dSDimitry Andric #include "dir.h" 10*bb722a7dSDimitry Andric 11*bb722a7dSDimitry Andric #include "src/__support/CPP/mutex.h" // lock_guard 12*bb722a7dSDimitry Andric #include "src/__support/CPP/new.h" 13*bb722a7dSDimitry Andric #include "src/__support/error_or.h" 14*bb722a7dSDimitry Andric #include "src/__support/libc_errno.h" // For error macros 15*bb722a7dSDimitry Andric #include "src/__support/macros/config.h" 16*bb722a7dSDimitry Andric 17*bb722a7dSDimitry Andric namespace LIBC_NAMESPACE_DECL { 18*bb722a7dSDimitry Andric open(const char * path)19*bb722a7dSDimitry AndricErrorOr<Dir *> Dir::open(const char *path) { 20*bb722a7dSDimitry Andric auto fd = platform_opendir(path); 21*bb722a7dSDimitry Andric if (!fd) 22*bb722a7dSDimitry Andric return LIBC_NAMESPACE::Error(fd.error()); 23*bb722a7dSDimitry Andric 24*bb722a7dSDimitry Andric LIBC_NAMESPACE::AllocChecker ac; 25*bb722a7dSDimitry Andric Dir *dir = new (ac) Dir(fd.value()); 26*bb722a7dSDimitry Andric if (!ac) 27*bb722a7dSDimitry Andric return LIBC_NAMESPACE::Error(ENOMEM); 28*bb722a7dSDimitry Andric return dir; 29*bb722a7dSDimitry Andric } 30*bb722a7dSDimitry Andric read()31*bb722a7dSDimitry AndricErrorOr<struct ::dirent *> Dir::read() { 32*bb722a7dSDimitry Andric cpp::lock_guard lock(mutex); 33*bb722a7dSDimitry Andric if (readptr >= fillsize) { 34*bb722a7dSDimitry Andric auto readsize = platform_fetch_dirents(fd, buffer); 35*bb722a7dSDimitry Andric if (!readsize) 36*bb722a7dSDimitry Andric return LIBC_NAMESPACE::Error(readsize.error()); 37*bb722a7dSDimitry Andric fillsize = readsize.value(); 38*bb722a7dSDimitry Andric readptr = 0; 39*bb722a7dSDimitry Andric } 40*bb722a7dSDimitry Andric if (fillsize == 0) 41*bb722a7dSDimitry Andric return nullptr; 42*bb722a7dSDimitry Andric 43*bb722a7dSDimitry Andric struct ::dirent *d = reinterpret_cast<struct ::dirent *>(buffer + readptr); 44*bb722a7dSDimitry Andric #ifdef __linux__ 45*bb722a7dSDimitry Andric // The d_reclen field is available on Linux but not required by POSIX. 46*bb722a7dSDimitry Andric readptr += d->d_reclen; 47*bb722a7dSDimitry Andric #else 48*bb722a7dSDimitry Andric // Other platforms have to implement how the read pointer is to be updated. 49*bb722a7dSDimitry Andric #error "DIR read pointer update is missing." 50*bb722a7dSDimitry Andric #endif 51*bb722a7dSDimitry Andric return d; 52*bb722a7dSDimitry Andric } 53*bb722a7dSDimitry Andric close()54*bb722a7dSDimitry Andricint Dir::close() { 55*bb722a7dSDimitry Andric { 56*bb722a7dSDimitry Andric cpp::lock_guard lock(mutex); 57*bb722a7dSDimitry Andric int retval = platform_closedir(fd); 58*bb722a7dSDimitry Andric if (retval != 0) 59*bb722a7dSDimitry Andric return retval; 60*bb722a7dSDimitry Andric } 61*bb722a7dSDimitry Andric delete this; 62*bb722a7dSDimitry Andric return 0; 63*bb722a7dSDimitry Andric } 64*bb722a7dSDimitry Andric 65*bb722a7dSDimitry Andric } // namespace LIBC_NAMESPACE_DECL 66