[libc++][Android] Allow testing libc++ with clang-r536225 (#116149)
[llvm-project.git] / libc / src / __support / File / dir.cpp
blob21b0106f7010619d43d7e9a267176f12c7154602
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 //===----------------------------------------------------------------------===//
9 #include "dir.h"
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
17 namespace LIBC_NAMESPACE_DECL {
19 ErrorOr<Dir *> Dir::open(const char *path) {
20 auto fd = platform_opendir(path);
21 if (!fd)
22 return LIBC_NAMESPACE::Error(fd.error());
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;
31 ErrorOr<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;
40 if (fillsize == 0)
41 return nullptr;
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;
54 int Dir::close() {
56 cpp::lock_guard lock(mutex);
57 int retval = platform_closedir(fd);
58 if (retval != 0)
59 return retval;
61 delete this;
62 return 0;
65 } // namespace LIBC_NAMESPACE_DECL