xref: /freebsd/contrib/llvm-project/libc/src/__support/File/dir.h (revision bb722a7d0f1642bff6487f943ad0427799a6e5bf)
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