1*bb722a7dSDimitry Andric //===--- A platform independent Dir class ---------------------------------===// 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 #ifndef LLVM_LIBC_SRC___SUPPORT_FILE_DIR_H 10*bb722a7dSDimitry Andric #define LLVM_LIBC_SRC___SUPPORT_FILE_DIR_H 11*bb722a7dSDimitry Andric 12*bb722a7dSDimitry Andric #include "src/__support/CPP/span.h" 13*bb722a7dSDimitry Andric #include "src/__support/error_or.h" 14*bb722a7dSDimitry Andric #include "src/__support/macros/config.h" 15*bb722a7dSDimitry Andric #include "src/__support/threads/mutex.h" 16*bb722a7dSDimitry Andric 17*bb722a7dSDimitry Andric #include <dirent.h> 18*bb722a7dSDimitry Andric 19*bb722a7dSDimitry Andric namespace LIBC_NAMESPACE_DECL { 20*bb722a7dSDimitry Andric 21*bb722a7dSDimitry Andric // Platform specific function which will open the directory |name| 22*bb722a7dSDimitry Andric // and return its file descriptor. Upon failure, the error value is returned. 23*bb722a7dSDimitry Andric ErrorOr<int> platform_opendir(const char *name); 24*bb722a7dSDimitry Andric 25*bb722a7dSDimitry Andric // Platform specific function which will close the directory with 26*bb722a7dSDimitry Andric // file descriptor |fd|. Returns 0 on success, or the error number on failure. 27*bb722a7dSDimitry Andric int platform_closedir(int fd); 28*bb722a7dSDimitry Andric 29*bb722a7dSDimitry Andric // Platform specific function which will fetch dirents in to buffer. 30*bb722a7dSDimitry Andric // Returns the number of bytes written into buffer or the error number on 31*bb722a7dSDimitry Andric // failure. 32*bb722a7dSDimitry Andric ErrorOr<size_t> platform_fetch_dirents(int fd, cpp::span<uint8_t> buffer); 33*bb722a7dSDimitry Andric 34*bb722a7dSDimitry Andric // This class is designed to allow implementation of the POSIX dirent.h API. 35*bb722a7dSDimitry Andric // By itself, it is platform independent but calls platform specific 36*bb722a7dSDimitry Andric // functions to perform OS operations. 37*bb722a7dSDimitry Andric class Dir { 38*bb722a7dSDimitry Andric static constexpr size_t BUFSIZE = 1024; 39*bb722a7dSDimitry Andric int fd; 40*bb722a7dSDimitry Andric size_t readptr = 0; // The current read pointer. 41*bb722a7dSDimitry Andric size_t fillsize = 0; // The number of valid bytes availabe in the buffer. 42*bb722a7dSDimitry Andric 43*bb722a7dSDimitry Andric // This is a buffer of struct dirent values which will be fetched 44*bb722a7dSDimitry Andric // from the OS. Since the d_name of struct dirent can be of a variable 45*bb722a7dSDimitry Andric // size, we store the data in a byte array. 46*bb722a7dSDimitry Andric uint8_t buffer[BUFSIZE]; 47*bb722a7dSDimitry Andric 48*bb722a7dSDimitry Andric Mutex mutex; 49*bb722a7dSDimitry Andric 50*bb722a7dSDimitry Andric // A directory is to be opened by the static method open and closed 51*bb722a7dSDimitry Andric // by the close method. So, all constructors and destructor are declared 52*bb722a7dSDimitry Andric // as private. Inappropriate constructors are declared as deleted. 53*bb722a7dSDimitry Andric LIBC_INLINE Dir() = delete; 54*bb722a7dSDimitry Andric LIBC_INLINE Dir(const Dir &) = delete; 55*bb722a7dSDimitry Andric Dir(int fdesc)56*bb722a7dSDimitry Andric LIBC_INLINE explicit Dir(int fdesc) 57*bb722a7dSDimitry Andric : fd(fdesc), readptr(0), fillsize(0), 58*bb722a7dSDimitry Andric mutex(/*timed=*/false, /*recursive=*/false, /*robust=*/false, 59*bb722a7dSDimitry Andric /*pshared=*/false) {} 60*bb722a7dSDimitry Andric LIBC_INLINE ~Dir() = default; 61*bb722a7dSDimitry Andric 62*bb722a7dSDimitry Andric LIBC_INLINE Dir &operator=(const Dir &) = delete; 63*bb722a7dSDimitry Andric 64*bb722a7dSDimitry Andric public: 65*bb722a7dSDimitry Andric static ErrorOr<Dir *> open(const char *path); 66*bb722a7dSDimitry Andric 67*bb722a7dSDimitry Andric ErrorOr<struct ::dirent *> read(); 68*bb722a7dSDimitry Andric 69*bb722a7dSDimitry Andric // Returns 0 on success or the error number on failure. If an error number 70*bb722a7dSDimitry Andric // was returned, then the resources associated with the directory are not 71*bb722a7dSDimitry Andric // cleaned up. 72*bb722a7dSDimitry Andric int close(); 73*bb722a7dSDimitry Andric getfd()74*bb722a7dSDimitry Andric LIBC_INLINE int getfd() { return fd; } 75*bb722a7dSDimitry Andric }; 76*bb722a7dSDimitry Andric 77*bb722a7dSDimitry Andric } // namespace LIBC_NAMESPACE_DECL 78*bb722a7dSDimitry Andric 79*bb722a7dSDimitry Andric #endif // LLVM_LIBC_SRC___SUPPORT_FILE_DIR_H 80