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