| //===--- Implementation of a platform independent Dir data structure ------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "dir.h" |
| |
| #include <stdlib.h> |
| |
| namespace __llvm_libc { |
| |
| Dir *Dir::open(const char *path) { |
| int fd = platform_opendir(path); |
| if (fd < 0) |
| return nullptr; |
| |
| Dir *dir = reinterpret_cast<Dir *>(malloc(sizeof(Dir))); |
| dir->fd = fd; |
| dir->readptr = 0; |
| dir->fillsize = 0; |
| Mutex::init(&dir->mutex, false, false, false); |
| |
| return dir; |
| } |
| |
| struct ::dirent *Dir::read() { |
| MutexLock lock(&mutex); |
| if (readptr >= fillsize) { |
| fillsize = platform_fetch_dirents( |
| fd, cpp::MutableArrayRef<uint8_t>(buffer, BUFSIZE)); |
| if (fillsize == 0) |
| return nullptr; |
| readptr = 0; |
| } |
| struct ::dirent *d = reinterpret_cast<struct ::dirent *>(buffer + readptr); |
| #ifdef __unix__ |
| // The d_reclen field is available on Linux but not required by POSIX. |
| readptr += d->d_reclen; |
| #else |
| // Other platforms have to implement how the read pointer is to be updated. |
| #error "DIR read pointer update is missing." |
| #endif |
| return d; |
| } |
| |
| int Dir::close() { |
| { |
| MutexLock lock(&mutex); |
| if (!platform_closedir(fd)) |
| return -1; |
| } |
| free(this); |
| return 0; |
| } |
| |
| } // namespace __llvm_libc |